Finished syntax highlighter docs and moved overrides to CSS

This commit is contained in:
squidfunk 2020-07-19 22:23:26 +02:00
parent 2fdee428ff
commit 8602969890
31 changed files with 578 additions and 1147 deletions

View File

@ -1,5 +1,6 @@
recursive-include material *.js *.css *.map *.html *.svg *.png *.yml
recursive-include material *.ttf *.woff *.woff2 LICENSE*
recursive-exclude material/assets overrides*
recursive-exclude material/overrides *
recursive-exclude site *
recursive-exclude src *

View File

@ -1,966 +0,0 @@
---
template: overrides/main.html
---
# CodeHilite
[CodeHilite][1] is an extension that adds syntax highlighting to code blocks
and is included in the standard Markdown library. It uses [Pygments][2] during
the compilation of the Markdown file to provide syntax highlighting for over
[300 languages][3] and has no JavaScript runtime dependency.
[1]: https://python-markdown.github.io/extensions/code_hilite/
[2]: https://pygments.org
[3]: http://pygments.org/languages
## Configuration
Add the following lines to `mkdocs.yml`:
``` yaml
markdown_extensions:
- codehilite
```
## Usage
### Specifying the language
The CodeHilite extension uses the same syntax as regular Markdown code blocks,
but needs to know the language of the code block. This can be done in three
different ways.
#### via Markdown syntax <small>recommended</small>
In Markdown, code blocks can be opened and closed by writing three backticks on
separate lines. To add code highlighting to those blocks, the easiest way is
to specify the language identifier directly after the opening block.
Example:
```` markdown
``` python
import tensorflow as tf
```
````
Result:
``` python
import tensorflow as tf
```
#### via Shebang
Alternatively, if the first line of a code block contains a shebang, the
language is derived from the path referenced in the shebang. This will only
work for code blocks that are indented using four spaces, not for those
encapsulated in three backticks.
Example:
```` markdown
#!/usr/bin/python
import tensorflow as tf
````
Result:
``` python
#!/usr/bin/python
import tensorflow as tf
```
#### via three colons
If the first line starts with three colons followed by a language identifier,
the first line is stripped. This will only work for code blocks that are
indented using four spaces, not for those encapsulated in three backticks.
Example:
``` markdown
:::python
import tensorflow as tf
```
Result:
:::python
import tensorflow as tf
### Adding line numbers
Line numbers can be added to a code block by enabling the `linenums` flag in
`mkdocs.yml` or adding `linenums=1` right after the language identifier:
``` yaml
markdown_extensions:
- codehilite:
linenums: true
```
Example:
```` markdown
``` python linenums="1"
""" Bubble sort """
def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
```
````
Result:
``` python linenums="1"
""" Bubble sort """
def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
```
### Grouping code blocks
The [Tabbed][4] extension which is part of the [PyMdown Extensions][5]
package adds support for grouping Markdown blocks with tabs. This is especially
useful for documenting projects with multiple language bindings.
Add the Tabbed and SuperFences extensions to `mkdocs.yml`:
``` yaml
markdown_extensions:
- codehilite
- pymdownx.tabbed
- pymdownx.superfences
```
Add your tabbed code to your markdown file. Example:
````
=== "Bash"
``` bash
#!/bin/bash
echo "Hello world!"
```
=== "C"
``` c
#include <stdio.h>
int main(void) {
printf("Hello world!\n");
return 0;
}
```
=== "C++"
``` c++
#include <iostream>
int main(void) {
std::cout << "Hello world!" << std::endl;
return 0;
}
```
=== "C#"
``` c#
using System;
class Program {
static void Main(string[] args) {
Console.WriteLine("Hello world!");
}
}
```
````
Result:
=== "Bash"
``` bash
#!/bin/bash
echo "Hello world!"
```
=== "C"
``` c
#include <stdio.h>
int main(void) {
printf("Hello world!\n");
return 0;
}
```
=== "C++"
``` c++
#include <iostream>
int main(void) {
std::cout << "Hello world!" << std::endl;
return 0;
}
```
=== "C#"
``` c#
using System;
class Program {
static void Main(string[] args) {
Console.WriteLine("Hello world!");
}
}
```
[4]: https://facelessuser.github.io/pymdown-extensions/extensions/tabbed/
[5]: https://facelessuser.github.io/pymdown-extensions
### Highlighting specific lines
Specific lines can be highlighted by passing the line numbers to the `hl_lines`
argument placed right after the language identifier. Line counts start at 1.
Example:
```` markdown
``` python hl_lines="3 4"
""" Bubble sort """
def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
```
````
Result:
``` python linenums="1" hl_lines="3 4"
""" Bubble sort """
def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
```
## Supported languages <small>excerpt</small>
CodeHilite uses [Pygments][2], a generic syntax highlighter with support for
over [300 languages][3], so the following list of examples is just an excerpt.
### Bash
``` bash
#!/bin/bash
for OPT in "$@"
do
case "$OPT" in
'-f' ) canonicalize=1 ;;
'-n' ) switchlf="-n" ;;
esac
done
# readlink -f
function __readlink_f {
target="$1"
while test -n "$target"; do
filepath="$target"
cd `dirname "$filepath"`
target=`readlink "$filepath"`
done
/bin/echo $switchlf `pwd -P`/`basename "$filepath"`
}
if [ ! "$canonicalize" ]; then
readlink $switchlf "$@"
else
for file in "$@"
do
case "$file" in
-* ) ;;
* ) __readlink_f "$file" ;;
esac
done
fi
exit $?
```
### C
``` c
extern size_t
pb_varint_scan(const uint8_t data[], size_t left) {
assert(data && left);
left = left > 10 ? 10 : left;
#ifdef __SSE2__
/* Mapping: remaining bytes ==> bitmask */
static const int mask_map[] = {
0x0000, 0x0001, 0x0003, 0x0007,
0x000F, 0x001F, 0x003F, 0x007F,
0x00FF, 0x01FF, 0x03FF
};
/* Load buffer into 128-bit integer and create high-bit mask */
__m128i temp = _mm_loadu_si128((const __m128i *)data);
__m128i high = _mm_set1_epi8(0x80);
/* Intersect and extract mask with high-bits set */
int mask = _mm_movemask_epi8(_mm_and_si128(temp, high));
mask = (mask & mask_map[left]) ^ mask_map[left];
/* Count trailing zeroes */
return mask ? __builtin_ctz(mask) + 1 : 0;
#else
/* Linear scan */
size_t size = 0;
while (data[size++] & 0x80)
if (!--left)
return 0;
return size;
#endif /* __SSE2__ */
}
```
### C++
``` cpp
Extension::
Extension(const Descriptor *descriptor, const Descriptor *scope) :
descriptor_(descriptor),
scope_(scope) {
/* Extract full name for signature */
variables_["signature"] = descriptor_->full_name();
/* Prepare message symbol */
variables_["message"] = StringReplace(
variables_["signature"], ".", "_", true);
LowerString(&(variables_["message"]));
/* Suffix scope to identifiers, if given */
string suffix ("");
if (scope_) {
suffix = scope_->full_name();
/* Check if the base and extension types are in the same package */
if (!scope_->file()->package().compare(descriptor_->file()->package()))
suffix = StripPrefixString(suffix,
scope_->file()->package() + ".");
/* Append to signature */
variables_["signature"] += ".[" + suffix +"]";
suffix = "_" + suffix;
}
/* Prepare extension symbol */
variables_["extension"] = StringReplace(
suffix, ".", "_", true);
LowerString(&(variables_["extension"]));
}
```
### C&#35;
``` csharp
public static void Send(
Socket socket, byte[] buffer, int offset, int size, int timeout) {
int startTickCount = Environment.TickCount;
int sent = 0;
do {
if (Environment.TickCount > startTickCount + timeout)
throw new Exception("Timeout.");
try {
sent += socket.Send(buffer, offset + sent,
size - sent, SocketFlags.None);
} catch (SocketException ex) {
if (ex.SocketErrorCode == SocketError.WouldBlock ||
ex.SocketErrorCode == SocketError.IOPending ||
ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable) {
/* Socket buffer is probably full, wait and try again */
Thread.Sleep(30);
} else {
throw ex;
}
}
} while (sent < size);
}
```
### Clojure
``` clojure
(clojure-version)
(defn partition-when
[f]
(fn [rf]
(let [a (java.util.ArrayList.)
fval (volatile! false)]
(fn
([] (rf))
([result]
(let [result (if (.isEmpty a)
result
(let [v (vec (.toArray a))]
;; Clear first
(.clear a)
(unreduced (rf result v))))]
(rf result)))
([result input]
(if-not (and (f input) @fval)
(do
(vreset! fval true)
(.add a input)
result)
(let [v (vec (.toArray a))]
(.clear a)
(let [ret (rf result v)]
(when-not (reduced? ret)
(.add a input))
ret))))))))
(into [] (partition-when
#(.startsWith % ">>"))
["1d" "33" ">> 1" ">> 2" "22" ">> 3"])
```
### Diff
``` diff
Index: grunt.js
===================================================================
--- grunt.js (revision 31200)
+++ grunt.js (working copy)
@@ -12,6 +12,7 @@
module.exports = function (grunt) {
+ console.log('hello world');
// Project configuration.
grunt.initConfig({
lint: {
@@ -19,10 +20,6 @@
'packages/services.web/{!(test)/**/,}*.js',
'packages/error/**/*.js'
],
- scripts: [
- 'grunt.js',
- 'db/**/*.js'
- ],
browser: [
'packages/web/server.js',
'packages/web/server/**/*.js',
```
### Docker
``` docker
FROM ubuntu
# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'
EXPOSE 5900
CMD ["x11vnc", "-forever", "-usepw", "-create"]
```
### Elixir
``` elixir
require Logger
def accept(port) do
{:ok, socket} = :gen_tcp.listen(port,
[:binary, packet: :line, active: false, reuseaddr: true])
Logger.info "Accepting connections on port #{port}"
loop_acceptor(socket)
end
defp loop_acceptor(socket) do
{:ok, client} = :gen_tcp.accept(socket)
serve(client)
loop_acceptor(socket)
end
defp serve(socket) do
socket
|> read_line()
|> write_line(socket)
serve(socket)
end
defp read_line(socket) do
{:ok, data} = :gen_tcp.recv(socket, 0)
data
end
defp write_line(line, socket) do
:gen_tcp.send(socket, line)
end
```
### Erlang
``` erlang
circular(Defs) ->
[ { { Type, Base }, Fields } ||
{ { Type, Base }, Fields } <- Defs, Type == msg, circular(Base, Defs) ].
circular(Base, Defs) ->
Fields = proplists:get_value({ msg, Base }, Defs),
circular(Defs, Fields, [Base]).
circular(_Defs, [], _Path) ->
false;
circular(Defs, [Field | Fields], Path) ->
case Field#field.type of
{ msg, Type } ->
case lists:member(Type, Path) of
false ->
Children = proplists:get_value({ msg, Type }, Defs),
case circular(Defs, Children, [Type | Path]) of
false -> circular(Defs, Fields, Path);
true -> true
end;
true ->
Type == lists:last(Path) andalso
(length(Path) == 1 orelse not is_tree(Path))
end;
_ ->
circular(Defs, Fields, Path)
end.
```
### F&#35;
``` fsharp
/// Asynchronously download retangles from the server
/// and decode the JSON format to F# Rectangle record
let [<Js>] getRectangles () : Async<Rectangle[]> = async {
let req = XMLHttpRequest()
req.Open("POST", "/get", true)
let! resp = req.AsyncSend()
return JSON.parse(resp) }
/// Repeatedly update rectangles after 0.5 sec
let [<Js>] updateLoop () = async {
while true do
do! Async.Sleep(500)
let! rects = getRectangles()
cleanRectangles()
rects |> Array.iter createRectangle }
```
### Go
``` go
package main
import "fmt"
func counter(id int, channel chan int, closer bool) {
for i := 0; i < 10000000; i++ {
fmt.Println("process", id," send", i)
channel <- 1
}
if closer { close(channel ) }
}
func main() {
channel := make(chan int)
go counter(1, channel, false)
go counter(2, channel, true)
x := 0
// receiving data from channel
for i := range channel {
fmt.Println("receiving")
x += i
}
fmt.Println(x)
}
```
### HTML
``` html
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>HTML5 Boilerplate</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<script src="js/vendor/modernizr-2.8.3.min.js"></script>
</head>
<body>
<p>Hello world! This is HTML5 Boilerplate.</p>
</body>
</html>
```
### Java
``` java
import java.util.LinkedList;
import java.lang.reflect.Array;
public class UnsortedHashSet<E> {
private static final double LOAD_FACTOR_LIMIT = 0.7;
private int size;
private LinkedList<E>[] con;
public UnsortedHashSet() {
con = (LinkedList<E>[])(new LinkedList[10]);
}
public boolean add(E obj) {
int oldSize = size;
int index = Math.abs(obj.hashCode()) % con.length;
if (con[index] == null)
con[index] = new LinkedList<E>();
if (!con[index].contains(obj)) {
con[index].add(obj);
size++;
}
if (1.0 * size / con.length > LOAD_FACTOR_LIMIT)
resize();
return oldSize != size;
}
private void resize() {
UnsortedHashSet<E> temp = new UnsortedHashSet<E>();
temp.con = (LinkedList<E>[])(new LinkedList[con.length * 2 + 1]);
for (int i = 0; i < con.length; i++) {
if (con[i] != null)
for (E e : con[i])
temp.add(e);
}
con = temp.con;
}
public int size() {
return size;
}
}
```
### JavaScript
``` javascript
var Math = require('lib/math');
var _extends = function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
target[key] = source[key];
}
}
return target;
};
var e = exports.e = 2.71828182846;
exports['default'] = function (x) {
return Math.exp(x);
};
module.exports = _extends(exports['default'], exports);
```
### JSON
``` json
{
"name": "mkdocs-material",
"version": "0.2.4",
"description": "A Material Design theme for MkDocs",
"homepage": "http://squidfunk.github.io/mkdocs-material/",
"authors": [
"squidfunk <martin.donath@squidfunk.com>"
],
"license": "MIT",
"main": "Gulpfile.js",
"scripts": {
"start": "./node_modules/.bin/gulp watch --mkdocs",
"build": "./node_modules/.bin/gulp build --production"
}
...
}
```
### Julia
``` julia
using MXNet
mlp = @mx.chain mx.Variable(:data) =>
mx.FullyConnected(name=:fc1, num_hidden=128) =>
mx.Activation(name=:relu1, act_type=:relu) =>
mx.FullyConnected(name=:fc2, num_hidden=64) =>
mx.Activation(name=:relu2, act_type=:relu) =>
mx.FullyConnected(name=:fc3, num_hidden=10) =>
mx.SoftmaxOutput(name=:softmax)
# data provider
batch_size = 100
include(Pkg.dir("MXNet", "examples", "mnist", "mnist-data.jl"))
train_provider, eval_provider = get_mnist_providers(batch_size)
# setup model
model = mx.FeedForward(mlp, context=mx.cpu())
# optimization algorithm
optimizer = mx.SGD(lr=0.1, momentum=0.9)
# fit parameters
mx.fit(model, optimizer, train_provider, n_epoch=20, eval_data=eval_provider)
```
### Lua
``` lua
local ffi = require("ffi")
ffi.cdef[[
void Sleep(int ms);
int poll(struct pollfd *fds, unsigned long nfds, int timeout);
]]
local sleep
if ffi.os == "Windows" then
function sleep(s)
ffi.C.Sleep(s*1000)
end
else
function sleep(s)
ffi.C.poll(nil, 0, s * 1000)
end
end
for i = 1,160 do
io.write("."); io.flush()
sleep(0.01)
end
io.write("\n")
```
### MySQL
``` mysql
SELECT
Employees.EmployeeID,
Employees.Name,
Employees.Salary,
Manager.Name AS Manager
FROM
Employees
LEFT JOIN
Employees AS Manager
ON
Employees.ManagerID = Manager.EmployeeID
WHERE
Employees.EmployeeID = '087652';
```
### PHP
``` php
<?php
// src/AppBundle/Controller/LuckyController.php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
class LuckyController {
/**
* @Route("/lucky/number")
*/
public function numberAction() {
$number = mt_rand(0, 100);
return new Response(
'<html><body>Lucky number: '.$number.'</body></html>'
);
}
}
```
### Protocol Buffers
``` proto
syntax = "proto2";
package caffe;
// Specifies the shape (dimensions) of a Blob.
message BlobShape {
repeated int64 dim = 1 [packed = true];
}
message BlobProto {
optional BlobShape shape = 7;
repeated float data = 5 [packed = true];
repeated float diff = 6 [packed = true];
// 4D dimensions -- deprecated. Use "shape" instead.
optional int32 num = 1 [default = 0];
optional int32 channels = 2 [default = 0];
optional int32 height = 3 [default = 0];
optional int32 width = 4 [default = 0];
}
```
### Python
``` python
"""
A very simple MNIST classifier.
See extensive documentation at
http://tensorflow.org/tutorials/mnist/beginners/index.md
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# Import data
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('data_dir', '/tmp/data/', 'Directory for storing data')
mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
sess = tf.InteractiveSession()
# Create the model
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b)
```
### Ruby
``` ruby
require 'finity/event'
require 'finity/machine'
require 'finity/state'
require 'finity/transition'
require 'finity/version'
module Finity
class InvalidCallback < StandardError; end
class MissingCallback < StandardError; end
class InvalidState < StandardError; end
# Class methods to be injected into the including class upon inclusion.
module ClassMethods
# Instantiate a new state machine for the including class by accepting a
# block with state and event (and subsequent transition) definitions.
def finity options = {}, &block
@finity ||= Machine.new self, options, &block
end
# Return the names of all registered states.
def states
@finity.states.map { |name, _| name }
end
# Return the names of all registered events.
def events
@finity.events.map { |name, _| name }
end
end
# Inject methods into the including class upon inclusion.
def self.included base
base.extend ClassMethods
end
end
```
### Scala
```scala
// Every record of this DataFrame contains the label and
// features represented by a vector.
val df = sqlContext.createDataFrame(data).toDF("label", "features")
// Set parameters for the algorithm.
// Here, we limit the number of iterations to 10.
val lr = new LogisticRegression().setMaxIter(10)
// Fit the model to the data.
val model = lr.fit(df)
// Inspect the model: get the feature weights.
val weights = model.weights
// Given a dataset, predict each point's label, and show the results.
model.transform(df).show()g
```
### XML
``` xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mainTag SYSTEM "some.dtd" [ENTITY % entity]>
<?oxygen RNGSchema="some.rng" type="xml"?>
<xs:main-Tag xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This is a sample comment -->
<childTag attribute="Quoted Value" another-attribute='Single quoted value'
a-third-attribute='123'>
<withTextContent>Some text content</withTextContent>
<withEntityContent>Some text content with &lt;entities&gt; and
mentioning uint8_t and int32_t</withEntityContent>
<otherTag attribute='Single quoted Value'/>
</childTag>
<![CDATA[ some CData ]]>
</main-Tag>
```

View File

@ -0,0 +1,34 @@
---
template: overrides/main.html
---
# Adding a git repository
- link edit button
- link related source file (via metadata)
## Configuration
To include a link to the repository of your project within your documentation,
set the following variables via your project's `mkdocs.yml`:
``` yaml
repo_name: squidfunk/mkdocs-material
repo_url: https://github.com/squidfunk/mkdocs-material
```
The name of the repository will be rendered next to the search bar on big
screens and as part of the main navigation drawer on smaller screen sizes.
Additionally, for GitHub and GitLab, the number of stars and forks is shown.
Note that the repository icon can be explicitly set through `theme.icon.repo`.
!!! question "Why is there an edit button at the top of every article?"
If the `repo_url` is set to a GitHub or BitBucket repository, and the
`repo_name` is set to *GitHub* or *BitBucket* (implied by default), an
edit button will appear at the top of every article. This is the automatic
behavior that MkDocs implements. See the [MkDocs documentation][20] on more
guidance regarding the `edit_uri` attribute, which defines whether the edit
button is shown or not.
[20]: https://www.mkdocs.org/user-guide/configuration/#edit_uri

View File

@ -31,23 +31,10 @@ theme:
:material-cursor-default-click-outline: click on a tile to change the color
scheme:
<style>
.md-typeset button[data-md-color-scheme] {
cursor: pointer;
transition: opacity 250ms;
}
.md-typeset button[data-md-color-scheme]:hover {
opacity: 0.75;
}
.md-typeset button[data-md-color-scheme] > code {
display: block;
color: var(--md-primary-bg-color);
background-color: var(--md-primary-fg-color);
}
</style>
<button data-md-color-scheme="default"><code>default</code></button>
<button data-md-color-scheme="slate"><code>slate</code></button>
<div class="tx-switch">
<button data-md-color-scheme="default"><code>default</code></button>
<button data-md-color-scheme="slate"><code>slate</code></button>
</div>
<script>
var buttons = document.querySelectorAll("button[data-md-color-scheme]")
@ -90,42 +77,29 @@ theme:
:material-cursor-default-click-outline: click on a tile to change the primary
color:
<style>
.md-typeset button[data-md-color-primary] {
cursor: pointer;
transition: opacity 250ms;
}
.md-typeset button[data-md-color-primary]:hover {
opacity: 0.75;
}
.md-typeset button[data-md-color-primary] > code {
display: block;
color: var(--md-primary-bg-color);
background-color: var(--md-primary-fg-color);
}
</style>
<button data-md-color-primary="red"><code>red</code></button>
<button data-md-color-primary="pink"><code>pink</code></button>
<button data-md-color-primary="purple"><code>purple</code></button>
<button data-md-color-primary="deep-purple"><code>deep purple</code></button>
<button data-md-color-primary="indigo"><code>indigo</code></button>
<button data-md-color-primary="blue"><code>blue</code></button>
<button data-md-color-primary="light-blue"><code>light blue</code></button>
<button data-md-color-primary="cyan"><code>cyan</code></button>
<button data-md-color-primary="teal"><code>teal</code></button>
<button data-md-color-primary="green"><code>green</code></button>
<button data-md-color-primary="light-green"><code>light green</code></button>
<button data-md-color-primary="lime"><code>lime</code></button>
<button data-md-color-primary="yellow"><code>yellow</code></button>
<button data-md-color-primary="amber"><code>amber</code></button>
<button data-md-color-primary="orange"><code>orange</code></button>
<button data-md-color-primary="deep-orange"><code>deep orange</code></button>
<button data-md-color-primary="brown"><code>brown</code></button>
<button data-md-color-primary="grey"><code>grey</code></button>
<button data-md-color-primary="blue-grey"><code>blue grey</code></button>
<button data-md-color-primary="black"><code>black</code></button>
<button data-md-color-primary="white"><code>white</code></button>
<div class="tx-switch">
<button data-md-color-primary="red"><code>red</code></button>
<button data-md-color-primary="pink"><code>pink</code></button>
<button data-md-color-primary="purple"><code>purple</code></button>
<button data-md-color-primary="deep-purple"><code>deep purple</code></button>
<button data-md-color-primary="indigo"><code>indigo</code></button>
<button data-md-color-primary="blue"><code>blue</code></button>
<button data-md-color-primary="light-blue"><code>light blue</code></button>
<button data-md-color-primary="cyan"><code>cyan</code></button>
<button data-md-color-primary="teal"><code>teal</code></button>
<button data-md-color-primary="green"><code>green</code></button>
<button data-md-color-primary="light-green"><code>light green</code></button>
<button data-md-color-primary="lime"><code>lime</code></button>
<button data-md-color-primary="yellow"><code>yellow</code></button>
<button data-md-color-primary="amber"><code>amber</code></button>
<button data-md-color-primary="orange"><code>orange</code></button>
<button data-md-color-primary="deep-orange"><code>deep orange</code></button>
<button data-md-color-primary="brown"><code>brown</code></button>
<button data-md-color-primary="grey"><code>grey</code></button>
<button data-md-color-primary="blue-grey"><code>blue grey</code></button>
<button data-md-color-primary="black"><code>black</code></button>
<button data-md-color-primary="white"><code>white</code></button>
</div>
<script>
var buttons = document.querySelectorAll("button[data-md-color-primary]")
@ -159,35 +133,30 @@ theme:
color:
<style>
.md-typeset button[data-md-color-accent] {
cursor: pointer;
transition: opacity 250ms;
}
.md-typeset button[data-md-color-accent]:hover {
opacity: 0.75;
}
.md-typeset button[data-md-color-accent] > code {
display: block;
background-color: var(--md-code-bg-color);
color: var(--md-accent-fg-color);
}
</style>
<button data-md-color-accent="red"><code>red</code></button>
<button data-md-color-accent="pink"><code>pink</code></button>
<button data-md-color-accent="purple"><code>purple</code></button>
<button data-md-color-accent="deep-purple"><code>deep purple</code></button>
<button data-md-color-accent="indigo"><code>indigo</code></button>
<button data-md-color-accent="blue"><code>blue</code></button>
<button data-md-color-accent="light-blue"><code>light blue</code></button>
<button data-md-color-accent="cyan"><code>cyan</code></button>
<button data-md-color-accent="teal"><code>teal</code></button>
<button data-md-color-accent="green"><code>green</code></button>
<button data-md-color-accent="light-green"><code>light green</code></button>
<button data-md-color-accent="lime"><code>lime</code></button>
<button data-md-color-accent="yellow"><code>yellow</code></button>
<button data-md-color-accent="amber"><code>amber</code></button>
<button data-md-color-accent="orange"><code>orange</code></button>
<button data-md-color-accent="deep-orange"><code>deep orange</code></button>
<div class="tx-switch">
<button data-md-color-accent="red"><code>red</code></button>
<button data-md-color-accent="pink"><code>pink</code></button>
<button data-md-color-accent="purple"><code>purple</code></button>
<button data-md-color-accent="deep-purple"><code>deep purple</code></button>
<button data-md-color-accent="indigo"><code>indigo</code></button>
<button data-md-color-accent="blue"><code>blue</code></button>
<button data-md-color-accent="light-blue"><code>light blue</code></button>
<button data-md-color-accent="cyan"><code>cyan</code></button>
<button data-md-color-accent="teal"><code>teal</code></button>
<button data-md-color-accent="green"><code>green</code></button>
<button data-md-color-accent="light-green"><code>light green</code></button>
<button data-md-color-accent="lime"><code>lime</code></button>
<button data-md-color-accent="yellow"><code>yellow</code></button>
<button data-md-color-accent="amber"><code>amber</code></button>
<button data-md-color-accent="orange"><code>orange</code></button>
<button data-md-color-accent="deep-orange"><code>deep orange</code></button>
</div>
<script>
var buttons = document.querySelectorAll("button[data-md-color-accent]")

View File

@ -77,7 +77,7 @@ extension][6] and [override the `fonts` block][7] with a `style` tag, or use an
The font can then be configured to be used as the regular or proportional font:
=== "Regular"
=== "Regular font"
``` css
body, input {
@ -85,7 +85,7 @@ The font can then be configured to be used as the regular or proportional font:
}
```
=== "Proportional"
=== "Proportional font"
``` css
pre, code, kbd {

View File

@ -35,7 +35,7 @@ The following languages are supported:
break-inside: avoid;
}
</style>
<ul class="md-language-list">
<ul class="tx-columns">
<li><code>af</code> / Afrikaans</li>
<li><code>ar</code> / Arabic</li>
<li><code>bn</code> / Bengali (Bangla)</li>
@ -88,10 +88,10 @@ The following languages are supported:
[1]: https://github.com/squidfunk/mkdocs-material/blob/master/src/partials/language/en.html
### Site search
### Site search language
[:octicons-file-code-24: Source][2] · :octicons-tools-24: Default: best match
for `theme.language`, automatically set
[:octicons-file-code-24: Source][2] · :octicons-tools-24: Default: automatically
set
Some languages, like Arabic or Japanese, need dedicated stemmers for search to
work properly. Material for MkDocs relies on [lunr-languages][3] to provide this
@ -104,8 +104,8 @@ functionality. See the [search plugin documentation][4] for more information.
### Directionality
[:octicons-file-code-24: Source][5] · :octicons-tools-24: Default: best match
for `theme.language`, automatically set
[:octicons-file-code-24: Source][5] · :octicons-tools-24: Default: automatically
set
While many languages are read `ltr` (left-to-right), Material for MkDocs also
supports `rtl` (right-to-left) directionality which is inferred from the
@ -119,23 +119,10 @@ theme:
:material-cursor-default-click-outline: click on a tile to change the
directionality:
<style>
.md-typeset button[data-md-dir] {
cursor: pointer;
transition: opacity 250ms;
}
.md-typeset button[data-md-dir]:hover {
opacity: 0.75;
}
.md-typeset button[data-md-dir] > code {
display: block;
color: var(--md-primary-bg-color);
background-color: var(--md-primary-fg-color);
}
</style>
<button data-md-dir="ltr"><code>ltr</code></button>
<button data-md-dir="rtl"><code>rtl</code></button>
<div class="tx-switch">
<button data-md-dir="ltr"><code>ltr</code></button>
<button data-md-dir="rtl"><code>rtl</code></button>
</div>
<script>
var buttons = document.querySelectorAll("button[data-md-dir]")

View File

@ -12,8 +12,9 @@ behavior of navigational elements, some of those through _feature flags_.
### Instant loading
[:octicons-file-code-24: Source][1] · :octicons-beaker-24: Experimental ·
:octicons-unlock-24: Feature flag
[:octicons-file-code-24: Source][1] ·
:octicons-unlock-24: Feature flag ·
:octicons-beaker-24: Experimental
When _instant loading_ is activated, clicks on all internal links will be
intercepted and dispatched via [XHR][2] without fully reloading the page. It
@ -62,12 +63,13 @@ sections. This is illustrated in the following example:
``` yaml
nav:
- Tab 1
- Page 1.1
- Tab 1 + Page 1.1
- Page 1.2
- Tab 2:
- Page 2.1
- Page 2.2
- Page 1.2
- Page 2.3
- Page 1.3
```
=== "Top-level sections"
@ -77,9 +79,11 @@ sections. This is illustrated in the following example:
- Tab 1:
- Page 1.1
- Page 1.2
- Page 1.3
- Tab 2:
- Page 2.1
- Page 2.2
- Page 2.3
```
Note that tabs are only shown for larger screens, so make sure that navigation
@ -93,7 +97,7 @@ used to render these pages.
[:octicons-file-code-24: Source][5] · [:octicons-workflow-24: Extension][6]
The [table of contents][7] extension, which is part of the standard Markdown
The [Table of Contents][7] extension, which is part of the standard Markdown
library, provides some options that are supported by Material for MkDocs to
customize its appearance:
@ -167,7 +171,8 @@ customize its appearance:
```
_Material for MkDocs doesn't provide official support for the other options of
this extension, so they may yield weird results. Use them at your own risk._
this extension, so they may be supported but can also yield weird results. Use
them at your own risk._
[5]: https://github.com/squidfunk/mkdocs-material/blob/master/src/partials/toc.html
[6]: https://python-markdown.github.io/extensions/toc/

View File

@ -17,7 +17,7 @@ during runtime using a JavaScript syntax highlighter.
[:octicons-file-code-24: Source][2] · [:octicons-workflow-24: Extension][3]
The [highlight][3] extension, which is part of [Python Markdown Extensions][4],
The [Highlight][3] extension, which is part of [Python Markdown Extensions][4],
integrates with Material for MkDocs and provides several options for
configuring syntax highlighting of code blocks:
@ -47,21 +47,63 @@ configuring syntax highlighting of code blocks:
??? example "Syntax highlighting with [Highlight.js][7]"
Highlight.js can be integrated by including the respective stylesheet
and JavaScript from a [CDN][8] in `mkdocs.yml`:
Highlight.js can be integrated by creating an [additional JavaScript][6]
file initializing the highlighter and including the respective
stylesheet and JavaScript from a [CDN][8] serving Highlight.js in
`mkdocs.yml`:
``` yaml
extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js
extra_css:
- https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/default.min.css
```
=== "docs/javascripts/extra.js"
Additionally, the following function must be called:
``` js
hljs.initHighlighting()
```
``` js
hljs.initHighlighting()
```
=== "mkdocs.yml"
``` yaml
extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js
- javascripts/extra.js
extra_css:
- https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/default.min.css
```
Note that Highlight.js has no affiliation with the Highlight extension.
`linenums`
: This option will add line numbers to _all_ code blocks. If you wish to add
line numbers to _some_, but not all code blocks, consult the section on
[adding line numbers][9] later in this document, which also contains some
tips on working with line numbers:
``` yaml
markdown_extensions:
- pymdownx.highlight:
linenums: true
```
`linenums_style`
: The Highlight extension provides three ways to add line numbers, all of
which are supported by Material for MkDocs. While `table` (default,
recommended) wraps a code block in a table, `inline` and `pymdownx.inline`
render line numbers as part of the line itself:
``` yaml
markdown_extensions:
- pymdownx.highlight:
linenums_style: pymdownx.inline
```
Note that `inline` will put line numbers next to the actual code, which
means that they will be included when selecting text with the cursor or
copying a code block to the clipboard. Thus, the usage of `table` or
`pymdownx.inline` is recommended.
_Material for MkDocs doesn't provide official support for the other options of
this extension, so they may be supported but can also yield weird results. Use
them at your own risk._
[2]: https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/extensions/pymdown/_highlight.scss
[3]: https://facelessuser.github.io/pymdown-extensions/extensions/highlight/
@ -70,3 +112,139 @@ configuring syntax highlighting of code blocks:
[6]: ../customization.md#additional-javascript
[7]: https://highlightjs.org/
[8]: https://cdnjs.com/libraries/highlight.js/
[9]: #adding-line-numbers
### InlineHilite
[:octicons-file-code-24: Source][2] · [:octicons-workflow-24: Extension][10]
The [InlineHilite][10] extension, which is part of [Python Markdown
Extensions][4] also integrates with Material for MkDocs and adds support for
syntax highlighting of inline code blocks. It's built on top of the
[Highlight][3] extension and can be enabled from `mkdocs.yml`:
``` yaml
markdown_extensions:
- pymdownx.inlinehilite
```
See the section on [inline code blocks][11] for usage information.
[10]: https://facelessuser.github.io/pymdown-extensions/extensions/inlinehilite/
[11]: #inline-code-blocks
## Customization
While syntax highlighting is implemented with [Pygments][1] or JavaScript,
Material for MkDocs defines the [appeareance][12] of code blocks, which can be
adjusted with [additional stylesheets][5].
[12]: https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/extensions/_codehilite.scss
## Usage
This section discusses how to use different syntax highlighting features with
[Pygments][1] the default highlighter so they don't apply when using
a JavaScript syntaxhighlighter.
### Specifying the language
Code blocks must be enclosed with two separate lines containing three backticks.
To add code highlighting to those blocks, add the language short name directly
after the opening block. See the [list of available lexers][13] to find the
short name for a given language.
_Example_:
```` markdown
``` python
import tensorflow as tf
```
````
_Result_:
``` python
import tensorflow as tf
```
[13]: https://pygments.org/docs/lexers/
### Adding line numbers
Line numbers can be added to a code block by using the `linenums="<start>"`
option directly after the short name, whereas `<start>` represents the starting
line number. A code block can start from a line number other than `1`, which
allows splitting large code blocks for readability.
_Example_:
```` markdown
``` python linenums="1"
""" Bubble sort """
def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
```
````
_Result_:
``` python linenums="1"
""" Bubble sort """
def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
```
### Highlighting specific lines
Specific lines can be highlighted by passing the line numbers to the `hl_lines`
argument placed right after the language short name. Note that line counts start
at `1`, regardless of the starting line number specified as part of `linenums`.
_Example_:
```` markdown
``` python hl_lines="3 4"
""" Bubble sort """
def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
```
````
_Result_:
``` python linenums="1" hl_lines="3 4"
""" Bubble sort """
def bubble_sort(items):
for i in range(len(items)):
for j in range(len(items) - 1 - i):
if items[j] > items[j + 1]:
items[j], items[j + 1] = items[j + 1], items[j]
```
### Inline code blocks
When [InlineHilite][14] is enabled, inline code blocks can be highlighted by
prefixing them with a shebang-like sequence, i.e. `#!`, directly followed by
the language short name.
_Example_:
```
The `#!python range()` function is used to generate a sequence of numbers.
```
_Result_:
The `#!python range()` function is used to generate a sequence of numbers.
[14]: #inlinehilite

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,12 +1,14 @@
{
"assets/javascripts/bundle.js": "assets/javascripts/bundle.2a81e305.min.js",
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.2a81e305.min.js.map",
"assets/javascripts/vendor.js": "assets/javascripts/vendor.568ba93b.min.js",
"assets/javascripts/vendor.js.map": "assets/javascripts/vendor.568ba93b.min.js.map",
"assets/javascripts/bundle.js": "assets/javascripts/bundle.b49b2592.min.js",
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.b49b2592.min.js.map",
"assets/javascripts/vendor.js": "assets/javascripts/vendor.877163d5.min.js",
"assets/javascripts/vendor.js.map": "assets/javascripts/vendor.877163d5.min.js.map",
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.a68abb33.min.js",
"assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.a68abb33.min.js.map",
"assets/stylesheets/main.css": "assets/stylesheets/main.04aed59c.min.css",
"assets/stylesheets/main.css.map": "assets/stylesheets/main.04aed59c.min.css.map",
"assets/stylesheets/palette.css": "assets/stylesheets/palette.e185632b.min.css",
"assets/stylesheets/palette.css.map": "assets/stylesheets/palette.e185632b.min.css.map"
"assets/stylesheets/main.css": "assets/stylesheets/main.d49d26fc.min.css",
"assets/stylesheets/main.css.map": "assets/stylesheets/main.d49d26fc.min.css.map",
"assets/stylesheets/overrides.css": "assets/stylesheets/overrides.0ad0ad40.min.css",
"assets/stylesheets/overrides.css.map": "assets/stylesheets/overrides.0ad0ad40.min.css.map",
"assets/stylesheets/palette.css": "assets/stylesheets/palette.87445083.min.css",
"assets/stylesheets/palette.css.map": "assets/stylesheets/palette.87445083.min.css.map"
}

View File

@ -0,0 +1,3 @@
:root{--md-admonition-icon--sponsor: url( 'data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14 20.408c-.492.308-.903.546-1.192.709-.153.086-.308.17-.463.252h-.002a.75.75 0 01-.686 0 16.709 16.709 0 01-.465-.252 31.147 31.147 0 01-4.803-3.34C3.8 15.572 1 12.331 1 8.513 1 5.052 3.829 2.5 6.736 2.5 9.03 2.5 10.881 3.726 12 5.605 13.12 3.726 14.97 2.5 17.264 2.5 20.17 2.5 23 5.052 23 8.514c0 3.818-2.801 7.06-5.389 9.262A31.146 31.146 0 0114 20.408z"/></svg>' )}.md-typeset .admonition.sponsor{border-color:#ea4aaa}.md-typeset .sponsor>.admonition-title{background-color:rgba(234,74,170,.1)}.md-typeset .sponsor>.admonition-title::before{background-color:#ea4aaa;-webkit-mask-image:var(--md-admonition-icon--sponsor);mask-image:var(--md-admonition-icon--sponsor)}.md-announce a,.md-announce a:focus,.md-announce a:hover{color:currentColor}.md-announce strong{white-space:nowrap}.md-announce .twitter{margin-left:.2em;color:#00acee}.md-typeset .tx-switch button{cursor:pointer;transition:opacity 250ms}.md-typeset .tx-switch button:hover{opacity:.75}.md-typeset .tx-switch button>code{display:block;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color)}.md-typeset .tx-columns{-moz-columns:2;columns:2}.md-typeset .tx-columns>*{-moz-column-break-inside:avoid;break-inside:avoid}
/*# sourceMappingURL=overrides.0ad0ad40.min.css.map*/

File diff suppressed because one or more lines are too long

View File

@ -41,9 +41,9 @@
{% endif %}
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.04aed59c.min.css' | url }}">
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.d49d26fc.min.css' | url }}">
{% if palette.scheme or palette.primary or palette.accent %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.e185632b.min.css' | url }}">
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.87445083.min.css' | url }}">
{% endif %}
{% if palette.primary %}
{% import "partials/palette.html" as map %}
@ -182,8 +182,8 @@
{% endblock %}
</div>
{% block scripts %}
<script src="{{ 'assets/javascripts/vendor.568ba93b.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.2a81e305.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/vendor.877163d5.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.b49b2592.min.js' | url }}"></script>
{%- set translations = {} -%}
{%- for key in [
"clipboard.copy",

View File

@ -22,9 +22,9 @@
<meta name="twitter:title" content="{{ title }}">
<meta name="twitter:description" content="{{ config.site_description }}">
<meta name="twitter:image" content="{{ image }}">
<link rel="stylesheet" href="{{ 'assets/stylesheets/overrides.0ad0ad40.min.css' | url }}">
{% endblock %}
{% block announce %}
<style>.md-announce a,.md-announce a:focus,.md-announce a:hover{color:currentColor}.md-announce strong{white-space:nowrap}.md-announce .twitter{margin-left:.2em;color:#00acee}</style>
<a href="https://twitter.com/squidfunk">
For updates follow <strong>@squidfunk</strong> on
<span class="twemoji twitter">

View File

@ -104,9 +104,7 @@ markdown_extensions:
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
- pymdownx.highlight:
use_pygments: true
# linenums_style: pymdownx-inline
- pymdownx.highlight
- pymdownx.inlinehilite
- pymdownx.keys
- pymdownx.magiclink:
@ -140,15 +138,14 @@ nav:
- Navigation: guides/navigation.md
- Syntax highlighting: guides/syntax-highlighting.md
- Adding a git repository: guides/adding-a-git-repository.md
- Adding an announcement bar: guides/adding-an-announcement-bar.md
- Adding icons and emojis: guides/adding-icons-and-emojis.md
- Adding footer links: guides/adding-footer-links.md
- Adding site analytics: guides/adding-site-analytics.md
- Adding a comment system: guides/adding-a-comment-system.md
- Adding an announcement bar: guides/adding-an-announcement-bar.md
- Adding a landing page: guides/adding-a-landing-page.md
- Extensions:
- Admonition: extensions/admonition.md
- CodeHilite: extensions/codehilite.md
- Footnotes: extensions/footnotes.md
- Metadata: extensions/metadata.md
- PyMdown: extensions/pymdown.md

View File

@ -52,7 +52,7 @@ $admonitions: (
$name: nth($names, 1);
$icon: nth($props, 1);
// Inline icon through postcss in webpack
// Inline icon through PostCSS in Webpack
--md-admonition-icon--#{$name}: svg-load("@mdi/svg/svg/#{$icon}.svg");
}
}

View File

@ -0,0 +1,41 @@
////
/// Copyright (c) 2016-2020 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
////
// ----------------------------------------------------------------------------
// Dependencies
// ----------------------------------------------------------------------------
@import "modularscale";
@import "material-color";
// ----------------------------------------------------------------------------
// Local imports
// ----------------------------------------------------------------------------
@import "utilities/break";
@import "utilities/convert";
@import "config";
@import "overrides/admonition";
@import "overrides/announce";
@import "overrides/typeset";

View File

@ -0,0 +1,83 @@
////
/// Copyright (c) 2016-2020 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
////
// ----------------------------------------------------------------------------
// Variables
// ----------------------------------------------------------------------------
///
/// Admonition flavours
///
$admonitions: (
sponsor: heart-fill-24 #EA4AAA
) !default;
// ----------------------------------------------------------------------------
// Rules: layout
// ----------------------------------------------------------------------------
// Icon definitions
:root {
@each $names, $props in $admonitions {
$name: nth($names, 1);
$icon: nth($props, 1);
// Inline icon through PostCSS in Webpack
--md-admonition-icon--#{$name}: svg-load(
"@primer/octicons/build/svg/#{$icon}.svg"
);
}
}
// ----------------------------------------------------------------------------
// Rules: flavours
// ----------------------------------------------------------------------------
@each $names, $props in $admonitions {
$name: nth($names, 1);
$tint: nth($props, 2);
// Define base class
.md-typeset .admonition.#{$name} {
border-color: $tint;
}
// Define base class
.md-typeset .#{$name} > .admonition-title {
background-color: transparentize($tint, 0.9);
// Icon
&::before {
background-color: $tint;
mask-image: var(--md-admonition-icon--#{$name});
}
}
// Define synonyms for base class
@if length($names) > 1 {
@for $n from 2 through length($names) {
.#{nth($names, $n)} {
@extend .#{$name};
}
}
}
}

View File

@ -0,0 +1,47 @@
////
/// Copyright (c) 2016-2020 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
// ----------------------------------------------------------------------------
// Announcement bar
.md-announce {
// Preserve link colors
a,
a:focus,
a:hover {
color: currentColor;
}
// Don't wrap name of blog article
strong {
white-space: nowrap;
}
// Twitter icon
.twitter {
margin-left: .2em;
color: #00ACEE;
}
}

View File

@ -0,0 +1,57 @@
////
/// Copyright (c) 2016-2020 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
// ----------------------------------------------------------------------------
// Typesetted content
.md-typeset {
// Extension: switch buttons
.tx-switch button {
cursor: pointer;
transition: opacity 250ms;
// Hovered button
&:hover {
opacity: 0.75;
}
// Code block
> code {
display: block;
color: var(--md-primary-bg-color);
background-color: var(--md-primary-fg-color);
}
}
// Two-column layout
.tx-columns {
columns: 2;
// Column
> * {
break-inside: avoid;
}
}
}

View File

@ -51,30 +51,16 @@
<meta name="twitter:title" content="{{ title }}" />
<meta name="twitter:description" content="{{ config.site_description }}" />
<meta name="twitter:image" content="{{ image }}" />
<!-- Extra stylesheets -->
<link
rel="stylesheet"
href="{{ 'assets/stylesheets/overrides.css' | url }}"
/>
{% endblock %}
<!-- Announcement bar -->
{% block announce %}
<style>
/* Preserve link color */
.md-announce a,
.md-announce a:focus,
.md-announce a:hover {
color: currentColor;
}
/* Don't wrap name of blog article */
.md-announce strong {
white-space: nowrap;
}
/* Twitter icon */
.md-announce .twitter {
margin-left: .2em;
color: #00acee;
}
</style>
<a href="https://twitter.com/squidfunk">
For updates follow <strong>@squidfunk</strong> on
<span class="twemoji twitter">

View File

@ -187,9 +187,10 @@ export default (_env: never, args: Configuration): Configuration[] => {
{
...base,
entry: {
"assets/javascripts/bundle": "src/assets/javascripts",
"assets/stylesheets/main": "src/assets/stylesheets/main.scss",
"assets/stylesheets/palette": "src/assets/stylesheets/palette.scss"
"assets/javascripts/bundle": "src/assets/javascripts",
"assets/stylesheets/main": "src/assets/stylesheets/main.scss",
"assets/stylesheets/overrides": "src/assets/stylesheets/overrides.scss",
"assets/stylesheets/palette": "src/assets/stylesheets/palette.scss"
},
output: {
path: path.resolve(__dirname, "material"),
@ -312,16 +313,21 @@ export default (_env: never, args: Configuration): Configuration[] => {
new EventHooksPlugin({
afterEmit: () => {
/* Replace asset URLs in base template */
/* Replace asset URLs in templates */
if (args.mode === "production") {
const manifest = require("./material/assets/manifest.json")
const template = toPairs<string>(manifest)
.reduce((content, [from, to]) => {
return content.replace(new RegExp(from, "g"), to)
}, fs.readFileSync("material/base.html", "utf8"))
for (const file of [
"material/base.html",
"material/overrides/main.html"
]) {
const template = toPairs<string>(manifest)
.reduce((content, [from, to]) => {
return content.replace(new RegExp(from, "g"), to)
}, fs.readFileSync(file, "utf8"))
/* Save template with replaced assets */
fs.writeFileSync("material/base.html", template, "utf8")
/* Save template with replaced assets */
fs.writeFileSync(file, template, "utf8")
}
}
}
}),