Refactored JavaScript architecture
@ -76,7 +76,8 @@
|
||||
"var": 2,
|
||||
"let": 2,
|
||||
"const": 3
|
||||
}
|
||||
},
|
||||
"SwitchCase": 1
|
||||
}],
|
||||
"init-declarations": 2,
|
||||
"key-spacing": 2,
|
||||
@ -115,7 +116,7 @@
|
||||
"max": 1
|
||||
}],
|
||||
"no-nested-ternary": 2,
|
||||
"no-new": 2,
|
||||
"no-new": 0,
|
||||
"no-new-object": 2,
|
||||
"no-param-reassign": 2,
|
||||
"no-prototype-builtins": 2,
|
||||
@ -142,7 +143,6 @@
|
||||
"no-whitespace-before-property": 2,
|
||||
"no-with": 2,
|
||||
"object-curly-spacing": [2, "always"],
|
||||
"object-property-newline": 2,
|
||||
"object-shorthand": 2,
|
||||
"one-var-declaration-per-line": 2,
|
||||
"operator-assignment": 2,
|
||||
|
@ -21,6 +21,8 @@
|
||||
files:
|
||||
ignore:
|
||||
- node_modules/**
|
||||
- src/assets/stylesheets/extensions/pymdown/_arithmatex.scss
|
||||
- src/assets/stylesheets/extensions/pymdown/_inlinehilite.scss
|
||||
- src/assets/stylesheets/_shame.scss
|
||||
|
||||
options:
|
||||
|
@ -130,7 +130,7 @@ gulp.task("assets:images:clean",
|
||||
load("assets/images/clean"))
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Javascripts
|
||||
* JavaScript
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
@ -161,13 +161,13 @@ gulp.task("assets:javascripts:build", (args.clean ? [
|
||||
})
|
||||
|
||||
/*
|
||||
* Clean javascripts generated by build
|
||||
* Clean JavaScript generated by build
|
||||
*/
|
||||
gulp.task("assets:javascripts:clean",
|
||||
load("assets/javascripts/clean"))
|
||||
|
||||
/*
|
||||
* Lint javascripts
|
||||
* Lint JavaScript
|
||||
*/
|
||||
gulp.task("assets:javascripts:lint",
|
||||
load("assets/javascripts/lint"))
|
||||
@ -321,7 +321,7 @@ gulp.task("watch", [
|
||||
`${config.assets.src}/stylesheets/**/*.scss`
|
||||
], ["assets:stylesheets:build"])
|
||||
|
||||
/* Rebuild javascripts */
|
||||
/* Rebuild JavaScript */
|
||||
gulp.watch([
|
||||
`${config.assets.src}/javascripts/**/*.{js,jsx}`
|
||||
], ["assets:javascripts:build:application"])
|
||||
|
@ -85,7 +85,8 @@ paragraphs and other blocks – except code blocks, because the parser from the
|
||||
standard Markdown library does not account for those.
|
||||
|
||||
However, the [PyMdown Extensions][] package adds an extension called
|
||||
`superfences`, which makes it possible to nest code blocks within other blocks.
|
||||
[SuperFences][], which makes it possible to nest code blocks within other
|
||||
blocks.
|
||||
|
||||
Example:
|
||||
|
||||
@ -310,3 +311,4 @@ Qualifiers:
|
||||
|
||||
[Admonition]: https://pythonhosted.org/Markdown/extensions/admonition.html
|
||||
[PyMdown Extensions]: https://facelessuser.github.io/pymdown-extensions
|
||||
[SuperFences]: https://facelessuser.github.io/pymdown-extensions/extensions/superfences/
|
||||
|
@ -6,8 +6,8 @@ executed during compilation of the Markdown file.
|
||||
|
||||
## Installation
|
||||
|
||||
CodeHilite parses code blocks and wraps them in `pre` tags. If [Pygments][] is
|
||||
installed, which is a generic syntax highlighter with support for over
|
||||
CodeHilite parses code blocks and wraps them in `<pre>` tags. If [Pygments][]
|
||||
is installed, which is a generic syntax highlighter with support for over
|
||||
[300 languages][], CodeHilite will also highlight the code block. Pygments can
|
||||
be installed with the following command:
|
||||
|
||||
|
@ -1,3 +1 @@
|
||||
# Metadata
|
||||
|
||||
Foobar
|
||||
|
@ -14,7 +14,7 @@ markdown_extensions:
|
||||
- toc(permalink=true)
|
||||
```
|
||||
|
||||
This will add a link containing the paragraph symbol "¶" at the end of each
|
||||
This will add a link containing the paragraph symbol `¶` at the end of each
|
||||
headline (exactly like on the page you're currently viewing), which the
|
||||
Material theme will make appear on hover. In order to change the text of the
|
||||
permalink, a string can be passed, e.g.:
|
||||
|
@ -0,0 +1,63 @@
|
||||
# Arithmatex <small>MathJax</small>
|
||||
|
||||
[Arithmatex][] integrates [MathJax][] with Markdown and is included in the
|
||||
[PyMdown Extensions][] package. It parses block-style and inline equations
|
||||
written in TeX markup and outputs them in mathematical notation.
|
||||
|
||||
## Installation
|
||||
|
||||
Make sure that the PyMdown Extensions package [is installed][] and add the
|
||||
following lines to your `mkdocs.yml`:
|
||||
|
||||
``` yaml
|
||||
markdown_extensions:
|
||||
- pymdownx.arithmatex
|
||||
```
|
||||
|
||||
The MathJax runtime is automatically included if the extension is enabled, so
|
||||
there is no need for extra JavaScript.
|
||||
|
||||
## Usage
|
||||
|
||||
MathJax searches for `:::tex $$...$$` (blocks) and `:::tex $...$` (inline)
|
||||
equations, parses their contents and renders them in mathematical notation.
|
||||
See [this thread][] on StackExchange for a short introduction and quick
|
||||
reference on how to write equations in TeX syntax.
|
||||
|
||||
### Blocks
|
||||
|
||||
Blocks are enclosed in `:::tex $$...$$` which are placed on separate lines.
|
||||
|
||||
Example:
|
||||
|
||||
``` tex
|
||||
$$
|
||||
\frac{n!}{k!(n-k)!} = \binom{n}{k}
|
||||
$$
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
$$
|
||||
\frac{n!}{k!(n-k)!} = \binom{n}{k}
|
||||
$$
|
||||
|
||||
### Inline
|
||||
|
||||
Inline equations need to be enclosed in `:::tex $...$`:
|
||||
|
||||
Example:
|
||||
|
||||
``` tex
|
||||
Lorem ipsum dolor sit amet: $p(x|y) = \frac{p(y|x)p(x)}{p(y)}$
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
Lorem ipsum dolor sit amet: $p(x|y) = \frac{p(y|x)p(x)}{p(y)}$
|
||||
|
||||
[Arithmatex]: https://facelessuser.github.io/pymdown-extensions/extensions/arithmatex/
|
||||
[MathJax]: https://www.mathjax.org/
|
||||
[PyMdown Extensions]: https://facelessuser.github.io/pymdown-extensions
|
||||
[is installed]: /extensions/pymdown/overview/#installation
|
||||
[this thread]: http://meta.math.stackexchange.com/questions/5020/
|
@ -1,37 +1,93 @@
|
||||
# PyMdown Extensions
|
||||
|
||||
[PyMdown Extensions][] is a collection of Markdown extensions that add some
|
||||
great and missing features to the standard Markdown library. For this reason,
|
||||
the **installation of this package is highly recommended** as it's
|
||||
well-integrated with the Material theme.
|
||||
great features to the standard Markdown library. For this reason, the
|
||||
**installation of this package is highly recommended** as it's well-integrated
|
||||
with the Material theme.
|
||||
|
||||
## Installation
|
||||
|
||||
The Pymdown Extensions can be installed with the following command:
|
||||
The PyMdown Extensions package can be installed with the following command:
|
||||
|
||||
``` sh
|
||||
pip install pymdown-extensions
|
||||
```
|
||||
|
||||
## Usage
|
||||
## Extensions
|
||||
|
||||
### Improvements on existing Markdown
|
||||
### GitHub Flavored Markdown
|
||||
|
||||
- BetterEm
|
||||
- SuperFences
|
||||
- MagicLink
|
||||
Most of the extensions included in the PyMdown Extensions package try to bring
|
||||
the Markdown experience closer to GitHub Flavored Markdown (GFM):
|
||||
|
||||
- [BetterEm][] improves the handling of emphasis markup (**bold** and *italic*)
|
||||
within Markdown by providing a more sophisticated parser for better detecting
|
||||
start and end tokens. Read the documentation for usage notes.
|
||||
|
||||
- [MagicLink][] detects links in Markdown and auto-generates the necessary
|
||||
markup, so no special syntax is required. It auto-links HTTP(S) and FTP
|
||||
links, as well as references to email addresses.
|
||||
|
||||
- [GitHub Emoji][] adds the ability to insert emojis, which does not only
|
||||
include the :octocat: emojis, but also a :shit:-load of emojis that we use in
|
||||
our daily lives. See the [Emoji Cheat Sheet][] for a list of all available
|
||||
emojis. Happy scrolling :tada:
|
||||
|
||||
- [SuperFences][] provides the ability to nest code blocks under blockquotes,
|
||||
lists and other block elements, which the [Fenced Code Blocks][] extension
|
||||
from the standard Markdown library doesn't parse correctly.
|
||||
|
||||
- [Tasklist][] adds support for styled checkbox lists. This is useful for
|
||||
keeping track of tasks and showing what has been done and has yet to be done.
|
||||
The usage of this extension is documented [here][].
|
||||
|
||||
- [Tilde][] provides an easy way to ~~strike through~~ cross out text.
|
||||
The portion of text that should be erased must be enclosed in two tildes
|
||||
`~~...~~`, and the extension will take care of the rest.
|
||||
|
||||
The PyMdown Extensions package adds a shorthand to enable all of the included
|
||||
extensions that provide the GFM experience. However, usage of the shorthand is
|
||||
discouraged, because some extensions are not supported, as the Material theme
|
||||
uses the counterparts included in the standard Markdown library.
|
||||
|
||||
To enable all extensions add the following lines to your `mkdocs.yml`:
|
||||
|
||||
``` yaml
|
||||
markdown_extensions:
|
||||
- pymdownx.betterem
|
||||
- pymdownx.githubemoji
|
||||
- pymdownx.magiclink
|
||||
- pymdownx.superfences
|
||||
- pymdownx.tasklist(custom_checkbox=true)
|
||||
- pymdownx.tilde
|
||||
```
|
||||
|
||||
### Syntactic Sugar
|
||||
|
||||
There are three other extensions that add further syntactic sugar:
|
||||
|
||||
- [Caret][] is the sister extension of [Tilde][] and makes it possible to
|
||||
highlight ^^inserted text^^. The portion of text that should be marked as
|
||||
added must be enclosed in two carets `^^...^^`, the extension will do the
|
||||
rest.
|
||||
|
||||
- [Mark][] add the ability to ==mark text==.
|
||||
- SmartSymbols
|
||||
|
||||
### New Syntax for...
|
||||
- Inlinehilite --- own documentation file
|
||||
- Critic --- own documentation file
|
||||
|
||||
- Caret
|
||||
- Mark
|
||||
- Tilde
|
||||
|
||||
### New features
|
||||
|
||||
- Arithmatex
|
||||
- Inlinehilite
|
||||
- Tasklist
|
||||
|
||||
[PyMdown Extensions]: http://facelessuser.github.io/pymdown-extensions/
|
||||
[usage notes]: https://facelessuser.github.io/pymdown-extensions/usage_notes/
|
||||
[BetterEm]: https://facelessuser.github.io/pymdown-extensions/extensions/betterem/
|
||||
[MagicLink]: https://facelessuser.github.io/pymdown-extensions/extensions/magiclink/
|
||||
[GitHub Emoji]: https://facelessuser.github.io/pymdown-extensions/extensions/githubemoji/
|
||||
[Emoji Cheat Sheet]: http://www.webpagefx.com/tools/emoji-cheat-sheet/
|
||||
[SuperFences]: https://facelessuser.github.io/pymdown-extensions/extensions/superfences/
|
||||
[Fenced Code Blocks]: https://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html
|
||||
[Tasklist]: https://facelessuser.github.io/pymdown-extensions/extensions/tasklist/
|
||||
[here]: /extensions/pymdown/tasklist
|
||||
[Tilde]: https://facelessuser.github.io/pymdown-extensions/extensions/tilde/
|
||||
[Caret]: https://facelessuser.github.io/pymdown-extensions/extensions/caret/
|
||||
[Mark]: https://facelessuser.github.io/pymdown-extensions/extensions/mark/
|
||||
|
@ -24,7 +24,7 @@ import clean from "del"
|
||||
import vinyl from "vinyl-paths"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Task: clean javascripts generated by build
|
||||
* Task: clean JavaScript generated by build
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default (gulp, config) => {
|
||||
|
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="352" height="448" viewBox="0 0 352 448"><path d="M203.75 214.75q2 15.75-12.625 25.25t-27.875 1.5q-9.75-4.25-13.375-14.5t-.125-20.5 13-14.5q9-4.5 18.125-3t16 8.875 6.875 16.875zm27.75-5.25q-3.5-26.75-28.25-41T154 165.25q-15.75 7-25.125 22.125t-8.625 32.375q1 22.75 19.375 38.75t41.375 14q22.75-2 38-21t12.5-42zM291.25 74q-5-6.75-14-11.125t-14.5-5.5T245 54.25q-72.75-11.75-141.5.5-10.75 1.75-16.5 3t-13.75 5.5T60.75 74q7.5 7 19 11.375t18.375 5.5T120 93.75Q177 101 232 94q15.75-2 22.375-3t18.125-5.375T291.25 74zm14.25 258.75q-2 6.5-3.875 19.125t-3.5 21-7.125 17.5-14.5 14.125q-21.5 12-47.375 17.875t-50.5 5.5-50.375-4.625q-11.5-2-20.375-4.5T88.75 412 70.5 401.125t-13-15.375q-6.25-24-14.25-73l1.5-4 4.5-2.25q55.75 37 126.625 37t126.875-37q5.25 1.5 6 5.75t-1.25 11.25-2 9.25zM350.75 92.5q-6.5 41.75-27.75 163.75-1.25 7.5-6.75 14t-10.875 10T291.75 288q-63 31.5-152.5 22-62-6.75-98.5-34.75-3.75-3-6.375-6.625t-4.25-8.75-2.25-8.5-1.5-9.875T25 232.75q-2.25-12.5-6.625-37.5t-7-40.375T5.5 118 0 78.5Q.75 72 4.375 66.375T12.25 57t11.25-7.5T35 43.875t12-4.625q31.25-11.5 78.25-16 94.75-9.25 169 12.5Q333 47.25 348 66.25q4 5 4.125 12.75t-1.375 13.5z"/></svg>
|
Before Width: | Height: | Size: 1.2 KiB |
20
material/assets/images/icons/bitbucket-black.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="352" height="448"
|
||||
viewBox="0 0 352 448">
|
||||
<path d="M203.75 214.75q2 15.75-12.625 25.25t-27.875
|
||||
1.5q-9.75-4.25-13.375-14.5t-0.125-20.5 13-14.5q9-4.5 18.125-3t16 8.875
|
||||
6.875 16.875zM231.5 209.5q-3.5-26.75-28.25-41t-49.25-3.25q-15.75
|
||||
7-25.125 22.125t-8.625 32.375q1 22.75 19.375 38.75t41.375 14q22.75-2
|
||||
38-21t12.5-42zM291.25
|
||||
74q-5-6.75-14-11.125t-14.5-5.5-17.75-3.125q-72.75-11.75-141.5 0.5-10.75
|
||||
1.75-16.5 3t-13.75 5.5-12.5 10.75q7.5 7 19 11.375t18.375 5.5 21.875
|
||||
2.875q57 7.25 112 0.25 15.75-2 22.375-3t18.125-5.375 18.75-11.625zM305.5
|
||||
332.75q-2 6.5-3.875 19.125t-3.5 21-7.125 17.5-14.5 14.125q-21.5
|
||||
12-47.375 17.875t-50.5 5.5-50.375-4.625q-11.5-2-20.375-4.5t-19.125-6.75-18.25-10.875-13-15.375q-6.25-24-14.25-73l1.5-4
|
||||
4.5-2.25q55.75 37 126.625 37t126.875-37q5.25 1.5 6 5.75t-1.25 11.25-2
|
||||
9.25zM350.75 92.5q-6.5 41.75-27.75 163.75-1.25 7.5-6.75 14t-10.875
|
||||
10-13.625 7.75q-63 31.5-152.5
|
||||
22-62-6.75-98.5-34.75-3.75-3-6.375-6.625t-4.25-8.75-2.25-8.5-1.5-9.875-1.375-8.75q-2.25-12.5-6.625-37.5t-7-40.375-5.875-36.875-5.5-39.5q0.75-6.5
|
||||
4.375-12.125t7.875-9.375 11.25-7.5 11.5-5.625 12-4.625q31.25-11.5
|
||||
78.25-16 94.75-9.25 169 12.5 38.75 11.5 53.75 30.5 4 5 4.125
|
||||
12.75t-1.375 13.5z" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="352" height="448" viewBox="0 0 352 448"><path d="M203.75 214.75q2 15.75-12.625 25.25t-27.875 1.5q-9.75-4.25-13.375-14.5t-.125-20.5 13-14.5q9-4.5 18.125-3t16 8.875 6.875 16.875zm27.75-5.25q-3.5-26.75-28.25-41T154 165.25q-15.75 7-25.125 22.125t-8.625 32.375q1 22.75 19.375 38.75t41.375 14q22.75-2 38-21t12.5-42zM291.25 74q-5-6.75-14-11.125t-14.5-5.5T245 54.25q-72.75-11.75-141.5.5-10.75 1.75-16.5 3t-13.75 5.5T60.75 74q7.5 7 19 11.375t18.375 5.5T120 93.75Q177 101 232 94q15.75-2 22.375-3t18.125-5.375T291.25 74zm14.25 258.75q-2 6.5-3.875 19.125t-3.5 21-7.125 17.5-14.5 14.125q-21.5 12-47.375 17.875t-50.5 5.5-50.375-4.625q-11.5-2-20.375-4.5T88.75 412 70.5 401.125t-13-15.375q-6.25-24-14.25-73l1.5-4 4.5-2.25q55.75 37 126.625 37t126.875-37q5.25 1.5 6 5.75t-1.25 11.25-2 9.25zM350.75 92.5q-6.5 41.75-27.75 163.75-1.25 7.5-6.75 14t-10.875 10T291.75 288q-63 31.5-152.5 22-62-6.75-98.5-34.75-3.75-3-6.375-6.625t-4.25-8.75-2.25-8.5-1.5-9.875T25 232.75q-2.25-12.5-6.625-37.5t-7-40.375T5.5 118 0 78.5Q.75 72 4.375 66.375T12.25 57t11.25-7.5T35 43.875t12-4.625q31.25-11.5 78.25-16 94.75-9.25 169 12.5Q333 47.25 348 66.25q4 5 4.125 12.75t-1.375 13.5z" fill="#fff"/></svg>
|
Before Width: | Height: | Size: 1.2 KiB |
20
material/assets/images/icons/bitbucket-white.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="352" height="448"
|
||||
viewBox="0 0 352 448">
|
||||
<path d="M203.75 214.75q2 15.75-12.625 25.25t-27.875
|
||||
1.5q-9.75-4.25-13.375-14.5t-0.125-20.5 13-14.5q9-4.5 18.125-3t16 8.875
|
||||
6.875 16.875zM231.5 209.5q-3.5-26.75-28.25-41t-49.25-3.25q-15.75
|
||||
7-25.125 22.125t-8.625 32.375q1 22.75 19.375 38.75t41.375 14q22.75-2
|
||||
38-21t12.5-42zM291.25
|
||||
74q-5-6.75-14-11.125t-14.5-5.5-17.75-3.125q-72.75-11.75-141.5 0.5-10.75
|
||||
1.75-16.5 3t-13.75 5.5-12.5 10.75q7.5 7 19 11.375t18.375 5.5 21.875
|
||||
2.875q57 7.25 112 0.25 15.75-2 22.375-3t18.125-5.375 18.75-11.625zM305.5
|
||||
332.75q-2 6.5-3.875 19.125t-3.5 21-7.125 17.5-14.5 14.125q-21.5
|
||||
12-47.375 17.875t-50.5 5.5-50.375-4.625q-11.5-2-20.375-4.5t-19.125-6.75-18.25-10.875-13-15.375q-6.25-24-14.25-73l1.5-4
|
||||
4.5-2.25q55.75 37 126.625 37t126.875-37q5.25 1.5 6 5.75t-1.25 11.25-2
|
||||
9.25zM350.75 92.5q-6.5 41.75-27.75 163.75-1.25 7.5-6.75 14t-10.875
|
||||
10-13.625 7.75q-63 31.5-152.5
|
||||
22-62-6.75-98.5-34.75-3.75-3-6.375-6.625t-4.25-8.75-2.25-8.5-1.5-9.875-1.375-8.75q-2.25-12.5-6.625-37.5t-7-40.375-5.875-36.875-5.5-39.5q0.75-6.5
|
||||
4.375-12.125t7.875-9.375 11.25-7.5 11.5-5.625 12-4.625q31.25-11.5
|
||||
78.25-16 94.75-9.25 169 12.5 38.75 11.5 53.75 30.5 4 5 4.125
|
||||
12.75t-1.375 13.5z" fill="white" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448"><path d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg>
|
Before Width: | Height: | Size: 959 B |
18
material/assets/images/icons/github-black.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
|
||||
viewBox="0 0 416 448">
|
||||
<path d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
|
||||
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
|
||||
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
|
||||
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
|
||||
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
|
||||
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
|
||||
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
|
||||
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
|
||||
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
|
||||
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
|
||||
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
|
||||
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
|
||||
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
|
||||
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
|
||||
99.5z" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448"><path d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z" fill="#fff"/></svg>
|
Before Width: | Height: | Size: 971 B |
18
material/assets/images/icons/github-white.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
|
||||
viewBox="0 0 416 448">
|
||||
<path d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
|
||||
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
|
||||
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
|
||||
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
|
||||
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
|
||||
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
|
||||
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
|
||||
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
|
||||
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
|
||||
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
|
||||
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
|
||||
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
|
||||
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
|
||||
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
|
||||
99.5z" fill="white" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 500 500"><path d="M249.865 474.507l90.684-279.097H159.18l90.684 279.097z"/><path d="M249.864 474.506L159.18 195.41H32.088l217.776 279.095z" opacity=".7"/><path d="M32.089 195.41l-27.56 84.816a18.773 18.773 0 0 0 6.822 20.99l238.514 173.29L32.089 195.41z" opacity=".5"/><path d="M32.089 195.412H159.18L104.56 27.314c-2.81-8.65-15.046-8.65-17.855 0L32.089 195.412z"/><path d="M249.865 474.506l90.684-279.095H467.64L249.865 474.506z" opacity=".7"/><path d="M467.641 195.41l27.56 84.816a18.772 18.772 0 0 1-6.822 20.99l-238.515 173.29L467.641 195.41z" opacity=".5"/><path d="M467.64 195.412H340.55l54.618-168.098c2.81-8.65 15.047-8.65 17.856 0l54.618 168.098z"/></svg>
|
Before Width: | Height: | Size: 742 B |
31
material/assets/images/icons/gitlab-black.svg
Normal file
@ -0,0 +1,31 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"
|
||||
viewBox="0 0 500 500">
|
||||
<g transform="translate(156.197863, 1.160267)">
|
||||
<path d="M93.667,473.347L93.667,473.347l90.684-279.097H2.983L93.667,
|
||||
473.347L93.667,473.347z" />
|
||||
</g>
|
||||
<g transform="translate(28.531199, 1.160800)" opacity="0.7">
|
||||
<path d="M221.333,473.345L130.649,194.25H3.557L221.333,473.345L221.333,
|
||||
473.345z" />
|
||||
</g>
|
||||
<g transform="translate(0.088533, 0.255867)" opacity="0.5">
|
||||
<path d="M32,195.155L32,195.155L4.441,279.97c-2.513,7.735,0.24,16.21,6.821,
|
||||
20.99l238.514,173.29 L32,195.155L32,195.155z" />
|
||||
</g>
|
||||
<g transform="translate(29.421866, 280.255593)">
|
||||
<path d="M2.667-84.844h127.092L75.14-252.942c-2.811-8.649-15.047-8.649-17.856,
|
||||
0L2.667-84.844 L2.667-84.844z" />
|
||||
</g>
|
||||
<g transform="translate(247.197860, 1.160800)" opacity="0.7">
|
||||
<path d="M2.667,473.345L93.351,194.25h127.092L2.667,473.345L2.667,
|
||||
473.345z" />
|
||||
</g>
|
||||
<g transform="translate(246.307061, 0.255867)" opacity="0.5">
|
||||
<path d="M221.334,195.155L221.334,195.155l27.559,84.815c2.514,7.735-0.24,
|
||||
16.21-6.821,20.99 L3.557,474.25L221.334,195.155L221.334,195.155z" />
|
||||
</g>
|
||||
<g transform="translate(336.973725, 280.255593)">
|
||||
<path d="M130.667-84.844H3.575l54.618-168.098c2.811-8.649,15.047-8.649,
|
||||
17.856,0L130.667-84.844 L130.667-84.844z" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 500 500"><path d="M249.865 474.507l90.684-279.097H159.18l90.684 279.097z" fill="#fff"/><path d="M249.864 474.506L159.18 195.41H32.088l217.776 279.095z" fill="#fff" opacity=".7"/><path d="M32.089 195.41l-27.56 84.816a18.773 18.773 0 0 0 6.822 20.99l238.514 173.29L32.089 195.41z" fill="#fff" opacity=".5"/><path d="M32.089 195.412H159.18L104.56 27.314c-2.81-8.65-15.046-8.65-17.855 0L32.089 195.412z" fill="#fff"/><path d="M249.865 474.506l90.684-279.095H467.64L249.865 474.506z" fill="#fff" opacity=".7"/><path d="M467.641 195.41l27.56 84.816a18.772 18.772 0 0 1-6.822 20.99l-238.515 173.29L467.641 195.41z" fill="#fff" opacity=".5"/><path d="M467.64 195.412H340.55l54.618-168.098c2.81-8.65 15.047-8.65 17.856 0l54.618 168.098z" fill="#fff"/></svg>
|
Before Width: | Height: | Size: 826 B |
32
material/assets/images/icons/gitlab-white.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"
|
||||
viewBox="0 0 500 500">
|
||||
<g transform="translate(156.197863, 1.160267)">
|
||||
<path d="M93.667,473.347L93.667,473.347l90.684-279.097H2.983L93.667,
|
||||
473.347L93.667,473.347z" fill="white" />
|
||||
</g>
|
||||
<g transform="translate(28.531199, 1.160800)" opacity="0.7">
|
||||
<path d="M221.333,473.345L130.649,194.25H3.557L221.333,473.345L221.333,
|
||||
473.345z" fill="white" />
|
||||
</g>
|
||||
<g transform="translate(0.088533, 0.255867)" opacity="0.5">
|
||||
<path d="M32,195.155L32,195.155L4.441,279.97c-2.513,7.735,0.24,16.21,6.821,
|
||||
20.99l238.514,173.29 L32,195.155L32,195.155z" fill="white" />
|
||||
</g>
|
||||
<g transform="translate(29.421866, 280.255593)">
|
||||
<path d="M2.667-84.844h127.092L75.14-252.942c-2.811-8.649-15.047-8.649-17.856,
|
||||
0L2.667-84.844 L2.667-84.844z" fill="white" />
|
||||
</g>
|
||||
<g transform="translate(247.197860, 1.160800)" opacity="0.7">
|
||||
<path d="M2.667,473.345L93.351,194.25h127.092L2.667,473.345L2.667,
|
||||
473.345z" fill="white" />
|
||||
</g>
|
||||
<g transform="translate(246.307061, 0.255867)" opacity="0.5">
|
||||
<path d="M221.334,195.155L221.334,195.155l27.559,84.815c2.514,7.735-0.24,
|
||||
16.21-6.821,20.99 L3.557,474.25L221.334,195.155L221.334,195.155z"
|
||||
fill="white" />
|
||||
</g>
|
||||
<g transform="translate(336.973725, 280.255593)">
|
||||
<path d="M130.667-84.844H3.575l54.618-168.098c2.811-8.649,15.047-8.649,
|
||||
17.856,0L130.667-84.844 L130.667-84.844z" fill="white" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
5407
material/assets/javascripts/application.js
Normal file
1286
material/assets/javascripts/modernizr.js
Normal file
1736
material/assets/stylesheets/application.css
Normal file
@ -20,19 +20,19 @@
|
||||
<meta name="author" content="{{ site_author }}">
|
||||
{% endif %}
|
||||
<meta name="generator" content="mkdocs+mkdocs-material#0.2.1">
|
||||
<script src="{{ base_url }}/assets/javascripts/modernizr-dede1352ed.js"></script>
|
||||
<script src="{{ base_url }}/assets/javascripts/modernizr.js"></script>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono:400">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-9cd3c99a66.css">
|
||||
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application.css">
|
||||
{% for path in extra_css %}
|
||||
<link rel="stylesheet" href="{{ path }}">
|
||||
{% endfor %}
|
||||
</head>
|
||||
<body>
|
||||
<input class="md-toggle md-toggle--drawer" type="checkbox" id="drawer">
|
||||
<input class="md-toggle md-toggle--search" type="checkbox" id="search">
|
||||
<label class="md-overlay" for="drawer"></label>
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="drawer">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="search">
|
||||
<label class="md-overlay" data-md-overlay for="drawer"></label>
|
||||
{% include "partials/header.html" %}
|
||||
<div class="md-container">
|
||||
<main class="md-main">
|
||||
@ -87,6 +87,12 @@
|
||||
</main>
|
||||
{% include "partials/footer.html" %}
|
||||
</div>
|
||||
{% for extension in config.markdown_extensions %}
|
||||
{% if extension == "pymdownx.arithmatex" %}
|
||||
{% set path = "mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML" %}
|
||||
<script src="https://cdn.mathjax.org/{{ path }}"></script>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<script src="{{ base_url }}/assets/javascripts/application.js"></script>
|
||||
<script>
|
||||
/* Configuration for application */
|
||||
|
@ -1,9 +1,9 @@
|
||||
{% if nav_item.children %}
|
||||
<li class="md-nav__item md-nav__item--nested">
|
||||
{% if nav_item.active %}
|
||||
<input class="md-toggle md-nav__toggle" type="checkbox" id="{{ path }}" checked>
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}" checked>
|
||||
{% else %}
|
||||
<input class="md-toggle md-nav__toggle" type="checkbox" id="{{ path }}">
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}">
|
||||
{% endif %}
|
||||
<label class="md-nav__link" for="{{ path }}">
|
||||
{{ nav_item.title }}
|
||||
@ -24,7 +24,7 @@
|
||||
</li>
|
||||
{% elif nav_item == current_page %}
|
||||
<li class="md-nav__item">
|
||||
<input class="md-toggle md-nav__toggle" type="checkbox" id="toc">
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="toc">
|
||||
<label class="md-nav__link md-nav__link--active" for="toc">
|
||||
{{ nav_item.title }}
|
||||
</label>
|
||||
|
@ -1,18 +1,13 @@
|
||||
<div class="md-search">
|
||||
<div class="md-search" data-md-search>
|
||||
<div class="md-search__overlay"></div>
|
||||
<div class="md-search__inner">
|
||||
<form class="md-search__form">
|
||||
<input type="text" class="md-search__input" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" id="query">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false">
|
||||
<label class="md-icon md-search__icon" for="search"></label>
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
<div class="md-search__scrollwrap">
|
||||
<div class="md-search-result">
|
||||
<div class="md-search-result__meta">
|
||||
Indexing
|
||||
</div>
|
||||
<ol class="md-search-result__list"></ol>
|
||||
</div>
|
||||
<div class="md-search-result" data-md-search-result></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,20 +1,19 @@
|
||||
{% set platform = config.extra.repo_icon or repo_url %}
|
||||
{% if "github" in platform %}
|
||||
{% set repo_type = "github" %}
|
||||
{% set repo_icon = "md-source--github" %}
|
||||
{% elif "gitlab" in platform %}
|
||||
{% set repo_type = "gitlab" %}
|
||||
{% set repo_icon = "md-source--gitlab" %}
|
||||
{% elif "bitbucket" in platform %}
|
||||
{% set repo_type = "bitbucket" %}
|
||||
{% set repo_icon = "md-source--bitbucket" %}
|
||||
{% else %}
|
||||
{% set repo_type = "" %}
|
||||
{% set repo_icon = "" %}
|
||||
{% endif %}
|
||||
<a href="{{ repo_url }}" title="Go to repository" class="md-source {{ repo_icon }}">
|
||||
<a href="{{ repo_url }}" title="Go to repository" class="md-source {{ repo_icon }}" data-md-source="{{ repo_type }}">
|
||||
<div class="md-source__repository">
|
||||
{{ repo_name }}
|
||||
<ul class="md-source__facts">
|
||||
{% if config.extra.version %}
|
||||
<li class="md-source__fact">v{{ config.extra.version }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
|
@ -52,9 +52,11 @@ markdown_extensions:
|
||||
- markdown.extensions.footnotes
|
||||
- markdown.extensions.meta
|
||||
- markdown.extensions.toc(permalink=true)
|
||||
- pymdownx.betterem
|
||||
- pymdownx.arithmatex
|
||||
- pymdownx.betterem(smart_enable=all)
|
||||
- pymdownx.caret
|
||||
- pymdownx.critic
|
||||
- pymdownx.githubemoji
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.magiclink
|
||||
- pymdownx.mark
|
||||
@ -76,6 +78,7 @@ pages:
|
||||
- Permalinks: extensions/permalinks.md
|
||||
- PyMdown:
|
||||
- Overview: extensions/pymdown/overview.md
|
||||
- Arithmatex: extensions/pymdown/arithmatex.md
|
||||
- Tasklist: extensions/pymdown/tasklist.md
|
||||
- Specimen: specimen.md
|
||||
- Customization: customization.md
|
||||
|
@ -31,6 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"fastclick": "^1.0.6",
|
||||
"js-cookie": "^2.1.3",
|
||||
"lunr": "^0.7.1",
|
||||
"material-design-color": "^2.3.1",
|
||||
"material-shadows": "^3.0.0",
|
||||
|
@ -20,182 +20,32 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Imports
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
import FastClick from "fastclick"
|
||||
|
||||
// import Expander from "./components/expander"
|
||||
|
||||
import GithubSourceFacts from "./components/GithubSourceFacts"
|
||||
import Material from "./components/Material"
|
||||
|
||||
// import Search from './components/search';
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Application
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
class Application {
|
||||
export default class Application {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create the application
|
||||
*
|
||||
* @constructor
|
||||
* @param {object} config Configuration object
|
||||
* @return {void}
|
||||
*/
|
||||
constructor(config) {
|
||||
this.config_ = config
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all components
|
||||
* Initialize all components and listeners
|
||||
*/
|
||||
initialize() {
|
||||
|
||||
/* Initialize sticky sidebars */
|
||||
this.initializeSidebar("[data-md-sidebar=primary]", "(min-width: 1200px)")
|
||||
this.initializeSidebar("[data-md-sidebar=secondary]")
|
||||
|
||||
/* Initialize navigation style modifiers */
|
||||
this.initializeNavBlur("[data-md-sidebar=secondary] .md-nav__link")
|
||||
this.initializeNavCollapse("[data-md-collapse]", "(min-width: 1200px)")
|
||||
|
||||
// TODO
|
||||
if (this.hasGithubRepo()) {
|
||||
const githubSource = new GithubSourceFacts(
|
||||
this.config_.storage,
|
||||
this.config_.repo.url
|
||||
)
|
||||
githubSource.initialize()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize sidebar within optional media query range
|
||||
*
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
* @param {string} [query] - Media query
|
||||
*/
|
||||
initializeSidebar(el, query = null) {
|
||||
const sidebar = new Material.Sidebar(el)
|
||||
const listeners = [
|
||||
new Material.Listener.Viewport.Offset(() => sidebar.update()),
|
||||
new Material.Listener.Viewport.Resize(() => sidebar.update())
|
||||
]
|
||||
|
||||
/* Initialize depending on media query */
|
||||
if (typeof query === "string" && query.length) {
|
||||
new Material.Listener.Viewport.Media(query, media => {
|
||||
if (media.matches) {
|
||||
sidebar.update()
|
||||
for (const listener of listeners)
|
||||
listener.listen()
|
||||
} else {
|
||||
sidebar.reset()
|
||||
for (const listener of listeners)
|
||||
listener.unlisten()
|
||||
}
|
||||
}).listen()
|
||||
|
||||
/* Initialize without media query */
|
||||
} else {
|
||||
sidebar.update()
|
||||
for (const listener of listeners)
|
||||
listener.listen()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize blurring of anchors above page y-offset
|
||||
*
|
||||
* @param {(string|NodeList<HTMLElement>)} els - Selector or HTML elements
|
||||
*/
|
||||
initializeNavBlur(els) {
|
||||
const blur = new Material.Nav.Blur(els)
|
||||
const listeners = [
|
||||
new Material.Listener.Viewport.Offset(() => blur.update())
|
||||
]
|
||||
|
||||
/* Initialize blur and listeners */
|
||||
blur.update()
|
||||
for (const listener of listeners)
|
||||
listener.listen()
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize collapsible nested navigation elements
|
||||
*
|
||||
* @param {(string|NodeList<HTMLElement>)} els - Selector or HTML elements
|
||||
* @param {string} [query] - Media query
|
||||
*/
|
||||
initializeNavCollapse(els, query = null) {
|
||||
const collapsibles = document.querySelectorAll(els)
|
||||
for (const collapsible of collapsibles) {
|
||||
const collapse = new Material.Nav.Collapse(collapsible)
|
||||
const listener = new Material.Listener.Toggle(
|
||||
collapsible.previousElementSibling, () => collapse.update())
|
||||
|
||||
/* Initialize depending on media query */
|
||||
new Material.Listener.Viewport.Media(query, media => {
|
||||
if (media.matches) {
|
||||
listener.listen()
|
||||
} else {
|
||||
collapse.reset()
|
||||
listener.unlisten()
|
||||
}
|
||||
}).listen()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this application about a Github repository?
|
||||
*
|
||||
* @return {bool} - true if `repo.icon` or `repo.url` contains 'github'
|
||||
*/
|
||||
hasGithubRepo() {
|
||||
return this.config_.repo.icon === "github"
|
||||
|| this.config_.repo.url.includes("github")
|
||||
}
|
||||
}
|
||||
|
||||
export default Application
|
||||
|
||||
// const consume = reader => {
|
||||
// let total = 0, body = ""
|
||||
// return new Promise((resolve, reject) => {
|
||||
// function pump() {
|
||||
// reader.read().then(({ done, value }) => {
|
||||
// if (done) {
|
||||
// console.log(body)
|
||||
// resolve()
|
||||
// return
|
||||
// }
|
||||
// total += value.byteLength
|
||||
// // value +=
|
||||
// body += value
|
||||
// console.log(`received ${value.byteLength}, total: ${total}`)
|
||||
// pump()
|
||||
// })
|
||||
// .catch(reject)
|
||||
// }
|
||||
// pump()
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// fetch("/mkdocs/search_index.json")
|
||||
// .then(res => consume(res.body.getReader()))
|
||||
// .then(() => console.log("consumed entire body"))
|
||||
// .catch(e => console.log(e))
|
||||
|
||||
// TODO: wrap in function call
|
||||
// application module export
|
||||
|
||||
/* Initialize application upon DOM ready */
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
/* Initialize Modernizr and Fastclick */
|
||||
new Material.Event.Listener(document, "DOMContentLoaded", () => {
|
||||
|
||||
/* Test for iOS */
|
||||
Modernizr.addTest("ios", () => {
|
||||
@ -209,45 +59,141 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
/* Attack FastClick to mitigate 300ms delay on touch devices */
|
||||
FastClick.attach(document.body)
|
||||
}).listen()
|
||||
|
||||
// query.addEventListener("focus", () => {
|
||||
// document.querySelector(".md-search").dataset.mdLocked = ""
|
||||
// })
|
||||
/* Cross-browser helper to dispatch/fire an event */
|
||||
const dispatch = (el, event) => {
|
||||
return document.createEvent
|
||||
? el.dispatchEvent(new Event(event))
|
||||
: el.fireEvent(`on${event}`, document.createEventObject())
|
||||
}
|
||||
|
||||
/* Intercept click on search mode toggle */
|
||||
/* Truncate a string after the given number of characters - this is not
|
||||
a reasonable approach, since the summaries kind of suck. It would be
|
||||
better to create something more intelligent, highlighting the search
|
||||
occurrences and making a better summary out of it */
|
||||
const truncate = function(string, n) {
|
||||
let i = n
|
||||
if (string.length > i) {
|
||||
while (string[i] !== " " && --i > 0);
|
||||
return `${string.substring(0, i)}...`
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
// TODO: this needs to be abstracted...
|
||||
document.getElementById("query").addEventListener("focus", () => {
|
||||
document.getElementById("search").checked = true
|
||||
/* Component: sidebar with navigation */
|
||||
new Material.Event.MatchMedia("(min-width: 1200px)",
|
||||
new Material.Event.Listener(window, [
|
||||
"scroll", "resize", "orientationchange"
|
||||
], new Material.Sidebar("[data-md-sidebar=primary]")))
|
||||
|
||||
/* Component: sidebar with table of contents */
|
||||
new Material.Event.MatchMedia("(min-width: 960px)",
|
||||
new Material.Event.Listener(window, [
|
||||
"scroll", "resize", "orientationchange"
|
||||
], new Material.Sidebar("[data-md-sidebar=secondary]")))
|
||||
|
||||
/* Component: link blurring for table of contents */
|
||||
new Material.Event.MatchMedia("(min-width: 960px)",
|
||||
new Material.Event.Listener(window, "scroll",
|
||||
new Material.Nav.Blur("[data-md-sidebar=secondary] .md-nav__link")))
|
||||
|
||||
/* Component: collapsible elements for navigation */
|
||||
const collapsibles = document.querySelectorAll("[data-md-collapse]")
|
||||
for (const collapse of collapsibles)
|
||||
new Material.Event.MatchMedia("(min-width: 1200px)",
|
||||
new Material.Event.Listener(collapse.previousElementSibling, "click",
|
||||
new Material.Nav.Collapse(collapse)))
|
||||
|
||||
/* Component: search body lock for mobile */
|
||||
new Material.Event.MatchMedia("(max-width: 959px)",
|
||||
new Material.Event.Listener("[data-md-toggle=search]", "change",
|
||||
new Material.Search.Lock("[data-md-toggle=search]")))
|
||||
|
||||
/* Component: search results */
|
||||
new Material.Event.Listener(document.forms.search.query, [
|
||||
"focus", "keyup"
|
||||
], new Material.Search.Result("[data-md-search-result]", () => {
|
||||
return fetch(`${this.config_.url.base}/mkdocs/search_index.json`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
return data.docs.map(doc => {
|
||||
doc.location = this.config_.url.base + doc.location
|
||||
doc.text = truncate(doc.text, 140)
|
||||
return doc
|
||||
})
|
||||
|
||||
// should be registered on body, but leads to problems
|
||||
document.querySelector(".md-container").addEventListener("click", () => {
|
||||
if (document.getElementById("search").checked)
|
||||
document.getElementById("search").checked = false
|
||||
})
|
||||
})).listen()
|
||||
|
||||
// stop propagation, if search is active...
|
||||
document.querySelector(".md-search").addEventListener("click", ev => {
|
||||
ev.stopPropagation()
|
||||
/* Listener: prevent touches on overlay if navigation is active */
|
||||
new Material.Event.MatchMedia("(max-width: 1199px)",
|
||||
new Material.Event.Listener("[data-md-overlay]", "touchstart",
|
||||
ev => ev.preventDefault()))
|
||||
|
||||
/* Listener: close drawer when anchor links are clicked */
|
||||
new Material.Event.MatchMedia("(max-width: 959px)",
|
||||
new Material.Event.Listener("[data-md-sidebar=primary] [href^='#']",
|
||||
"click", () => {
|
||||
const toggle = document.querySelector("[data-md-toggle=drawer]")
|
||||
if (toggle.checked) {
|
||||
toggle.checked = false
|
||||
dispatch(toggle, "change")
|
||||
}
|
||||
}))
|
||||
|
||||
/* Listener: focus input after activating search */
|
||||
new Material.Event.Listener("[data-md-toggle=search]", "change", ev => {
|
||||
setTimeout(toggle => {
|
||||
const query = document.forms.search.query
|
||||
if (toggle.checked)
|
||||
query.focus()
|
||||
}, 400, ev.target)
|
||||
}).listen()
|
||||
|
||||
/* Listener: activate search on focus */
|
||||
new Material.Event.MatchMedia("(min-width: 960px)",
|
||||
new Material.Event.Listener(document.forms.search.query, "focus", () => {
|
||||
const toggle = document.querySelector("[data-md-toggle=search]")
|
||||
if (!toggle.checked) {
|
||||
toggle.checked = true
|
||||
dispatch(toggle, "change")
|
||||
}
|
||||
}))
|
||||
|
||||
/* Listener: disable search when clicking outside */
|
||||
new Material.Event.MatchMedia("(min-width: 960px)",
|
||||
new Material.Event.Listener(document.body, "click", () => {
|
||||
const toggle = document.querySelector("[data-md-toggle=search]")
|
||||
if (toggle.checked) {
|
||||
toggle.checked = false
|
||||
dispatch(toggle, "change")
|
||||
}
|
||||
}))
|
||||
|
||||
/* Listener: fix unclickable toggle due to blur handler */
|
||||
new Material.Event.MatchMedia("(min-width: 960px)",
|
||||
new Material.Event.Listener("[data-md-toggle=search]", "click",
|
||||
ev => ev.stopPropagation()))
|
||||
|
||||
/* Listener: prevent search from closing when clicking */
|
||||
new Material.Event.MatchMedia("(min-width: 960px)",
|
||||
new Material.Event.Listener("[data-md-search]", "click",
|
||||
ev => ev.stopPropagation()))
|
||||
|
||||
/* Retrieve the facts for the given repository type */
|
||||
;(() => {
|
||||
const el = document.querySelector("[data-md-source]")
|
||||
switch (el.dataset.mdSource) {
|
||||
case "github": return new Material.Source.Adapter.GitHub(el).fetch()
|
||||
default: return Promise.resolve([])
|
||||
}
|
||||
|
||||
/* Render repository source information */
|
||||
})().then(facts => {
|
||||
const sources = document.querySelectorAll("[data-md-source]")
|
||||
for (const source of sources)
|
||||
new Material.Source.Repository(source)
|
||||
.initialize(facts)
|
||||
})
|
||||
// toggleSearchClose.addEventListener("click", ev => {
|
||||
// ev.preventDefault()
|
||||
// // ev.target
|
||||
//
|
||||
// const search = document.getElementById("search")
|
||||
// search.checked = false
|
||||
// })
|
||||
|
||||
// }, 1000);
|
||||
|
||||
fetch(
|
||||
"https://api.github.com/repos/squidfunk/mkdocs-material/releases/latest")
|
||||
.then(response => {
|
||||
return response.json()
|
||||
})
|
||||
// .then(data => {
|
||||
// // console.log(data)
|
||||
// })
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Github Source
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default
|
||||
class GithubSourceFacts {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @constructor
|
||||
* @param {object} storage - Accessor to storage, eg. `window.sessionStorage`
|
||||
* @param {string} repoUrl - URL to Github repository
|
||||
*/
|
||||
constructor(storage, repoUrl) {
|
||||
this.storage = storage
|
||||
this.storageKey = "github-source-facts"
|
||||
this.apiRepoUrl = repoUrl.replace("github.com/", "api.github.com/repos/")
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve stars and fork counts for the repository before invoking
|
||||
* `GithubSourceFacts.paint`.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
initialize() {
|
||||
const facts = this.storage.getItem(this.storageKey)
|
||||
|
||||
// Retrieve the facts, then invoke paint
|
||||
if (!facts) {
|
||||
fetch(this.apiRepoUrl)
|
||||
.then(response => {
|
||||
return response.json()
|
||||
})
|
||||
.then(data => {
|
||||
const repoFacts = {
|
||||
stars: data.stargazers_count,
|
||||
forks: data.forks_count
|
||||
}
|
||||
|
||||
this.storage.setItem(this.storageKey, JSON.stringify(repoFacts))
|
||||
|
||||
GithubSourceFacts.paint(repoFacts)
|
||||
})
|
||||
.catch(() => {
|
||||
// console.log("parsing failed", ex)
|
||||
})
|
||||
// Use the cached facts
|
||||
} else {
|
||||
GithubSourceFacts.paint(JSON.parse(facts))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates `.md-source__facts` with star and fork counts.
|
||||
*
|
||||
* @param {integer} options.stars - Stars count for the repo
|
||||
* @param {integer} options.forks - Fork count for the repo
|
||||
* @return {void}
|
||||
*/
|
||||
static paint({ stars, forks }) {
|
||||
const lists = document.querySelectorAll(".md-source__facts"); // TODO 2x list in drawer and header
|
||||
|
||||
// TODO: use ... of ...
|
||||
[].forEach.call(lists, list => {
|
||||
let li = (
|
||||
<li class="md-source__fact md-source__fact--hidden">
|
||||
{stars} Stars
|
||||
</li>
|
||||
)
|
||||
setTimeout(fact => {
|
||||
fact.classList.remove("md-source__fact--hidden")
|
||||
}, 100, li)
|
||||
list.appendChild(li)
|
||||
|
||||
li = (
|
||||
<li class="md-source__fact md-source__fact--hidden">
|
||||
{forks} Forks
|
||||
</li>
|
||||
)
|
||||
setTimeout(fact => {
|
||||
fact.classList.remove("md-source__fact--hidden")
|
||||
}, 500, li)
|
||||
list.appendChild(li)
|
||||
})
|
||||
}
|
||||
}
|
@ -20,56 +20,20 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Event from "./Material/Event"
|
||||
import Nav from "./Material/Nav"
|
||||
import Search from "./Material/Search"
|
||||
import Listener from "./Material/Listener"
|
||||
import Sidebar from "./Material/Sidebar"
|
||||
import Source from "./Material/Source"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Module
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default {
|
||||
Event,
|
||||
Nav,
|
||||
Search,
|
||||
Listener,
|
||||
Sidebar
|
||||
Sidebar,
|
||||
Source
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
// export default class Material {
|
||||
//
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
// static initializeSearch() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Initialize all components
|
||||
// */
|
||||
// static initialize() {
|
||||
//
|
||||
// const search = new Search.Lock("#search", () => {
|
||||
// document.getElementById("query").focus()
|
||||
// })
|
||||
// search.listen() // TODO when this is commented out, focusing the search somehow breaks things...
|
||||
//
|
||||
// const searchx = document.getElementById("search")
|
||||
// const initialize = () => {
|
||||
// const foo = new Search.Index()
|
||||
// console.log(foo)
|
||||
//
|
||||
// searchx.removeEventListener("change", initialize)
|
||||
// }
|
||||
// searchx.addEventListener("change", initialize)
|
||||
// console.log(searchx)
|
||||
//
|
||||
// // TODO nav bar is blurry until 959px, when expanded...
|
||||
// }
|
||||
// }
|
||||
|
@ -20,16 +20,14 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Media from "./Viewport/Media"
|
||||
import Offset from "./Viewport/Offset"
|
||||
import Resize from "./Viewport/Resize"
|
||||
import Listener from "./Event/Listener"
|
||||
import MatchMedia from "./Event/MatchMedia"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Module
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default {
|
||||
Media,
|
||||
Offset,
|
||||
Resize
|
||||
Listener,
|
||||
MatchMedia
|
||||
}
|
77
src/assets/javascripts/components/Material/Event/Listener.js
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Listener {
|
||||
|
||||
/**
|
||||
* Generic event listener
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|NodeList<HTMLElement>)} els - Selector or HTML elements
|
||||
* @param {Array.<string>} events - Event names
|
||||
* @param {(object|function)} handler - Handler to be invoked
|
||||
*/
|
||||
constructor(els, events, handler) {
|
||||
this.els_ = (typeof els === "string")
|
||||
? document.querySelectorAll(els)
|
||||
: [].concat(els)
|
||||
|
||||
/* Set handler as function or directly as object */
|
||||
this.handler_ = typeof handler === "function"
|
||||
? { update: handler }
|
||||
: handler
|
||||
|
||||
/* Initialize event names and update handler */
|
||||
this.events_ = [].concat(events)
|
||||
this.update_ = ev => this.handler_.update(ev)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener for all relevant events
|
||||
*/
|
||||
listen() {
|
||||
for (const el of this.els_)
|
||||
for (const event of this.events_)
|
||||
el.addEventListener(event, this.update_, false)
|
||||
|
||||
/* Execute setup handler, if implemented */
|
||||
if (typeof this.handler_.setup === "function")
|
||||
this.handler_.setup()
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listener for all relevant events
|
||||
*/
|
||||
unlisten() {
|
||||
for (const el of this.els_)
|
||||
for (const event of this.events_)
|
||||
el.removeEventListener(event, this.update_)
|
||||
|
||||
/* Execute reset handler, if implemented */
|
||||
if (typeof this.handler_.reset === "function")
|
||||
this.handler_.reset()
|
||||
}
|
||||
}
|
@ -21,37 +21,34 @@
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Media {
|
||||
export default class MatchMedia {
|
||||
|
||||
/**
|
||||
* Listener which checks for media queries on dimension changes
|
||||
* Media query listener
|
||||
*
|
||||
* This class listens for state changes of media queries and automatically
|
||||
* switches the given listeners on or off.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} query - Media query
|
||||
* @param {Function} handler - Event handler to execute
|
||||
* @param {string} query - Media query to test for
|
||||
* @param {Listener} listener - Event listener
|
||||
*/
|
||||
constructor(query, handler) {
|
||||
this.media_ = window.matchMedia(query)
|
||||
this.handler_ = media => {
|
||||
handler(media)
|
||||
}
|
||||
constructor(query, listener) {
|
||||
this.handler_ = mq => {
|
||||
if (mq.matches)
|
||||
listener.listen()
|
||||
else
|
||||
listener.unlisten()
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener for media query check
|
||||
*/
|
||||
listen() {
|
||||
this.media_.addListener(this.handler_)
|
||||
this.handler_(this.media_)
|
||||
}
|
||||
/* Initialize media query listener */
|
||||
const media = window.matchMedia(query)
|
||||
media.addListener(this.handler_)
|
||||
|
||||
/**
|
||||
* Unregister listener for media query check
|
||||
*/
|
||||
unlisten() {
|
||||
this.media_.removeListener(this.handler_)
|
||||
/* Always check at initialization */
|
||||
this.handler_(media)
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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.
|
||||
*/
|
||||
|
||||
import Abstract from "../Abstract"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Resize extends Abstract {
|
||||
|
||||
/**
|
||||
* Listener which monitors changes to the dimensions of the viewport
|
||||
*
|
||||
* @constructor
|
||||
* @param {Function} handler - Event handler to execute
|
||||
*/
|
||||
constructor(handler) {
|
||||
super(window, ["resize", "orientationchange"], handler)
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Blur {
|
||||
@ -47,6 +47,13 @@ export default class Blur {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize anchor states
|
||||
*/
|
||||
setup() {
|
||||
this.update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update anchor states
|
||||
*/
|
||||
@ -58,7 +65,7 @@ export default class Blur {
|
||||
for (let i = this.index_ + 1; i < this.els_.length; i++) {
|
||||
if (this.anchors_[i].offsetTop <= offset) {
|
||||
if (i > 0)
|
||||
this.els_[i - 1].dataset.mdBlurred = ""
|
||||
this.els_[i - 1].dataset.mdState = "blur"
|
||||
this.index_ = i
|
||||
} else {
|
||||
break
|
||||
@ -70,7 +77,7 @@ export default class Blur {
|
||||
for (let i = this.index_; i >= 0; i--) {
|
||||
if (this.anchors_[i].offsetTop > offset) {
|
||||
if (i > 0)
|
||||
delete this.els_[i - 1].dataset.mdBlurred
|
||||
delete this.els_[i - 1].dataset.mdState
|
||||
} else {
|
||||
this.index_ = i
|
||||
break
|
||||
@ -86,8 +93,11 @@ export default class Blur {
|
||||
* Reset anchor states
|
||||
*/
|
||||
reset() {
|
||||
[].forEach.call(this.els_, el => {
|
||||
delete el.dataset.mdBlurred
|
||||
})
|
||||
for (const el of this.els_)
|
||||
delete el.dataset.mdState
|
||||
|
||||
/* Reset index and page y-offset */
|
||||
this.index_ = 0
|
||||
this.offset_ = window.pageYOffset
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Collapse {
|
||||
@ -39,7 +39,7 @@ export default class Collapse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Make expand and collapse transition smoothly
|
||||
* Animate expand and collapse smoothly
|
||||
*/
|
||||
update() {
|
||||
const current = this.el_.getBoundingClientRect().height
|
||||
@ -48,43 +48,43 @@ export default class Collapse {
|
||||
if (current) {
|
||||
this.el_.style.maxHeight = `${current}px`
|
||||
requestAnimationFrame(() => {
|
||||
this.el_.dataset.mdAnimated = ""
|
||||
this.el_.dataset.mdState = "animate"
|
||||
this.el_.style.maxHeight = "0px"
|
||||
})
|
||||
|
||||
/* Collapsed, so expand */
|
||||
} else {
|
||||
this.el_.dataset.mdState = "expand"
|
||||
this.el_.style.maxHeight = ""
|
||||
this.el_.dataset.mdExpanded = ""
|
||||
|
||||
/* Read height and unset pseudo-toggled state */
|
||||
const height = this.el_.getBoundingClientRect().height
|
||||
delete this.el_.dataset.mdExpanded
|
||||
delete this.el_.dataset.mdState
|
||||
|
||||
/* Set initial state and animate */
|
||||
this.el_.style.maxHeight = "0px"
|
||||
requestAnimationFrame(() => {
|
||||
this.el_.dataset.mdAnimated = ""
|
||||
this.el_.dataset.mdState = "animate"
|
||||
this.el_.style.maxHeight = `${height}px`
|
||||
})
|
||||
}
|
||||
|
||||
/* Remove state on end of transition */
|
||||
const end = function(ev) {
|
||||
delete ev.target.dataset.mdAnimated
|
||||
delete ev.target.dataset.mdState
|
||||
ev.target.style.maxHeight = ""
|
||||
|
||||
/* Only fire once, so remove event listener again */
|
||||
/* Only fire once, so directly remove event listener */
|
||||
ev.target.removeEventListener("transitionend", end, false)
|
||||
}
|
||||
this.el_.addEventListener("transitionend", end, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Nothing to reset
|
||||
* Reset height and pseudo-toggled state
|
||||
*/
|
||||
reset() {
|
||||
delete this.el_.dataset.mdState
|
||||
this.el_.style.maxHeight = ""
|
||||
delete this.el_.dataset.mdToggled
|
||||
}
|
||||
}
|
||||
|
@ -20,14 +20,14 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Index from "./Search/Index"
|
||||
import Lock from "./Search/Lock"
|
||||
import Result from "./Search/Result"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Module
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default {
|
||||
Index,
|
||||
Lock
|
||||
Lock,
|
||||
Result
|
||||
}
|
||||
|
@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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.
|
||||
*/
|
||||
|
||||
import lunr from "lunr"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Index {
|
||||
|
||||
/**
|
||||
* // TODO: just copy+pasted
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
constructor() {
|
||||
const query = document.getElementById("query")
|
||||
// TODO: put this in search index class...
|
||||
// setTimeout(function() {
|
||||
|
||||
// indexed percentage!
|
||||
|
||||
fetch("/mkdocs/search_index.json") // TODO: prepend BASE URL!!!
|
||||
.then(response => {
|
||||
return response.json()
|
||||
})
|
||||
.then(data => {
|
||||
|
||||
/* Create index */
|
||||
const index = lunr(function() {
|
||||
/* eslint-disable no-invalid-this, lines-around-comment */
|
||||
this.field("title", { boost: 10 })
|
||||
this.field("text")
|
||||
this.ref("location")
|
||||
/* eslint-enable no-invalid-this, lines-around-comment */
|
||||
})
|
||||
|
||||
/* Index articles */
|
||||
const articles = {}
|
||||
data.docs.forEach((article, i) => {
|
||||
// console.log(`indexing...${i}`)
|
||||
const meta = document.querySelector(".md-search-result__meta")
|
||||
meta.innerHTML = `Indexing: ${(i + 1) / data.docs.length}%`
|
||||
|
||||
// TODO: match for two whitespaces, then replace unnecessary whitespace after string
|
||||
article.text = article.text.replace(/\s(\.,\:)\s/gi, (string, g1) => {
|
||||
return `${g1} `
|
||||
})
|
||||
// TODO: window.baseUrl sucks...
|
||||
article.location = window.baseUrl + article.location
|
||||
articles[article.location] = article
|
||||
index.add(article)
|
||||
})
|
||||
|
||||
/* Truncate a string after the given number of characters */
|
||||
const truncate = function(string, n) {
|
||||
let i = n
|
||||
if (string.length > i) {
|
||||
while (string[i] !== " " && --i > 0);
|
||||
return `${string.substring(0, i)}…`
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
/* Register keyhandler to execute search on key up */
|
||||
const queryx = document.getElementById("query")
|
||||
queryx.addEventListener("keyup", () => {
|
||||
const container = document.querySelector(".md-search-result__list")
|
||||
while (container.firstChild)
|
||||
container.removeChild(container.firstChild)
|
||||
|
||||
// /* Abort, if the query is empty */
|
||||
// var bar = document.querySelector('.bar.search');
|
||||
// if (!query.value.length) {
|
||||
// while (meta.firstChild)
|
||||
// meta.removeChild(meta.firstChild);
|
||||
//
|
||||
// /* Restore state */
|
||||
// bar.classList.remove('non-empty');
|
||||
// return;
|
||||
// }
|
||||
|
||||
/* Show reset button */
|
||||
// bar.classList.add('non-empty');
|
||||
|
||||
/* Execute search */
|
||||
const results = index.search(query.value)
|
||||
results.forEach(result => {
|
||||
const article = articles[result.ref]
|
||||
|
||||
container.appendChild(
|
||||
<li class="md-search-result__item">
|
||||
<a href={article.location} title={article.title}
|
||||
class="md-search-result__link">
|
||||
<article class="md-search-result__article">
|
||||
<h1 class="md-search-result__title">
|
||||
{article.title}
|
||||
</h1>
|
||||
<p class="md-search-result__teaser">
|
||||
{truncate(article.text, 140)}
|
||||
</p>
|
||||
</article>
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
/* Show number of search results */
|
||||
// var number = document.createElement('strong');
|
||||
|
||||
const meta = document.querySelector(".md-search-result__meta")
|
||||
meta.innerHTML = `${results.length} search result${
|
||||
results.length !== 1
|
||||
? "s"
|
||||
: ""}`
|
||||
|
||||
/* Update number */
|
||||
// while (meta.firstChild)
|
||||
// meta.removeChild(meta.firstChild);
|
||||
// meta.appendChild(number);
|
||||
})
|
||||
|
||||
// setTimeout(function() {
|
||||
// li.classList.remove('md-source__fact--hidden');
|
||||
// }, 100);
|
||||
|
||||
})
|
||||
.catch(() => {
|
||||
// console.log("parsing failed", ex)
|
||||
})
|
||||
}
|
||||
}
|
@ -21,102 +21,68 @@
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Lock {
|
||||
|
||||
/**
|
||||
* Lock body for full-screen search bar
|
||||
* Lock body for full-screen search modal
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
* @param {Function} handler - Callback to execute in active search mode
|
||||
*/
|
||||
constructor(el, handler) {
|
||||
constructor(el) {
|
||||
this.el_ = (typeof el === "string")
|
||||
? document.querySelector(el)
|
||||
: el
|
||||
|
||||
/* Initialize page y-offset and callback */
|
||||
this.offset_ = 0
|
||||
this.handler_ = handler
|
||||
|
||||
/* Dispatch update on next repaint */
|
||||
this.handler_ = ev => {
|
||||
this.update(ev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update state
|
||||
*
|
||||
* @param {Event} ev - Event
|
||||
* Setup locked state
|
||||
*/
|
||||
update(ev) {
|
||||
setup() {
|
||||
this.update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update locked state
|
||||
*/
|
||||
update() {
|
||||
|
||||
/* Entering search mode */
|
||||
if (ev.target.checked) {
|
||||
this.offset_ = window.scrollY
|
||||
if (this.el_.checked) {
|
||||
this.offset_ = window.pageYOffset
|
||||
|
||||
/* First timeout: scroll to top after transition, to omit flickering */
|
||||
/* Scroll to top after transition, to omit flickering */
|
||||
setTimeout(() => {
|
||||
window.scrollTo(0, 0)
|
||||
}, 400)
|
||||
|
||||
/* Second timeout: Lock body after finishing transition and scrolling
|
||||
to top and focus input field. Sadly, the focus event is not dispatched
|
||||
on iOS Safari and there's nothing we can do about it. */
|
||||
setTimeout(() => {
|
||||
|
||||
/* This additional check is necessary to handle fast subsequent clicks
|
||||
on the toggle and the timeout to lock the body must be cancelled */
|
||||
if (ev.target.checked) {
|
||||
document.body.dataset.mdLocked = ""
|
||||
setTimeout(this.handler_, 200)
|
||||
/* Lock body after finishing transition */
|
||||
if (this.el_.checked) {
|
||||
document.body.dataset.mdState = "lock"
|
||||
}
|
||||
}, 400)
|
||||
|
||||
/* Exiting search mode */
|
||||
} else {
|
||||
delete document.body.dataset.mdLocked
|
||||
delete document.body.dataset.mdState
|
||||
|
||||
/* Scroll to former position, but wait for 100ms to prevent flashes on
|
||||
iOS. A short timeout seems to do the trick */
|
||||
setTimeout(() => {
|
||||
if (typeof this.offset_ !== "undefined")
|
||||
window.scrollTo(0, this.offset_)
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset state
|
||||
*
|
||||
* @param {Event} ev - Event
|
||||
* Reset locked state and page y-offset
|
||||
*/
|
||||
reset() {
|
||||
delete document.body.dataset.mdLocked
|
||||
if (document.body.dataset.mdState)
|
||||
window.scrollTo(0, this.offset_)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener for all relevant events
|
||||
*/
|
||||
listen() {
|
||||
["change"].forEach(name => {
|
||||
this.el_.addEventListener(name, this.handler_, false)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listener for all relevant events
|
||||
*/
|
||||
unlisten() {
|
||||
["change"].forEach(name => {
|
||||
this.el_.removeEventListener(name, this.handler_, false)
|
||||
})
|
||||
|
||||
/* Final reset */
|
||||
this.reset()
|
||||
delete document.body.dataset.mdState
|
||||
}
|
||||
}
|
||||
|
125
src/assets/javascripts/components/Material/Search/Result.jsx
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2016 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.
|
||||
*/
|
||||
|
||||
import lunr from "lunr"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Result {
|
||||
|
||||
/**
|
||||
* Perform search and update results on keyboard events
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
* @param {(Array.<object>|Function)} data - Promise or array providing data
|
||||
*/
|
||||
constructor(el, data) {
|
||||
this.el_ = (typeof el === "string")
|
||||
? document.querySelector(el)
|
||||
: el
|
||||
|
||||
/* Set data and create metadata and list elements */
|
||||
this.data_ = data
|
||||
this.meta_ = (
|
||||
<div class="md-search-result__meta">
|
||||
Type to start searching
|
||||
</div>
|
||||
)
|
||||
this.list_ = (
|
||||
<ol class="md-search-result__list"></ol>
|
||||
)
|
||||
|
||||
/* Inject created elements */
|
||||
this.el_.appendChild(this.meta_)
|
||||
this.el_.appendChild(this.list_)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update search results
|
||||
*
|
||||
* @param {Event} ev - Input or focus event
|
||||
*/
|
||||
update(ev) {
|
||||
|
||||
/* Initialize index, if this has not be done yet */
|
||||
if (ev.type === "focus" && !this.index_) {
|
||||
|
||||
/* Initialize index */
|
||||
const init = data => {
|
||||
this.index_ = lunr(function() {
|
||||
/* eslint-disable no-invalid-this, lines-around-comment */
|
||||
this.field("title", { boost: 10 })
|
||||
this.field("text")
|
||||
this.ref("location")
|
||||
/* eslint-enable no-invalid-this, lines-around-comment */
|
||||
})
|
||||
|
||||
/* Index documents */
|
||||
this.data_ = data.reduce((docs, doc) => {
|
||||
this.index_.add(doc)
|
||||
docs[doc.location] = doc
|
||||
return docs
|
||||
}, {})
|
||||
}
|
||||
|
||||
/* Initialize index after short timeout to account for transition */
|
||||
setTimeout(() => {
|
||||
return typeof this.data_ === "function"
|
||||
? this.data_().then(init)
|
||||
: init(this.data_)
|
||||
}, 250)
|
||||
|
||||
/* Execute search on new input event after clearing current list */
|
||||
} else if (ev.type === "keyup") {
|
||||
while (this.list_.firstChild)
|
||||
this.list_.removeChild(this.list_.firstChild)
|
||||
|
||||
/* Perform search on index and render documents */
|
||||
const result = this.index_.search(ev.target.value)
|
||||
for (const item of result) {
|
||||
const doc = this.data_[item.ref]
|
||||
this.list_.appendChild(
|
||||
<li class="md-search-result__item">
|
||||
<a href={doc.location} title={doc.title}
|
||||
class="md-search-result__link">
|
||||
<article class="md-search-result__article">
|
||||
<h1 class="md-search-result__title">
|
||||
{doc.title}
|
||||
</h1>
|
||||
<p class="md-search-result__teaser">
|
||||
{doc.text}
|
||||
</p>
|
||||
</article>
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
/* Update search metadata */
|
||||
this.meta_.textContent =
|
||||
`${result.length} search result${result.length !== 1 ? "s" : ""}`
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Sidebar {
|
||||
@ -37,7 +37,7 @@ export default class Sidebar {
|
||||
? document.querySelector(el)
|
||||
: el
|
||||
|
||||
/* Index inner and outer container */
|
||||
/* Retrieve inner and outer container */
|
||||
const inner = this.el_.parentNode
|
||||
const outer = this.el_.parentNode.parentNode
|
||||
|
||||
@ -52,6 +52,13 @@ export default class Sidebar {
|
||||
this.height_ = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize sidebar state
|
||||
*/
|
||||
setup() {
|
||||
this.update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update locked state and height
|
||||
*/
|
||||
@ -71,12 +78,12 @@ export default class Sidebar {
|
||||
|
||||
/* Sidebar should be locked, as we're below parent offset */
|
||||
if (offset < this.offset_) {
|
||||
if (!this.el_.dataset.mdLocked)
|
||||
this.el_.dataset.mdLocked = ""
|
||||
if (this.el_.dataset.mdState !== "lock")
|
||||
this.el_.dataset.mdState = "lock"
|
||||
|
||||
/* Sidebar should be unlocked, if locked */
|
||||
} else if (typeof this.el_.dataset.mdLocked === "string") {
|
||||
delete this.el_.dataset.mdLocked
|
||||
} else if (this.el_.dataset.mdState === "lock") {
|
||||
delete this.el_.dataset.mdState
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +91,7 @@ export default class Sidebar {
|
||||
* Reset locked state and height
|
||||
*/
|
||||
reset() {
|
||||
delete this.el_.dataset.mdLocked
|
||||
delete this.el_.dataset.mdState
|
||||
this.el_.style.height = ""
|
||||
this.height_ = 0
|
||||
}
|
||||
|
@ -20,19 +20,14 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Adapter from "./Source/Adapter"
|
||||
import Repository from "./Source/Repository"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Module
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default
|
||||
class Abstract {
|
||||
|
||||
/**
|
||||
* Dispatch update on next repaint
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
// constructor() {
|
||||
//
|
||||
// }
|
||||
export default {
|
||||
Adapter,
|
||||
Repository
|
||||
}
|
@ -20,14 +20,12 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Toggle from "./Listener/Toggle"
|
||||
import Viewport from "./Listener/Viewport"
|
||||
import GitHub from "./Adapter/GitHub"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Module
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default {
|
||||
Toggle,
|
||||
Viewport
|
||||
GitHub
|
||||
}
|
@ -20,49 +20,71 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Cookies from "js-cookie"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Abstract {
|
||||
|
||||
/**
|
||||
* Abstract listener
|
||||
* Retrieve source information
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
* @param {Array.<string>} events - Event names to listen on
|
||||
* @param {Function} handler - Event handler to execute
|
||||
*/
|
||||
constructor(el, events, handler) {
|
||||
if (this === Abstract)
|
||||
throw new Error("Cannot construct abstract instance")
|
||||
|
||||
/* Resolve element */
|
||||
constructor(el) {
|
||||
this.el_ = (typeof el === "string")
|
||||
? document.querySelector(el)
|
||||
: el
|
||||
|
||||
/* Set event names and handler */
|
||||
this.events_ = events
|
||||
this.handler_ = handler
|
||||
/* Retrieve base URL */
|
||||
this.base_ = this.el_.href
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener for all relevant events
|
||||
* Retrieve data from Cookie or fetch from respective API
|
||||
*
|
||||
* @return {Promise} Promise that returns an array of facts
|
||||
*/
|
||||
listen() {
|
||||
this.events_.forEach(name => {
|
||||
this.el_.addEventListener(name, this.handler_, false)
|
||||
fetch() {
|
||||
return new Promise(resolve => {
|
||||
const cached = Cookies.getJSON(".cache-source")
|
||||
if (typeof cached !== "undefined") {
|
||||
resolve(cached)
|
||||
|
||||
/* If the data is not cached in a cookie, invoke fetch */
|
||||
} else {
|
||||
this.fetch_().then(data => {
|
||||
Cookies.set(".cache-source", data)
|
||||
resolve(data)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listener for all relevant events
|
||||
* Abstract private function that fetches relevant repository information
|
||||
*
|
||||
* @abstract
|
||||
* @return {Promise} Promise that provides the facts in an array
|
||||
*/
|
||||
unlisten() {
|
||||
this.events_.forEach(name => {
|
||||
this.el_.removeEventListener(name, this.handler_, false)
|
||||
})
|
||||
fetch_() {
|
||||
throw new Error("fetch_(): Not implemented")
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a number with suffix
|
||||
*
|
||||
* @param {Number} number - Number to format
|
||||
* @return {Number} Formatted number
|
||||
*/
|
||||
format_(number) {
|
||||
if (number > 10000)
|
||||
return `${(number / 1000).toFixed(0)}k`
|
||||
else if (number > 1000)
|
||||
return `${(number / 1000).toFixed(1)}k`
|
||||
return number
|
||||
}
|
||||
}
|
@ -20,21 +20,40 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Abstract from "../Abstract"
|
||||
import Abstract from "./Abstract"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Offset extends Abstract {
|
||||
export default class GitHub extends Abstract {
|
||||
|
||||
/**
|
||||
* Listener which monitors changes to the offset of the viewport
|
||||
* Retrieve source information from GitHub
|
||||
*
|
||||
* @constructor
|
||||
* @param {Function} handler - Event handler to execute
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
*/
|
||||
constructor(handler) {
|
||||
super(window, ["scroll"], handler)
|
||||
constructor(el) {
|
||||
super(el)
|
||||
|
||||
/* Adjust base URL to reach API endpoints */
|
||||
this.base_ = this.base_.replace("github.com/", "api.github.com/repos/")
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch relevant source information from GitHub
|
||||
*
|
||||
* @return {function} Promise returning an array of facts
|
||||
*/
|
||||
fetch_() {
|
||||
return fetch(this.base_)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
return [
|
||||
`${this.format_(data.stargazers_count)} Stars`,
|
||||
`${this.format_(data.forks_count)} Forks`
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
@ -20,22 +20,39 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Abstract from "./Abstract"
|
||||
import Cookies from "js-cookie"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Definition
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default class Toggle extends Abstract {
|
||||
export default class Repository {
|
||||
|
||||
/**
|
||||
* Listener which monitors state changes of a toggle
|
||||
* Render repository information
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
* @param {Function} handler - Event handler to execute
|
||||
*/
|
||||
constructor(el, handler) {
|
||||
super(el, ["click"], handler)
|
||||
constructor(el) {
|
||||
this.el_ = (typeof el === "string")
|
||||
? document.querySelector(el)
|
||||
: el
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the source repository
|
||||
*
|
||||
* @param {Array.<string>} facts - Facts to be rendered
|
||||
*/
|
||||
initialize(facts) {
|
||||
this.el_.children[0].appendChild(
|
||||
<ul class="md-source__facts">
|
||||
{facts.map(fact => <li class="md-source__fact">{fact}</li>)}
|
||||
</ul>
|
||||
)
|
||||
|
||||
/* Finish rendering with animation */
|
||||
this.el_.dataset.mdState = "done"
|
||||
}
|
||||
}
|
@ -55,7 +55,10 @@
|
||||
@import "extensions/footnotes";
|
||||
@import "extensions/permalinks";
|
||||
|
||||
@import "extensions/pymdown/arithmatex";
|
||||
@import "extensions/pymdown/critic";
|
||||
@import "extensions/pymdown/emoji";
|
||||
@import "extensions/pymdown/inlinehilite";
|
||||
@import "extensions/pymdown/tasklist";
|
||||
|
||||
@import "shame";
|
||||
|
@ -24,12 +24,9 @@
|
||||
// Rules
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Enfore correct box model - the prefixed versions are necessary for older
|
||||
// browsers, i.e. Chrome < 10, Firefox < 29, Safari < 6 and Android < 4
|
||||
// Enfore correct box model
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
|
||||
// All elements shall inherit the document default
|
||||
@ -37,8 +34,6 @@ html {
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: inherit;
|
||||
-moz-box-sizing: inherit;
|
||||
-webkit-box-sizing: inherit;
|
||||
}
|
||||
|
||||
// Prevent adjustments of font size after orientation changes in IE and iOS
|
||||
@ -51,19 +46,6 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// Add correct display property in IE < 9
|
||||
article,
|
||||
aside,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
main,
|
||||
nav,
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Reset horizontal rules in FF
|
||||
hr {
|
||||
overflow: visible;
|
||||
@ -82,7 +64,7 @@ a {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove gaps in links underline in iOS >= 8 and Safari >= 8
|
||||
// Remove gaps in underlined links in iOS >= 8 and Safari >= 8
|
||||
a {
|
||||
-webkit-text-decoration-skip: objects;
|
||||
}
|
||||
|
@ -226,9 +226,10 @@ kbd {
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
// Style scrollbar thumb
|
||||
&-thumb {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: $md-color-black--lighter;
|
||||
|
||||
// Hovered scrollbar thumb
|
||||
@ -236,7 +237,6 @@ kbd {
|
||||
background-color: $md-color-accent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset, if code is inside pre
|
||||
> code {
|
||||
|
@ -229,9 +229,10 @@ $codehilite-whitespace: transparent;
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
// Style scrollbar thumb
|
||||
&-thumb {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: $md-color-black--lighter;
|
||||
|
||||
// Hovered scrollbar thumb
|
||||
@ -239,7 +240,6 @@ $codehilite-whitespace: transparent;
|
||||
background-color: $md-color-accent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hack: set pre-tag to inline-block, in order to stetch the content on
|
||||
// overflow correctly to the whole width
|
||||
|
@ -63,7 +63,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Correct anchor offset of headlines
|
||||
// Correct anchor offset of active targets
|
||||
@each $level, $delta in (
|
||||
h1: 3.0rem,
|
||||
h2: 0.2rem,
|
||||
@ -72,7 +72,7 @@
|
||||
h5: 1.0rem,
|
||||
h6: 1.0rem
|
||||
) {
|
||||
#{$level}[id]::before {
|
||||
#{$level}[id]:target::before {
|
||||
display: block;
|
||||
margin-top: -(5.6rem + 2.4rem + $delta);
|
||||
padding-top: (5.6rem + 2.4rem + $delta);
|
||||
|
51
src/assets/stylesheets/extensions/pymdown/_arithmatex.scss
Normal file
@ -0,0 +1,51 @@
|
||||
////
|
||||
/// Copyright (c) 2016 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
|
||||
////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Rules
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Scoped in typesetted content to match specificity of regular content
|
||||
.md-typeset {
|
||||
|
||||
// MathJax integration - add padding to omit vertical scrollbar
|
||||
.MJXc-display {
|
||||
margin: 0.75em 0;
|
||||
padding: 0.25em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
// Stretch top-level containers
|
||||
> p > .MJXc-display {
|
||||
|
||||
// [mobile -]: Stretch to whole width
|
||||
@include break-to-device(mobile) {
|
||||
margin: 0.75em -1.6rem;
|
||||
padding: 0.25em 1.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove outline on tab index
|
||||
.MathJax_CHTML {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
30
src/assets/stylesheets/extensions/pymdown/_emoji.scss
Normal file
@ -0,0 +1,30 @@
|
||||
////
|
||||
/// Copyright (c) 2016 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
|
||||
////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Rules
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Correct alignment of emojis
|
||||
.emoji {
|
||||
vertical-align: text-top;
|
||||
}
|
37
src/assets/stylesheets/extensions/pymdown/_inlinehilite.scss
Normal file
@ -0,0 +1,37 @@
|
||||
////
|
||||
/// Copyright (c) 2016 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
|
||||
////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Rules
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Scoped in typesetted content to match specificity of regular content
|
||||
.md-typeset {
|
||||
|
||||
// Qualified class selector to distinguish inline code from code blocks
|
||||
code.codehilite {
|
||||
$correct: 1 / 0.85;
|
||||
|
||||
margin: 0 0.25em * $correct;
|
||||
padding: 0.0625em * $correct 0;
|
||||
}
|
||||
}
|
@ -49,10 +49,10 @@
|
||||
@extend %md-icon;
|
||||
|
||||
position: absolute;
|
||||
top: 0.15em;
|
||||
top: 0.05em;
|
||||
left: -1.25em;
|
||||
color: $md-color-black--lighter;
|
||||
font-size: 1.25em;
|
||||
font-size: 1.5em;
|
||||
content: "check_box_outline_blank";
|
||||
vertical-align: -0.25em;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ body {
|
||||
@include break-to-device(tablet portrait) {
|
||||
|
||||
// Lock body to viewport height (e.g. in search mode)
|
||||
&[data-md-locked] {
|
||||
&[data-md-state="lock"] {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
@ -117,7 +117,7 @@ hr {
|
||||
@include break-to-device(tablet) {
|
||||
|
||||
// Expanded drawer
|
||||
.md-toggle--drawer:checked ~ & {
|
||||
[data-md-toggle="drawer"]:checked ~ & {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition:
|
||||
|
@ -113,7 +113,7 @@
|
||||
}
|
||||
|
||||
// Blurred item
|
||||
&[data-md-blurred] {
|
||||
&[data-md-state="blur"] {
|
||||
color: $md-color-black--light;
|
||||
}
|
||||
|
||||
@ -334,7 +334,7 @@
|
||||
|
||||
// Animation is only possible if JavaScript is available, as the max-height
|
||||
// property must be calculated before transitioning
|
||||
&[data-md-animated] {
|
||||
&[data-md-state="animate"] {
|
||||
transition: max-height 0.25s cubic-bezier(0.86, 0.0, 0.07, 1.0);
|
||||
}
|
||||
|
||||
@ -346,7 +346,7 @@
|
||||
|
||||
// Expand nested navigation, if toggle is checked
|
||||
.md-nav__toggle:checked ~ &,
|
||||
&[data-md-expanded] {
|
||||
&[data-md-state="expand"] {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
||||
z-index: 1;
|
||||
|
||||
// Expanded overlay
|
||||
.md-toggle--search:checked ~ .md-header & {
|
||||
[data-md-toggle="search"]:checked ~ .md-header & {
|
||||
transition:
|
||||
transform 0.4s,
|
||||
opacity 0.1s;
|
||||
@ -71,7 +71,7 @@
|
||||
}
|
||||
|
||||
// Set scale factors
|
||||
.md-toggle--search:checked ~ .md-header & {
|
||||
[data-md-toggle="search"]:checked ~ .md-header & {
|
||||
|
||||
// [mobile portrait -]: Scale up 45 times
|
||||
@include break-to-device(mobile portrait) {
|
||||
@ -109,7 +109,7 @@
|
||||
z-index: 2;
|
||||
|
||||
// Active search modal
|
||||
.md-toggle--search:checked ~ .md-header & {
|
||||
[data-md-toggle="search"]:checked ~ .md-header & {
|
||||
left: 0;
|
||||
transform: translateX(0);
|
||||
transition:
|
||||
@ -144,7 +144,7 @@
|
||||
}
|
||||
|
||||
// Set maximum width
|
||||
.md-toggle--search:checked ~ .md-header & {
|
||||
[data-md-toggle="search"]:checked ~ .md-header & {
|
||||
|
||||
// [tablet landscape]: Do not overlay title
|
||||
@include break-at-device(tablet landscape) {
|
||||
@ -204,7 +204,7 @@
|
||||
}
|
||||
|
||||
// Set light background on active search field
|
||||
.md-toggle--search:checked ~ .md-header & {
|
||||
[data-md-toggle="search"]:checked ~ .md-header & {
|
||||
border-radius: 0.2rem 0.2rem 0 0;
|
||||
background: $md-color-white;
|
||||
color: $md-color-black;
|
||||
@ -269,7 +269,7 @@
|
||||
opacity: 0;
|
||||
|
||||
// Show search output in active state
|
||||
.md-toggle--search:checked ~ .md-header & {
|
||||
[data-md-toggle="search"]:checked ~ .md-header & {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@ -299,12 +299,22 @@
|
||||
box-shadow: 0 0.1rem 0 $md-color-black--lightest inset;
|
||||
overflow-y: auto;
|
||||
|
||||
// [tablet landscape]: Set absolute width to omit unnecessary reflow
|
||||
@include break-at-device(tablet landscape) {
|
||||
width: 46.8rem;
|
||||
}
|
||||
|
||||
// [screen +]: Set absolute width to omit unnecessary reflow
|
||||
@include break-from-device(screen) {
|
||||
width: 66.8rem;
|
||||
}
|
||||
|
||||
// [tablet landscape +]: Limit height to viewport
|
||||
@include break-from-device(tablet landscape) {
|
||||
max-height: 0;
|
||||
|
||||
// Expand in active state
|
||||
.md-toggle--search:checked ~ .md-header & {
|
||||
[data-md-toggle="search"]:checked ~ .md-header & {
|
||||
max-height: 75vh;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
}
|
||||
|
||||
// Lock sidebar to container height (account for fixed header)
|
||||
&[data-md-locked] {
|
||||
&[data-md-state="lock"] {
|
||||
position: fixed;
|
||||
top: 5.6rem;
|
||||
}
|
||||
@ -65,7 +65,7 @@
|
||||
}
|
||||
|
||||
// Expanded drawer
|
||||
.md-toggle--drawer:checked ~ .md-container & {
|
||||
[data-md-toggle="drawer"]:checked ~ .md-container & {
|
||||
@include z-depth(8);
|
||||
|
||||
transform: translateX(24.2rem);
|
||||
@ -93,7 +93,7 @@
|
||||
float: right;
|
||||
|
||||
// Hack: align right in case of locked sidebar
|
||||
&[data-md-locked] {
|
||||
&[data-md-state="lock"] {
|
||||
margin-left: 100%;
|
||||
transform: translate(-100%, 0);
|
||||
|
||||
|
@ -24,6 +24,40 @@
|
||||
// Rules
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Show source facts
|
||||
@keyframes md-source__facts--done {
|
||||
|
||||
0% {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
height: 1.3rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Show source fact
|
||||
@keyframes md-source__fact--done {
|
||||
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Rules
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Source container
|
||||
.md-source {
|
||||
display: block;
|
||||
@ -98,25 +132,25 @@
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
opacity: 0.75;
|
||||
overflow: auto;
|
||||
list-style-type: none;
|
||||
|
||||
// Show after the data was loaded
|
||||
[data-md-state="done"] & {
|
||||
animation: md-source__facts--done 0.25s ease-in;
|
||||
}
|
||||
}
|
||||
|
||||
// Fact
|
||||
&__fact {
|
||||
float: left;
|
||||
transform: translateY(0%);
|
||||
transition:
|
||||
transform 0.25s cubic-bezier(0.1, 0.7, 0.1, 1.0),
|
||||
opacity 0.25s;
|
||||
opacity: 1;
|
||||
|
||||
// Facts are hidden by default
|
||||
&--hidden {
|
||||
transform: translateY(100%);
|
||||
opacity: 0;
|
||||
// Show after the data was loaded
|
||||
[data-md-state="done"] & {
|
||||
animation: md-source__fact--done 0.4s ease-out;
|
||||
}
|
||||
|
||||
// Middle dots before fact
|
||||
// Middle dot before fact
|
||||
&::before {
|
||||
margin: 0 0.2rem;
|
||||
content: "\00B7";
|
||||
|
@ -79,11 +79,13 @@
|
||||
<body>
|
||||
|
||||
<!-- State toggles -->
|
||||
<input class="md-toggle md-toggle--drawer" type="checkbox" id="drawer" />
|
||||
<input class="md-toggle md-toggle--search" type="checkbox" id="search" />
|
||||
<input class="md-toggle" data-md-toggle="drawer"
|
||||
type="checkbox" id="drawer" />
|
||||
<input class="md-toggle" data-md-toggle="search"
|
||||
type="checkbox" id="search" />
|
||||
|
||||
<!-- Overlay for expanded drawer -->
|
||||
<label class="md-overlay" for="drawer"></label>
|
||||
<label class="md-overlay" data-md-overlay for="drawer"></label>
|
||||
|
||||
<!-- Application header -->
|
||||
{% include "partials/header.html" %}
|
||||
@ -170,7 +172,17 @@
|
||||
{% include "partials/footer.html" %}
|
||||
</div>
|
||||
|
||||
<!-- Theme-related and custom javascripts -->
|
||||
<!-- Extension-related JavaScript -->
|
||||
{% for extension in config.markdown_extensions %}
|
||||
|
||||
<!-- MathJax integration -->
|
||||
{% if extension == "pymdownx.arithmatex" %}
|
||||
{% set path = "mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML" %}
|
||||
<script src="https://cdn.mathjax.org/{{ path }}"></script>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<!-- Theme-related and custom JavaScript -->
|
||||
<script src="{{ base_url }}/assets/javascripts/application.js"></script>
|
||||
<script>
|
||||
|
||||
|
@ -26,11 +26,11 @@
|
||||
|
||||
<!-- Active checkbox expands items contained within nested section -->
|
||||
{% if nav_item.active %}
|
||||
<input class="md-toggle md-nav__toggle" type="checkbox"
|
||||
id="{{ path }}" checked />
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="{{ path }}"
|
||||
type="checkbox" id="{{ path }}" checked />
|
||||
{% else %}
|
||||
<input class="md-toggle md-nav__toggle" type="checkbox"
|
||||
id="{{ path }}" />
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="{{ path }}"
|
||||
type="checkbox" id="{{ path }}" />
|
||||
{% endif %}
|
||||
|
||||
<!-- Expand active pages -->
|
||||
@ -54,12 +54,13 @@
|
||||
</nav>
|
||||
</li>
|
||||
|
||||
<!-- Main navigation item with nested items -->
|
||||
<!-- Current navigation item -->
|
||||
{% elif nav_item == current_page %}
|
||||
<li class="md-nav__item">
|
||||
|
||||
<!-- Active checkbox expands items contained within nested section -->
|
||||
<input class="md-toggle md-nav__toggle" type="checkbox" id="toc" />
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc"
|
||||
type="checkbox" id="toc" />
|
||||
|
||||
<!-- Expand active pages -->
|
||||
<label class="md-nav__link md-nav__link--active" for="toc">
|
||||
|
@ -21,23 +21,18 @@
|
||||
-->
|
||||
|
||||
<!-- Search interface -->
|
||||
<div class="md-search">
|
||||
<div class="md-search" data-md-search>
|
||||
<div class="md-search__overlay"></div>
|
||||
<div class="md-search__inner">
|
||||
<form class="md-search__form">
|
||||
<input type="text" class="md-search__input"
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query"
|
||||
placeholder="Search" autocapitalize="off" autocorrect="off"
|
||||
autocomplete="off" spellcheck="false" id="query" />
|
||||
autocomplete="off" spellcheck="false" />
|
||||
<label class="md-icon md-search__icon" for="search"></label>
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
<div class="md-search__scrollwrap">
|
||||
<div class="md-search-result">
|
||||
<div class="md-search-result__meta">
|
||||
Indexing
|
||||
</div>
|
||||
<ol class="md-search-result__list"></ol>
|
||||
</div>
|
||||
<div class="md-search-result" data-md-search-result></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -26,24 +26,23 @@
|
||||
-->
|
||||
{% set platform = config.extra.repo_icon or repo_url %}
|
||||
{% if "github" in platform %}
|
||||
{% set repo_icon = "md-source--github" %}
|
||||
{% set repo_type = "github" %}
|
||||
{% set repo_icon = "md-source--github" %} <!-- TODO: remove this in favor of type -->
|
||||
{% elif "gitlab" in platform %}
|
||||
{% set repo_type = "gitlab" %}
|
||||
{% set repo_icon = "md-source--gitlab" %}
|
||||
{% elif "bitbucket" in platform %}
|
||||
{% set repo_type = "bitbucket" %}
|
||||
{% set repo_icon = "md-source--bitbucket" %}
|
||||
{% else %}
|
||||
{% set repo_type = "" %}
|
||||
{% set repo_icon = "" %}
|
||||
{% endif %}
|
||||
|
||||
<!-- Repository containing source -->
|
||||
<a href="{{ repo_url }}" title="Go to repository"
|
||||
class="md-source {{ repo_icon }}">
|
||||
class="md-source {{ repo_icon }}" data-md-source="{{ repo_type }}"> <!-- use <> for custom / private repo -->
|
||||
<div class="md-source__repository">
|
||||
{{ repo_name }}
|
||||
<ul class="md-source__facts">
|
||||
{% if config.extra.version %}
|
||||
<li class="md-source__fact">v{{ config.extra.version }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
|