aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2020-03-25 05:12:40 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2020-03-25 05:12:40 +0100
commited161e7fb20a697ecba070ef7db4c231d700f245 (patch)
tree5a415f8e758c6b7001ade8003ca2aa26b476b58c
parentfb94d7aef76a5996892ef82938524cb0c2e0d285 (diff)
downloadmitjafelicijan.com-ed161e7fb20a697ecba070ef7db4c231d700f245.tar.gz
Move to my own static generator
-rw-r--r--.nojekyll0
-rw-r--r--Makefile14
-rw-r--r--assets/dna-sequence/benchmarks.ods (renamed from src/files/dna-sequence/benchmarks.ods)bin21911 -> 21911 bytes
-rw-r--r--assets/dna-sequence/chart-encoding-speed.png (renamed from src/files/dna-sequence/chart-encoding-speed.png)bin14201 -> 14201 bytes
-rw-r--r--assets/dna-sequence/chart-file-sizes.png (renamed from src/files/dna-sequence/chart-file-sizes.png)bin12391 -> 12391 bytes
-rw-r--r--assets/dna-sequence/dna-basics.jpg (renamed from src/files/dna-sequence/dna-basics.jpg)bin165883 -> 165883 bytes
-rw-r--r--assets/dna-sequence/quote.png (renamed from src/files/dna-sequence/quote.png)bin1068 -> 1068 bytes
-rw-r--r--assets/dna-sequence/sample-binary-file.png (renamed from src/files/dna-sequence/sample-binary-file.png)bin66417 -> 66417 bytes
-rw-r--r--assets/dna-sequence/sample.png (renamed from src/files/dna-sequence/sample.png)bin65930 -> 65930 bytes
-rw-r--r--assets/do-fuse/copy-benchmarks.tsv (renamed from src/files/do-fuse/copy-benchmarks.tsv)0
-rw-r--r--assets/do-fuse/fuse-droplets.png (renamed from src/files/do-fuse/fuse-droplets.png)bin42891 -> 42891 bytes
-rw-r--r--assets/do-fuse/fuse-spaces.png (renamed from src/files/do-fuse/fuse-spaces.png)bin32450 -> 32450 bytes
-rw-r--r--assets/do-fuse/sqlite-benchmarks.tsv (renamed from src/files/do-fuse/sqlite-benchmarks.tsv)0
-rw-r--r--assets/go-profiling/golang-profiling-cpu.pdf (renamed from src/files/go-profiling/golang-profiling-cpu.pdf)bin16518 -> 16518 bytes
-rw-r--r--assets/go-profiling/golang-profiling-mem.pdf (renamed from src/files/go-profiling/golang-profiling-mem.pdf)bin19221 -> 19221 bytes
-rw-r--r--assets/iot-application/iot-app-output.png (renamed from src/files/iot-application/iot-app-output.png)bin23767 -> 23767 bytes
-rw-r--r--assets/iot-application/iot-rest-example.png (renamed from src/files/iot-application/iot-rest-example.png)bin33912 -> 33912 bytes
-rw-r--r--assets/iot-application/iot-sqlite-db.png (renamed from src/files/iot-application/iot-sqlite-db.png)bin199821 -> 199821 bytes
-rw-r--r--assets/iot-application/kcachegrind.png (renamed from src/files/iot-application/kcachegrind.png)bin88486 -> 88486 bytes
-rw-r--r--assets/iot-application/profiling-viewer.png (renamed from src/files/iot-application/profiling-viewer.png)bin173672 -> 173672 bytes
-rw-r--r--assets/iot-application/simple-iot-application-overview.svg (renamed from src/files/iot-application/simple-iot-application-overview.svg)0
-rw-r--r--assets/iot-application/simple-iot-application.zip (renamed from src/files/iot-application/simple-iot-application.zip)bin6406 -> 6406 bytes
-rw-r--r--assets/iot-application/snakeviz.png (renamed from src/files/iot-application/snakeviz.png)bin59601 -> 59601 bytes
-rw-r--r--assets/python-profiling/kcachegrind.png (renamed from src/files/python-profiling/kcachegrind.png)bin88486 -> 88486 bytes
-rw-r--r--assets/python-profiling/profiling-viewer.png (renamed from src/files/python-profiling/profiling-viewer.png)bin173672 -> 173672 bytes
-rw-r--r--assets/python-profiling/snakeviz.png (renamed from src/files/python-profiling/snakeviz.png)bin59601 -> 59601 bytes
-rw-r--r--assets/sentiment-analysis/.ipynb_checkpoints/TF Test-checkpoint.ipynb (renamed from src/files/sentiment-analysis/.ipynb_checkpoints/TF Test-checkpoint.ipynb)0
-rw-r--r--assets/sentiment-analysis/.ipynb_checkpoints/sentiment-analysis-checkpoint.ipynb (renamed from src/files/sentiment-analysis/.ipynb_checkpoints/sentiment-analysis-checkpoint.ipynb)0
-rw-r--r--assets/sentiment-analysis/guardian-sa-title-desc-relationship.png (renamed from src/files/sentiment-analysis/guardian-sa-title-desc-relationship.png)bin15404 -> 15404 bytes
-rw-r--r--assets/sentiment-analysis/sentiment-analysis.ipynb (renamed from src/files/sentiment-analysis/sentiment-analysis.ipynb)0
-rw-r--r--config40
-rw-r--r--content/curriculum-vitae.md (renamed from src/curriculum-vitae.md)10
-rw-r--r--content/encoding-binary-data-into-dna-sequence.md (renamed from src/experiments/encoding-binary-data-into-dna-sequence.md)26
-rw-r--r--content/golang-profiling-simplified.md (renamed from src/notes/golang-profiling-simplified.md)16
-rw-r--r--content/profiling-python-web-applications-with-visual-tools.md (renamed from src/experiments/profiling-python-web-applications-with-visual-tools.md)18
-rw-r--r--content/simple-iot-application.md (renamed from src/experiments/simple-iot-application.md)22
-rw-r--r--content/simplifying-and-reducing-clutter.md (renamed from src/notes/simplifying-and-reducing-clutter.md)12
-rw-r--r--content/using-digitalocean-spaces-object-storage-with-fuse.md (renamed from src/experiments/using-digitalocean-spaces-object-storage-with-fuse.md)24
-rw-r--r--content/using-sentiment-analysis-for-click-bait-detection-in-rss-feeds.md (renamed from src/experiments/using-sentiment-analysis-for-click-bait-detection-in-rss-feeds.md)16
-rw-r--r--content/what-i-ve-learned-developing-ad-server.md (renamed from src/notes/what-i-ve-learned-developing-ad-server.md)12
-rw-r--r--site.tmpl140
-rw-r--r--src/404.html3
-rw-r--r--src/comments.html100
-rw-r--r--src/feed.atom55
-rw-r--r--src/index.html21
-rw-r--r--src/static/comments.js65
-rw-r--r--src/static/style.css319
-rw-r--r--static/avatar-512x512.png (renamed from src/static/avatar-512x512.png)bin244569 -> 244569 bytes
-rw-r--r--static/avatar-64x64.png (renamed from src/static/avatar-64x64.png)bin16769 -> 16769 bytes
-rw-r--r--static/style.css172
-rw-r--r--staticgen.yml21
-rw-r--r--templates/index.twig56
-rw-r--r--templates/page.twig52
-rw-r--r--templates/partials/navigation.twig6
-rw-r--r--templates/post.twig59
55 files changed, 450 insertions, 829 deletions
diff --git a/.nojekyll b/.nojekyll
deleted file mode 100644
index e69de29..0000000
--- a/.nojekyll
+++ /dev/null
diff --git a/Makefile b/Makefile
index 7af4018..a4db862 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,11 @@
1GS ?= gostatic 1dev:
2 2 browser-sync ./public/ -w --no-notify --no-open
3compile: clean
4 $(GS) config
5 3
6clean: 4clean:
7 -rm public -rf 5 rm -rf public/*
8 6
9dev: clean 7generate:
10 $(GS) -w config 8 staticgen --generate
11 9
12deploy: clean compile 10deploy: clean generate
13 firebase deploy 11 firebase deploy
diff --git a/src/files/dna-sequence/benchmarks.ods b/assets/dna-sequence/benchmarks.ods
index 62a8e30..62a8e30 100644
--- a/src/files/dna-sequence/benchmarks.ods
+++ b/assets/dna-sequence/benchmarks.ods
Binary files differ
diff --git a/src/files/dna-sequence/chart-encoding-speed.png b/assets/dna-sequence/chart-encoding-speed.png
index 7fb106d..7fb106d 100644
--- a/src/files/dna-sequence/chart-encoding-speed.png
+++ b/assets/dna-sequence/chart-encoding-speed.png
Binary files differ
diff --git a/src/files/dna-sequence/chart-file-sizes.png b/assets/dna-sequence/chart-file-sizes.png
index 31bfa66..31bfa66 100644
--- a/src/files/dna-sequence/chart-file-sizes.png
+++ b/assets/dna-sequence/chart-file-sizes.png
Binary files differ
diff --git a/src/files/dna-sequence/dna-basics.jpg b/assets/dna-sequence/dna-basics.jpg
index c2e7f52..c2e7f52 100644
--- a/src/files/dna-sequence/dna-basics.jpg
+++ b/assets/dna-sequence/dna-basics.jpg
Binary files differ
diff --git a/src/files/dna-sequence/quote.png b/assets/dna-sequence/quote.png
index 09fb01c..09fb01c 100644
--- a/src/files/dna-sequence/quote.png
+++ b/assets/dna-sequence/quote.png
Binary files differ
diff --git a/src/files/dna-sequence/sample-binary-file.png b/assets/dna-sequence/sample-binary-file.png
index 1e4622a..1e4622a 100644
--- a/src/files/dna-sequence/sample-binary-file.png
+++ b/assets/dna-sequence/sample-binary-file.png
Binary files differ
diff --git a/src/files/dna-sequence/sample.png b/assets/dna-sequence/sample.png
index 30f12da..30f12da 100644
--- a/src/files/dna-sequence/sample.png
+++ b/assets/dna-sequence/sample.png
Binary files differ
diff --git a/src/files/do-fuse/copy-benchmarks.tsv b/assets/do-fuse/copy-benchmarks.tsv
index c7a7af4..c7a7af4 100644
--- a/src/files/do-fuse/copy-benchmarks.tsv
+++ b/assets/do-fuse/copy-benchmarks.tsv
diff --git a/src/files/do-fuse/fuse-droplets.png b/assets/do-fuse/fuse-droplets.png
index d7ce243..d7ce243 100644
--- a/src/files/do-fuse/fuse-droplets.png
+++ b/assets/do-fuse/fuse-droplets.png
Binary files differ
diff --git a/src/files/do-fuse/fuse-spaces.png b/assets/do-fuse/fuse-spaces.png
index 4dcc1c5..4dcc1c5 100644
--- a/src/files/do-fuse/fuse-spaces.png
+++ b/assets/do-fuse/fuse-spaces.png
Binary files differ
diff --git a/src/files/do-fuse/sqlite-benchmarks.tsv b/assets/do-fuse/sqlite-benchmarks.tsv
index daa2c21..daa2c21 100644
--- a/src/files/do-fuse/sqlite-benchmarks.tsv
+++ b/assets/do-fuse/sqlite-benchmarks.tsv
diff --git a/src/files/go-profiling/golang-profiling-cpu.pdf b/assets/go-profiling/golang-profiling-cpu.pdf
index 15241cb..15241cb 100644
--- a/src/files/go-profiling/golang-profiling-cpu.pdf
+++ b/assets/go-profiling/golang-profiling-cpu.pdf
Binary files differ
diff --git a/src/files/go-profiling/golang-profiling-mem.pdf b/assets/go-profiling/golang-profiling-mem.pdf
index 822e445..822e445 100644
--- a/src/files/go-profiling/golang-profiling-mem.pdf
+++ b/assets/go-profiling/golang-profiling-mem.pdf
Binary files differ
diff --git a/src/files/iot-application/iot-app-output.png b/assets/iot-application/iot-app-output.png
index 1c80589..1c80589 100644
--- a/src/files/iot-application/iot-app-output.png
+++ b/assets/iot-application/iot-app-output.png
Binary files differ
diff --git a/src/files/iot-application/iot-rest-example.png b/assets/iot-application/iot-rest-example.png
index 3ed86aa..3ed86aa 100644
--- a/src/files/iot-application/iot-rest-example.png
+++ b/assets/iot-application/iot-rest-example.png
Binary files differ
diff --git a/src/files/iot-application/iot-sqlite-db.png b/assets/iot-application/iot-sqlite-db.png
index 82e1e29..82e1e29 100644
--- a/src/files/iot-application/iot-sqlite-db.png
+++ b/assets/iot-application/iot-sqlite-db.png
Binary files differ
diff --git a/src/files/iot-application/kcachegrind.png b/assets/iot-application/kcachegrind.png
index 0dc48ab..0dc48ab 100644
--- a/src/files/iot-application/kcachegrind.png
+++ b/assets/iot-application/kcachegrind.png
Binary files differ
diff --git a/src/files/iot-application/profiling-viewer.png b/assets/iot-application/profiling-viewer.png
index a450513..a450513 100644
--- a/src/files/iot-application/profiling-viewer.png
+++ b/assets/iot-application/profiling-viewer.png
Binary files differ
diff --git a/src/files/iot-application/simple-iot-application-overview.svg b/assets/iot-application/simple-iot-application-overview.svg
index 817666d..817666d 100644
--- a/src/files/iot-application/simple-iot-application-overview.svg
+++ b/assets/iot-application/simple-iot-application-overview.svg
diff --git a/src/files/iot-application/simple-iot-application.zip b/assets/iot-application/simple-iot-application.zip
index 46d3205..46d3205 100644
--- a/src/files/iot-application/simple-iot-application.zip
+++ b/assets/iot-application/simple-iot-application.zip
Binary files differ
diff --git a/src/files/iot-application/snakeviz.png b/assets/iot-application/snakeviz.png
index 5bab395..5bab395 100644
--- a/src/files/iot-application/snakeviz.png
+++ b/assets/iot-application/snakeviz.png
Binary files differ
diff --git a/src/files/python-profiling/kcachegrind.png b/assets/python-profiling/kcachegrind.png
index 0dc48ab..0dc48ab 100644
--- a/src/files/python-profiling/kcachegrind.png
+++ b/assets/python-profiling/kcachegrind.png
Binary files differ
diff --git a/src/files/python-profiling/profiling-viewer.png b/assets/python-profiling/profiling-viewer.png
index a450513..a450513 100644
--- a/src/files/python-profiling/profiling-viewer.png
+++ b/assets/python-profiling/profiling-viewer.png
Binary files differ
diff --git a/src/files/python-profiling/snakeviz.png b/assets/python-profiling/snakeviz.png
index 5bab395..5bab395 100644
--- a/src/files/python-profiling/snakeviz.png
+++ b/assets/python-profiling/snakeviz.png
Binary files differ
diff --git a/src/files/sentiment-analysis/.ipynb_checkpoints/TF Test-checkpoint.ipynb b/assets/sentiment-analysis/.ipynb_checkpoints/TF Test-checkpoint.ipynb
index e2a85c4..e2a85c4 100644
--- a/src/files/sentiment-analysis/.ipynb_checkpoints/TF Test-checkpoint.ipynb
+++ b/assets/sentiment-analysis/.ipynb_checkpoints/TF Test-checkpoint.ipynb
diff --git a/src/files/sentiment-analysis/.ipynb_checkpoints/sentiment-analysis-checkpoint.ipynb b/assets/sentiment-analysis/.ipynb_checkpoints/sentiment-analysis-checkpoint.ipynb
index 2c0934c..2c0934c 100644
--- a/src/files/sentiment-analysis/.ipynb_checkpoints/sentiment-analysis-checkpoint.ipynb
+++ b/assets/sentiment-analysis/.ipynb_checkpoints/sentiment-analysis-checkpoint.ipynb
diff --git a/src/files/sentiment-analysis/guardian-sa-title-desc-relationship.png b/assets/sentiment-analysis/guardian-sa-title-desc-relationship.png
index 7195bbf..7195bbf 100644
--- a/src/files/sentiment-analysis/guardian-sa-title-desc-relationship.png
+++ b/assets/sentiment-analysis/guardian-sa-title-desc-relationship.png
Binary files differ
diff --git a/src/files/sentiment-analysis/sentiment-analysis.ipynb b/assets/sentiment-analysis/sentiment-analysis.ipynb
index 2c0934c..2c0934c 100644
--- a/src/files/sentiment-analysis/sentiment-analysis.ipynb
+++ b/assets/sentiment-analysis/sentiment-analysis.ipynb
diff --git a/config b/config
deleted file mode 100644
index 0861a1a..0000000
--- a/config
+++ /dev/null
@@ -1,40 +0,0 @@
1TEMPLATES = site.tmpl
2SOURCE = src
3OUTPUT = public
4TITLE = Mitja Felicijan
5DESCRIPTION = Fan of science fiction and dabbler in code
6GOOGLE_VERIFICATION = EwUGW1WlCkRIQuyQ9AE1-bLitWthw-eVMZFTAMZVZaA
7TWITTER_HANDLE = @mitjafelicijan
8URL = https://mitjafelicijan.com
9AUTHOR = Mitja Felicijan
10
11notes/*.md:
12 config
13 ext .html
14 tags tags/*.tag
15 markdown
16 template post
17 template page
18
19experiments/*.md:
20 config
21 ext .html
22 tags tags/*.tag
23 markdown
24 template post
25 template page
26
27feed.atom: notes/*.md
28 inner-template
29
30*.md:
31 config
32 ext .html
33 markdown
34 template post
35 template page
36
37index.html: blog/*.md
38 config
39 inner-template
40 template page
diff --git a/src/curriculum-vitae.md b/content/curriculum-vitae.md
index acbd83e..b215b03 100644
--- a/src/curriculum-vitae.md
+++ b/content/curriculum-vitae.md
@@ -1,8 +1,8 @@
1title: Curriculum Vitae 1~ title: Curriculum Vitae
2date: 2018-01-16 2~ slug: /curriculum-vitae.html
3type: page 3~ date: 2018-01-16
4hide: false 4~ template: page
5---- 5~ hide: true
6 6
7**Mitja Felicijan** 7**Mitja Felicijan**
8 8
diff --git a/src/experiments/encoding-binary-data-into-dna-sequence.md b/content/encoding-binary-data-into-dna-sequence.md
index bfcf710..a4f8b86 100644
--- a/src/experiments/encoding-binary-data-into-dna-sequence.md
+++ b/content/encoding-binary-data-into-dna-sequence.md
@@ -1,9 +1,9 @@
1title: Encoding binary data into DNA sequence 1~ title: Encoding binary data into DNA sequence
2description: Imagine a world where you could go outside and take a leaf from a tree and put it through your personal DNA sequencer and get data like music, videos or computer programs from it 2~ description: Imagine a world where you could go outside and take a leaf from a tree and put it through your ~ personal DNA sequencer and get data like music, videos or computer programs from it
3date: 2019-01-03 3~ slug: /experiments/encoding-binary-data-into-dna-sequence.html
4type: post 4~ date: 2019-01-03
5hide: false 5~ template: post
6---- 6~ hide: false
7 7
8## Initial thoughts 8## Initial thoughts
9 9
@@ -81,7 +81,7 @@ Deoxyribonucleic acid, a self-replicating material which is **present in nearly
81 81
82The nucleotide in DNA consists of a sugar (deoxyribose), one of four bases (cytosine (C), thymine (T), adenine (A), guanine (G)), and a phosphate. Cytosine and thymine are pyrimidine bases, while adenine and guanine are purine bases. The sugar and the base together are called a nucleoside. 82The nucleotide in DNA consists of a sugar (deoxyribose), one of four bases (cytosine (C), thymine (T), adenine (A), guanine (G)), and a phosphate. Cytosine and thymine are pyrimidine bases, while adenine and guanine are purine bases. The sugar and the base together are called a nucleoside.
83 83
84![DNA](/files/dna-sequence/dna-basics.jpg#center) 84![DNA](/assets/dna-sequence/dna-basics.jpg#center)
85 85
86*DNA (a) forms a double stranded helix, and (b) adenine pairs with thymine and cytosine pairs with guanine. (credit a: modification of work by Jerome Walker, Dennis Myts) [^3]* 86*DNA (a) forms a double stranded helix, and (b) adenine pairs with thymine and cytosine pairs with guanine. (credit a: modification of work by Jerome Walker, Dennis Myts) [^3]*
87 87
@@ -114,7 +114,7 @@ using a single nucleotide. In this way, we are able to use the 4 bases that comp
114 114
115With this in mind we can simply encode any data by using two-bit to Nucleotides conversion 115With this in mind we can simply encode any data by using two-bit to Nucleotides conversion
116 116
117```pascal 117```python
118{ Algorithm 1: Naive byte array to DNA encode } 118{ Algorithm 1: Naive byte array to DNA encode }
119procedure EncodeToDNASequence(f) string 119procedure EncodeToDNASequence(f) string
120begin 120begin
@@ -179,7 +179,7 @@ FASTA format was extended by [FASTQ](https://en.wikipedia.org/wiki/FASTQ_format)
179 179
180With this in mind we can create a simple algorithm to create PNG representation of a DNA sequence. 180With this in mind we can create a simple algorithm to create PNG representation of a DNA sequence.
181 181
182```pascal 182```python
183{ Algorithm 2: Naive DNA to PNG encode from FASTA file } 183{ Algorithm 2: Naive DNA to PNG encode from FASTA file }
184procedure EncodeDNASequenceToPNG(f) 184procedure EncodeDNASequenceToPNG(f)
185begin 185begin
@@ -246,11 +246,11 @@ Then we encode FASTA file from previous operation to encode this data into PNG.
246 246
247After encoding into PNG format this file looks like this. 247After encoding into PNG format this file looks like this.
248 248
249![Encoded Quote in PNG format](/files/dna-sequence/quote.png) 249![Encoded Quote in PNG format](/assets/dna-sequence/quote.png)
250 250
251The larger the input stream is the larger the PNG file would be. 251The larger the input stream is the larger the PNG file would be.
252 252
253Compiled basic Hello World C program with [GCC](https://www.gnu.org/software/gcc/) would [look like](/files/dna-sequence/sample.png). 253Compiled basic Hello World C program with [GCC](https://www.gnu.org/software/gcc/) would [look like](/assets/dna-sequence/sample.png).
254 254
255```c 255```c
256// gcc -O3 -o sample sample.c 256// gcc -O3 -o sample sample.c
@@ -313,7 +313,7 @@ dd if=<(openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=
313 313
314Our freshly generated 1KB file looks something like this (its full of garbage data as intended). 314Our freshly generated 1KB file looks something like this (its full of garbage data as intended).
315 315
316![Sample binary file 1KB](/files/dna-sequence/sample-binary-file.png) 316![Sample binary file 1KB](/assets/dna-sequence/sample-binary-file.png)
317 317
318We create following binary files: 318We create following binary files:
319- 1KB.bin 319- 1KB.bin
@@ -335,7 +335,7 @@ Then we GZIP all the FASTA files to see how much the can be compressed.
335gzip -9 < 10MB.fa > 10MB.fa.gz 335gzip -9 < 10MB.fa > 10MB.fa.gz
336``` 336```
337 337
338[Download ODS file with benchmarks](/files/dna-sequence/benchmarks.ods). 338[Download ODS file with benchmarks](/assets/dna-sequence/benchmarks.ods).
339 339
340## References 340## References
341 341
diff --git a/src/notes/golang-profiling-simplified.md b/content/golang-profiling-simplified.md
index 29e07d6..7b60580 100644
--- a/src/notes/golang-profiling-simplified.md
+++ b/content/golang-profiling-simplified.md
@@ -1,9 +1,9 @@
1title: Golang profiling simplified 1~ title: Golang profiling simplified
2description: Golang profiling demystified 2~ description: Golang profiling demystified
3date: 2017-03-07 3~ slug: /notes/golang-profiling-simplified.html
4type: post 4~ date: 2017-03-07
5hide: false 5~ template: post
6---- 6~ hide: false
7 7
8Many posts have been written regarding profiling in Golang and I haven’t found proper tutorial regarding this. Almost all of them are missing some part of important information and it gets pretty frustrating when you have a deadline and are not finding simple distilled solution. 8Many posts have been written regarding profiling in Golang and I haven’t found proper tutorial regarding this. Almost all of them are missing some part of important information and it gets pretty frustrating when you have a deadline and are not finding simple distilled solution.
9 9
@@ -107,5 +107,5 @@ go tool pprof -pdf ./cpu cpu.pprof > cpu.pdf
107 107
108This will generate PDF document with visualized profile. 108This will generate PDF document with visualized profile.
109 109
110- [Memory PDF profile example](/files/go-profiling/golang-profiling-mem.pdf) 110- [Memory PDF profile example](/assets/go-profiling/golang-profiling-mem.pdf)
111- [CPU PDF profile example](/files/go-profiling/golang-profiling-cpu.pdf) 111- [CPU PDF profile example](/assets/go-profiling/golang-profiling-cpu.pdf)
diff --git a/src/experiments/profiling-python-web-applications-with-visual-tools.md b/content/profiling-python-web-applications-with-visual-tools.md
index cf7164c..dd9a692 100644
--- a/src/experiments/profiling-python-web-applications-with-visual-tools.md
+++ b/content/profiling-python-web-applications-with-visual-tools.md
@@ -1,9 +1,9 @@
1title: Profiling Python web applications with visual tools 1~ title: Profiling Python web applications with visual tools
2description: Missing link when debugging and profiling python web application 2~ description: Missing link when debugging and profiling python web application
3date: 2017-04-21 3~ slug: /experiments/profiling-python-web-applications-with-visual-tools.html
4type: post 4~ date: 2017-04-21
5hide: false 5~ template: post
6---- 6~ hide: false
7 7
8I have been profiling my software with KCachegrind for a long time now and I was missing this option when I am developing API's or other web services. I always knew that this is possible but never really took the time and dive into it. 8I have been profiling my software with KCachegrind for a long time now and I was missing this option when I am developing API's or other web services. I always knew that this is possible but never really took the time and dive into it.
9 9
@@ -16,7 +16,7 @@ Before we begin there are some requirements. We will need to:
16 16
17If you are using MacOS you should check out [Profiling Viewer](http://www.profilingviewer.com/) or [MacCallGrind](http://www.maccallgrind.com/). 17If you are using MacOS you should check out [Profiling Viewer](http://www.profilingviewer.com/) or [MacCallGrind](http://www.maccallgrind.com/).
18 18
19![KCachegrind](/files/python-profiling/kcachegrind.png) 19![KCachegrind](/assets/python-profiling/kcachegrind.png)
20 20
21We will be dividing this post into two main categories: 21We will be dividing this post into two main categories:
22 22
@@ -135,7 +135,7 @@ $ pyprof2calltree -i awesome_random_number.prof
135 135
136This file can be opened with visualizing tools listed above. In this case we will be using Profilling Viewer under MacOS. You can open image in new tab. As you can see from this example there is hierarchy of execution order of your code. 136This file can be opened with visualizing tools listed above. In this case we will be using Profilling Viewer under MacOS. You can open image in new tab. As you can see from this example there is hierarchy of execution order of your code.
137 137
138![Profilling Viewer](/files/python-profiling/profiling-viewer.png) 138![Profilling Viewer](/assets/python-profiling/profiling-viewer.png)
139 139
140> Make sure you convert output of the cProfile output every time you want to refresh and take a look at your possible optimizations because cProfile updates .prof file every time browser hits the function. 140> Make sure you convert output of the cProfile output every time you want to refresh and take a look at your possible optimizations because cProfile updates .prof file every time browser hits the function.
141 141
@@ -158,7 +158,7 @@ $ snakeviz awesome_random_number.prof
158# shows visualized profile 158# shows visualized profile
159``` 159```
160 160
161![SnakeViz](/files/python-profiling/snakeviz.png) 161![SnakeViz](/assets/python-profiling/snakeviz.png)
162 162
163Reddit user [ccharles](https://www.reddit.com/user/ccharles) suggested a better way for installing pip software by targeting user level instead of using sudo. 163Reddit user [ccharles](https://www.reddit.com/user/ccharles) suggested a better way for installing pip software by targeting user level instead of using sudo.
164 164
diff --git a/src/experiments/simple-iot-application.md b/content/simple-iot-application.md
index c7f59cf..6a8c733 100644
--- a/src/experiments/simple-iot-application.md
+++ b/content/simple-iot-application.md
@@ -1,9 +1,9 @@
1title: Simple IOT application supported by real-time monitoring and data history 1~ title: Simple IOT application supported by real-time monitoring and data history
2description: Develop simple IOT application with Arduino MKR1000 and Python 2~ description: Develop simple IOT application with Arduino MKR1000 and Python
3date: 2017-08-11 3~ slug: /experiments/simple-iot-application.html
4type: post 4~ date: 2017-08-11
5hide: false 5~ template: post
6---- 6~ hide: false
7 7
8## Initial thoughts 8## Initial thoughts
9 9
@@ -27,7 +27,7 @@ Step 1. and 3. will share the same web application. One route will be dedicated
27 27
28Schema below represents what we will try to achieve and how different parts correlates to each other. 28Schema below represents what we will try to achieve and how different parts correlates to each other.
29 29
30![Overview](/files/iot-application/simple-iot-application-overview.svg) 30![Overview](/assets/iot-application/simple-iot-application-overview.svg)
31 31
32## Simple Python API 32## Simple Python API
33 33
@@ -148,11 +148,11 @@ To run this simply go to folder containing python file and run ```python webapp.
148 148
149After testing the service with Restlet Client you should be able to view your data in a database file ```data.db```. 149After testing the service with Restlet Client you should be able to view your data in a database file ```data.db```.
150 150
151![REST settings example](/files/iot-application/iot-rest-example.png) 151![REST settings example](/assets/iot-application/iot-rest-example.png)
152 152
153You can also check the contents of new database file by using desktop client for SQLite → [DB Browser for SQLite](http://sqlitebrowser.org/). 153You can also check the contents of new database file by using desktop client for SQLite → [DB Browser for SQLite](http://sqlitebrowser.org/).
154 154
155![SQLite database example](/files/iot-application/iot-sqlite-db.png) 155![SQLite database example](/assets/iot-application/iot-sqlite-db.png)
156 156
157Table structure is as simple as it can be. We have ts (timestamp) and value (value from Arduino). As you can see timestamp is generated on API side. If you would happen to have atomic clock on Arduino it would be then better to generate and send timestamp with the value. This would be particularity useful if we would be collecting sensor data at a higher frequency and then sending this data in bulk to API. 157Table structure is as simple as it can be. We have ts (timestamp) and value (value from Arduino). As you can see timestamp is generated on API side. If you would happen to have atomic clock on Arduino it would be then better to generate and send timestamp with the value. This would be particularity useful if we would be collecting sensor data at a higher frequency and then sending this data in bulk to API.
158 158
@@ -469,9 +469,9 @@ If everything goes well you should be seeing new data-points rendered on chart e
469 469
470If you navigate to ```http://0.0.0.0:5000``` you should see rendered chart as shown on picture below. 470If you navigate to ```http://0.0.0.0:5000``` you should see rendered chart as shown on picture below.
471 471
472![Application output](/files/iot-application/iot-app-output.png) 472![Application output](/assets/iot-application/iot-app-output.png)
473 473
474Complete application with all the code is available for [download](/files/iot-application/simple-iot-application.zip). 474Complete application with all the code is available for [download](/assets/iot-application/simple-iot-application.zip).
475 475
476## Conclusion 476## Conclusion
477 477
diff --git a/src/notes/simplifying-and-reducing-clutter.md b/content/simplifying-and-reducing-clutter.md
index 483d0dc..7182a4e 100644
--- a/src/notes/simplifying-and-reducing-clutter.md
+++ b/content/simplifying-and-reducing-clutter.md
@@ -1,9 +1,9 @@
1title: Simplifying and reducing clutter in my life and work 1~ title: Simplifying and reducing clutter in my life and work
2description: Simplifying and reducing clutter in my life and work 2~ description: Simplifying and reducing clutter in my life and work
3date: 2019-10-14 3~ slug: /notes/simplifying-and-reducing-clutter.html
4type: post 4~ date: 2019-10-14
5hide: false 5~ template: post
6---- 6~ hide: false
7 7
8I recently moved my main working machine back from Hachintosh to Linux. Well the experiment was interesting and I have done some great work on macOS but it was time to move back. 8I recently moved my main working machine back from Hachintosh to Linux. Well the experiment was interesting and I have done some great work on macOS but it was time to move back.
9 9
diff --git a/src/experiments/using-digitalocean-spaces-object-storage-with-fuse.md b/content/using-digitalocean-spaces-object-storage-with-fuse.md
index 1d3fe48..e2b3ad8 100644
--- a/src/experiments/using-digitalocean-spaces-object-storage-with-fuse.md
+++ b/content/using-digitalocean-spaces-object-storage-with-fuse.md
@@ -1,9 +1,9 @@
1title: Using DigitalOcean Spaces Object Storage with FUSE 1~ title: Using DigitalOcean Spaces Object Storage with FUSE
2description: Using DigitalOcean Spaces Object Storage with FUSE 2~ description: Using DigitalOcean Spaces Object Storage with FUSE
3date: 2018-01-16 3~ slug: /experiments/using-digitalocean-spaces-object-storage-with-fuse.html
4type: post 4~ date: 2018-01-16
5hide: false 5~ template: post
6---- 6~ hide: false
7 7
8Couple of months ago [DigitalOcean](https://www.digitalocean.com) introduced new product called [Spaces](https://blog.digitalocean.com/introducing-spaces-object-storage/) which is Object Storage very similar to Amazon's S3. This really peaked my interest, because this was something I was missing and even the thought of going over the internet for such functionality was in no interest to me. Also in fashion with their previous pricing this also is very cheap and pricing page is a no-brainer compared to AWS or GCE. [Prices are clearly and precisely defined and outlined](https://www.digitalocean.com/pricing/). You must love them for that :) 8Couple of months ago [DigitalOcean](https://www.digitalocean.com) introduced new product called [Spaces](https://blog.digitalocean.com/introducing-spaces-object-storage/) which is Object Storage very similar to Amazon's S3. This really peaked my interest, because this was something I was missing and even the thought of going over the internet for such functionality was in no interest to me. Also in fashion with their previous pricing this also is very cheap and pricing page is a no-brainer compared to AWS or GCE. [Prices are clearly and precisely defined and outlined](https://www.digitalocean.com/pricing/). You must love them for that :)
9 9
@@ -26,13 +26,13 @@ To make this work you will need DigitalOcean account. If you don't have one you
26 26
27Instuctions on how to use SSH keys and how to setup them are available in article [How To Use SSH Keys with DigitalOcean Droplets](https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-droplets). 27Instuctions on how to use SSH keys and how to setup them are available in article [How To Use SSH Keys with DigitalOcean Droplets](https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-droplets).
28 28
29![DigitalOcean Droplets](/files/do-fuse/fuse-droplets.png) 29![DigitalOcean Droplets](/assets/do-fuse/fuse-droplets.png)
30 30
31After we created Droplet it's time to create new Space. This is done by clicking on a button [Create](https://cloud.digitalocean.com/spaces/new) (right top corner) and selecting Spaces. Choose pronounceable ```Unique name``` because we will use it in examples below. You can either choose Private or Public, it doesn't matter in our case. And you can always change that in the future. 31After we created Droplet it's time to create new Space. This is done by clicking on a button [Create](https://cloud.digitalocean.com/spaces/new) (right top corner) and selecting Spaces. Choose pronounceable ```Unique name``` because we will use it in examples below. You can either choose Private or Public, it doesn't matter in our case. And you can always change that in the future.
32 32
33When you have created new Space we should [generate Access key](https://cloud.digitalocean.com/settings/api/tokens). This link will guide to the page when you can generate this key. After you create new one, please save provided Key and Secret because Secret will not be shown again. 33When you have created new Space we should [generate Access key](https://cloud.digitalocean.com/settings/api/tokens). This link will guide to the page when you can generate this key. After you create new one, please save provided Key and Secret because Secret will not be shown again.
34 34
35![DigitalOcean Spaces](/files/do-fuse/fuse-spaces.png) 35![DigitalOcean Spaces](/assets/do-fuse/fuse-spaces.png)
36 36
37Now that we have new Space and Access key we should SSH into our machine. 37Now that we have new Space and Access key we should SSH into our machine.
38 38
@@ -102,14 +102,14 @@ As I suspected, object size is not really that important. Sadly I don't have the
102 102
103**Here are plotted results** 103**Here are plotted results**
104 104
105You can download [raw result here](/files/do-fuse/copy-benchmarks.tsv). Measurements are in seconds. 105You can download [raw result here](/assets/do-fuse/copy-benchmarks.tsv). Measurements are in seconds.
106 106
107<script src="//cdn.plot.ly/plotly-latest.min.js"></script> 107<script src="//cdn.plot.ly/plotly-latest.min.js"></script>
108<div id="copy-benchmarks"></div> 108<div id="copy-benchmarks"></div>
109<script> 109<script>
110(function(){ 110(function(){
111 var request = new XMLHttpRequest(); 111 var request = new XMLHttpRequest();
112 request.open("GET", "/files/do-fuse/copy-benchmarks.tsv", true); 112 request.open("GET", "/assets/do-fuse/copy-benchmarks.tsv", true);
113 request.onload = function() { 113 request.onload = function() {
114 if (request.status >= 200 && request.status < 400) { 114 if (request.status >= 200 && request.status < 400) {
115 var payload = request.responseText.trim(); 115 var payload = request.responseText.trim();
@@ -218,13 +218,13 @@ result_time = CLOSE = end_time - start_time
218print("CLOSE: %g seconds" % (result_time)) 218print("CLOSE: %g seconds" % (result_time))
219``` 219```
220 220
221You can download [raw result here](/files/do-fuse/sqlite-benchmarks.tsv). And again, these results are done on a local block storage and do not represent capabilities of object storage. With my current approach and state of the test code these can not be done. I would need to make Python code much more robust and check locking etc. 221You can download [raw result here](/assets/do-fuse/sqlite-benchmarks.tsv). And again, these results are done on a local block storage and do not represent capabilities of object storage. With my current approach and state of the test code these can not be done. I would need to make Python code much more robust and check locking etc.
222 222
223<div id="sqlite-benchmarks"></div> 223<div id="sqlite-benchmarks"></div>
224<script> 224<script>
225(function(){ 225(function(){
226 var request = new XMLHttpRequest(); 226 var request = new XMLHttpRequest();
227 request.open("GET", "/files/do-fuse/sqlite-benchmarks.tsv", true); 227 request.open("GET", "/assets/do-fuse/sqlite-benchmarks.tsv", true);
228 request.onload = function() { 228 request.onload = function() {
229 if (request.status >= 200 && request.status < 400) { 229 if (request.status >= 200 && request.status < 400) {
230 var payload = request.responseText.trim(); 230 var payload = request.responseText.trim();
diff --git a/src/experiments/using-sentiment-analysis-for-click-bait-detection-in-rss-feeds.md b/content/using-sentiment-analysis-for-click-bait-detection-in-rss-feeds.md
index ad0362b..d849763 100644
--- a/src/experiments/using-sentiment-analysis-for-click-bait-detection-in-rss-feeds.md
+++ b/content/using-sentiment-analysis-for-click-bait-detection-in-rss-feeds.md
@@ -1,9 +1,9 @@
1title: Using sentiment analysis for click&#8209;bait detection in RSS feeds 1~ title: Using sentiment analysis for click&#8209;bait detection in RSS feeds
2description: Using Python with sentiment analysis to detect if titles in RSS feeds are click-bait 2~ description: Using Python with sentiment analysis to detect if titles in RSS feeds are click-bait
3date: 2019-10-19 3~ slug: /experiments/using-sentiment-analysis-for-click-bait-detection-in-rss-feeds.html
4type: post 4~ date: 2019-10-19
5hide: false 5~ template: post
6---- 6~ hide: false
7 7
8## Initial thoughts 8## Initial thoughts
9 9
@@ -72,11 +72,11 @@ plt.show()
722. Rule-based approach may not be the best way of doing this. By using deep learning we would be able to get better insights. 722. Rule-based approach may not be the best way of doing this. By using deep learning we would be able to get better insights.
733. **Next step would be to** periodically fetch RSS items and store them over a longer period of time and then perform analysis again and use either machine learning or deep learning on top of it. 733. **Next step would be to** periodically fetch RSS items and store them over a longer period of time and then perform analysis again and use either machine learning or deep learning on top of it.
74 74
75![Relationship between title and description](/files/sentiment-analysis/guardian-sa-title-desc-relationship.png) 75![Relationship between title and description](/assets/sentiment-analysis/guardian-sa-title-desc-relationship.png)
76 76
77Figure above displays difference between title and description sentiment for specific RSS feed item. 1 means positive and -1 means negative sentiment. 77Figure above displays difference between title and description sentiment for specific RSS feed item. 1 means positive and -1 means negative sentiment.
78 78
79[» Download Jupyter Notebook](/files/sentiment-analysis/sentiment-analysis.ipynb) 79[» Download Jupyter Notebook](/assets/sentiment-analysis/sentiment-analysis.ipynb)
80 80
81## Going further 81## Going further
82 82
diff --git a/src/notes/what-i-ve-learned-developing-ad-server.md b/content/what-i-ve-learned-developing-ad-server.md
index 25f11a3..e546775 100644
--- a/src/notes/what-i-ve-learned-developing-ad-server.md
+++ b/content/what-i-ve-learned-developing-ad-server.md
@@ -1,9 +1,9 @@
1title: What I've learned developing ad server 1~ title: What I've learned developing ad server
2description: Lessons I learned developing contextual ad server 2~ description: Lessons I learned developing contextual ad server
3date: 2017-04-17 3~ slug: /notes/what-i-ve-learned-developing-ad-server.html
4type: post 4~ date: 2017-04-17
5hide: false 5~ template: post
6---- 6~ hide: false
7 7
8For the past year and half I have been developing native advertising server that contextually matches ads and displays them in different template forms on variety of websites. This project grew from serving thousands of ads per day to millions. 8For the past year and half I have been developing native advertising server that contextually matches ads and displays them in different template forms on variety of websites. This project grew from serving thousands of ads per day to millions.
9 9
diff --git a/site.tmpl b/site.tmpl
deleted file mode 100644
index c745997..0000000
--- a/site.tmpl
+++ /dev/null
@@ -1,140 +0,0 @@
1{{ define "header" }}
2<!doctype html>
3<html lang="en">
4
5 <head>
6 <meta charset="utf-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1.0">
8 <meta name="theme-color" content="#ffffff">
9 <meta name="google-site-verification" content="{{ html .Site.Other.Google_verification }}">
10 <meta http-equiv="X-UA-Compatible" content="ie=edge">
11
12 <link rel="preconnect" href="https://www.google-analytics.com">
13
14 <link rel="alternate" type="application/atom+xml" title="{{ html .Site.Other.Title }} feed" href="{{ .Rel "feed.atom" }}">
15 <link rel="stylesheet" type="text/css" href="{{ .Rel "static/style.css" }}?v={{ .ModTime.Format "20060102150405" }}">
16 <link rel="icon" type="image/png" href="{{ .Rel "static/avatar-64x64.png" }}?v={{ .ModTime.Format "20060102150405" }}">
17
18 <title>{{ if .Title }}{{ .Title }} - {{ end }}{{ .Site.Other.Title }}</title>
19 <meta name="author" content="{{ html .Site.Other.Author }}">
20 <meta name="description" content="{{ if .Other.Description }}{{ .Other.Description }}{{ else }}{{ html .Site.Other.Description }}{{ end }}">
21
22 <meta property="og:title" content="{{ if .Title }}{{ .Title }} - {{ end }}{{ .Site.Other.Title }}">
23 <meta property="og:description" content="{{ if .Other.Description }}{{ .Other.Description }}{{ else }}{{ html .Site.Other.Description }}{{ end }}">
24 <meta property="og:url" content="{{ .Site.Other.Url }}/{{ .Url }}">
25
26 <meta name="twitter:card" content="summary">
27 <meta name="twitter:site" content="{{ html .Site.Other.Twitter_handle }}">
28 </head>
29
30 <body>
31 <main>
32 {{ end }}
33 {{ define "footer" }}
34 </main>
35 {{ template "ga" . }}
36 </body>
37
38</html>
39{{ end }}
40
41{{ define "navigation" }}
42<nav>
43 <a href="/">{{ html .Site.Other.Author }}</a>
44 <a href="/curriculum-vitae.html">CV</a>
45 <a href="https://twitter.com/mitjafelicijan" target="_blank" rel="noopener nofollow">Twitter</a>
46 <a href="https://github.com/mitjafelicijan" target="_blank" rel="noopener nofollow">Github</a>
47</nav>
48{{ end }}
49
50{{ define "author" }}
51<span>by {{ html .Site.Other.Author }}</span>
52{{ end }}
53
54{{define "date"}}
55<time datetime="{{ .Format "2006-01-02T15:04:05Z07:00" }}">
56 {{ .Format "2006, January 02" }}
57</time>
58{{end}}
59
60{{define "modified"}}
61<p class="modified">Modified on {{ .ModTime.Format "2006-01-02T15:04:05" }}</p>
62{{end}}
63
64{{ define "page" }}
65{{ template "header" . }}
66{{ template "navigation" . }}
67{{ .Content }}
68{{ template "prism" . }}
69{{ template "mathjax" . }}
70{{ template "footer" . }}
71{{ end }}
72
73{{ define "post" }}
74<article>
75 <header>
76 <h1>{{ .Title }}</h1>
77 {{ if eq .Other.Type "post" }}
78 <div class="info">
79 {{ template "date" .Date }}
80 {{ template "author" . }}
81 </div>
82 {{ end }}
83 </header>
84 <section>
85 {{ .Content }}
86 </section>
87</article>
88
89{{ if eq .Other.Type "post" }}
90{{ template "comments" . }}
91{{ end }}
92
93{{ template "modified" . }}
94{{ end }}
95
96{{ define "mathjax" }}
97<script type="text/x-mathjax-config">
98 MathJax.Hub.Config({
99 TeX: { equationNumbers: { autoNumber: "AMS" } },
100 tex2jax: {
101 inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ],
102 displayMath: [ ['$$', '$$'] ],
103 processEscapes: true
104 }});
105 </script>
106<script src="//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML" async="async"></script>
107{{ end }}
108
109{{ define "ga" }}
110<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-12769079-10"></script>
111<script>
112 window.dataLayer = window.dataLayer || [];
113 function gtag() {
114 dataLayer.push(arguments);
115 }
116 gtag('js', new Date());
117 gtag('config', 'UA-12769079-10');
118</script>
119{{ end }}
120
121{{ define "prism" }}
122<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/components/prism-core.min.js"></script>
123<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/autoloader/prism-autoloader.min.js"></script>
124{{ end }}
125
126{{ define "comments" }}
127<div class="comments">
128 <h3>Comments</h3>
129 <div class="form">
130 <div><input id="name" placeholder="Your name" maxlength="20"></div>
131 <div><textarea id="comment" placeholder="Your comment" maxlength="500"></textarea></div>
132 <div><button id="submit">Post a comment</button></div>
133 </div>
134 <ul></ul>
135</div>
136
137<script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-app.js"></script>
138<script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-database.js"></script>
139<script src="{{ .Rel "static/comments.js" }}?v={{ .ModTime.Format "20060102150405" }}" async></script>
140{{ end }}
diff --git a/src/404.html b/src/404.html
deleted file mode 100644
index 0f0a0b9..0000000
--- a/src/404.html
+++ /dev/null
@@ -1,3 +0,0 @@
1<h1>Content you are looking for is not here.</h1>
2
3<a href="/">« Return to main page</a>
diff --git a/src/comments.html b/src/comments.html
deleted file mode 100644
index 3d990da..0000000
--- a/src/comments.html
+++ /dev/null
@@ -1,100 +0,0 @@
1<!DOCTYPE html>
2<html lang="en">
3
4 <head>
5 <meta charset="utf-8">
6 <meta name="theme-color" content="#ffffff">
7 <meta name="viewport" content="width=device-width, initial-scale=1.0">
8 <meta http-equiv="X-UA-Compatible" content="ie=edge">
9 <title>Commenta dashboard</title>
10
11 <style>
12 th {
13 text-align: left;
14 }
15
16 .comment-item {
17 padding: 10px 0 30px 0;
18 border-bottom: 2px inset gray;
19 }
20 </style>
21
22 </head>
23
24 <body>
25
26 <h1>Comments</h1>
27 <div id="results"></div>
28
29 <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-app.js"></script>
30 <script src="https://www.gstatic.com/firebasejs/7.2.1/firebase-database.js"></script>
31 <script src="static/comments.js"></script>
32
33 <script>
34
35 // var tableResults = document.querySelector('#results tbody');
36 var resultsPlaceholder = document.querySelector('#results');
37
38 function snapshotToArray(snapshot) {
39 var returnArr = [];
40 snapshot.forEach(function (childSnapshot) {
41 var arrItem = childSnapshot.val();
42 arrItem.key = childSnapshot.key;
43 returnArr.push(arrItem);
44 });
45
46 var comments = [];
47 returnArr.forEach(function (item) {
48 var keys = Object.keys(item);
49 for (var key of keys) {
50 let group = item.key;
51 if (key !== 'key') {
52 for (var itemKey of Object.keys(item[key])) {
53 item[key][itemKey].slug = key;
54 item[key][itemKey].group = group;
55 item[key][itemKey].itemKey = itemKey
56 comments.push(item[key][itemKey]);
57 }
58 }
59 }
60 });
61
62 return comments;
63 };
64
65 var path = window.location.hostname.replace('.', '-') + '/comments';
66 var ref = firebase.database().ref(path);
67 ref.on("value", function (snap) {
68 resultsPlaceholder.innerHTML = '';
69 var comments = snapshotToArray(snap);
70 comments.forEach(function (item) {
71 var commentContent = document.createElement('div');
72
73 commentContent.classList.add('comment-item');
74 commentContent.innerHTML = `
75 <p><b>${item.name} (${item.published})</b><br>
76 <i>${item.group}/${item.slug}</i></p>
77 <p>${item.comment}</p>
78 `;
79
80 var buttonDelete = document.createElement('button');
81 buttonDelete.innerText = 'Delete comment';
82 buttonDelete.dataset.id = `${window.location.hostname.replace('.', '-')}/comments/${item.group}/${item.slug}/${item.itemKey}`;
83 buttonDelete.addEventListener('click', function (evt) {
84 if (confirm('Are you sure you want to delete this comment?')) {
85 firebase.database().ref(evt.target.dataset.id).remove();
86 }
87 });
88
89 commentContent.appendChild(buttonDelete);
90 resultsPlaceholder.appendChild(commentContent);
91 });
92 }, function (errorObject) {
93 console.log(`The read failed: ${errorObject.code}`);
94 });
95
96 </script>
97
98 </body>
99
100</html>
diff --git a/src/feed.atom b/src/feed.atom
deleted file mode 100644
index dda420c..0000000
--- a/src/feed.atom
+++ /dev/null
@@ -1,55 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0">
3 <id>{{ .Site.Other.Url }}</id>
4 <title>{{ .Site.Other.Title }}</title>
5 {{ with .Site.Pages.Children "notes/" }}
6 <updated>{{ .First.Date.Format "2006-01-02T15:04:05Z07:00" }}</updated>
7 {{ end }}
8 <author><name>{{ .Site.Other.Author }}</name></author>
9 <link href="{{ .Site.Other.Url }}" rel="alternate"></link>
10 <generator uri="https://github.com/piranha/gostatic">gostatic</generator>
11
12{{ with .Site.Pages.Children "notes/" }}
13{{ range .Slice 0 5 }}
14<entry>
15 <id>{{ .Url }}</id>
16 <author><name>{{ or .Other.Author .Site.Other.Author }}</name></author>
17 <title type="html">{{ html .Title }}</title>
18 <published>{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}</published>
19 {{ range .Tags }}
20 <category term="{{ . }}"></category>
21 {{ end }}
22 <link href="{{ .Site.Other.Url }}/{{ .Url }}" rel="alternate"></link>
23 <content type="html">
24 {{/* .Process runs here in case only feed changed */}}
25 {{ with cut "<section>" "</section>" .Process.Content }}
26 {{ html . }}
27 {{ end }}
28 </content>
29</entry>
30{{ end }}
31{{ end }}
32
33{{ with .Site.Pages.Children "experiments/" }}
34{{ range .Slice 0 5 }}
35<entry>
36 <id>{{ .Url }}</id>
37 <author><name>{{ or .Other.Author .Site.Other.Author }}</name></author>
38 <title type="html">{{ html .Title }}</title>
39 <published>{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}</published>
40 {{ range .Tags }}
41 <category term="{{ . }}"></category>
42 {{ end }}
43 <link href="{{ .Site.Other.Url }}/{{ .Url }}" rel="alternate"></link>
44 <content type="html">
45 {{/* .Process runs here in case only feed changed */}}
46 {{ with cut "<section>" "</section>" .Process.Content }}
47 {{ html . }}
48 {{ end }}
49 </content>
50</entry>
51{{ end }}
52{{ end }}
53
54
55</feed>
diff --git a/src/index.html b/src/index.html
deleted file mode 100644
index 6b987f7..0000000
--- a/src/index.html
+++ /dev/null
@@ -1,21 +0,0 @@
1<h2>Experiments</h2>
2<ul class="article-list">
3{{ range .Site.Pages.Children "experiments/" }}
4 <li>
5 <div>
6 <time>{{ template "date" .Date }}</time>
7 <a href="{{ $.Rel .Url }}" title="{{ .Title }}">{{ .Title }}</a>
8 </div>
9 </li>
10{{ end }}
11</ul>
12
13<h2>General notes</h2>
14<ul class="article-list">
15{{ range .Site.Pages.Children "notes/" }}
16 <li>
17 <time>{{ template "date" .Date }}</time>
18 <a href="{{ $.Rel .Url }}" title="{{ .Title }}">{{ .Title }}</a>
19 </li>
20{{ end }}
21</ul>
diff --git a/src/static/comments.js b/src/static/comments.js
deleted file mode 100644
index 3f373e5..0000000
--- a/src/static/comments.js
+++ /dev/null
@@ -1,65 +0,0 @@
1var firebaseConfig = {
2 apiKey: "AIzaSyD3E0XtiUJI4-JIxcIPZziNLGVaTdojz20",
3 authDomain: "mitja-felicijan-blog.firebaseapp.com",
4 databaseURL: "https://mitja-felicijan-blog.firebaseio.com",
5 projectId: "mitja-felicijan-blog",
6 storageBucket: "mitja-felicijan-blog.appspot.com",
7 messagingSenderId: "41650892882",
8 appId: "1:41650892882:web:b308f0a9c47198bdf7ef8b"
9};
10firebase.initializeApp(firebaseConfig);
11
12var database = firebase.database();
13var docPath = window.location.hostname.replace('.', '-') + '/comments' + window.location.pathname.replace('.html', '');
14var submit = document.querySelector('#submit');
15var comments = document.querySelector('.comments ul');
16var textName = document.querySelector('#name');
17var textComment = document.querySelector('#comment');
18var ref = firebase.database().ref(docPath);
19
20function encodeHTML(s) {
21 return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
22}
23
24if (submit) {
25 ref.on("value", function (snapshot) {
26 comments.innerHTML = '';
27 var commentList = Array();
28
29 // generating normal array
30 snapshot.forEach(function (item) {
31 commentList.push(item.val())
32 });
33
34 // rendering html
35 commentList.reverse().forEach(function (item) {
36 var liItem = `<li>
37 <div><b>${encodeHTML(item.name)}</b> - ${encodeHTML(item.published)}</div>
38 <div>${encodeHTML(item.comment)}</div>
39 </li>`;
40 comments.innerHTML += liItem;
41 });
42
43 }, function (errorObject) {
44 console.log("The read failed: " + errorObject.code);
45 });
46
47 submit.addEventListener('click', function (evt) {
48 if (textName.value && textComment.value) {
49 submit.disabled = true;
50 firebase.database().ref(docPath + '/' + Date.now()).set({
51 name: textName.value,
52 comment: textComment.value,
53 published: new Date().toISOString().slice(0, 16).replace('T', ' '),
54 }, function (error) {
55 if (error) {
56 alert('Data could not be saved.' + error);
57 } else {
58 textName.value = '';
59 textComment.value = '';
60 submit.disabled = false;
61 }
62 });
63 }
64 });
65}
diff --git a/src/static/style.css b/src/static/style.css
deleted file mode 100644
index d2b3203..0000000
--- a/src/static/style.css
+++ /dev/null
@@ -1,319 +0,0 @@
1* {
2 box-sizing: border-box;
3}
4
5body {
6 line-height: 150%;
7 margin-bottom: 100px;
8 font-family: serif;
9}
10
11main {
12 max-width: 760px;
13 padding: 20px 30px;
14}
15
16nav {
17 margin-bottom: 50px;
18}
19
20nav a {
21 display: inline-block;
22 margin-right: 20px;
23}
24
25h1 {
26 font-size: 280%;
27 line-height: initial;
28}
29
30h2 {
31 font-size: 200%;
32 line-height: initial;
33}
34
35h3 {
36 font-size: 160%;
37 line-height: initial;
38}
39
40img {
41 max-width: 100%;
42 margin: 30px auto;
43 display: block;
44}
45
46ul.article-list li {
47 margin-bottom: 10px;
48}
49
50ul.article-list li div {
51 display: flex;
52}
53
54ul.article-list time {
55 display: inline-block;
56 min-width: 160px;
57}
58
59
60article .info {
61 font-style: oblique;
62}
63
64pre {
65 overflow: auto;
66}
67
68table {
69 width: 100%;
70}
71
72table, th, td {
73 border: 1px solid black;
74 text-align: left;
75}
76
77th, td {
78 padding: 5px 10px;
79}
80
81code, pre {
82 font-size: 14px;
83}
84
85code {
86 background: rgb(255, 241, 177);
87 padding: 2px 5px;
88}
89
90pre > code {
91 background: unset;
92 padding: unset;
93}
94
95p.modified {
96 font-style: oblique;
97 font-size: 90%;
98 margin-top: 50px;
99}
100
101::selection {
102 background: #ff0;
103 color: #000;
104}
105
106::-moz-selection {
107 background: #ff0;
108 color: #000;
109}
110
111.comments {
112 margin-top: 50px;
113}
114.comments ul {
115 margin-top: 30px;
116 padding-left: 15px;
117}
118.comments ul li {
119 margin-bottom: 20px;
120}
121.comments input,
122.comments textarea {
123 width: 100%;
124 padding: 10px;
125 margin-bottom: 10px;
126 font-family: inherit;
127 font-size: inherit;
128 border: 1px solid lightgray;
129}
130.comments textarea {
131 resize: vertical;
132 height: 100px;
133}
134
135@media only screen and (max-width:480px) {
136 main {
137 padding: 20px;
138 }
139
140 nav {
141 text-align: center;
142 margin-bottom: initial;
143 }
144
145 nav a {
146 margin-bottom: 10px;
147 }
148
149 ul.article-list {
150 padding-left: 20px;
151
152 }
153
154 ul.article-list li {
155 margin-bottom: 20px;
156
157 }
158
159 ul.article-list li div {
160 display: block;
161 margin-top: 15px;
162 }
163
164 ul.article-list a {
165 display: block;
166 margin-top: 5px;
167 }
168
169 h1 {
170 font-size: 220%;
171 }
172
173 h2 {
174 font-size: 180%;
175 }
176
177 h3 {
178 font-size: 160%;
179 }
180}
181
182@media (prefers-color-scheme: light) {
183 body {
184 background-color: white;
185 color: black;
186 }
187}
188
189@media (prefers-color-scheme: dark) {
190 body {
191 background-color: rgb(30, 30, 30);
192 color: white;
193 }
194
195 a {
196 color: white;
197 }
198}
199
200/* prism theme */
201
202/**
203 * GHColors theme by Avi Aryan (http://aviaryan.in)
204 * Inspired by Github syntax coloring
205 */
206
207code[class*="language-"],
208pre[class*="language-"] {
209 color: #393A34;
210 font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
211 direction: ltr;
212 text-align: left;
213 white-space: pre;
214 word-spacing: normal;
215 word-break: normal;
216 line-height: 1.2em;
217
218 -moz-tab-size: 4;
219 -o-tab-size: 4;
220 tab-size: 4;
221
222 -webkit-hyphens: none;
223 -moz-hyphens: none;
224 -ms-hyphens: none;
225 hyphens: none;
226 }
227
228 pre > code[class*="language-"] {
229
230 }
231
232 pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
233 code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
234 background: #b3d4fc;
235 }
236
237 pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
238 code[class*="language-"]::selection, code[class*="language-"] ::selection {
239 background: #b3d4fc;
240 }
241
242 /* Code blocks */
243 pre[class*="language-"] {
244 padding: 1em;
245 margin: .5em 0;
246 overflow: auto;
247 border: 1px solid #dddddd;
248 background-color: white;
249 }
250
251 /* Inline code */
252 :not(pre) > code[class*="language-"] {
253 padding: .2em;
254 padding-top: 1px; padding-bottom: 1px;
255 background: #f8f8f8;
256 border: 1px solid #dddddd;
257 }
258
259 .token.comment,
260 .token.prolog,
261 .token.doctype,
262 .token.cdata {
263 color: #999988; font-style: italic;
264 }
265
266 .token.namespace {
267 opacity: .7;
268 }
269
270 .token.string,
271 .token.attr-value {
272 color: #e3116c;
273 }
274 .token.punctuation,
275 .token.operator {
276 color: #393A34; /* no highlight */
277 }
278
279 .token.entity,
280 .token.url,
281 .token.symbol,
282 .token.number,
283 .token.boolean,
284 .token.variable,
285 .token.constant,
286 .token.property,
287 .token.regex,
288 .token.inserted {
289 color: #36acaa;
290 }
291
292 .token.atrule,
293 .token.keyword,
294 .token.attr-name,
295 .language-autohotkey .token.selector {
296 color: #00a4db;
297 }
298
299 .token.function,
300 .token.deleted,
301 .language-autohotkey .token.tag {
302 color: #9a050f;
303 }
304
305 .token.tag,
306 .token.selector,
307 .language-autohotkey .token.keyword {
308 color: #00009f;
309 }
310
311 .token.important,
312 .token.function,
313 .token.bold {
314 font-weight: bold;
315 }
316
317 .token.italic {
318 font-style: italic;
319}
diff --git a/src/static/avatar-512x512.png b/static/avatar-512x512.png
index fc34eee..fc34eee 100644
--- a/src/static/avatar-512x512.png
+++ b/static/avatar-512x512.png
Binary files differ
diff --git a/src/static/avatar-64x64.png b/static/avatar-64x64.png
index 1406f46..1406f46 100644
--- a/src/static/avatar-64x64.png
+++ b/static/avatar-64x64.png
Binary files differ
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..1254dc9
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,172 @@
1* {
2 box-sizing: border-box;
3}
4
5body {
6 line-height: 150%;
7 margin-bottom: 100px;
8 font-family: serif;
9}
10
11main {
12 max-width: 760px;
13 padding: 20px 30px;
14}
15
16nav {
17 margin-bottom: 50px;
18}
19
20nav a {
21 display: inline-block;
22 margin-right: 20px;
23}
24
25h1 {
26 font-size: 280%;
27 line-height: initial;
28}
29
30h2 {
31 font-size: 200%;
32 line-height: initial;
33}
34
35h3 {
36 font-size: 160%;
37 line-height: initial;
38}
39
40img {
41 max-width: 100%;
42 margin: 30px auto;
43 display: block;
44}
45
46ul.article-list li {
47 margin-bottom: 10px;
48}
49
50ul.article-list li div {
51 display: flex;
52}
53
54ul.article-list time {
55 display: inline-block;
56 min-width: 160px;
57}
58
59article .info {
60 font-style: oblique;
61}
62
63pre {
64 overflow: auto;
65}
66
67table {
68 width: 100%;
69}
70
71table, th, td {
72 border: 1px solid black;
73 text-align: left;
74}
75
76th, td {
77 padding: 5px 10px;
78}
79
80code, pre {
81 font-size: 13px;
82}
83
84code {
85 background: rgb(255, 241, 177);
86 padding: 2px 5px;
87}
88
89pre > code {
90 background: unset;
91 padding: unset;
92}
93
94p.modified {
95 font-style: oblique;
96 font-size: 90%;
97 margin-top: 50px;
98}
99
100::selection {
101 background: #ff0;
102 color: #000;
103}
104
105::-moz-selection {
106 background: #ff0;
107 color: #000;
108}
109
110@media only screen and (max-width:480px) {
111 main {
112 padding: 20px;
113 }
114
115 nav {
116 text-align: center;
117 margin-bottom: initial;
118 }
119
120 nav a {
121 margin-bottom: 10px;
122 }
123
124 ul {
125 padding-left: 20px;
126 }
127
128 ul.article-list li {
129 margin-bottom: 20px;
130
131 }
132
133 ul.article-list li div {
134 display: block;
135 margin-top: 15px;
136 }
137
138 ul.article-list a {
139 display: block;
140 margin-top: 5px;
141 }
142
143 h1 {
144 font-size: 220%;
145 }
146
147 h2 {
148 font-size: 180%;
149 }
150
151 h3 {
152 font-size: 160%;
153 }
154}
155
156@media (prefers-color-scheme: light) {
157 body {
158 background-color: white;
159 color: black;
160 }
161}
162
163@media (prefers-color-scheme: dark) {
164 body {
165 background-color: rgb(30, 30, 30);
166 color: white;
167 }
168
169 a {
170 color: white;
171 }
172}
diff --git a/staticgen.yml b/staticgen.yml
new file mode 100644
index 0000000..447daa2
--- /dev/null
+++ b/staticgen.yml
@@ -0,0 +1,21 @@
1# folders
2content: content/
3public: public/
4templates: templates/
5static: static/
6assets: assets/
7
8# global settings
9title: Mitja Felicijan
10description: Fan of science fiction and dabbler in code
11author: Mitja Felicijan
12email: mitja.felicijan@gmail.com
13domain: https://mitjafelicijan.com
14twitter: @mitjafelicijan
15
16# use name of css file without .css extension
17# https://github.com/highlightjs/highlight.js/tree/master/src/styles
18highlightStye: github
19
20# google analytics
21ga: UA-12769079-10
diff --git a/templates/index.twig b/templates/index.twig
new file mode 100644
index 0000000..4a0eb00
--- /dev/null
+++ b/templates/index.twig
@@ -0,0 +1,56 @@
1<!DOCTYPE html>
2<html lang="en">
3
4 <head>
5
6 <meta charset="utf-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1.0">
8 <meta http-equiv="X-UA-Compatible" content="ie=edge">
9
10 <meta name="theme-color" content="#ffffff">
11 <meta name="generator" content="https://github.com/mitjafelicijan/staticgen">
12
13 <link rel="preconnect" href="https://www.google-analytics.com">
14
15 <title>{{ global.title }}</title>
16 <meta name="author" content="{{ global.author }}">
17 <meta name="description" content="{{ global.description }}">
18
19 <meta property="og:title" content="{{ global.title }}">
20 <meta property="og:description" content="{{ global.description }}">
21 <meta property="og:url" content="{{ global.domain }}">
22
23 <meta name="twitter:card" content="summary">
24 <meta name="twitter:site" content="{{ global.twitter }}">
25
26 <link rel="alternate" type="application/atom+xml" title="{{ global.author }}'s feed" href="/feed.atom">
27 <link rel="stylesheet" href="/static/style.css?v={{ "now"|date("YmdHi") }}">
28 <link rel="icon" type="image/png" href="/static/avatar-64x64.png?v={{ "now"|date("YmdHi") }}">
29
30 </head>
31
32 <body>
33
34 <main>
35
36 {% include "partials/navigation.twig" %}
37
38 <h2>Notes</h2>
39
40 <ul class="article-list">
41 {% for item in list %}
42 <li>
43 <time datetime="{{ item.date|date("Y, F j") }}">{{ item.date|date("Y, F j") }}</time>
44 <a href="{{ item.slug }}">{{ item.title }}</a>
45 </li>
46 {% endfor %}
47 </ul>
48
49 </main>
50
51 <!-- google analytics -->
52 {{ global.ga }}
53
54 </body>
55
56</html>
diff --git a/templates/page.twig b/templates/page.twig
new file mode 100644
index 0000000..128e321
--- /dev/null
+++ b/templates/page.twig
@@ -0,0 +1,52 @@
1<!DOCTYPE html>
2<html lang="en">
3
4 <head>
5
6 <meta charset="utf-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1.0">
8 <meta http-equiv="X-UA-Compatible" content="ie=edge">
9
10 <meta name="theme-color" content="#ffffff">
11 <meta name="generator" content="https://github.com/mitjafelicijan/staticgen">
12
13 <link rel="preconnect" href="https://www.google-analytics.com">
14
15 <title>{{ options.title }}</title>
16 <meta name="author" content="{{ global.author }}">
17 <meta name="description" content="{{ options.description }}">
18
19 <meta property="og:title" content="{{ options.title }}">
20 <meta property="og:description" content="{{ options.description }}">
21 <meta property="og:url" content="{{ global.domain }}{{ options.slug }}">
22
23 <meta name="twitter:card" content="summary">
24 <meta name="twitter:site" content="{{ global.twitter }}">
25
26 <link rel="alternate" type="application/atom+xml" title="{{ global.author }}'s feed" href="/feed.atom">
27 <link rel="stylesheet" href="/static/style.css?v={{ "now"|date("YmdHi") }}">
28 <link rel="icon" type="image/png" href="/static/avatar-64x64.png?v={{ "now"|date("YmdHi") }}">
29
30 </head>
31
32 <body>
33
34 <main>
35
36 {% include "partials/navigation.twig" %}
37
38 <article>
39 <header>
40 <h1>{{ options.title }}</h1>
41 </header>
42 {{ content }}
43 </article>
44
45 </main>
46
47 <!-- google analytics -->
48 {{ global.ga }}
49
50 </body>
51
52</html>
diff --git a/templates/partials/navigation.twig b/templates/partials/navigation.twig
new file mode 100644
index 0000000..cff6152
--- /dev/null
+++ b/templates/partials/navigation.twig
@@ -0,0 +1,6 @@
1<nav>
2 <a href="/">Mitja Felicijan</a>
3 <a href="/curriculum-vitae.html">CV</a>
4 <a href="https://twitter.com/mitjafelicijan" target="_blank" rel="noopener nofollow">Twitter</a>
5 <a href="https://github.com/mitjafelicijan" target="_blank" rel="noopener nofollow">Github</a>
6</nav>
diff --git a/templates/post.twig b/templates/post.twig
new file mode 100644
index 0000000..bd9fdaa
--- /dev/null
+++ b/templates/post.twig
@@ -0,0 +1,59 @@
1<!DOCTYPE html>
2<html lang="en">
3
4 <head>
5
6 <meta charset="utf-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1.0">
8 <meta http-equiv="X-UA-Compatible" content="ie=edge">
9
10 <meta name="theme-color" content="#ffffff">
11 <meta name="generator" content="https://github.com/mitjafelicijan/staticgen">
12
13 <link rel="preconnect" href="https://www.google-analytics.com">
14
15 <title>{{ options.title }}</title>
16 <meta name="author" content="{{ global.author }}">
17 <meta name="description" content="{{ options.description }}">
18
19 <meta property="og:title" content="{{ options.title }}">
20 <meta property="og:description" content="{{ options.description }}">
21 <meta property="og:url" content="{{ global.domain }}{{ options.slug }}">
22
23 <meta name="twitter:card" content="summary">
24 <meta name="twitter:site" content="{{ global.twitter }}">
25
26 <link rel="alternate" type="application/atom+xml" title="{{ global.author }}'s feed" href="/feed.atom">
27 <link rel="stylesheet" href="/static/style.css?v={{ "now"|date("YmdHi") }}">
28 <link rel="icon" type="image/png" href="/static/avatar-64x64.png?v={{ "now"|date("YmdHi") }}">
29
30 </head>
31
32 <body>
33
34 <main>
35
36 {% include "partials/navigation.twig" %}
37
38 <article>
39 <header>
40 <h1>{{ options.title }}</h1>
41 <div class="info">
42 <time datetime="{{ item.date|date("Y, F j") }}">{{ item.date|date("Y, F j") }}</time>
43 <span>by {{ global.author }}</span>
44 </div>
45 </header>
46 {{ content }}
47 </article>
48
49 </main>
50
51 <!-- code highlighting -->
52 {{ global.highlight }}
53
54 <!-- google analytics -->
55 {{ global.ga }}
56
57 </body>
58
59</html>