first commit
This commit is contained in:
commit
13c1ed7b2a
17
.github/workflows/docs.yml
vendored
Normal file
17
.github/workflows/docs.yml
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
name: Build and deploy GH Pages
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v3.0.0
|
||||||
|
- name: build_and_deploy
|
||||||
|
uses: shalzz/zola-deploy-action@v0.17.2
|
||||||
|
env:
|
||||||
|
PAGES_BRANCH: gh-pages
|
||||||
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.idea/
|
||||||
|
public
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Vincent Prouillet
|
||||||
|
|
||||||
|
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 NONINFRINGEMENT. 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.
|
54
README.md
Normal file
54
README.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# book
|
||||||
|
|
||||||
|
A theme based on [Gitbook](https://www.gitbook.com), to write documentation
|
||||||
|
or books.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Options](#options)
|
||||||
|
- [Numbered chapters](#numbered-chapters)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
First download this theme to your `themes` directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd themes
|
||||||
|
$ git clone https://github.com/getzola/book.git
|
||||||
|
```
|
||||||
|
and then enable it in your `config.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
theme = "book"
|
||||||
|
# Optional, if you want search
|
||||||
|
build_search_index = true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
Book will generate a book from the files you place in the `content` directory. Your book
|
||||||
|
can have two levels of hierarchy: chapters and subchapters.
|
||||||
|
|
||||||
|
Each chapter should be a `section` within the Gutenberg site and should have an `_index.md`
|
||||||
|
file that sets its `weight` front-matter variable to its chapter number. For example,
|
||||||
|
chapter 2 should have `weight = 2`. Additionally, each chapter should also set the
|
||||||
|
`sort_by = "weight"` in its front matter.
|
||||||
|
|
||||||
|
Each subchapter should be a `page` and should have its `weight` variable set to the subchapter
|
||||||
|
number. For example, subchapter 3.4 should have `weight = 4`.
|
||||||
|
|
||||||
|
Finally, you should create an `_index.md` file and set the `redirect_to` front-matter variable
|
||||||
|
to redirect to the first section of your content. For example, if your first section has the
|
||||||
|
slug `introduction`, then you would set `redirect_to = "introduction"`.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### Numbered chapters
|
||||||
|
By default, the `book` theme will number the chapters and pages in the left menu.
|
||||||
|
You can disable that by setting the `book_number_chapters` in `extra`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
book_number_chapters = false
|
||||||
|
```
|
12
config.toml
Normal file
12
config.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
base_url = "https://getzola.github.io/book/"
|
||||||
|
compile_sass = true
|
||||||
|
title = "book theme"
|
||||||
|
description = "A book theme"
|
||||||
|
build_search_index = true
|
||||||
|
|
||||||
|
[markdown]
|
||||||
|
highlight_code = true
|
||||||
|
highlight_theme = "css"
|
||||||
|
|
||||||
|
[extra]
|
||||||
|
book_number_chapters = true
|
3
content/_index.md
Normal file
3
content/_index.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
+++
|
||||||
|
redirect_to = "chapter1"
|
||||||
|
+++
|
152
content/chapter1/_index.md
Normal file
152
content/chapter1/_index.md
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
+++
|
||||||
|
title = "Introduction"
|
||||||
|
weight = 1
|
||||||
|
sort_by = "weight"
|
||||||
|
insert_anchor_links = "right"
|
||||||
|
+++
|
||||||
|
|
||||||
|
BH (Bluespec Haskell/Classic) is a language for hardware design. The
|
||||||
|
language borrows its notation, type and package system from an existing
|
||||||
|
general-purpose functional programming language called Haskell
|
||||||
|
[@haskell12] where those constructs have been well tested for over a
|
||||||
|
decade. Unlike Haskell, BH is meant solely for hardware design--- a BH
|
||||||
|
program represents a circuit. The abstract model for these circuits is a
|
||||||
|
Term Rewriting System (TRS); details about using TRSs for describing
|
||||||
|
circuits, and compiling these descriptions to real hardware, may be
|
||||||
|
found in James Hoe's thesis [@jhoe]. BH has several restrictions and
|
||||||
|
extensions relative to Haskell, arising out of this hardware focus.
|
||||||
|
|
||||||
|
|
||||||
|
This document is not meant as a tutorial on BH (separate documents exist
|
||||||
|
for that purpose). Nevertheless, this document has numerous small
|
||||||
|
examples to explicate BH notation.
|
||||||
|
|
||||||
|
|
||||||
|
## Meta notation
|
||||||
|
|
||||||
|
|
||||||
|
The grammar rules in the presentation below mostly follow the usual EBNF
|
||||||
|
(Extended BNF) structure. Grammar alternatives are separated by
|
||||||
|
"$\mid$". Items enclosed in \[ \] are optional. Items enclosed in { }
|
||||||
|
can be repeated zero or more times. The last piece of notation is used
|
||||||
|
sloppily; sometimes there must be at least one item, and also, the last
|
||||||
|
terminal inside the { } is sometimes a separator rather than terminator.
|
||||||
|
|
||||||
|
|
||||||
|
## Identifiers and the rôle of upper and lower case
|
||||||
|
|
||||||
|
|
||||||
|
An identifier in BH consists of a letter followed by zero or more
|
||||||
|
letters, digits, underscores and single quotes. Identifiers are case
|
||||||
|
sensitive: `glurph`, `gluRph` and `Glurph` are three distinct
|
||||||
|
identifiers.
|
||||||
|
|
||||||
|
|
||||||
|
The case of the first letter in an identifier is very important. If the
|
||||||
|
first letter is lower case, the identifier is a "variable identifier",
|
||||||
|
referred to in the grammar rules as a *varId*. If the first letter is
|
||||||
|
upper case, the identifier is a "constructor identifier", referred to in
|
||||||
|
the grammar rules as a *conId*.
|
||||||
|
|
||||||
|
|
||||||
|
In BH, package names (*packageId*), type names (*tycon*) and value
|
||||||
|
constructor names are all constructor identifiers. (Ordinary) variables,
|
||||||
|
field names and type variables are all variable identifiers.
|
||||||
|
|
||||||
|
|
||||||
|
A lone underscore, "` `", is treated as a special identifier--- it is
|
||||||
|
used as a "don't care" pattern or expression (more details in Sections
|
||||||
|
[5.10](fixme) and
|
||||||
|
[6.1](fixme)).
|
||||||
|
|
||||||
|
|
||||||
|
## The Standard Prelude
|
||||||
|
|
||||||
|
|
||||||
|
The Standard Prelude is a predefined package that is imported implicitly
|
||||||
|
into every BH package. It contains a number of useful predefined
|
||||||
|
entities (types, values/functions, classes, instances, etc.). It is
|
||||||
|
somewhat analogous to the combination of various ".h" files and standard
|
||||||
|
libraries in C, except that in BH no special action is needed to import
|
||||||
|
the prelude or to link it in. We will refer to the prelude periodically
|
||||||
|
in the following sections, and there are more details in appendix
|
||||||
|
[15](fixme).
|
||||||
|
|
||||||
|
|
||||||
|
## Lexical syntax/layout
|
||||||
|
|
||||||
|
|
||||||
|
In BH, there are various syntactic constructs that involve zero or more
|
||||||
|
items enclosed in braces and separated by semicolons: These braces and semicolons can be omitted
|
||||||
|
entirely if the components are laid out with proper indentation.
|
||||||
|
|
||||||
|
|
||||||
|
Suppose the parser discovers a missing open brace (e.g., after the
|
||||||
|
keywords `where`, `let`, `do` and `of`). Then, the indentation of the
|
||||||
|
next lexical element is remembered (and the missing open brace is
|
||||||
|
implicitly inserted before it). For each subsequent line, if it contains
|
||||||
|
only whitespace or is indented more, then it is treated as a
|
||||||
|
continuation of the current item. If it is indented the same amount, it
|
||||||
|
is treated as the beginning of the next item (*i.e.,* a semicolon is
|
||||||
|
inserted implicitly before the item). If it is indented less, then the
|
||||||
|
list of items is considered to be complete (*i.e.,* a closing brace is
|
||||||
|
implicitly inserted). An explicit brace is never matched against an
|
||||||
|
implicit one. Thus, while using the layout rule, if the parser
|
||||||
|
encounters an explicit open brace, then it does not resume using the
|
||||||
|
layout rule for this list of items until it has "emerged" past the
|
||||||
|
explicit corresponding closing brace (a construct nested inside this
|
||||||
|
list of items may still use the layout rule).
|
||||||
|
|
||||||
|
|
||||||
|
## Comments in BH programs
|
||||||
|
|
||||||
|
|
||||||
|
In a BH program, a *comment* is legal as whitespace, and may be
|
||||||
|
introduced in two ways. An *ordinary comment* is introduced by a lexical
|
||||||
|
token consisting of two or more consecutive dashes followed by a
|
||||||
|
non-symbol, and extends up to and including the end of the line. (See
|
||||||
|
Section
|
||||||
|
[\[sec-infix-applications\]](fixme) for the list of symbols.) Note: the
|
||||||
|
lexical token `—>` is a legal token in BH, and since it contains three
|
||||||
|
consecutive dashes followed by a symbol, it does not begin a comment.
|
||||||
|
|
||||||
|
|
||||||
|
A *nested comment* is introduced by the lexeme "`{-`" and extends until
|
||||||
|
the next matching "`-}`", possibly spanning multiple lines. A nested
|
||||||
|
comment can itself contain another nested comment; this nesting can be
|
||||||
|
repeated to any depth.
|
||||||
|
|
||||||
|
|
||||||
|
In an ordinary comment, the character sequences "`{-`" and "`-}`" have
|
||||||
|
no special significance, and, in a nested comment, a sequence of dashes
|
||||||
|
has no special significance.
|
||||||
|
|
||||||
|
|
||||||
|
## General organization of this document
|
||||||
|
|
||||||
|
|
||||||
|
A concept that is pervasive in BH is the notion of a *type*. Every value
|
||||||
|
expression in BH, even a basic value identifier, has a type, and the
|
||||||
|
compiler does extensive static type checking to rule out absurd use of
|
||||||
|
values (such as taking the square root of an IP address). Types are
|
||||||
|
discussed in section [2](fixme).
|
||||||
|
|
||||||
|
|
||||||
|
A BH program consists of one or more packages. These outermost
|
||||||
|
constructs are described in section
|
||||||
|
[3](fixme). As
|
||||||
|
explained later, a BH package is a linguistic namespace-management
|
||||||
|
mechanism and does not have any direct correlation with any hardware
|
||||||
|
module being described by the program. Hardware modules correspond to
|
||||||
|
*modules*, a particular type of value in BH.
|
||||||
|
|
||||||
|
|
||||||
|
Within each package is a collection of top-level definitions. These are
|
||||||
|
described in section [4](fixme).
|
||||||
|
|
||||||
|
|
||||||
|
Amongst the top-level definitions are *value definitions* (section
|
||||||
|
[4.7](fixme)),
|
||||||
|
which constitute the actual meat of the code. Value definitions are
|
||||||
|
built around *expressions*, which are described in section
|
||||||
|
[5](fixme).
|
103
content/chapter2/_index.md
Normal file
103
content/chapter2/_index.md
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
+++
|
||||||
|
title = "Types"
|
||||||
|
weight = 2
|
||||||
|
sort_by = "weight"
|
||||||
|
insert_anchor_links = "right"
|
||||||
|
+++
|
||||||
|
|
||||||
|
Every value expression and, in particular, every value identifier in BH
|
||||||
|
has a *type*. In some cases the programmer must supply a *type
|
||||||
|
signature* specifying this and in many cases the compiler infers it
|
||||||
|
automatically. The BH programmer should be aware of types at all times.
|
||||||
|
|
||||||
|
```
|
||||||
|
type ::= btype [ "->" type ]
|
||||||
|
btype ::= [ btype ] atype
|
||||||
|
atype ::= tycon | tyvar | ( { type , } )
|
||||||
|
tycon ::= conId
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Most type expressions have the form: *TypeConstructor* $t_1$ $\cdots$
|
||||||
|
$t_n$ where $t_1$ $\cdots$ $t_n$ are themselves type expressions, and $n
|
||||||
|
{\geq} 0$. The $t_1$ $\cdots$ $t_n$ are referred to as the *type
|
||||||
|
arguments* to the type constructor. $n$ is also called the *arity* of
|
||||||
|
the type constructor.
|
||||||
|
|
||||||
|
|
||||||
|
Familiar basic types have zero-arity type constructors (no type
|
||||||
|
arguments, $n = 0$). Examples:
|
||||||
|
|
||||||
|
- `Integer`
|
||||||
|
- `Bool`
|
||||||
|
- `String`
|
||||||
|
- `Action`
|
||||||
|
|
||||||
|
Other type constructors have arity $n > 0$; these are also known as
|
||||||
|
*parameterized types*.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- `List Bool`
|
||||||
|
- `List (List Bool)`
|
||||||
|
- `Array Integer String`
|
||||||
|
- `Maybe Integer`
|
||||||
|
|
||||||
|
These represent the types of lists of
|
||||||
|
Booleans, lists of lists of Booleans, arrays indexed by integers and
|
||||||
|
containing strings, and an optional result possibly containing an
|
||||||
|
integer.
|
||||||
|
|
||||||
|
|
||||||
|
A type can be *polymorphic*, indicated using type variables. Examples:
|
||||||
|
|
||||||
|
- `List a`
|
||||||
|
- `List (Llist b)`
|
||||||
|
- `Array i (List String)`
|
||||||
|
|
||||||
|
|
||||||
|
These represent lists of things of some unknown type "`a`", lists of
|
||||||
|
lists of things of some unknown type "`b`", and arrays indexed by some
|
||||||
|
unknown type "`i`" and containing lists of strings.
|
||||||
|
|
||||||
|
|
||||||
|
One type constructor is given special status in the syntax. The type of
|
||||||
|
functions from arguments of type $t_1$ to results of type $t_2$ could
|
||||||
|
have been written as:
|
||||||
|
|
||||||
|
Function $t_1$ $t_2$
|
||||||
|
|
||||||
|
but in BH we write the constructor as an infix arrow:
|
||||||
|
|
||||||
|
$t_1$ -\> $t_2$
|
||||||
|
|
||||||
|
These associate to the right, *i.e.,*
|
||||||
|
|
||||||
|
$t_1$ -\> $\cdots$ -\> $t_{n-1}$ -\> $t_n$ $\equiv$ $t_1$
|
||||||
|
-\> ($\cdots$ -\> ($t_{n-1}$ -\> $t_n$))
|
||||||
|
|
||||||
|
|
||||||
|
There is one particular set of niladic type constructors that look like
|
||||||
|
numbers. These are used to represent certain "sizes". For example, the
|
||||||
|
type:
|
||||||
|
|
||||||
|
`Bit 16`
|
||||||
|
|
||||||
|
consists of the unary type constructor `Bit` applied to type represented
|
||||||
|
by the niladic type constructor "`16`". The type as a whole represents
|
||||||
|
bit vectors of length 16 bits. Similarly the type
|
||||||
|
|
||||||
|
`UInt 32`
|
||||||
|
|
||||||
|
|
||||||
|
represents the type of unsigned integers that can be represented in 32
|
||||||
|
bits. These numeric types are said to have kind `#`, rather than kind
|
||||||
|
`*` for value types.
|
||||||
|
|
||||||
|
|
||||||
|
Strings can also be used as type, having kind `$`. This is less common,
|
||||||
|
but string types are quite useful in the generics library, described in
|
||||||
|
the *Libraries Reference Guide*. Examples:
|
||||||
|
|
||||||
|
- `MetaData#("Prelude","Maybe",PrimUnit,2)`
|
||||||
|
- `MetaConsNamed#("Valid",1,1)`
|
108
content/chapter2/page1.md
Normal file
108
content/chapter2/page1.md
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
+++
|
||||||
|
title = "Type classes and overloading"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
BH's `class` and `instance` mechanisms form a systematic way to do
|
||||||
|
*overloading* (the approach has been well tested in Haskell).
|
||||||
|
|
||||||
|
|
||||||
|
Overloading is a way to use a common name to refer to a set of
|
||||||
|
operations at different types. For example, we may want to use the "`<`"
|
||||||
|
operator name for the integer comparison operation, the floating-point
|
||||||
|
comparison operation, the vector comparison operation and the matrix
|
||||||
|
comparison operation. Note that this is not the same as polymorphism: a
|
||||||
|
polymorphic function is a *single* function that is meaningful at an
|
||||||
|
infinity of types (*i.e.,* at every possible instantiation of the type
|
||||||
|
variables in its type). An overloaded identifier, on the other hand,
|
||||||
|
usually uses a common name to refer to a (usually) small set of distinct
|
||||||
|
operations.
|
||||||
|
|
||||||
|
|
||||||
|
Further, it may make sense to have "`<=`", "`>`" and "`>=`" operations
|
||||||
|
wherever there is a "`<`" operation, on integers, floating points
|
||||||
|
numbers, vectors and matrices. Rather than handle these separately, we
|
||||||
|
say:
|
||||||
|
|
||||||
|
|
||||||
|
- there is class of types which we will call `Ord` (for "ordered types"),
|
||||||
|
- that the integer, floating point, vector and matrix types are members
|
||||||
|
(or "instances") of this class, and
|
||||||
|
- that all types that are members of this class have appropriate
|
||||||
|
definitions for the "`<`", "`<=`", "`>`" and "`>=`" operations. We also
|
||||||
|
say that these operations are *overloaded* across these instance types,
|
||||||
|
and we refer to these operations as the *methods* of this class.
|
||||||
|
|
||||||
|
|
||||||
|
Another example: we could use a class `Hashable` with an operation
|
||||||
|
called `hash` to represent those types $T$ for which we can and do
|
||||||
|
define a hashing function. Each such type $T$ has to specify how to
|
||||||
|
compute the `hash` function at that type.
|
||||||
|
|
||||||
|
|
||||||
|
Classes, and the membership of a type in a class, do not come into
|
||||||
|
existence by magic. Every class is created explicitly using a class
|
||||||
|
declaration, described in section
|
||||||
|
[4.5](fixme).
|
||||||
|
A type must explicitly be made an instance of a class and the
|
||||||
|
corresponding class methods have to be provided explicitly; this is
|
||||||
|
described in [4.6](fixme).
|
||||||
|
|
||||||
|
|
||||||
|
### Context-qualified types
|
||||||
|
|
||||||
|
|
||||||
|
Consider the following type declaration:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
sort :: (Ord a) => List a -> List a
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
It expresses the idea that a sorting function takes an (unsorted) input
|
||||||
|
list of items and produces a (sorted) output list of items, but it is
|
||||||
|
only meaningful for those types of items ("`a`") for which the ordering
|
||||||
|
functions (such as "`<`") are defined. Thus, it is ok to apply `sort` to
|
||||||
|
lists of `Integer`'s or lists of `Bool`'s, because those types are
|
||||||
|
instances of `Ord`, but it is not ok to apply `sort` to a list of, say,
|
||||||
|
`Counter`'s (assuming `Counter` is not an instance of the `Ord` class).
|
||||||
|
|
||||||
|
|
||||||
|
In the type of `sort` above, the part before "`=>`" is called a
|
||||||
|
*context*. A context expresses constraints on one or more type
|
||||||
|
variables--- in the above example, the constraint is that any actual
|
||||||
|
type "`a`" must be an instance of the `Ord` class.
|
||||||
|
|
||||||
|
|
||||||
|
A context-qualified type has the following grammar:
|
||||||
|
|
||||||
|
```
|
||||||
|
ctxType ::= [ context => ] type
|
||||||
|
context ::= ( {classId { varId }, })
|
||||||
|
classId ::= conId
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above example, the class `Ord` had only one type parameter
|
||||||
|
(*i.e.,* it constrains a single type) but, in general, a type class can
|
||||||
|
have multiple type parameters. For example, in BH we frequently use the
|
||||||
|
class "`Bits a n`" which constrains the type represented by `a` to be
|
||||||
|
representable in bit strings of length represented by the type `n`.
|
||||||
|
|
||||||
|
|
||||||
|
> **NOTE:**
|
||||||
|
>
|
||||||
|
> When using an overloaded identifier `x` there is always a question of
|
||||||
|
> whether or not there is enough type information available to the
|
||||||
|
> compiler to determine which of the overloaded `x`'s you mean. For
|
||||||
|
> example, if `read` is an overloaded function that takes strings to
|
||||||
|
> integers or Booleans, and `show` is an overloaded function that takes
|
||||||
|
> integers or Booleans to strings, then the expression `show (read s)` is
|
||||||
|
> ambiguous--- is the thing to be read an integer or a Boolean?
|
||||||
|
>
|
||||||
|
> In such ambiguous situations, the compiler will so notify you, and you
|
||||||
|
> may need to give it a little help by inserting an explicit type
|
||||||
|
> signature, e.g.,
|
||||||
|
>
|
||||||
|
> ```hs
|
||||||
|
> show ((read s) :: Bool)
|
||||||
|
> ```
|
82
content/chapter3/_index.md
Normal file
82
content/chapter3/_index.md
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
+++
|
||||||
|
title = "Packages"
|
||||||
|
weight = 3
|
||||||
|
sort_by = "weight"
|
||||||
|
insert_anchor_links = "right"
|
||||||
|
+++
|
||||||
|
|
||||||
|
Packages are the outermost constructs in BH--- all BH code must be
|
||||||
|
inside packages. There should be one package per file. A BH package is a
|
||||||
|
linguistic device for namespace control, and is particularly useful for
|
||||||
|
programming-in-the-large. A package does not directly correspond to
|
||||||
|
hardware modules. (Hardware modules correspond to BH modules, described
|
||||||
|
in section [5.13](fixme))
|
||||||
|
|
||||||
|
|
||||||
|
A BH package consists of the package header, import declarations, and
|
||||||
|
top level definitions. The package header indicates which names defined
|
||||||
|
in this package are exported, *i.e.,* available for import into other
|
||||||
|
packages.
|
||||||
|
|
||||||
|
```
|
||||||
|
packageDefn ::= package packageId ( exportDecl ) where {
|
||||||
|
{ importDecl ; }
|
||||||
|
{ fixityDecl ; }
|
||||||
|
{ topDefn ; }
|
||||||
|
}
|
||||||
|
exportDecl ::= varId |typeId [ conList ]
|
||||||
|
conList ::= (..)
|
||||||
|
importDecl ::= import [ qualified ] packageId
|
||||||
|
fixityDecl ::= fixity integer varId
|
||||||
|
fixity ::= infix |infixl |infixr
|
||||||
|
packageId ::= conId
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
package Foo (x, y) where
|
||||||
|
import Bar
|
||||||
|
import Glurph
|
||||||
|
|
||||||
|
-- top level definition ...
|
||||||
|
-- top level definition ...
|
||||||
|
-- top level definition ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, `Foo` is the name of this package, `x` and `y`
|
||||||
|
are names exported from this package (they will be defined amongst the
|
||||||
|
top level definitions in this package), and `Bar` and `Glurph` are the
|
||||||
|
names of package being imported (for use in this package).
|
||||||
|
|
||||||
|
|
||||||
|
The export list is a list of identifiers, each optionally followed by
|
||||||
|
`(..)`. Each identifier in the list will be visible outside the package.
|
||||||
|
If the exported identifier is the name of `data`, `struct`, or
|
||||||
|
`interface`, then the constructors or fields of the type will be visible
|
||||||
|
only if `(..)` is used. Otherwise, if you export only the name of a type
|
||||||
|
without the `(..)` suffix, the type is an abstract (opaque) data type
|
||||||
|
outside the package. The list of identifiers may include identifiers
|
||||||
|
defined in the package as well as identifiers imported from other
|
||||||
|
packages.
|
||||||
|
|
||||||
|
|
||||||
|
If the keyword `qualified` is present in the import declaration all the
|
||||||
|
imported entities from that package must be referred to by a qualified
|
||||||
|
name.
|
||||||
|
|
||||||
|
|
||||||
|
The fixity declaration can be used to give a precedence level to a
|
||||||
|
user-defined infix operator. The `infixl` specifies a left associative
|
||||||
|
operator, `infixr` a right associative operator, and `infix` a
|
||||||
|
non-associative operator.
|
||||||
|
|
||||||
|
|
||||||
|
## Name clashes and qualified names
|
||||||
|
|
||||||
|
|
||||||
|
When used in any scope, a name must have an unambiguous meaning. If
|
||||||
|
there is name clash for a name $x$ because it is defined in the current
|
||||||
|
package and/or it is available from one or more imported packages, then
|
||||||
|
the ambiguity can be resolved by using a qualified name of the form
|
||||||
|
$M.x$ to refer to the version of $x$ contained in package $M$.
|
12
content/chapter4/_index.md
Normal file
12
content/chapter4/_index.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
+++
|
||||||
|
title = "Top Level Definitions"
|
||||||
|
weight = 4
|
||||||
|
sort_by = "weight"
|
||||||
|
insert_anchor_links = "right"
|
||||||
|
+++
|
||||||
|
|
||||||
|
# Top level definitions
|
||||||
|
|
||||||
|
|
||||||
|
Top level definitions can be used only on the top level within a
|
||||||
|
package.
|
146
content/chapter4/page1.md
Normal file
146
content/chapter4/page1.md
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
+++
|
||||||
|
title = "`data`"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
A `data` definition defines a brand new type, which is different from
|
||||||
|
every primitive type and every other type defined using a `data`
|
||||||
|
definition, even if they look structurally similar. The new type defined
|
||||||
|
by a `data` definition is a "sum of products", or a "union of products".
|
||||||
|
|
||||||
|
```
|
||||||
|
topDefn ::= data typeId {tyVarId } = {summand | }[ derive ]
|
||||||
|
summand ::= conId {type }
|
||||||
|
summand ::= conId { { fieldDef ; }}
|
||||||
|
derive ::= deriving ( { classId , })
|
||||||
|
fieldDef ::= fieldId :: type
|
||||||
|
```
|
||||||
|
|
||||||
|
The *typeId* is the name of this new type. If the *tyVarId*'s exist,
|
||||||
|
they are type parameters, thereby making this new type polymorphic. In
|
||||||
|
each *summand*, the *conId* is called a "constructor". You can think of
|
||||||
|
them as unique *tag*'s that identify each summand. Each *conId* is
|
||||||
|
followed by a specification for the fields involved in that summand
|
||||||
|
(*i.e.,* the fields are the "product" within the summand). In the first
|
||||||
|
way of specifying a summand, the fields are just identified by position,
|
||||||
|
hence we only specify the types of the fields. In the second way of
|
||||||
|
specifying a summand, the fields are named, hence we specify the field
|
||||||
|
names (*fieldId*'s) and their types.
|
||||||
|
|
||||||
|
|
||||||
|
The same constructor name may occur in more than one type. The same
|
||||||
|
field name can occur in more than one type. The same field name can
|
||||||
|
occur in more than one summand within the same type, but the type of the
|
||||||
|
field must be the same in each summand.
|
||||||
|
|
||||||
|
|
||||||
|
The optional *derive* clause is used as a shorthand to make this new
|
||||||
|
type an instance of the *classId*'s, instead of using a separate,
|
||||||
|
full-blown `instance` declaration. This can only be done for certain
|
||||||
|
predefined *classId*'s: `Bits`, `Eq`, and `Bounded`. The compiler
|
||||||
|
automatically derives the operations corresponding to those classes
|
||||||
|
(such as `pack` and `unpack` for the `Bits` class). Type classes,
|
||||||
|
instances, and `deriving` are described in more detail in sections
|
||||||
|
[2.1](fixme), [4.5](fixme) and [
|
||||||
|
4.6](fixme).
|
||||||
|
|
||||||
|
To construct a value corresponding to some `data` definition $T$, one
|
||||||
|
simply applies the constructor to the appropriate number of arguments
|
||||||
|
(see section [5.3](fixme){reference-type="ref"
|
||||||
|
reference="sec-exprs-constrs"}); the values of those arguments become
|
||||||
|
the components/fields of the data structure.
|
||||||
|
|
||||||
|
|
||||||
|
To extract a component/field from such a value, one uses pattern
|
||||||
|
matching (see section [6](fixme){reference-type="ref"
|
||||||
|
reference="sec-patterns"}).
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data Bool = False | True
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
This is a "trivial" case of a `data` definition. The type is not
|
||||||
|
polymorphic (no type parameters); there are two summands with
|
||||||
|
constructors `False` and `True`, and neither constructor has any fields.
|
||||||
|
It is a 2-way sum of empty products. A value of type `Bool` is either
|
||||||
|
the value `False` or the value `True` Definitions like these correspond
|
||||||
|
to an "enum" definition in C.
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data Operand = Register (Bit 5)
|
||||||
|
| Literal (Bit 22)
|
||||||
|
| Indexed (Bit 5) (Bit 5)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Here, the first two summands have one field each; the third has two
|
||||||
|
fields. The fields are positional (no field names). The field of a
|
||||||
|
`Register` value must have type Bit 5. A value of type `Operand` is
|
||||||
|
either a `Register` containing a 5-bit value, or a `Literal` containing
|
||||||
|
a 22-bit value, or an `Indexed` containing two 5-bit values.
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data Maybe a = Nothing | Just a
|
||||||
|
deriving (Eq, Bits)
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a very useful and commonly used type. Consider a function that,
|
||||||
|
given a key, looks up a table and returns some value associated with
|
||||||
|
that key. Such a function can return either `Nothing`, if the table does
|
||||||
|
not contain an entry for the given key, of `Just `$v$, if the table
|
||||||
|
contains $v$ associated with the key. The type is polymorphic (type
|
||||||
|
parameter "`a`") because it may be used with lookup functions for
|
||||||
|
integer tables, string tables, IP address tables, etc., *i.e.,* we do
|
||||||
|
not want here to over-specify the type of the value $v$ at which it may
|
||||||
|
be used.
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data Instruction = Immediate { op::Op; rs::Reg; rt::CPUReg; imm::UInt16; }
|
||||||
|
| Jump { op::Op; target::UInt26; }
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
An `Instruction` is either an `Immediate` or a `Jump`. In the former
|
||||||
|
case, it contains a field called `op` containing a value of type `Op`, a
|
||||||
|
field called `rs` containing a value of type `Reg`, a field called `rt`
|
||||||
|
containing a value of type `CPUReg`, and a field called `imm` containing
|
||||||
|
a value of type `UInt16`. In the latter case, it contains a field called
|
||||||
|
`op` containing a value of type `Op`, and a field called `target`
|
||||||
|
containing a value of type `UInt26`.
|
||||||
|
|
||||||
|
> **NOTE:**
|
||||||
|
>
|
||||||
|
> Error messages involving data type definitions sometimes show traces of
|
||||||
|
> how they are handled internally. Data type definitions are translated
|
||||||
|
> into a data type where each constructor has exactly one argument. The
|
||||||
|
> types above translate to:
|
||||||
|
>
|
||||||
|
> ```hs
|
||||||
|
> data Bool = False PrimUnit | True PrimUnit
|
||||||
|
>
|
||||||
|
> data Operand = Register (Bit 5)
|
||||||
|
> | Literal (Bit 22)
|
||||||
|
> | Indexed Operand_$Indexed
|
||||||
|
> struct Operand_$Indexed = { _1 :: Reg 5; _2 :: Reg 5 }
|
||||||
|
>
|
||||||
|
> data Maybe a = Nothing PrimUnit | Just a
|
||||||
|
>
|
||||||
|
> data Instruction = Immediate Instruction_$Immediate
|
||||||
|
> | Register Instruction_$Register
|
||||||
|
>
|
||||||
|
> struct Instruction_$Immediate = { op::Op; rs::Reg; rt::CPUReg; imm::UInt16; }
|
||||||
|
> struct Instruction_$Register = { op::Op; target::UInt26; }
|
||||||
|
> ```
|
68
content/chapter4/page2.md
Normal file
68
content/chapter4/page2.md
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
+++
|
||||||
|
title = "`struct`"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
Defines a record type (a "pure product"). This is a specialized form of
|
||||||
|
a `data` definition. The same field name may occur in more than one
|
||||||
|
type.
|
||||||
|
|
||||||
|
```
|
||||||
|
topDefn ::= struct typeId {tyVarId }= { { fieldDef ; }} [ derive ]
|
||||||
|
fieldDef ::= fieldId :: type
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct Proc = { pc :: Addr; rf :: RegFile; mem :: Memory }
|
||||||
|
struct Coord = { x :: Int; y :: Int }
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Section [5.6](fixme) describes how to construct values of a
|
||||||
|
`struct` type. A field of a `struct` type can be extracted either
|
||||||
|
directly using "dot" notation (section
|
||||||
|
[5.7](fixme)) or using pattern matching (section
|
||||||
|
[6.3](fixme)).
|
||||||
|
|
||||||
|
|
||||||
|
### Tuples {#sec-tuple-type}
|
||||||
|
|
||||||
|
|
||||||
|
One way to group multiple values together is to use a `data` definition
|
||||||
|
in which a constructor has multiple fields.
|
||||||
|
|
||||||
|
|
||||||
|
However, there is a built-in notation for a common form of grouping,
|
||||||
|
called "tuples". To group two (or more) values together the Prelude
|
||||||
|
contains a type, `PrimPair`, for which there is syntactic sugar for type
|
||||||
|
expressions, value expressions, and patterns.
|
||||||
|
|
||||||
|
The type has the following definition
|
||||||
|
|
||||||
|
```hs
|
||||||
|
struct PrimPair a b = { fst :: a; snd :: b } deriving (Eq, Bits, Bounded)
|
||||||
|
```
|
||||||
|
|
||||||
|
For type expressions the following shorthand can be used:
|
||||||
|
|
||||||
|
(a, b) $\equiv$ PrimPair a b
|
||||||
|
|
||||||
|
Or, more generally,
|
||||||
|
|
||||||
|
($t_1$, $t_2$, $\cdots$, $t_n$) $\equiv$ PrimPair $t_1$ (PrimPair $t_2$ ($\cdots$ $t_n$))
|
||||||
|
|
||||||
|
|
||||||
|
There is a corresponding shorthand for value expressions and patterns:
|
||||||
|
|
||||||
|
(a, b) $\equiv$ PrimPair { fst = a; snd = b }
|
||||||
|
|
||||||
|
There is also special syntax for the empty tuple. It is written "`()`"
|
||||||
|
for types, expressions, and patterns. The real type has the following
|
||||||
|
definition
|
||||||
|
|
||||||
|
```hs
|
||||||
|
struct PrimUnit = { } deriving (Eq, Bits, Bounded)
|
||||||
|
```
|
||||||
|
|
38
content/chapter4/page3.md
Normal file
38
content/chapter4/page3.md
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
+++
|
||||||
|
title = "`type`"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
Defines a type synonym. These are used purely for readability, *i.e.,* a
|
||||||
|
type synonym can always be "expanded out" to its definition at any time.
|
||||||
|
|
||||||
|
```
|
||||||
|
topDefn ::= type typeId {tyVarId }= type
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
type Byte = Bit 8
|
||||||
|
type Word = Bit 16
|
||||||
|
type LongWord = Bit 32
|
||||||
|
```
|
||||||
|
|
||||||
|
These provide commonly used names for certain bit lengths. In a
|
||||||
|
specification of a processor:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data RegName = R0 | R1 | ... | R31
|
||||||
|
type Rdest = RegName
|
||||||
|
type Rsrc = RegName
|
||||||
|
data ArithInstr = Add Rdest Rsrc Rsrc
|
||||||
|
| Sub Rdest Rsrc Rsrc
|
||||||
|
```
|
||||||
|
|
||||||
|
the last two lines suggest the roles of the registers in the
|
||||||
|
instructions, and is more readable than:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data ArithInstr = Add RegName RegName RegName
|
||||||
|
| Sub RegName RegName RegName
|
||||||
|
```
|
43
content/chapter4/page4.md
Normal file
43
content/chapter4/page4.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
+++
|
||||||
|
title = "`interface`"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
Defines an interface for a hardware module (see section
|
||||||
|
[5.13](fixme)). An
|
||||||
|
interface is essentially a `struct`, but its components are restricted
|
||||||
|
to those things that have a physical interpretation as wires in and out
|
||||||
|
of a circuit. The types of fields in an interface are more likely to
|
||||||
|
involve `Action`'s (see section
|
||||||
|
[5.11](fixme)),
|
||||||
|
which are typically interpreted as "enable signals" into a circuit. The
|
||||||
|
fields of an interface are also known as *methods* (not to be confused
|
||||||
|
with methods of a class, described in Sections
|
||||||
|
[2.1](fixme) and
|
||||||
|
[4.5](fixme)).
|
||||||
|
|
||||||
|
```
|
||||||
|
topDefn ::= interface typeId {tyVarId }= { { fieldDef ; }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
interface Stack a =
|
||||||
|
push :: a -> Action
|
||||||
|
pop :: Action
|
||||||
|
top :: Maybe a
|
||||||
|
```
|
||||||
|
|
||||||
|
This describes a circuit that implements a stack (a LIFO) of items. This
|
||||||
|
polymorphic definition does not specify the type of the contents of the
|
||||||
|
stack, just that they have some type "`a`". Corresponding to the `push`
|
||||||
|
method, the circuit will have input wires to carry a value of type
|
||||||
|
"`a`", and a "push-enable" input wire that specifies when the value
|
||||||
|
present on the input wires should be pushed on the stack. Corresponding
|
||||||
|
to the `pop` component, the circuit will have a "pop-enable" input wire
|
||||||
|
that specifies when a value should be popped off the stack.
|
||||||
|
Corresponding to the `top` component, the circuit will have a set of
|
||||||
|
output wires: if the stack is empty, the wires will represent the value
|
||||||
|
`Nothing`, and if the stack is non-empty and $v$ is the value at the top
|
||||||
|
of the stack, the wires will represent `Maybe` $v$.
|
86
content/chapter4/page5.md
Normal file
86
content/chapter4/page5.md
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
+++
|
||||||
|
title = "`class` declarations"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
The general concepts behind classes, instances, overloading etc. were
|
||||||
|
introduced in section [2.1](fixme). A new class is declared using the
|
||||||
|
following:
|
||||||
|
|
||||||
|
```
|
||||||
|
topDefn ::= class [ context => ] classId {tyVarId }[ | funDep ] where {
|
||||||
|
{varId :: ctxType ; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
*classId* is the newly declared class. It can be polymorphic, if
|
||||||
|
*tyVarId*'s exist; these are called the *parameters* of the type class.
|
||||||
|
The *tyVarId*'s may themselves be constrained by *context*, in which
|
||||||
|
case the classes named in *context* are called the "super-classes" of
|
||||||
|
this class. The "*varId*`::`*ctxType*" list declares the class method
|
||||||
|
names and their types.
|
||||||
|
|
||||||
|
Example (from the Prelude):
|
||||||
|
|
||||||
|
```hs
|
||||||
|
class Literal a where
|
||||||
|
fromInteger :: Integer -> a
|
||||||
|
```
|
||||||
|
|
||||||
|
This defines the class `Literal`. It says that any type `a` in this
|
||||||
|
class must have a method (a function) called `fromInteger` that converts
|
||||||
|
an `Integer` value into the type `a`. In fact, this is the mechanism the
|
||||||
|
BH uses to interpret literal constants, e.g., to resolve whether a
|
||||||
|
literal like `6`847 is to be interpreted as a signed integer, an
|
||||||
|
unsigned integer, a floating point number, a bit value of 10 bits, a bit
|
||||||
|
value of 8 bits, etc. (This is described in more detail in Section
|
||||||
|
[5.3](fixme).)
|
||||||
|
|
||||||
|
|
||||||
|
Example (from the Prelude):
|
||||||
|
|
||||||
|
```hs
|
||||||
|
class (Literal a) => Arith a where
|
||||||
|
(+) :: a -> a -> a
|
||||||
|
(-) :: a -> a -> a
|
||||||
|
negate :: a -> a
|
||||||
|
(*) :: a -> a -> a
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
This defines the class `Arith` with super-class `Literal`. It says that
|
||||||
|
for any type `a` that is a member of the class `Arith`, it must also be
|
||||||
|
a member of the class `Literal`, and it must have four methods with the
|
||||||
|
given names and types. Said another way, an `Arith` type must have a way
|
||||||
|
to convert integer literals into that type, and it must have addition,
|
||||||
|
subtraction, negation and multiplication defined on it.
|
||||||
|
|
||||||
|
|
||||||
|
The optional *funDep* section specifies *functional dependencies*
|
||||||
|
between the parameters of the type class:
|
||||||
|
|
||||||
|
```
|
||||||
|
funDep ::= { {tyVarId }-> {tyVarId }, }
|
||||||
|
```
|
||||||
|
|
||||||
|
These declarations specify that a type parameter may be determined
|
||||||
|
uniquely by certain other type parameters. For example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
class Add x y z | x y -> z, y z -> x, z x -> y
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, the class declaration says that for any triple of types `x`, `y`
|
||||||
|
and `z` that are in the class `Add`, any two of the types uniquely
|
||||||
|
determines the remaining type, *i.e.,*
|
||||||
|
|
||||||
|
- x and y uniquely determine z,
|
||||||
|
- y and z uniquely determine x, and
|
||||||
|
- z and z uniquely determine y.
|
||||||
|
|
||||||
|
See section [8.1](fixme) for more detailed insights into
|
||||||
|
the use of functional dependencies.
|
||||||
|
|
||||||
|
> **NOTE:**
|
||||||
|
> Functional dependencies are not currently checked by the compiler.
|
113
content/chapter4/page6.md
Normal file
113
content/chapter4/page6.md
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
+++
|
||||||
|
title = "`instance` declarations"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
A type can be declared as an instance of a class in two ways. The
|
||||||
|
general mechanism is the `instance` declaration; a convenient shortcut
|
||||||
|
that can sometimes be used is the `deriving` mechanism.
|
||||||
|
|
||||||
|
The general `instance` declaration grammar is the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
topDefn ::= instance context => classId {type }where
|
||||||
|
{ {localDefn ; }}
|
||||||
|
```
|
||||||
|
|
||||||
|
This can be read as saying that the type *type* is an instance of class
|
||||||
|
*classId*, provided the constraints of *context* hold, and where the
|
||||||
|
*localDefn*'s specify the implementation of the methods of the class.
|
||||||
|
|
||||||
|
Sometimes, when a new type is defined using a `data` declaration, it can
|
||||||
|
simultaneously be made a member of certain useful, predefined classes,
|
||||||
|
allowing the compiler to choose the "obvious" implementation of the
|
||||||
|
class methods. This is done using the `deriving` qualification to a
|
||||||
|
`data` declaration (described in section
|
||||||
|
[4.1](fixme)) or to a
|
||||||
|
`struct` declaration (described in section
|
||||||
|
[4.2](fixme)). The only classes for which `deriving` can
|
||||||
|
be used for general types are `Bits`, `Eq` and `Bounded`. Furthermore,
|
||||||
|
`deriving` can be used for any class if the type is a data type that is
|
||||||
|
isomorphic to a type that has an instance for the derived class.
|
||||||
|
|
||||||
|
### Deriving `Bits` {#sec-deriving-Bits}
|
||||||
|
|
||||||
|
The instances derived for the `Bits` class can be described as follows:
|
||||||
|
|
||||||
|
- For a `struct` type it is simply the the concatenation of the bits for
|
||||||
|
all the fields. The first field is in the leftmost (most significant)
|
||||||
|
bits, and so on.
|
||||||
|
- For a `data` type, all values of the type occupy the same number of
|
||||||
|
bits, regardless of which disjunct (constructor) it belongs to. This
|
||||||
|
size is determined by the largest disjunct. The leftmost (most
|
||||||
|
significant) bits are a code (a tag) for the constructor. As few bits as
|
||||||
|
possible are used for this. The first constructor in the definition is
|
||||||
|
coded 0, the next constructor is coded 1, and so on. The size of the
|
||||||
|
rest of the bits is determined by the largest numbers of bits needed to
|
||||||
|
encode the fields for the constructors. For each constructor, the fields
|
||||||
|
are laid out left to right, and the concatenated bits are stored right
|
||||||
|
justified (*i.e.,* at the least significant bits). For disjuncts that
|
||||||
|
are smaller than the largest one, the bits between the constructor code
|
||||||
|
and the field bits, if any, are "don't care" bits.
|
||||||
|
|
||||||
|
Examples: The type
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data Bool = False | True
|
||||||
|
```
|
||||||
|
|
||||||
|
uses one bit. `False` is represented by 0 and `True` by 1.
|
||||||
|
|
||||||
|
```hs
|
||||||
|
struct Två = { första :: Bit 8; andra:: Bit 16 }
|
||||||
|
```
|
||||||
|
|
||||||
|
uses 24 bits with `första` in the upper 8 bits and `andra`
|
||||||
|
in the lower 16.
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data Maybe a = Nothing | Just
|
||||||
|
```
|
||||||
|
|
||||||
|
a will use $1+n$ bits,
|
||||||
|
where $n$ bits are needed to represent values of type `a`. The extra bit
|
||||||
|
will be the most significant bit and it will be 0 (followed by $n$
|
||||||
|
unspecified bits) for `Nothing` and 1 (followed by the $n$ bits for `a`)
|
||||||
|
for `Just`.
|
||||||
|
|
||||||
|
|
||||||
|
### Deriving `Eq`
|
||||||
|
|
||||||
|
|
||||||
|
The instances derived for the `Eq` class is the natural equality for the
|
||||||
|
type. For a struct all fields have to be equal, for a data type the
|
||||||
|
constructors have to be equal and then all their parts.
|
||||||
|
|
||||||
|
|
||||||
|
### Deriving `Bounded`
|
||||||
|
|
||||||
|
|
||||||
|
An instance for `Bounded` can be derived for an enumeration type,
|
||||||
|
*i.e.,* a data type where all constructors are niladic. The `minBound`
|
||||||
|
will be the first constructor and the `maxBound` will be the last.
|
||||||
|
|
||||||
|
`Bounded` can also be derived for a `struct` type if all the field types
|
||||||
|
of the struct are `Bounded`. The `minBound` will be the struct with all
|
||||||
|
fields having their respective `minBound`, and correspondingly for
|
||||||
|
`maxBound`.
|
||||||
|
|
||||||
|
### Deriving for isomorphic types
|
||||||
|
|
||||||
|
A data type with one constructor and one argument is isomorphic to its
|
||||||
|
type argument. For such a type any one-parameter class can be used, in a
|
||||||
|
`deriving`, for which there is an instance for the underlying type.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data Apples = Apple (UInt 32) deriving (Literal, Arith)
|
||||||
|
five :: Apples
|
||||||
|
five = 5
|
||||||
|
eatApple :: Apples -\> Apples
|
||||||
|
eatApple n = n - 1
|
||||||
|
```
|
94
content/chapter4/page7.md
Normal file
94
content/chapter4/page7.md
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
+++
|
||||||
|
title = "Value definitions"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
A value definition defines the value of an identifier (which could be a
|
||||||
|
function). Value definitions are the meat of a BH program.
|
||||||
|
|
||||||
|
Value definitions consist of a type signature followed immediately by
|
||||||
|
one or more defining clauses:
|
||||||
|
|
||||||
|
```
|
||||||
|
topDefn ::= valueDefn
|
||||||
|
valueDefn ::= varId :: ctxType ;
|
||||||
|
{clause ; }
|
||||||
|
clause ::= varId
|
||||||
|
{apat }[ when guard ]= exp
|
||||||
|
```
|
||||||
|
|
||||||
|
The first line of a value definition is the type signature--- it simply
|
||||||
|
specifies that the identifier *varId* has the type *ctxType*. Subsequent
|
||||||
|
lines define the value, one clause at a time. The *varId*'s on the
|
||||||
|
left-hand side of the type signature and on the left-hand side of each
|
||||||
|
clause must all be the same, *i.e.,* they collectively define a single
|
||||||
|
*varId*.
|
||||||
|
|
||||||
|
Each clause defines part of the value, using pattern matching and
|
||||||
|
guards. If there are patterns (*apat*'s) present, then the *varId* being
|
||||||
|
defined is a function, and the patterns represent arguments to the
|
||||||
|
function. The *guard* is a list of arbitrary predicates that may use
|
||||||
|
identifiers bound in the patterns (see Section [7](fixme)).
|
||||||
|
|
||||||
|
The clause should be read as follows: if the function *varId* is applied to
|
||||||
|
arguments that match the corresponding *apat*'s (in which case,
|
||||||
|
identifiers in the *apat*'s are bound to the corresponding components of
|
||||||
|
the arguments), and if the predicates in the *guard* are true, then the
|
||||||
|
function returns the value of the expression *exp*.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
wordSize :: Integer
|
||||||
|
wordSize = 16
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
This simply defines the identifier `wordSize` to have type `Integer` and
|
||||||
|
value 16.
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
not :: Bool -> Bool
|
||||||
|
not True = False
|
||||||
|
not False = True
|
||||||
|
```
|
||||||
|
|
||||||
|
This defines the classical Boolean negation function. The type signature
|
||||||
|
specifies that `not` is a function with argument type `Bool` and result
|
||||||
|
type `Bool`. After that, the first clause specifies that if the argument
|
||||||
|
matches the value `True` (*i.e.,* it *is* the value `True`), then it
|
||||||
|
returns `False`. The final clause specifies that if the argument is
|
||||||
|
`False` it returns `True`.
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
f :: Maybe Int -> Int -> Int
|
||||||
|
f (Just x) y when x > 10, Just y’ <- g y = x + y'
|
||||||
|
f _ _ = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
(If necessary, please first remember the definition of the `Maybe` type,
|
||||||
|
introduced in section [4.1](fixme)). The first line specifies that
|
||||||
|
`f` is a function
|
||||||
|
of two arguments, of type `Maybe Int` and `Int`, respectively, and that
|
||||||
|
its result has type `Int`. The second line specifies that if the first
|
||||||
|
argument has the form `Just x` (in which case let us call its component
|
||||||
|
`x`), if the second argument is anything (let us call it `y`), if `x`'s
|
||||||
|
value is greater than 10, if the result of applying `g` to `y` has the
|
||||||
|
form `Just y’` (in which case let us call the component `y’`), then the
|
||||||
|
result is the value of `x + y’`. In all other cases, the result is the
|
||||||
|
value 0. The bare underscores in the second line are *wild-card*
|
||||||
|
patterns that match anything (described in section
|
||||||
|
[6.1](fixme)).
|
||||||
|
|
||||||
|
|
||||||
|
Clauses are attempted in order, from top to bottom, proceeding to the
|
||||||
|
next clause only if the pattern matching and guard evaluation fail.
|
||||||
|
Within each clause, pattern matching and guard evaluation are attempted
|
||||||
|
from left to right. If no clause succeeds, then the system will raise a
|
||||||
|
"pattern matching error".
|
46
content/chapter4/page8.md
Normal file
46
content/chapter4/page8.md
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
+++
|
||||||
|
title = "Calling foreign functions"
|
||||||
|
weight = 1
|
||||||
|
+++
|
||||||
|
|
||||||
|
A function can be declared to be foreign which means that its
|
||||||
|
implementation is not in BH.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
topDefn ::= foreign varId :: type [= string ] [ , ( {string }) ]
|
||||||
|
```
|
||||||
|
|
||||||
|
The optional string gives the name of the external "function" to use. If
|
||||||
|
no string is given the same name as the BH name is used. The optional
|
||||||
|
strings in parentheses are the port names of the Verilog module that
|
||||||
|
implements the function. Without port names positional arguments will be
|
||||||
|
used.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
foreign countOnes :: Bit n -> Bit 32 = "pop_count"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
A call to `countOnes` will instantiate the Verilog `pop`` ``count`
|
||||||
|
module. It should have the same number of arguments (with the same type)
|
||||||
|
as the BH function, *and* an additional trailing argument which is the
|
||||||
|
result. If the function is (size) polymorphic the instantiated types
|
||||||
|
will be used as Verilog parameters.
|
||||||
|
|
||||||
|
|
||||||
|
Example: using the declaration above an action, with the type of `x`
|
||||||
|
being `Bit 5`,
|
||||||
|
|
||||||
|
```hs
|
||||||
|
y := countOnes x
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
will translate to something like
|
||||||
|
|
||||||
|
```hs
|
||||||
|
pop_count #(5) ires1(R_x, I_y);
|
||||||
|
```
|
21
content/preface/_index.md
Normal file
21
content/preface/_index.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
+++
|
||||||
|
title = "UNDER CONSTRUCTION ⚠️"
|
||||||
|
weight = 5
|
||||||
|
sort_by = "weight"
|
||||||
|
insert_anchor_links = "right"
|
||||||
|
+++
|
||||||
|
|
||||||
|
> Note that these docs are under construction and may not be finished
|
||||||
|
> until summer 2025!
|
||||||
|
> There are several chapters remaining to complete!
|
||||||
|
|
||||||
|
This is a largely manual attempt(with much assistance from
|
||||||
|
[Pandoc][pandoc]) to convert the
|
||||||
|
[Bluespec Haskell/Classic LaTeX docs][bhdocs] to an online
|
||||||
|
readable markdown format.
|
||||||
|
|
||||||
|
If you find any errors, please reach out to me at
|
||||||
|
[yehowshua@joyofhardware.com](mailto:yehowshua@joyofhardware.com)
|
||||||
|
|
||||||
|
[pandoc]: https://pandoc.org
|
||||||
|
[bhdocs]: https://github.com/B-Lang-org/bsc/tree/main/doc/BH_ref_guide
|
231
sass/_content.scss
Normal file
231
sass/_content.scss
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
@use "variables";
|
||||||
|
.page {
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% - #{variables.$sidebar-width});
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
color: #000;
|
||||||
|
background: #fff;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
transition: 0.5s;
|
||||||
|
|
||||||
|
.zola-anchor {
|
||||||
|
color: #357aba;
|
||||||
|
padding-left: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: initial;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
a {
|
||||||
|
color: #357aba;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
height: 4px;
|
||||||
|
padding: 0;
|
||||||
|
margin: 1.7em 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #e7e7e7;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: .85em;
|
||||||
|
padding: 0 15px;
|
||||||
|
color: #858585;
|
||||||
|
border-left: 4px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 0.1em 0.3em;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #6e6b5e;
|
||||||
|
background: #f1f1f1;
|
||||||
|
font-size: 0.875em;
|
||||||
|
font-family: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin: 0 auto;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-color: #cccccc;
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 3px 20px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead {
|
||||||
|
th {
|
||||||
|
padding: 6px 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
font-size: 1.6rem;
|
||||||
|
word-wrap: break-word;
|
||||||
|
line-height: 1.7;
|
||||||
|
position: relative;
|
||||||
|
left: 0;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 15px 40px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0.85em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.previous, .next {
|
||||||
|
position: fixed;
|
||||||
|
display: flex;
|
||||||
|
top: 50px;
|
||||||
|
bottom: 0;
|
||||||
|
font-size: 2.5em;
|
||||||
|
color: #ccc;
|
||||||
|
text-decoration: none;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
max-width: 150px;
|
||||||
|
min-width: 90px;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.previous {
|
||||||
|
left: variables.$sidebar-width;
|
||||||
|
float: left;
|
||||||
|
transition: left 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.next {
|
||||||
|
// not 0 as it goes over the sidebar otherwise
|
||||||
|
right: 15px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include variables.max-screen(1250px) {
|
||||||
|
.previous, .next {
|
||||||
|
position: static;
|
||||||
|
top: auto;
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 49%;
|
||||||
|
width: 49%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include variables.min-screen(600px) {
|
||||||
|
.page {
|
||||||
|
left: variables.$sidebar-width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-without-menu {
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
.previous {
|
||||||
|
left: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include variables.max-screen(600px) {
|
||||||
|
.page {
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-without-menu {
|
||||||
|
left: calc(100% - 100px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-container {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&--is-visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
width: 100%;
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results {
|
||||||
|
&__header {
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 1rem 0rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__items {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__teaser {
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-mode {
|
||||||
|
.prev-link, .next-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
18
sass/_document.scss
Normal file
18
sass/_document.scss
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 62.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body, html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
letter-spacing: 0.2px;
|
||||||
|
}
|
160
sass/_header.scss
Normal file
160
sass/_header.scss
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
@mixin menu-icon() {
|
||||||
|
@keyframes clickfirst {
|
||||||
|
0% {
|
||||||
|
transform: translateY(6px) rotate(0deg);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0) rotate(45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes clickmid {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes clicklast {
|
||||||
|
0% {
|
||||||
|
transform: translateY(-6px) rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0) rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes outfirst {
|
||||||
|
0% {
|
||||||
|
transform: translateY(0) rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(-6px) rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes outmid {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes outlast {
|
||||||
|
0% {
|
||||||
|
transform: translateY(0) rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(6px) rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
position: absolute;
|
||||||
|
/* fallback for browsers which still doesn't support for `calc()` */
|
||||||
|
left: 15px;
|
||||||
|
top: 25px;
|
||||||
|
left: calc((100% - 20px) / 2);
|
||||||
|
top: calc((100% - 1px) / 2);
|
||||||
|
width: 20px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
transform: translateY(6px) rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
transform: translateY(-6px) rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.icon-click {
|
||||||
|
span:nth-child(1) {
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
animation-name: clickfirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:nth-child(2) {
|
||||||
|
animation-duration: 0.2s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
animation-name: clickmid;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:nth-child(3) {
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
animation-name: clicklast;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.icon-out {
|
||||||
|
span:nth-child(1) {
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
animation-name: outfirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:nth-child(2) {
|
||||||
|
animation-duration: 0.2s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
animation-name: outmid;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:nth-child(3) {
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
animation-name: outlast;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page__header {
|
||||||
|
height: 50px;
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
font-size: 24px;
|
||||||
|
text-align: center;
|
||||||
|
float: left;
|
||||||
|
position: relative;
|
||||||
|
transition: background .5s;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
@include menu-icon();
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
span {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 50px;
|
||||||
|
color: rgba(0, 0, 0, 0.5);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 2rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: black
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
sass/_navigation.scss
Normal file
57
sass/_navigation.scss
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
@use "variables";
|
||||||
|
.menu {
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
width: 300px;
|
||||||
|
color: #364149;
|
||||||
|
background: #fafafa;
|
||||||
|
border-right: 1px solid rgba(0, 0, 0, 0.07);
|
||||||
|
transition: 0.5s;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
color: #364149;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 10px 15px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li.active > a {
|
||||||
|
color: #0053bc;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-hidden {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include variables.max-screen(600px) {
|
||||||
|
.menu {
|
||||||
|
width: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-hidden {
|
||||||
|
width: calc(100% - 100px);
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
}
|
447
sass/_normalize.scss
Normal file
447
sass/_normalize.scss
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||||
|
|
||||||
|
/* Document
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the line height in all browsers.
|
||||||
|
* 2. Prevent adjustments of font size after orientation changes in
|
||||||
|
* IE on Windows Phone and in iOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
-ms-text-size-adjust: 100%; /* 2 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the margin in all browsers (opinionated).
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 9-.
|
||||||
|
*/
|
||||||
|
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
nav,
|
||||||
|
section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the font size and margin on `h1` elements within `section` and
|
||||||
|
* `article` contexts in Chrome, Firefox, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grouping content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 9-.
|
||||||
|
* 1. Add the correct display in IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
figcaption,
|
||||||
|
figure,
|
||||||
|
main { /* 1 */
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct margin in IE 8.
|
||||||
|
*/
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 1em 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in Firefox.
|
||||||
|
* 2. Show the overflow in Edge and IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box; /* 1 */
|
||||||
|
height: 0; /* 1 */
|
||||||
|
overflow: visible; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text-level semantics
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Remove the gray background on active links in IE 10.
|
||||||
|
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent; /* 1 */
|
||||||
|
-webkit-text-decoration-skip: objects; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
|
||||||
|
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: none; /* 1 */
|
||||||
|
text-decoration: underline; /* 2 */
|
||||||
|
text-decoration: underline dotted; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font style in Android 4.3-.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dfn {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct background and color in IE 9-.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mark {
|
||||||
|
background-color: #ff0;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||||
|
* all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 9-.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio,
|
||||||
|
video {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in iOS 4-7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio:not([controls]) {
|
||||||
|
display: none;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the border on images inside links in IE 10-.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the overflow in IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
svg:not(:root) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Change the font styles in all browsers (opinionated).
|
||||||
|
* 2. Remove the margin in Firefox and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: sans-serif; /* 1 */
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the overflow in IE.
|
||||||
|
* 1. Show the overflow in Edge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input { /* 1 */
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||||
|
* 1. Remove the inheritance of text transform in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select { /* 1 */
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||||
|
* controls in Android 4.
|
||||||
|
* 2. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
html [type="button"], /* 1 */
|
||||||
|
[type="reset"],
|
||||||
|
[type="submit"] {
|
||||||
|
-webkit-appearance: button; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner border and padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
|
[type="reset"]::-moz-focus-inner,
|
||||||
|
[type="submit"]::-moz-focus-inner {
|
||||||
|
border-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the focus styles unset by the previous rule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button:-moz-focusring,
|
||||||
|
[type="button"]:-moz-focusring,
|
||||||
|
[type="reset"]:-moz-focusring,
|
||||||
|
[type="submit"]:-moz-focusring {
|
||||||
|
outline: 1px dotted ButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
padding: 0.35em 0.75em 0.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the text wrapping in Edge and IE.
|
||||||
|
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||||
|
* 3. Remove the padding so developers are not caught out when they zero out
|
||||||
|
* `fieldset` elements in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
color: inherit; /* 2 */
|
||||||
|
display: table; /* 1 */
|
||||||
|
max-width: 100%; /* 1 */
|
||||||
|
padding: 0; /* 3 */
|
||||||
|
white-space: normal; /* 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct display in IE 9-.
|
||||||
|
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
progress {
|
||||||
|
display: inline-block; /* 1 */
|
||||||
|
vertical-align: baseline; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the default vertical scrollbar in IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in IE 10-.
|
||||||
|
* 2. Remove the padding in IE 10-.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="checkbox"],
|
||||||
|
[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the odd appearance in Chrome and Safari.
|
||||||
|
* 2. Correct the outline style in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
outline-offset: -2px; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-cancel-button,
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
* 2. Change font properties to `inherit` in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interactive
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in IE 9-.
|
||||||
|
* 1. Add the correct display in Edge, IE, and Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
details, /* 1 */
|
||||||
|
menu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scripting
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 9-.
|
||||||
|
*/
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hidden
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10-.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
162
sass/_syntax-charcoal.scss
Normal file
162
sass/_syntax-charcoal.scss
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
@mixin dark {
|
||||||
|
.z-code {
|
||||||
|
color: #cccece;
|
||||||
|
background-color: #191919;
|
||||||
|
}
|
||||||
|
.z-comment, .z-punctuation.z-definition.z-comment {
|
||||||
|
color: #7e8384;
|
||||||
|
}
|
||||||
|
.z-variable {
|
||||||
|
color: #cccece;
|
||||||
|
}
|
||||||
|
.z-keyword, .z-storage.z-type, .z-storage.z-modifier {
|
||||||
|
color: #c594c5;
|
||||||
|
}
|
||||||
|
.z-keyword.z-operator, .z-constant.z-other.z-color, .z-punctuation, .z-meta.z-tag, .z-punctuation.z-definition.z-tag, .z-punctuation.z-separator.z-inheritance.z-php, .z-punctuation.z-definition.z-tag.z-html, .z-punctuation.z-definition.z-tag.z-begin.z-html, .z-punctuation.z-definition.z-tag.z-end.z-html, .z-punctuation.z-section.z-embedded, .z-keyword.z-other.z-template, .z-keyword.z-other.z-substitution {
|
||||||
|
color: #5fb3b3;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-tag, .z-meta.z-tag.z-sgml, .z-markup.z-deleted.z-git_gutter {
|
||||||
|
color: #ff7b84;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-function, .z-meta.z-function-call, .z-variable.z-function, .z-support.z-function, .z-keyword.z-other.z-special-method, .z-meta.z-block-level {
|
||||||
|
color: #78aade;
|
||||||
|
}
|
||||||
|
.z-support.z-other.z-variable, .z-string.z-other.z-link {
|
||||||
|
color: #fa7e81;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric, .z-constant.z-language, .z-support.z-constant, .z-constant.z-character, .z-variable.z-parameter, .z-keyword.z-other.z-unit {
|
||||||
|
color: #f99157;
|
||||||
|
}
|
||||||
|
.z-string, .z-constant.z-other.z-symbol, .z-constant.z-other.z-key, .z-entity.z-other.z-inherited-class, .z-markup.z-heading, .z-markup.z-inserted.z-git_gutter, .z-meta.z-group.z-braces.z-curly .z-constant.z-other.z-object.z-key.z-js .z-string.z-unquoted.z-label.z-js {
|
||||||
|
color: #99c794;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-class, .z-entity.z-name.z-type.z-class, .z-support.z-type, .z-support.z-class, .z-support.z-orther.z-namespace.z-use.z-php, .z-meta.z-use.z-php, .z-support.z-other.z-namespace.z-php, .z-markup.z-changed.z-git_gutter {
|
||||||
|
color: #fac863;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-module.z-js, .z-variable.z-import.z-parameter.z-js, .z-variable.z-other.z-class.z-js {
|
||||||
|
color: #fe7d83;
|
||||||
|
}
|
||||||
|
.z-variable.z-language {
|
||||||
|
color: #fe7d83;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-method.z-js {
|
||||||
|
color: #d8dee9;
|
||||||
|
}
|
||||||
|
.z-meta.z-class-method.z-js .z-entity.z-name.z-function.z-js, .z-variable.z-function.z-constructor {
|
||||||
|
color: #d8dee9;
|
||||||
|
}
|
||||||
|
.z-entity.z-other.z-attribute-name {
|
||||||
|
color: #cd91c4;
|
||||||
|
}
|
||||||
|
.z-markup.z-inserted {
|
||||||
|
color: #99c794;
|
||||||
|
}
|
||||||
|
.z-markup.z-deleted {
|
||||||
|
color: #fe7d83;
|
||||||
|
}
|
||||||
|
.z-markup.z-changed {
|
||||||
|
color: #cd91c4;
|
||||||
|
}
|
||||||
|
.z-string.z-regexp {
|
||||||
|
color: #5fb3b3;
|
||||||
|
}
|
||||||
|
.z-constant.z-character.z-escape {
|
||||||
|
color: #5fb3b3;
|
||||||
|
}
|
||||||
|
.z-*url*, .z-*link*, .z-*uri* {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric.z-line-number.z-find-in-files {
|
||||||
|
color: #cf9a87;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-filename.z-find-in-files {
|
||||||
|
color: #99c794;
|
||||||
|
}
|
||||||
|
.z-tag.z-decorator.z-js .z-entity.z-name.z-tag.z-js, .z-tag.z-decorator.z-js .z-punctuation.z-definition.z-tag.z-js {
|
||||||
|
color: #78aade;
|
||||||
|
}
|
||||||
|
.z-source.z-js .z-constant.z-other.z-object.z-key.z-js .z-string.z-unquoted.z-label.z-js {
|
||||||
|
color: #fe7d83;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@mixin light {
|
||||||
|
.z-code {
|
||||||
|
color: #727373;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.z-comment, .z-punctuation.z-definition.z-comment {
|
||||||
|
color: #5f6364;
|
||||||
|
}
|
||||||
|
.z-variable {
|
||||||
|
color: #727373;
|
||||||
|
}
|
||||||
|
.z-keyword, .z-storage.z-type, .z-storage.z-modifier {
|
||||||
|
color: #916392;
|
||||||
|
}
|
||||||
|
.z-keyword.z-operator, .z-constant.z-other.z-color, .z-punctuation, .z-meta.z-tag, .z-punctuation.z-definition.z-tag, .z-punctuation.z-separator.z-inheritance.z-php, .z-punctuation.z-definition.z-tag.z-html, .z-punctuation.z-definition.z-tag.z-begin.z-html, .z-punctuation.z-definition.z-tag.z-end.z-html, .z-punctuation.z-section.z-embedded, .z-keyword.z-other.z-template, .z-keyword.z-other.z-substitution {
|
||||||
|
color: #237e7f;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-tag, .z-meta.z-tag.z-sgml, .z-markup.z-deleted.z-git_gutter {
|
||||||
|
color: #ca4251;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-function, .z-meta.z-function-call, .z-variable.z-function, .z-support.z-function, .z-keyword.z-other.z-special-method, .z-meta.z-block-level {
|
||||||
|
color: #4076a7;
|
||||||
|
}
|
||||||
|
.z-support.z-other.z-variable, .z-string.z-other.z-link {
|
||||||
|
color: #c14c52;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric, .z-constant.z-language, .z-support.z-constant, .z-constant.z-character, .z-variable.z-parameter, .z-keyword.z-other.z-unit {
|
||||||
|
color: #b75922;
|
||||||
|
}
|
||||||
|
.z-string, .z-constant.z-other.z-symbol, .z-constant.z-other.z-key, .z-entity.z-other.z-inherited-class, .z-markup.z-heading, .z-markup.z-inserted.z-git_gutter, .z-meta.z-group.z-braces.z-curly .z-constant.z-other.z-object.z-key.z-js .z-string.z-unquoted.z-label.z-js {
|
||||||
|
color: #517c4e;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-class, .z-entity.z-name.z-type.z-class, .z-support.z-type, .z-support.z-class, .z-support.z-orther.z-namespace.z-use.z-php, .z-meta.z-use.z-php, .z-support.z-other.z-namespace.z-php, .z-markup.z-changed.z-git_gutter {
|
||||||
|
color: #926c00;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-module.z-js, .z-variable.z-import.z-parameter.z-js, .z-variable.z-other.z-class.z-js {
|
||||||
|
color: #cb414d;
|
||||||
|
}
|
||||||
|
.z-variable.z-language {
|
||||||
|
color: #cb414d;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-method.z-js {
|
||||||
|
color: #6c727c;
|
||||||
|
}
|
||||||
|
.z-meta.z-class-method.z-js .z-entity.z-name.z-function.z-js, .z-variable.z-function.z-constructor {
|
||||||
|
color: #6c727c;
|
||||||
|
}
|
||||||
|
.z-entity.z-other.z-attribute-name {
|
||||||
|
color: #996091;
|
||||||
|
}
|
||||||
|
.z-markup.z-inserted {
|
||||||
|
color: #517c4e;
|
||||||
|
}
|
||||||
|
.z-markup.z-deleted {
|
||||||
|
color: #cb414d;
|
||||||
|
}
|
||||||
|
.z-markup.z-changed {
|
||||||
|
color: #996091;
|
||||||
|
}
|
||||||
|
.z-string.z-regexp {
|
||||||
|
color: #237e7f;
|
||||||
|
}
|
||||||
|
.z-constant.z-character.z-escape {
|
||||||
|
color: #237e7f;
|
||||||
|
}
|
||||||
|
.z-*url*, .z-*link*, .z-*uri* {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric.z-line-number.z-find-in-files {
|
||||||
|
color: #976756;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-filename.z-find-in-files {
|
||||||
|
color: #517c4e;
|
||||||
|
}
|
||||||
|
.z-tag.z-decorator.z-js .z-entity.z-name.z-tag.z-js, .z-tag.z-decorator.z-js .z-punctuation.z-definition.z-tag.z-js {
|
||||||
|
color: #4076a7;
|
||||||
|
}
|
||||||
|
.z-source.z-js .z-constant.z-other.z-object.z-key.z-js .z-string.z-unquoted.z-label.z-js {
|
||||||
|
color: #cb414d;
|
||||||
|
}
|
||||||
|
}
|
551
sass/_syntax.scss
Normal file
551
sass/_syntax.scss
Normal file
|
@ -0,0 +1,551 @@
|
||||||
|
@mixin dark {
|
||||||
|
.z-code {
|
||||||
|
color: #bfbab0;
|
||||||
|
background-color: #191919;
|
||||||
|
}
|
||||||
|
.z-comment, .z-punctuation.z-definition.z-comment {
|
||||||
|
color: #87929f;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-variable {
|
||||||
|
color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-string, .z-constant.z-other.z-symbol {
|
||||||
|
color: #c2d94c;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric {
|
||||||
|
color: #f29718;
|
||||||
|
}
|
||||||
|
.z-string.z-regexp, .z-constant.z-character.z-escape {
|
||||||
|
color: #95e6cb;
|
||||||
|
}
|
||||||
|
.z-constant.z-language {
|
||||||
|
color: #f29718;
|
||||||
|
}
|
||||||
|
.z-constant.z-character, .z-constant.z-other {
|
||||||
|
color: #f29718;
|
||||||
|
}
|
||||||
|
.z-variable.z-member {
|
||||||
|
color: #fe7d83;
|
||||||
|
}
|
||||||
|
.z-keyword, .z-keyword.z-operator.z-word {
|
||||||
|
color: #00bbff;
|
||||||
|
}
|
||||||
|
.z-keyword.z-operator {
|
||||||
|
color: #f29668;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-separator, .z-punctuation.z-terminator {
|
||||||
|
color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-section {
|
||||||
|
color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-accessor {
|
||||||
|
color: #f29668;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-definition.z-annotation {
|
||||||
|
color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-variable.z-other.z-dollar.z-only.z-js, .z-variable.z-other.z-object.z-dollar.z-only.z-js, .z-variable.z-type.z-dollar.z-only.z-js, .z-support.z-class.z-dollar.z-only.z-js {
|
||||||
|
color: #e6b673;
|
||||||
|
}
|
||||||
|
.z-storage {
|
||||||
|
color: #00bbff;
|
||||||
|
}
|
||||||
|
.z-storage.z-type {
|
||||||
|
color: #00bbff;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-function {
|
||||||
|
color: #ffb454;
|
||||||
|
}
|
||||||
|
.z-entity.z-name, .z-entity.z-name.z-tag, .z-entity.z-name.z-label {
|
||||||
|
color: #59c2ff;
|
||||||
|
}
|
||||||
|
.z-entity.z-other.z-inherited-class {
|
||||||
|
color: #59c2ff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.z-variable.z-parameter {
|
||||||
|
color: #f29718;
|
||||||
|
}
|
||||||
|
.z-variable.z-language {
|
||||||
|
color: #39bae6;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-tag, .z-meta.z-tag.z-sgml {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-definition.z-tag.z-end, .z-punctuation.z-definition.z-tag.z-begin, .z-punctuation.z-definition.z-tag {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-entity.z-other.z-attribute-name {
|
||||||
|
color: #ffb454;
|
||||||
|
}
|
||||||
|
.z-variable.z-function, .z-variable.z-annotation {
|
||||||
|
color: #ffb454;
|
||||||
|
}
|
||||||
|
.z-support.z-function, .z-support.z-macro {
|
||||||
|
color: #fe7d83;
|
||||||
|
}
|
||||||
|
.z-support.z-constant {
|
||||||
|
color: #f29668;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-support.z-type, .z-support.z-class {
|
||||||
|
color: #39bae6;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-invalid {
|
||||||
|
color: #ff7c6d;
|
||||||
|
}
|
||||||
|
.z-invalid.z-deprecated {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #00bbff;
|
||||||
|
}
|
||||||
|
.z-meta.z-diff, .z-meta.z-diff.z-header {
|
||||||
|
color: #c594c5;
|
||||||
|
}
|
||||||
|
.z-source.z-ruby .z-variable.z-other.z-readwrite {
|
||||||
|
color: #ffb454;
|
||||||
|
}
|
||||||
|
.z-source.z-css .z-entity.z-name.z-tag, .z-source.z-sass .z-entity.z-name.z-tag, .z-source.z-scss .z-entity.z-name.z-tag, .z-source.z-less .z-entity.z-name.z-tag, .z-source.z-stylus .z-entity.z-name.z-tag {
|
||||||
|
color: #59c2ff;
|
||||||
|
}
|
||||||
|
.z-source.z-css .z-support.z-type, .z-source.z-sass .z-support.z-type, .z-source.z-scss .z-support.z-type, .z-source.z-less .z-support.z-type, .z-source.z-stylus .z-support.z-type {
|
||||||
|
color: #798491;
|
||||||
|
}
|
||||||
|
.z-support.z-type.z-property-name {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric.z-line-number.z-find-in-files {
|
||||||
|
color: #798491;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric.z-line-number.z-match {
|
||||||
|
color: #00bbff;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-filename.z-find-in-files {
|
||||||
|
color: #c2d94c;
|
||||||
|
}
|
||||||
|
.z-message.z-error {
|
||||||
|
color: #ff7c6d;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-markup.z-heading {
|
||||||
|
color: #00bbff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.z-string.z-other.z-link, .z-markup.z-underline.z-link {
|
||||||
|
color: #95e6cb;
|
||||||
|
text-decoration: underline;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-definition.z-image {
|
||||||
|
color: #ffb454;
|
||||||
|
}
|
||||||
|
.z-markup.z-italic {
|
||||||
|
color: #fe7d83;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-markup.z-bold {
|
||||||
|
color: #fe7d83;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.z-markup.z-italic .z-markup.z-bold, .z-markup.z-bold .z-markup.z-italic {
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-markup.z-raw {
|
||||||
|
background-color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-markup.z-raw.z-inline {
|
||||||
|
background-color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-meta.z-separator {
|
||||||
|
color: #798491;
|
||||||
|
background-color: #bfbab0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.z-markup.z-quote {
|
||||||
|
color: #f29718;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-markup.z-list.z-numbered.z-bullet, .z-markup.z-list .z-punctuation.z-definition.z-list_item {
|
||||||
|
color: #95e6cb;
|
||||||
|
}
|
||||||
|
.z-markup.z-inserted {
|
||||||
|
color: #c2d94c;
|
||||||
|
}
|
||||||
|
.z-markup.z-changed {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-markup.z-deleted {
|
||||||
|
color: #fe7d83;
|
||||||
|
}
|
||||||
|
.z-markup.z-strike {
|
||||||
|
color: #e6b673;
|
||||||
|
}
|
||||||
|
.z-markup.z-table {
|
||||||
|
color: #39bae6;
|
||||||
|
background-color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-text.z-html.z-markdown .z-markup.z-raw.z-inline {
|
||||||
|
color: #f29668;
|
||||||
|
}
|
||||||
|
.z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break {
|
||||||
|
color: #798491;
|
||||||
|
}
|
||||||
|
.z-markup.z-raw.z-block.z-fenced.z-markdown {
|
||||||
|
color: #bfbab0;
|
||||||
|
background-color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-definition.z-fenced.z-markdown, .z-variable.z-language.z-fenced.z-markdown {
|
||||||
|
color: #798491;
|
||||||
|
background-color: #bfbab0;
|
||||||
|
}
|
||||||
|
.z-variable.z-language.z-fenced.z-markdown {
|
||||||
|
color: #798491;
|
||||||
|
}
|
||||||
|
.z-markup.z-inserted.z-git_gutter {
|
||||||
|
color: #c2d94c;
|
||||||
|
}
|
||||||
|
.z-markup.z-changed.z-git_gutter {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-markup.z-deleted.z-git_gutter {
|
||||||
|
color: #ff7c6d;
|
||||||
|
}
|
||||||
|
.z-markup.z-ignored.z-git_gutter {
|
||||||
|
color: #20272c;
|
||||||
|
}
|
||||||
|
.z-markup.z-untracked.z-git_gutter {
|
||||||
|
color: #20272c;
|
||||||
|
}
|
||||||
|
.z-gutter_color {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.z-acejump.z-label.z-blue {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-acejump.z-label.z-green {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #c2d94c;
|
||||||
|
}
|
||||||
|
.z-acejump.z-label.z-orange {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #00bbff;
|
||||||
|
}
|
||||||
|
.z-acejump.z-label.z-purple {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #fe7d83;
|
||||||
|
}
|
||||||
|
.z-sublimelinter.z-mark.z-warning {
|
||||||
|
color: #39bae6;
|
||||||
|
}
|
||||||
|
.z-sublimelinter.z-gutter-mark {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.z-sublimelinter.z-mark.z-error {
|
||||||
|
color: #ff7c6d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@mixin light {
|
||||||
|
.z-code {
|
||||||
|
color: #50565a;
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
.z-comment, .z-punctuation.z-definition.z-comment {
|
||||||
|
color: #676c72;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-variable {
|
||||||
|
color: #50565a;
|
||||||
|
}
|
||||||
|
.z-string, .z-constant.z-other.z-symbol {
|
||||||
|
color: #497700;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric {
|
||||||
|
color: #b04e00;
|
||||||
|
}
|
||||||
|
.z-string.z-regexp, .z-constant.z-character.z-escape {
|
||||||
|
color: #007b59;
|
||||||
|
}
|
||||||
|
.z-constant.z-language {
|
||||||
|
color: #b04e00;
|
||||||
|
}
|
||||||
|
.z-constant.z-character, .z-constant.z-other {
|
||||||
|
color: #b04e00;
|
||||||
|
}
|
||||||
|
.z-variable.z-member {
|
||||||
|
color: #c33947;
|
||||||
|
}
|
||||||
|
.z-keyword, .z-keyword.z-operator.z-word {
|
||||||
|
color: #0062e8;
|
||||||
|
}
|
||||||
|
.z-keyword.z-operator {
|
||||||
|
color: #a4552c;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-separator, .z-punctuation.z-terminator {
|
||||||
|
color: #50565a;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-section {
|
||||||
|
color: #50565a;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-accessor {
|
||||||
|
color: #a4552c;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-definition.z-annotation {
|
||||||
|
color: #50565a;
|
||||||
|
}
|
||||||
|
.z-variable.z-other.z-dollar.z-only.z-js, .z-variable.z-other.z-object.z-dollar.z-only.z-js, .z-variable.z-type.z-dollar.z-only.z-js, .z-support.z-class.z-dollar.z-only.z-js {
|
||||||
|
color: #8b6426;
|
||||||
|
}
|
||||||
|
.z-storage {
|
||||||
|
color: #0062e8;
|
||||||
|
}
|
||||||
|
.z-storage.z-type {
|
||||||
|
color: #0062e8;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-function {
|
||||||
|
color: #a45600;
|
||||||
|
}
|
||||||
|
.z-entity.z-name, .z-entity.z-name.z-tag, .z-entity.z-name.z-label {
|
||||||
|
color: #0070b3;
|
||||||
|
}
|
||||||
|
.z-entity.z-other.z-inherited-class {
|
||||||
|
color: #0070b3;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.z-variable.z-parameter {
|
||||||
|
color: #b04e00;
|
||||||
|
}
|
||||||
|
.z-variable.z-language {
|
||||||
|
color: #007492;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-tag, .z-meta.z-tag.z-sgml {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-definition.z-tag.z-end, .z-punctuation.z-definition.z-tag.z-begin, .z-punctuation.z-definition.z-tag {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-entity.z-other.z-attribute-name {
|
||||||
|
color: #a45600;
|
||||||
|
}
|
||||||
|
.z-variable.z-function, .z-variable.z-annotation {
|
||||||
|
color: #a45600;
|
||||||
|
}
|
||||||
|
.z-support.z-function, .z-support.z-macro {
|
||||||
|
color: #b94046;
|
||||||
|
}
|
||||||
|
.z-support.z-constant {
|
||||||
|
color: #a4552c;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-support.z-type, .z-support.z-class {
|
||||||
|
color: #007492;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-invalid {
|
||||||
|
color: #da0001;
|
||||||
|
}
|
||||||
|
.z-invalid.z-deprecated {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #0062e8;
|
||||||
|
}
|
||||||
|
.z-source.z-ruby .z-variable.z-other.z-readwrite {
|
||||||
|
color: #a45600;
|
||||||
|
}
|
||||||
|
.z-source.z-css .z-entity.z-name.z-tag, .z-source.z-sass .z-entity.z-name.z-tag, .z-source.z-scss .z-entity.z-name.z-tag, .z-source.z-less .z-entity.z-name.z-tag, .z-source.z-stylus .z-entity.z-name.z-tag {
|
||||||
|
color: #0070b3;
|
||||||
|
}
|
||||||
|
.z-source.z-css .z-support.z-type, .z-source.z-sass .z-support.z-type, .z-source.z-scss .z-support.z-type, .z-source.z-less .z-support.z-type, .z-source.z-stylus .z-support.z-type {
|
||||||
|
color: #676c72;
|
||||||
|
}
|
||||||
|
.z-support.z-type.z-property-name {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric.z-line-number.z-find-in-files {
|
||||||
|
color: #676c72;
|
||||||
|
}
|
||||||
|
.z-constant.z-numeric.z-line-number.z-match {
|
||||||
|
color: #0062e8;
|
||||||
|
}
|
||||||
|
.z-entity.z-name.z-filename.z-find-in-files {
|
||||||
|
color: #497700;
|
||||||
|
}
|
||||||
|
.z-message.z-error {
|
||||||
|
color: #da0001;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json, .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-markup.z-heading {
|
||||||
|
color: #0062e8;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.z-string.z-other.z-link, .z-markup.z-underline.z-link {
|
||||||
|
color: #007b59;
|
||||||
|
text-decoration: underline;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-definition.z-image {
|
||||||
|
color: #a45600;
|
||||||
|
}
|
||||||
|
.z-markup.z-italic {
|
||||||
|
color: #b94046;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-markup.z-bold {
|
||||||
|
color: #b94046;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.z-markup.z-italic .z-markup.z-bold, .z-markup.z-bold .z-markup.z-italic {
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-markup.z-raw {
|
||||||
|
background-color: #50565a;
|
||||||
|
}
|
||||||
|
.z-markup.z-raw.z-inline {
|
||||||
|
background-color: #50565a;
|
||||||
|
}
|
||||||
|
.z-meta.z-separator {
|
||||||
|
color: #676c72;
|
||||||
|
background-color: #50565a;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.z-markup.z-quote {
|
||||||
|
color: #b04e00;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.z-markup.z-list.z-numbered.z-bullet, .z-markup.z-list .z-punctuation.z-definition.z-list_item {
|
||||||
|
color: #007b59;
|
||||||
|
}
|
||||||
|
.z-markup.z-inserted {
|
||||||
|
color: #497700;
|
||||||
|
}
|
||||||
|
.z-markup.z-changed {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-markup.z-deleted {
|
||||||
|
color: #b94046;
|
||||||
|
}
|
||||||
|
.z-markup.z-strike {
|
||||||
|
color: #8b6426;
|
||||||
|
}
|
||||||
|
.z-markup.z-table {
|
||||||
|
color: #007492;
|
||||||
|
background-color: #50565a;
|
||||||
|
}
|
||||||
|
.z-text.z-html.z-markdown .z-markup.z-raw.z-inline {
|
||||||
|
color: #a4552c;
|
||||||
|
}
|
||||||
|
.z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break {
|
||||||
|
color: #676c72;
|
||||||
|
}
|
||||||
|
.z-markup.z-raw.z-block.z-fenced.z-markdown {
|
||||||
|
color: #50565a;
|
||||||
|
background-color: #50565a;
|
||||||
|
}
|
||||||
|
.z-punctuation.z-definition.z-fenced.z-markdown, .z-variable.z-language.z-fenced.z-markdown {
|
||||||
|
color: #676c72;
|
||||||
|
background-color: #50565a;
|
||||||
|
}
|
||||||
|
.z-variable.z-language.z-fenced.z-markdown {
|
||||||
|
color: #676c72;
|
||||||
|
}
|
||||||
|
.z-markup.z-inserted.z-git_gutter {
|
||||||
|
color: #497700;
|
||||||
|
}
|
||||||
|
.z-markup.z-changed.z-git_gutter {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-markup.z-deleted.z-git_gutter {
|
||||||
|
color: #da0001;
|
||||||
|
}
|
||||||
|
.z-markup.z-ignored.z-git_gutter {
|
||||||
|
color: #696b6c;
|
||||||
|
}
|
||||||
|
.z-markup.z-untracked.z-git_gutter {
|
||||||
|
color: #696b6c;
|
||||||
|
}
|
||||||
|
.z-gutter_color {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.z-acejump.z-label.z-blue {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #007492;
|
||||||
|
}
|
||||||
|
.z-acejump.z-label.z-green {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #497700;
|
||||||
|
}
|
||||||
|
.z-acejump.z-label.z-orange {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #0062e8;
|
||||||
|
}
|
||||||
|
.z-acejump.z-label.z-purple {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #b94046;
|
||||||
|
}
|
||||||
|
.z-sublimelinter.z-mark.z-warning {
|
||||||
|
color: #007492;
|
||||||
|
}
|
||||||
|
.z-sublimelinter.z-gutter-mark {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
.z-sublimelinter.z-mark.z-error {
|
||||||
|
color: #da0001;
|
||||||
|
}
|
||||||
|
}
|
13
sass/_variables.scss
Normal file
13
sass/_variables.scss
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
@mixin min-screen($min-width: $body-width) {
|
||||||
|
@media screen and (min-width: $min-width) {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin max-screen($max-width: $body-width) {
|
||||||
|
@media screen and (max-width: $max-width) {
|
||||||
|
@content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sidebar-width: 300px;
|
12
sass/book.scss
Normal file
12
sass/book.scss
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
@charset "utf-8";
|
||||||
|
|
||||||
|
@use "normalize";
|
||||||
|
|
||||||
|
@use "variables";
|
||||||
|
@use "document";
|
||||||
|
@use "navigation";
|
||||||
|
@use "content";
|
||||||
|
@use "header";
|
||||||
|
|
||||||
|
@use "syntax" as syntax;
|
||||||
|
@include syntax.light;
|
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 142 KiB |
223
static/book.js
Normal file
223
static/book.js
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
function initToggleMenu() {
|
||||||
|
var $menu = document.querySelector(".menu");
|
||||||
|
var $menuIcon = document.querySelector(".menu-icon");
|
||||||
|
var $page = document.querySelector(".page");
|
||||||
|
$menuIcon.addEventListener("click", function() {
|
||||||
|
$menu.classList.toggle("menu-hidden");
|
||||||
|
$page.classList.toggle("page-without-menu");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function debounce(func, wait) {
|
||||||
|
var timeout;
|
||||||
|
|
||||||
|
return function () {
|
||||||
|
var context = this;
|
||||||
|
var args = arguments;
|
||||||
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
timeout = setTimeout(function () {
|
||||||
|
timeout = null;
|
||||||
|
func.apply(context, args);
|
||||||
|
}, wait);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Taken from mdbook
|
||||||
|
// The strategy is as follows:
|
||||||
|
// First, assign a value to each word in the document:
|
||||||
|
// Words that correspond to search terms (stemmer aware): 40
|
||||||
|
// Normal words: 2
|
||||||
|
// First word in a sentence: 8
|
||||||
|
// Then use a sliding window with a constant number of words and count the
|
||||||
|
// sum of the values of the words within the window. Then use the window that got the
|
||||||
|
// maximum sum. If there are multiple maximas, then get the last one.
|
||||||
|
// Enclose the terms in <b>.
|
||||||
|
function makeTeaser(body, terms) {
|
||||||
|
var TERM_WEIGHT = 40;
|
||||||
|
var NORMAL_WORD_WEIGHT = 2;
|
||||||
|
var FIRST_WORD_WEIGHT = 8;
|
||||||
|
var TEASER_MAX_WORDS = 30;
|
||||||
|
|
||||||
|
var stemmedTerms = terms.map(function (w) {
|
||||||
|
return elasticlunr.stemmer(w.toLowerCase());
|
||||||
|
});
|
||||||
|
var termFound = false;
|
||||||
|
var index = 0;
|
||||||
|
var weighted = []; // contains elements of ["word", weight, index_in_document]
|
||||||
|
|
||||||
|
// split in sentences, then words
|
||||||
|
var sentences = body.toLowerCase().split(". ");
|
||||||
|
|
||||||
|
for (var i in sentences) {
|
||||||
|
var words = sentences[i].split(" ");
|
||||||
|
var value = FIRST_WORD_WEIGHT;
|
||||||
|
|
||||||
|
for (var j in words) {
|
||||||
|
var word = words[j];
|
||||||
|
|
||||||
|
if (word.length > 0) {
|
||||||
|
for (var k in stemmedTerms) {
|
||||||
|
if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {
|
||||||
|
value = TERM_WEIGHT;
|
||||||
|
termFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
weighted.push([word, value, index]);
|
||||||
|
value = NORMAL_WORD_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += word.length;
|
||||||
|
index += 1; // ' ' or '.' if last word in sentence
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1; // because we split at a two-char boundary '. '
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weighted.length === 0) {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
var windowWeights = [];
|
||||||
|
var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);
|
||||||
|
// We add a window with all the weights first
|
||||||
|
var curSum = 0;
|
||||||
|
for (var i = 0; i < windowSize; i++) {
|
||||||
|
curSum += weighted[i][1];
|
||||||
|
}
|
||||||
|
windowWeights.push(curSum);
|
||||||
|
|
||||||
|
for (var i = 0; i < weighted.length - windowSize; i++) {
|
||||||
|
curSum -= weighted[i][1];
|
||||||
|
curSum += weighted[i + windowSize][1];
|
||||||
|
windowWeights.push(curSum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't find the term, just pick the first window
|
||||||
|
var maxSumIndex = 0;
|
||||||
|
if (termFound) {
|
||||||
|
var maxFound = 0;
|
||||||
|
// backwards
|
||||||
|
for (var i = windowWeights.length - 1; i >= 0; i--) {
|
||||||
|
if (windowWeights[i] > maxFound) {
|
||||||
|
maxFound = windowWeights[i];
|
||||||
|
maxSumIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var teaser = [];
|
||||||
|
var startIndex = weighted[maxSumIndex][2];
|
||||||
|
for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) {
|
||||||
|
var word = weighted[i];
|
||||||
|
if (startIndex < word[2]) {
|
||||||
|
// missing text from index to start of `word`
|
||||||
|
teaser.push(body.substring(startIndex, word[2]));
|
||||||
|
startIndex = word[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// add <em/> around search terms
|
||||||
|
if (word[1] === TERM_WEIGHT) {
|
||||||
|
teaser.push("<b>");
|
||||||
|
}
|
||||||
|
startIndex = word[2] + word[0].length;
|
||||||
|
teaser.push(body.substring(word[2], startIndex));
|
||||||
|
|
||||||
|
if (word[1] === TERM_WEIGHT) {
|
||||||
|
teaser.push("</b>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
teaser.push("…");
|
||||||
|
return teaser.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatSearchResultItem(item, terms) {
|
||||||
|
var li = document.createElement("li");
|
||||||
|
li.classList.add("search-results__item");
|
||||||
|
li.innerHTML = `<a href="${item.ref}">${item.doc.title}</a>`;
|
||||||
|
li.innerHTML += `<div class="search-results__teaser">${makeTeaser(item.doc.body, terms)}</div>`;
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go from the book view to the search view
|
||||||
|
function toggleSearchMode() {
|
||||||
|
var $bookContent = document.querySelector(".book-content");
|
||||||
|
var $searchContainer = document.querySelector(".search-container");
|
||||||
|
if ($searchContainer.classList.contains("search-container--is-visible")) {
|
||||||
|
$searchContainer.classList.remove("search-container--is-visible");
|
||||||
|
document.body.classList.remove("search-mode");
|
||||||
|
$bookContent.style.display = "block";
|
||||||
|
} else {
|
||||||
|
$searchContainer.classList.add("search-container--is-visible");
|
||||||
|
document.body.classList.add("search-mode");
|
||||||
|
$bookContent.style.display = "none";
|
||||||
|
document.getElementById("search").focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSearch() {
|
||||||
|
var $searchInput = document.getElementById("search");
|
||||||
|
if (!$searchInput) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var $searchIcon = document.querySelector(".search-icon");
|
||||||
|
$searchIcon.addEventListener("click", toggleSearchMode);
|
||||||
|
|
||||||
|
var $searchResults = document.querySelector(".search-results");
|
||||||
|
var $searchResultsHeader = document.querySelector(".search-results__header");
|
||||||
|
var $searchResultsItems = document.querySelector(".search-results__items");
|
||||||
|
var MAX_ITEMS = 10;
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
bool: "AND",
|
||||||
|
fields: {
|
||||||
|
title: {boost: 2},
|
||||||
|
body: {boost: 1},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var currentTerm = "";
|
||||||
|
var index = elasticlunr.Index.load(window.searchIndex);
|
||||||
|
|
||||||
|
$searchInput.addEventListener("keyup", debounce(function() {
|
||||||
|
var term = $searchInput.value.trim();
|
||||||
|
if (term === currentTerm || !index) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$searchResults.style.display = term === "" ? "none" : "block";
|
||||||
|
$searchResultsItems.innerHTML = "";
|
||||||
|
if (term === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var results = index.search(term, options).filter(function (r) {
|
||||||
|
return r.doc.body !== "";
|
||||||
|
});
|
||||||
|
if (results.length === 0) {
|
||||||
|
$searchResultsHeader.innerText = `No search results for '${term}'.`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTerm = term;
|
||||||
|
$searchResultsHeader.innerText = `${results.length} search results for '${term}':`;
|
||||||
|
for (var i = 0; i < Math.min(results.length, MAX_ITEMS); i++) {
|
||||||
|
if (!results[i].doc.body) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// var item = document.createElement("li");
|
||||||
|
// item.innerHTML = formatSearchResultItem(results[i], term.split(" "));
|
||||||
|
console.log(results[i]);
|
||||||
|
$searchResultsItems.appendChild(formatSearchResultItem(results[i], term.split(" ")));
|
||||||
|
}
|
||||||
|
}, 150));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === "complete" ||
|
||||||
|
(document.readyState !== "loading" && !document.documentElement.doScroll)
|
||||||
|
) {
|
||||||
|
initToggleMenu();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
initToggleMenu();
|
||||||
|
initSearch();
|
||||||
|
});
|
||||||
|
}
|
130
templates/index.html
Normal file
130
templates/index.html
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
|
|
||||||
|
<!-- Enable responsiveness on mobile devices-->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
{% if page %}
|
||||||
|
{% if page.description %}
|
||||||
|
<meta name="description" content="{{ page.description }}" />
|
||||||
|
{% elif config.description %}
|
||||||
|
<meta name="description" content="{{ config.description }}" />
|
||||||
|
{% endif %}
|
||||||
|
{% elif config.description %}
|
||||||
|
<meta name="description" content="{{ config.description }}" />
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<title>{% block title %}{{ config.title }}{% endblock title %}</title>
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{% endblock js %}
|
||||||
|
|
||||||
|
<!-- CSS -->
|
||||||
|
{% block css %}
|
||||||
|
<link rel="stylesheet" href="{{ get_url(path="book.css") | safe }}">
|
||||||
|
{% endblock css %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
{% endblock extra_head %}
|
||||||
|
<script>
|
||||||
|
window.MathJax = {
|
||||||
|
tex: {
|
||||||
|
inlineMath: [['$', '$'], ['\\(', '\\)']]
|
||||||
|
},
|
||||||
|
svg: {
|
||||||
|
fontCache: 'global'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script async src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
|
||||||
|
<script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="menu">
|
||||||
|
{% block before_menu %}
|
||||||
|
{% endblock before_menu %}
|
||||||
|
<nav role="navigation">
|
||||||
|
<ul>
|
||||||
|
{% block menu %}
|
||||||
|
{% set index = get_section(path="_index.md") %}
|
||||||
|
{% for s in index.subsections %}
|
||||||
|
{% set subsection = get_section(path=s) %}
|
||||||
|
<li {% if current_path == subsection.path %}class="active"{% endif %}>
|
||||||
|
{% set chapter_num = loop.index %}
|
||||||
|
<a href="{{ subsection.permalink | safe }}">
|
||||||
|
{% if config.extra.book_number_chapters %}<strong>{{ chapter_num }}.</strong>{% endif %}
|
||||||
|
{{ subsection.title }}
|
||||||
|
</a>
|
||||||
|
{% if subsection.pages %}
|
||||||
|
<ul>
|
||||||
|
{% for page in subsection.pages %}
|
||||||
|
<li {% if current_path == page.path %}class="active"{% endif %}>
|
||||||
|
<a href="{{ page.permalink | safe }}">
|
||||||
|
{% if config.extra.book_number_chapters %}<strong>{{ chapter_num }}.{{ loop.index }}.</strong>{% endif %}
|
||||||
|
{{ page.title }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock menu %}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{% block after_menu %}
|
||||||
|
{% endblock after_menu %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page">
|
||||||
|
<div class="page__header">
|
||||||
|
<div class="menu-icon">
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
</div>
|
||||||
|
{% if config.build_search_index %}
|
||||||
|
<span class="search-icon">🔎</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="page__content">
|
||||||
|
{% if config.build_search_index %}
|
||||||
|
<div class="search-container">
|
||||||
|
<input id="search" type="search" placeholder="Search..">
|
||||||
|
<div class="search-results">
|
||||||
|
<div class="search-results__header"></div>
|
||||||
|
<ul class="search-results__items"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="book-content">
|
||||||
|
{% block content %}
|
||||||
|
{% endblock content %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="prev-link">
|
||||||
|
{% block prev_link %}
|
||||||
|
{% endblock prev_link %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="next-link">
|
||||||
|
{% block next_link %}
|
||||||
|
{% endblock next_link %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block js_body %}
|
||||||
|
{% if config.build_search_index %}
|
||||||
|
<script type="text/javascript" src="{{ get_url(path="elasticlunr.min.js") | safe }}"></script>
|
||||||
|
<script type="text/javascript" src="{{ get_url(path="search_index.en.js") | safe }}"></script>
|
||||||
|
{% endif %}
|
||||||
|
<script type="text/javascript" src="{{ get_url(path="book.js") | safe }}"></script>
|
||||||
|
{% endblock js_body %}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
40
templates/page.html
Normal file
40
templates/page.html
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{% extends "index.html" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{{ page.title }}</h1>
|
||||||
|
{{ page.content | safe }}
|
||||||
|
{% endblock content %}
|
||||||
|
|
||||||
|
{% block prev_link %}
|
||||||
|
{% if page.smaller %}
|
||||||
|
<a class="previous" href="{{ page.smaller.permalink | safe }}"><</a>
|
||||||
|
{% else %}
|
||||||
|
{# No page before, find the link for the section it's in if there is one #}
|
||||||
|
{% set parent = get_section(path=page.ancestors | reverse | first) %}
|
||||||
|
<a class="previous" href="{{ parent.permalink | safe }}"><</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock prev_link %}
|
||||||
|
|
||||||
|
{% block next_link %}
|
||||||
|
{% if page.higher %}
|
||||||
|
<a class="next" href="{{ page.higher.permalink | safe }}">></a>
|
||||||
|
{% else %}
|
||||||
|
{# No page after, find the link for the following section #}
|
||||||
|
{% set index = get_section(path="_index.md") %}
|
||||||
|
{% set found_current = false %}
|
||||||
|
{% for s in index.subsections %}
|
||||||
|
{% set subsection = get_section(path=s) %}
|
||||||
|
{% if found_current %}
|
||||||
|
<a class="next" href="{{ subsection.permalink | safe }}">></a>
|
||||||
|
{# no break #}
|
||||||
|
{% set_global found_current = false %}
|
||||||
|
{% endif %}
|
||||||
|
{% for p in subsection.pages %}
|
||||||
|
{% if p.permalink == page.permalink %}
|
||||||
|
{% set_global found_current = true %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock next_link %}
|
52
templates/section.html
Normal file
52
templates/section.html
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{% extends "index.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{{ section.title }}</h1>
|
||||||
|
{{ section.content | safe }}
|
||||||
|
{% endblock content %}
|
||||||
|
|
||||||
|
{% block prev_link %}
|
||||||
|
{# need to find the last page of the previous section or the previous section directly
|
||||||
|
if there isn't any pages in it #}
|
||||||
|
{% set index = get_section(path="_index.md") %}
|
||||||
|
{% set found_current = false %}
|
||||||
|
{% for s in index.subsections | reverse %}
|
||||||
|
{% set subsection = get_section(path=s) %}
|
||||||
|
{% if subsection.permalink == section.permalink %}
|
||||||
|
{% set_global found_current = true %}
|
||||||
|
{% else %}
|
||||||
|
{% if found_current %}
|
||||||
|
{% if subsection.pages %}
|
||||||
|
{% set last_page = subsection.pages | last %}
|
||||||
|
<a class="previous" href="{{ last_page.permalink | safe }}"><</a>
|
||||||
|
{% else %}
|
||||||
|
<a class="previous" href="{{ subsection.permalink | safe }}"><</a>
|
||||||
|
{% endif %}
|
||||||
|
{# no break #}
|
||||||
|
{% set_global found_current = false %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock prev_link %}
|
||||||
|
|
||||||
|
{% block next_link %}
|
||||||
|
{% if section.pages %}
|
||||||
|
{% set next_page = section.pages | first %}
|
||||||
|
<a class="next" href="{{ next_page.permalink | safe }}">></a>
|
||||||
|
{% else %}
|
||||||
|
{# No page in the section, find the link for the following section #}
|
||||||
|
{% set index = get_section(path="_index.md") %}
|
||||||
|
{% set found_current = false %}
|
||||||
|
{% for s in index.subsections %}
|
||||||
|
{% set subsection = get_section(path=s) %}
|
||||||
|
{% if found_current %}
|
||||||
|
<a class="next" href="{{ subsection.permalink | safe }}">></a>
|
||||||
|
{# no break #}
|
||||||
|
{% set_global found_current = false %}
|
||||||
|
{% endif %}
|
||||||
|
{% if subsection.permalink == section.permalink %}
|
||||||
|
{% set_global found_current = true %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock next_link %}
|
13
theme.toml
Normal file
13
theme.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
name = "book"
|
||||||
|
description = "A book theme inspired from GitBook/mdBook"
|
||||||
|
license = "MIT"
|
||||||
|
homepage = "https://github.com/getzola/book"
|
||||||
|
min_version = "0.17.0"
|
||||||
|
demo = "https://getzola.github.io/book/"
|
||||||
|
|
||||||
|
[extra]
|
||||||
|
book_number_chapters = true
|
||||||
|
|
||||||
|
[author]
|
||||||
|
name = "Vincent Prouillet"
|
||||||
|
homepage = "https://www.vincentprouillet.com"
|
Loading…
Reference in a new issue