Initial commit
This commit is contained in:
commit
1f637ed41e
33 changed files with 832 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
public/
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "themes/hugo-tania"]
|
||||||
|
path = themes/hugo-tania
|
||||||
|
url = https://github.com/WingLim/hugo-tania
|
6
archetypes/default.md
Normal file
6
archetypes/default.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
title: "{{ replace .Name "-" " " | title }}"
|
||||||
|
date: {{ .Date }}
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
1
build_blog
Executable file
1
build_blog
Executable file
|
@ -0,0 +1 @@
|
||||||
|
rm -rf public && hugo && rsync -av --delete public/* renne@personal:/home/renne/blog/content
|
66
config.yaml
Normal file
66
config.yaml
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
baseurl: "https://rennerocha.com/"
|
||||||
|
languageCode: "pt-br"
|
||||||
|
title: "Renne Rocha"
|
||||||
|
theme: "hugo-tania"
|
||||||
|
paginate: 6
|
||||||
|
|
||||||
|
params:
|
||||||
|
author: "Renne Rocha"
|
||||||
|
|
||||||
|
siteName: "Hugo Tania is Amazing"
|
||||||
|
siteDesc: "Hugo is Absurdly Fast!"
|
||||||
|
|
||||||
|
|
||||||
|
colorScheme:
|
||||||
|
toggle: true
|
||||||
|
default: auto
|
||||||
|
|
||||||
|
# Limit how many categories filter show above search input.
|
||||||
|
# Default to 5
|
||||||
|
maxCategoryToShow: 10
|
||||||
|
|
||||||
|
# Show your socail information with icon on index bio with `_index.md` content.
|
||||||
|
socialOptions:
|
||||||
|
email: "renne@rocha.dev.br"
|
||||||
|
github: "https://github.com/rennerocha"
|
||||||
|
twitter: "https://twitter.com/rennerocha"
|
||||||
|
|
||||||
|
# Comments settings
|
||||||
|
comments:
|
||||||
|
enabled: true
|
||||||
|
provider: giscus
|
||||||
|
|
||||||
|
giscus:
|
||||||
|
repo: WingLim/hugo-tania
|
||||||
|
id: MDEwOlJlcG9zaXRvcnkzMTYyNjQzMDc=
|
||||||
|
category:
|
||||||
|
name: Comments
|
||||||
|
id: DIC_kwDOEtnPc84B_WKP
|
||||||
|
|
||||||
|
menu:
|
||||||
|
header:
|
||||||
|
- name: Articles
|
||||||
|
url: "/articles/"
|
||||||
|
footer:
|
||||||
|
- name: RSS
|
||||||
|
url: "/index.xml"
|
||||||
|
|
||||||
|
markup:
|
||||||
|
highlight:
|
||||||
|
noClasses: false
|
||||||
|
lineNos: true
|
||||||
|
codeFences: true
|
||||||
|
guessSyntax: false
|
||||||
|
hl_Lines: ""
|
||||||
|
lineNoStart: 1
|
||||||
|
lineNos: false
|
||||||
|
lineNumbersInTable: true
|
||||||
|
noClasses: true
|
||||||
|
style: "monokai"
|
||||||
|
tabWidth: 4
|
||||||
|
goldmark:
|
||||||
|
renderer:
|
||||||
|
unsafe: true
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
home: ["HTML", "RSS", "JSON"]
|
159
content/posts/validando-dados-extraidos-com-scrapy.md
Normal file
159
content/posts/validando-dados-extraidos-com-scrapy.md
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
---
|
||||||
|
title: "Validando dados extraídos com Scrapy"
|
||||||
|
publishdate: 2019-03-08
|
||||||
|
tags: ["scrapy", "scraping", "monitoramento"]
|
||||||
|
---
|
||||||
|
|
||||||
|
Como você garante a qualidade e a confiabilidade dos dados que você está
|
||||||
|
extraindo em seu crawler?
|
||||||
|
|
||||||
|
Se o seu crawler foi desenvolvido com [Scrapy](https://scrapy.org), você tem a
|
||||||
|
disposição a extensão [Spidermon](https://spidermon.readthedocs.io/), que junto
|
||||||
|
com a biblioteca [Schematics](https://schematics.readthedocs.io/) permite que
|
||||||
|
você inclua validações de dados de maneira simples e altamente customizável.
|
||||||
|
|
||||||
|
Definindo modelos de dados, é possível comparar os items retornados com uma
|
||||||
|
estrutura pré-determinada, garantido que todos os campos contém dados no
|
||||||
|
formato esperado.
|
||||||
|
|
||||||
|
## Nosso exemplo
|
||||||
|
|
||||||
|
Para explicar o uso do **[Spidermon](https://spidermon.readthedocs.io/)**
|
||||||
|
para realizar a validação dos dados, criamos um projeto de exemplo simples,
|
||||||
|
que extrai citações do site [http://quotes.toscrape.com/](http://quotes.toscrape.com/).
|
||||||
|
|
||||||
|
Começamos instalando as bibliotecas necessárias:
|
||||||
|
|
||||||
|
{{<highlight bash>}}
|
||||||
|
$ python3 -m venv .venv
|
||||||
|
$ source .venv/bin/activate
|
||||||
|
(.venv) $ pip install scrapy spidermon schematics
|
||||||
|
{{</highlight>}}
|
||||||
|
|
||||||
|
Em seguida criamos um novo projeto **[Scrapy](https://scrapy.org)**:
|
||||||
|
|
||||||
|
{{<highlight bash>}}
|
||||||
|
$ scrapy startproject quotes_crawler
|
||||||
|
$ cd myproject & scrapy genspider quotes quotes.com
|
||||||
|
{{</highlight>}}
|
||||||
|
|
||||||
|
Definimos um [item](https://docs.scrapy.org/en/latest/topics/items.html) que
|
||||||
|
será retornado pelo nosso
|
||||||
|
[spider](https://docs.scrapy.org/en/latest/topics/spiders.html):
|
||||||
|
|
||||||
|
{{<highlight python>}}
|
||||||
|
# quotes_crawler/spiders/items.py
|
||||||
|
import scrapy
|
||||||
|
|
||||||
|
class QuoteItem(scrapy.Item):
|
||||||
|
quote = scrapy.Field()
|
||||||
|
author = scrapy.Field()
|
||||||
|
author_url = scrapy.Field()
|
||||||
|
tags = scrapy.Field()
|
||||||
|
{{</highlight>}}
|
||||||
|
|
||||||
|
E finalmente criamos o nosso spider:
|
||||||
|
|
||||||
|
{{<highlight python>}}
|
||||||
|
# quotes_crawler/spiders/quotes.py
|
||||||
|
import scrapy
|
||||||
|
from myproject.items import QuoteItem
|
||||||
|
|
||||||
|
class QuotesSpider(scrapy.Spider):
|
||||||
|
name = "quotes"
|
||||||
|
allowed_domains = ["quotes.toscrape.com"]
|
||||||
|
start_urls = ["http://quotes.toscrape.com/"]
|
||||||
|
|
||||||
|
def parse(self, response):
|
||||||
|
for quote in response.css(".quote"):
|
||||||
|
item = QuoteItem(
|
||||||
|
quote=quote.css(".text::text").get(),
|
||||||
|
author=quote.css(".author::text").get(),
|
||||||
|
author_url=response.urljoin(
|
||||||
|
quote.css(".author a::attr(href)").get()),
|
||||||
|
tags=quote.css(".tag *::text").getall(),
|
||||||
|
)
|
||||||
|
yield item
|
||||||
|
yield scrapy.Request(
|
||||||
|
response.urljoin(response.css(
|
||||||
|
".next a::attr(href)").get())
|
||||||
|
)
|
||||||
|
{{</highlight>}}
|
||||||
|
|
||||||
|
Com isso já é possível executar o nosso crawler e obter os dados desejados:
|
||||||
|
|
||||||
|
{{<highlight bash>}}
|
||||||
|
$ scrapy crawl quotes -o quotes.csv
|
||||||
|
{{</highlight>}}
|
||||||
|
|
||||||
|
## Definindo nosso modelo de validação
|
||||||
|
|
||||||
|
**[Schematics](https://schematics.readthedocs.io/)** é uma biblioteca de validação de dados baseada em modelos (muito
|
||||||
|
parecidos com modelos do Django). Esses modelos incluem alguns tipos de dados
|
||||||
|
comuns e validadores, mas também é possível extendê-los e definir regras de
|
||||||
|
validação customizadas.
|
||||||
|
|
||||||
|
Baseado no nosso exemplo anterior, vamos criar um modelo para o nosso item
|
||||||
|
contendo algumas regras básicas de validação:
|
||||||
|
|
||||||
|
{{<highlight python>}}
|
||||||
|
# quotes_crawler/spiders/validators.py
|
||||||
|
from schematics.models import Model
|
||||||
|
from schematics.types import URLType, StringType, ListType
|
||||||
|
|
||||||
|
class QuoteItem(Model):
|
||||||
|
# String de preenchimento obrigatório
|
||||||
|
quote = StringType(required=True)
|
||||||
|
|
||||||
|
# String de preenchimento obrigatório
|
||||||
|
author = StringType(required=True)
|
||||||
|
|
||||||
|
# Uma string que represente uma URL de preenchimento obrigatório
|
||||||
|
author_url = URLType(required=True)
|
||||||
|
|
||||||
|
# Lista de Strings de preenchimento não obrigatório
|
||||||
|
tags = ListType(StringType)
|
||||||
|
{{</highlight>}}
|
||||||
|
|
||||||
|
Precisamos agora habilitar o **Spidermon** e configurá-lo para que os campos
|
||||||
|
retornados pelo nosso spider sejam validados contra esse modelo:
|
||||||
|
|
||||||
|
{{<highlight python>}}
|
||||||
|
# quotes_crawler/settings.py
|
||||||
|
SPIDERMON_ENABLED = True
|
||||||
|
|
||||||
|
EXTENSIONS = {
|
||||||
|
"spidermon.contrib.scrapy.extensions.Spidermon": 500,
|
||||||
|
}
|
||||||
|
|
||||||
|
ITEM_PIPELINES = {
|
||||||
|
"spidermon.contrib.scrapy.pipelines.ItemValidationPipeline": 800
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIDERMON_VALIDATION_MODELS = (
|
||||||
|
"quotes_crawler.validators.QuoteItem",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Inclui um campo '_validation' nos items que contenham erros
|
||||||
|
# com detalhes do problema encontrado
|
||||||
|
SPIDERMON_VALIDATION_ADD_ERRORS_TO_ITEMS = True
|
||||||
|
{{</highlight>}}
|
||||||
|
|
||||||
|
Conforme os dados forem extraidos, eles serão validados de acordo com as regras
|
||||||
|
definidas no modelo e, caso algum erro seja encontrado, um novo campo
|
||||||
|
`_validation` será incluído no item com detalhes do erro.
|
||||||
|
|
||||||
|
Caso um item receba uma URL inválida no campo `author_url` por exemplo, o
|
||||||
|
resultado será:
|
||||||
|
|
||||||
|
{{<highlight js>}}
|
||||||
|
{
|
||||||
|
'_validation': defaultdict(
|
||||||
|
<class 'list'>, {'author_url': ['Invalid URL']}),
|
||||||
|
'author': 'C.S. Lewis',
|
||||||
|
'author_url': 'invalid_url',
|
||||||
|
'quote': 'Some day you will be old enough to start reading fairy tales '
|
||||||
|
'again.',
|
||||||
|
'tags': ['age', 'fairytales', 'growing-up']
|
||||||
|
}
|
||||||
|
{{</highlight>}}
|
20
themes/er/LICENSE.md
Normal file
20
themes/er/LICENSE.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2018 Lingyi Hu
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
68
themes/er/README.md
Normal file
68
themes/er/README.md
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
# Er.
|
||||||
|
|
||||||
|
A configurable blog theme for Hugo, with elements inspired by [this blog](https://aranair.github.io/posts/).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- produces an Atom feed at `feed.xml`(taken from [this discussion](https://github.com/comfusion/after-dark/issues/32)). It generates the latest 15 posts by default.
|
||||||
|
- Open graph tags
|
||||||
|
- tag and category pages
|
||||||
|
- table of contents for your posts (from [tocbot](https://github.com/tscanlin/tocbot))
|
||||||
|
- renders Math with KaTeX
|
||||||
|
- tag cloud on big screens
|
||||||
|
|
||||||
|
## Configurations
|
||||||
|
|
||||||
|
### Favicon
|
||||||
|
|
||||||
|
You can put your favicon at `static/favicon.ico`, the theme will automatically look for it there. If you want to choose a different path, please set the `favicon` parameter in `[params]` in the config.
|
||||||
|
|
||||||
|
### Atom feed
|
||||||
|
|
||||||
|
In order to enable Atom feed (instead of RSS), put this in your `config.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[outputs]
|
||||||
|
home = ["HTML", "Atom"]
|
||||||
|
|
||||||
|
[mediaTypes]
|
||||||
|
[mediaTypes."application/atom"]
|
||||||
|
suffix = "xml"
|
||||||
|
|
||||||
|
[outputFormats.Atom]
|
||||||
|
mediaType = "application/atom"
|
||||||
|
baseName = "feed"
|
||||||
|
isPlainText = false
|
||||||
|
|
||||||
|
disableKinds = ['RSS']
|
||||||
|
```
|
||||||
|
### Customize the colors
|
||||||
|
|
||||||
|
This theme uses [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables), and if you want to change the colours on this theme, you can override the `variables.css` in `layouts/partials/css`. This is loaded before the theme css.
|
||||||
|
|
||||||
|
### Google analytics
|
||||||
|
|
||||||
|
Google analytics tracking code can be added to `config.toml` like this:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
googleAnalytics = "UA-123-45"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Markdown TOC
|
||||||
|
|
||||||
|
Table of contents is activated by default, if it detects markdown headings. To turn it off, just add `toc = false` in the frontmatter. Alternatively, you can turn off contents page for the whole site by setting `showtoc = false` under the `[params]` section of `config.toml`, like this:
|
||||||
|
```toml
|
||||||
|
[params]
|
||||||
|
showtoc = false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Math rendering
|
||||||
|
|
||||||
|
Math rendering is off by default, can be turned on for individual posts or pages by setting `math = true` in the frontmatter.
|
||||||
|
|
||||||
|
### Tag cloud
|
||||||
|
|
||||||
|
Tag cloud is shown by default. To disable, add `showTagCloud = false` under the `[params]` section, similar to `showtoc`. You can also configure the maximum number of tags you want to show in your tag cloud, using the `maxTags` key under `[params]`. This number is 50 by default.
|
||||||
|
|
||||||
|
### back to top button
|
||||||
|
|
||||||
|
Back to top button is also shown by default. To disable, add `showScrollToTop = false` under `[params]`.
|
2
themes/er/archetypes/default.md
Normal file
2
themes/er/archetypes/default.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
+++
|
||||||
|
+++
|
BIN
themes/er/images/screenshot.png
Normal file
BIN
themes/er/images/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 118 KiB |
BIN
themes/er/images/tn.png
Normal file
BIN
themes/er/images/tn.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
9
themes/er/layouts/404.html
Normal file
9
themes/er/layouts/404.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="center mv4 content-width ph3">
|
||||||
|
<div class="f2 fw6 heading-color heading-font">404</div>
|
||||||
|
<p class="lh-copy post-content f4">
|
||||||
|
Sorry, but nothing exists here. <br>
|
||||||
|
Find something <a href='{{ "" | relURL }}'>interesting to read.</a>
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
10
themes/er/layouts/_default/baseof.html
Normal file
10
themes/er/layouts/_default/baseof.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>{{ partial "header.html" . }}</head>
|
||||||
|
<body class="global-font">
|
||||||
|
{{ partial "nav.html" . }}
|
||||||
|
{{ block "main" . }}{{ end }}
|
||||||
|
{{ partial "footer.html" . }}
|
||||||
|
{{ partial "scripts.html" . }}
|
||||||
|
</body>
|
||||||
|
</html>
|
14
themes/er/layouts/_default/list.html
Normal file
14
themes/er/layouts/_default/list.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="center mv4 content-width ph3">
|
||||||
|
<h1 class="f2 fw6 heading-font">{{ .Title }}</h1>
|
||||||
|
{{ .Content }}
|
||||||
|
<ul class="list-pages">
|
||||||
|
{{ range .Data.Pages }}
|
||||||
|
<li class="lh-copy"><a href="{{ .Permalink | relURL }}" class="link f5">{{ .Title }}</a> - <time>{{ .Date.Format "02 Jan 2006" }}</time></li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
<div class="pagination tc db fixed-l bottom-2-l right-2-l mb3 mb0-l">
|
||||||
|
{{ partial "back-to-top.html" . }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
26
themes/er/layouts/_default/single.html
Normal file
26
themes/er/layouts/_default/single.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="center mv4 content-width ph3">
|
||||||
|
<div class="f3 fw6 heading-color heading-font post-title">{{ .Title }}</div>
|
||||||
|
<p class="silver f6 mt1 mb4 post-meta">
|
||||||
|
{{ if not .Date.IsZero }}<time>{{ .Date.Format "02 Jan 2006" }}</time> {{ end }}
|
||||||
|
{{ if or .Params.tags .Params.categories .Params.series }} | {{ end }}
|
||||||
|
{{ if isset .Params "categories" }}
|
||||||
|
categories: [ {{ range .Params.categories }}<a href='{{ "/categories/" | relLangURL }}{{ . | urlize }}' class="link silver">{{ . }}</a> {{ end }} ]
|
||||||
|
{{ end }}
|
||||||
|
{{ if isset .Params "tags" }}
|
||||||
|
tags: [ {{ range .Params.tags }}<a href='{{ "/tags/" | relLangURL }}{{ . | urlize }}' class="link silver">{{ . }}</a> {{ end }} ]
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
<div class="lh-copy post-content">{{ .Content }}</div>
|
||||||
|
</main>
|
||||||
|
{{ partial "table-of-contents" . }}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="pagination tc tr-l db fixed-l bottom-2-l right-2-l mb3 mb0-l">
|
||||||
|
{{ partial "back-to-top.html" . }}<br>
|
||||||
|
<p class="mb0 mt2">
|
||||||
|
{{ with .PrevInSection }}{{ if . }}<a href="{{ .Permalink }}">prev post</a>{{ end }}{{ end }}
|
||||||
|
{{ with .NextInSection }}{{ if . }}<a href="{{ .Permalink }}">next post</a>{{ end }}{{ end }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
14
themes/er/layouts/_default/tag.html
Normal file
14
themes/er/layouts/_default/tag.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="center mv4 content-width ph3">
|
||||||
|
<h1 class="f2 fw6 heading-font"><span class="secondary-color">#</span> {{ .Data.Term }}</h1>
|
||||||
|
{{ .Content }}
|
||||||
|
<ul class="list-pages">
|
||||||
|
{{ range .Data.Pages }}
|
||||||
|
<li class="lh-copy"><a href="{{ .Permalink | relURL }}" class="link f5">{{ .Title }}</a> - <time>{{ .Date.Format "02 Jan 2006" }}</time></li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
<div class="pagination tc db fixed-l bottom-2-l right-2-l mb3 mb0-l">
|
||||||
|
{{ partial "back-to-top.html" . }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
15
themes/er/layouts/_default/terms.html
Normal file
15
themes/er/layouts/_default/terms.html
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="center mv4 content-width ph3">
|
||||||
|
{{ $type := .Type }}
|
||||||
|
<h1 class="f2 fw6 heading-font">{{ .Title }}</h1>
|
||||||
|
{{ .Content }}
|
||||||
|
<ul class="list-pages list pl0">
|
||||||
|
{{ range $key, $value := .Data.Terms }}
|
||||||
|
<li class="lh-copy di bg-light-gray ph1"><a href="{{ $key | urlize }}" class="link f5">{{ $key }} ({{ len $value }})</a></li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
<div class="pagination tc db fixed-l bottom-2-l right-2-l mb3 mb0-l">
|
||||||
|
{{ partial "back-to-top.html" . }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
27
themes/er/layouts/index.atom.xml
Normal file
27
themes/er/layouts/index.atom.xml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
{{ if .IsHome }}
|
||||||
|
<title>{{ .Title }}</title>
|
||||||
|
{{ else }}
|
||||||
|
<title>{{ .Title }} - {{ .Site.Title }}</title>
|
||||||
|
{{ end }}
|
||||||
|
<link href="{{ .Permalink }}index.xml" rel="self"/>
|
||||||
|
<link href="{{ .Permalink }}"/>{{ if not .Date.IsZero }}
|
||||||
|
<updated>{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</updated>{{ end }}
|
||||||
|
<id>{{ .Permalink }}</id>{{ with .Site.Author.name }}
|
||||||
|
<author>
|
||||||
|
<name>{{.}}</name>{{ with $.Site.Author.email }}
|
||||||
|
<email>{{.}}</email>{{end}}
|
||||||
|
</author>{{end}}
|
||||||
|
<generator>Hugo -- gohugo.io</generator>{{ range first 15 (where .Data.Pages "Type" "in" .Site.Params.mainSections) }}
|
||||||
|
<entry>
|
||||||
|
{{ `<title type="html"><![CDATA[` | safeHTML }}{{ .Title }}]]></title>
|
||||||
|
<link href="{{ .Permalink }}"/>
|
||||||
|
<id>{{ .Permalink }}</id>{{ with .Site.Params.Author }}
|
||||||
|
<author>
|
||||||
|
<name>{{.}}</name>
|
||||||
|
</author>{{end}}
|
||||||
|
<published>{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</published>
|
||||||
|
<updated>{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</updated>
|
||||||
|
{{ `<content type="html"><![CDATA[` | safeHTML }}{{ .Content }}]]></content>
|
||||||
|
</entry>{{ end }}
|
||||||
|
</feed>
|
24
themes/er/layouts/index.html
Normal file
24
themes/er/layouts/index.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
{{ $paginator := .Paginate (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) }}
|
||||||
|
<main class="center mv4 content-width ph3">
|
||||||
|
<ul class="list pa0">
|
||||||
|
{{ range $paginator.Pages }}
|
||||||
|
<li class="mb2">
|
||||||
|
<a class="f4 heading-color heading-font fw6 no-underline" href="{{ .Permalink }}">{{ .Title }}</a>
|
||||||
|
<p class="f5 mt1 silver">
|
||||||
|
<time>{{ .Date.Format "02 Jan 2006" }}</time>
|
||||||
|
{{ if or .Params.tags .Params.categories }} | {{ end }}
|
||||||
|
{{ if isset .Params "categories" }}
|
||||||
|
categories: [ {{ range .Params.categories }}<a href='{{ "/categories/" | relLangURL }}{{ . | urlize }}' class="link silver">{{ . }}</a> {{ end }} ]
|
||||||
|
{{ end }}
|
||||||
|
{{ if isset .Params "tags" }}
|
||||||
|
tags: [ {{ range .Params.tags }}<a href='{{ "/tags/" | relLangURL }}{{ . | urlize }}' class="link silver">{{ . }}</a> {{ end }} ]
|
||||||
|
{{ end }}
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
{{ partial "tag_cloud.html" . }}
|
||||||
|
{{ partial "pagination.html" . }}
|
||||||
|
{{ end }}
|
3
themes/er/layouts/partials/back-to-top.html
Normal file
3
themes/er/layouts/partials/back-to-top.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{{ if .Site.Params.showScrollToTop | default true }}
|
||||||
|
<a id="scroll-to-top" class="f6 o-0 link br2 ph2 pv1 mb1 bg-main-color pointer" onclick="topFunction()" style="color: #fff; visibility: hidden; display: none; transition: opacity .5s, visibility .5s;" title="back to top">back to top</a>
|
||||||
|
{{ end }}
|
9
themes/er/layouts/partials/css/variables.css
Normal file
9
themes/er/layouts/partials/css/variables.css
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
/*https://coolors.co/afd5aa-f0f2ef-a69f98-3d3d3d-8c6057*/
|
||||||
|
:root {
|
||||||
|
--main-color: #8C6056;
|
||||||
|
--secondary-color: #AFD5AA;
|
||||||
|
--logo-text-color: #fff;
|
||||||
|
--body-text-color: #3d3d3d;
|
||||||
|
--heading-text-color: #383838;
|
||||||
|
--background-color: #fff;
|
||||||
|
}
|
5
themes/er/layouts/partials/footer.html
Normal file
5
themes/er/layouts/partials/footer.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<footer class="content-width mt0 mt5-l mb4 f6 center ph3 gray tc tl-l">
|
||||||
|
<hr class="dn db-l ml0-l gray w3"><br>
|
||||||
|
Powered by <a href="https://gohugo.io/" target="_blank" class="link gray dim">Hugo</a>, based on the <a href="https://github.com/lingxz/er" target="_blank" class="link gray dim">Er</a> theme. <br>
|
||||||
|
{{ with .Site.Copyright }}{{ . }}{{end}}
|
||||||
|
</footer>
|
22
themes/er/layouts/partials/header.html
Normal file
22
themes/er/layouts/partials/header.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta content='text/html; charset=utf-8' http-equiv='content-type' />
|
||||||
|
{{ partial "open_graph.html" . }}
|
||||||
|
{{ hugo.Generator }}
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600" rel="stylesheet">
|
||||||
|
<style type="text/css">{{ partial "css/variables.css" . | safeCSS }}</style>
|
||||||
|
<link href='{{ "css/tachyons.min.css" | relURL }}' rel="stylesheet">
|
||||||
|
<link href='{{ "css/styles.css" | relURL }}' rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Icon -->
|
||||||
|
<link rel="icon"
|
||||||
|
{{ if .Site.Params.favicon }}
|
||||||
|
href="{{ .Site.Params.favicon | relURL }}"
|
||||||
|
{{ else }}
|
||||||
|
href='{{ "/favicon.ico" | relURL }}'
|
||||||
|
{{ end }}
|
||||||
|
type="image/x-icon"/>
|
||||||
|
|
||||||
|
<link href='{{ "/feed.xml" | relURL }}' rel="alternate" type="application/atom+xml" title="{{ .Site.Title }}" />
|
||||||
|
{{ template "_internal/google_analytics_async.html" . }}
|
12
themes/er/layouts/partials/nav.html
Normal file
12
themes/er/layouts/partials/nav.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<nav class="{{ with .Site.Menus.main }}{{ if lt (len .) 3 }} flex {{ else }} flex-ns{{ end }}{{ end }} justify-between border-box pa3 pl3-l pr2-l mt1 mt0-ns" id="navbar">
|
||||||
|
<div class="flex">
|
||||||
|
<a class="f4 fw6 ttu no-underline dim bg-main-color pv1 ph2 br2" id="site-title" href='{{ "" | relURL }}' title="Home">{{ .Site.Title }}</a>
|
||||||
|
</div>
|
||||||
|
{{ with .Site.Menus.main }}
|
||||||
|
<div class="{{ if lt (len . ) 3 }} flex-grow {{ else }} flex-ns mt2 mt0-ns{{ end }} pv1">
|
||||||
|
{{ range . }}
|
||||||
|
<a class="link dim dark-gray f6 dib mr2 mr3-l ttu tracked" href='{{.URL}}' title="{{ .Name }}">{{ .Name }}</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</nav>
|
48
themes/er/layouts/partials/open_graph.html
Normal file
48
themes/er/layouts/partials/open_graph.html
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{{ if .IsHome }}
|
||||||
|
<title>{{ .Title }}</title>
|
||||||
|
<meta content='{{ .Title }}' property='title' />
|
||||||
|
<meta content='{{ .Title }}' property='og:title' />
|
||||||
|
{{ else }}
|
||||||
|
<title>{{ .Title }} - {{ .Site.Title }}</title>
|
||||||
|
<meta content='{{ .Title }} - {{ .Site.Title }}' property='title' />
|
||||||
|
<meta content='{{ .Title }} - {{ .Site.Title }}' property='og:title' />
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<meta property="og:description" content="{{ with .Description }}{{ . }}{{ else }}{{if .IsPage}}{{ .Summary }}{{ else }}{{ with .Site.Params.description }}{{ . }}{{ end }}{{ end }}{{ end }}" />
|
||||||
|
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
|
||||||
|
<meta property="og:url" content="{{ .Permalink }}" />
|
||||||
|
{{ with .Params.images }}{{ range first 6 . }}
|
||||||
|
<meta property="og:image" content="{{ . | absURL }}" />
|
||||||
|
{{ end }}{{ end }}
|
||||||
|
{{ if .IsPage }}
|
||||||
|
{{ if not .PublishDate.IsZero }}<meta property="article:published_time" content="{{ .PublishDate.Format "2006-01-02T15:04:05-07:00" | safeHTML }}"/>
|
||||||
|
{{ else if not .Date.IsZero }}<meta property="article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}"/>{{ end }}
|
||||||
|
{{ if not .Lastmod.IsZero }}<meta property="article:modified_time" content="{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}"/>{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ if not .Date.IsZero }}<meta property="og:updated_time" content="{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}"/>{{ end }}
|
||||||
|
{{ end }}{{ with .Params.audio }}
|
||||||
|
<meta property="og:audio" content="{{ . }}" />{{ end }}{{ with .Params.locale }}
|
||||||
|
<meta property="og:locale" content="{{ . }}" />{{ end }}{{ with .Site.Params.title }}
|
||||||
|
<meta property="og:site_name" content="{{ . }}" />{{ end }}{{ with .Params.videos }}
|
||||||
|
{{ range .Params.videos }}
|
||||||
|
<meta property="og:video" content="{{ . | absURL }}" />
|
||||||
|
{{ end }}{{ end }}
|
||||||
|
<!-- If it is part of a series, link to related articles -->
|
||||||
|
{{ $permalink := .Permalink }}
|
||||||
|
{{ $siteSeries := .Site.Taxonomies.series }}{{ with .Params.series }}
|
||||||
|
{{ range $name := . }}
|
||||||
|
{{ $series := index $siteSeries $name }}
|
||||||
|
{{ range $page := first 6 $series.Pages }}
|
||||||
|
{{ if ne $page.Permalink $permalink }}<meta property="og:see_also" content="{{ $page.Permalink }}" />{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}{{ end }}
|
||||||
|
{{ if .IsPage }}
|
||||||
|
{{ range .Site.Authors }}{{ with .Social.facebook }}
|
||||||
|
<meta property="article:author" content="https://www.facebook.com/{{ . }}" />{{ end }}{{ with .Site.Social.facebook }}
|
||||||
|
<meta property="article:publisher" content="https://www.facebook.com/{{ . }}" />{{ end }}
|
||||||
|
<meta property="article:section" content="{{ .Section }}" />
|
||||||
|
{{ with .Params.tags }}{{ range first 6 . }}
|
||||||
|
<meta property="article:tag" content="{{ . }}" />{{ end }}{{ end }}
|
||||||
|
{{ end }}{{ end }}
|
||||||
|
<!-- Facebook Page Admin ID for Domain Insights -->
|
||||||
|
{{ with .Site.Social.facebook_admin }}<meta property="fb:admins" content="{{ . }}" />{{ end }}
|
9
themes/er/layouts/partials/pagination.html
Normal file
9
themes/er/layouts/partials/pagination.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{{ if gt .Paginator.TotalPages 1 }}
|
||||||
|
<div class="pagination tc db fixed-l bottom-2-l right-2-l mb3 mb0-l">
|
||||||
|
{{ partial "back-to-top.html" . }}<br>
|
||||||
|
<p class="mb0 mt2">Page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }} <br>
|
||||||
|
{{ if .Paginator.HasNext }}<a href="{{ .Paginator.Next.URL | relURL }}">Older Posts</a>{{ end }}
|
||||||
|
{{ if .Paginator.HasPrev }}<a href="{{ .Paginator.Prev.URL | relURL }}">Newer Posts</a>{{ end }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
101
themes/er/layouts/partials/scripts.html
Normal file
101
themes/er/layouts/partials/scripts.html
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
{{ if .Site.Params.showtoc | default true }}
|
||||||
|
{{ $headers := findRE "<h[1-6].*?>(.|\n])+?</h[1-6]>" .Content }}
|
||||||
|
{{ $has_headers := ge (len $headers) 1 }}
|
||||||
|
{{ if and $has_headers (ne .Params.toc false) }}
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.css">
|
||||||
|
<style>.is-active-link::before { background-color: var(--secondary-color); }</style>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if or (.Site.Params.showTagCloud | default true) (.Site.Params.showtoc | default true) (.Site.Params.showScrollToTop | default true) }}
|
||||||
|
<script type="text/javascript">
|
||||||
|
var prevScrollpos = window.pageYOffset;
|
||||||
|
window.onscroll = function() {
|
||||||
|
var currentScrollPos = window.pageYOffset;
|
||||||
|
|
||||||
|
{{ if .Site.Params.showTagCloud | default true }}
|
||||||
|
if (document.getElementById("tag-cloud") !== null) {
|
||||||
|
if (prevScrollpos > currentScrollPos) { // scroll up
|
||||||
|
document.getElementById("tag-cloud").style.visibility = "visible";
|
||||||
|
document.getElementById("tag-cloud").style.opacity = "1";
|
||||||
|
} else {
|
||||||
|
document.getElementById("tag-cloud").style.visibility = "hidden";
|
||||||
|
document.getElementById("tag-cloud").style.opacity = "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if .Site.Params.showScrollToTop | default true }}
|
||||||
|
if (document.body.scrollTop > 1000 || document.documentElement.scrollTop > 1000) {
|
||||||
|
document.getElementById("scroll-to-top").style.display = "inline";
|
||||||
|
document.getElementById("scroll-to-top").style.visibility = "visible";
|
||||||
|
document.getElementById("scroll-to-top").style.opacity = "1";
|
||||||
|
} else {
|
||||||
|
document.getElementById("scroll-to-top").style.visibility = "hidden";
|
||||||
|
document.getElementById("scroll-to-top").style.opacity = "0";
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
prevScrollpos = currentScrollPos;
|
||||||
|
}
|
||||||
|
{{ if .Site.Params.showScrollToTop | default true }}
|
||||||
|
// When the user clicks on the button, scroll to the top of the document
|
||||||
|
function topFunction() {
|
||||||
|
document.body.scrollTop = 0; // For Safari
|
||||||
|
document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if .Site.Params.showtoc | default true }}
|
||||||
|
{{ $headers := findRE "<h[1-6].*?>(.|\n])+?</h[1-6]>" .Content }}
|
||||||
|
{{ $has_headers := ge (len $headers) 1 }}
|
||||||
|
{{ if and $has_headers (ne .Params.toc false) }}
|
||||||
|
if (document.getElementById("contents-list") !== null && document.getElementsByClassName("post-content").length !== 0) {
|
||||||
|
tocbot.init({
|
||||||
|
// Where to render the table of contents.
|
||||||
|
tocSelector: '#contents-list',
|
||||||
|
// Where to grab the headings to build the table of contents.
|
||||||
|
contentSelector: '.post-content',
|
||||||
|
// Which headings to grab inside of the contentSelector element.
|
||||||
|
headingSelector: 'h1, h2, h3',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</script>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if .Params.math }}
|
||||||
|
<!-- Load KaTeX -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/contrib/auto-render.min.js" integrity="sha384-dq1/gEHSxPZQ7DdrM82ID4YVol9BYyU7GbWlIwnwyPzotpoc57wDw/guX8EaYGPx" crossorigin="anonymous"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.css">
|
||||||
|
<script>
|
||||||
|
renderMathInElement(document.body,
|
||||||
|
{
|
||||||
|
delimiters: [
|
||||||
|
{left: "$$", right: "$$", display: true},
|
||||||
|
{left: "$", right: "$", display: false},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
var inlineMathArray = document.querySelectorAll("script[type='math/tex']");
|
||||||
|
for (var i = 0; i < inlineMathArray.length; i++) {
|
||||||
|
var inlineMath = inlineMathArray[i];
|
||||||
|
var tex = inlineMath.innerText || inlineMath.textContent;
|
||||||
|
var replaced = document.createElement("span");
|
||||||
|
replaced.innerHTML = katex.renderToString(tex, {displayMode: false});
|
||||||
|
inlineMath.parentNode.replaceChild(replaced, inlineMath);
|
||||||
|
}
|
||||||
|
|
||||||
|
var displayMathArray = document.querySelectorAll("script[type='math/tex; mode=display']");
|
||||||
|
for (var i = 0; i < displayMathArray.length; i++) {
|
||||||
|
var displayMath = displayMathArray[i];
|
||||||
|
var tex = displayMath.innerHTML;
|
||||||
|
var replaced = document.createElement("span");
|
||||||
|
replaced.innerHTML = katex.renderToString(tex.replace(/%.*/g, ''), {displayMode: true});
|
||||||
|
displayMath.parentNode.replaceChild(replaced, displayMath);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{{end}}
|
9
themes/er/layouts/partials/table-of-contents.html
Normal file
9
themes/er/layouts/partials/table-of-contents.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<!-- ignore empty links with + -->
|
||||||
|
{{ $headers := findRE "<h[1-6].*?>(.|\n])+?</h[1-6]>" .Content }}
|
||||||
|
<!-- at least one header to link to -->
|
||||||
|
{{ $has_headers := ge (len $headers) 1 }}
|
||||||
|
<!-- a post can explicitly disable Table of Contents with toc: false -->
|
||||||
|
{{ $show_toc := and (ne .Params.toc false) (ne .Site.Params.showtoc false) }}
|
||||||
|
{{ if and $has_headers $show_toc }}
|
||||||
|
<div class="tl fixed list-pages lh-copy" id="contents-list"></div>
|
||||||
|
{{ end }}
|
9
themes/er/layouts/partials/tag_cloud.html
Normal file
9
themes/er/layouts/partials/tag_cloud.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{{ $maxtags := .Site.Params.maxTags | default 50 }}
|
||||||
|
{{ if .Site.Params.showTagCloud | default true }}
|
||||||
|
<div class="dn tr fixed right-2" id="tag-cloud">
|
||||||
|
tags <br>
|
||||||
|
{{ range first $maxtags .Site.Taxonomies.tags.ByCount }}
|
||||||
|
<a class="silver no-underline" href="{{ "/tags/" | relLangURL }}{{ .Name | urlize }}">{{ .Name }}</a></li>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
122
themes/er/static/css/styles.css
Normal file
122
themes/er/static/css/styles.css
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
html { font-size: 16px; }
|
||||||
|
body { color: var(--body-text-color); background-color: var(--background-color);}
|
||||||
|
.main-color { color: var(--main-color); }
|
||||||
|
.secondary-color { color: var(--secondary-color); }
|
||||||
|
.bg-main-color { background-color: var(--main-color); color: var(--logo-text-color); }
|
||||||
|
.heading-font, .global-font { font-family: "Source Sans Pro"; }
|
||||||
|
.heading-color { color: var(--heading-text-color); }
|
||||||
|
.post-content a, .list-pages a, .pagination a {
|
||||||
|
border-bottom: 1px solid rgba(0,0,0,0.4);
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
main a:hover, .list-pages a:hover, .pagination a:hover, #tag-cloud a:hover {
|
||||||
|
border-bottom: 1px solid var(--body-text-color);
|
||||||
|
color: var(--body-text-color);
|
||||||
|
}
|
||||||
|
.content-width { max-width: 650px; }
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
letter-spacing: 0px;
|
||||||
|
color: var(--main-color);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-size: 0.9em;
|
||||||
|
padding: 10px 20px 10px 20px;
|
||||||
|
overflow: auto;
|
||||||
|
line-height: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p code {
|
||||||
|
padding: .25rem .5rem;
|
||||||
|
font-size: 0.9em;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tag-cloud { max-width: 250px; }
|
||||||
|
#contents-list>.toc-list {
|
||||||
|
max-width: 250px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: fixed;
|
||||||
|
right: 2rem;
|
||||||
|
}
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
#contents-list>.toc-list, #tag-cloud {
|
||||||
|
display: block;
|
||||||
|
top: 100px;
|
||||||
|
}
|
||||||
|
#tag-cloud {
|
||||||
|
-webkit-transition: opacity .5s, visibility .5s;
|
||||||
|
transition: opacity .5s, visibility .5s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-width: 1330px) { #contents-list>.toc-list { max-width: 300px; right: 3rem;}}
|
||||||
|
#contents-list ol { list-style: none; }
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 2em 1em;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
box-shadow: 1px 1px 2px 2px #bbb;
|
||||||
|
}
|
||||||
|
figcaption {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left-style: solid;
|
||||||
|
border-left-width: 1px;
|
||||||
|
border-color: var(--secondary-color);
|
||||||
|
border-width: .25rem;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p {
|
||||||
|
color: #666;
|
||||||
|
margin-top: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote p>cite {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-style: normal;
|
||||||
|
letter-spacing: .1em;
|
||||||
|
font-size: .875rem;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
font-size: 14px;
|
||||||
|
border-collapse:collapse;
|
||||||
|
margin: 2rem auto;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr {
|
||||||
|
border-top:1px solid #ccc;
|
||||||
|
background-color:#fff;
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr:nth-child(2n) {
|
||||||
|
background-color:#f8f8f8;
|
||||||
|
}
|
||||||
|
table tr th[align="center"], table tr td[align="center"] {
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
table tr th, table tr td {
|
||||||
|
border:1px solid #ccc;
|
||||||
|
text-align:left;
|
||||||
|
margin:0;
|
||||||
|
padding:6px 13px;
|
||||||
|
}
|
2
themes/er/static/css/tachyons.min.css
vendored
Normal file
2
themes/er/static/css/tachyons.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
15
themes/er/theme.toml
Normal file
15
themes/er/theme.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# theme.toml template for a Hugo theme
|
||||||
|
# See https://github.com/gohugoio/hugoThemes#themetoml for an example
|
||||||
|
|
||||||
|
name = "Er"
|
||||||
|
license = "MIT"
|
||||||
|
licenselink = "https://github.com/lingxz/er/blob/master/LICENSE.md"
|
||||||
|
description = "A clean Hugo theme for blogging"
|
||||||
|
homepage = "http://github.com/lingxz/er"
|
||||||
|
tags = ["responsive", "white", "blog"]
|
||||||
|
features = ["responsive", "blog"]
|
||||||
|
min_version = "0.57.0"
|
||||||
|
|
||||||
|
[author]
|
||||||
|
name = "Lingyi Hu"
|
||||||
|
homepage = "https://theconfused.me"
|
1
themes/hugo-tania
Submodule
1
themes/hugo-tania
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit c52acfb01bb0188da4f76b1378d9045041772a99
|
Loading…
Add table
Add a link
Reference in a new issue