mirror of
https://github.com/explosion/spaCy.git
synced 2024-12-25 17:36:30 +03:00
Merge branch 'master' into space_head_bug
This commit is contained in:
commit
d328e0b4a8
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -73,6 +73,11 @@ htmlcov/
|
|||
nosetests.xml
|
||||
coverage.xml
|
||||
|
||||
# Website
|
||||
website/www/
|
||||
website/demos/displacy/
|
||||
website/demos/sense2vec/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
|
@ -88,11 +93,6 @@ coverage.xml
|
|||
*.log
|
||||
*.pot
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
docs/_themes/
|
||||
setup.py
|
||||
|
||||
# Windows local helper files
|
||||
*.bat
|
||||
|
||||
|
|
|
@ -43,7 +43,3 @@ Supports
|
|||
* OSX
|
||||
* Linux
|
||||
* Windows (Cygwin, MinGW, Visual Studio)
|
||||
|
||||
Difficult to support:
|
||||
|
||||
* PyPy
|
||||
|
|
|
@ -13,7 +13,7 @@ Requires:
|
|||
* WordNet
|
||||
* words.sgt.prob --- Smoothed unigram probabilities
|
||||
* clusters.txt --- Output of hierarchical clustering, e.g. Brown clusters
|
||||
* vectors.tgz --- output of something like word2vec
|
||||
* vectors.bz2 --- output of something like word2vec, compressed with bzip
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
@ -98,7 +98,7 @@ def _read_probs(loc):
|
|||
return probs, probs['-OOV-']
|
||||
|
||||
|
||||
def _read_freqs(loc, max_length=100, min_doc_freq=0, min_freq=200):
|
||||
def _read_freqs(loc, max_length=100, min_doc_freq=5, min_freq=200):
|
||||
if not loc.exists():
|
||||
print("Warning: Frequencies file not found")
|
||||
return {}, 0.0
|
||||
|
@ -109,7 +109,7 @@ def _read_freqs(loc, max_length=100, min_doc_freq=0, min_freq=200):
|
|||
else:
|
||||
file_ = loc.open()
|
||||
for i, line in enumerate(file_):
|
||||
freq, doc_freq, key = line.split('\t', 2)
|
||||
freq, doc_freq, key = line.rstrip().split('\t', 2)
|
||||
freq = int(freq)
|
||||
counts.inc(i+1, freq)
|
||||
total += freq
|
||||
|
@ -121,15 +121,13 @@ def _read_freqs(loc, max_length=100, min_doc_freq=0, min_freq=200):
|
|||
file_ = loc.open()
|
||||
probs = {}
|
||||
for line in file_:
|
||||
freq, doc_freq, key = line.split('\t', 2)
|
||||
freq, doc_freq, key = line.rstrip().split('\t', 2)
|
||||
doc_freq = int(doc_freq)
|
||||
freq = int(freq)
|
||||
if doc_freq >= min_doc_freq and freq >= min_freq and len(key) < max_length:
|
||||
# word = literal_eval(key)
|
||||
word = key
|
||||
word = literal_eval(key)
|
||||
smooth_count = counts.smoother(int(freq))
|
||||
log_smooth_count = math.log(smooth_count)
|
||||
probs[word] = log_smooth_count - log_total
|
||||
probs[word] = math.log(smooth_count) - log_total
|
||||
oov_prob = math.log(counts.smoother(0)) - log_total
|
||||
return probs, oov_prob
|
||||
|
||||
|
@ -157,7 +155,7 @@ def setup_vocab(get_lex_attr, tag_map, src_dir, dst_dir):
|
|||
if not dst_dir.exists():
|
||||
dst_dir.mkdir()
|
||||
|
||||
vectors_src = src_dir / 'vectors.tgz'
|
||||
vectors_src = src_dir / 'vectors.bz2'
|
||||
if vectors_src.exists():
|
||||
write_binary_vectors(str(vectors_src), str(dst_dir / 'vec.bin'))
|
||||
else:
|
||||
|
@ -166,7 +164,7 @@ def setup_vocab(get_lex_attr, tag_map, src_dir, dst_dir):
|
|||
clusters = _read_clusters(src_dir / 'clusters.txt')
|
||||
probs, oov_prob = _read_probs(src_dir / 'words.sgt.prob')
|
||||
if not probs:
|
||||
probs, oov_prob = _read_freqs(src_dir / 'freqs.txt')
|
||||
probs, oov_prob = _read_freqs(src_dir / 'freqs.txt.gz')
|
||||
if not probs:
|
||||
oov_prob = -20
|
||||
else:
|
||||
|
|
|
@ -141,7 +141,7 @@ def train(Language, gold_tuples, model_dir, n_iter=15, feat_set=u'basic',
|
|||
nlp.tagger(tokens)
|
||||
gold = GoldParse(tokens, annot_tuples)
|
||||
if not gold.is_projective:
|
||||
raise Exception("Non-projective sentence in training: %s" % annot_tuples)
|
||||
raise Exception("Non-projective sentence in training: %s" % annot_tuples[1])
|
||||
loss += nlp.parser.train(tokens, gold)
|
||||
nlp.entity.train(tokens, gold)
|
||||
nlp.tagger.train(tokens, gold.tags)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import inventoryCount as mainModule
|
||||
import os
|
||||
from spacy.en import English, LOCAL_DATA_DIR
|
||||
data_dir = os.environ.get('SPACY_DATA', LOCAL_DATA_DIR)
|
||||
from spacy.en import English
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""
|
||||
|
|
|
@ -11,49 +11,48 @@ token_properties = {
|
|||
"are": {"L": "be", "pos": "VBP", "number": 2},
|
||||
"ca": {"L": "can", "pos": "MD"},
|
||||
"can": {"L": "can", "pos": "MD"},
|
||||
"could": {"pos": "MD"}, # no lemma for could?
|
||||
"could": {"pos": "MD", "L": "could"},
|
||||
"'d": {"L": "would", "pos": "MD"},
|
||||
"did": {"L": "do", "pos": "VBD"},
|
||||
"do": {"L": "do"}, # no POS for do?
|
||||
"do": {"L": "do"},
|
||||
"does": {"L": "do", "pos": "VBZ"},
|
||||
"had": {"L": "have", "pos": "VBD"},
|
||||
"has": {}, # no POS or lemma for has?
|
||||
"have": {"pos": "VB"}, # no lemma for have?
|
||||
"he": {"L": "-PRON-"}, # no POS for he?
|
||||
"how": {}, # no POS or lemma for how?
|
||||
"i": {"L": "-PRON-"}, # no POS for i?
|
||||
"has": {"L": "have", "pos": "VBZ"},
|
||||
"have": {"pos": "VB"},
|
||||
"he": {"L": "-PRON-", "pos": "PRP"},
|
||||
"how": {},
|
||||
"i": {"L": "-PRON-", "pos": "PRP"},
|
||||
"is": {"L": "be", "pos": "VBZ"},
|
||||
"it": {"L": "-PRON-"}, # no POS for it?
|
||||
"it": {"L": "-PRON-", "pos": "PRP"},
|
||||
"'ll": {"L": "will", "pos": "MD"},
|
||||
"'m": {"L": "be", "pos": "VBP", "number": 1, "tenspect": 1},
|
||||
"'ma": {}, # no POS or lemma for ma?
|
||||
"might": {}, # no POS or lemma for might?
|
||||
"must": {}, # no POS or lemma for must?
|
||||
"need": {}, # no POS or lemma for need?
|
||||
"'ma": {},
|
||||
"might": {},
|
||||
"must": {},
|
||||
"need": {},
|
||||
"not": {"L": "not", "pos": "RB"},
|
||||
"'nt": {"L": "not", "pos": "RB"},
|
||||
"n't": {"L": "not", "pos": "RB"},
|
||||
"'re": {}, # no POS or lemma for re?
|
||||
"'re": {"L": "be", "pos": "VBZ"},
|
||||
"'s": {}, # no POS or lemma for s?
|
||||
"sha": {}, # no POS or lemma for sha?
|
||||
"she": {"L": "-PRON-"}, # no POS for she?
|
||||
"should": {}, # no POS or lemma for should?
|
||||
"that": {}, # no POS or lemma for that?
|
||||
"there": {}, # no POS or lemma for there?
|
||||
"they": {"L": "-PRON-"}, # no POS for they?
|
||||
"was": {}, # no POS or lemma for was?
|
||||
"we": {}, # no POS or lemma for we?
|
||||
"were": {}, # no POS or lemma for were?
|
||||
"what": {}, # no POS or lemma for what?
|
||||
"when": {}, # no POS or lemma for when?
|
||||
"where": {}, # no POS or lemma for where?
|
||||
"who": {}, # no POS or lemma for who?
|
||||
"why": {}, # no POS or lemma for why?
|
||||
"wo": {}, # no POS or lemma for wo?
|
||||
"would": {}, # no POS or lemma for would?
|
||||
"you": {"L": "-PRON-"}, # no POS or lemma for you?
|
||||
"sha": {"L": "shall", "pos": "MD"},
|
||||
"she": {"L": "-PRON-", "pos": "PRP"},
|
||||
"should": {},
|
||||
"that": {},
|
||||
"there": {},
|
||||
"they": {"L": "-PRON-", "pos": "PRP"},
|
||||
"was": {},
|
||||
"we": {"L": "-PRON-", "pos": "PRP"},
|
||||
"were": {},
|
||||
"what": {},
|
||||
"when": {},
|
||||
"where": {},
|
||||
"who": {},
|
||||
"why": {},
|
||||
"wo": {},
|
||||
"would": {},
|
||||
"you": {"L": "-PRON-", "pos": "PRP"},
|
||||
"'ve": {"L": "have", "pos": "VB"}
|
||||
|
||||
}
|
||||
|
||||
# contains starting tokens with their potential contractions
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
\.\.\.
|
||||
(?<=[a-z])\.(?=[A-Z])
|
||||
(?<=[a-zA-Z])-(?=[a-zA-z])
|
||||
(?<=[a-zA-Z])--(?=[a-zA-z])
|
||||
(?<=[0-9])-(?=[0-9])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "en",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "english test model",
|
||||
"license": "public domain",
|
||||
"include": [
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
cython
|
||||
cython < 0.24
|
||||
pathlib
|
||||
numpy
|
||||
cymem>=1.30,<1.32
|
||||
|
|
7
setup.py
7
setup.py
|
@ -17,6 +17,7 @@ PACKAGES = [
|
|||
'spacy',
|
||||
'spacy.tokens',
|
||||
'spacy.en',
|
||||
'spacy.de',
|
||||
'spacy.serialize',
|
||||
'spacy.syntax',
|
||||
'spacy.munge',
|
||||
|
@ -63,14 +64,15 @@ MOD_NAMES = [
|
|||
'spacy.cfile',
|
||||
'spacy.matcher',
|
||||
'spacy.syntax.ner',
|
||||
'spacy.symbols']
|
||||
'spacy.symbols',
|
||||
'spacy.syntax.iterators']
|
||||
|
||||
|
||||
# By subclassing build_extensions we have the actual compiler that will be used
|
||||
# which is really known only after finalize_options
|
||||
# http://stackoverflow.com/questions/724664/python-distutils-how-to-get-a-compiler-that-is-going-to-be-used
|
||||
compile_options = {
|
||||
'msvc': ['/Ox', '/EHsc'],
|
||||
'msvc': ['/Ox', '/EHsc', '/openmp'],
|
||||
'mingw32' : ['-O3', '-Wno-strict-prototypes', '-Wno-unused-function'],
|
||||
'other' : ['-O3', '-Wno-strict-prototypes', '-Wno-unused-function']
|
||||
}
|
||||
|
@ -213,3 +215,4 @@ def setup_package():
|
|||
|
||||
if __name__ == '__main__':
|
||||
setup_package()
|
||||
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
from . import util
|
||||
from .util import set_lang_class, get_lang_class, get_package, get_package_by_name
|
||||
|
||||
from .en import English
|
||||
from .de import German
|
||||
|
||||
|
||||
set_lang_class(English.lang, English)
|
||||
set_lang_class(German.lang, German)
|
||||
|
||||
|
||||
def load(name, vectors=None, via=None):
|
||||
return English(
|
||||
package=util.get_package_by_name(name, via=via),
|
||||
vectors_package=util.get_package_by_name(vectors, via=via))
|
||||
package = get_package_by_name(name, via=via)
|
||||
vectors_package = get_package_by_name(vectors, via=via)
|
||||
cls = get_lang_class(name)
|
||||
return cls(package=package, vectors_package=vectors_package)
|
||||
|
|
|
@ -4,10 +4,14 @@
|
|||
# https://github.com/pypa/warehouse/blob/master/warehouse/__about__.py
|
||||
|
||||
__title__ = 'spacy'
|
||||
__version__ = '0.100.6'
|
||||
__version__ = '0.100.7'
|
||||
__summary__ = 'Industrial-strength NLP'
|
||||
__uri__ = 'https://spacy.io'
|
||||
__author__ = 'Matthew Honnibal'
|
||||
__email__ = 'matt@spacy.io'
|
||||
__license__ = 'MIT'
|
||||
__default_model__ = 'en>=1.0.0,<1.1.0'
|
||||
__models__ = {
|
||||
'en': 'en>=1.1.0,<1.2.0',
|
||||
'de': 'de>=1.0.0,<1.1.0',
|
||||
}
|
||||
__default_lang__ = 'en'
|
||||
|
|
|
@ -14,12 +14,12 @@ cpdef enum attr_id_t:
|
|||
LIKE_EMAIL
|
||||
IS_STOP
|
||||
IS_OOV
|
||||
|
||||
FLAG14 = 14
|
||||
FLAG15
|
||||
FLAG16
|
||||
FLAG17
|
||||
FLAG18
|
||||
IS_BRACKET
|
||||
IS_QUOTE
|
||||
IS_LEFT_PUNCT
|
||||
IS_RIGHT_PUNCT
|
||||
|
||||
FLAG18 = 18
|
||||
FLAG19
|
||||
FLAG20
|
||||
FLAG21
|
||||
|
@ -85,11 +85,7 @@ cpdef enum attr_id_t:
|
|||
HEAD
|
||||
SPACY
|
||||
PROB
|
||||
|
||||
LANG
|
||||
|
||||
# Move these up to FLAG14--FLAG18 once we finish the functionality and
|
||||
# are ready to regenerate the model
|
||||
#IS_BRACKET
|
||||
#IS_QUOTE
|
||||
#IS_LEFT_PUNCT
|
||||
#IS_RIGHT_PUNCT
|
||||
|
||||
|
|
|
@ -13,10 +13,10 @@ IDS = {
|
|||
"LIKE_EMAIL": LIKE_EMAIL,
|
||||
"IS_STOP": IS_STOP,
|
||||
"IS_OOV": IS_OOV,
|
||||
"FLAG14": FLAG14,
|
||||
"FLAG15": FLAG15,
|
||||
"FLAG16": FLAG16,
|
||||
"FLAG17": FLAG17,
|
||||
"IS_BRACKET": IS_BRACKET,
|
||||
"IS_QUOTE": IS_QUOTE,
|
||||
"IS_LEFT_PUNCT": IS_LEFT_PUNCT,
|
||||
"IS_RIGHT_PUNCT": IS_RIGHT_PUNCT,
|
||||
"FLAG18": FLAG18,
|
||||
"FLAG19": FLAG19,
|
||||
"FLAG20": FLAG20,
|
||||
|
@ -83,6 +83,7 @@ IDS = {
|
|||
"HEAD": HEAD,
|
||||
"SPACY": SPACY,
|
||||
"PROB": PROB,
|
||||
"LANG": LANG,
|
||||
}
|
||||
|
||||
# ATTR IDs, in order of the symbol
|
||||
|
|
13
spacy/de/download.py
Normal file
13
spacy/de/download.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
import plac
|
||||
from ..download import download
|
||||
|
||||
|
||||
@plac.annotations(
|
||||
force=("Force overwrite", "flag", "f", bool),
|
||||
)
|
||||
def main(data_size='all', force=False):
|
||||
download('de', force)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
plac.call(main)
|
33
spacy/download.py
Normal file
33
spacy/download.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
||||
import sputnik
|
||||
from sputnik.package_list import (PackageNotFoundException,
|
||||
CompatiblePackageNotFoundException)
|
||||
|
||||
from . import about
|
||||
|
||||
|
||||
def download(lang, force=False):
|
||||
if force:
|
||||
sputnik.purge(about.__title__, about.__version__)
|
||||
|
||||
try:
|
||||
sputnik.package(about.__title__, about.__version__, about.__models__[lang])
|
||||
print("Model already installed. Please run 'python -m "
|
||||
"spacy.%s.download --force' to reinstall." % lang, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except (PackageNotFoundException, CompatiblePackageNotFoundException):
|
||||
pass
|
||||
|
||||
package = sputnik.install(about.__title__, about.__version__, about.__models__[lang])
|
||||
|
||||
try:
|
||||
sputnik.package(about.__title__, about.__version__, about.__models__[lang])
|
||||
except (PackageNotFoundException, CompatiblePackageNotFoundException):
|
||||
print("Model failed to install. Please run 'python -m "
|
||||
"spacy.%s.download --force'." % lang, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print("Model successfully installed.", file=sys.stderr)
|
|
@ -33,10 +33,6 @@ your yours yourself yourselves
|
|||
STOPWORDS = set(w for w in STOPWORDS.split() if w)
|
||||
|
||||
|
||||
# This is deprecated as of v100
|
||||
LOCAL_DATA_DIR = path.join(path.dirname(__file__), 'data')
|
||||
|
||||
|
||||
class English(Language):
|
||||
lang = 'en'
|
||||
|
||||
|
|
|
@ -1,57 +1,12 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import plac
|
||||
import sputnik
|
||||
from sputnik.package_list import (PackageNotFoundException,
|
||||
CompatiblePackageNotFoundException)
|
||||
|
||||
from .. import about
|
||||
|
||||
|
||||
def migrate(path):
|
||||
data_path = os.path.join(path, 'data')
|
||||
if os.path.isdir(data_path):
|
||||
if os.path.islink(data_path):
|
||||
os.unlink(data_path)
|
||||
else:
|
||||
shutil.rmtree(data_path)
|
||||
for filename in os.listdir(path):
|
||||
if filename.endswith('.tgz'):
|
||||
os.unlink(os.path.join(path, filename))
|
||||
from ..download import download
|
||||
|
||||
|
||||
@plac.annotations(
|
||||
force=("Force overwrite", "flag", "f", bool),
|
||||
)
|
||||
def main(data_size='all', force=False):
|
||||
if force:
|
||||
sputnik.purge(about.__title__, about.__version__)
|
||||
|
||||
try:
|
||||
sputnik.package(about.__title__, about.__version__, about.__default_model__)
|
||||
print("Model already installed. Please run 'python -m "
|
||||
"spacy.en.download --force' to reinstall.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except (PackageNotFoundException, CompatiblePackageNotFoundException):
|
||||
pass
|
||||
|
||||
package = sputnik.install(about.__title__, about.__version__, about.__default_model__)
|
||||
|
||||
try:
|
||||
sputnik.package(about.__title__, about.__version__, about.__default_model__)
|
||||
except (PackageNotFoundException, CompatiblePackageNotFoundException):
|
||||
print("Model failed to install. Please run 'python -m "
|
||||
"spacy.en.download --force'.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# FIXME clean up old-style packages
|
||||
migrate(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
print("Model successfully installed.", file=sys.stderr)
|
||||
download('en', force)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -33,10 +33,6 @@ class Language(object):
|
|||
@staticmethod
|
||||
def norm(string):
|
||||
return string
|
||||
|
||||
@staticmethod
|
||||
def shape(string):
|
||||
return orth.word_shape(string)
|
||||
|
||||
@staticmethod
|
||||
def prefix(string):
|
||||
|
@ -50,66 +46,14 @@ class Language(object):
|
|||
def cluster(string):
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def is_alpha(string):
|
||||
return orth.is_alpha(string)
|
||||
|
||||
@staticmethod
|
||||
def is_ascii(string):
|
||||
return orth.is_ascii(string)
|
||||
|
||||
@staticmethod
|
||||
def is_digit(string):
|
||||
return string.isdigit()
|
||||
|
||||
@staticmethod
|
||||
def is_lower(string):
|
||||
return orth.is_lower(string)
|
||||
|
||||
@staticmethod
|
||||
def is_punct(string):
|
||||
return orth.is_punct(string)
|
||||
|
||||
@staticmethod
|
||||
def is_space(string):
|
||||
return string.isspace()
|
||||
|
||||
@staticmethod
|
||||
def is_title(string):
|
||||
return orth.is_title(string)
|
||||
|
||||
@staticmethod
|
||||
def is_bracket(string):
|
||||
return orth.is_bracket(string)
|
||||
|
||||
@staticmethod
|
||||
def is_quote(string):
|
||||
return orth.is_quote(string)
|
||||
|
||||
@staticmethod
|
||||
def is_left_punct(string):
|
||||
return orth.is_left_punct(string)
|
||||
|
||||
@staticmethod
|
||||
def is_right_punct(string):
|
||||
return orth.is_right_punct(string)
|
||||
|
||||
@staticmethod
|
||||
def is_upper(string):
|
||||
return orth.is_upper(string)
|
||||
|
||||
@staticmethod
|
||||
def like_url(string):
|
||||
return orth.like_url(string)
|
||||
|
||||
@staticmethod
|
||||
def like_num(string):
|
||||
return orth.like_number(string)
|
||||
|
||||
@staticmethod
|
||||
def like_email(string):
|
||||
return orth.like_email(string)
|
||||
|
||||
@staticmethod
|
||||
def is_stop(string):
|
||||
return 0
|
||||
|
@ -120,26 +64,27 @@ class Language(object):
|
|||
return {
|
||||
attrs.LOWER: cls.lower,
|
||||
attrs.NORM: cls.norm,
|
||||
attrs.SHAPE: cls.shape,
|
||||
attrs.SHAPE: orth.word_shape,
|
||||
attrs.PREFIX: cls.prefix,
|
||||
attrs.SUFFIX: cls.suffix,
|
||||
attrs.CLUSTER: cls.cluster,
|
||||
attrs.PROB: lambda string: oov_prob,
|
||||
attrs.IS_ALPHA: cls.is_alpha,
|
||||
attrs.IS_ASCII: cls.is_ascii,
|
||||
attrs.LANG: lambda string: cls.lang,
|
||||
attrs.IS_ALPHA: orth.is_alpha,
|
||||
attrs.IS_ASCII: orth.is_ascii,
|
||||
attrs.IS_DIGIT: cls.is_digit,
|
||||
attrs.IS_LOWER: cls.is_lower,
|
||||
attrs.IS_PUNCT: cls.is_punct,
|
||||
attrs.IS_LOWER: orth.is_lower,
|
||||
attrs.IS_PUNCT: orth.is_punct,
|
||||
attrs.IS_SPACE: cls.is_space,
|
||||
attrs.IS_TITLE: cls.is_title,
|
||||
attrs.IS_UPPER: cls.is_upper,
|
||||
attrs.FLAG14: cls.is_bracket,
|
||||
attrs.FLAG15: cls.is_quote,
|
||||
attrs.FLAG16: cls.is_left_punct,
|
||||
attrs.FLAG17: cls.is_right_punct,
|
||||
attrs.LIKE_URL: cls.like_url,
|
||||
attrs.LIKE_NUM: cls.like_num,
|
||||
attrs.LIKE_EMAIL: cls.like_email,
|
||||
attrs.IS_TITLE: orth.is_title,
|
||||
attrs.IS_UPPER: orth.is_upper,
|
||||
attrs.IS_BRACKET: orth.is_bracket,
|
||||
attrs.IS_QUOTE: orth.is_quote,
|
||||
attrs.IS_LEFT_PUNCT: orth.is_left_punct,
|
||||
attrs.IS_RIGHT_PUNCT: orth.is_right_punct,
|
||||
attrs.LIKE_URL: orth.like_url,
|
||||
attrs.LIKE_NUM: orth.like_number,
|
||||
attrs.LIKE_EMAIL: orth.like_email,
|
||||
attrs.IS_STOP: cls.is_stop,
|
||||
attrs.IS_OOV: lambda string: True
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from .typedefs cimport attr_t, hash_t, flags_t, len_t, tag_t
|
||||
from .attrs cimport attr_id_t
|
||||
from .attrs cimport ID, ORTH, LOWER, NORM, SHAPE, PREFIX, SUFFIX, LENGTH, CLUSTER
|
||||
from .attrs cimport ID, ORTH, LOWER, NORM, SHAPE, PREFIX, SUFFIX, LENGTH, CLUSTER, LANG
|
||||
|
||||
from .structs cimport LexemeC
|
||||
from .strings cimport StringStore
|
||||
|
@ -41,6 +41,8 @@ cdef class Lexeme:
|
|||
lex.suffix = value
|
||||
elif name == CLUSTER:
|
||||
lex.cluster = value
|
||||
elif name == LANG:
|
||||
lex.lang = value
|
||||
|
||||
@staticmethod
|
||||
cdef inline attr_t get_struct_attr(const LexemeC* lex, attr_id_t feat_name) nogil:
|
||||
|
@ -67,6 +69,8 @@ cdef class Lexeme:
|
|||
return lex.length
|
||||
elif feat_name == CLUSTER:
|
||||
return lex.cluster
|
||||
elif feat_name == LANG:
|
||||
return lex.lang
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
|
|
@ -18,10 +18,10 @@ import numpy
|
|||
|
||||
from .attrs cimport IS_ALPHA, IS_ASCII, IS_DIGIT, IS_LOWER, IS_PUNCT, IS_SPACE
|
||||
from .attrs cimport IS_TITLE, IS_UPPER, LIKE_URL, LIKE_NUM, LIKE_EMAIL, IS_STOP
|
||||
from .attrs cimport FLAG14 as IS_BRACKET
|
||||
from .attrs cimport FLAG15 as IS_QUOTE
|
||||
from .attrs cimport FLAG16 as IS_LEFT_PUNCT
|
||||
from .attrs cimport FLAG17 as IS_RIGHT_PUNCT
|
||||
from .attrs cimport IS_BRACKET
|
||||
from .attrs cimport IS_QUOTE
|
||||
from .attrs cimport IS_LEFT_PUNCT
|
||||
from .attrs cimport IS_RIGHT_PUNCT
|
||||
from .attrs cimport IS_OOV
|
||||
|
||||
|
||||
|
@ -74,8 +74,8 @@ cdef class Lexeme:
|
|||
raise ValueError(
|
||||
"Word vectors set to length 0. This may be because the "
|
||||
"data is not installed. If you haven't already, run"
|
||||
"\npython -m spacy.en.download all\n"
|
||||
"to install the data."
|
||||
"\npython -m spacy.%s.download all\n"
|
||||
"to install the data." % self.vocab.lang
|
||||
)
|
||||
|
||||
vector_view = <float[:length,]>self.c.vector
|
||||
|
@ -123,6 +123,10 @@ cdef class Lexeme:
|
|||
def __get__(self): return self.c.cluster
|
||||
def __set__(self, int x): self.c.cluster = x
|
||||
|
||||
property lang:
|
||||
def __get__(self): return self.c.lang
|
||||
def __set__(self, int x): self.c.lang = x
|
||||
|
||||
property prob:
|
||||
def __get__(self): return self.c.prob
|
||||
def __set__(self, float x): self.c.prob = x
|
||||
|
@ -147,6 +151,10 @@ cdef class Lexeme:
|
|||
def __get__(self): return self.vocab.strings[self.c.suffix]
|
||||
def __set__(self, unicode x): self.c.suffix = self.vocab.strings[x]
|
||||
|
||||
property lang_:
|
||||
def __get__(self): return self.vocab.strings[self.c.lang]
|
||||
def __set__(self, unicode x): self.c.lang = self.vocab.strings[x]
|
||||
|
||||
property flags:
|
||||
def __get__(self): return self.c.flags
|
||||
def __set__(self, flags_t x): self.c.flags = x
|
||||
|
|
|
@ -5,9 +5,6 @@ import unicodedata
|
|||
import re
|
||||
|
||||
|
||||
TAGS = 'adj adp adv conj det noun num pdt pos pron prt punct verb'.upper().split()
|
||||
|
||||
|
||||
# Binary string features
|
||||
cpdef bint is_alpha(unicode string):
|
||||
return string.isalpha()
|
||||
|
@ -36,20 +33,25 @@ cpdef bint is_ascii(unicode string):
|
|||
else:
|
||||
return True
|
||||
|
||||
|
||||
cpdef bint is_bracket(unicode string):
|
||||
return False
|
||||
brackets = ('(',')','[',']','{','}','<','>')
|
||||
return string in brackets
|
||||
|
||||
|
||||
cpdef bint is_quote(unicode string):
|
||||
if string in ('"', "'"):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
quotes = ('"',"'",'`','«','»','‘','’','‚','‛','“','”','„','‟','‹','›','❮','❯',"''",'``')
|
||||
return string in quotes
|
||||
|
||||
|
||||
cpdef bint is_left_punct(unicode string):
|
||||
return False
|
||||
left_punct = ('(','[','{','<','"',"'",'«','‘','‚','‛','“','„','‟','‹','❮','``')
|
||||
return string in left_punct
|
||||
|
||||
|
||||
cpdef bint is_right_punct(unicode string):
|
||||
return False
|
||||
right_punct = (')',']','}','>','"',"'",'»','’','”','›','❯',"''")
|
||||
return string in right_punct
|
||||
|
||||
|
||||
cpdef bint is_title(unicode string):
|
||||
|
|
|
@ -24,3 +24,4 @@ cdef class StringStore:
|
|||
cdef int64_t _resize_at
|
||||
|
||||
cdef const Utf8Str* intern(self, unicode py_string) except NULL
|
||||
cdef const Utf8Str* _intern_utf8(self, char* utf8_string, int length) except NULL
|
||||
|
|
|
@ -1,30 +1,25 @@
|
|||
from __future__ import unicode_literals
|
||||
import codecs
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
cimport cython
|
||||
from libc.string cimport memcpy
|
||||
from libc.stdint cimport uint64_t
|
||||
|
||||
from murmurhash.mrmr cimport hash64
|
||||
|
||||
from preshed.maps cimport map_iter, key_t
|
||||
|
||||
from cpython cimport PyUnicode_AS_DATA
|
||||
from cpython cimport PyUnicode_GET_DATA_SIZE
|
||||
|
||||
from libc.stdint cimport int64_t
|
||||
|
||||
|
||||
from .typedefs cimport hash_t, attr_t
|
||||
|
||||
try:
|
||||
import codecs as io
|
||||
except ImportError:
|
||||
import io
|
||||
from .typedefs cimport hash_t
|
||||
|
||||
import ujson as json
|
||||
|
||||
|
||||
cpdef hash_t hash_string(unicode string) except 0:
|
||||
chars = string.encode('utf8')
|
||||
return hash64(<char*>chars, len(chars), 1)
|
||||
return _hash_utf8(chars, len(chars))
|
||||
|
||||
|
||||
cdef hash_t _hash_utf8(char* utf8_string, int length):
|
||||
return hash64(utf8_string, length, 1)
|
||||
|
||||
|
||||
cdef unicode _decode(const Utf8Str* string):
|
||||
|
@ -92,45 +87,45 @@ cdef class StringStore:
|
|||
|
||||
def __getitem__(self, object string_or_id):
|
||||
cdef bytes byte_string
|
||||
cdef unicode py_string
|
||||
cdef const Utf8Str* utf8str
|
||||
cdef unsigned int int_id
|
||||
|
||||
cdef int id_
|
||||
if isinstance(string_or_id, int) or isinstance(string_or_id, long):
|
||||
if string_or_id == 0:
|
||||
return u''
|
||||
elif string_or_id < 1 or string_or_id >= self.size:
|
||||
if isinstance(string_or_id, (int, long)):
|
||||
try:
|
||||
int_id = string_or_id
|
||||
except OverflowError:
|
||||
raise IndexError(string_or_id)
|
||||
utf8str = &self.c[<int>string_or_id]
|
||||
if int_id == 0:
|
||||
return u''
|
||||
elif int_id >= <uint64_t>self.size:
|
||||
raise IndexError(string_or_id)
|
||||
utf8str = &self.c[int_id]
|
||||
return _decode(utf8str)
|
||||
elif isinstance(string_or_id, bytes):
|
||||
if len(string_or_id) == 0:
|
||||
byte_string = <bytes>string_or_id
|
||||
if len(byte_string) == 0:
|
||||
return 0
|
||||
py_string = string_or_id.decode('utf8')
|
||||
utf8str = self.intern(py_string)
|
||||
utf8str = self._intern_utf8(byte_string, len(byte_string))
|
||||
return utf8str - self.c
|
||||
elif isinstance(string_or_id, unicode):
|
||||
if len(string_or_id) == 0:
|
||||
if len(<unicode>string_or_id) == 0:
|
||||
return 0
|
||||
py_string = string_or_id
|
||||
utf8str = self.intern(py_string)
|
||||
byte_string = (<unicode>string_or_id).encode('utf8')
|
||||
utf8str = self._intern_utf8(byte_string, len(byte_string))
|
||||
return utf8str - self.c
|
||||
else:
|
||||
raise TypeError(type(string_or_id))
|
||||
|
||||
def __contains__(self, unicode string):
|
||||
def __contains__(self, unicode string not None):
|
||||
if len(string) == 0:
|
||||
return True
|
||||
cdef hash_t key = hash_string(string)
|
||||
value = <Utf8Str*>self._map.get(key)
|
||||
return True if value is not NULL else False
|
||||
return self._map.get(key) is not NULL
|
||||
|
||||
def __iter__(self):
|
||||
cdef int i
|
||||
for i in range(self.size):
|
||||
if i == 0:
|
||||
yield u''
|
||||
else:
|
||||
utf8str = &self.c[i]
|
||||
yield _decode(utf8str)
|
||||
yield _decode(&self.c[i]) if i > 0 else u''
|
||||
|
||||
def __reduce__(self):
|
||||
strings = [""]
|
||||
|
@ -142,21 +137,26 @@ cdef class StringStore:
|
|||
|
||||
cdef const Utf8Str* intern(self, unicode py_string) except NULL:
|
||||
# 0 means missing, but we don't bother offsetting the index.
|
||||
cdef hash_t key = hash_string(py_string)
|
||||
cdef bytes byte_string = py_string.encode('utf8')
|
||||
return self._intern_utf8(byte_string, len(byte_string))
|
||||
|
||||
@cython.final
|
||||
cdef const Utf8Str* _intern_utf8(self, char* utf8_string, int length) except NULL:
|
||||
# 0 means missing, but we don't bother offsetting the index.
|
||||
cdef hash_t key = _hash_utf8(utf8_string, length)
|
||||
value = <Utf8Str*>self._map.get(key)
|
||||
if value != NULL:
|
||||
if value is not NULL:
|
||||
return value
|
||||
|
||||
if self.size == self._resize_at:
|
||||
self._realloc()
|
||||
cdef bytes byte_string = py_string.encode('utf8')
|
||||
self.c[self.size] = _allocate(self.mem, <unsigned char*>byte_string, len(byte_string))
|
||||
self.c[self.size] = _allocate(self.mem, <unsigned char*>utf8_string, length)
|
||||
self._map.set(key, <void*>&self.c[self.size])
|
||||
self.size += 1
|
||||
return &self.c[self.size-1]
|
||||
|
||||
def dump(self, file_):
|
||||
string_data = json.dumps([s for s in self])
|
||||
string_data = json.dumps(list(self))
|
||||
if not isinstance(string_data, unicode):
|
||||
string_data = string_data.decode('utf8')
|
||||
file_.write(string_data)
|
||||
|
@ -166,8 +166,10 @@ cdef class StringStore:
|
|||
if strings == ['']:
|
||||
return None
|
||||
cdef unicode string
|
||||
for string in strings:
|
||||
if string:
|
||||
for string in strings:
|
||||
# explicit None/len check instead of simple truth testing
|
||||
# (bug in Cython <= 0.23.4)
|
||||
if string is not None and len(string):
|
||||
self.intern(string)
|
||||
|
||||
def _realloc(self):
|
||||
|
|
|
@ -9,6 +9,8 @@ cdef struct LexemeC:
|
|||
|
||||
flags_t flags
|
||||
|
||||
attr_t lang
|
||||
|
||||
attr_t id
|
||||
attr_t length
|
||||
|
||||
|
|
19
spacy/syntax/iterators.pxd
Normal file
19
spacy/syntax/iterators.pxd
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
from spacy.tokens.doc cimport Doc
|
||||
|
||||
cdef dict CHUNKERS
|
||||
|
||||
cdef class DocIterator:
|
||||
cdef Doc _doc
|
||||
|
||||
cdef class EnglishNounChunks(DocIterator):
|
||||
cdef int i
|
||||
cdef int _np_label
|
||||
cdef set _np_deps
|
||||
cdef int _conjunct
|
||||
|
||||
cdef class GermanNounChunks(DocIterator):
|
||||
cdef int i
|
||||
cdef int _np_label
|
||||
cdef set _np_deps
|
||||
cdef int _close_app
|
84
spacy/syntax/iterators.pyx
Normal file
84
spacy/syntax/iterators.pyx
Normal file
|
@ -0,0 +1,84 @@
|
|||
from spacy.structs cimport TokenC
|
||||
from spacy.tokens.span cimport Span
|
||||
from spacy.tokens.doc cimport Doc
|
||||
from spacy.tokens.token cimport Token
|
||||
|
||||
from spacy.parts_of_speech cimport NOUN
|
||||
|
||||
CHUNKERS = {'en':EnglishNounChunks, 'de':GermanNounChunks}
|
||||
|
||||
# base class for document iterators
|
||||
cdef class DocIterator:
|
||||
def __init__(self, Doc doc):
|
||||
self._doc = doc
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
cdef class EnglishNounChunks(DocIterator):
|
||||
def __init__(self, Doc doc):
|
||||
super(EnglishNounChunks,self).__init__(doc)
|
||||
labels = ['nsubj', 'dobj', 'nsubjpass', 'pcomp', 'pobj', 'attr', 'root']
|
||||
self._np_label = self._doc.vocab.strings['NP']
|
||||
self._np_deps = set( self._doc.vocab.strings[label] for label in labels )
|
||||
self._conjunct = self._doc.vocab.strings['conj']
|
||||
self.i = 0
|
||||
|
||||
def __next__(self):
|
||||
cdef const TokenC* word
|
||||
cdef widx
|
||||
while self.i < self._doc.length:
|
||||
widx = self.i
|
||||
self.i += 1
|
||||
word = &self._doc.c[widx]
|
||||
if word.pos == NOUN:
|
||||
if word.dep in self._np_deps:
|
||||
return Span(self._doc, word.l_edge, widx+1, label=self._np_label)
|
||||
elif word.dep == self._conjunct:
|
||||
head = word+word.head
|
||||
while head.dep == self._conjunct and head.head < 0:
|
||||
head += head.head
|
||||
# If the head is an NP, and we're coordinated to it, we're an NP
|
||||
if head.dep in self._np_deps:
|
||||
return Span(self._doc, word.l_edge, widx+1, label=self._np_label)
|
||||
raise StopIteration
|
||||
|
||||
|
||||
# this iterator extracts spans headed by NOUNs starting from the left-most
|
||||
# syntactic dependent until the NOUN itself
|
||||
# for close apposition and measurement construction, the span is sometimes
|
||||
# extended to the right of the NOUN
|
||||
# example: "eine Tasse Tee" (a cup (of) tea) returns "eine Tasse Tee" and not
|
||||
# just "eine Tasse", same for "das Thema Familie"
|
||||
cdef class GermanNounChunks(DocIterator):
|
||||
def __init__(self, Doc doc):
|
||||
super(GermanNounChunks,self).__init__(doc)
|
||||
labels = ['sb', 'oa', 'da', 'nk', 'mo', 'ag', 'root', 'cj', 'pd', 'og', 'app']
|
||||
self._np_label = self._doc.vocab.strings['NP']
|
||||
self._np_deps = set( self._doc.vocab.strings[label] for label in labels )
|
||||
self._close_app = self._doc.vocab.strings['nk']
|
||||
self.i = 0
|
||||
|
||||
def __next__(self):
|
||||
cdef const TokenC* word
|
||||
cdef int rbracket
|
||||
cdef Token rdep
|
||||
cdef widx
|
||||
while self.i < self._doc.length:
|
||||
widx = self.i
|
||||
self.i += 1
|
||||
word = &self._doc.c[widx]
|
||||
if word.pos == NOUN and word.dep in self._np_deps:
|
||||
rbracket = widx+1
|
||||
# try to extend the span to the right
|
||||
# to capture close apposition/measurement constructions
|
||||
for rdep in self._doc[widx].rights:
|
||||
if rdep.pos == NOUN and rdep.dep == self._close_app:
|
||||
rbracket = rdep.i+1
|
||||
return Span(self._doc, word.l_edge, rbracket, label=self._np_label)
|
||||
raise StopIteration
|
||||
|
|
@ -47,6 +47,7 @@ from ._parse_features cimport fill_context
|
|||
from .stateclass cimport StateClass
|
||||
from ._state cimport StateC
|
||||
|
||||
from spacy.syntax.iterators cimport CHUNKERS, DocIterator, EnglishNounChunks, GermanNounChunks
|
||||
|
||||
|
||||
DEBUG = False
|
||||
|
@ -113,12 +114,9 @@ cdef class Parser:
|
|||
cdef int nr_feat = self.model.nr_feat
|
||||
with nogil:
|
||||
self.parseC(tokens.c, tokens.length, nr_feat, nr_class)
|
||||
tokens.is_parsed = True
|
||||
# Check for KeyboardInterrupt etc. Untested
|
||||
PyErr_CheckSignals()
|
||||
# projectivize output
|
||||
if self._projectivize:
|
||||
PseudoProjectivity.deprojectivize(tokens)
|
||||
self._finalize(tokens)
|
||||
|
||||
def pipe(self, stream, int batch_size=1000, int n_threads=2):
|
||||
cdef Pool mem = Pool()
|
||||
|
@ -144,7 +142,7 @@ cdef class Parser:
|
|||
raise ValueError("Error parsing doc: %s" % sent_str)
|
||||
PyErr_CheckSignals()
|
||||
for doc in queue:
|
||||
doc.is_parsed = True
|
||||
self._finalize(doc)
|
||||
yield doc
|
||||
queue = []
|
||||
batch_size = len(queue)
|
||||
|
@ -155,10 +153,19 @@ cdef class Parser:
|
|||
with gil:
|
||||
sent_str = queue[i].text
|
||||
raise ValueError("Error parsing doc: %s" % sent_str)
|
||||
for doc in queue:
|
||||
doc.is_parsed = True
|
||||
yield doc
|
||||
PyErr_CheckSignals()
|
||||
for doc in queue:
|
||||
self._finalize(doc)
|
||||
yield doc
|
||||
|
||||
def _finalize(self, Doc doc):
|
||||
# deprojectivize output
|
||||
if self._projectivize:
|
||||
PseudoProjectivity.deprojectivize(doc)
|
||||
# set annotation-specific iterators
|
||||
doc.noun_chunks = CHUNKERS.get(doc.vocab.lang,DocIterator)
|
||||
# mark doc as parsed
|
||||
doc.is_parsed = True
|
||||
|
||||
cdef int parseC(self, TokenC* tokens, int length, int nr_feat, int nr_class) nogil:
|
||||
cdef ExampleC eg
|
||||
|
|
|
@ -32,3 +32,18 @@ def test_email(en_tokenizer):
|
|||
assert len(tokens) == 1
|
||||
|
||||
|
||||
def test_double_hyphen(en_tokenizer):
|
||||
tokens = en_tokenizer(u'No decent--let alone well-bred--people.')
|
||||
assert tokens[0].text == u'No'
|
||||
assert tokens[1].text == u'decent'
|
||||
assert tokens[2].text == u'--'
|
||||
assert tokens[3].text == u'let'
|
||||
assert tokens[4].text == u'alone'
|
||||
assert tokens[5].text == u'well'
|
||||
assert tokens[6].text == u'-'
|
||||
# TODO: This points to a deeper issue with the tokenizer: it doesn't re-enter
|
||||
# on infixes.
|
||||
#assert tokens[7].text == u'bred'
|
||||
#assert tokens[8].text == u'--'
|
||||
#assert tokens[9].text == u'people'
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@ import numpy as np
|
|||
from spacy.attrs import HEAD, DEP
|
||||
from spacy.symbols import nsubj, dobj, punct, amod, nmod, conj, cc, root
|
||||
from spacy.en import English
|
||||
|
||||
from spacy.syntax.iterators import EnglishNounChunks
|
||||
|
||||
|
||||
def test_not_nested():
|
||||
nlp = English(parser=False)
|
||||
nlp = English(parser=False, entity=False)
|
||||
sent = u'''Peter has chronic command and control issues'''.strip()
|
||||
tokens = nlp(sent)
|
||||
tokens.from_array(
|
||||
|
@ -22,6 +22,7 @@ def test_not_nested():
|
|||
[-2, conj],
|
||||
[-5, dobj]
|
||||
], dtype='int32'))
|
||||
tokens.noun_chunks = EnglishNounChunks
|
||||
for chunk in tokens.noun_chunks:
|
||||
print(chunk.text)
|
||||
word_occurred = {}
|
||||
|
@ -31,3 +32,4 @@ def test_not_nested():
|
|||
word_occurred[word.text] += 1
|
||||
for word, freq in word_occurred.items():
|
||||
assert freq == 1, (word, [chunk.text for chunk in tokens.noun_chunks])
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@ cimport cython
|
|||
|
||||
from . import util
|
||||
from .tokens.doc cimport Doc
|
||||
from .util import read_lang_data
|
||||
from .util import get_package
|
||||
from .util import read_lang_data, get_package
|
||||
|
||||
|
||||
cdef class Tokenizer:
|
||||
|
|
|
@ -7,6 +7,8 @@ from ..structs cimport TokenC, LexemeC
|
|||
from ..typedefs cimport attr_t
|
||||
from ..attrs cimport attr_id_t
|
||||
|
||||
from spacy.syntax.iterators cimport DocIterator
|
||||
|
||||
|
||||
cdef attr_t get_token_attr(const TokenC* token, attr_id_t feat_name) nogil
|
||||
|
||||
|
@ -42,6 +44,8 @@ cdef class Doc:
|
|||
cdef int length
|
||||
cdef int max_length
|
||||
|
||||
cdef DocIterator noun_chunks_iterator
|
||||
|
||||
cdef int push_back(self, LexemeOrToken lex_or_tok, bint trailing_space) except -1
|
||||
|
||||
cpdef np.ndarray to_array(self, object features)
|
||||
|
|
|
@ -8,6 +8,7 @@ import struct
|
|||
cimport numpy as np
|
||||
import math
|
||||
import six
|
||||
import warnings
|
||||
|
||||
from ..lexeme cimport Lexeme
|
||||
from ..lexeme cimport EMPTY_LEXEME
|
||||
|
@ -80,6 +81,7 @@ cdef class Doc:
|
|||
self.is_parsed = False
|
||||
self._py_tokens = []
|
||||
self._vector = None
|
||||
self.noun_chunks_iterator = DocIterator(self)
|
||||
|
||||
def __getitem__(self, object i):
|
||||
"""Get a Token or a Span from the Doc.
|
||||
|
@ -166,7 +168,7 @@ cdef class Doc:
|
|||
|
||||
@property
|
||||
def text(self):
|
||||
return u' '.join(t.text for t in self)
|
||||
return u''.join(t.text for t in self)
|
||||
|
||||
property ents:
|
||||
def __get__(self):
|
||||
|
@ -230,33 +232,22 @@ cdef class Doc:
|
|||
# Set start as B
|
||||
self.c[start].ent_iob = 3
|
||||
|
||||
@property
|
||||
def noun_chunks(self):
|
||||
"""Yield spans for base noun phrases."""
|
||||
if not self.is_parsed:
|
||||
raise ValueError(
|
||||
"noun_chunks requires the dependency parse, which "
|
||||
"requires data to be installed. If you haven't done so, run: "
|
||||
"\npython -m spacy.en.download all\n"
|
||||
"to install the data")
|
||||
|
||||
cdef const TokenC* word
|
||||
labels = ['nsubj', 'dobj', 'nsubjpass', 'pcomp', 'pobj',
|
||||
'attr', 'root']
|
||||
np_deps = [self.vocab.strings[label] for label in labels]
|
||||
conj = self.vocab.strings['conj']
|
||||
np_label = self.vocab.strings['NP']
|
||||
for i in range(self.length):
|
||||
word = &self.c[i]
|
||||
if word.pos == NOUN and word.dep in np_deps:
|
||||
yield Span(self, word.l_edge, i+1, label=np_label)
|
||||
elif word.pos == NOUN and word.dep == conj:
|
||||
head = word+word.head
|
||||
while head.dep == conj and head.head < 0:
|
||||
head += head.head
|
||||
# If the head is an NP, and we're coordinated to it, we're an NP
|
||||
if head.dep in np_deps:
|
||||
yield Span(self, word.l_edge, i+1, label=np_label)
|
||||
|
||||
property noun_chunks:
|
||||
def __get__(self):
|
||||
"""Yield spans for base noun phrases."""
|
||||
if not self.is_parsed:
|
||||
raise ValueError(
|
||||
"noun_chunks requires the dependency parse, which "
|
||||
"requires data to be installed. If you haven't done so, run: "
|
||||
"\npython -m spacy.%s.download all\n"
|
||||
"to install the data" % self.vocab.lang)
|
||||
|
||||
yield from self.noun_chunks_iterator
|
||||
|
||||
def __set__(self, DocIterator):
|
||||
self.noun_chunks_iterator = DocIterator(self)
|
||||
|
||||
|
||||
@property
|
||||
def sents(self):
|
||||
|
@ -267,8 +258,8 @@ cdef class Doc:
|
|||
raise ValueError(
|
||||
"sentence boundary detection requires the dependency parse, which "
|
||||
"requires data to be installed. If you haven't done so, run: "
|
||||
"\npython -m spacy.en.download all\n"
|
||||
"to install the data")
|
||||
"\npython -m spacy.%s.download all\n"
|
||||
"to install the data" % self.vocab.lang)
|
||||
cdef int i
|
||||
start = 0
|
||||
for i in range(1, self.length):
|
||||
|
|
|
@ -18,10 +18,10 @@ from ..attrs cimport POS, LEMMA, TAG, DEP
|
|||
from ..parts_of_speech cimport CONJ, PUNCT
|
||||
|
||||
from ..attrs cimport IS_ALPHA, IS_ASCII, IS_DIGIT, IS_LOWER, IS_PUNCT, IS_SPACE
|
||||
from ..attrs cimport FLAG14 as IS_BRACKET
|
||||
from ..attrs cimport FLAG15 as IS_QUOTE
|
||||
from ..attrs cimport FLAG16 as IS_LEFT_PUNCT
|
||||
from ..attrs cimport FLAG17 as IS_RIGHT_PUNCT
|
||||
from ..attrs cimport IS_BRACKET
|
||||
from ..attrs cimport IS_QUOTE
|
||||
from ..attrs cimport IS_LEFT_PUNCT
|
||||
from ..attrs cimport IS_RIGHT_PUNCT
|
||||
from ..attrs cimport IS_TITLE, IS_UPPER, LIKE_URL, LIKE_NUM, LIKE_EMAIL, IS_STOP
|
||||
from ..attrs cimport IS_OOV
|
||||
|
||||
|
@ -95,6 +95,10 @@ cdef class Token:
|
|||
def __get__(self):
|
||||
return self.c.lex.prob
|
||||
|
||||
property lang:
|
||||
def __get__(self):
|
||||
return self.c.lex.lang
|
||||
|
||||
property idx:
|
||||
def __get__(self):
|
||||
return self.c.idx
|
||||
|
@ -161,8 +165,8 @@ cdef class Token:
|
|||
raise ValueError(
|
||||
"Word vectors set to length 0. This may be because the "
|
||||
"data is not installed. If you haven't already, run"
|
||||
"\npython -m spacy.en.download all\n"
|
||||
"to install the data."
|
||||
"\npython -m spacy.%s.download all\n"
|
||||
"to install the data." % self.vocab.lang
|
||||
)
|
||||
vector_view = <float[:length,]>self.c.lex.vector
|
||||
return numpy.asarray(vector_view)
|
||||
|
@ -177,23 +181,11 @@ cdef class Token:
|
|||
|
||||
property n_lefts:
|
||||
def __get__(self):
|
||||
cdef int n = 0
|
||||
cdef const TokenC* ptr = self.c - self.i
|
||||
while ptr != self.c:
|
||||
if ptr + ptr.head == self.c:
|
||||
n += 1
|
||||
ptr += 1
|
||||
return n
|
||||
return self.c.l_kids
|
||||
|
||||
property n_rights:
|
||||
def __get__(self):
|
||||
cdef int n = 0
|
||||
cdef const TokenC* ptr = self.c + (self.array_len - self.i)
|
||||
while ptr != self.c:
|
||||
if ptr + ptr.head == self.c:
|
||||
n += 1
|
||||
ptr -= 1
|
||||
return n
|
||||
return self.c.r_kids
|
||||
|
||||
property lefts:
|
||||
def __get__(self):
|
||||
|
@ -415,6 +407,10 @@ cdef class Token:
|
|||
def __get__(self):
|
||||
return self.vocab.strings[self.c.lex.suffix]
|
||||
|
||||
property lang_:
|
||||
def __get__(self):
|
||||
return self.vocab.strings[self.c.lex.lang]
|
||||
|
||||
property lemma_:
|
||||
def __get__(self):
|
||||
return self.vocab.strings[self.c.lemma]
|
||||
|
|
|
@ -14,6 +14,21 @@ from . import about
|
|||
from .attrs import TAG, HEAD, DEP, ENT_IOB, ENT_TYPE
|
||||
|
||||
|
||||
LANGUAGES = {}
|
||||
|
||||
|
||||
def set_lang_class(name, cls):
|
||||
global LANGUAGES
|
||||
LANGUAGES[name] = cls
|
||||
|
||||
|
||||
def get_lang_class(name):
|
||||
lang = re.split('[^a-zA-Z0-9_]', name, 1)[0]
|
||||
if lang not in LANGUAGES:
|
||||
raise RuntimeError('Language not supported: %s' % lang)
|
||||
return LANGUAGES[lang]
|
||||
|
||||
|
||||
def get_package(data_dir):
|
||||
if not isinstance(data_dir, six.string_types):
|
||||
raise RuntimeError('data_dir must be a string')
|
||||
|
@ -21,17 +36,20 @@ def get_package(data_dir):
|
|||
|
||||
|
||||
def get_package_by_name(name=None, via=None):
|
||||
package_name = name or about.__models__[about.__default_lang__]
|
||||
lang = get_lang_class(package_name)
|
||||
try:
|
||||
return sputnik.package(about.__title__, about.__version__,
|
||||
name or about.__default_model__, data_path=via)
|
||||
package_name, data_path=via)
|
||||
except PackageNotFoundException as e:
|
||||
raise RuntimeError("Model %s not installed. Please run 'python -m "
|
||||
"spacy.en.download' to install latest compatible "
|
||||
"model." % name)
|
||||
raise RuntimeError("Model '%s' not installed. Please run 'python -m "
|
||||
"%s.download' to install latest compatible "
|
||||
"model." % (name, lang.__module__))
|
||||
except CompatiblePackageNotFoundException as e:
|
||||
raise RuntimeError("Installed model is not compatible with spaCy "
|
||||
"version. Please run 'python -m spacy.en.download "
|
||||
"--force' to install latest compatible model.")
|
||||
"version. Please run 'python -m %s.download "
|
||||
"--force' to install latest compatible model." %
|
||||
(lang.__module__))
|
||||
|
||||
|
||||
def normalize_slice(length, start, stop, step=None):
|
||||
|
|
|
@ -25,9 +25,8 @@ from . import attrs
|
|||
from . import symbols
|
||||
|
||||
from cymem.cymem cimport Address
|
||||
from . import util
|
||||
from .serialize.packer cimport Packer
|
||||
from .attrs cimport PROB
|
||||
from .attrs cimport PROB, LANG
|
||||
|
||||
try:
|
||||
import copy_reg
|
||||
|
@ -105,6 +104,13 @@ cdef class Vocab:
|
|||
self._serializer = Packer(self, self.serializer_freqs)
|
||||
return self._serializer
|
||||
|
||||
property lang:
|
||||
def __get__(self):
|
||||
langfunc = None
|
||||
if self.get_lex_attr:
|
||||
langfunc = self.get_lex_attr.get(LANG,None)
|
||||
return langfunc('_') if langfunc else ''
|
||||
|
||||
def __len__(self):
|
||||
"""The current number of lexemes stored."""
|
||||
return self.length
|
||||
|
@ -246,6 +252,7 @@ cdef class Vocab:
|
|||
fp.write_from(&lexeme.prob, sizeof(lexeme.prob), 1)
|
||||
fp.write_from(&lexeme.sentiment, sizeof(lexeme.sentiment), 1)
|
||||
fp.write_from(&lexeme.l2_norm, sizeof(lexeme.l2_norm), 1)
|
||||
fp.write_from(&lexeme.lang, sizeof(lexeme.lang), 1)
|
||||
fp.close()
|
||||
|
||||
def load_lexemes(self, loc):
|
||||
|
@ -278,6 +285,7 @@ cdef class Vocab:
|
|||
fp.read_into(&lexeme.prob, 1, sizeof(lexeme.prob))
|
||||
fp.read_into(&lexeme.sentiment, 1, sizeof(lexeme.sentiment))
|
||||
fp.read_into(&lexeme.l2_norm, 1, sizeof(lexeme.l2_norm))
|
||||
fp.read_into(&lexeme.lang, 1, sizeof(lexeme.lang))
|
||||
|
||||
lexeme.vector = EMPTY_VEC
|
||||
py_str = self.strings[lexeme.orth]
|
||||
|
|
10
website/404.jade
Normal file
10
website/404.jade
Normal file
|
@ -0,0 +1,10 @@
|
|||
include _includes/_mixins
|
||||
|
||||
//- 404 Error
|
||||
//- ============================================================================
|
||||
|
||||
+lead.text-center Ooops, this page does not exist. Click #[a(href='javascript:history.go(-1)') here] to go back or check out one of the latest posts below.
|
||||
|
||||
+divider('bottom')
|
||||
|
||||
!=partial('_includes/_latest-posts', { max: 3 } )
|
|
@ -1,29 +1,22 @@
|
|||
Source for spacy.io
|
||||
==============================
|
||||
# Source files for the spacy.io website and docs
|
||||
|
||||
This directory contains the source for official spaCy website at http://spacy.io/.
|
||||
The [spacy.io](https://spacy.io) website is implemented in [Jade (aka Pug)](https://www.jade-lang.org), and is built or served by [Harp](https://harpjs.com).
|
||||
|
||||
Fixes, updates and suggestions are welcome.
|
||||
## Building the site
|
||||
|
||||
To build the site and start making changes:
|
||||
|
||||
Releases
|
||||
--------
|
||||
Changes made to this directory go live on spacy.io. <When / how often?>
|
||||
sudo npm install --global harp
|
||||
git clone https://github.com/spacy-io/website
|
||||
cd website
|
||||
harp server
|
||||
|
||||
This will serve the site on [http://localhost:9000](http://localhost:9000). You can then edit the jade source and refresh the page to see your changes.
|
||||
|
||||
The Stack
|
||||
--------
|
||||
The site is built with the [Jade](http://jade-lang.com/) template language.
|
||||
## Reading the source
|
||||
|
||||
See [fabfile.py](/fabfile.py) under ```web()``` for more
|
||||
Jade is an extensible templating language with a readable syntax, that compiles to HTML.
|
||||
The website source makes extensive use of Jade mixins, so that the design system is abstracted away from the content you're
|
||||
writing. You can read more about our approach in our blog post, ["Rebuilding a Website with Modular Markup Components"](https://spacy.io/blog/modular-markup).
|
||||
|
||||
|
||||
Developing
|
||||
--------
|
||||
To make and test changes
|
||||
```
|
||||
npm install jade --global
|
||||
fab web
|
||||
cd website/site; python -m SimpleHTTPServer 8000; cd -
|
||||
```
|
||||
Then visit [localhost:8000](http://localhost:8000)
|
||||
If you want to write or edit the pages, the site's [styleguide](http://spacy.io/styleguide) serves as a useful reference of the available mixins.
|
||||
|
|
51
website/_data.json
Normal file
51
website/_data.json
Normal file
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"index": {
|
||||
"landing": true
|
||||
},
|
||||
|
||||
"feed": {
|
||||
"layout": false
|
||||
},
|
||||
|
||||
"robots": {
|
||||
"layout": false
|
||||
},
|
||||
|
||||
"404": {
|
||||
"title": "404 Error",
|
||||
"asides": false
|
||||
},
|
||||
|
||||
"team": {
|
||||
"title": "Team"
|
||||
},
|
||||
|
||||
"legal": {
|
||||
"title": "Legal & Imprint",
|
||||
"sidebar": true,
|
||||
"asides": true
|
||||
},
|
||||
|
||||
"styleguide": {
|
||||
"title" : "Styleguide",
|
||||
"standalone" : true,
|
||||
"asides": true,
|
||||
|
||||
"sidebar": {
|
||||
"About": [
|
||||
["Introduction", "#section-introduction", "introduction"]
|
||||
],
|
||||
"Design": [
|
||||
["Colors", "#section-colors", "colors"],
|
||||
["Logo", "#section-logo", "logo"],
|
||||
["Typography", "#section-typography", "typography"],
|
||||
["Grid", "#section-grid", "grid"],
|
||||
["Elements", "#section-elements", "elements"],
|
||||
["Components", "#section-components", "components"]
|
||||
],
|
||||
"Code": [
|
||||
["Source", "#section-source", "source"]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
94
website/_fabfile.py
Normal file
94
website/_fabfile.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
from __future__ import print_function
|
||||
|
||||
from fabric.api import local
|
||||
import os
|
||||
import hashlib
|
||||
import mimetypes
|
||||
import shutil
|
||||
|
||||
import boto.s3.connection
|
||||
|
||||
|
||||
mimetypes.init()
|
||||
|
||||
buckets = {
|
||||
'staging': 'staging.spacy.io',
|
||||
'production': 'spacy.io',
|
||||
}
|
||||
|
||||
|
||||
def compile():
|
||||
shutil.rmtree('www')
|
||||
local('NODE_ENV=s3 harp compile')
|
||||
|
||||
|
||||
def publish(env='staging', site_path='www'):
|
||||
os.environ['S3_USE_SIGV4'] = 'True'
|
||||
conn = boto.s3.connection.S3Connection(host='s3.eu-central-1.amazonaws.com',
|
||||
calling_format=boto.s3.connection.OrdinaryCallingFormat())
|
||||
bucket = conn.get_bucket(buckets[env], validate=False)
|
||||
|
||||
keys = {k.name: k for k in bucket.list()}
|
||||
keys_left = set(keys)
|
||||
|
||||
for root, dirnames, filenames in os.walk(site_path):
|
||||
for dirname in dirnames:
|
||||
target = os.path.relpath(os.path.join(root, dirname), site_path)
|
||||
source = os.path.join(target, 'index.html')
|
||||
|
||||
if os.path.exists(os.path.join(root, dirname, 'index.html')):
|
||||
redirect = '//%s/%s' % (bucket.name, target)
|
||||
key = bucket.lookup(source)
|
||||
if not key:
|
||||
key = bucket.new_key(source)
|
||||
key.set_redirect(redirect)
|
||||
print('setting redirect for %s' % target)
|
||||
elif key.get_redirect() != redirect:
|
||||
key.set_redirect(redirect)
|
||||
print('setting redirect for %s' % target)
|
||||
|
||||
if source in keys_left:
|
||||
keys_left.remove(source)
|
||||
|
||||
for filename in filenames:
|
||||
source = os.path.join(root, filename)
|
||||
|
||||
if filename == 'index.html':
|
||||
target = os.path.normpath(os.path.relpath(root, site_path))
|
||||
if target == '.':
|
||||
target = filename
|
||||
else:
|
||||
target = os.path.normpath(os.path.join(os.path.relpath(root, site_path), filename))
|
||||
if target.endswith('.html'):
|
||||
target = target[:-len('.html')]
|
||||
|
||||
content_type = mimetypes.guess_type(source)[0]
|
||||
cache_control = 'no-transform,public,max-age=300,s-maxage=300'
|
||||
checksum = hashlib.md5(open(source).read()).hexdigest()
|
||||
|
||||
if (target not in keys
|
||||
or keys[target].etag.replace('"', '') != checksum):
|
||||
|
||||
key = bucket.new_key(target)
|
||||
if content_type:
|
||||
key.content_type = content_type
|
||||
key.set_contents_from_filename(source,
|
||||
headers={'Cache-Control': cache_control})
|
||||
print('uploading %s' % target)
|
||||
|
||||
elif content_type:
|
||||
key = bucket.lookup(target)
|
||||
if (key
|
||||
and (key.content_type != content_type
|
||||
or key.cache_control != cache_control)):
|
||||
key.copy(key.bucket, key.name, preserve_acl=True,
|
||||
metadata={'Content-Type': content_type,
|
||||
'Cache-Control': cache_control})
|
||||
print('update headers %s' % target)
|
||||
|
||||
if target in keys_left:
|
||||
keys_left.remove(target)
|
||||
|
||||
for key_name in keys_left:
|
||||
print('deleting %s' % key_name)
|
||||
bucket.delete_key(key_name)
|
85
website/_harp.json
Normal file
85
website/_harp.json
Normal file
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
"globals": {
|
||||
"title": "spaCy.io",
|
||||
"sitename": "spaCy",
|
||||
"slogan": "Industrial-strength Natural Language Processing",
|
||||
"description": "spaCy is a free open-source library featuring state-of-the-art speed and accuracy and a powerful Python API.",
|
||||
"url": "https://spacy.io",
|
||||
"email": "contact@spacy.io",
|
||||
"company": "spaCy GmbH",
|
||||
"team_members": [ "henning", "matt", "wolfgang", "elmar", "ines" ],
|
||||
|
||||
"navigation": { "Docs": "docs", "Demos": "demos", "Team": "team", "Blog": "blog" },
|
||||
"profiles": { "twitter": "spacy_io", "github": "spacy-io", "reddit": "spacynlp", "medium": "spacy" },
|
||||
"google_analytics": "UA-58931649-1",
|
||||
|
||||
"stylesheets": { "default": "style", "blog": "style_blog" },
|
||||
"scripts" : [ "main", "prism" ],
|
||||
"feed": "feed.xml",
|
||||
"image_sizes" : { "small" : "640", "medium": "1440", "large": "2000" },
|
||||
"default_syntax" : "python",
|
||||
|
||||
"spacy_version": "0.100.6",
|
||||
"spacy_stars": "1500",
|
||||
"github_settings": { "user": "spacy-io", "repo": "spacy" },
|
||||
|
||||
"apis": {
|
||||
"displacy": "https://displacy.spacy.io/",
|
||||
"sense2vec": "https://sense2vec.spacy.io/api/similarity/reddit/"
|
||||
},
|
||||
|
||||
"authors" : {
|
||||
"matt" : {
|
||||
"name" : "Matthew Honnibal",
|
||||
"title": "CTO",
|
||||
"description" : "is co-founder and CTO of spaCy. He studied linguistics as an undergrad, and never thought he'd be a programmer. By 2009 he had a PhD in computer science, and in 2014 he left academia to write spaCy. He's from Sydney and lives in Berlin.",
|
||||
"links": {
|
||||
"twitter": [ "https://twitter.com/honnibal", "Twitter" ],
|
||||
"website": [ "https://www.semanticscholar.org/search?q=Matthew%20Honnibal", "Semantic Scholar" ]
|
||||
}
|
||||
},
|
||||
|
||||
"henning": {
|
||||
"name": "Henning Peters",
|
||||
"title": "CEO",
|
||||
"description": "is co-founder and CEO of spaCy. He holds a MSc in computer science and has been co-founder and CTO of Skoobe and Absolventa. His passions are uncommon languages and backcountry skiing.",
|
||||
"links": {
|
||||
"twitter": [ "https://twitter.com/henningpeters", "Twitter"],
|
||||
"linkedin": [ "https://de.linkedin.com/in/hepeters", "LinkedIn"],
|
||||
"github": [ "https://github.com/henningpeters", "GitHub"]
|
||||
}
|
||||
},
|
||||
|
||||
"ines": {
|
||||
"name": "Ines Montani",
|
||||
"title": "Front-End",
|
||||
"description": "As Head of Front-End, Ines is in charge of showing people what spaCy can do. She develops, designs and implements our interactive demos and the spacy.io website. Ines has a degree in media, linguistics and communications, and over ten years experience in web development.",
|
||||
"links": {
|
||||
"twitter": [ "https://twitter.com/_inesmontani", "Twitter" ],
|
||||
"codepen": [ "https://codepen.io/inesmontani", "Codepen"],
|
||||
"github": [ "https://github.com/inesmontani", "GitHub"],
|
||||
"website": [ "http://ines.io", "Blog" ]
|
||||
}
|
||||
},
|
||||
|
||||
"wolfgang": {
|
||||
"name": "Wolfgang Seeker",
|
||||
"title": "NLP Engineer",
|
||||
"description": "is a computational linguist from Germany. He is fascinated with the complexity and variety of human language, and spent his PhD looking for ways to make NLP work well with any kind of language in the world. He joined spaCy to build effective and truly multilingual NLP software.",
|
||||
"links": {
|
||||
"website": [ "https://www.semanticscholar.org/search?q=Wolfgang%20Seeker", "Semantic Scholar" ]
|
||||
}
|
||||
},
|
||||
|
||||
"elmar": {
|
||||
"name": "Elmar Haußmann",
|
||||
"title": "NLP Engineer",
|
||||
"description": "is an NLP engineer at spaCy, passionate about deep learning. He has a background in both, academic research, with a PhD in computer science, and industry, as a former consultant and software engineer at IBM. Originally from Stuttgart, the avid snowboarder and mountain biker doesn't only ride powder and trails but also covers distances via plane between the spaCy office in Berlin and his new home in Beijing.",
|
||||
"links": {
|
||||
"github": [ "https://github.com/elmar-haussmann", "GitHub"],
|
||||
"twitter": [ "https://twitter.com/elhaussmann", "Twitter" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
7
website/_includes/_analytics.jade
Normal file
7
website/_includes/_analytics.jade
Normal file
|
@ -0,0 +1,7 @@
|
|||
if environment != 'development'
|
||||
script.
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', '#{google_analytics}', 'auto'); ga('send', 'pageview');
|
34
website/_includes/_article.jade
Normal file
34
website/_includes/_article.jade
Normal file
|
@ -0,0 +1,34 @@
|
|||
include ../_includes/_mixins
|
||||
|
||||
//- Article
|
||||
//- ============================================================================
|
||||
|
||||
article.article(id=current.source)
|
||||
|
||||
header.article-header
|
||||
+h2.article-title=title
|
||||
.article-meta
|
||||
if author
|
||||
| by #[a.link(href=(authors[author].url || url) target='_blank')=authors[author].name] on
|
||||
| #[+date(date)]
|
||||
|
||||
.article-body!=yield
|
||||
|
||||
footer.article-footer
|
||||
|
||||
+grid('padding', 'align-right', 'valign-center')
|
||||
+tweet(title)
|
||||
|
||||
if links
|
||||
for link, index in links
|
||||
div: +button('primary', 'small', index.toLowerCase())(href=link target='_blank')
|
||||
+icon(index.toLowerCase(), 'medium', 'secondary')
|
||||
| Discussion on #{index}
|
||||
|
||||
if author
|
||||
+divider
|
||||
|
||||
!=partial('_profile', { label: 'About the Author', style: 'alt' })
|
||||
|
||||
!=partial('_newsletter', { divider: 'both' })
|
||||
!=partial('_latest-posts', { max: 2, _section: _section } )
|
14
website/_includes/_footer.jade
Normal file
14
website/_includes/_footer.jade
Normal file
|
@ -0,0 +1,14 @@
|
|||
include _mixins
|
||||
|
||||
//- Footer
|
||||
//- ============================================================================
|
||||
|
||||
footer.footer
|
||||
span © #{new Date().getFullYear()} #{company}
|
||||
a(href='/legal') Legal / Imprint
|
||||
|
||||
a(href='https://twitter.com/' + profiles.twitter target='_blank' aria-label="Twitter")
|
||||
+icon('twitter', 'secondary')
|
||||
|
||||
a(href='/feed.xml' target='_blank' aria-label="RSS Feed")
|
||||
+icon('feed', 'secondary')
|
101
website/_includes/_functions.jade
Normal file
101
website/_includes/_functions.jade
Normal file
|
@ -0,0 +1,101 @@
|
|||
//- Functions
|
||||
//- ============================================================================
|
||||
|
||||
//- Full page title
|
||||
|
||||
- function getPageTitle() {
|
||||
- if(current.path[0] == 'blog' && current.source != 'index') title += ' | Blog';
|
||||
- return (current.path[0] == 'index') ? sitename + ' | ' + slogan : title + ' | ' + sitename;
|
||||
- }
|
||||
|
||||
|
||||
//- Get current URL
|
||||
current - [string] current path
|
||||
|
||||
- function getCurrentUrl() {
|
||||
- var base = current.path;
|
||||
- if(current.source == 'index') base.pop();
|
||||
- return url + '/' + base.join('/');
|
||||
- }
|
||||
|
||||
|
||||
//- Assign flexbox order, elements are assigned negative values to always move
|
||||
them to the start of a flexbox in the correct order (i.e. -3, -2, -1)
|
||||
counter - [integer] index of current item
|
||||
max - [integer] amount of items in total
|
||||
start - [integer] index of start position, i.e. 0 -> oder: -1 (optional)
|
||||
|
||||
- function assignOrder(counter, max, start) {
|
||||
- if(counter >= 0 && counter < max) return "order: -" + (max - counter + (start || 0));
|
||||
- }
|
||||
|
||||
|
||||
//- Create Twitter share URL
|
||||
current - [string] current path
|
||||
tweet - [string] text to be shared with link
|
||||
|
||||
- function twitterShareUrl(current, tweet) {
|
||||
- return "https://twitter.com/share?text=" + tweet + "&url=" + getCurrentUrl(current) + ";via=" + profiles.twitter;
|
||||
- }
|
||||
|
||||
|
||||
//- Add prefix to each item in an array (used for modifier CSS classes)
|
||||
array - [array] array of strings, taken from mixin arguments
|
||||
prefix - [string] class prefix (i.e. 'button--')
|
||||
|
||||
- function prefixArgs(array, prefix) {
|
||||
- for(var i = 0; i < array.length; i++) {
|
||||
- array[i] = prefix + array[i];
|
||||
- }
|
||||
- return array.join(' ');
|
||||
- }
|
||||
|
||||
|
||||
//- Convert date to human readable and timestamp format
|
||||
input - [string] date in the format YYYY-MM-DD
|
||||
|
||||
- function convertDate(input) {
|
||||
- var dates = [];
|
||||
- var months = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ];
|
||||
- var date = new Date(input);
|
||||
- dates.full = months[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear();
|
||||
- dates.timestamp = JSON.parse(JSON.stringify(date));
|
||||
- return dates;
|
||||
- }
|
||||
|
||||
|
||||
//- Convert date to valid RSS pubDate
|
||||
input - [string] date in the format YYYY-MM-DD
|
||||
|
||||
- function convertPubDate(input) {
|
||||
- var date = new Date(input);
|
||||
- var pieces = date.toString().split(' ');
|
||||
- var offsetTime = pieces[5].match(/[-+]\d{4}/);
|
||||
- var offset = (offsetTime) ? offsetTime : pieces[5];
|
||||
- var parts = [ pieces[0] + ',', pieces[2], pieces[1], pieces[3], pieces[4], offset ];
|
||||
- return parts.join(' ');
|
||||
- }
|
||||
|
||||
|
||||
//- Compile scrset attribute for hero images
|
||||
image - [object] article image object from _data.json
|
||||
path - [string] relative path to image folder
|
||||
|
||||
- function getScrset(image, path) {
|
||||
- var scrset = path + image.file + ' ' + image_sizes.medium + 'w';
|
||||
- if(image.file_small) scrset += ', ' + path + image.file_small + ' ' + image_sizes.small + 'w';
|
||||
- if(image.file_large) scrset += ', ' + path + image.file_large + ' ' + image_sizes.large + 'w';
|
||||
- return scrset;
|
||||
- }
|
||||
|
||||
|
||||
//- Get meta image
|
||||
|
||||
- function getMetaImage() {
|
||||
- if(current.path[0] == 'blog' && image && image.file) {
|
||||
- return url + '/blog/img/' + image.file;
|
||||
- }
|
||||
- else {
|
||||
- return url + '/assets/img/social.png';
|
||||
- }
|
||||
- }
|
31
website/_includes/_head.jade
Normal file
31
website/_includes/_head.jade
Normal file
|
@ -0,0 +1,31 @@
|
|||
include _mixins
|
||||
|
||||
- var is_blog = (_section == 'blog')
|
||||
|
||||
|
||||
//- Head
|
||||
//- ============================================================================
|
||||
|
||||
head
|
||||
title=getPageTitle()
|
||||
|
||||
meta(charset='utf-8')
|
||||
meta(name="viewport" content="width=device-width, initial-scale=1.0")
|
||||
meta(name='referrer' content='always')
|
||||
|
||||
meta(property='og:type' content='website')
|
||||
meta(property='og:site_name' content=sitename)
|
||||
meta(property='og:url' content=getCurrentUrl())
|
||||
meta(property='og:title' content=title)
|
||||
meta(property='og:description' content=description)
|
||||
meta(property='og:image' content=getMetaImage())
|
||||
|
||||
meta(name='twitter:card' content='summary_large_image')
|
||||
meta(name='twitter:site' content='@' + profiles.twitter)
|
||||
meta(name='twitter:title' content=title)
|
||||
meta(name='twitter:description' content=description)
|
||||
meta(name='twitter:image' content=getMetaImage())
|
||||
|
||||
link(rel='icon' type='image/x-icon' href='/assets/img/favicon.ico')
|
||||
link(href='/assets/css/' + ((is_blog) ? stylesheets.blog : stylesheets.default) + '.css' rel='stylesheet')
|
||||
link(href='/' + feed rel='alternate' type='application/rss+xml' title='RSS')
|
21
website/_includes/_header.jade
Normal file
21
website/_includes/_header.jade
Normal file
|
@ -0,0 +1,21 @@
|
|||
include _mixins
|
||||
|
||||
//- Header
|
||||
//- ============================================================================
|
||||
|
||||
header.header(class=(image) ? 'hero' : '')
|
||||
|
||||
if image
|
||||
img(srcset=getScrset(image, 'img/') alt=image.alt sizes='100vw')
|
||||
|
||||
if image.credit
|
||||
.hero-credit
|
||||
if image.url
|
||||
a(href=image.url target='_blank')=image.credit
|
||||
|
||||
else
|
||||
!=image.credit
|
||||
|
||||
else
|
||||
if !is_article && headline != false
|
||||
h1.header-title=title
|
17
website/_includes/_latest-posts.jade
Normal file
17
website/_includes/_latest-posts.jade
Normal file
|
@ -0,0 +1,17 @@
|
|||
include _mixins
|
||||
|
||||
- var post_counter = 0
|
||||
- var is_docs = (_section == 'docs')
|
||||
|
||||
|
||||
//- Latest Posts
|
||||
//- ============================================================================
|
||||
|
||||
+grid('padding')
|
||||
each post, slug in ( (_section == 'docs' ) ? public.docs.tutorials._data : public.blog._data)
|
||||
if slug != 'index' && slug != current.source && post_counter < (max || 3)
|
||||
|
||||
+grid-col('space-between', ((max > 2 && max % 3 == 0) ? 'third' : 'half'))
|
||||
!=partial('_teaser', { teaser: post, slug: slug, _root: (is_docs) ? '/docs/tutorials/' : '/blog/' })
|
||||
|
||||
- post_counter++
|
5
website/_includes/_logo.jade
Normal file
5
website/_includes/_logo.jade
Normal file
|
@ -0,0 +1,5 @@
|
|||
//- Logo
|
||||
//- ============================================================================
|
||||
|
||||
svg.logo(class=(logo_size) ? 'logo--' + logo_size : '' viewBox='0 0 675 215' width='500')
|
||||
path(d='M83.6 83.3C68.3 81.5 67.2 61 47.5 62.8c-9.5 0-18.4 4-18.4 12.7 0 13.2 20.3 14.4 32.5 17.7 20.9 6.3 41 10.7 41 33.3 0 28.8-22.6 38.8-52.4 38.8-24.9 0-50.2-8.9-50.2-31.8 0-6.4 6.1-11.3 12-11.3 7.5 0 10.1 3.2 12.7 8.4 5.8 10.2 12.3 15.6 28.3 15.6 10.2 0 20.6-3.9 20.6-12.7 0-12.6-12.8-15.3-26.1-18.4-23.5-6.6-43.6-10-46-36.1C-1 34.5 91.7 32.9 97 71.9c.1 7.1-6.5 11.4-13.4 11.4zm110.2-39c32.5 0 51 27.2 51 60.8 0 33.7-17.9 60.8-51 60.8-18.4 0-29.8-7.8-38.1-19.8v44.5c0 13.4-4.3 19.8-14.1 19.8-11.9 0-14.1-7.6-14.1-19.8V61.3c0-10.6 4.4-17 14.1-17 9.1 0 14.1 7.2 14.1 17v3.6c9.2-11.6 19.7-20.6 38.1-20.6zm-7.7 98.4c19.1 0 27.6-17.6 27.6-38.1 0-20.1-8.6-38.1-27.6-38.1-19.8 0-29 16.3-29 38.1 0 21.2 9.2 38.1 29 38.1zM266.9 76c0-23.4 26.9-31.7 52.9-31.7 36.6 0 51.7 10.7 51.7 46v34c0 8.1 5 24.1 5 29 0 7.4-6.8 12-14.1 12-8.1 0-14.1-9.5-18.4-16.3-11.9 9.5-24.5 16.3-43.8 16.3-21.3 0-38.1-12.6-38.1-33.3 0-18.4 13.2-28.9 29-32.5 0 .1 51-12 51-12.1 0-15.7-5.5-22.6-22-22.6-14.5 0-21.9 4-27.5 12.7-4.5 6.6-4 10.6-12.7 10.6-6.9-.1-13-4.9-13-12.1zm43.6 70.2c22.3 0 31.8-11.8 31.8-35.3v-5c-6 2-30.3 8-36.8 9.1-7 1.4-14.1 6.6-14.1 14.9.1 9.1 9.4 16.3 19.1 16.3zM474.5 0c31.5 0 65.7 18.8 65.7 48.8 0 7.7-5.8 14.1-13.4 14.1-10.3 0-11.8-5.5-16.3-13.4-7.6-13.9-16.5-23.3-36.1-23.3-30.2-.2-43.7 25.6-43.7 57.8 0 32.4 11.2 55.8 42.4 55.8 20.7 0 32.2-12 38.1-27.6 2.4-7.1 6.7-14.1 15.6-14.1 7 0 14.1 7.2 14.1 14.8 0 31.8-32.4 53.8-65.8 53.8-36.5 0-57.2-15.4-68.5-41-5.5-12.2-9.1-24.9-9.1-42.4-.1-49.2 28.6-83.3 77-83.3zm180.3 44.3c8 0 12.7 5.2 12.7 13.4 0 3.3-2.6 9.9-3.6 13.4L625.1 173c-8.6 22.1-15.1 37.4-44.5 37.4-14 0-26.1-1.2-26.1-13.4 0-7 5.3-10.6 12.7-10.6 1.4 0 3.6.7 5 .7 2.1 0 3.6.7 5 .7 14.7 0 16.8-15.1 22-25.5l-37.4-92.6c-2.1-5-3.6-8.4-3.6-11.3 0-8.2 6.4-14.1 14.8-14.1 9.5 0 13.3 7.5 15.6 15.6l24.7 73.5L638 65.5c3.9-10.5 4.2-21.2 16.8-21.2z')
|
381
website/_includes/_mixins.jade
Normal file
381
website/_includes/_mixins.jade
Normal file
|
@ -0,0 +1,381 @@
|
|||
include _functions
|
||||
|
||||
//- Mixins
|
||||
//- ============================================================================
|
||||
|
||||
//- Sections for content pages
|
||||
id - [string] id, can be headline id as it's being prefixed (optional)
|
||||
block - section content (block and inline elements)
|
||||
|
||||
mixin section(id)
|
||||
section.section(id=(id) ? 'section-' + id : '')&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- Flexbox grid to align children elements
|
||||
...style - [strings] flexbox CSS classes without prefix (optional)
|
||||
block - container content (block and inline elements)
|
||||
|
||||
mixin grid(...style)
|
||||
.grid(class=prefixArgs(style, 'grid--'))&attributes(attributes)
|
||||
block
|
||||
|
||||
mixin grid-col(...style)
|
||||
.grid-col(class=prefixArgs(style, 'grid-col--'))&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- Aside
|
||||
headline - [string] Headline of aside (optional)
|
||||
block - aside content (inline elements)
|
||||
|
||||
mixin aside(headline)
|
||||
span.aside(data-label=headline)&attributes(attributes)
|
||||
span.aside-body
|
||||
block
|
||||
|
||||
|
||||
//- Paragraphs
|
||||
block - paragraph content (inline elements)
|
||||
|
||||
mixin lead
|
||||
p.text-lead&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- Various text styles
|
||||
block - text (inline elements)
|
||||
|
||||
mixin example
|
||||
p.text-example&attributes(attributes)
|
||||
block
|
||||
|
||||
mixin source
|
||||
span.text-source&attributes(attributes)
|
||||
block
|
||||
|
||||
mixin label(...style)
|
||||
span(class=(style != '') ? prefixArgs(style, 'label-') : 'label')&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- Headings with optional permalinks
|
||||
id - [string] unique id (optional, no permalink without id)
|
||||
source - [string] link for source button (optional)
|
||||
block - headline text (inline elements)
|
||||
|
||||
mixin headline(level, id, source)
|
||||
if level == 2
|
||||
+h2(id, source)
|
||||
block
|
||||
|
||||
else if level == 3
|
||||
+h3(id, source)
|
||||
block
|
||||
|
||||
else if level == 4
|
||||
+h4(id, source)
|
||||
block
|
||||
|
||||
else if level == 5
|
||||
+h5(id, source)
|
||||
block
|
||||
|
||||
else
|
||||
+h6(id, source)
|
||||
block
|
||||
|
||||
mixin h1(id, source)
|
||||
h1(id=id)&attributes(attributes)
|
||||
+permalink(id, source)
|
||||
block
|
||||
|
||||
mixin h2(id, source)
|
||||
h2(id=id)&attributes(attributes)
|
||||
+permalink(id, source)
|
||||
block
|
||||
|
||||
mixin h3(id, source)
|
||||
h3(id=id)&attributes(attributes)
|
||||
+permalink(id, source)
|
||||
block
|
||||
|
||||
mixin h4(id, source)
|
||||
h4(id=id)&attributes(attributes)
|
||||
+permalink(id, source)
|
||||
block
|
||||
|
||||
mixin h5(id, source)
|
||||
h5(id=id)&attributes(attributes)
|
||||
+permalink(id, source)
|
||||
block
|
||||
|
||||
mixin h6(id, source)
|
||||
h6(id=id)&attributes(attributes)
|
||||
+permalink(id, source)
|
||||
block
|
||||
|
||||
mixin permalink(id, source)
|
||||
if id
|
||||
a.permalink(href='#' + id)
|
||||
block
|
||||
|
||||
else
|
||||
block
|
||||
|
||||
if source
|
||||
+button('secondary', 'small', 'source')(href=source target='_blank') Source
|
||||
|
||||
|
||||
//- Button
|
||||
element - [string] specifies HTML element, 'button' or 'link'
|
||||
...style - [strings] button CSS classes without prefix (optional)
|
||||
block - button text (inline elements)
|
||||
|
||||
mixin button(type, ...style)
|
||||
- var classname = 'button-' + type + ' ' + ((style) ? prefixArgs(style, 'button--') : '')
|
||||
|
||||
a.button(class=classname)&attributes(attributes)
|
||||
block
|
||||
|
||||
mixin form-button(type, ...style)
|
||||
- var classname = 'button-' + type + ' ' + ((style) ? prefixArgs(style, 'button--') : '')
|
||||
button(class=classname)&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- Input
|
||||
placeholder - [string] placeholder for input field (optional)
|
||||
value - [string] value of input field (optional)
|
||||
|
||||
mixin input(placeholder, value)
|
||||
input.input(placeholder=placeholder value=value)&attributes(attributes)
|
||||
|
||||
|
||||
//- Icon
|
||||
name - [string] icon name, refers to CSS classes
|
||||
size - [string] 'medium' or 'large' (optional)
|
||||
type - [string] 'button' (optional)
|
||||
block - description, if as a text node to the icon element it prevents line
|
||||
breaks between icon and text (inline elements)
|
||||
|
||||
mixin icon(type, ...style)
|
||||
span(class='icon-' + type + ' ' + prefixArgs(style, 'icon--') aria-hidden="true")&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- Image for illustration purposes
|
||||
file - [string] file name (in /img)
|
||||
alt - [string] descriptive alt text (optional)
|
||||
caption - [string] image caption (optional)
|
||||
|
||||
mixin image(file, alt, caption)
|
||||
figure.image-container&attributes(attributes)
|
||||
img(src='img/' + file alt=alt)
|
||||
|
||||
if caption
|
||||
figcaption.text-caption=caption
|
||||
|
||||
block
|
||||
|
||||
|
||||
//- Illustrated code view
|
||||
title - [string] title of window
|
||||
|
||||
mixin code-demo(title)
|
||||
.x-terminal&attributes(attributes)
|
||||
.x-terminal-icons: span
|
||||
.x-terminal-title=title
|
||||
+code.x-terminal-code
|
||||
block
|
||||
|
||||
|
||||
//- Data table
|
||||
head - [array] column headings (optional, without headings no table
|
||||
head is displayed)
|
||||
...style - [strings] table CSS classes without prefix (optional)
|
||||
block - only +row (tr)
|
||||
|
||||
mixin table(head, ...style)
|
||||
table.table(class=prefixArgs(style, 'table--'))&attributes(attributes)
|
||||
|
||||
if head
|
||||
tr.table-row
|
||||
each column in head
|
||||
th.table-head-cell=column
|
||||
|
||||
block
|
||||
|
||||
|
||||
//- Data table row
|
||||
block - only +cell (td)
|
||||
|
||||
mixin row(...style)
|
||||
tr.table-row(class=prefixArgs(style, 'table-cell--'))&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- Data table cell
|
||||
block - table cell content (inline elements)
|
||||
|
||||
mixin cell(...style)
|
||||
td.table-cell(class=prefixArgs(style, 'table-cell--'))&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- General list (ordered and unordered)
|
||||
type - [string] 'numbers', 'letters', 'roman' (optional)
|
||||
start - [integer] starting point of list (1 = list starts at 1 or A)
|
||||
block - only +item (li)
|
||||
|
||||
mixin list(type, start)
|
||||
if type
|
||||
ol.list(class='list--' + type style=(start === 0 || start) ? 'counter-reset: li ' + (start - 1) : '')&attributes(attributes)
|
||||
block
|
||||
|
||||
else
|
||||
ul.list.list--bullets&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- List item
|
||||
block - item text (inline elements)
|
||||
|
||||
mixin item
|
||||
li.list-item&attributes(attributes)
|
||||
block
|
||||
|
||||
|
||||
//- Blockquote
|
||||
source - [string] quote source / author (optional)
|
||||
link - [string] link to quote source (only with source, optional)
|
||||
block - quote text (inline elements)
|
||||
|
||||
mixin quote(source, link)
|
||||
blockquote.quote&attributes(attributes)
|
||||
p.quote-text
|
||||
block
|
||||
|
||||
if source && link
|
||||
| #[a.quote-source(href=link target='_blank')=source]
|
||||
|
||||
else if source && !link
|
||||
.quote-source !{source}
|
||||
|
||||
|
||||
//- Pullquotes with optional 'tweet this' function
|
||||
tweet - [string] text to be tweeted (optional)
|
||||
block - pullquote text (inline elements, only shown if no tweet text)
|
||||
|
||||
mixin pullquote(tweet)
|
||||
blockquote.quote&attributes(attributes)
|
||||
|
||||
p.quote-text-strong
|
||||
if tweet
|
||||
| !{tweet} #[a.quote-source(href=twitterShareUrl(current.path, tweet) target='_blank') Tweet this]
|
||||
|
||||
else
|
||||
block
|
||||
|
||||
|
||||
//- Code block
|
||||
use as +code(args). to preserve whitespace and prevent code interprettion
|
||||
language - [string] language for syntax highlighting (optional, default:
|
||||
'python', see Prism for options: http://prismjs.com)
|
||||
label - [string] code block headline (optional)
|
||||
block - code text (inline elements)
|
||||
|
||||
|
||||
mixin code(language, label)
|
||||
pre.code-block(class='lang-' + (language || default_syntax) data-label=label)&attributes(attributes)
|
||||
code.code-inline
|
||||
block
|
||||
|
||||
|
||||
//- Infobox for notes and alerts
|
||||
label - [string] infobox headline (optional)
|
||||
block - infobox text (inline and block elements)
|
||||
|
||||
mixin infobox(label)
|
||||
.box.box--info(data-label=label)&attributes(attributes)
|
||||
p.box-body
|
||||
block
|
||||
|
||||
|
||||
//- Alerts for notes and updates
|
||||
|
||||
mixin alert(button)
|
||||
.alert&attributes(attributes)
|
||||
block
|
||||
|
||||
if button
|
||||
+form-button('primary', 'small')(onclick='this.parentNode.parentNode.removeChild(this.parentNode);')=button
|
||||
|
||||
else
|
||||
button.alert-close(onclick='this.parentNode.parentNode.removeChild(this.parentNode);')
|
||||
|
||||
|
||||
|
||||
//- Embeds
|
||||
border - [boolean] add border to embed container
|
||||
caption - [string] embed caption
|
||||
block - embed content (inline and block elements)
|
||||
|
||||
mixin embed(border, caption)
|
||||
figure.embed(class=(border) ? 'embed--border' : '')&attributes(attributes)
|
||||
block
|
||||
|
||||
if caption
|
||||
figcaption.embed-caption=caption
|
||||
|
||||
|
||||
//- displaCy
|
||||
filename - [string] name of file in displacy folder (no .html)
|
||||
caption - [string] caption (optional)
|
||||
height - [integer] iframe height in px (optional)
|
||||
|
||||
mixin displacy(filename, caption, height)
|
||||
+embed(true, caption).embed--displacy
|
||||
iframe(src='/blog/displacy/' + filename height=height)
|
||||
|
||||
|
||||
//- Logo, imports SVG
|
||||
size - [string] 'tiny', 'small', 'regular' or 'large'
|
||||
|
||||
mixin logo(size)
|
||||
!=partial('/_includes/_logo', { logo_size: size })
|
||||
|
||||
|
||||
//- <time> element with date
|
||||
input - [string] date in the format YYYY-MM-DD
|
||||
type - [string] 'timestamp' (optional)
|
||||
|
||||
mixin date(input, type)
|
||||
- var dates = convertDate(input)
|
||||
|
||||
if type == 'timestamp'
|
||||
time=dates.timestamp
|
||||
|
||||
else
|
||||
time(datetime=dates.timestamp)=dates.full
|
||||
|
||||
|
||||
//- Divider
|
||||
type - [string] divider tpe
|
||||
|
||||
mixin divider(type, ...style)
|
||||
div(class=((type) ? 'divider-' + type : 'divider') + ' ' + prefixArgs(style, 'divider--'))&attributes(attributes)
|
||||
if type == 'text'
|
||||
.divider-text-content
|
||||
block
|
||||
|
||||
else
|
||||
block
|
||||
|
||||
|
||||
//- Twitter Share Button
|
||||
tweet - [string] text to be shared with the tweet
|
||||
|
||||
mixin tweet(tweet)
|
||||
a(href=twitterShareUrl(current.path, tweet) target='_blank' aria-label="Shsre on Twitter")
|
||||
+icon('twitter', 'large')
|
32
website/_includes/_nav.jade
Normal file
32
website/_includes/_nav.jade
Normal file
|
@ -0,0 +1,32 @@
|
|||
include _mixins
|
||||
|
||||
- var nav_active_class = 'nav-item--active'
|
||||
|
||||
|
||||
//- Top Navigation Bar
|
||||
//- ============================================================================
|
||||
|
||||
nav#topnav.nav
|
||||
|
||||
a(href='/')
|
||||
!=partial('_logo', { logo_size: 'small' })
|
||||
|
||||
input(type='checkbox' class='nav-checkbox' id='nav-checkbox' aria-hidden='true')
|
||||
|
||||
ul.nav-menu
|
||||
|
||||
if standalone
|
||||
li.nav-item(class=nav_active_class)=title
|
||||
li.nav-item: a(href='/') Back to website
|
||||
|
||||
else
|
||||
li.nav-item(class=(_section == 'index') ? nav_active_class : '')
|
||||
a(href='/') Home
|
||||
|
||||
each slug, item in navigation
|
||||
li.nav-item(class=(_section == slug) ? nav_active_class : '')
|
||||
a(href='/' + slug)=item
|
||||
|
||||
li.nav-item: a(href='https://github.com/' + profiles.github + '/spaCy' target='_blank') GitHub
|
||||
|
||||
label(for='nav-checkbox' class='nav-button' arial-label='Toggle Navigation')
|
21
website/_includes/_newsletter.jade
Normal file
21
website/_includes/_newsletter.jade
Normal file
|
@ -0,0 +1,21 @@
|
|||
include _mixins
|
||||
|
||||
//- Newsletter Signup
|
||||
//- ============================================================================
|
||||
|
||||
.block.text-center(class=(divider) ? 'divider-' + divider : '')
|
||||
|
||||
+label('strong') Sign up for the spaCy newsletter
|
||||
+h3.h1 Stay in the loop!
|
||||
+lead Receive updates about new releases, tutorials and more.
|
||||
|
||||
form(action='https://spacy.us12.list-manage.com/subscribe/post?u=83b0498b1e7fa3c91ce68c3f1&id=89ad33e698' method='post' id='mc-embedded-subscribe-form' name='mc-embedded-subscribe-form' target="_blank" novalidate)
|
||||
|
||||
+grid('align-center', 'valign-center', 'margin-right')
|
||||
+input('Your email address', '')(type='email' name='EMAIL' id='mce-EMAIL')
|
||||
|
||||
//- Spam bot protection
|
||||
div(style='position: absolute; left: -5000px;' aria-hidden='true')
|
||||
input(type='text' name='b_83b0498b1e7fa3c91ce68c3f1_89ad33e698' tabindex='-1' value='')
|
||||
|
||||
+form-button('primary', 'small')(type='submit' name='subscribe' id='mc-embedded-subscribe') Sign up
|
21
website/_includes/_profile.jade
Normal file
21
website/_includes/_profile.jade
Normal file
|
@ -0,0 +1,21 @@
|
|||
//- Author profile
|
||||
//- ============================================================================
|
||||
|
||||
include _mixins
|
||||
|
||||
if authors[author]
|
||||
.box.box--info(data-label=label)
|
||||
if image != false
|
||||
.box-image: img(src='/assets/img/profile_' + author + ( (style) ? '_' + style : '' ) + '.png')
|
||||
|
||||
p.box-body.text-big
|
||||
if authors[author].name
|
||||
strong=authors[author].name + ' '
|
||||
|
||||
if authors[author].description
|
||||
!=authors[author].description
|
||||
|
||||
if authors[author].links
|
||||
span.box-links
|
||||
each link, index in authors[author].links
|
||||
a(href=link[0] target='_blank') #[+icon(index)=(link[1] || index)]
|
12
website/_includes/_sidebar.jade
Normal file
12
website/_includes/_sidebar.jade
Normal file
|
@ -0,0 +1,12 @@
|
|||
include _mixins
|
||||
|
||||
//- Sidebar
|
||||
//- ============================================================================
|
||||
|
||||
nav#sidebar.sidebar: .sidebar-body
|
||||
each items, menu in sidebar
|
||||
|
||||
ul.sidebar-menu(data-label=menu)
|
||||
each item in items
|
||||
li.sidebar-menu-item
|
||||
a(href=item[1] data-section=(item[2]) ? 'section-' + item[2] : null)=item[0]
|
22
website/_includes/_teaser.jade
Normal file
22
website/_includes/_teaser.jade
Normal file
|
@ -0,0 +1,22 @@
|
|||
include _mixins
|
||||
|
||||
//- Teaser
|
||||
//- ============================================================================
|
||||
|
||||
.teaser
|
||||
if teaser.image
|
||||
a(href=(_root || '') + slug target=teaser.target)
|
||||
.image-ratio: img(src=(_root || '') + 'img/' + ((is_featured) ? teaser.image.file : teaser.image.file_small || teaser.image.file))
|
||||
|
||||
+h2
|
||||
if is_featured
|
||||
div: .label-strong Featured
|
||||
|
||||
a.block(href=(_root || '') + slug target=teaser.target class=(is_featured) ? 'h1' : 'h2')=teaser.title
|
||||
|
||||
p(class=(is_featured) ? 'text-lead' : '')=teaser.description
|
||||
|
||||
if showmeta != false
|
||||
.text-meta.text-small
|
||||
//- | by #{authors[teaser.author].name} on
|
||||
| #[+date(teaser.date)]
|
43
website/_layout.jade
Normal file
43
website/_layout.jade
Normal file
|
@ -0,0 +1,43 @@
|
|||
include _includes/_mixins
|
||||
|
||||
- var _section = current.path[0]
|
||||
- var _site = current.source
|
||||
|
||||
- var is_article = ( (_section == 'blog' && _site != 'index') || template == 'article')
|
||||
- var has_asides = (is_article || (_section == 'docs' && asides != false) || asides)
|
||||
|
||||
|
||||
//- Layout
|
||||
//- ============================================================================
|
||||
|
||||
doctype html
|
||||
|
||||
html(lang="en")
|
||||
!=partial("_includes/_head", { _section: _section })
|
||||
|
||||
body.body
|
||||
!=partial('_includes/_nav', { _section: _section, _site: _site })
|
||||
|
||||
if landing
|
||||
!= yield
|
||||
|
||||
else
|
||||
!=partial('_includes/_header', { is_article: is_article })
|
||||
|
||||
if sidebar
|
||||
!=partial('_includes/_sidebar')
|
||||
|
||||
main.main(class='#{(sidebar) ? "main--sidebar" : "" } #{(has_asides) ? "main--asides" : "" } #{(is_article) ? "main--article" : "" }')
|
||||
|
||||
if is_article
|
||||
!=partial('_includes/_article', { _section: _section })
|
||||
|
||||
else
|
||||
!=yield
|
||||
|
||||
!=partial('_includes/_footer')
|
||||
|
||||
each script in scripts
|
||||
script(src='/assets/js/' + script + '.js', type='text/javascript')
|
||||
|
||||
!=partial('_includes/_analytics')
|
23
website/assets/css/_base/_animations.sass
Normal file
23
website/assets/css/_base/_animations.sass
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Animations
|
||||
// ============================================================================
|
||||
|
||||
// Element slides in from the top
|
||||
|
||||
@keyframes slideInDown
|
||||
from
|
||||
transform: translate3d(0, -100%, 0);
|
||||
visibility: visible;
|
||||
|
||||
to
|
||||
transform: translate3d(0, 0, 0);
|
||||
|
||||
|
||||
// Element blinks
|
||||
|
||||
@keyframes blink
|
||||
0%
|
||||
opacity: 1
|
||||
50%
|
||||
opacity: 0
|
||||
100%
|
||||
opacity: 1
|
112
website/assets/css/_base/_fonts.sass
Normal file
112
website/assets/css/_base/_fonts.sass
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Fonts
|
||||
// ============================================================================
|
||||
|
||||
// Lato (regular, italic, bold, bold italic)
|
||||
|
||||
@font-face
|
||||
font-family: 'Lato'
|
||||
font-style: normal
|
||||
font-weight: 400
|
||||
src: url('../fonts/lato-regular.eot')
|
||||
src: url('../fonts/lato-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/lato-regular.woff2') format('woff2'), url('../fonts/lato-regular.woff') format('woff'), url('../fonts/lato-regular.ttf') format('truetype'), url('../fonts/lato-regular.svg#latoregular') format('svg')
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF
|
||||
|
||||
@font-face
|
||||
font-family: 'Lato'
|
||||
font-style: normal
|
||||
font-weight: 400
|
||||
src: url('../fonts/lato-regular.eot')
|
||||
src: url('../fonts/lato-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/lato-regular.woff2') format('woff2'), url('../fonts/lato-regular.woff') format('woff'), url('../fonts/lato-regular.ttf') format('truetype'), url('../fonts/lato-regular.svg#latoregular') format('svg')
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000
|
||||
|
||||
@font-face
|
||||
font-family: 'Lato'
|
||||
font-style: italic
|
||||
font-weight: 400
|
||||
src: url('../fonts/lato-italic.eot')
|
||||
src: url('../fonts/lato-italic.eot?#iefix') format('embedded-opentype'), url('../fonts/lato-italic.woff2') format('woff2'), url('../fonts/lato-italic.woff') format('woff'), url('../fonts/lato-italic.ttf') format('truetype'), url('../fonts/lato-italic.svg#latoitalic') format('svg')
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF
|
||||
|
||||
@font-face
|
||||
font-family: 'Lato'
|
||||
font-style: italic
|
||||
font-weight: 400
|
||||
src: url('../fonts/lato-italic.eot')
|
||||
src: url('../fonts/lato-italic.eot?#iefix') format('embedded-opentype'), url('../fonts/lato-italic.woff2') format('woff2'), url('../fonts/lato-italic.woff') format('woff'), url('../fonts/lato-italic.ttf') format('truetype'), url('../fonts/lato-italic.svg#latoitalic') format('svg')
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000
|
||||
|
||||
@font-face
|
||||
font-family: 'Lato'
|
||||
font-style: normal
|
||||
font-weight: 700
|
||||
src: url('../fonts/lato-bold.eot')
|
||||
src: url('../fonts/lato-bold.eot?#iefix') format('embedded-opentype'), url('../fonts/lato-bold.woff2') format('woff2'), url('../fonts/lato-bold.woff') format('woff'), url('../fonts/lato-bold.ttf') format('truetype'), url('../fonts/lato-bold.svg#latobold') format('svg')
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF
|
||||
|
||||
@font-face
|
||||
font-family: 'Lato'
|
||||
font-style: normal
|
||||
font-weight: 700
|
||||
src: url('../fonts/lato-bold.eot')
|
||||
src: url('../fonts/lato-bold.eot?#iefix') format('embedded-opentype'), url('../fonts/lato-bold.woff2') format('woff2'), url('../fonts/lato-bold.woff') format('woff'), url('../fonts/lato-bold.ttf') format('truetype'), url('../fonts/lato-bold.svg#latobold') format('svg')
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000
|
||||
|
||||
@font-face
|
||||
font-family: 'Lato'
|
||||
font-style: italic
|
||||
font-weight: 700
|
||||
src: url('../fonts/lato-bolditalic.eot')
|
||||
src: url('../fonts/lato-bolditalic.eot?#iefix') format('embedded-opentype'), url('../fonts/lato-bolditalic.woff2') format('woff2'), url('../fonts/lato-bolditalic.woff') format('woff'), url('../fonts/lato-bolditalic.ttf') format('truetype'), url('../fonts/lato-bolditalic.svg#latobolditalic') format('svg')
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF
|
||||
|
||||
@font-face
|
||||
font-family: 'Lato'
|
||||
font-style: italic
|
||||
font-weight: 700
|
||||
src: url('../fonts/lato-bolditalic.eot')
|
||||
src: url('../fonts/lato-bolditalic.eot?#iefix') format('embedded-opentype'), url('../fonts/lato-bolditalic.woff2') format('woff2'), url('../fonts/lato-bolditalic.woff') format('woff'), url('../fonts/lato-bolditalic.ttf') format('truetype'), url('../fonts/lato-bolditalic.svg#latobolditalic') format('svg')
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000
|
||||
|
||||
|
||||
// Work Sans (regular, semibold, bold)
|
||||
|
||||
@font-face
|
||||
font-family: 'Work Sans'
|
||||
font-style: normal
|
||||
font-weight: 400
|
||||
src: url('../fonts/worksans-regular.eot')
|
||||
src: url('../fonts/worksans-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/worksans-regular.woff2') format('woff2'), url('../fonts/worksans-regular.woff') format('woff'), url('../fonts/worksans-regular.ttf') format('truetype'), url('../fonts/worksans-regular.svg#worksansregular') format('svg')
|
||||
|
||||
@font-face
|
||||
font-family: 'Work Sans'
|
||||
font-style: normal
|
||||
font-weight: 600
|
||||
src: url('../fonts/worksans-semibold.eot')
|
||||
src: url('../fonts/worksans-semibold.eot?#iefix') format('embedded-opentype'), url('../fonts/worksans-semibold.woff2') format('woff2'), url('../fonts/worksans-semibold.woff') format('woff'), url('../fonts/worksans-semibold.ttf') format('truetype'), url('../fonts/worksans-semibold.svg#worksanssemibold') format('svg')
|
||||
|
||||
@font-face
|
||||
font-family: 'Work Sans'
|
||||
font-style: normal
|
||||
font-weight: 700
|
||||
src: url('../fonts/worksans-bold.eot')
|
||||
src: url('../fonts/worksans-bold.eot?#iefix') format('embedded-opentype'), url('../fonts/worksans-bold.woff2') format('woff2'), url('../fonts/worksans-bold.woff') format('woff'), url('../fonts/worksans-bold.ttf') format('truetype'), url('../fonts/worksans-bold.svg#worksansbold') format('svg')
|
||||
|
||||
|
||||
// Source Code Pro (semibold)
|
||||
|
||||
@font-face
|
||||
font-family: 'Source Code Pro'
|
||||
font-style: normal
|
||||
font-weight: 600
|
||||
src: url('../fonts/sourcecodepro-semibold.eot')
|
||||
src: url('../fonts/sourcecodepro-semibold.eot?#iefix') format('embedded-opentype'), url('../fonts/sourcecodepro-semibold.woff') format('woff'), url('../fonts/sourcecodepro-semibold.ttf') format('truetype'), url('../fonts/sourcecodepro-semibold.svg#sourcecodepro_semibold') format('svg')
|
||||
|
||||
|
||||
// Icomoon (regular)
|
||||
|
||||
@font-face
|
||||
font-family: 'Icomoon'
|
||||
font-style: normal
|
||||
font-weight: 400
|
||||
src: url('../fonts/icomoon.eot?nt9usq')
|
||||
src: url('../fonts/icomoon.eot?nt9usq#iefix') format('embedded-opentype'), url('../fonts/icomoon.ttf?nt9usq') format('truetype'), url('../fonts/icomoon.woff?nt9usq') format('woff'), url('../fonts/icomoon.svg?nt9usq#icomoon') format('svg')
|
131
website/assets/css/_base/_grid.sass
Normal file
131
website/assets/css/_base/_grid.sass
Normal file
|
@ -0,0 +1,131 @@
|
|||
// Grid - Variables
|
||||
// ============================================================================
|
||||
|
||||
$grid-cols : $columns
|
||||
$grid-padding : 2.25rem
|
||||
$grid-margin : 1rem
|
||||
|
||||
|
||||
// Grid - Style
|
||||
// ============================================================================
|
||||
|
||||
// Blocks
|
||||
|
||||
p,
|
||||
.block
|
||||
@extend .has-aside
|
||||
margin-bottom: 5rem
|
||||
|
||||
.no-block.no-block
|
||||
margin-bottom: 0
|
||||
|
||||
|
||||
// Responsive containers
|
||||
|
||||
.responsive-container
|
||||
max-width: 100%
|
||||
overflow: auto
|
||||
width: 100%
|
||||
|
||||
|
||||
// Flexbox grid container
|
||||
// .grid--wrap - wraps chrildren if bigger than the container
|
||||
// .grid--space-between - aligns children horizontally, adds space between them
|
||||
// .grid--space-around - aligns children horizontally, adds space around them
|
||||
// .grid--align-center - aligns children horizonally and centered
|
||||
// .grid--align-right - aligns children horizontally on the right
|
||||
// .grid--valign-bottom - aligns children vertically at the bottom
|
||||
// .grid-padding - adds padding to children
|
||||
// .grid--margin-right - adds right margin to children
|
||||
// .grid--margin-left - adds left margin to children
|
||||
// .grid--block - extends block style
|
||||
|
||||
.grid,
|
||||
.grid-col
|
||||
align-items: flex-start
|
||||
display: flex
|
||||
flex-wrap: wrap
|
||||
|
||||
&.grid--nowrap,
|
||||
&.grid-col--nowrap
|
||||
flex-wrap: nowrap
|
||||
|
||||
&.grid--space-between,
|
||||
&.grid-col--space-between
|
||||
justify-content: space-between
|
||||
|
||||
&.grid--space-around,
|
||||
&.grid-col--space-around
|
||||
justify-content: space-around
|
||||
|
||||
&.grid--align-center,
|
||||
&.grid-col--align-center
|
||||
justify-content: center
|
||||
|
||||
&.grid--align-right,
|
||||
&.grid-col--align-right
|
||||
justify-content: flex-end
|
||||
|
||||
&.grid--valign-center,
|
||||
&.grid-col--valign-center
|
||||
align-items: center
|
||||
|
||||
&.grid--valign-bottom,
|
||||
&.grid-col--valign-bottom
|
||||
align-items: flex-end
|
||||
|
||||
&.grid--valign-space-between,
|
||||
&.grid-col--valign-space-between
|
||||
align-items: space-between
|
||||
|
||||
&.grid--text-center,
|
||||
&.grid-col--text-center
|
||||
text-align: center
|
||||
|
||||
&.grid--block,
|
||||
&.grid-col--block
|
||||
@extend .block
|
||||
|
||||
|
||||
.grid
|
||||
&--padding > *
|
||||
padding: $grid-padding
|
||||
|
||||
&--margin-right > *
|
||||
margin-right: $grid-margin
|
||||
|
||||
&--margin-left > *
|
||||
margin-left: $grid-margin
|
||||
|
||||
|
||||
.grid-col
|
||||
overflow: hidden
|
||||
|
||||
& > *
|
||||
flex-shrink: 1
|
||||
max-width: 100%
|
||||
|
||||
|
||||
// Responsive grid elements
|
||||
// adapted from Gridly, https://github.com/IonicaBizau/gridly
|
||||
|
||||
@media (min-width: #{$screen-size-medium})
|
||||
.grid
|
||||
flex-direction: row
|
||||
align-items: stretch
|
||||
|
||||
.grid-col
|
||||
display: flex
|
||||
flex: 0 0 100%
|
||||
flex-direction: column
|
||||
|
||||
@each $grid-mode, $grid-percentage in $grid-cols
|
||||
&--#{$grid-mode}
|
||||
flex: 0 0 $grid-percentage
|
||||
max-width: $grid-percentage
|
||||
|
||||
|
||||
@media(max-width: #{$screen-size-medium})
|
||||
.grid-col.grid-col
|
||||
flex: 0 0 100%
|
||||
flex-flow: column wrap
|
75
website/assets/css/_base/_reset.sass
Normal file
75
website/assets/css/_base/_reset.sass
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Reset - Variables
|
||||
// ============================================================================
|
||||
|
||||
$reset-font-size : $base-font-size
|
||||
$reset-font-size-small : $base-font-size * 0.8
|
||||
|
||||
|
||||
// Reset - Style
|
||||
// ============================================================================
|
||||
|
||||
// normalize.css
|
||||
|
||||
@import ../_vendors/normalize
|
||||
|
||||
|
||||
// Clearfix
|
||||
|
||||
%clearfix
|
||||
*zoom: 1
|
||||
|
||||
&:before,
|
||||
&:after
|
||||
content: ''
|
||||
display: table
|
||||
|
||||
&:after
|
||||
clear: both
|
||||
|
||||
|
||||
// Custom Resets
|
||||
|
||||
*
|
||||
border: 0
|
||||
box-sizing: border-box
|
||||
margin: 0
|
||||
outline: 0
|
||||
padding: 0
|
||||
-webkit-font-smoothing: antialiased
|
||||
|
||||
html
|
||||
font-size: $reset-font-size
|
||||
|
||||
@media (max-width: #{$screen-size-small})
|
||||
font-size: $reset-font-size-small
|
||||
|
||||
header,
|
||||
footer,
|
||||
figure
|
||||
width: 100%
|
||||
max-width: 100%
|
||||
|
||||
table
|
||||
border-collapse: collapse
|
||||
max-width: 100%
|
||||
text-align: left
|
||||
width: 100%
|
||||
|
||||
td,
|
||||
th
|
||||
vertical-align: top
|
||||
|
||||
ul,
|
||||
ol
|
||||
list-style: none
|
||||
|
||||
a
|
||||
color: inherit
|
||||
text-decoration: none
|
||||
|
||||
img
|
||||
height: auto
|
||||
max-width: 100%
|
||||
|
||||
[data-label]:before
|
||||
content: attr(data-label)
|
174
website/assets/css/_base/_typography.sass
Normal file
174
website/assets/css/_base/_typography.sass
Normal file
|
@ -0,0 +1,174 @@
|
|||
// Typography - Variables
|
||||
// ============================================================================
|
||||
|
||||
$font-size : 1.6rem
|
||||
$headings : h1, h2, h3, h4, h5, h6
|
||||
$heading-font-family : $font-secondary
|
||||
$heading-font-sizes : 5rem, 2.8rem, 2.4rem, 2rem, 1.8rem, 1.6rem
|
||||
$heading-font-weight : bold
|
||||
$heading-padding : $height-navbar 0 1.5rem 0
|
||||
$heading-text-shadow : 2px 2px
|
||||
$line-height : 1.375
|
||||
$page-title-size : 6rem
|
||||
$color-highlight : color($theme)
|
||||
$color-highlight-dark : color($theme, dark)
|
||||
|
||||
|
||||
// Typography - Style
|
||||
// ============================================================================
|
||||
|
||||
// Placeholders
|
||||
|
||||
%font-base
|
||||
font-size: $font-size
|
||||
line-height: $line-height
|
||||
|
||||
%font-big
|
||||
font-size: round-dec($font-size * 1.25)
|
||||
line-height: round-dec($line-height * 1.15)
|
||||
|
||||
%font-lead
|
||||
font-size: round-dec($font-size * 1.75)
|
||||
line-height: round-dec($line-height * 1.2)
|
||||
|
||||
%font-small
|
||||
font-size: round-dec($font-size * 0.75)
|
||||
line-height: round-dec($line-height * 1.1)
|
||||
|
||||
%font-medium-small
|
||||
font-size: round-dec($font-size * 0.875)
|
||||
line-height: round-dec($line-height * 1.1)
|
||||
|
||||
%font-primary
|
||||
font-family: $font-primary
|
||||
|
||||
%font-secondary
|
||||
font-family: $font-secondary
|
||||
|
||||
%font-code
|
||||
font-family: $font-code
|
||||
|
||||
|
||||
// Text styles
|
||||
// .text - regular text
|
||||
// .text-big - bigger style for blogs
|
||||
// .text-lead - large style for intro paragraphs
|
||||
// .text-small - smaller font size
|
||||
// .text-quote - style for quotation
|
||||
// .text-meta - slightly fainter but emphasized font for meta text
|
||||
// .text-meta-strong - emphasized meta text
|
||||
// .text-label - text for labels
|
||||
// .text-credit - meta text with copyright symbol for image credits
|
||||
// .text-caption - text for figure captions
|
||||
// .text-source - text for bibliography sources
|
||||
// .text-example - text for linguistic examples
|
||||
|
||||
.text
|
||||
@extend %font-primary, %font-base
|
||||
|
||||
.text-big
|
||||
@extend %font-primary, %font-big
|
||||
|
||||
.text-lead
|
||||
@extend %font-primary, %font-lead
|
||||
|
||||
.text-medium-small
|
||||
@extend %font-medium-small
|
||||
|
||||
.text-small
|
||||
@extend %font-small
|
||||
|
||||
.text-quote
|
||||
@extend .text-big
|
||||
font-style: italic
|
||||
|
||||
.text-meta
|
||||
@extend %font-secondary, %font-base
|
||||
font-style: normal
|
||||
font-weight: 600
|
||||
text-transform: uppercase
|
||||
|
||||
.text-meta-strong
|
||||
@extend .text-meta
|
||||
font-weight: bold
|
||||
|
||||
.text-label
|
||||
@extend %font-secondary
|
||||
font-size: round-dec($font-size * 0.875)
|
||||
line-height: $line-height
|
||||
font-weight: normal
|
||||
text-transform: uppercase
|
||||
|
||||
.text-credit
|
||||
@extend .text-meta, .text-small
|
||||
@include icon(copyright, currentColor, 0 0.25em 0 0)
|
||||
color: color(grey, dark)
|
||||
|
||||
.text-caption
|
||||
@extend .text-small
|
||||
color: color(grey, dark)
|
||||
padding-top: 2rem
|
||||
|
||||
.text-source
|
||||
@extend .text-quote
|
||||
display: block
|
||||
|
||||
.text-example
|
||||
@extend .text-lead
|
||||
color: color(grey, dark)
|
||||
font-style: italic
|
||||
|
||||
.text-code
|
||||
@extend %font-code
|
||||
font-size: round-dec($font-size * 0.875)
|
||||
font-weight: 600
|
||||
font-style: normal
|
||||
line-height: round-dec($line-height * 1.65)
|
||||
|
||||
.text-center
|
||||
text-align: center
|
||||
|
||||
|
||||
// Headings - Style
|
||||
// ============================================================================
|
||||
|
||||
// Global heading style
|
||||
|
||||
%heading
|
||||
font-weight: $heading-font-weight
|
||||
font-family: $heading-font-family
|
||||
position: relative
|
||||
|
||||
|
||||
// Headings
|
||||
|
||||
.h0
|
||||
font-size: $page-title-size
|
||||
line-height: round-dec($line-height * 0.9)
|
||||
margin: 0
|
||||
text-shadow: $heading-text-shadow $color-highlight-dark
|
||||
|
||||
@for $i from 1 through length($headings)
|
||||
$heading: nth($headings, $i)
|
||||
|
||||
#{$heading},
|
||||
.#{$heading}
|
||||
@extend %heading
|
||||
font-size: nth($heading-font-sizes, $i)
|
||||
|
||||
@if $i == 1
|
||||
.#{$heading}
|
||||
padding: 0
|
||||
|
||||
@else
|
||||
#{$heading}
|
||||
padding: $heading-padding
|
||||
|
||||
|
||||
// Selection - Style
|
||||
// ============================================================================
|
||||
|
||||
*::selection
|
||||
text-shadow: none
|
||||
background: $color-highlight
|
||||
color: color(white)
|
33
website/assets/css/_components/_alerts.sass
Normal file
33
website/assets/css/_components/_alerts.sass
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Variables
|
||||
// ============================================================================
|
||||
|
||||
$alert-background : color(white)
|
||||
$alert-border : 1px solid
|
||||
$alert-close-size : 2.25rem
|
||||
$alert-color : color($theme)
|
||||
$alert-padding : 1.5rem 2rem
|
||||
|
||||
|
||||
// Style
|
||||
// ============================================================================
|
||||
|
||||
// Alert boxes
|
||||
// .alert - alert container
|
||||
// .alert-close - icon to close alert
|
||||
|
||||
.alert
|
||||
@include position(fixed, bottom, left, 0, 0)
|
||||
align-items: center
|
||||
background: $alert-background
|
||||
border-top: $alert-border
|
||||
color: $alert-color
|
||||
display: flex
|
||||
justify-content: space-between
|
||||
padding: $alert-padding
|
||||
width: 100%
|
||||
z-index: 200
|
||||
|
||||
.alert-close
|
||||
@include icon(close, currentColor, 0, $alert-close-size)
|
||||
background: transparent
|
||||
color: $alert-color
|
69
website/assets/css/_components/_asides.sass
Normal file
69
website/assets/css/_components/_asides.sass
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Variables
|
||||
// ============================================================================
|
||||
|
||||
$aside-block-margin : 4rem
|
||||
$aside-border : 1px solid color(grey)
|
||||
$aside-font-size : 1.4rem
|
||||
$aside-font-family : $font-primary
|
||||
$aside-line-height : 1.65
|
||||
$aside-margin-side : 1.5rem
|
||||
$aside-opacity : 0.4
|
||||
$aside-padding : 0 2rem
|
||||
$aside-transition : $transition
|
||||
$aside-width : $width-aside
|
||||
|
||||
|
||||
// Style
|
||||
// ============================================================================
|
||||
|
||||
// Aside content
|
||||
// :hover - show aside on hover
|
||||
// [data-label] - style of aside headlines
|
||||
|
||||
.aside
|
||||
@extend .text-small
|
||||
|
||||
@media (max-width: #{$screen-size-large})
|
||||
display: block
|
||||
margin-bottom: $aside-block-margin
|
||||
margin-top: $aside-block-margin
|
||||
|
||||
@media (min-width: #{$screen-size-large})
|
||||
@include position(absolute, top, left, 0, calc(100% + #{$aside-margin-side}))
|
||||
border-left: $aside-border
|
||||
opacity: $aside-opacity
|
||||
padding: $aside-padding
|
||||
transition: $aside-transition
|
||||
white-space: normal
|
||||
width: $aside-width
|
||||
|
||||
&:hover
|
||||
opacity: 1
|
||||
|
||||
&[data-label]:before
|
||||
@extend .label-strong
|
||||
display: block
|
||||
|
||||
.block
|
||||
margin-bottom: ($aside-block-margin / 2)
|
||||
|
||||
.code-inline
|
||||
@extend .code-small
|
||||
|
||||
.code-block
|
||||
@extend .code-block-small
|
||||
|
||||
.table &
|
||||
top: initial
|
||||
|
||||
.aside-body
|
||||
display: block
|
||||
|
||||
|
||||
// Aside container
|
||||
|
||||
.has-aside
|
||||
position: relative
|
||||
|
||||
&:hover > .aside
|
||||
opacity: 1
|
39
website/assets/css/_components/_boxes.sass
Normal file
39
website/assets/css/_components/_boxes.sass
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Boxes - Variables
|
||||
// ============================================================================
|
||||
|
||||
$box-border : 1px solid
|
||||
$box-padding : 2em
|
||||
|
||||
|
||||
// Boxes - Style
|
||||
// ============================================================================
|
||||
|
||||
// Box for notes and alerts
|
||||
// [data-label] - style of box labels
|
||||
// .box--info - emphasized style for info boxes
|
||||
// .box-image - optional image, like profile image
|
||||
// .box-body - body text of box
|
||||
// .box-links - link list
|
||||
|
||||
.box
|
||||
@extend .block, .text
|
||||
padding: ($box-padding / 2) 0
|
||||
|
||||
&[data-label]:before
|
||||
@extend .label-box
|
||||
|
||||
&--info
|
||||
background: color($theme, light)
|
||||
border: $box-border darken(color($theme, light), 4)
|
||||
|
||||
.box-image
|
||||
@extend .image-profile
|
||||
float: right
|
||||
|
||||
.box-body
|
||||
margin-bottom: 0
|
||||
padding: $box-padding
|
||||
|
||||
.box-links
|
||||
@extend .link-list
|
||||
padding: $box-padding
|
75
website/assets/css/_components/_buttons.sass
Normal file
75
website/assets/css/_components/_buttons.sass
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Buttons - Variables
|
||||
// ============================================================================
|
||||
|
||||
$button-border-radius : $border-radius
|
||||
$button-border-style : solid
|
||||
$button-border-width : 2px
|
||||
$button-color : color($theme)
|
||||
$button-opacity-hover : 0.85
|
||||
$button-padding : 1em 1.5em 0.75em
|
||||
$button-margin : 0.5rem
|
||||
|
||||
|
||||
// Buttons - Style
|
||||
// ============================================================================
|
||||
|
||||
// :active - effect on active
|
||||
// :hover - effect on hover
|
||||
// .button--small - small style
|
||||
// .button--#{$social-button} - social button styled according to site
|
||||
// .button-primary - primary style
|
||||
// .button-secondary - secondary style
|
||||
// .button-tertiary - tertiary style
|
||||
|
||||
.button
|
||||
@extend .text-meta
|
||||
border: $button-border-width $button-border-style
|
||||
border-radius: $button-border-radius
|
||||
padding: $button-padding
|
||||
|
||||
&--small
|
||||
@extend .text-small
|
||||
border-width: ($button-border-width / 2)
|
||||
|
||||
&--source
|
||||
float: right
|
||||
margin-left: $button-margin
|
||||
|
||||
@each $social-button in $social-buttons
|
||||
&.button--#{$social-button}
|
||||
background: color(social, $social-button)
|
||||
border-color: color(social, $social-button)
|
||||
color: color(white)
|
||||
|
||||
.button-primary
|
||||
@extend .button
|
||||
background-color: $button-color
|
||||
border-color: $button-color
|
||||
color: color(white)
|
||||
|
||||
&:hover,
|
||||
&:active
|
||||
opacity: $button-opacity-hover
|
||||
|
||||
.button-secondary
|
||||
@extend .button
|
||||
background: color(white)
|
||||
color: $button-color
|
||||
|
||||
&:hover,
|
||||
&:active
|
||||
background: $button-color
|
||||
color: color(white)
|
||||
opacity: 1
|
||||
|
||||
.button-tertiary
|
||||
@extend .button
|
||||
background: color(white)
|
||||
color: color(grey, dark)
|
||||
border-color: currentColor
|
||||
|
||||
&:hover,
|
||||
&:active
|
||||
border-color: $button-color
|
||||
color: $button-color
|
||||
opacity: 1
|
44
website/assets/css/_components/_cards.sass
Normal file
44
website/assets/css/_components/_cards.sass
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Cards - Variables
|
||||
// ============================================================================
|
||||
|
||||
$card-border-radius : $border-radius
|
||||
$card-border : 1px solid color(grey)
|
||||
$card-figure-background : color(grey, light)
|
||||
$card-figure-ratio : $image-ratio
|
||||
$card-padding : 8%
|
||||
$card-shadow-light : 0 0 5px color(grey, light)
|
||||
$card-shadow : 0 0 5px color(grey)
|
||||
$card-transition : $transition
|
||||
|
||||
|
||||
// Cards - Style
|
||||
// ============================================================================
|
||||
|
||||
// .card - card element, ideally used within grids
|
||||
// .card-strong - highlighted style
|
||||
// .card-figure - graphic element within card
|
||||
|
||||
.card
|
||||
border: $card-border
|
||||
border-radius: $border-radius
|
||||
flex: 1
|
||||
overflow: auto
|
||||
padding: $card-padding
|
||||
width: 100%
|
||||
|
||||
.card-strong
|
||||
@extend .card
|
||||
box-shadow: $card-shadow
|
||||
transition: $card-transition
|
||||
|
||||
&:hover
|
||||
box-shadow: $card-shadow-light
|
||||
|
||||
.card-figure
|
||||
background: $card-figure-background
|
||||
border-radius: $card-border-radius
|
||||
display: block
|
||||
height: 0
|
||||
margin-bottom: $card-padding
|
||||
overflow: hidden
|
||||
padding-bottom: 50%
|
87
website/assets/css/_components/_code.sass
Normal file
87
website/assets/css/_components/_code.sass
Normal file
|
@ -0,0 +1,87 @@
|
|||
// Variables
|
||||
// ============================================================================
|
||||
|
||||
$code-background : color(grey, light)
|
||||
$code-background-dark : color(black)
|
||||
$code-block-border : 4px solid color($theme)
|
||||
$code-block-padding : 2em 3em
|
||||
$code-block-padding-small : 1em 1.5em
|
||||
$code-inline-margin : 0.25em 0.5em 0 0.5em
|
||||
$code-inline-padding : 0 0.25rem
|
||||
$code-line-height : 2.25
|
||||
$code-text-shadow : 1px 1px 0 color(white)
|
||||
|
||||
|
||||
// Style
|
||||
// ============================================================================
|
||||
|
||||
// General code style
|
||||
// .code-inline - source code
|
||||
// .code-small - smaller style
|
||||
|
||||
.code-inline
|
||||
@extend .text-code
|
||||
direction: ltr
|
||||
text-shadow: $code-text-shadow
|
||||
white-space: pre
|
||||
word-spacing: normal
|
||||
word-break: normal
|
||||
|
||||
.code-small
|
||||
@extend .text-small
|
||||
padding-top: 0
|
||||
padding-bottom: 0
|
||||
|
||||
|
||||
// Inline Code
|
||||
// :not(.code-block) - style for items outside of code blocks
|
||||
|
||||
code
|
||||
@extend .code-inline
|
||||
|
||||
:not(.code-block) > .code-inline
|
||||
background: $code-background
|
||||
display: inline
|
||||
line-height: inherit
|
||||
margin: $code-inline-margin
|
||||
padding: $code-inline-padding
|
||||
|
||||
|
||||
// Code blocks in preformatted text
|
||||
// .code-block - block of source code
|
||||
// .code - text content of code blocks
|
||||
// [data-label] - style of code labels
|
||||
// .code-block-small - smaller style
|
||||
// .code-block-dark - alternative dark style
|
||||
|
||||
.code-block
|
||||
@extend .block
|
||||
background: $code-background
|
||||
border-left: $code-block-border
|
||||
max-width: 100%
|
||||
overflow: auto
|
||||
padding: 1em 0
|
||||
white-space: pre
|
||||
width: 100%
|
||||
|
||||
.code-inline
|
||||
display: block
|
||||
padding: $code-block-padding
|
||||
|
||||
&[data-label]:before
|
||||
@extend .label-box
|
||||
|
||||
.code-block-small
|
||||
@extend .code-small
|
||||
|
||||
.code-inline
|
||||
padding: $code-block-padding-small
|
||||
|
||||
.code-block-dark
|
||||
@extend .code-block
|
||||
background: $code-background-dark
|
||||
border: none
|
||||
color: color(white)
|
||||
|
||||
.code-inline
|
||||
text-shadow: none
|
72
website/assets/css/_components/_dividers.sass
Normal file
72
website/assets/css/_components/_dividers.sass
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Dividers - Variables
|
||||
// ============================================================================
|
||||
|
||||
$divider-border : 1px solid color(grey)
|
||||
$divider-locations : top, bottom
|
||||
$divider-margin : 5rem
|
||||
$divider-padding : 3rem
|
||||
$divider-text-align : center
|
||||
|
||||
|
||||
// Dividers - Style
|
||||
// ============================================================================
|
||||
|
||||
// General divider
|
||||
|
||||
.divider
|
||||
@extend %clearfix
|
||||
width: 100%
|
||||
margin: $divider-margin 0
|
||||
|
||||
@each $divider-location in $divider-locations
|
||||
%divider-#{$divider-location}
|
||||
@extend .divider
|
||||
border-#{$divider-location}: $divider-border
|
||||
|
||||
|
||||
// Divider above element
|
||||
// .divider-top - add divider to top of element
|
||||
// .divider-bottom - add divider to bottom of element
|
||||
// .divider-both - add divider to top and bottom of element
|
||||
|
||||
.divider-top
|
||||
@extend %divider-top
|
||||
padding-top: $divider-padding
|
||||
|
||||
.divider-bottom
|
||||
@extend %divider-bottom
|
||||
padding-bottom: $divider-padding
|
||||
|
||||
.divider-both
|
||||
@extend .divider-top
|
||||
@extend .divider-bottom
|
||||
|
||||
|
||||
// Divider bar for text and links
|
||||
// .divider-bar - container element
|
||||
|
||||
.divider-bar
|
||||
@extend %divider-top, %divider-bottom, .label
|
||||
margin: 0
|
||||
text-align: $divider-text-align
|
||||
|
||||
|
||||
// Divider with text
|
||||
// .divider-text - container element
|
||||
// .divider-text-content - text content
|
||||
|
||||
.divider-text
|
||||
@extend %divider-top
|
||||
text-align: $divider-text-align
|
||||
margin: $divider-margin 0
|
||||
|
||||
.divider-text-content
|
||||
background: color(white)
|
||||
display: inline-block
|
||||
line-height: 0.5
|
||||
margin: -0.5em 0 0 0
|
||||
padding: 0 0.5em
|
||||
|
||||
& > *
|
||||
margin: 0
|
||||
padding: 0
|
35
website/assets/css/_components/_embeds.sass
Normal file
35
website/assets/css/_components/_embeds.sass
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Embeds - Variables
|
||||
// ============================================================================
|
||||
|
||||
$embed-border : 1px solid color(grey)
|
||||
$embed-caption-align : center
|
||||
$embed-padding : 2rem
|
||||
$embed-displacy-min : 325px
|
||||
|
||||
|
||||
// Embeds - Style
|
||||
// ============================================================================
|
||||
|
||||
// iframe - content of embed
|
||||
// .embed--border - embed with border
|
||||
// .embed--displacy - embed for displaCy visualization
|
||||
|
||||
.embed
|
||||
@extend .block
|
||||
margin-left: 0
|
||||
padding: $embed-padding
|
||||
|
||||
iframe
|
||||
max-width: 100%
|
||||
width: 100%
|
||||
|
||||
&--border
|
||||
border: $embed-border
|
||||
|
||||
&--displacy iframe
|
||||
min-height: $embed-displacy-min
|
||||
|
||||
.embed-caption
|
||||
@extend .label
|
||||
display: block
|
||||
text-align: $embed-caption-align
|
28
website/assets/css/_components/_forms.sass
Normal file
28
website/assets/css/_components/_forms.sass
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Form Elements - Variables
|
||||
// ============================================================================
|
||||
|
||||
$input-border : 1px solid color(grey)
|
||||
$input-border-radius : $border-radius
|
||||
$input-color : color(grey, dark)
|
||||
$input-padding : 0.5em 0.75em
|
||||
$input-transition : $transition
|
||||
|
||||
|
||||
// Form Elements - Style
|
||||
// ============================================================================
|
||||
|
||||
// Text input field
|
||||
// :hover - style on hover
|
||||
// :focus - style on focus
|
||||
|
||||
.input
|
||||
@extend .text
|
||||
border: $input-border
|
||||
border-radius: $input-border-radius
|
||||
color: $input-color
|
||||
padding: $input-padding
|
||||
transition: $input-transition
|
||||
|
||||
&:hover,
|
||||
&:focus
|
||||
border-color: currentColor
|
39
website/assets/css/_components/_icons.sass
Normal file
39
website/assets/css/_components/_icons.sass
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Icons - Variables
|
||||
// ============================================================================
|
||||
|
||||
$icon-padding : 0.5em
|
||||
$icon-large-size : 3rem
|
||||
$icon-medium-size : 1.75rem
|
||||
|
||||
|
||||
// Icons - Style
|
||||
// ============================================================================
|
||||
|
||||
// .icon--secondary - non-colored version of icon
|
||||
// .icon--large - large version of graphic icon
|
||||
// .icon-#{$icon} - graphic icon
|
||||
|
||||
%icon
|
||||
display: inline-block
|
||||
font-family: $font-icons
|
||||
font-style: normal
|
||||
font-weight: normal
|
||||
line-height: 1
|
||||
|
||||
.icon
|
||||
display: inline-block
|
||||
vertical-align: middle
|
||||
|
||||
&--secondary:before
|
||||
color: currentColor !important
|
||||
|
||||
&--medium:before
|
||||
font-size: $icon-medium-size
|
||||
|
||||
&--large:before
|
||||
font-size: $icon-large-size
|
||||
|
||||
@each $icon, $unicode in $icons
|
||||
.icon-#{$icon}
|
||||
@extend .icon
|
||||
@include icon($icon, color(social, $icon), 0 $icon-padding)
|
39
website/assets/css/_components/_images.sass
Normal file
39
website/assets/css/_components/_images.sass
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Images - Variables
|
||||
// ============================================================================
|
||||
|
||||
$image-background : color(grey, light)
|
||||
$image-profile-margin : 1rem 3rem
|
||||
$image-profile-width : $width-profile
|
||||
$image-ratio : $image-ratio
|
||||
|
||||
|
||||
// Images - Style
|
||||
// ============================================================================
|
||||
|
||||
// Image Containers
|
||||
// .image-container - container for figures and inline images
|
||||
// .image-hero - container for hero image for blog posts
|
||||
// .image-profile - container for profile photo
|
||||
|
||||
.image-container
|
||||
@extend .block
|
||||
margin-left: 0
|
||||
margin-right: 0
|
||||
|
||||
.image-profile
|
||||
@include size($image-profile-width)
|
||||
background: $image-background
|
||||
border-radius: 50%
|
||||
margin: $image-profile-margin
|
||||
overflow: hidden
|
||||
shape-outside: circle()
|
||||
|
||||
|
||||
// Global image ratio
|
||||
|
||||
.image-ratio
|
||||
background: $image-background
|
||||
height: 0
|
||||
overflow: hidden
|
||||
padding-bottom: (100% / $image-ratio)
|
||||
width: 100%
|
46
website/assets/css/_components/_labels.sass
Normal file
46
website/assets/css/_components/_labels.sass
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Labels - Variables
|
||||
// ============================================================================
|
||||
|
||||
$label-border-radius : $border-radius
|
||||
$label-color : color(grey, dark)
|
||||
$label-color-light : color(grey, light)
|
||||
$label-color-dark : color($theme)
|
||||
$label-padding : 0.75em
|
||||
$label-padding-small : 0.25em 0.75em
|
||||
$label-margin-side : 1rem
|
||||
|
||||
|
||||
// Labels - Style
|
||||
// ============================================================================
|
||||
|
||||
// .label - regular label
|
||||
// .label-strong - stronger version
|
||||
// .label-box - label in box with background
|
||||
// .label-tag - label in inline-tag style
|
||||
|
||||
.label
|
||||
@extend .text-label
|
||||
color: $label-color
|
||||
display: inline-block
|
||||
padding: $label-padding 0
|
||||
|
||||
.label-strong
|
||||
@extend .label
|
||||
color: $label-color-dark
|
||||
font-weight: bold
|
||||
|
||||
.label-box
|
||||
@extend .label
|
||||
background: $label-color-dark
|
||||
color: color(white)
|
||||
font-weight: 600
|
||||
padding: $label-padding
|
||||
|
||||
.label-tag
|
||||
@extend .label, .text-small
|
||||
background: $label-color-light
|
||||
border: 1px solid darken($label-color-light, 7.5)
|
||||
border-radius: $label-border-radius
|
||||
margin: 0 $label-margin-side 0 0
|
||||
padding: $label-padding-small
|
||||
vertical-align: text-top
|
60
website/assets/css/_components/_links.sass
Normal file
60
website/assets/css/_components/_links.sass
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Links - Variables
|
||||
// ============================================================================
|
||||
|
||||
$link-border : 1px solid currentColor
|
||||
$link-color : color($theme)
|
||||
$link-icon-color : color(grey, dark)
|
||||
$link-icon-color-hidden : color(grey)
|
||||
$link-icon-size : 2rem
|
||||
$link-list-padding : 0.5em
|
||||
$link-transition : $transition
|
||||
|
||||
|
||||
// Links - Style
|
||||
// ============================================================================
|
||||
|
||||
.link
|
||||
color: $link-color
|
||||
transition: $link-transition
|
||||
|
||||
.link-strong
|
||||
@extend .link
|
||||
border-bottom: $link-border
|
||||
|
||||
p a,
|
||||
.table-cell a,
|
||||
.list-item a,
|
||||
.aside a
|
||||
@extend .link-strong
|
||||
|
||||
|
||||
// Permalinks
|
||||
// :before - indicate permalink with icon
|
||||
// :hover:before - hover effect on permalink indicator
|
||||
// :active:before - different styling of active permalink indicator
|
||||
|
||||
.permalink
|
||||
@include icon(permalink, $link-icon-color-hidden, 0 $link-icon-size 0 0, $link-icon-size)
|
||||
position: relative
|
||||
|
||||
&:before
|
||||
@include position(absolute, top, left, calc(50% - #{$link-icon-size / 2}), (-$link-icon-size * 1.5))
|
||||
transition: $link-transition
|
||||
width: $link-icon-size
|
||||
|
||||
&:hover:before
|
||||
color: $link-icon-color
|
||||
|
||||
&:active:before
|
||||
color: $link-color
|
||||
|
||||
|
||||
// List of links, like social profiles
|
||||
|
||||
.link-list
|
||||
@extend .text-label
|
||||
font-weight: 600
|
||||
|
||||
& > *
|
||||
display: inline-block
|
||||
padding: $link-list-padding
|
59
website/assets/css/_components/_lists.sass
Normal file
59
website/assets/css/_components/_lists.sass
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Lists - Variables
|
||||
// ============================================================================
|
||||
|
||||
$list-alternatives : (letters, upper-latin), (roman, lower-roman)
|
||||
$list-icon-color : color($theme)
|
||||
$list-icon-size : 2.4rem
|
||||
$list-item-padding : 1em
|
||||
$list-margin-side : 5%
|
||||
$list-padding-side : 2rem
|
||||
|
||||
|
||||
// Lists - Style
|
||||
// ============================================================================
|
||||
|
||||
// .list - list of items
|
||||
// .list--bullets - unordered list with bullets
|
||||
// .list--numbers - ordered list with numbers
|
||||
// .list--letters - ordered list with letters
|
||||
// .list--roman - ordered list with roman numerals
|
||||
// .list-item - list item
|
||||
|
||||
.list
|
||||
@extend .block, .text
|
||||
padding-left: $list-margin-side
|
||||
|
||||
&--bullets
|
||||
margin-left: $list-margin-side
|
||||
|
||||
.list-item
|
||||
@include icon(bullet, none, 0 $list-padding-side 0 0, $list-icon-size)
|
||||
|
||||
&--numbers
|
||||
counter-reset: li
|
||||
margin-left: $list-margin-side
|
||||
|
||||
.list-item:before
|
||||
@extend .h3
|
||||
content: counter(li) '.'
|
||||
counter-increment: li
|
||||
padding-right: $list-padding-side
|
||||
|
||||
@each $list-type, $list-counter in $list-alternatives
|
||||
&--#{$list-type}
|
||||
@extend .list--numbers
|
||||
|
||||
.list-item:before
|
||||
content: counter(li, #{$list-counter}) '.'
|
||||
|
||||
.list-item
|
||||
margin-bottom: $list-item-padding
|
||||
text-indent: -$list-margin-side
|
||||
|
||||
&:before
|
||||
color: $list-icon-color
|
||||
display: inline-block
|
||||
line-height: 1
|
||||
text-align: center
|
||||
width: $list-icon-size
|
||||
vertical-align: middle
|
36
website/assets/css/_components/_logo.sass
Normal file
36
website/assets/css/_components/_logo.sass
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Logo - Variables
|
||||
// ============================================================================
|
||||
|
||||
$logo-size-large : nth($width-logo, 1)
|
||||
$logo-size-regular : nth($width-logo, 2)
|
||||
$logo-size-small : nth($width-logo, 3)
|
||||
$logo-size-tiny : nth($width-logo, 4)
|
||||
|
||||
|
||||
// Logo - Style
|
||||
// ============================================================================
|
||||
|
||||
// path - SVG path of logo
|
||||
// .logo--small - smaller style
|
||||
// .logo--regular - regular style
|
||||
// .logo--large - bigger style
|
||||
|
||||
.logo
|
||||
width: 100%
|
||||
|
||||
path
|
||||
width: 100%
|
||||
fill: currentColor
|
||||
|
||||
&--tiny
|
||||
vertical-align: text-bottom
|
||||
width: $logo-size-tiny
|
||||
|
||||
&--small
|
||||
width: $logo-size-small
|
||||
|
||||
&--regular
|
||||
width: $logo-size-regular
|
||||
|
||||
&--large
|
||||
width: $logo-size-large
|
88
website/assets/css/_components/_misc.sass
Normal file
88
website/assets/css/_components/_misc.sass
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Misc - Variables
|
||||
// ============================================================================
|
||||
|
||||
$x-terminal-background : color(grey)
|
||||
$x-terminal-border-radius : $border-radius * 2
|
||||
$x-terminal-color : color(black)
|
||||
$x-terminal-cursor-animation : blink 0.9s infinite
|
||||
$x-terminal-cursor : '\258B'
|
||||
$x-terminal-icon-colors : color(red), color(green), color(yellow)
|
||||
$x-terminal-icon-size : 1em
|
||||
$x-terminal-padding : 0.75em
|
||||
|
||||
$x-bubble-size : 35px
|
||||
$x-bubble-margin : 1rem
|
||||
|
||||
|
||||
// Misc - Style
|
||||
// ============================================================================
|
||||
|
||||
// Terminal window illustration to display code
|
||||
// .x-terminal - terminal window
|
||||
// .x-terminal-title - title of terminal window
|
||||
// .x-terminal-icons - container for toolbar icons
|
||||
// .x-terminal-code - code box
|
||||
// .x-terminal-code:after - cursor in last line
|
||||
// %x-terminal-icon - general style of toolbar icons
|
||||
|
||||
.x-terminal
|
||||
background: $x-terminal-background
|
||||
border-radius: $x-terminal-border-radius
|
||||
color: $x-terminal-color
|
||||
width: 100%
|
||||
|
||||
&--cursor
|
||||
.code:after
|
||||
animation: $x-terminal-cursor-animation
|
||||
opacity: 1
|
||||
content: $x-terminal-cursor
|
||||
|
||||
.x-terminal-title
|
||||
text-align: center
|
||||
padding: $x-terminal-padding
|
||||
|
||||
.x-terminal-icons
|
||||
padding: $x-terminal-padding
|
||||
position: absolute
|
||||
|
||||
&:before
|
||||
@extend %x-terminal-icon
|
||||
content: ''
|
||||
background: nth($x-terminal-icon-colors, 1)
|
||||
|
||||
span
|
||||
@extend %x-terminal-icon
|
||||
background: nth($x-terminal-icon-colors, 2)
|
||||
|
||||
&:after
|
||||
@extend %x-terminal-icon
|
||||
content: ''
|
||||
background: nth($x-terminal-icon-colors, 3)
|
||||
|
||||
.x-terminal-code
|
||||
@extend .code-block-dark
|
||||
border-bottom-left-radius: $x-terminal-border-radius
|
||||
border-bottom-right-radius: $x-terminal-border-radius
|
||||
padding: $x-terminal-padding * 2
|
||||
max-width: 100%
|
||||
width: 100%
|
||||
white-space: pre-wrap
|
||||
|
||||
&.code-block
|
||||
margin-bottom: 0
|
||||
|
||||
%x-terminal-icon
|
||||
@include size($x-terminal-icon-size)
|
||||
display: inline-block
|
||||
float: left
|
||||
border-radius: 50%
|
||||
margin-right: $x-terminal-padding
|
||||
|
||||
|
||||
// Bubble to display colors
|
||||
|
||||
.x-bubble
|
||||
@include size($x-bubble-size)
|
||||
border-radius: 50%
|
||||
cursor: pointer
|
||||
margin-right: $x-bubble-margin
|
36
website/assets/css/_components/_quotes.sass
Normal file
36
website/assets/css/_components/_quotes.sass
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Quotes - Variables
|
||||
// ============================================================================
|
||||
|
||||
$quote-icon-color : color($theme)
|
||||
$quote-icon-size : 6rem
|
||||
$quote-padding-side : 10rem
|
||||
|
||||
|
||||
// Quotes - Style
|
||||
// ============================================================================
|
||||
|
||||
// :before - icon to emphasize blockquote
|
||||
// .quote-text - quote text content
|
||||
// .quote-text-strong - emphasized style of quote text content
|
||||
// .quote-source - source of quote (link optional)
|
||||
|
||||
.quote
|
||||
@extend .block
|
||||
@include icon(quote, color(grey), 0, $quote-icon-size)
|
||||
padding-left: $quote-padding-side
|
||||
|
||||
&:before
|
||||
@include position(relative, top, left, ($quote-icon-size / 1.75), -$quote-padding-side)
|
||||
color: $quote-icon-color
|
||||
|
||||
.quote-text
|
||||
@extend .text-quote
|
||||
|
||||
.quote-text-strong
|
||||
@extend .h2
|
||||
padding: 0
|
||||
|
||||
.quote-source
|
||||
@extend .text-meta-strong
|
||||
@include icon(dash, color(grey), 0 0.75rem 0 0)
|
||||
border: none
|
79
website/assets/css/_components/_tables.sass
Normal file
79
website/assets/css/_components/_tables.sass
Normal file
|
@ -0,0 +1,79 @@
|
|||
// Tables - Variables
|
||||
// ============================================================================
|
||||
|
||||
$table-background-color : color(white)
|
||||
$table-border-color : color(grey)
|
||||
$table-border-style : solid
|
||||
$table-border-width : 1px
|
||||
$table-color : color($theme)
|
||||
$table-head-color : color(white)
|
||||
$table-highlight-border : 3px solid color($theme)
|
||||
$table-padding : 1em
|
||||
$table-shade-color : color(grey, light)
|
||||
$table-shadow-color : color(black, dark)
|
||||
|
||||
|
||||
// Tables - Style
|
||||
// ============================================================================
|
||||
|
||||
// .table - data table
|
||||
// .table--code - table with code in first column
|
||||
// .table--params - table with parameters in first column
|
||||
// .table-row - table row
|
||||
// .table-cell - table cell
|
||||
// .table-cell--highlight - style for highlighted table cell(s)
|
||||
// .table-head-cell - table head cell
|
||||
// .table-container - block containing table
|
||||
|
||||
.table
|
||||
@extend .table-responsive, .block, .text
|
||||
vertical-align: top
|
||||
|
||||
&--code .table-cell:first-child
|
||||
background: $table-shade-color
|
||||
|
||||
&--params .table-cell:first-child
|
||||
font-weight: bold
|
||||
white-space: nowrap
|
||||
|
||||
.table-cell
|
||||
border: $table-border-width $table-border-style $table-border-color
|
||||
padding: $table-padding
|
||||
|
||||
&--highlight
|
||||
border: $table-highlight-border
|
||||
|
||||
.table-head-cell
|
||||
@extend .text-meta
|
||||
background: $table-color
|
||||
border: $table-border-width $table-border-style $table-color
|
||||
color: $table-head-color
|
||||
display: table-cell
|
||||
padding: $table-padding
|
||||
|
||||
.table-container
|
||||
@extend .responsive-container
|
||||
|
||||
|
||||
// Responsive Table Markup
|
||||
// adapted from David Bushell, http://codepen.io/dbushell/pen/wGaamR
|
||||
|
||||
@media(max-width: #{$screen-size-large})
|
||||
.table-responsive
|
||||
@include scroll-shadow-base($table-shadow-color)
|
||||
display: inline-block
|
||||
overflow-x: auto
|
||||
width: auto
|
||||
-webkit-overflow-scrolling: touch
|
||||
|
||||
.table-cell
|
||||
&:first-child
|
||||
@include scroll-shadow-cover(left, $table-background-color)
|
||||
|
||||
&:last-child
|
||||
@include scroll-shadow-cover(right, $table-background-color)
|
||||
|
||||
.table-responsive.table--code
|
||||
.table-cell
|
||||
&:first-child
|
||||
@include scroll-shadow-cover(left, $table-shade-color)
|
44
website/assets/css/_components/_tooltips.sass
Normal file
44
website/assets/css/_components/_tooltips.sass
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Tooltips - Variables
|
||||
// ============================================================================
|
||||
|
||||
$tooltip-background : color(black)
|
||||
$tooltip-border-radius : $border-radius
|
||||
$tooltip-color : color(white)
|
||||
$tooltip-padding : 0.15rem 1rem
|
||||
|
||||
|
||||
// Tooltips - Style
|
||||
// ============================================================================
|
||||
|
||||
// [data-tooltip] - tooltip
|
||||
// :after - tooltip content
|
||||
// :hover - display tooltip on hover
|
||||
// .visible - makes tooltip visible
|
||||
|
||||
[data-tooltip]
|
||||
display: inline
|
||||
position: relative
|
||||
|
||||
&:after
|
||||
@extend .text, .text-small
|
||||
@include position(absolute, top, left, 125%, 50%)
|
||||
background: $tooltip-background
|
||||
border-radius: $tooltip-border-radius
|
||||
color: $tooltip-color
|
||||
content: attr(data-tooltip)
|
||||
opacity: 0
|
||||
padding: $tooltip-padding
|
||||
text-shadow: none
|
||||
text-transform: none
|
||||
transform: translateX(-50%) translateY(-2px)
|
||||
transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1)
|
||||
visibility: hidden
|
||||
white-space: nowrap
|
||||
z-index: 200
|
||||
|
||||
&:hover:after,
|
||||
&.visible:after
|
||||
display: block
|
||||
opacity: 1
|
||||
transform: translateX(-50%) translateY(0)
|
||||
visibility: visible
|
25
website/assets/css/_layout/_article.sass
Normal file
25
website/assets/css/_layout/_article.sass
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Article - Variables
|
||||
// ============================================================================
|
||||
|
||||
$article-header-margin : 6rem
|
||||
$article-footer-margin : 1.5rem
|
||||
|
||||
|
||||
// Article - Style
|
||||
// ============================================================================
|
||||
|
||||
article p,
|
||||
article .list
|
||||
@extend .text-big
|
||||
|
||||
.article-header
|
||||
margin-bottom: $article-header-margin
|
||||
|
||||
.article-title
|
||||
@extend .h1
|
||||
|
||||
.article-meta
|
||||
@extend .text-meta
|
||||
|
||||
.article-footer
|
||||
margin-top: $article-footer-margin
|
53
website/assets/css/_layout/_body.sass
Normal file
53
website/assets/css/_layout/_body.sass
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Body - Variables
|
||||
// ============================================================================
|
||||
|
||||
$body-background : color(white)
|
||||
$body-color : color(black)
|
||||
$main-padding-sides : 4rem
|
||||
$main-padding-bottom : 8rem
|
||||
$main-article-margin-left : 10rem
|
||||
|
||||
|
||||
// Body - Style
|
||||
// ============================================================================
|
||||
|
||||
.body
|
||||
@extend .text
|
||||
background: $body-background
|
||||
color: $body-color
|
||||
display: flex
|
||||
flex-flow: row wrap
|
||||
|
||||
|
||||
// Main content
|
||||
// .main - main content container
|
||||
// .main--asides - main content with asides
|
||||
// .main--article - main content for articles
|
||||
|
||||
.main
|
||||
flex: 1 1 auto
|
||||
max-width: 100%
|
||||
padding: $height-navbar $main-padding-sides $main-padding-bottom $main-padding-sides
|
||||
width: $width-content - $width-aside
|
||||
|
||||
|
||||
// Remove top padding from first element if it's a level 2 headline
|
||||
|
||||
& > *:first-child > h2:first-child
|
||||
padding-top: 0
|
||||
|
||||
|
||||
// Large screens only
|
||||
|
||||
@media (min-width: #{$screen-size-large})
|
||||
&.main--asides
|
||||
margin-right: $width-aside
|
||||
|
||||
&.main--article
|
||||
margin-left: $main-article-margin-left
|
||||
|
||||
|
||||
// Sections
|
||||
|
||||
.section
|
||||
@extend .block
|
20
website/assets/css/_layout/_footer.sass
Normal file
20
website/assets/css/_layout/_footer.sass
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Footer - Variables
|
||||
// ============================================================================
|
||||
|
||||
$footer-background : color($theme) pattern($theme)
|
||||
$footer-color : color(white)
|
||||
$footer-padding : 2.75rem
|
||||
$footer-text-align : center
|
||||
|
||||
|
||||
// Footer - Style
|
||||
// ============================================================================
|
||||
|
||||
.footer
|
||||
@extend .link-list
|
||||
background: $footer-background
|
||||
color: $footer-color
|
||||
overflow: auto
|
||||
padding: $footer-padding
|
||||
text-align: $footer-text-align
|
||||
z-index: 100
|
50
website/assets/css/_layout/_header.sass
Normal file
50
website/assets/css/_layout/_header.sass
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Header - Variables
|
||||
// ============================================================================
|
||||
|
||||
$header-background : color($theme) pattern($theme)
|
||||
$header-color-highlight : color($theme, dark)
|
||||
$header-min-height : 250px
|
||||
$header-padding : 4rem 5rem 5rem
|
||||
$header-text-color : color(white)
|
||||
$header-text-shadow : 2px 2px
|
||||
$hero-credit-bottom : -2em
|
||||
$hero-credit-right : 1em
|
||||
|
||||
|
||||
// Header - Style
|
||||
// ============================================================================
|
||||
|
||||
.header
|
||||
background: $header-background
|
||||
display: flex
|
||||
flex-flow: column nowrap
|
||||
justify-content: center
|
||||
margin-top: $height-navbar
|
||||
min-height: $header-min-height
|
||||
text-align: center
|
||||
|
||||
.header-title
|
||||
@extend .h0
|
||||
color: $header-text-color
|
||||
|
||||
&.header-title--center
|
||||
@extend .text-center
|
||||
|
||||
.header-body
|
||||
color: $header-text-color
|
||||
padding: $header-padding
|
||||
text-align: left
|
||||
|
||||
.header-text
|
||||
text-shadow: $header-text-shadow $header-color-highlight
|
||||
|
||||
|
||||
// Hero image
|
||||
|
||||
.hero
|
||||
position: relative
|
||||
min-height: 0
|
||||
|
||||
.hero-credit
|
||||
@extend .text-credit
|
||||
@include position(absolute, bottom, right, $hero-credit-bottom, $hero-credit-right)
|
108
website/assets/css/_layout/_nav.sass
Normal file
108
website/assets/css/_layout/_nav.sass
Normal file
|
@ -0,0 +1,108 @@
|
|||
// Top Navigation Bar - Variables
|
||||
// ============================================================================
|
||||
|
||||
$nav-animation : slideInDown 0.5s ease-in-out
|
||||
$nav-background : color(white)
|
||||
$nav-color : color($theme)
|
||||
$nav-height : $height-navbar
|
||||
$nav-height-small : $nav-height * 0.8
|
||||
$nav-icon-size : 3.5rem
|
||||
$nav-item-spacing : 1em
|
||||
$nav-mobile-border : 1px solid
|
||||
$nav-mobile-font-size : 1.25em
|
||||
$nav-mobile-padding : 1rem
|
||||
$nav-mobile-width : 20vw
|
||||
$nav-padding : 0 0 0 2rem
|
||||
$nav-triangle-size : 8px
|
||||
|
||||
|
||||
// Top Navigation Bar - Style
|
||||
// ============================================================================
|
||||
|
||||
// .nav - top and primary navigation bar
|
||||
// .fixed - sticky version
|
||||
// .logo - special styling for logo
|
||||
// .nav-menu - menu bar containing menu items
|
||||
// .nav-item - menu list item
|
||||
// .nav-button - button to toggle mobile navigation
|
||||
// .nav-checkbox - checkbox for checkbox hack
|
||||
// .active - active menu item
|
||||
|
||||
.nav
|
||||
@extend .text-label
|
||||
@include position(absolute, top, left, 0, 0)
|
||||
@include size(100%, $nav-height)
|
||||
align-items: center
|
||||
background: $nav-background
|
||||
border-color: $nav-background
|
||||
color: $nav-color
|
||||
display: flex
|
||||
justify-content: space-between
|
||||
padding: $nav-padding
|
||||
z-index: 10
|
||||
width: 100%
|
||||
|
||||
&.fixed
|
||||
animation: $nav-animation
|
||||
background: $nav-color
|
||||
border-color: $nav-color
|
||||
color: $nav-background
|
||||
position: fixed
|
||||
|
||||
@media (min-width: #{$screen-size-small})
|
||||
height: $nav-height-small
|
||||
|
||||
.nav-menu
|
||||
@include size(100%)
|
||||
justify-content: flex-end
|
||||
border-color: inherit
|
||||
display: flex
|
||||
margin: 0
|
||||
|
||||
@media (max-width: #{$screen-size-small})
|
||||
@include position(absolute, top, left, $nav-height, 0)
|
||||
flex-flow: row wrap
|
||||
|
||||
.nav-checkbox:checked + &
|
||||
background: inherit
|
||||
|
||||
.nav-item
|
||||
@include visibility(visible)
|
||||
|
||||
& + .nav-button:before
|
||||
color: color(grey)
|
||||
|
||||
.nav-item
|
||||
align-items: center
|
||||
border-color: inherit
|
||||
display: flex
|
||||
height: 100%
|
||||
position: relative
|
||||
|
||||
&--active
|
||||
font-weight: bold
|
||||
|
||||
@media (min-width: #{$screen-size-small})
|
||||
margin-right: $nav-item-spacing
|
||||
|
||||
&--active:after
|
||||
@include triangle-down($nav-triangle-size)
|
||||
@include position(absolute, bottom, left, -$nav-triangle-size, calc(50% - #{$nav-triangle-size}))
|
||||
|
||||
@media (max-width: #{$screen-size-small})
|
||||
@include size(100%, auto)
|
||||
@include visibility(hidden)
|
||||
background: inherit
|
||||
border-top: $nav-mobile-border
|
||||
font-size: $nav-mobile-font-size
|
||||
justify-content: center
|
||||
padding: $nav-mobile-padding
|
||||
|
||||
.nav-button
|
||||
@media (max-width: #{$screen-size-small})
|
||||
@include icon(menu, none, $nav-mobile-padding 0 0 0, $nav-icon-size)
|
||||
cursor: pointer
|
||||
padding: 0 1em 1em 0
|
||||
|
||||
.nav-checkbox
|
||||
display: none
|
65
website/assets/css/_layout/_sidebar.sass
Normal file
65
website/assets/css/_layout/_sidebar.sass
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Sidebar - Variables
|
||||
// ============================================================================
|
||||
|
||||
$sidebar-breakpoint : 900px
|
||||
$sidebar-highlight-color : color($theme)
|
||||
$sidebar-margin-left : 4rem
|
||||
$sidebar-margin-right : 6rem
|
||||
$sidebar-margin-top : $height-navbar
|
||||
$sidebar-menu-spacing : 3rem
|
||||
$sidebar-small-border : 1px solid color(grey, light)
|
||||
$sidebar-small-padding : 2rem 3rem
|
||||
$sidebar-width : $width-sidebar
|
||||
|
||||
|
||||
// Sidebar - Style
|
||||
// ============================================================================
|
||||
|
||||
// .sidebar - sidebar
|
||||
// .fixed - sticky version
|
||||
// .menu - menu list in sidebar
|
||||
// .active - active menu item
|
||||
// .sidebar-label - menu label
|
||||
|
||||
.sidebar
|
||||
@media (min-width: #{$sidebar-breakpoint})
|
||||
flex: 0 0 $sidebar-width
|
||||
margin-right: $sidebar-margin-right
|
||||
margin-left: $sidebar-margin-left
|
||||
padding-top: $height-navbar
|
||||
width: $sidebar-width
|
||||
|
||||
&.fixed .sidebar-body
|
||||
@include position(fixed, top, left, $sidebar-margin-top, $sidebar-margin-left)
|
||||
@include size($sidebar-width, calc(100vh - #{$sidebar-margin-top}))
|
||||
overflow: auto
|
||||
transition: none
|
||||
|
||||
@media (max-width: #{$sidebar-breakpoint})
|
||||
border-bottom: $sidebar-small-border
|
||||
flex: 100%
|
||||
width: 100%
|
||||
|
||||
.sidebar-body
|
||||
display: flex
|
||||
flex-flow: row wrap
|
||||
|
||||
.sidebar-menu
|
||||
@media (min-width: #{$sidebar-breakpoint})
|
||||
margin-bottom: $sidebar-menu-spacing
|
||||
|
||||
@media (max-width: #{$sidebar-breakpoint})
|
||||
flex: 1
|
||||
margin: 0
|
||||
padding: $sidebar-small-padding
|
||||
border-top: $sidebar-small-border
|
||||
|
||||
&:not(:last-child)
|
||||
border-right: $sidebar-small-border
|
||||
|
||||
.active
|
||||
color: $sidebar-highlight-color
|
||||
font-weight: bold
|
||||
|
||||
.sidebar-menu[data-label]:before
|
||||
@extend .label
|
23
website/assets/css/_utils/_functions.sass
Normal file
23
website/assets/css/_utils/_functions.sass
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Functions
|
||||
// ============================================================================
|
||||
|
||||
// Helper to round to decimals (used for rem units)
|
||||
// $calculation - value or performed calculation
|
||||
|
||||
@function round-dec($calculation)
|
||||
@return round($calculation * 10) / 10
|
||||
|
||||
|
||||
// Helper for colors (refers to $colors in colors)
|
||||
// $color-name - name of predefined color (i.e. blue)
|
||||
// $color-variant - predefined hue (default: base)
|
||||
|
||||
@function color($color-name, $color-variant: base)
|
||||
@return map-get(map-get($colors, $color-name), $color-variant)
|
||||
|
||||
|
||||
// Helper for patterns, returns pattern image of color
|
||||
// $color-name - name of predefined color (i.e. blue)
|
||||
|
||||
@function pattern($color-name)
|
||||
@return url('../img/pattern_#{$color-name}.jpg') center center repeat scroll
|
96
website/assets/css/_utils/_mixins.sass
Normal file
96
website/assets/css/_utils/_mixins.sass
Normal file
|
@ -0,0 +1,96 @@
|
|||
// Mixins
|
||||
// ============================================================================
|
||||
|
||||
// Helper for position
|
||||
// $position - valid position value (static, absolute, fixed, relative)
|
||||
// $pos-y - position direction Y (top, bottom)
|
||||
// $pos-x - position direction X (left, right)
|
||||
// $pos-y-value - value of position Y direction
|
||||
// $pos-x-value - value of position X direction
|
||||
|
||||
@mixin position($position, $pos-y, $pos-x, $pos-y-value, $pos-x-value)
|
||||
position: $position
|
||||
#{$pos-y}: $pos-y-value
|
||||
#{$pos-x}: $pos-x-value
|
||||
|
||||
|
||||
// Helper for width and height
|
||||
// $width - width of element
|
||||
// $height - height of element (default: $width)
|
||||
|
||||
@mixin size($width, $height: $width)
|
||||
height: $height
|
||||
width: $width
|
||||
|
||||
|
||||
// Icon before or after an element
|
||||
// $icon-name - name of icon, refers to icon specified in settings
|
||||
// $icon-color - color of icon (default: no color specified)
|
||||
// $icon-padding - padding around icon (in shorthand style, default: 0)
|
||||
// $icon-size - font size of icon (default: no size specified)
|
||||
|
||||
@mixin icon($icon-name, $icon-color: none, $icon-padding: 0, $icon-size: none)
|
||||
&:before
|
||||
@extend %icon
|
||||
content: map-get($icons, $icon-name)
|
||||
padding: $icon-padding
|
||||
|
||||
@if $icon-color != none
|
||||
color: $icon-color
|
||||
|
||||
@if $icon-size != none
|
||||
font-size: $icon-size
|
||||
|
||||
|
||||
// Triangle pointing down
|
||||
// $triangle-size - width of the triangle
|
||||
|
||||
@mixin triangle-down($triangle-size)
|
||||
@include size(0)
|
||||
border-color: transparent
|
||||
border-style: solid
|
||||
border-top-color: inherit
|
||||
border-width: $triangle-size $triangle-size 0 $triangle-size
|
||||
content: ''
|
||||
|
||||
|
||||
// Make element visible or invisible (included as mixin to work in media queries)
|
||||
// $visibility-state - visible or invisible
|
||||
// $visibility-transition - transition (default: $transition)
|
||||
|
||||
@mixin visibility($visibility-state, $visibility-transition: $transition)
|
||||
transition: $visibility-transition
|
||||
|
||||
@if $visibility-state == hidden
|
||||
opacity: 0
|
||||
pointer-events: none
|
||||
visibility: hidden
|
||||
|
||||
@else
|
||||
opacity: 1
|
||||
pointer-events: initial
|
||||
visibility: visible
|
||||
|
||||
|
||||
// Scroll shadows for reponsive tables
|
||||
// adapted from David Bushell, http://codepen.io/dbushell/pen/wGaamR
|
||||
// $scroll-shadow-color - color of shadow
|
||||
// $scroll-shadow-side - side to cover shadow (left or right)
|
||||
// $scroll-shadow-background - original background color to match
|
||||
|
||||
@mixin scroll-shadow-base($scroll-shadow-color)
|
||||
background: radial-gradient(left, ellipse, rgba(0,0,0, .2) 0%, rgba(0,0,0, 0) 75%) 0 center, radial-gradient(right, ellipse, rgba(0,0,0, .2) 0%, rgba(0,0,0, 0) 75%) 100% center
|
||||
background-size: 10px 100%, 10px 100%
|
||||
background-attachment: scroll, scroll
|
||||
background-repeat: no-repeat
|
||||
|
||||
@mixin scroll-shadow-cover($scroll-shadow-side, $scroll-shadow-background)
|
||||
$scroll-gradient-direction: right !default
|
||||
|
||||
@if $scroll-shadow-side == right
|
||||
$scroll-gradient-direction: left
|
||||
background-position: 100% 0
|
||||
|
||||
background-image: linear-gradient(to #{$scroll-gradient-direction}, rgba($scroll-shadow-background, 1) 50%, rgba($scroll-shadow-background, 0) 100%)
|
||||
background-repeat: no-repeat
|
||||
background-size: 20px 100%
|
93
website/assets/css/_variables.scss
Normal file
93
website/assets/css/_variables.scss
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Variables
|
||||
// ============================================================================
|
||||
|
||||
// Settings and Sizes
|
||||
|
||||
$theme : blue !default;
|
||||
|
||||
$base-font-size : 10px !default;
|
||||
|
||||
$width-logo : 500px, 250px, 100px, 65px !default;
|
||||
$width-content : 800px;
|
||||
$width-aside : 300px;
|
||||
$width-sidebar : 230px;
|
||||
$width-profile : 160px;
|
||||
$height-navbar : 55px;
|
||||
|
||||
$border-radius : 4px;
|
||||
$image-ratio : 3 / 1;
|
||||
$transition : all 0.2s;
|
||||
$social-buttons : twitter, reddit, hackernews, producthunt;
|
||||
|
||||
$screen-size-small : 480px;
|
||||
$screen-size-medium : 800px;
|
||||
$screen-size-large : 1200px;
|
||||
|
||||
|
||||
// Grid Columns
|
||||
|
||||
$columns: ( fifth, 20% ),
|
||||
( quarter, 25% ),
|
||||
( third, (100% / 3) ),
|
||||
( half, 50% ),
|
||||
( two-thirds, (100% / 1.5) ),
|
||||
( full, 100% );
|
||||
|
||||
// Fonts
|
||||
|
||||
$font-primary : Lato, Tahoma, Geneva, sans-serif !default;
|
||||
$font-secondary : 'Work Sans', 'Arial Black', Gadget, sans-serif !default;
|
||||
$font-code : 'Source Code Pro', Consolas, 'Andale Mono', Menlo, Monaco, Courier, monospace !default;
|
||||
$font-icons : Icomoon !default;
|
||||
|
||||
|
||||
// Colors
|
||||
// only to be used with the color() function, i.e. color(blue, light)
|
||||
|
||||
$colors: (
|
||||
blue : ( base: #09a3d5, dark: #008ebc, light: #e2f7fe ),
|
||||
red : ( base: #e4514f, dark: #dd2422, light: #fceeed ),
|
||||
grey : ( base: #dddddd, dark: #999999, light: #f6f6f6 ),
|
||||
black : ( base: #222222, dark: #000000 ),
|
||||
white : ( base: #ffffff ),
|
||||
yellow : ( base: #f4c025 ),
|
||||
green : ( base: #3ec930 ),
|
||||
purple : ( base: #8130c9 ),
|
||||
orange : ( base: #f47725 ),
|
||||
|
||||
social: (
|
||||
twitter : #5ea9dd,
|
||||
hackernews : #ff6600,
|
||||
reddit : #ff4500,
|
||||
producthunt : #da552f,
|
||||
github : #000000,
|
||||
linkedin : #0077b5,
|
||||
facebook : #3b5999,
|
||||
medium : #02b875,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
// Icons
|
||||
|
||||
$icons: (
|
||||
website : '\1f310',
|
||||
search : '\1f50d',
|
||||
feed : '\1f525',
|
||||
quote : '\275d',
|
||||
twitter : '\e900',
|
||||
github : '\e901',
|
||||
producthunt : '\e902',
|
||||
linkedin : '\e903',
|
||||
hackernews : '\e904',
|
||||
reddit : '\e905',
|
||||
facebook : '\e906',
|
||||
medium : '\e907',
|
||||
codepen : '\e908',
|
||||
dash : '\2014',
|
||||
bullet : '\2022',
|
||||
menu : '\2261',
|
||||
close : '\2715',
|
||||
copyright : '\00a9',
|
||||
permalink : '\0023',
|
||||
);
|
42
website/assets/css/_vendors/_displacy.sass
Normal file
42
website/assets/css/_vendors/_displacy.sass
Normal file
|
@ -0,0 +1,42 @@
|
|||
// displaCy Custom Visualization - Variables
|
||||
// ============================================================================
|
||||
|
||||
$displacy-classes: ( bad: color(red), good: color(green), highlight: color(yellow), lowlight: color(grey, dark) )
|
||||
$displacy-word-margin : 3rem
|
||||
|
||||
|
||||
// displaCy Custom Visualization - Style
|
||||
// ============================================================================
|
||||
|
||||
// displaCy visualization (refers to exports from displaCy v1)
|
||||
// .word - token container
|
||||
// .word span - word
|
||||
// .arrow:before - arrow label
|
||||
// .word:after - part-of-speech tag
|
||||
// .arrow.#{$displacy-class}:before - arrow with special styling
|
||||
// .arrow.#{$displacy-class}:after - arrow head with special styling
|
||||
// .word.#{$displacy-class} span - word with special styling
|
||||
// $displacy-classes - refers to $displacy-classes in settings
|
||||
|
||||
#displacy
|
||||
width: 100%
|
||||
|
||||
.word
|
||||
margin-top: $displacy-word-margin
|
||||
|
||||
.word span
|
||||
@extend .h4
|
||||
|
||||
.arrow:before,
|
||||
.word:after
|
||||
@extend .text-label
|
||||
|
||||
@each $displacy-class, $displacy-color in $displacy-classes
|
||||
.arrow.#{$displacy-class}:before
|
||||
border-color: $displacy-color
|
||||
|
||||
.arrow.#{$displacy-class}:after
|
||||
border-top-color: $displacy-color
|
||||
|
||||
.word.#{$displacy-class} span
|
||||
color: $displacy-color
|
181
website/assets/css/_vendors/_normalize.sass
Normal file
181
website/assets/css/_vendors/_normalize.sass
Normal file
|
@ -0,0 +1,181 @@
|
|||
// Normalize
|
||||
// ============================================================================
|
||||
|
||||
// adapted from normalize.css, https://github.com/necolas/normalize.css
|
||||
|
||||
html
|
||||
font-family: sans-serif
|
||||
-ms-text-size-adjust: 100%
|
||||
-webkit-text-size-adjust: 100%
|
||||
|
||||
body
|
||||
margin: 0
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary
|
||||
display: block
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video
|
||||
display: inline-block
|
||||
vertical-align: baseline
|
||||
|
||||
audio:not([controls])
|
||||
display: none
|
||||
height: 0
|
||||
|
||||
[hidden],
|
||||
template
|
||||
display: none
|
||||
|
||||
a
|
||||
background-color: transparent
|
||||
|
||||
a:active,
|
||||
a:hover
|
||||
outline: 0
|
||||
|
||||
abbr[title]
|
||||
border-bottom: none
|
||||
text-decoration: underline
|
||||
text-decoration: underline dotted
|
||||
|
||||
b,
|
||||
strong
|
||||
font-weight: inherit
|
||||
|
||||
b,
|
||||
strong
|
||||
font-weight: bolder
|
||||
|
||||
dfn
|
||||
font-style: italic
|
||||
|
||||
h1
|
||||
font-size: 2em
|
||||
margin: 0.67em 0
|
||||
|
||||
mark
|
||||
background-color: #ff0
|
||||
color: #000
|
||||
|
||||
small
|
||||
font-size: 80%
|
||||
|
||||
sub,
|
||||
sup
|
||||
font-size: 75%
|
||||
line-height: 0
|
||||
position: relative
|
||||
vertical-align: baseline
|
||||
|
||||
sup
|
||||
top: -0.5em
|
||||
|
||||
sub
|
||||
bottom: -0.25em
|
||||
|
||||
img
|
||||
border: 0
|
||||
|
||||
svg:not(:root)
|
||||
overflow: hidden
|
||||
|
||||
figure
|
||||
margin: 1em 40px
|
||||
|
||||
hr
|
||||
box-sizing: content-box
|
||||
height: 0
|
||||
overflow: visible
|
||||
|
||||
pre
|
||||
overflow: auto
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp
|
||||
font-family: monospace, monospace
|
||||
font-size: 1em
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea
|
||||
font: inherit
|
||||
margin: 0
|
||||
|
||||
button
|
||||
overflow: visible
|
||||
|
||||
button,
|
||||
select
|
||||
text-transform: none
|
||||
|
||||
button,
|
||||
html input[type="button"],
|
||||
input[type="reset"],
|
||||
input[type="submit"]
|
||||
-webkit-appearance: button
|
||||
cursor: pointer
|
||||
|
||||
button[disabled],
|
||||
html input[disabled]
|
||||
cursor: default
|
||||
|
||||
input,
|
||||
button
|
||||
&::-moz-focus-inner
|
||||
border: 0
|
||||
padding: 0
|
||||
|
||||
&:-moz-focusring
|
||||
outline: 1px dotted ButtonText
|
||||
|
||||
input
|
||||
line-height: normal
|
||||
|
||||
&[type="checkbox"],
|
||||
&[type="radio"]
|
||||
box-sizing: border-box
|
||||
padding: 0
|
||||
|
||||
&[type="number"]::-webkit-inner-spin-button,
|
||||
&[type="number"]::-webkit-outer-spin-button
|
||||
height: auto
|
||||
|
||||
&[type="search"]
|
||||
-webkit-appearance: textfield
|
||||
|
||||
&[type="search"]::-webkit-search-cancel-button,
|
||||
&[type="search"]::-webkit-search-decoration
|
||||
-webkit-appearance: none
|
||||
|
||||
fieldset
|
||||
border: 1px solid #c0c0c0
|
||||
margin: 0 2px
|
||||
padding: 0.35em 0.625em 0.75em
|
||||
|
||||
legend
|
||||
border: 0
|
||||
padding: 0
|
||||
|
||||
textarea
|
||||
overflow: auto
|
||||
|
||||
optgroup
|
||||
font-weight: bold
|
77
website/assets/css/_vendors/_prism.sass
Normal file
77
website/assets/css/_vendors/_prism.sass
Normal file
|
@ -0,0 +1,77 @@
|
|||
// prism.js Syntax Highlighting
|
||||
// ============================================================================
|
||||
|
||||
// Commment, prolog, doctype, CDATA, punctuation
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata,
|
||||
.token.punctuation
|
||||
color: color(grey, dark)
|
||||
|
||||
|
||||
// Property, tag, constant, symbol, deleted
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted
|
||||
color: color(green)
|
||||
|
||||
|
||||
// Boolean, number
|
||||
|
||||
.token.boolean,
|
||||
.token.number
|
||||
color: color(purple)
|
||||
|
||||
|
||||
// Selector, attribute name, string, char, built in, inserted
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted
|
||||
color: color(blue)
|
||||
|
||||
|
||||
// Operator, entity, URL, CSS string, variable
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string,
|
||||
.token.variable
|
||||
color: color(red)
|
||||
|
||||
|
||||
// @-rule, attribute value, function
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.function
|
||||
color: color(blue)
|
||||
|
||||
|
||||
// Keyword
|
||||
|
||||
.token.keyword
|
||||
color: color(red)
|
||||
|
||||
|
||||
// Regex, important
|
||||
|
||||
.token.regex,
|
||||
.token.important
|
||||
color: color(yellow)
|
||||
|
||||
|
||||
// Italic
|
||||
|
||||
.token.italic
|
||||
font-style: italic
|
60
website/assets/css/style.sass
Normal file
60
website/assets/css/style.sass
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Style
|
||||
// ============================================================================
|
||||
|
||||
// Variables
|
||||
|
||||
@import variables
|
||||
|
||||
|
||||
// Utilities
|
||||
|
||||
@import _utils/functions
|
||||
@import _utils/mixins
|
||||
|
||||
|
||||
// Base
|
||||
|
||||
@import _base/animations
|
||||
@import _base/fonts
|
||||
@import _base/reset
|
||||
@import _base/grid
|
||||
@import _base/typography
|
||||
|
||||
|
||||
// Layout
|
||||
|
||||
@import _layout/article
|
||||
@import _layout/body
|
||||
@import _layout/footer
|
||||
@import _layout/header
|
||||
@import _layout/nav
|
||||
@import _layout/sidebar
|
||||
|
||||
|
||||
// Components
|
||||
|
||||
@import _components/alerts
|
||||
@import _components/asides
|
||||
@import _components/boxes
|
||||
@import _components/buttons
|
||||
@import _components/cards
|
||||
@import _components/code
|
||||
@import _components/dividers
|
||||
@import _components/embeds
|
||||
@import _components/forms
|
||||
@import _components/icons
|
||||
@import _components/links
|
||||
@import _components/logo
|
||||
@import _components/images
|
||||
@import _components/labels
|
||||
@import _components/lists
|
||||
@import _components/misc
|
||||
@import _components/quotes
|
||||
@import _components/tables
|
||||
@import _components/tooltips
|
||||
|
||||
|
||||
// Vendors
|
||||
|
||||
@import _vendors/prism
|
||||
@import _vendors/displacy
|
6
website/assets/css/style_blog.sass
Normal file
6
website/assets/css/style_blog.sass
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Style Blog
|
||||
// ============================================================================
|
||||
|
||||
$theme: red
|
||||
|
||||
@import style
|
BIN
website/assets/fonts/icomoon.eot
Normal file
BIN
website/assets/fonts/icomoon.eot
Normal file
Binary file not shown.
27
website/assets/fonts/icomoon.svg
Normal file
27
website/assets/fonts/icomoon.svg
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Generated by IcoMoon</metadata>
|
||||
<defs>
|
||||
<font id="icomoon" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="#" glyph-name="link" d="M440.236 324.234c-13.31 0-26.616 5.076-36.77 15.23-95.134 95.136-95.134 249.934 0 345.070l192 192c46.088 46.086 107.36 71.466 172.534 71.466s126.448-25.38 172.536-71.464c95.132-95.136 95.132-249.934 0-345.070l-87.766-87.766c-20.308-20.308-53.23-20.308-73.54 0-20.306 20.306-20.306 53.232 0 73.54l87.766 87.766c54.584 54.586 54.584 143.404 0 197.99-26.442 26.442-61.6 41.004-98.996 41.004s-72.552-14.562-98.996-41.006l-192-191.998c-54.586-54.586-54.586-143.406 0-197.992 20.308-20.306 20.306-53.232 0-73.54-10.15-10.152-23.462-15.23-36.768-15.23zM256-52c-65.176 0-126.45 25.38-172.534 71.464-95.134 95.136-95.134 249.934 0 345.070l87.764 87.764c20.308 20.306 53.234 20.306 73.54 0 20.308-20.306 20.308-53.232 0-73.54l-87.764-87.764c-54.586-54.586-54.586-143.406 0-197.992 26.44-26.44 61.598-41.002 98.994-41.002s72.552 14.562 98.998 41.006l192 191.998c54.584 54.586 54.584 143.406 0 197.992-20.308 20.308-20.306 53.232 0 73.54 20.306 20.306 53.232 20.306 73.54-0.002 95.132-95.134 95.132-249.932 0.002-345.068l-192.002-192c-46.090-46.088-107.364-71.466-172.538-71.466z" />
|
||||
<glyph unicode="•" glyph-name="Bullet" d="M768 426.667c0 70.699-28.672 134.699-74.965 181.035-46.336 46.293-110.336 74.965-181.035 74.965-70.656 0-134.656-28.672-180.992-74.965-46.336-46.336-75.008-110.336-75.008-181.035 0-70.656 28.672-134.656 75.008-180.992s110.336-75.008 180.992-75.008c70.699 0 134.699 28.672 181.035 75.008 46.293 46.336 74.965 110.336 74.965 180.992z" />
|
||||
<glyph unicode="≡" glyph-name="menu" d="M128 725.334h768q17.667 0 30.167-12.5t12.5-30.167-12.5-30.167-30.167-12.5h-768q-17.667 0-30.167 12.5t-12.5 30.167 12.5 30.167 30.167 12.5zM128 213.334h768q17.667 0 30.167-12.5t12.5-30.167-12.5-30.167-30.167-12.5h-768q-17.667 0-30.167 12.5t-12.5 30.167 12.5 30.167 30.167 12.5zM128 469.334h768q17.667 0 30.167-12.5t12.5-30.167-12.5-30.167-30.167-12.5h-768q-17.667 0-30.167 12.5t-12.5 30.167 12.5 30.167 30.167 12.5z" />
|
||||
<glyph unicode="✕" glyph-name="cross" d="M810.667 768q18.333 0 30.5-12.167t12.167-30.5q0-18-12.333-30.333l-268.667-268.333 268.667-268.333q12.333-12.333 12.333-30.333 0-18.333-12.167-30.5t-30.5-12.167q-18 0-30.333 12.333l-268.333 268.667-268.333-268.667q-12.333-12.333-30.333-12.333-18.333 0-30.5 12.167t-12.167 30.5q0 18 12.333 30.333l268.667 268.333-268.667 268.333q-12.333 12.333-12.333 30.333 0 18.333 12.167 30.5t30.5 12.167q18 0 30.333-12.333l268.333-268.667 268.333 268.667q12.333 12.333 30.333 12.333z" />
|
||||
<glyph unicode="❝" glyph-name="Quote" d="M1024 64v384h-256c0 141.12 114.752 256 256 256v128c-211.744 0-384-172.256-384-384v-384h384zM384 64v384h-256c0 141.12 114.752 256 256 256v128c-211.744 0-384-172.256-384-384v-384h384z" />
|
||||
<glyph unicode="" glyph-name="Twitter" d="M1024 733.6c-37.6-16.8-78.2-28-120.6-33 43.4 26 76.6 67.2 92.4 116.2-40.6-24-85.6-41.6-133.4-51-38.4 40.8-93 66.2-153.4 66.2-116 0-210-94-210-210 0-16.4 1.8-32.4 5.4-47.8-174.6 8.8-329.4 92.4-433 219.6-18-31-28.4-67.2-28.4-105.6 0-72.8 37-137.2 93.4-174.8-34.4 1-66.8 10.6-95.2 26.2 0-0.8 0-1.8 0-2.6 0-101.8 72.4-186.8 168.6-206-17.6-4.8-36.2-7.4-55.4-7.4-13.6 0-26.6 1.4-39.6 3.8 26.8-83.4 104.4-144.2 196.2-146-72-56.4-162.4-90-261-90-17 0-33.6 1-50.2 3 93.2-59.8 203.6-94.4 322.2-94.4 386.4 0 597.8 320.2 597.8 597.8 0 9.2-0.2 18.2-0.6 27.2 41 29.4 76.6 66.4 104.8 108.6z" />
|
||||
<glyph unicode="" glyph-name="Github" d="M512.008 947.358c-282.738 0-512.008-229.218-512.008-511.998 0-226.214 146.704-418.132 350.136-485.836 25.586-4.738 34.992 11.11 34.992 24.632 0 12.204-0.48 52.542-0.696 95.324-142.448-30.976-172.504 60.41-172.504 60.41-23.282 59.176-56.848 74.916-56.848 74.916-46.452 31.778 3.51 31.124 3.51 31.124 51.4-3.61 78.476-52.766 78.476-52.766 45.672-78.27 119.776-55.64 149.004-42.558 4.588 33.086 17.852 55.68 32.506 68.464-113.73 12.942-233.276 56.85-233.276 253.032 0 55.898 20.004 101.574 52.76 137.428-5.316 12.9-22.854 64.972 4.952 135.5 0 0 43.006 13.752 140.84-52.49 40.836 11.348 84.636 17.036 128.154 17.234 43.502-0.198 87.336-5.886 128.256-17.234 97.734 66.244 140.656 52.49 140.656 52.49 27.872-70.528 10.35-122.6 5.036-135.5 32.82-35.856 52.694-81.532 52.694-137.428 0-196.654-119.778-239.95-233.79-252.624 18.364-15.89 34.724-47.046 34.724-94.812 0-68.508-0.596-123.644-0.596-140.508 0-13.628 9.222-29.594 35.172-24.566 203.322 67.776 349.842 259.626 349.842 485.768 0 282.78-229.234 511.998-511.992 511.998z" />
|
||||
<glyph unicode="" glyph-name="product-hunt" d="M657.143 515.428q0-32-22.571-54.286t-54.571-22.286h-144.571v153.714h144.571q32 0 54.571-22.571t22.571-54.571zM759.429 515.428q0 74.286-52.286 126.857t-127.143 52.571h-247.429v-512h102.857v153.714h144.571q74.286 0 126.857 52.286t52.571 126.571zM1024 438.857q0-104-40.571-198.857t-109.143-163.429-163.429-109.143-198.857-40.571-198.857 40.571-163.429 109.143-109.143 163.429-40.571 198.857 40.571 198.857 109.143 163.429 163.429 109.143 198.857 40.571 198.857-40.571 163.429-109.143 109.143-163.429 40.571-198.857z" />
|
||||
<glyph unicode="" glyph-name="linkedin-square" horiz-adv-x="878" d="M135.429 142.857h132v396.571h-132v-396.571zM276 661.714q-0.571 29.714-20.571 49.143t-53.143 19.429-54-19.429-20.857-49.143q0-29.143 20.286-48.857t52.857-19.714h0.571q33.714 0 54.286 19.714t20.571 48.857zM610.286 142.857h132v227.429q0 88-41.714 133.143t-110.286 45.143q-77.714 0-119.429-66.857h1.143v57.714h-132q1.714-37.714 0-396.571h132v221.714q0 21.714 4 32 8.571 20 25.714 34t42.286 14q66.286 0 66.286-89.714v-212zM877.714 713.143v-548.571q0-68-48.286-116.286t-116.286-48.286h-548.571q-68 0-116.286 48.286t-48.286 116.286v548.571q0 68 48.286 116.286t116.286 48.286h548.571q68 0 116.286-48.286t48.286-116.286z" />
|
||||
<glyph unicode="" glyph-name="Hacker-News" horiz-adv-x="878" d="M462.286 386.286l152 285.143h-64l-89.714-178.286q-13.714-27.429-25.143-52.571l-24 52.571-88.571 178.286h-68.571l150.286-281.714v-185.143h57.714v181.714zM877.714 722.286v-548.571q0-68-48.286-116.286t-116.286-48.286h-548.571q-68 0-116.286 48.286t-48.286 116.286v548.571q0 68 48.286 116.286t116.286 48.286h548.571q68 0 116.286-48.286t48.286-116.286z" />
|
||||
<glyph unicode="" glyph-name="reddit" d="M256 310.857c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64s-64 28.654-64 64zM640 310.857c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64s-64 28.654-64 64zM643.112 174.079c16.482 12.986 40.376 10.154 53.364-6.332s10.152-40.378-6.334-53.366c-45.896-36.158-115.822-59.524-178.142-59.524-62.322 0-132.248 23.366-178.144 59.522-16.486 12.99-19.32 36.882-6.332 53.368 12.99 16.482 36.882 19.318 53.366 6.332 26.422-20.818 78.722-43.222 131.11-43.222s104.688 22.404 131.112 43.222zM1024 438.857c0 70.692-57.308 128-128 128-48.116 0-89.992-26.57-111.852-65.82-65.792 35.994-145.952 59.246-233.28 64.608l76.382 171.526 146.194-42.2c13.152-37.342 48.718-64.114 90.556-64.114 53.020 0 96 42.98 96 96s-42.98 96-96 96c-36.56 0-68.342-20.442-84.554-50.514l-162.906 47.024c-18.224 5.258-37.538-3.722-45.252-21.052l-103.77-233.026c-85.138-5.996-163.262-29.022-227.636-64.236-21.864 39.25-63.766 65.804-111.882 65.804-70.692 0-128-57.308-128-128 0-52.312 31.402-97.254 76.372-117.102-8.070-24.028-12.372-49.104-12.372-74.898 0-176.73 200.576-320 448-320 247.422 0 448 143.27 448 320 0 25.792-4.3 50.862-12.368 74.886 44.97 19.85 76.368 64.802 76.368 117.114zM864 762.857c19.882 0 36-16.118 36-36s-16.118-36-36-36-36 16.118-36 36 16.118 36 36 36zM64 438.857c0 35.29 28.71 64 64 64 25.508 0 47.572-15.004 57.846-36.646-33.448-25.366-61.166-54.626-81.666-86.738-23.524 9.47-40.18 32.512-40.18 59.384zM512 2.857c-205.45 0-372 109.242-372 244s166.55 244 372 244c205.45 0 372-109.242 372-244s-166.55-244-372-244zM919.82 379.473c-20.5 32.112-48.218 61.372-81.666 86.738 10.276 21.642 32.338 36.646 57.846 36.646 35.29 0 64-28.71 64-64 0-26.872-16.656-49.914-40.18-59.384z" />
|
||||
<glyph unicode="" glyph-name="Facebook" horiz-adv-x="878" d="M713.143 877.714q68 0 116.286-48.286t48.286-116.286v-548.571q0-68-48.286-116.286t-116.286-48.286h-107.429v340h113.714l17.143 132.571h-130.857v84.571q0 32 13.429 48t52.286 16l69.714 0.571v118.286q-36 5.143-101.714 5.143-77.714 0-124.286-45.714t-46.571-129.143v-97.714h-114.286v-132.571h114.286v-340h-304q-68 0-116.286 48.286t-48.286 116.286v548.571q0 68 48.286 116.286t116.286 48.286h548.571z" />
|
||||
<glyph unicode="" glyph-name="Medium" d="M341.143 710.286v-670.286q0-14.286-7.143-24.286t-20.857-10q-9.714 0-18.857 4.571l-265.714 133.143q-12 5.714-20.286 19.143t-8.286 26.571v651.429q0 11.429 5.714 19.429t16.571 8q8 0 25.143-8.571l292-146.286q1.714-1.714 1.714-2.857zM377.714 652.571l305.143-494.857-305.143 152v342.857zM1024 642.286v-602.286q0-14.286-8-23.143t-21.714-8.857-26.857 7.429l-252 125.714zM1022.286 710.857q0-1.714-146.571-239.714t-171.714-278.571l-222.857 362.286 185.143 301.143q9.714 16 29.714 16 8 0 14.857-3.429l309.143-154.286q2.286-1.143 2.286-3.429z" />
|
||||
<glyph unicode="" glyph-name="codepen" d="M945.75 582.815l-448 298.666c-10.748 7.166-24.752 7.166-35.5 0l-448-298.666c-8.902-5.934-14.25-15.926-14.25-26.624v-298.666c0-10.7 5.348-20.692 14.25-26.624l448-298.666c5.374-3.584 11.562-5.376 17.75-5.376s12.376 1.792 17.75 5.376l448 298.666c8.902 5.934 14.25 15.926 14.25 26.624v298.666c0 10.698-5.348 20.69-14.25 26.624zM480 295.981l-166.312 110.876 166.312 110.874 166.312-110.874-166.312-110.876zM512 573.315v221.75l358.31-238.876-166.31-110.874-192 128zM448 573.315l-192-128-166.312 110.874 358.312 238.876v-221.75zM198.312 406.857l-134.312-89.542v179.082l134.312-89.54zM256 368.399l192-128v-221.748l-358.312 238.872 166.312 110.876zM512 240.399l192 128 166.312-110.876-358.312-238.874v221.75zM761.688 406.857l134.312 89.54v-179.084l-134.312 89.544z" />
|
||||
<glyph unicode="🌐" glyph-name="Globe" d="M480 896c-265.096 0-480-214.904-480-480 0-265.098 214.904-480 480-480 265.098 0 480 214.902 480 480 0 265.096-214.902 480-480 480zM751.59 256c8.58 40.454 13.996 83.392 15.758 128h127.446c-3.336-44.196-13.624-87.114-30.68-128h-112.524zM208.41 576c-8.58-40.454-13.996-83.392-15.758-128h-127.444c3.336 44.194 13.622 87.114 30.678 128h112.524zM686.036 576c9.614-40.962 15.398-83.854 17.28-128h-191.316v128h174.036zM512 640v187.338c14.59-4.246 29.044-11.37 43.228-21.37 26.582-18.74 52.012-47.608 73.54-83.486 14.882-24.802 27.752-52.416 38.496-82.484h-155.264zM331.232 722.484c21.528 35.878 46.956 64.748 73.54 83.486 14.182 10 28.638 17.124 43.228 21.37v-187.34h-155.264c10.746 30.066 23.616 57.68 38.496 82.484zM448 576v-128h-191.314c1.88 44.146 7.666 87.038 17.278 128h174.036zM95.888 256c-17.056 40.886-27.342 83.804-30.678 128h127.444c1.762-44.608 7.178-87.546 15.758-128h-112.524zM256.686 384h191.314v-128h-174.036c-9.612 40.96-15.398 83.854-17.278 128zM448 192v-187.34c-14.588 4.246-29.044 11.372-43.228 21.37-26.584 18.74-52.014 47.61-73.54 83.486-14.882 24.804-27.75 52.418-38.498 82.484h155.266zM628.768 109.516c-21.528-35.876-46.958-64.746-73.54-83.486-14.184-9.998-28.638-17.124-43.228-21.37v187.34h155.266c-10.746-30.066-23.616-57.68-38.498-82.484zM512 256v128h191.314c-1.88-44.146-7.666-87.040-17.28-128h-174.034zM767.348 448c-1.762 44.608-7.178 87.546-15.758 128h112.524c17.056-40.886 27.344-83.806 30.68-128h-127.446zM830.658 640h-95.9c-18.638 58.762-44.376 110.294-75.316 151.428 42.536-20.34 81.058-47.616 114.714-81.272 21.48-21.478 40.362-44.938 56.502-70.156zM185.844 710.156c33.658 33.658 72.18 60.932 114.714 81.272-30.942-41.134-56.676-92.666-75.316-151.428h-95.898c16.138 25.218 35.022 48.678 56.5 70.156zM129.344 192h95.898c18.64-58.762 44.376-110.294 75.318-151.43-42.536 20.34-81.058 47.616-114.714 81.274-21.48 21.478-40.364 44.938-56.502 70.156zM774.156 121.844c-33.656-33.658-72.18-60.934-114.714-81.274 30.942 41.134 56.678 92.668 75.316 151.43h95.9c-16.14-25.218-35.022-48.678-56.502-70.156z" />
|
||||
<glyph unicode="🔍" glyph-name="Search" d="M426.667 896q78 0 149.167-30.5t122.5-81.833 81.833-122.5 30.5-149.167q0-67-21.833-128.333t-62.167-111.333l242.333-242q12.333-12.333 12.333-30.333 0-18.333-12.167-30.5t-30.5-12.167q-18 0-30.333 12.333l-242 242.333q-50-40.333-111.333-62.167t-128.333-21.833q-78 0-149.167 30.5t-122.5 81.833-81.833 122.5-30.5 149.167 30.5 149.167 81.833 122.5 122.5 81.833 149.167 30.5zM426.667 810.667q-60.667 0-116-23.667t-95.333-63.667-63.667-95.333-23.667-116 23.667-116 63.667-95.333 95.333-63.667 116-23.667 116 23.667 95.333 63.667 63.667 95.333 23.667 116-23.667 116-63.667 95.333-95.333 63.667-116 23.667z" />
|
||||
<glyph unicode="🔥" glyph-name="feed" horiz-adv-x="805" d="M219.429 182.857q0-45.714-32-77.714t-77.714-32-77.714 32-32 77.714 32 77.714 77.714 32 77.714-32 32-77.714zM512 112.571q1.143-16-9.714-27.429-10.286-12-26.857-12h-77.143q-14.286 0-24.571 9.429t-11.429 23.714q-12.571 130.857-105.429 223.714t-223.714 105.429q-14.286 1.143-23.714 11.429t-9.429 24.571v77.143q0 16.571 12 26.857 9.714 9.714 24.571 9.714h2.857q91.429-7.429 174.857-46t148-103.714q65.143-64.571 103.714-148t46-174.857zM804.571 111.428q1.143-15.429-10.286-26.857-10.286-11.429-26.286-11.429h-81.714q-14.857 0-25.429 10t-11.143 24.286q-6.857 122.857-57.714 233.429t-132.286 192-192 132.286-233.429 58.286q-14.286 0.571-24.286 11.143t-10 24.857v81.714q0 16 11.429 26.286 10.286 10.286 25.143 10.286h1.714q149.714-7.429 286.571-68.571t243.143-168q106.857-106.286 168-243.143t68.571-286.571z" />
|
||||
</font></defs></svg>
|
After Width: | Height: | Size: 13 KiB |
BIN
website/assets/fonts/icomoon.ttf
Normal file
BIN
website/assets/fonts/icomoon.ttf
Normal file
Binary file not shown.
BIN
website/assets/fonts/icomoon.woff
Normal file
BIN
website/assets/fonts/icomoon.woff
Normal file
Binary file not shown.
BIN
website/assets/fonts/lato-bold.eot
Executable file
BIN
website/assets/fonts/lato-bold.eot
Executable file
Binary file not shown.
2787
website/assets/fonts/lato-bold.svg
Executable file
2787
website/assets/fonts/lato-bold.svg
Executable file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 197 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user