summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rwxr-xr-xbuild.sh3
-rw-r--r--config.toml116
-rw-r--r--content/_index.md10
-rw-r--r--content/blog/archlinux-macbook-a1211.md362
-rw-r--r--content/blog/bacula-lto4-backup.md253
-rw-r--r--content/blog/mail-disaster.md287
-rw-r--r--content/blog/no-github.md11
-rw-r--r--content/blog/openbsd-firewall-and-securityrouter.org.md2
-rw-r--r--content/blog/openbsd-firewall-appliance-intro.md8
-rw-r--r--content/blog/retro-computing-unisys.md20
-rw-r--r--content/blog/retro-computing-vintage-computer-festival-zurich-2019.md111
-rw-r--r--content/blog/retro-computing-vintage-computer-festival-zurich-2021.md87
-rw-r--r--content/blog/retro-computing-vintage-computer-festival-zurich-2022.md100
-rw-r--r--content/blog/retro-computing-vintage-computer-festival-zurich-2023.md113
-rw-r--r--content/blog/web-search-homepage.md18
-rw-r--r--content/contact/_index.md57
-rw-r--r--content/dataprotection/_index.md11
-rw-r--r--content/git/_index.md4
-rw-r--r--content/hardware/_index.md9
-rw-r--r--content/hardware/imc-2001-chargen40.md90
-rw-r--r--content/hardware/imc-2001-documentation.md18
-rw-r--r--content/hardware/imc-2001-firmware.md185
-rw-r--r--content/hardware/imc-2001-images.md20
-rw-r--r--content/hardware/imc-2001-keyboard.md58
-rw-r--r--content/hardware/imc-2001-links.md19
-rw-r--r--content/hardware/imc-2001-power.md26
-rw-r--r--content/hardware/imc-2001-status-todos.md133
-rw-r--r--content/hardware/imc-2001.md18
-rw-r--r--content/search/_index.md4
-rw-r--r--content/slide/_index.md6
-rw-r--r--content/slide/strus-webservice.md411
-rw-r--r--content/software/OpenBSD_firewall.md66
-rw-r--r--content/software/nagios_plugin_curl.md12
-rw-r--r--content/toolbox/_index.md66
-rw-r--r--search/fts5/README87
-rw-r--r--search/fts5/hugo-0.120.1-charset.patch12
-rw-r--r--static/blog/robots.txt2
-rw-r--r--static/contact/aba.pub57
-rw-r--r--static/hardware/imc-2001/chargen.rombin0 -> 2048 bytes
-rw-r--r--static/hardware/imc-2001/manual_imc_2001_2.01.pdfbin0 -> 5560212 bytes
-rw-r--r--static/images/blog/archlinux-macbook-a1211/macbook-A1211.jpgbin0 -> 142930 bytes
-rw-r--r--static/images/blog/bacula-lto4-backup/fitting.jpgbin0 -> 76296 bytes
-rw-r--r--static/images/blog/bacula-lto4-backup/lto4.jpgbin0 -> 83527 bytes
-rw-r--r--static/images/blog/mail-disaster/ibm.pngbin0 -> 26792 bytes
-rw-r--r--static/images/blog/mail-disaster/mail-disaster.pngbin0 -> 21834 bytes
-rw-r--r--static/images/blog/mail-disaster/zy0_de.pngbin0 -> 45099 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-Apple-2.jpgbin0 -> 125881 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-FS4.jpgbin0 -> 136549 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-IBM-5155.jpgbin0 -> 139482 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDF-11.jpgbin0 -> 112527 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDP-11.jpgbin0 -> 112527 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-apple-games-book.jpgbin0 -> 154623 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019.jpgbin0 -> 139482 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-BK-0010-01.jpgbin0 -> 124284 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-agat.jpgbin0 -> 114318 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-ceres3.jpgbin0 -> 107014 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-oberon-books.jpgbin0 -> 123308 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-olpc-xo-1.jpgbin0 -> 184679 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-tektronix-4010.jpgbin0 -> 83653 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021.jpgbin0 -> 126546 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-cpm-machines.jpgbin0 -> 246340 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-electronics-teaching.jpgbin0 -> 149902 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-front.jpgbin0 -> 123033 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-harddisk.jpgbin0 -> 169120 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-self-made.jpgbin0 -> 170874 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-smaky-100.jpgbin0 -> 144148 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-acorns.jpgbin0 -> 309911 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-ibm-convertible.jpgbin0 -> 129039 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-olpcs.jpgbin0 -> 119875 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-others.jpgbin0 -> 221100 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-portables.jpgbin0 -> 284953 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpgbin0 -> 124687 bytes
-rw-r--r--static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-selnau1.jpgbin0 -> 317388 bytes
-rw-r--r--static/images/github.svg1
-rw-r--r--static/images/hardware/imc-2001/chargen.pngbin0 -> 3209 bytes
-rw-r--r--static/images/hardware/imc-2001/computer_full.jpgbin0 -> 436722 bytes
-rw-r--r--static/images/hardware/imc-2001/cpm/README1
-rw-r--r--static/images/hardware/imc-2001/cpm/README.MBASIC1
-rw-r--r--static/images/hardware/imc-2001/cpm_40chars.jpgbin0 -> 349924 bytes
-rw-r--r--static/images/hardware/imc-2001/floppies/README12
-rw-r--r--static/images/hardware/imc-2001/keyboard_cable.jpgbin0 -> 115481 bytes
-rw-r--r--static/images/hardware/imc-2001/keyboard_front.jpgbin0 -> 410833 bytes
-rw-r--r--static/images/hardware/imc-2001/keyboard_pcb_controller_prom.jpgbin0 -> 414127 bytes
-rw-r--r--static/images/hardware/imc-2001/manual_ascii_table.jpgbin0 -> 450211 bytes
-rw-r--r--static/images/hardware/imc-2001/manual_frontpage.jpgbin0 -> 32146 bytes
-rw-r--r--static/images/hardware/imc-2001/motherboard_internal.jpgbin0 -> 439776 bytes
-rw-r--r--static/images/hardware/imc-2001/new_psu.jpgbin0 -> 446105 bytes
-rw-r--r--static/images/hardware/imc-2001/old_psu.jpgbin0 -> 516917 bytes
-rw-r--r--static/images/hardware/imc-2001/oscilloscope_serial_keyboard.jpgbin0 -> 395487 bytes
-rw-r--r--static/images/hardware/imc-2001/romboard.jpgbin0 -> 1342367 bytes
-rw-r--r--static/images/twitter.svg1
-rw-r--r--static/text/blog/archlinux-macbook-a1211/radeon_bios-5.7.6.c759
-rw-r--r--static/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c764
-rw-r--r--static/text/blog/archlinux-macbook-a1211/radeon_bios.c749
-rwxr-xr-xsync_backup.sh8
-rwxr-xr-xsync_backup_local.sh8
-rwxr-xr-xsync_ssl.sh13
-rwxr-xr-xtest.sh2
-rw-r--r--themes/new_theme/CHANGES13
-rw-r--r--themes/new_theme/assets/css/style.css1306
-rw-r--r--themes/new_theme/i18n/bg.yaml94
-rw-r--r--themes/new_theme/i18n/cs.yaml94
-rw-r--r--themes/new_theme/i18n/de.yaml94
-rw-r--r--themes/new_theme/i18n/en.yaml94
-rw-r--r--themes/new_theme/i18n/es.yaml92
-rw-r--r--themes/new_theme/i18n/fr.yaml93
-rw-r--r--themes/new_theme/i18n/hu.yaml95
-rw-r--r--themes/new_theme/i18n/it.yaml94
-rw-r--r--themes/new_theme/i18n/ja.yaml95
-rw-r--r--themes/new_theme/i18n/nl.yaml93
-rw-r--r--themes/new_theme/i18n/pt-br.yaml93
-rw-r--r--themes/new_theme/i18n/pt.yaml93
-rw-r--r--themes/new_theme/i18n/ru.yaml95
-rw-r--r--themes/new_theme/i18n/vi.yaml93
-rw-r--r--themes/new_theme/i18n/zh-cn.yaml92
-rw-r--r--themes/new_theme/i18n/zh-tw.yaml93
-rw-r--r--themes/new_theme/images/screenshot.pngbin0 -> 58734 bytes
-rw-r--r--themes/new_theme/images/tn.pngbin0 -> 51105 bytes
-rw-r--r--themes/new_theme/layouts/404.html23
-rw-r--r--themes/new_theme/layouts/_default/baseof.html58
-rw-r--r--themes/new_theme/layouts/_default/list.html85
-rw-r--r--themes/new_theme/layouts/_default/single.html66
-rw-r--r--themes/new_theme/layouts/_default/summary.html32
-rw-r--r--themes/new_theme/layouts/index.html68
-rw-r--r--themes/new_theme/layouts/partials/authorbox.html21
-rw-r--r--themes/new_theme/layouts/partials/comments.html5
-rw-r--r--themes/new_theme/layouts/partials/footer.html23
-rw-r--r--themes/new_theme/layouts/partials/footer_links.html8
-rw-r--r--themes/new_theme/layouts/partials/header.html36
-rw-r--r--themes/new_theme/layouts/partials/header_slide.html2
-rw-r--r--themes/new_theme/layouts/partials/logo.html24
-rw-r--r--themes/new_theme/layouts/partials/mathjax.html3
-rw-r--r--themes/new_theme/layouts/partials/menu.html23
-rw-r--r--themes/new_theme/layouts/partials/pager.html22
-rw-r--r--themes/new_theme/layouts/partials/pagination.html14
-rw-r--r--themes/new_theme/layouts/partials/post_meta.html7
-rw-r--r--themes/new_theme/layouts/partials/post_meta/author.html6
-rw-r--r--themes/new_theme/layouts/partials/post_meta/categories.html16
-rw-r--r--themes/new_theme/layouts/partials/post_meta/date.html13
-rw-r--r--themes/new_theme/layouts/partials/post_meta/translations.html10
-rw-r--r--themes/new_theme/layouts/partials/post_tags.html10
-rw-r--r--themes/new_theme/layouts/partials/post_toc.html8
-rw-r--r--themes/new_theme/layouts/partials/ranklist_elasticlunr.html (renamed from themes/new_theme/layouts/partials/ranklist.html)0
-rw-r--r--themes/new_theme/layouts/partials/ranklist_fts5.html152
-rw-r--r--themes/new_theme/layouts/partials/sidebar.html30
-rw-r--r--themes/new_theme/layouts/partials/svg/author.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/bitbucket.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/category.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/email.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/facebook.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/files.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/github.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/gitlab.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/instagram.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/linkedin.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/tag.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/telegram.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/time.svg1
-rw-r--r--themes/new_theme/layouts/partials/svg/twitter.svg1
-rw-r--r--themes/new_theme/layouts/partials/widgets/categories.html17
-rw-r--r--themes/new_theme/layouts/partials/widgets/elasticlunr_search.html9
-rw-r--r--themes/new_theme/layouts/partials/widgets/fts5_search.html21
-rw-r--r--themes/new_theme/layouts/partials/widgets/languages.html20
-rw-r--r--themes/new_theme/layouts/partials/widgets/recent.html9
-rw-r--r--themes/new_theme/layouts/partials/widgets/search.html9
-rw-r--r--themes/new_theme/layouts/partials/widgets/sidemenu.html14
-rw-r--r--themes/new_theme/layouts/partials/widgets/social.html90
-rw-r--r--themes/new_theme/layouts/partials/widgets/taglist.html17
-rw-r--r--themes/new_theme/layouts/robots.txt4
-rw-r--r--themes/new_theme/layouts/slide/single.html2
-rw-r--r--themes/new_theme/static/apple-touch-icon.pngbin0 -> 111 bytes
-rw-r--r--themes/new_theme/static/favicon.icobin0 -> 1350 bytes
-rw-r--r--themes/new_theme/static/img/avatar.pngbin0 -> 1139 bytes
-rw-r--r--themes/new_theme/static/img/placeholder.pngbin0 -> 4711 bytes
-rw-r--r--themes/new_theme/static/js/menu.js25
-rw-r--r--themes/new_theme/static/js/require.js5
-rw-r--r--themes/new_theme/static/js/sql-wasm.js203
-rw-r--r--themes/new_theme/static/js/sql-wasm.wasmbin0 -> 1213472 bytes
-rw-r--r--themes/new_theme/static/slide/css/theme/beige.css2
-rw-r--r--themes/new_theme/static/slide/css/theme/blood.css2
-rw-r--r--themes/new_theme/static/slide/css/theme/league.css2
-rw-r--r--themes/new_theme/static/slide/css/theme/moon.css2
-rw-r--r--themes/new_theme/static/slide/css/theme/night.css4
-rw-r--r--themes/new_theme/static/slide/css/theme/simple.css4
-rw-r--r--themes/new_theme/static/slide/css/theme/sky.css4
-rw-r--r--themes/new_theme/static/slide/css/theme/solarized.css2
-rw-r--r--themes/new_theme/static/slide/css/theme/source/beige.scss2
-rw-r--r--themes/new_theme/static/slide/css/theme/source/blood.scss2
-rw-r--r--themes/new_theme/static/slide/css/theme/source/league.scss2
-rw-r--r--themes/new_theme/static/slide/css/theme/source/moon.scss2
-rw-r--r--themes/new_theme/static/slide/css/theme/source/night.scss4
-rw-r--r--themes/new_theme/static/slide/css/theme/source/simple.scss4
-rw-r--r--themes/new_theme/static/slide/css/theme/source/sky.scss4
-rw-r--r--themes/new_theme/static/slide/css/theme/source/solarized.scss2
-rw-r--r--themes/new_theme/theme.toml14
196 files changed, 8833 insertions, 457 deletions
diff --git a/.gitignore b/.gitignore
index 81e1aed..aab4f21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ public/luceneanalyzer
.gitkeep
static/minilinux
static/luceneanalyzer
+ssl-public
diff --git a/build.sh b/build.sh
index d60d54b..93f33b2 100755
--- a/build.sh
+++ b/build.sh
@@ -9,6 +9,7 @@ fi
TEST_URL=`grep strus_url config.toml | cut -f 2 -d '"'`
rm -rf public
-hugo -v -b http://www.andreasbaumann.cc
+hugo -v -b http://www.andreasbaumann.cc/
$SED -i "s@$TEST_URL@http://www.andreasbaumann.cc/strus/query/wwwandreasbaumanncc@g" \
public/search/index.html
+cp themes/new_theme/layouts/robots.txt public/.
diff --git a/config.toml b/config.toml
index 7e7976a..9d1d0c5 100644
--- a/config.toml
+++ b/config.toml
@@ -1,79 +1,115 @@
baseURL = "http://www.andreasbaumann.cc/"
languageCode = "en-us"
title = "Andreas Baumann's Personal Home Page"
+paginate = "10" # Number of posts per page
theme = "new_theme"
disableRss = true
-enableRobotsTXT = true
-SectionPagesMenu = "main"
+disqusShortname = "" # Enable comments by entering your Disqus shortname
+googleAnalytics = "" # Enable Google Analytics by entering your tracking id
[Params]
- author = "Andreas Baumann"
+ # author = "Andreas Baumann"
description = "Andreas Baumann's Personal Home Page"
toptitle = "Andreas Baumann's"
subtitle = "Personal Home Page"
location = "Zurich"
- copyright_years = "2009 - 2018"
+ copyright_years = "2009 - 2023"
opengraph = true
+ authorbox = false # Show "Read more" button in list if true
+ twitter_cards = false
strus_url = "http://eeepc.home:8080/strus/query/wwwandreasbaumanncc"
+ pager = true
+ post_meta = ["date", "categories"] # Order of post meta information
+ mathjax = false
+ customCSS = [ "css/localstyle.css" ]
+ # customJS = [ "/js/jquery.js" ] # doesn't work, added directly to baseof.html
+[Params.logo]
+ subtitle = "Personal Home Page" # Logo subtitle
+
[Params.widgets]
search = true
recent_articles = true
categories = true
tags = true
+ recent_num = 5 # Set the number of articles in the "Recent articles" widget
+ tags_counter = false # Enable counter for each tag in "Tags" widget (disabled by default)
+
+[Params.sidebar]
+ home = "right" # Configure layout for home page
+ list = "right" # Configure layout for list pages
+ single = "right" # Configure layout for single pages
+ # Enable widgets in given order
+ widgets = ["dataprotection", "fts5_search", "recent", "categories"]
[taxonomies]
-category = "categories"
+ category = "categories"
+
+[[menu.main]]
+ name = "Home"
+ weight = 30
+ identifier = "home"
+ url = "/"
[[menu.main]]
- name = "Home"
- weight = 30
- identifier = "home"
- url = "/"
+ name = "Software"
+ weight = 40
+ identifier = "software"
+ url = "/software"
[[menu.main]]
- name = "Software"
- weight = 40
- identifier = "software"
- url = "/software"
+ name = "Hardware"
+ weight = 50
+ identifier = "hardware"
+ url = "/hardware"
[[menu.main]]
- name = "Toolbox"
- weight = 50
- identifier = "toolbox"
- url = "/toolbox"
+ name = "Toolbox"
+ weight = 60
+ identifier = "toolbox"
+ url = "/toolbox"
[[menu.main]]
- name = "Git"
- weight = 60
- identifier = "git"
- url = "/git"
+ name = "Git"
+ weight = 70
+ identifier = "git"
+ url = "/git"
[[menu.main]]
- name = "Slides"
- weight = 70
- identifier = "slide"
- url = "/slide"
+ name = "Slides"
+ weight = 80
+ identifier = "slide"
+ url = "/slide"
[[menu.main]]
- name = "Blog"
- weight = 80
- identifier = "blog"
- url = "/blog"
+ name = "Blog"
+ weight = 90
+ identifier = "blog"
+ url = "/blog"
[[menu.main]]
- name = "Search"
- weight = 90
- identifier = "search"
- url = "/search"
+ name = "Search"
+ weight = 100
+ identifier = "search"
+ url = "/search"
[[menu.main]]
- name = "Contact"
- weight = 100
- identifier = "contact"
- url = "/contact"
+ name = "Contact"
+ weight = 110
+ identifier = "contact"
+ url = "/contact"
[outputs]
- home = [ "HTML", "JSON"]
- page = [ "HTML"]
-
+ home = [ "HTML", "JSON"]
+ page = [ "HTML"]
+
+[sitemap]
+ changefreq = "monthly"
+ filename = "sitemap.xml"
+ priority = 0.5
+
+[mediaTypes.'application/wasm']
+ suffixes = [ 'wasm' ]
+
+[mediaTypes.'application/octet-stream']
+ suffixes = [ 'db' ]
diff --git a/content/_index.md b/content/_index.md
index da5657c..2d1a90e 100644
--- a/content/_index.md
+++ b/content/_index.md
@@ -2,6 +2,11 @@
title = "Andreas Baumann's Personal Home Page"
+++
+You reached my personal web page and blog. I post on technologies, projects
+and ideas currently on my mind.
+
+## Technical Technicalities
+
Using a static HTML generator now called [Hugo](https://gohugo.io/).
Before I used HTML and server-side-includes.
Synchronization is done with rsync over ssh.
@@ -10,7 +15,8 @@ the two wikis/CMS I had before (I don't mention names) were hacked in
no time. And don't want to spend any time doing security updates all
the time.
-Hosting is done on a Raspberry Pi 1 B+ with [ArchARM](https://archlinuxarm.org/).
+Hosting is done on a Raspberry Pi 1 B+ (as of 20th of July 2019 it has
+been upgraded to a Raspberry Pi 2 Model B) with [ArchARM](https://archlinuxarm.org/).
I was simply fed up with the speed and the cumbersome user interface of
nowadays virtualized web hosting solutions (I don't mention names here again).
@@ -22,3 +28,5 @@ my personal domain.
![Alix and Raspberry Pi for hosting](images/alix_rpi.jpg "Alix and Raspberry Pi for hosting")
..and yes, the table is dirty.. :-)
+
+## Blog articles
diff --git a/content/blog/archlinux-macbook-a1211.md b/content/blog/archlinux-macbook-a1211.md
new file mode 100644
index 0000000..3df776a
--- /dev/null
+++ b/content/blog/archlinux-macbook-a1211.md
@@ -0,0 +1,362 @@
++++
+title = "Archlinux on a MacBook Pro 15'' Model A1211"
+categories = [ "Operating System", "Archlinux", "MacBook" ]
+date = "2018-11-12T16:55:39+01:00"
+thumbnail = "/images/blog/archlinux-macbook-a1211/macbook-A1211.jpg"
++++
+
+## History
+
+I got an old Mac from a collegue at work. Apple decided not to
+support those devices anymore, anyway, they date back to 2006.
+I think, it's a pitty, because this Mac has a solid case, a pretty fast
+64-bit processor (sorry Archlinux32, no test machine for you) and
+a graphic chip which is not melting away like in later models
+(I don't name brand names here)..
+
+Here the specifications:
+
+* 2.3 GHz Intel Core 2 Duo
+* 2GB 667 DDR2 SDRAM
+* OSX 10.6.8
+* ATI Radeon X1600 256 MB RAM, 1440x900, 32 bit
+
+I didn't try any Sierra OS X hacks (or installing a Capitan, rumours are,
+it works even on such an old laptop) on old hardware and besides,
+Archlinux is a better choice for a developer on a Mac. Although
+there are still MacPorts for OS X 10.6.x (no Brew though), it can be
+quite painful to get something compiled on a Mac OS that old.
+
+As we will see later, we want to keep OS X around to be able to
+change some settings, extract some firmware, etc.
+
+## Installation
+
+### Prepare for dual installation
+
+We have a whooping 120 GB hard disk space, so I shrank the OS X partition to 64 GB.
+This can be done in the *Disk Utility.app*, just leave EFI in peace, set OSX to
+64 GB and assign the rest of the hard disk as free space.
+
+Prepare the USB stick for installation, I had no luck with the standard ISO,
+but a hand-crafted USB-stick worked:
+
+```
+hdiutil convert -format UDRW -o archlinux-2018.09.01-x86_64.img archlinux-2018.09.01-x86_64.iso
+dd if=archlinux-2018.09.01-x86_64.dmg of=/dev/disk2 bs=1m
+```
+
+### EFI boot
+
+I used [ReFIT for MAC](http://refit.sourceforge.net/) to improve the
+somewhat limited EFI environment of an early Mac (don't get me wrong, it's
+pretty impressive that such an old machine already had EFI, but nowadays this
+EFI shows its age).
+
+The firmware is a 32-bit EFI without a proper command line mode,
+causing trouble all along. I didn't take ReFind as I didn't expect the
+32-bit EFI to be currently supported, especially as I see Tianocore
+failing to build with more modern 32-bit binutils and gcc.
+
+I installed a 32-bit GRUB onto the EFI partition as a second boot option
+along to OSX. This one then boots ArchLinux. This is easier than trying
+to load a 64-bit kernel with kernel EFI stub support from an 32-bit
+EFI environemnt with systemd-boot.
+
+### ATI VESA BIOS
+
+I didn't want to boot into legacy mode to make the VGA BIOS visible, so
+I got a nice problem during KMS switching during early boot: the
+graphical output just froze. The irony here is that modern Linux and Xorg
+don't care at all about the old VGA/VESA BIOS, but they do so for KMS,
+where the kernel has to rely on 16-bit firmware functions in the video
+BIOS to program the video chip for graphics mode.
+
+All I got was the following kernel and Xorg error messages:
+
+```
+[2.052705] [drm] initializing kernel modesetting (RV530 0x1002:0x71C5 0x106B:0x0080 0x00).
+[2.052742] radeon 0000:01:00.0: Invalid PCI ROM header signature: expecting 0xaa55, got 0xa1a1
+[2.052817] [drm:radeon_get_bios [radeon]] *ERROR* Unable to locate a BIOS ROM
+[2.052825] radeon 0000:01:00.0: Fatal error during GPU init
+[2.053037] radeon: probe of 0000:01:00.0 failed with error -22
+...
+[31.041] (EE) open /dev/dri/card0: No such file or directory
+```
+
+So this basically translates to: "I don't have a direct rendering interface,
+because there is no video card, because there is no BIOS for that card".
+
+The key idea was to extract the VESA BIOS on a distribution which handles
+the KMS switching correctly (in my case an old Ubuntu 10).
+
+```
+dd if=/dev/mem of=vbios.bin bs=65536 skip=12 count=1
+```
+
+Verify that you actually got the right firmware. There is an error message
+when booting the kernel saying:
+
+```
+[2.052742] radeon 0000:01:00.0: Invalid PCI ROM header signature: expecting 0xaa55, got 0xa1a1
+```
+
+so we expect to find that signature at the beginning of the *vbios.bin* file:
+
+```
+hexdump -C vbios.bin | head -n 1
+00000000 55 aa 7d e9 7f 02 00 00 00 00 00 00 00 00 00 00 |U.}.............|
+```
+
+This firmware comes into */lib/firmware/radeon/vbios.bin* to be available during
+boot.
+
+The next problem was that the radeon module in the Linux kernel doesn't
+know about this firmware. There is a patch in https://bugs.freedesktop.org/show_bug.cgi?id=26891
+for older kernels, but it translates easily to the latest kernel. All
+it does is to load the *vbios.bin* file from the right place, when all the other
+options fail.
+
+My version of the module is [here](/text/blog/archlinux-macbook-a1211/radeon_bios.c), check
+out function *radeon_read_bios_from_firmware* and the code calling that function.
+
+
+In order to use the Radeon driver for KMS as early as possible,
+I put it into the init-RAM-disk:
+
+So, I added to */etc/mkinitcpio.conf* and rebuilt the ram disks:
+
+```
+MODULES=(radeon)
+FILES=(/usr/lib/firmware/radeon/vbios.bin)
+```
+
+### "Total Darkness" after 10 minutes
+
+Everything was running smoothly.. for about 10 minutes. Then my LCD display
+just went pitch black.
+
+Setting the brightness manually didn't help:
+
+```
+xrandr --output LVDS --brightness 1
+```
+
+(it did work later though to set the brightness between 0.0 and 1.0)
+
+The trick is to tell the radeon module to handle the LCD backlight, not
+one of the Apple brightness modules. In */etc/modprobe.d/radeon.conf* put:
+
+```
+options radeon backlight=1
+```
+
+Also handy is the https://aur.archlinux.org/packages/brightd/, though
+I think also systemd-backlight can nowadays at least save the brightness
+across reboots and suspends.
+
+### Function keys or special keys
+
+If you don't need the special keys for controlling the volume and brightness but instead the old
+Fxx function keys, add the following to */etc/modprobe.d/hid_apple.conf*:
+
+```
+options hid_apple fnmode=2
+```
+
+### Camera
+
+Here we come to iSight and why we need OS X around to extract the proper
+firmware.
+
+https://wiki.archlinux.org/index.php/Mac#Webcam has a really nice walkthrough.
+
+Shortly, you need https://aur.archlinux.org/packages/hfsprogs/ to mount the HFS
+partition. There you will find a file called *AppleUSBVideoSupport* in
+*/System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBVideoSupport.kext/Contents/MacOS*.
+
+You will also need https://aur.archlinux.org/packages/isight-firmware-tools/.
+It contains tools to extract the file containg the firmware called *isight.fw*
+from *AppleUSBVideoSupport*.
+
+Finally it contains an udev rule in */etc/udev/rules.d/isight.rules* which then makes
+sure the firmware is also loaded on startup during detection of the camera via udev.
+
+### Wifi
+
+The wireless card was supported without any problems. Just some channels
+were not visible.
+
+Install *wireless-regdb* and make sure to enable the proper regulatory domain in
+*/etc/conf.d/wireless-regdom*:
+
+```
+WIRELESS_REGDOM="CH"
+```
+
+The regulatory domain has to be set properly, put it into */etc/modprobe.d/regdom.conf*:
+
+```
+options cfg80211 ieee80211_regdom=CH
+```
+
+(CH is for Switzerland, pick your own country here)
+
+Note: I think my method is deprecated and you can also specify the
+regulatory domain directly in wpa_supplicant.conf, but then how
+to use systemd-networkd with that?
+
+### Fans and sensors
+
+[macfanctl](https://aur.archlinux.org/packages/macfanctld/) from the AUR works nicely,
+also lm_sensors had no problems to get the sensor data.
+
+### Power consumption
+
+cpupower seems to work fine. Just make sure the 'p4-clockmod' module is loaded
+at boot.
+
+Note: I didn't try powertop or other tweaks. I got some worriesome ticking
+noises of the hard disk after a suspend and my battery is not that powerful
+anyway, so I'll run mostly on net power.
+
+### Mouse buttons
+
+Managers might like to use only one mouse button. Also keyboard fanatics may
+be happy by just switching off the mousepad completly.
+
+The one button mouse is a disaster for people being used to Xorg copy-
+paste or Oberon enthusiasts used to three mouse buttons.
+
+Scrolling with two fingers is nice, but per default they are enabled only for up and down.
+I enabled also scrolling to the left and right. Besides, the keyboard is missing
+PageUp, PageDown keys, which is a usability nightmare when you want to
+scroll bigger source code files or web pages (yes, I know there is Fn-Page,
+but having Ctrl, Alt, Meta and Fn all on the same spot doesn't make it
+easier to find the right one).
+
+Side note: I'm using *Fn* for keyboard scrolling (PgUp, PgDown), *Ctrl* for Wordstar short-cuts, "Alt" for
+Notion (window manager) shortcuts, and they are really _CLOSE_ together..
+
+Change */etc/X11/xorg.conf.d/50-synaptics.conf* as follows to your likings:
+```
+Section "InputClass"
+ Identifier "Touchpad Catchall"
+ Driver "synaptics"
+ MatchIsTouchpad "on"
+ Option "TapButton1" "0"
+ Option "TapButton2" "3"
+ Option "TapButton3" "2"
+ Option "VertTwoFingerScroll" "1"
+ Option "HorizTwoFingerScroll" "1"
+ Option "ClickFinger2" = 0
+ Option "ClickFinger3" = 0
+EndSection
+```
+
+*TabButton1=1* only leads to all kind of frantic behaviour, because I
+touch the touchpad by accident too often. *ClickButton* and *TapButton*
+for the second and third button are just completly useless. Either no menu
+appears for TapButton or a menu appears for ClickFinger, but I can no
+longer do copy-pastes.
+
+The default modifiers Ctrl, Alt, Meta don't do anything with the mouse
+or just very weird stuff, like Alt-2-fingers jumps to the beginning of
+my text.
+
+For now, I choose TapButtons for copy-paste, as this is the function
+I need most often.
+
+I might add some Ctrl, Meta modifiers to get 2, 3 mouse button clicks later.
+
+## Philosophical Outro
+
+In a world where companies try hard to get people into their ecosystem (controlling
+what users can do with the products they bought and own, what they can repair or let repair, what kind
+of operating system and software they are supposed to use), I think, it's the
+duty of any tech professional to invest some time to give old hardware back some
+purpose (hence I'm also working on the Archlinux32 project). Also, throwing
+away barely used machines, just because a company wants to earn billions, is an
+ecological disaster. Remember, companies have been invented to make money, don't
+get fooled by "we are there to make the world a better place" or any other marketing bs.
+As the company which should not be named is quite good at this kind of business, I
+expect all major vendors to follow soon. So that's why I keep a park of old machines
+around and I'm not buying new machines since 10 years (I do buy old ones from Ebay though).
+
+## References
+
+* https://everymac.com/systems/apple/macbook_pro/specs/macbook-pro-core-2-duo-2.33-15-specs.html :
+ specifications of the A1211 model
+* [https://bugs.freedesktop.org/show_bug.cgi?id=26891](https://bugs.freedesktop.org/show_bug.cgi?id=26891): the patch to radeon.ko,
+ enabling loading of file as VESA bios
+* [https://bbs.archlinux.org/viewtopic.php?id=139511](https://bbs.archlinux.org/viewtopic.php?id=139511): some discussions about
+ the VESA radeon topic in the Archlinux forum.
+* https://wiki.archlinux.org/index.php/Mac#Webcam: how to make the camera work
+
+## Addendum 19.2.2021
+
+For kernel 5.7.6 updated version [here](/text/blog/archlinux-macbook-a1211/radeon_bios-5.7.6.c) .
+
+Also a small walkthrough on how to update the module (in a most likely not too official way):
+
+```
+wget https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.7.6.tar.xz
+tar xf linux-5.7.6.tar.xz
+cd linux-5.7.6
+make mrproper
+# use the the configuration of the new kernel!
+zcat /proc/config.gz > .config
+sed -i 's/.*CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION="-arch1-1"/g' .config
+sed -i 's/.*CONFIG_LOCALVERSION_AUTO.*/# CONFIG_LOCALVERSION_AUTO is not set/g' .config
+make oldconfig
+make scripts prepare modules_prepare
+# copy radeon_bios.c to drivers/gpu/drm/radeon
+make -C . M=drivers/gpu/drm/radeon
+rm -f /lib/modules/5.7.6-arch1-1/kernel/drivers/gpu/drm/radeon/radeon.ko.xz
+xz -c drivers/gpu/drm/radeon/radeon.ko \
+ > /lib/modules/5.7.6-arch1-1/kernel/drivers/gpu/drm/radeon/radeon.ko.xz
+depmod -av
+mkinitcpio -P
+cp /boot/initramfs-linux.img /mnt/efi/.
+cp /boot/initramfs-linux-fallback.img /mnt/efi/.
+
+# Archlinux kernel compilation
+https://wiki.archlinux.org/index.php/Kernel/Traditional_compilation#Download_the_kernel_source
+# build just one module
+https://yoursunny.com/t/2018/one-kernel-module/
+```
+
+Where /mnt/efi is the VFAT rEFIt EFI partition which contains grub and the kernel
+image and RAM disk.
+
+## Addendum 18.6.2023
+
+For kernel 6.3.8 updated version [here](/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c) .
+
+## Addendum 22.10.2023
+
+Tried a kernel 6.5.8 (still working with the 6.3.8 version of the radeon_bios patch avaiable
+[here](/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c)).
+
+Here is also another way to build the kernel and the patched radeon module:
+
+```
+mount /mnt/efi (before updating the kernel!)
+pacman -Syyu
+cp /boot/vmlinuz-linux /mnt/efi/vmlinuz-linux
+cp /boot/initramfs-linux.img /mnt/efi/initramfs-linux.img
+cp /boot/initramfs-linux-fallback.img /mnt/efi/initramfs-linux-fallback.img
+
+pkgctl repo clone linux
+cd linux
+makepkg -do
+cp ~/radeon_bios-6.3.8.c src/linux-6.5.8/drivers/gpu/drm/radeon/radeon_bios.c
+makepkg -s
+
+cp pkg/linux/usr/lib/modules/6.5.8-arch1-1/kernel/drivers/gpu/drm/radeon/radeon.ko.zst \
+ /lib/modules/6.5.8-arch1-1/kernel/drivers/gpu/drm/radeon/radeon.ko.zst
+depmod -av
+mkinitcpio -P
+cp /boot/initramfs-linux.img /mnt/efi/initramfs-linux.img
+cp /boot/initramfs-linux-fallback.img /mnt/efi/initramfs-linux-fallback.img
+```
diff --git a/content/blog/bacula-lto4-backup.md b/content/blog/bacula-lto4-backup.md
new file mode 100644
index 0000000..6a91978
--- /dev/null
+++ b/content/blog/bacula-lto4-backup.md
@@ -0,0 +1,253 @@
++++
+date = "2021-08-04T12:10:05+01:00"
+description = ""
+title = "LTO-4 Backup with Bacula"
+categories = [ "Backup", "Bacula", "Tape", "LTO-4" ]
+thumbnail = "/images/blog/bacula-lto4-backup/lto4.jpg"
++++
+
+## Intro
+
+With Archlinux32 reaching some terabytes of data to backup I needed
+something "modern", like a tape. Now, big tapes like LTO-8 are close
+to unaffordable, LTO-4 drives and tapes on the other hand can be
+aqcuired on the cheap. They get thrown out of servers rooms at the moment.
+
+An LTO-4 tape can take 800 GB uncompressed data and the drive can be bought
+on Ebay for 200 to 300 CHF. Media is affordable at ca. 40 CHF per tape.
+
+# Tape Drive
+
+My first drive I ordered was advertised as working, which proved to
+be more the kind of drive only able to produce squealing noises and
+to be really hungry for tapes (and killing them). Well, my plan was
+to be under 1000 CHF for a backup solution, so I simply ordered a
+second one, keeping the first one for spare parts. Both drives are a
+HP Ultrium 1840.
+
+The second drive turned out to work just fine. But now, trying to connect, it
+showed some issues. The tape drive comes in a noisy black box, which
+I definitely don't want to run 24 hours a day. So I decided to remove
+the drive and squeeze it (quite literaly) into a machine.
+
+# Tape Media
+
+After ordering quite the wrong tape (LTO-4 WORM, which costs more and
+can be written only once, but has "smartness" built in to be tamperfree,
+oh well), I got boxes and boxes of old tapes from Ricardo from somebody
+desperately trying to get rid of them. Which is cool with me. The
+price per tape dropped to around 20 CHF this way and I have more tapes
+than I could ever have wished for.
+
+# Connectivity Issues
+
+I tried several SCSI cards to connect to the drive. The drive uses
+the last generation of parallel SCSI, which is quite a nuisance to
+find cards for. Either SCSI cards are server-grade (PCI-X) or they
+are not fast enough. Some cards (like dedicated backup SCA host
+adapters) work fine in some machines, but not in others. The SCSI
+cables are prone to transmition errors, especially a 4 meter long
+external SCSI cable with 320 MHz (external or internal 68-pin LVDS)
+is somehow not really reliable at this high speed.
+
+I went with a short shielded internal SCSI cable and putting the drive
+as close to the SCA host adapter as possible. This provided the best
+results.
+
+The result looks like this:
+
+{{< figure src="/images/blog/bacula-lto4-backup/fitting.jpg" alt="LTO-4 drive fitting the machine" >}}
+
+# Manual Backups and Tools
+
+## tar
+
+Most people nowadays don't know anymore what the 't' in 'tar' stands
+for - you guessed it: '***t***ape ***ar***chive'. :-)
+
+There are other formats but usually the "rule-of-least-surprise" applies
+here, the simpler the command line parameters used and the more widespread
+the format, the more likely somebody else (or even you yourself) is able
+to actually read and restore the data.
+
+## mt
+
+The old magnetic tape tool is no longer available as binary package
+on Archlinux, but there is an AUR package 'mt-st-git' providing the
+'mt-st' binary.
+
+This tool you need to do basic operations on the tape like positioning,
+ejecting, setting compression levels, etc.
+
+## Some use cases
+
+### Rewind and eject
+
+```
+mt-st -f /dev/nst0 rewoffl
+```
+
+### Erasing tapes
+
+```
+mt-st -f /dev/nst0 defcompression 0
+mt-st -f /dev/nst0 compression 0
+mt-st -f /dev/nst0 rewind
+tar -cvf /dev/nst0 /dev/null
+mt-st -f /dev/nst0 rewind
+```
+
+***Note***
+
+I'm disabling compression on the tapes for several reasons:
+* with compression on I'm not able to deliver enough data, resuling in shoe-shining
+* the remaining size of a tape is so much more predictable
+* I have enough tapes anyway. :-)
+
+### Append to end of data
+
+```
+mt-st -f /dev/nst0 eom
+tar zcvf /dev/nst0 *
+```
+
+### Status of the drive, current position of the tape
+
+```
+mt-st -f /dev/nst0 status
+```
+
+## sg_logs
+
+This tool can give you all kind of internal information like
+temperature, I/O errors of the drive, media information.
+
+The first page of information serves as sort of an index, of
+what the drive can report:
+
+```
+shell> sg_logs /dev/nst0 -p 0
+
+ HP Ultrium 4-SCSI B32D
+Supported log pages [0x0]:
+ 0x00 Supported log pages [sp]
+ 0x02 Write error [we]
+ 0x03 Read error [re]
+ 0x0c Sequential access device [sad]
+ 0x0d Temperature [temp]
+ 0x11 DT Device status [dtds]
+ 0x12 Tape alert response [tar]
+ 0x13 Requested recovery [rr]
+ 0x18 Protocol specific port [psp]
+ 0x2e Tape alert [ta]
+ 0x30 Tape usage (lto-5, 6) [tu_]
+ 0x31 Tape capacity (lto-5, 6) [tc_]
+ 0x32 Data compression (lto-5) [dc_]
+ 0x33 Write errors (lto-5) [we_]
+ 0x34 Read forward errors (lto-5) [rfe_]
+ 0x35 DT Device Error (lto-5, 6) [dtde_]
+ 0x3e Device Status (lto-5, 6) [ds_]
+```
+
+For instance I can get the temperature of the drive with:
+
+```
+shell> sg_logs /dev/nst0 -p 13
+
+ HP Ultrium 4-SCSI B32D
+Temperature page [0xd]
+ Current temperature = 47 C
+ Reference temperature = <not available>
+
+```
+
+This could be meshed into a nagios check script, checking the sanity
+of the drive, but then I have to manually unmount the tape pool in
+bacula-sd before each check.
+
+## socat
+
+socat is like netcat and more. It allows to build tunnels between
+machines, so that the 'tar' command can pack files on one machine
+and send them to another machine, where the tape write command is
+attached to a listening socat.
+
+```
+# on the machine with the files to backup
+tar cvf - * | socat - TCP4:<server_with_tape>:8080
+# on the machine where the tape is
+socat TCP4-LISTEN:8080 - | dd of=/dev/nst0 bs=10240 status=progress
+```
+
+***Note***
+
+If using dd I set the blocksize manually to 20*512=10240, this seems
+to be the standard blocksize of 'tar' on Linux.
+
+## mbuffer
+
+Writting directly to the tape has some drawbacks as the tape drive
+is very fast and you cannot deliver data fast enough over a 1GBit/s
+network. So here 'mbuffer' helps to at least buffer data for some time
+and then flash it in one burst to the tape drive. This avoids the
+dreadful "shoe-shining" which not only drives you crazy (the sounds of it),
+but also reduces the lifetime of the components (or at least of the
+mechanics of the tape drive):
+
+```
+tar cvf - * | mbuffer -m 2G -P100% | \
+ socat - TCP4:<server_with_tape>:8080
+socat TCP4-LISTEN:8080 - | mbuffer -m 2G -P100% | \
+ dd of=/dev/nst0 bs=10240 status=progress
+```
+
+Buffering on either side is possible, not sure if having a buffer on both sides
+improves anything.
+
+# Use Cases
+
+## Full Backup
+
+I did a full backup of everything onto 10 tapes with the
+'tar/socat/mbuffer/dd' method.
+
+This is data which is quite stable and never changes, so I'll just keep
+it on some tapes with the write protection label on. It doesn't make
+much sense to put them into a bacula job, as the retention period is
+basically 30 years or so - or till the tape dies.
+
+The index of the tape is a simple text file, noting the kind of data,
+the size, the tape number, the file number (offset on tape) and the
+date of the backup:
+
+```
+doc 946M 1 0 17.4.2021
+Attic 13G 1 1 17.4.2021
+bilder 19G 1 2 17.4.2021
+projects 29G 1 3 18.4.2021
+ARCHIVE 16G 1 5 18.4.2021
+BACKUPS 122G 1 6 18.4.2021
+...
+music 154G 4 0 19.4.2021
+movies part1 547G 5 0 19.4.2021
+movies part2 785G 6 0 20.4.2021
+```
+
+## Bacula
+
+I use bacula for the daily incremental and full backups now for tape
+and offline cloud storage.
+
+bacula-sd just works fine and integrates with the rest of my backup system
+(the master bacula-dir is still living on an old Raspberry Pi). The only
+thing I was missing is to be able to copy a bacula job to two different
+media, one being the remote cloud storage and the other one the tape.
+Sort of a bacula 'tee' would be nice to have.
+
+# References
+
+* http://cdrtools.sourceforge.net/private/portability-of-tar-features.html:
+ on tar formats and compatibility
+* https://copyconstruct.medium.com/socat-29453e9fc8a6: blog about socat
+* https://www.commandlinefu.com/commands/view/13582/backup-to-lto-tape-with-progress-checksums-and-buffering
+* https://aur.archlinux.org/packages/mt-st-git/
diff --git a/content/blog/mail-disaster.md b/content/blog/mail-disaster.md
new file mode 100644
index 0000000..ab6d452
--- /dev/null
+++ b/content/blog/mail-disaster.md
@@ -0,0 +1,287 @@
++++
+title = "Mail Problems"
+categories = [ "Mail", "Linux", "Security" ]
+date = "2019-03-29T12:58:31+01:00"
+thumbnail = "/images/blog/mail-disaster/mail-disaster.png"
++++
+
+## History
+
+It was a beautiful day. My mailserver on the Raspberry Pi B was running
+without any issues for some time now.
+
+In the evening of March 12th I got a nice email from my external DNS
+provider:
+
+```
+The BuddyNS janitor writing. A safety notification on your BuddyNS account:
+
+ Your zones reached 60% of your account's traffic quota.
+
+Details:
+* Total traffic produced this month: 181 Thousand queries.
+* Current traffic quota: 0.3 Million queries/month.
+```
+
+Well, fine, I thought, finally somebody is checking on my web page and I
+went to sleep.
+
+Of course this was not the case: I had a weak password in one of the accounts
+of my mailserver (which allowed any legitimate Linux user to send
+emails). This caused all those DNS lookups for my domain on the
+BuddyNS DNS servers.
+
+So, my thinking went along the lines: well, some weeks ago
+I replaced the SD card, because the old one was worn out, I cannot
+remember whether I replaced all standard passwords. My suspicion got
+confirmed when I saw the following line in the my mail log:
+
+```
+From: "George"<alarm@andreasbaumann.cc>
+```
+
+Swearing big times about my own stupidity (the default password for the
+'alarm' account is - well - weak) I started cleaning up the mess.
+
+Checking my mail server logs I found that all attacks went via one single
+IP (185.228.80.18). So just blocking the firewall was the fastest way to
+fix the tousands of spam email being sent via my now defacto open mail relay.
+
+## Checking status
+
+There are various helpfull tools to check the status of your mail
+server. I picked https://mxtoolbox.com/. This is what I got:
+
+```
+ dmarc andreasbaumann.cc DNS Record not found
+ blacklist smtp.andreasbaumann.cc 127.0.0.2
+ blacklist smtp.andreasbaumann.cc Blacklisted by JUNKEMAIL
+ blacklist smtp.andreasbaumann.cc Blacklisted by NIXSPAM
+ blacklist smtp.andreasbaumann.cc Blacklisted by TRUNCATE
+ blacklist smtp.andreasbaumann.cc Blacklisted by UCEPROTECTL1
+ blacklist smtp.andreasbaumann.cc Blacklisted by WPBL
+ mx andreasbaumann.cc No DMARC Record found
+ mx andreasbaumann.cc DMARC Quarantine/Reject policy not enabled
+```
+
+I also like the results from ~~[http://zy0.de/q/83.150.2.48](http://zy0.de/q/83.150.2.48)~~:
+
+{{< figure src="/images/blog/mail-disaster/zy0_de.png" alt="zy0_de check resulst for 83.150.2.48" >}}
+
+Especially it shows you headers of SPAM mails, which are quite helpful
+to detect, what went wrong:
+
+```
+Spam samples A small selection
+
+ 12.03.2019 02:03 (Z) (date of processing)
+
+Return-Path: <alarm@andreasbaumann.cc>
+X-Original-To: cindy@SPAMTRAP.INVALID
+Received: from smtp.andreasbaumann.cc (smtp.andreasbaumann.cc [83.150.2.48])
+ by mail.ixlab.de (Spamtrap) with ESMTP
+ for <cindy@SPAMTRAP.INVALID>; Tue, 12 Mar 2019 03:03:20 +0100 (CET)
+Received: from User (unknown [185.228.80.18])
+ by smtp.andreasbaumann.cc (Postfix) with ESMTPA id 909CD77F2A;
+ Tue, 12 Mar 2019 01:22:20 +0100 (CET)
+Reply-To: <gg828579@gmail.com>
+From: "George"<alarm@andreasbaumann.cc>
+Subject: Good Day!!
+Date: Mon, 11 Mar 2019 17:22:27 -0700
+MIME-Version: 1.0
+Content-Type: text/html;
+ charset="Windows-1251"
+Content-Transfer-Encoding: 7bit
+X-Priority: 3
+X-MSMail-Priority: Normal
+X-Mailer: Microsoft Outlook Express 6.00.2600.0000
+X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
+X-NiX-Spam-Hash2: 5994f93f698c55d5b527b1da55f31611
+X-NiX-Spam-Source-IP: 83.150.2.48
+X-NiX-Spam-MX: mail.ixlab.de
+X-NiX-Spam-Listed: yes
+```
+
+## Blacklisting
+
+Mail servers can ask blacklists for bad IPs or domains and then block
+incoming mails.
+
+Most blacklists give you a home page, where they explain, how they
+manage the list. There you might also find the status of your IP or domain.
+
+There are basically three ways you can try to get off such a list:
+
+* you can fill in a form, usually describing what went wrong and how
+ you solved the problem.
+* you have to send an email with basically the same kind of information
+* you can do nothing, the delisting happens automatically
+
+Keep in mind, that humans read those messages, be polite and be open
+about what went wrong. I never had a problem getting delisted, when
+I described, what I did wrong in the past and how I will enforce better
+security in the future.
+
+Also note: you usually don't get any email or feedback. Give people time
+and they will consider the case. If they think, you deserve to send
+emails again, they will delist you from the blacklist.
+
+Find below short descriptions of what I had to do in the individual cases.
+
+### JumkMailFilter
+
+Visited the "remove from the list" for at:
+
+https://ipadmin.junkemailfilter.com/remove.php
+
+Entered my IP and some text, why I got onto the list.
+
+### DNSBL
+
+~~[http://www.dnsbl.manitu.net/remove.php?value=83.150.2.48](http://www.dnsbl.manitu.net/remove.php?value=83.150.2.48)~~
+
+I had to fill in a form and describe, what went wrong on my side and
+how I fixed the problem.
+
+### TRUNCATE
+
+http://www.gbudb.com/truncate/index.jsp
+
+Had nothing to do here, but wait:
+
+```
+"Maintenance of this list is completely automated and there are no
+provisions for the manual addition or removal of entries."
+```
+
+### UCEPROTECTL1
+
+```
+"This blacklist does not offer any form of manual request to delist.
+Your IP Address will either automatically expire from listing after
+a given timeframe, or after time expires from the last receipt of
+spam into their spamtraps from your IP Address.
+
+There is an express delisting for 89 CHF
+```
+
+For a personal domain I can wait for seven days sending out no spam.
+
+For a business domain I would most likely pay the 89 CHF. :-)
+
+### WPBL
+
+~~[http://www.wpbl.info/](http://www.wpbl.info/)~~
+
+```
+IP addresses are automatically removed with time, after
+spam stops arriving. For example, a lone spam sighting
+will only get an IP listed for 7 days. You can also
+remove an IP address using the Lookup facility at the
+top of the page. This no-questions-asked, instant removal
+facility is provided for the benefit of administrators
+who feel that the record is in error or have fixed the
+security problem that allowed spam to be sent through
+their hosts. Access to the removal facility may be
+restricted if there is any abuse of our system, including
+attempts to automate removal of multiple IPs using
+scripts. Removed records still remain in database backups.
+```
+
+Clicking on:
+
+http://www.wpbl.info/cgi-bin/remove.cgi
+
+I got:
+
+```
+Found IP address 83.150.2.48 in database, marking for removal.
+Record removed. The published list is updated hourly, so changes may not show immediately.
+```
+
+### SPAMCOP
+
+https://www.spamcop.net/w3m?action=checkblock&ip=83.150.2.48
+
+I filled in the provided form.
+
+### IBM DNS
+
+This is a nice security product called 'IBM-X-Forge-Exchange',
+so I had to log in with my IBM Id.
+
+{{< figure src="/images/blog/mail-disaster/ibm.png" alt="entries in IBM-X-Forge-Exchange" >}}
+
+I also had to describe my case to get delisted.
+
+### Gmail
+
+Now this one was tricky. Google has a not-so-great postmaster tool, hard
+to find forms to fill in and some confusing documentation.
+
+I tried here:
+
+https://glockapps.com/blog/remove-ip-address-gmail-blacklist/
+
+https://support.google.com/mail/contact/msgdelivery
+
+The postmaster tools are not a big help, really, I registered nonetheless.
+
+I got reject till March 28th, as far as I can tell the domain reputation below
+is one of the worst ones you can get and the only option is to wait some weeks
+after filling in the forms:
+
+```
+Our system has detected that this message
+is 550-5.7.1 likely suspicious due to the very low
+reputation of the sending 550-5.7.1 domain
+```
+
+## Course of Action for a better mail service
+
+I made sure, I have some security standards in place, so that
+at least faking the domain in the 'From:' field is not so simple:
+
+* [SPF](https://en.wikipedia.org/wiki/Sender_Policy_Framework): Sender Policy Framework
+* [DKIM](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail): Domain Keys Identified Mail
+* [DMARC](https://en.wikipedia.org/wiki/DMARC): Domain-based Message Authentication, Reporting and Conformance
+
+Those things don't help against a broken account on the mail server,
+as in my case, but they provide positive rating for emails being
+judged in the future, and they are simple to implement.
+
+I also added a list of accounts/emails to the postfix configuration.
+Only those accounts are allowed to send emails from the host.
+Even if this means you have to generate the entry in '/etc/passwd'
+and another one in that postfix list. This makes sure,
+no "rogue" Linux account can be abused for sending emails, when
+compromised.
+
+I added myself to the [DNSWL](https://www.dnswl.org) white list too.
+
+And of course, I deleted the 'alarm' account on the machine. :-)
+
+### Update 4.4.2019
+
+Gmail is still blocking me (or again?). So is bluewin.ch. The mess is
+not over, so I can only recommend everybody to make sure not to get
+into this situation in the first place.
+
+Added [Fail2Ban](https://www.fail2ban.org) to filter for common Postfix
+and Postfix SASL errors, like password-breach attempts via SASL. This
+works like a charm.
+
+Added [Spamassassin](https://spamassassin.apache.org/) and
+[Razor](http://razor.sourceforge.net/) to get rid of spam.
+
+### Update 15.4.2019
+
+Gmail likes us again.. :-)
+
+## References
+
+* https://mxtoolbox.com/
+* http://zy0.de/
+* https://en.wikipedia.org/wiki/Sender_Policy_Framework
+* https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
+* https://en.wikipedia.org/wiki/DMARC
diff --git a/content/blog/no-github.md b/content/blog/no-github.md
index 1d9d56d..f5641f1 100644
--- a/content/blog/no-github.md
+++ b/content/blog/no-github.md
@@ -14,3 +14,14 @@ The reasons should be obvious:
Find my software on http://git.andreasbaumann.cc/cgit/.
If you want to collaborate or supply a patch, you can contact me via email.
+
+### Update 22.2.2024
+
+I started to make exceptions to the rule above: when forking and working on existing
+projects which happen to be on Github already. Or when I push a read-only copy
+to Github from personal repos, just to increase the visibility of the project.
+
+
+Or if I want my code to be used in Copilot as example how to do good (or maybe bad)
+coding. ;-)
+
diff --git a/content/blog/openbsd-firewall-and-securityrouter.org.md b/content/blog/openbsd-firewall-and-securityrouter.org.md
index 178b827..b58a070 100644
--- a/content/blog/openbsd-firewall-and-securityrouter.org.md
+++ b/content/blog/openbsd-firewall-and-securityrouter.org.md
@@ -5,5 +5,5 @@ categories = [ "OpenBSD", "Security" ]
thumbnail = "/images/blog/openbsd-firewall-and-securityrouter/openbsd-firewall-and-securityrouter.png"
+++
-Found a really nice new router appliance based on OpenBSD 6.0, http://securityrouter.org. I’m still missing some features like a split-horizon DNS, so I will not abandon the script-based project http://github.com/andreasbaumann/OpenBSD-firewall just for now.
+Found a really nice new router appliance based on OpenBSD 6.0, http://securityrouter.org. I’m still missing some features like a split-horizon DNS, so I will not abandon the script-based project http://git.andreasbaumann.cc/cgit/OpenBSD-firewall just for now.
diff --git a/content/blog/openbsd-firewall-appliance-intro.md b/content/blog/openbsd-firewall-appliance-intro.md
index c9b73d2..31a805c 100644
--- a/content/blog/openbsd-firewall-appliance-intro.md
+++ b/content/blog/openbsd-firewall-appliance-intro.md
@@ -203,7 +203,7 @@ I would like to test more things around the following topics:
stuff it into a floppy to compact flash adapter, write the image, put
it back. This is tedious. :-)
-## Github
+## Git
The whole project can be found here:
@@ -212,10 +212,4 @@ http://git.andreasbaumann.cc/cgit/OpenBSD-firewall/
Feedback welcome. :-)
-## Note on Github
-
-There is a version on https://github.com/Eurospider/OpenBSD-firewall. This
-is the original version and I don't plan to update it anymore.
-Further development happens on my personal repo (as I'm basically the only
-one using it anyway).
diff --git a/content/blog/retro-computing-unisys.md b/content/blog/retro-computing-unisys.md
index a3f39fa..28ee60d 100644
--- a/content/blog/retro-computing-unisys.md
+++ b/content/blog/retro-computing-unisys.md
@@ -98,14 +98,25 @@ series on Youtube by Andres Ramos.
## Future plans
I want to be able to boot a modern Linux kernel and distribution on
-it. Currently I'm working on a "port" of [Archlinux32](http://www.archlinux32.org)
+it. Currently I'm working on a "port" of [Archlinux32](https://www.archlinux32.org)
to the i486 architecture using the [crosstool-ng](https://crosstool-ng.github.io/)
-toolchain (see [bootstrap32](https://github.com/archlinux32/bootstrap32)).
+toolchain (see [bootstrap32](https://git.archlinux32.org/bootstrap32)).
The installation process has to be something over iPXE, as a 1.44MB floppy
really doesn't hold a kernel 4.15.x anymore. iPXE itself will need some
patching for i486 too.
+### Update 26.11.2022
+
+Had to set up the machine again, either the SD card died or my Linux experiments
+nuked the MBR. Found [mTCP](http://www.brutman.com/mTCP/) to be a very nice
+alternative networking package, also having a FTP and HTTP server.
+
+Also the sentence about not being able to boot a modern Linux from floppy is wrong.
+In the meantime I can boot it with the
+[Archlinux32 i486 Floppy](https://git.archlinux32.org/archi486/tree/floppy), just the
+NEx000 drivers in modern kernels are currently quite misbehaving somehow.
+
## Videos and Links
* LGR: [My Smallest 486 Desktop PC: Unisys CWD-4002](https://www.youtube.com/watch?v=ddgmzmw6_qE)
@@ -135,6 +146,9 @@ patching for i486 too.
* [DOS drivers for the NE2000](http://www.georgpotthast.de/sioux/packet.htm), the NE2000.EXE package driver
* [Vibra 16 Soundblaster drivers on Vogons.org](http://www.vogonsdrivers.com/getfile.php?fileid=33&menustate=0)
+### DOS software
+* http://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/net/wget/: wget for DOS
+
### Windows 3.1 drivers
* [Cirrus Logic GD5424](http://www.vogonsdrivers.com/index.php?catid=47)
@@ -154,5 +168,5 @@ patching for i486 too.
### Other Links
-* [Index of Interesting DOS programs](http://www.opus.co.tt/dave/indexall.htm)
+* ~~[Index of Interesting DOS programs](http://www.opus.co.tt/dave/indexall.htm)~~
diff --git a/content/blog/retro-computing-vintage-computer-festival-zurich-2019.md b/content/blog/retro-computing-vintage-computer-festival-zurich-2019.md
new file mode 100644
index 0000000..98b9f28
--- /dev/null
+++ b/content/blog/retro-computing-vintage-computer-festival-zurich-2019.md
@@ -0,0 +1,111 @@
++++
+title = "Retro Computing - Vintage Computer Festival Zürich 2019"
+categories = [ "Retro Computing", "Vintage Computer Festival", "VCF" ]
+date = "2019-12-08T09:37:22+01:00"
+thumbnail = "/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019.jpg"
++++
+
+## Intro
+
+My first visit to an exhibition of old computers. It was held on
+November 30th and December 1st in Zürich in the "Rote Fabrik".
+Given my collection of not-so-old computers I wanted to see a collection
+of really old computers.
+
+## PDP-11
+
+The first thing which catched my attention was a PDP-11 emulator with
+frontend also simulating a Tektronix 4010 graphical terminal. It's
+running on a Raspberry-PI fully emulating a PDP-11 running BSD 2.11.
+I was aware of old Unix V6 or V7 versions running on emulators, but
+a BSD 2.11 with a TCP/IP-stack is so much nicer.
+
+The following is a real desktop PDP-11 with some emulators for things
+like tapes and external devices:
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDP-11.jpg" alt="PDP-11" >}}
+
+## Apple ][
+
+I brought some old floppies and was astonished they were booting the
+oldest Apple machines without any problems. Even the chess program
+worked (one of my earliest encounters with a computer was playing
+chess in the computer room back at my high school on an Apple \]\[).
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-Apple-2.jpg" alt="Apple \]\[" >}}
+
+I was also able to run a "games disk" with a menu system I once typed
+in from a book during my holidays back in school (yes, floppies where
+too expensive back then and you learned BASIC as a bonus while typing).
+
+Obviously too excited this still worked I didn't take any photos of it,
+so here is a placeholer, the original book with the program listings:
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-apple-games-book.jpg" alt="Apple Game Book" >}}
+
+## old PCS
+
+While everybody else at the exhibitation was showing off their machines,
+the IBM-PC guys were trying to make sure that monitors didn't explode
+(one did) and building up a network, so they were constantly busy
+doing something on those machines. I was able to run a Flight Simulator 4
+from Microsoft on an EGA-based machine, really nice:
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-FS4.jpg" alt="Fligh Simulator 4" >}}
+
+## SoftVGA
+
+Really interesting speech on how to implement a VGA "card" on an Atmel-based
+board. This catched my interest because I'm all in for minimalistic
+hardware and software on an FPGA.
+
+## Fluxengine
+
+This was more out of personal interest, as I still own 100nds of Apple \]\[,
+CP/M and PC-disks reaching back into the mid-80ies. My oldest two machines
+(an IMC-2001 Taiwanese Apple/CPM-clone and the Olivetti M290) are not working
+anymore and I can hardly find a floppy connector on the already old machines
+I own.
+
+Fluxenine reads floppy images via a 5V FPGA on a stick, one side is an
+old floppy connector, the oder side a normal USB connection.
+
+I brought some old floppies I could donate (in form of an image) for
+future analysis.
+
+## What else
+
+SGI, a Next, IBM/360 on an FPGA, Amiga, Commodore, tons of Apple/Macintosh,
+ZX Spectrum, ...
+
+## What not
+
+I personally missed some CP/M-based machines (not counting the electronic
+type writer running CP/M and running games from a small tape drive, which
+was interesting to see). Closest (from the outer appearance) came the
+following IBM portable:
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-IBM-5155.jpg" alt="IBM 5155 Portable" >}}
+
+Also I missed some Atari (like the ST TT series) machines (or maybe
+I just didn't see them).
+
+## Important Lessons Learned
+
+Talk to everybody! Every single one is an enthusiast and has an interesting
+history. If you just walk through the hall and stare at the machines, most
+things will not be impressive at all. Also the talks I can recommend.
+
+## Links
+
+* general links
+ * [Vintage Computer Festival Zurich](http://vcfe.ch/doku.php): official Webpage with exhibitors and schedule of speeches held
+ * [Event Information "Rote Fabrik"](https://rotefabrik.ch/#/events/5084?utm_medium=display&utm_source=kulturzueri.ch&utm_campaign=kulturzueri#/events/5084):
+ event information
+ * [Wikipedia entry on vintage Computer Festival](https://de.wikipedia.org/wiki/Vintage_Computer_Festival): history and purpose of the event
+ * [Gallery 2019](https://www.skv-net.ch/mobilegallery/gallery.php?a=456)
+* PDP-11/Tektronik:
+ * [Tek4010](https://github.com/rricharz/Tek4010)
+ * [BSD 2.11](https://github.com/RetroBSD/2.11BSD)
+* [SoftVGA](http://neil.franklin.ch/Projects/SoftVGA/)
+* [Fluxengine](http://cowlark.com/fluxengine): the FPGA-based USB-floppy reader
diff --git a/content/blog/retro-computing-vintage-computer-festival-zurich-2021.md b/content/blog/retro-computing-vintage-computer-festival-zurich-2021.md
new file mode 100644
index 0000000..58d7158
--- /dev/null
+++ b/content/blog/retro-computing-vintage-computer-festival-zurich-2021.md
@@ -0,0 +1,87 @@
++++
+
+title = "Retro Computing - Vintage Computer Festival Zürich 2021"
+categories = [ "Retro Computing", "Vintage Computer Festival", "VCF" ]
+date = "2021-11-29T06:43:34+01:00"
+thumbnail = "/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021.jpg"
++++
+
+## Intro
+
+First of all, quite amazing it could even happen given the pandemic
+situation, thanks to all organizers and exhibitors. It was held on
+November 27th/28th in Zürich in the "Rote Fabrik".
+
+No talks were held this year, also for obvious reasons. There were
+not many people there presumably also due to the pandemic situation.
+
+## Tektronix 4010
+
+2019 I saw a PDP-11 emulator along with an emulated Tektronix 4010
+graphical terminal. This time there was the real thing. Really impressive,
+and a phenomenal keyboard. (The image below is unintentionally blured
+due to the subpar photographic skills of the author):
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-tektronix-4010.jpg" alt="Tektronix 4010" >}}
+
+## Soviet computers
+
+There were all kinds of Soviet computers, something we don't get to
+see very often here.
+
+For instance the Agat computer based on a 6502:
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-agat.jpg" alt="Agat" >}}
+
+The BK-0010-01 Soviet computer was really nice, being roughly a PDB-11 clone
+with an impressive dual-head monitor setup:
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-BK-0010-01.jpg" alt="BK-0010-01" >}}
+
+## Lilith and Ceres
+
+For the first time I saw the "portable" version of the Lilith and sadly
+non-working versions of the Ceres 1 and 3 workstations. I did my studies
+on the Ceres 3 when back at ETH Zurich from 1992 to 1997. Mr Gutknecht was
+around to explain things.
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-ceres3.jpg" alt="Ceres 3 Workstation" >}}
+
+I brought along my old school books, so that people had at least the chance
+to read a little bit about the system.
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-oberon-books.jpg" alt="Programming in Oberon and The Oberon System" >}}
+
+
+## OLPC XO-1
+
+I was exhibiting my OLPC XO-1 computer in a series of communication devices
+from enter.ch.
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-olpc-xo-1.jpg" alt="OLPC XO-1" >}}
+
+## Important Lessons Learned
+
+My machines are not old or rare enough. I should really try to get the IMC-2001 running again
+doing some 6502-Apple2, Z80-CP/M stuff. Or the Olivetti with a 286 board inside or the 386..
+
+## Links
+
+* general links
+ * [Vintage Computer Festival Zurich](https://vintagecomputerfestival.ch): official webpage
+* PDP-11/Tektronik:
+ * [Tektronix 4010](https://en.wikipedia.org/wiki/Tektronix_4010)
+* Soviet Computers:
+ * [BK-0010-01 Soviet computer](https://wiki.vcfb.de/2020/en:soviet_computers)
+ * [Agat](https://en.wikipedia.org/wiki/Agat_(computer))
+* OLPC XO-1
+ * [OLPC XO-1](https://www.eguide.ch/en/objekt/xo-1-one-laptop-per-child/)
+* Computermuseum
+ * [Enter.ch](https://www.enter.ch)
+* Ceres/Lilith/Oberon:
+ * [Project Oberon 2013](http://www.projectoberon.com/): second edition, with a RISC-5 CPU done on FPGA
+ * https://verhoeven272.nl/fruttenboel/Oberon: all kind of information and nice links
+ * http://www.ethistory.ethz.ch/rueckblicke/departemente/dinfk/forschung/weitere_seiten/lilith/index_DE/popupfriendly/:
+ some nice screenshots of the machines
+
+
diff --git a/content/blog/retro-computing-vintage-computer-festival-zurich-2022.md b/content/blog/retro-computing-vintage-computer-festival-zurich-2022.md
new file mode 100644
index 0000000..2edbf62
--- /dev/null
+++ b/content/blog/retro-computing-vintage-computer-festival-zurich-2022.md
@@ -0,0 +1,100 @@
++++
+
+title = "Retro Computing - Vintage Computer Festival Zürich 2022"
+categories = [ "Retro Computing", "Vintage Computer Festival", "VCF" ]
+date = "2022-11-21T07:56:22+01:00"
+thumbnail = "/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-harddisk.jpg"
++++
+
+## Intro
+
+This is the last vintage computer festival in Zürich in the "Rote Fabrik"
+(which has to be restorated after a bad fire back in 2012) - at least
+for now. It was held on November 19th/20th.
+
+It was back to what it was before the pandemic in terms of exhibits,
+the amount of people attending, the talks (which where held again this year).
+
+It's an ever growing community of exhibitors, most of them try to
+attend every year, so I'm just pointing out the new things, which
+catched my attention (the others can be seen on older blog entries
+of the series).
+
+This year we had challenges, so visitors could try their skills by
+solving puzzles or programming tasks at the exhibition desks. This
+is a good idea to get visitors more involved and it's not just a
+museum then, where exhibitors have to say 20 times the same stuff
+or people are just walking by the computers and making photos.
+
+I was sceptical in the beginning (basically because I don't like
+puzzling), but in the end I also did one or two of the challenges:
+trying to use a Lisa desktop and trying to get a message to Mastodon
+from an old Unix System V.
+
+## Local Heroes
+
+Again we had the ETHZ Lilith and Ceres as local Zürich computers, but
+this time also the group around Prof. Jean-Daniel Nicoud from the EPFL
+Lausanne. He showed some really interesting things.
+
+### Teaching Electronics
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-electronics-teaching.jpg" alt="Teaching Electronics" >}}
+
+Those blocks are basically 74xxx series logic chips in a block with
+schematics on top. You use cables to connect them and form logical
+blocks like for instance a small adder with carry. This is much nicer
+to deal with than with breadboards and the real logic chips.
+
+### Smaky
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-smaky-100.jpg" alt="Smaky 100" >}}
+
+This is a series of 8-bit computers, the first one based on Intel 8080, later on Z80.
+This one is based on a 68k processor. The really nice thing is the graphical interface,
+the keyboard and the mouse which feel absolutely modern.
+
+### Self-made computers
+
+On Youtube you can find a lot of people doing their own computer
+projects based on 6502 and Z80 CPUs. This one is a really early example
+of it (and totally without Youtube - the green one on the left with
+the high voltage sign and the cards sticking out as in a toaster):
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-self-made.jpg" alt="Self made computers" >}}
+
+## Apple Lisa
+
+This is a computer you usually see not running and only behind some centimeters of glas.
+At the VCF you had the chance to experience the GUI (especially its speed, ahem).
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-front.jpg" alt="Apple Lisa" >}}
+
+## CP/M
+
+Hidden in a corner were some really nice CP/M-based machines:
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-cpm-machines.jpg" alt="CP/M machines" >}}
+
+## Important Lessons Learned
+
+My IMC-2001 is still not running and I'm currently fighting all kind of
+broken stuff (keyboard circuit, power supply, broken ROM-chip). Not having
+an exact twin of this machine makes it hard to repair.
+
+..and yes, I know how to create a document on the Apple Lisa now. ;-)
+
+## Links
+
+* general links
+ * [Vintage Computer Festival Zurich](https://vintagecomputerfestival.ch): official webpage
+* Smaky (sadly a lot of the links are broken)
+ * [Smaky Mouse and Keyboard](https://www.informatiquegestion.ch/mouse-and-keyboard): close up images
+ * [Smaky machines](https://www.smaky.ch/chapitre.php?id=lami_4): the timeline of the Smaky computers
+ * [Smaky@museebolo](https://www.museebolo.ch/): where the Smakies can usually be seen outside the VCF
+ * [Video on Smaky](https://www.youtube.com/watch?v=5Vt01NJIy18): on Youtube, shows off various Smakies,
+ history, games, etc. @debConf
+* videos
+ * [Youtube Gamo Tech25](https://youtu.be/rL4lvOuebJE)
+ * [Tomaniac](https://youtu.be/hIb0VxhVU2M)
+ * [The Phintage Collector](https://youtu.be/baWwDEKfXBA)
diff --git a/content/blog/retro-computing-vintage-computer-festival-zurich-2023.md b/content/blog/retro-computing-vintage-computer-festival-zurich-2023.md
new file mode 100644
index 0000000..75a2785
--- /dev/null
+++ b/content/blog/retro-computing-vintage-computer-festival-zurich-2023.md
@@ -0,0 +1,113 @@
++++
+
+title = "Retro Computing - Vintage Computer Festival Zürich 2023"
+categories = [ "Retro Computing", "Vintage Computer Festival", "VCF" ]
+date = "2023-11-12T17:32:22+02:00"
+thumbnail = "/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpg"
++++
+
+## Intro
+
+This time the vintage computer festival in Zürich was held in
+the "EWZ Kraftwerk Selnau". This is a former substation in the middle
+of Zurich which is a museum, event hall and coworking area now.
+The enterior is best described as a bunch of ship containers
+aranged in a middle of a factory hall. In the middle there is a bar
+now. There are corners with couches and a big room upstears which
+looks like the former control room (and most likely was one).
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-selnau1.jpg" alt="EWZ substation at Selnau" >}}
+
+As always I'm not listing all exhibitors and exhibited pieces, I'm
+just pointing out new things, which catched my attention this year
+(the others can be seen on older blog entries of the series).
+
+This year I was not in for challenges, I rather prefer talking to
+people, but everybody can do what he wants.
+
+New this year is a full recording of all the talks, this is nice
+as you don't have to decide whether you are watching the computers
+in the exhibition and having discussions with the exhibitors or whether
+you are watching the talks. This also good for the exhibitors themselves who
+would love to be able to attend to the talks too.
+
+## Portables
+
+A full room upstears was dedicated to a bunch of portable computers
+from the venerable Osborne OCC-1, Commodore SX-64, Amstrad,
+various PC portables, etc.
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-portables.jpg" alt="Portable computers" >}}
+
+### OLPCs
+
+It's nice to see two OLPC XO-1 next to each other, with the mesh
+wlan in action. My takeaway is that it's not only the pieces of
+hardware you have and want to show, it's also about the story
+you tell about them and the way you present them - and where.
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-olpcs.jpg" alt="Two 'One Laptop per Child' OLPC XO-1 on a bench" >}}
+
+### IBM PC Convertible (model 5140)
+
+I couldn't resist to play Planet X3 on CGA Composite on a small
+surveilance monitor thingy (sorry, one photo was blurred and the
+other one has now a non-syncing output signal, I promise,
+take my word, it worked just fine in "full" CGA colors).
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-ibm-convertible.jpg" alt="IBM PC Convertible (model 5140) with external monitor" >}}
+
+### Scrib
+
+Thankfully they was a Scrib teletype writer from the Smaky series
+of computers in that room which you could actually touch without
+white glowes. It was the technological equivalent of a Chinese
+fingertrap to me, trying to spin my head around the way you use this
+thing. Unique is the idea of using a mirror on the back to reflect the
+image of the CRT (which is mounted on the back). The image is cristal
+clear compared to other CRT displays of that time.
+
+I managed to print something, but couldn't remember the key combination
+I pressed so I spent far too much time to reproduce printing.
+I managed all kind of "erreurs de casettes" (behind the little
+shiny glas cover on the right the machine can hold two small tapes)
+but sadly not a second print.
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpg" alt="Smaky Scrib" >}}
+
+## BBC Acorn Econet school network
+
+It was real joy to see the UKs pride of computing in a series of Acorn
+machines joined in a Econet network. Of course various Raspberry PIs
+were serving as coprocessor emulators, network files servers, etc.
+
+It was really pleasant to talk to Mark Usher and his plans collecting and
+documenting those machines.
+
+Who has the time should see BCC early education series on computing on TV.
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-acorns.jpg" alt="Acorns" >}}
+
+## Other nice projects
+
+Especially nice was the Fusix on a Dragon32 (something I can also imagine
+to try on my IMC-2001) and the fully restaurated Sol-20 with wooden borders.
+
+{{< figure src="/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-others.jpg" alt="Dragon 32 and Sol-20" >}}
+
+## Important Lessons Learned
+
+Fix that darn IMC-2001.. ;-)
+
+## Links
+
+* general links
+ * [Vintage Computer Festival Zurich](https://vintagecomputerfestival.ch): official webpage
+* smaky
+ * [Smaky Scribd](https://www.smaky.ch/chapitre.php?id=lami_6)
+* Acorn, Econet
+ * [Listing of computer models](https://www.retro-kit.co.uk/page.cfm/content/Acorn-Computers-Ltd/index.html)
+ * [Econet manuals](http://www.8bs.com/othrdnld/manuals/econet.shtml)
+* videos
+ * [Youtube video on the IBM PC Convertible (model 5140)](https://www.youtube.com/watch?v=F4fH6iPMxGw)
+
diff --git a/content/blog/web-search-homepage.md b/content/blog/web-search-homepage.md
index a3a1cc3..98b81c7 100644
--- a/content/blog/web-search-homepage.md
+++ b/content/blog/web-search-homepage.md
@@ -258,10 +258,24 @@ The upload to the remote webserver can be done more elegantly.
One idea is to use the backup/replication API of strus for this:
build an index locally and sync it to the strusWebService.
-Update March 2018: currently the ARM version of strus is completely broken
+### Update 8.3.2018
+
+Currently the ARM version of strus is completely broken
and the strusWebService is being rewritten. So there will be an updated
blog entry when those things are fixed.
+### Update 29.4.2018
+
+Replaced the web page search with an [Elasticlunr](http://elasticlunr.com/)
+Javascript search, running 100% on the client for added security and load
+distribution benefits.
+
+### Update 17.12.2023
+
+Replaced the Elasticlunr search with a webassembly version of
+[Sqlite Free Text Search 5](https://www.sqlite.org/fts5.html).
+Also runs completely on the clients browser.
+
# Sources
As always you can find the sources of the project on my github (also hosted
@@ -271,5 +285,5 @@ http://git.andreasbaumann.cc/cgit/www-andreasbaumann-cc/
The strus specific scripts and configuration are in:
-http://git.andreasbaumann.cc/cgit/www-andreasbaumann-cc/tree/strus
+http://git.andreasbaumann.cc/cgit/www-andreasbaumann-cc/tree/search/strus
diff --git a/content/contact/_index.md b/content/contact/_index.md
index e01bd58..66cb333 100644
--- a/content/contact/_index.md
+++ b/content/contact/_index.md
@@ -30,27 +30,42 @@ tzehXAMDqBBPyqlL88XZUBpXTIOyHBqC1kDjwTsIla+6AgepIRZQ2KDUaZrpuvDZ
jdnkclNZOIdmJapUfUu37CN4EP0noOkfvLOcsgqedWqtOox0GpGg5zoMFzG//O1H
V8H8yj65hsUa2118wXyy5MJ3+a6UkMuROgW5Hingks7md0QHbjQqG8EZherqdYm7
9Aa74y/O82hhYFHJJzpcRUo5hFrUusF3+uWrABEBAAG0KEFuZHJlYXMgQmF1bWFu
-biA8bWFpbEBhbmRyZWFzYmF1bWFubi5jYz6JAVQEEwEIAD4WIQQ4rKagJtJc3SJ9
-JIMvY5nc0iEhlQUCWaWx+AIbAwUJA8JnAAULCQgHAgYVCAkKCwIEFgIDAQIeAQIX
-gAAKCRAvY5nc0iEhlfnMCADzJPsby7+rBDFmt/QR929SiE35Uod+Q91YWYlC23/E
-o3HxRk01GAUmv6InN9cYJoCZEdcXDYJPtJhHjO/DSURDU2xx5gBd3gWbIFIsTiUi
-ryqqDyeIoq+pMWzQ9LG3eQfdGfIcRu5jLem7k/naPCQvxSpHf6O3YekwHZqng6i3
-yDmwUp5CSNDxDqV7HnwW6d02kHvA+3Q6undDAWQF0XdP7wgm3mlMVLNkTqDmYeQS
-ATptJcOpMEwi8t9mYmuiWYYPwDm492NScK5AoUF0WVK42aG5BEz2Oz9LVtcXKquu
-17Zr6xcuKtgM71paCO3dxnlvef0HbFeHFmOTT6lqu1z2uQENBFmlsfgBCADfP4Se
-cL8GvCKgVWuoM1tOEaZ/eND4jc4RcYTRdEiZYHfGah8S+kNd21Zpep++FSvQbwb+
-PjdQRbCwn+dBdxgpMhrLfZ3zy3Xtd4EEftq0y8Gyi+6ejJjk8eW7Xvl91objJSyh
-J5Fx5v/K9bof9uCTLaWq/aFjcWpovsbbDWrq/OXowp8A69xMPAmJee8zW/Nj7Fv0
-sgQrIGNe3T4BWVncuuzP3YWxCB85ysk99l17joKrQx6w7FaG0e/n+gd1X0YRofYg
-eu2UCpswbwfu7pwiWnNtgCajhaw47Og/9FMpsXGvuQs93pOLon7jLlPn1nsOaX5h
-NkHfmyYabykXlpZBABEBAAGJATwEGAEIACYWIQQ4rKagJtJc3SJ9JIMvY5nc0iEh
-lQUCWaWx+AIbDAUJA8JnAAAKCRAvY5nc0iEhlaMBCADIwsJwRi9XqkxaldehThkx
-giQDp6M99J+quKLsevVRtDKi88tSWEhYRNKNjZLkmfQ8cKcR4eSDEIN9135RTK+w
-mYq+IWgKIAPaFeMGQmBm2vlKTSpR4cuNMUCCToXwq4vUr5e/jRg+TzTf7j2pH7hi
-HIQILaiU74g7KCcR2X8EUxG6Dus1Sk6zcvmnASBirw2M8bgarTBlr8GPpDUxnp7Q
-LilZfyClqM29IfDjGOa+9RvOqHeC4m3xW8pqjIEuKOQeMmSY4xX7B01rFgILqhH4
-+IzlxIwq3xx0kxUup0zNLUtzBg2y9W6KX+VwruO4jH3qG91m3l/+1y1jRnQrtVkf
-=hS12
+biA8bWFpbEBhbmRyZWFzYmF1bWFubi5jYz6JAVQEEwEIAD4CGwMFCwkIBwIGFQgJ
+CgsCBBYCAwECHgECF4AWIQQ4rKagJtJc3SJ9JIMvY5nc0iEhlQUCZWIaRwUJDZ2b
+zwAKCRAvY5nc0iEhlSkcCACWXadTea1QUA9Ny9RoEqKCnEN+IbnEyukewmsnq4Xc
+6iX2MlkAxtPqUGxk8L3xxp1/q9s0yXaSNZjjBzj0uu0KS6QGDbTXDVzyC567jlbQ
+qeDI8IfJlVZl28FJtPwuTOBqnxx+0BwEZX4WGoa3d+lhuuoqjpXw6Z4QZYVGEucW
+m2Ri8qJFDpGXOjornaq7NJfhVx3Z8vNrwr0mipRG9B7HzleqPwwaJ/CmJrFeDY3B
+Qv5cMTZiSPRUa/j/qh59rCwyhMlqX6MdOxQ62BaeapM0I4tS2CsdiRWxF+pWbRXc
+rIB2Vb20J4h/R4IbHt/H078ABtPI2dwUs2VvPzf1lLjAiQFUBBMBCAA+FiEEOKym
+oCbSXN0ifSSDL2OZ3NIhIZUFAlmlsfgCGwMFCQPCZwAFCwkIBwIGFQgJCgsCBBYC
+AwECHgECF4AACgkQL2OZ3NIhIZX5zAgA8yT7G8u/qwQxZrf0EfdvUohN+VKHfkPd
+WFmJQtt/xKNx8UZNNRgFJr+iJzfXGCaAmRHXFw2CT7SYR4zvw0lEQ1NsceYAXd4F
+myBSLE4lIq8qqg8niKKvqTFs0PSxt3kH3RnyHEbuYy3pu5P52jwkL8UqR3+jt2Hp
+MB2ap4Oot8g5sFKeQkjQ8Q6lex58FundNpB7wPt0Orp3QwFkBdF3T+8IJt5pTFSz
+ZE6g5mHkEgE6bSXDqTBMIvLfZmJrolmGD8A5uPdjUnCuQKFBdFlSuNmhuQRM9js/
+S1bXFyqrrte2a+sXLirYDO9aWgjt3cZ5b3n9B2xXhxZjk0+partc9okBVAQTAQgA
+PgIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgBYhBDispqAm0lzdIn0kgy9jmdzS
+ISGVBQJdS9cGBQkHaIwOAAoJEC9jmdzSISGVEAcH/RfoMGcAw4A4GnlwQO3cBXIb
+G6z06H/7gPuAwSwGETBCIh6D3rkpjSw7I8YqXsbpNzWloXOhRoX1jsy3a0Vy5rps
+e6dddBXcyJOPSvTgNw3uWU0FbXQHlqVlwJ/SWQq882aOZZFnXITkaxzYK3TZtqRJ
+p4vgszEHhtaycMfyeXQNmlWQY0SHXA9AVgxYecIvvxkxp1AZ4GrhHXR9KC40FcSY
+CDvXluc6Uuscnl2t2Elxbjl8fpeb2Ifjy34AIUHB8vPPaVqfDfne6MbthYG8gG+s
+92NQPlhYjUCPc/IbWD2IvNJObXbBna9jGYsEg0/rR0DzChkzNA5SxJXb6I8DX0e5
+AQ0EWaWx+AEIAN8/hJ5wvwa8IqBVa6gzW04Rpn940PiNzhFxhNF0SJlgd8ZqHxL6
+Q13bVml6n74VK9BvBv4+N1BFsLCf50F3GCkyGst9nfPLde13gQR+2rTLwbKL7p6M
+mOTx5bte+X3WhuMlLKEnkXHm/8r1uh/24JMtpar9oWNxami+xtsNaur85ejCnwDr
+3Ew8CYl57zNb82PsW/SyBCsgY17dPgFZWdy67M/dhbEIHznKyT32XXuOgqtDHrDs
+VobR7+f6B3VfRhGh9iB67ZQKmzBvB+7unCJac22AJqOFrDjs6D/0Uymxca+5Cz3e
+k4uifuMuU+fWew5pfmE2Qd+bJhpvKReWlkEAEQEAAYkBPAQYAQgAJgIbDBYhBDis
+pqAm0lzdIn0kgy9jmdzSISGVBQJlM3LABQkNbvRIAAoJEC9jmdzSISGV3VsH/2or
+KR4Dvf+KYmdjYRSJmN0qczO7x/IZx9WGCIUrKCj+11d8voDOGCPwleiPlDQ6UO0p
+TknWn9oH0xuJoRLhZCaxCb04p2x1Urbscb09NJA9opibs3g8lbX1Mjdg3ayeUDb3
+5EkpowtI4tyjkX+sqtBYbwxgqg0kGwtt38xhLutilCIxSD8q92Sm92DKePaEAgGi
+NqYf/QUfjWtwswo7B/vhIUNbCBIUk0oWtW9P3HfJ/nQfWyG+N7N9KEvrTXaJ2o0K
+pLo22OY6Cg3qbLvbCkQ0/H30bPRQo7dqm6tvWP7V/Qy6PZX7NOiphka4cRw3uI8W
+Q1qs4ogfoSGjc/IkYyc=
+=3o73
-----END PGP PUBLIC KEY BLOCK-----
```
diff --git a/content/dataprotection/_index.md b/content/dataprotection/_index.md
index 2d92266..0d35960 100644
--- a/content/dataprotection/_index.md
+++ b/content/dataprotection/_index.md
@@ -12,6 +12,11 @@ or Piwik.
I do keep Apache log entries and firewall rules with IP, Date and User-Agent
information for at most 7 days in order to fight attacks and spam.
-Currently I'm using a Wordpress theme which uses Google fonts.
-For more information about Google Fonts see https://developers.google.com/fonts/faq,
-section "What does using the Google Fonts API mean for the privacy of my users?".
+Currently I'm using a Wordpress theme which uses Bunny fonts.
+For more information about Bunny Fonts see
+[https://bunny.net/fonts/](https://bunny.net/fonts/).
+
+This page is available both via HTTPS and HTTP, because using retro
+computers usually means you don't have the necessary libraries or
+computing power for TLS. To learn more about this topic see
+[http://neil.franklin.ch/Save_HTTP/index.html.en](http://neil.franklin.ch/Save_HTTP/index.html.en).
diff --git a/content/git/_index.md b/content/git/_index.md
index 4467646..1edb036 100644
--- a/content/git/_index.md
+++ b/content/git/_index.md
@@ -15,3 +15,7 @@ git clone git://git.andreasbaumann.cc/repo.git
If you have comments or patches, you can send them via email.
If you want to collaborate, I can give you write access.
+
+## Github
+
+Forked projects are on [Github](https://github.com/andreasbaumann?tab=repositories).
diff --git a/content/hardware/_index.md b/content/hardware/_index.md
new file mode 100644
index 0000000..c6475dc
--- /dev/null
+++ b/content/hardware/_index.md
@@ -0,0 +1,9 @@
++++
+title = "Hardware"
++++
+
+A (not so curated) list of old hardware I own:
+
+- [IMC-2001](/hardware/imc-2001): Taiwanese Apple \]\[ / CP/M clone
+
+
diff --git a/content/hardware/imc-2001-chargen40.md b/content/hardware/imc-2001-chargen40.md
new file mode 100644
index 0000000..84bf54a
--- /dev/null
+++ b/content/hardware/imc-2001-chargen40.md
@@ -0,0 +1,90 @@
++++
+title = "IMC-2001 40 character mode"
++++
+
+{{< figure src="/images/hardware/imc-2001/chargen.png" alt="character in the 40-char ROM" >}}
+
+*A4-A6* on the schematics is the character ROM in a chip labelled
+UMC UM2316-J127 8432, it is Intel 2716 EPROM compatible chip it seems.
+
+It can be read with the TL866 and returns the following 2K dump:
+
+[chargen.rom](/hardware/imc-2001/chargen.rom): Chargen 40-column ROM
+
+The official ROM
+[3410036.BIN](http://www.applelogic.org/APPLEASICs.html) on
+http://www.applelogic.org/APPLEASICs.html doesn't match
+at all. The arangement of the characters is different and there are
+lowercase characters in the clone ROM.
+
+I wrote a small program to show the contents of chargen.rom:
+
+```
+#!/usr/bin/tcc -run -Werror -DSDL_DISABLE_IMMINTRIN_H -I/usr/include/SDL2 -lSDL2
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <SDL.h>
+
+int main( int argc, char *argv[] )
+{
+ FILE *f = fopen( "./chargen.rom", "r" );
+ char *buf = malloc( 2 * 1024 );
+ fread( buf, 2 * 1024, 1, f );
+
+ SDL_Renderer *renderer;
+ SDL_Window *window;
+
+ SDL_Init( SDL_INIT_VIDEO );
+ SDL_CreateWindowAndRenderer( 300, 200, 0, &window, &renderer );
+ SDL_SetRenderDrawColor( renderer, 0, 0, 0, 0 );
+ SDL_RenderClear( renderer );
+ SDL_SetRenderDrawColor(renderer, 0xFF, 0xB0, 0, 255 );
+
+ int x = 0;
+ int y = 0;
+ for( int c = 0; c < 2 * 1024; c++ ) {
+ int v = buf[c] & 0x00ff;
+ for( int b = 0; b < 8; b++ ) {
+ if( v & 0x01 ) {
+ SDL_RenderDrawPoint( renderer, x, y );
+ }
+ v >>= 1;
+ x++;
+ }
+ x -= 8;
+ y += 1;
+ if( ( (c+1) % 128 ) == 0 ) {
+ x += 10;
+ y = 0;
+ }
+ }
+
+ SDL_RenderPresent( renderer );
+
+ int done = 0;
+ while( !done ) {
+ SDL_Event event;
+ SDL_PollEvent( &event );
+ switch( event.type ) {
+ case SDL_QUIT:
+ case SDL_KEYDOWN:
+ done = 1;
+ break;
+ }
+ }
+
+
+ SDL_DestroyRenderer( renderer );
+ SDL_DestroyWindow( window );
+ SDL_Quit( );
+
+ free( buf );
+ fclose( f );
+ return 0;
+}
+```
+
+And indeed I get:
+
+{{< figure src="/images/hardware/imc-2001/chargen.png" alt="character in the 40-char ROM" >}}
diff --git a/content/hardware/imc-2001-documentation.md b/content/hardware/imc-2001-documentation.md
new file mode 100644
index 0000000..20fce81
--- /dev/null
+++ b/content/hardware/imc-2001-documentation.md
@@ -0,0 +1,18 @@
++++
+title = "IMC-2001 Documentation"
++++
+
+# Operation Manual
+
+"Operation Manual for IMC-2001, version 2.01":
+
+{{< figure src="/images/hardware/imc-2001/manual_frontpage.jpg" alt="manual frontpage" >}}
+
+[The complete scanned manual](/hardware/imc-2001/manual_imc_2001_2.01.pdf)
+(also on archive.org, see [https://archive.org/details/manual_imc_2001_2.01](https://archive.org/details/manual_imc_2001_2.01))
+
+# Super Serial Card
+
+I got a super serial card from Ebay, the documentation of it can be
+found here [https://archive.org/details/Apple_II_Super_Serial_Card_1981_Apple](https://archive.org/details/Apple_II_Super_Serial_Card_1981_Apple).
+
diff --git a/content/hardware/imc-2001-firmware.md b/content/hardware/imc-2001-firmware.md
new file mode 100644
index 0000000..8e4aabc
--- /dev/null
+++ b/content/hardware/imc-2001-firmware.md
@@ -0,0 +1,185 @@
++++
+title = "IMC-2001 Firmware"
++++
+
+{{< figure src="/images/hardware/imc-2001/romboard.jpg" alt="IMC-2001 ROM card" >}}
+
+# Intro
+
+The ROM consists of two ROM chips. The bigger chip labelled "ROM1" was
+broken (it got really hot) and could not be read (it returned all zeroes).
+It has no markings on it, so one can only guess it is something AT28C256
+compatible.
+
+The ROMs sit in the special "slot 0". The board has two other
+unused ROM sockets and an arrow pointing to an additional ROM socket on
+the motherboard itself.
+
+On the schematics the slot is not labelled "slot 0" but "ROM" and this
+gives away it's special purpose for the machine.
+
+# ROM 2
+
+ROM 2 (sticker with hand-written red 2 on top) is a Mitsubishi M5L2732K,
+32k-bit, 4k-ROM, seems very ok during operation (the carvings say
+"M5L2732K, 83080L, JAPAN").
+
+## lower-case patch
+
+Comparing ROM2 to the standard Apple autostart ROM
+(https://6502disassembly.com/a2-rom/AutoF8ROM.html) we see only one difference at:
+
+```
+FD80 (F800+580)
+
+AutoF8ROM
+00000580 90 02 29 df 9d 00 02 c9 8d d0 b2 20 9c fc a9 8d |..)........ ....|
+monitor.rom:
+00000580 90 02 ea ea 9d 00 02 c9 8d d0 b2 20 9c fc a9 8d |........... ....|
+```
+
+```
+fd80: 90 02 bcc ADDINP
+fd82: 29 df and #$df ;shift to upper case
+fd84: 9d 00 02 ADDINP sta IN,x
+fd87: c9 8d cmp #$8d
+fd89: d0 b2 bne NOTCR
+fd8b: 20 9c fc CROUT1 jsr CLREOL
+fd8e: a9 8d CROUT lda #$8d
+fd90: d0 5b bne COUT
+```
+
+*EA EA* are 2 nops where the *and #$df* is. This seems to do away with
+uppercasing the byte coming from the keyboard, so that lower-case character
+work.
+
+# ROM 1
+
+ROM 1 is hard to guess, what it originally contained (as mine got fried).
+
+# addressing mode
+
+I put back the original Autostart ROM, the addressing on the PCB is a little
+bit weird. As the monitor was working I could write a test ROM with
+
+```
+#!/usr/bin/tcc -run -Werror
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main( int argc, char *argv[] )
+{
+ FILE *f = fopen( "./pattern.rom", "w" );
+ char *buf = malloc( 1024 );
+ for( int i = 0; i < 32; i++ ) {
+ memset( buf, i, 1024 );
+ fwrite( buf, 1024, 1, f );
+ }
+ fclose( f );
+ free( buf );
+ return 0;
+}
+```
+
+and get the following pattern in the monitor:
+
+```
+D000 1C
+D400 1D
+D800 1E
+DC00 1F
+E000 18
+E400 19
+E800 1A
+EC00 1B
+```
+
+So the replacement AT28C256 is arranged as follows:
+
+```
+0x6000 18 must contain the second 4k of the apple rom starting with e000 (24k)
+0x7000 1c must contain the first 4k of the apple rom d000
+```
+
+So I ended up doing this:
+
+```
+dd if=/dev/zero of=zero1 bs=1 count=24576
+dd if=Applesoft of=apple1 bs=1 skip=4096 count=4096
+dd if=Applesoft of=apple2 bs=1 count=4096
+cat zero1 apple1 apple2 > newrom1.rom
+```
+
+## Unkown difference
+
+When I watched the series on the Apple clone from Adrian's Digital Basement
+(he has a nice 3 part mini-series on the fixing of an Apple clone of unknown
+origin) I noticed the following difference:
+
+ROMS he published 'Apple\ II\ Clone\ ROM\ E0\ 300854cc.bin' which
+has one single difference in the E000 ROM:
+
+```
+ ; Convert FAC to integer. Must be -32767 <= FAC <= 32767.
+e10c: a5 9d AYINT lda FAC ;exponent of value in FAC
+e10e: c9 90 cmp #$90 ;abs(value) < 32768?
+e110: 90 09 bcc MI2 ;yes, okay for integer
+e112: a9 fe lda #<NEG32768 ;no; next few lines are supposed
+e114: a0 e0 ldy #>NEG32768 ;to allow -32768 ($8000), but do not!
+e116: 20 b2 eb jsr FCOMP ;because compared to -32768.00049
+ ; <<< BUG: A=-32768.00049:A%=A is accepted, but PRINT A,A% shows that A=-
+ ; 32768.0005 (ok), A%=32767 (wrong!) >>>
+```
+
+instead of *a0e0* it has *a0e5*
+
+```
+ ; <<< meant to be -32768, which would be 9080000000 >>>
+ ; <<< 1 byte short, so picks up $20 from next instruction >>>
+e0fe: 90 80 00 00 NEG32768 .bulk $90,$80,$00,$00 ;-32768.00049 in floating point
+```
+
+maybe the variable got moved to *e5fe* for some reasons? hard to tell, especially
+as the other ROMs have no differences. I kept mine on the original autostart ROM.
+
+## PIN Layout
+
+Found on https://forum.classic-computing.de/forum/index.php?thread/11666-apple-clon-gtac-fragen/&postID=401752#post457130
+
+```
+Slot Rom1 Rom2 Slot Rom1 Rom2
+
+Pin Pin
+
+26 12 14-12 25 28 24
+27 20,18 24
+28 22 23
+29 22
+30 21
+31 20
+32 19
+33 18
+34 17
+35 16
+36 15
+37 14 2
+38 13 23
+39 12 20
+40 11 24
+41 10 25 23
+42 9 3 1
+43 8 4 2
+44 7 5 3
+45 6 6 4
+46 5 7 5
+47 4 8 6
+48 3 9 7
+49 2 PIN10 8
+50 1
+```
+
+## Links
+
+* https://forum.classic-computing.de/forum/index.php?thread/11666-apple-clon-gtac-fragen/&postID=401752#post457130
diff --git a/content/hardware/imc-2001-images.md b/content/hardware/imc-2001-images.md
new file mode 100644
index 0000000..f7d3bdb
--- /dev/null
+++ b/content/hardware/imc-2001-images.md
@@ -0,0 +1,20 @@
++++
+title = "IMC-2001 Images"
++++
+
+From the outside:
+
+{{< figure src="/images/hardware/imc-2001/computer_full.jpg" alt="IMC-2001" >}}
+
+Booting into Apple \]\[ CP/M 56k:
+
+{{< figure src="/images/hardware/imc-2001/cpm_40chars.jpg" alt="IMC-2001" >}}
+
+The motherboard and floppy drives:
+
+{{< figure src="/images/hardware/imc-2001/motherboard_internal.jpg" alt="IMC-2001" >}}
+
+The motherboard seems to be a CTAG-2 Taiwanese motherboard, so pretty standard.
+
+The floppy drives are standard TEAC-55A-U-00, with the short cable without the ground
+pins between data lines presumably.
diff --git a/content/hardware/imc-2001-keyboard.md b/content/hardware/imc-2001-keyboard.md
new file mode 100644
index 0000000..aaeea43
--- /dev/null
+++ b/content/hardware/imc-2001-keyboard.md
@@ -0,0 +1,58 @@
++++
+title = "IMC-2001 keyboard"
++++
+
+connector to machine (sort of a rubber version of a DB-9):
+
+The connector on the computer side has a 9-pin DSUB connector male:
+
+```
+ +----------- white INTR
+ | +--------- black GND
+ | | +------- green DATA
+ | | | +----- blue RESET
+ | | | | +--- Yellow CLOCK
+-------------
+\ O O O O O /
+ \ O O O O /
+ ---------
+ | | | +---- red 5V
+ | | +------ n.c.
+ | +-------- n.c.
+ +---------- n.c.
+```
+
+On the keyboard PCB there is a strange white connector with the following layout:
+
+```
+ +------------- white INTR (active low, after last clock tick)
+ | +----------- black GND
+ | | +--------- blue RESET (active low)
+ | | | +------- green DATA
+ | | | | +----- yellow CLOCK
+ | | | | | +--- red +5V
+ +-----------+
+ |o o o o o o|
+ +-----------+
+ | |
+```
+
+Keyboard layout:
+
+{{< figure src="/images/hardware/imc-2001/keyboard_front.jpg" alt="keyboard layout" >}}
+
+Keyboard has a 8039 CPU inside and a 2K EPROM:
+
+{{< figure src="/images/hardware/imc-2001/keyboard_pcb_controller_prom.jpg" alt="PCB and controller" >}}
+
+On the oscilloscope:
+
+{{< figure src="/images/hardware/imc-2001/oscilloscope_serial_keyboard.jpg" alt="serial keyboard signal" >}}
+
+The protocol is basically ASCII over 19200 baud serial, with an interesting end signal which
+IMHO triggers a latch on the motherboard or so (INTR white above).
+
+Broken keyboard cable (the black pins are just connectors added by me to test connectivity,
+both connector are female per default):
+
+{{< figure src="/images/hardware/imc-2001/keyboard_cable.jpg" alt="PCB and controller" >}}
diff --git a/content/hardware/imc-2001-links.md b/content/hardware/imc-2001-links.md
new file mode 100644
index 0000000..2d8a421
--- /dev/null
+++ b/content/hardware/imc-2001-links.md
@@ -0,0 +1,19 @@
++++
+title = "IMC-2001 Links"
++++
+
+## Other IMC-2001
+
+* [Mention of the IMC-2001](http://www.epocalc.net/php/liste_models.php?texte=&look=All+fields&yearmax=2018&nocomp=pc&cat=Apple+2+clone):
+ mentions it on the list of Apple clones
+* [Youtube video of similar machine](https://www.youtube.com/watch?v=c7crlJg80Zg):
+ "APPLE II CLONE + CP/M ------- IMC 2001 made in taiwan.--------", Retro Computacion Argentina Jorge E. Nuviola
+
+## Other Similar Clones
+
+* West PC 800:
+ - Pietro Filiberi: https://www.youtube.com/@dustylife/videos
+ - Retro Erik: https://www.youtube.com/watch?v=Kop7mHEmJyM
+* https://github.com/eyalabraham/apple2 or
+ https://github.com/pfiliberti/gtac-appleclone
+* http://john.ccac.rwth-aachen.de:8000/patrick/MEWA48.htm
diff --git a/content/hardware/imc-2001-power.md b/content/hardware/imc-2001-power.md
new file mode 100644
index 0000000..ee8e3a1
--- /dev/null
+++ b/content/hardware/imc-2001-power.md
@@ -0,0 +1,26 @@
++++
+title = "IMC-2001 Power and PSU"
++++
+
+Power connector on the motherboard:
+
+```
++-------------+
+| O O O O O O |
++-------------|
+ | | | | | +--- GND black
+ | | | | +----- +12V red
+ | | | +------- -5V blue
+ | | +--------- -12V brown
+ | +----------- +5V white
+ +------------- +5V white
+```
+
+Old PSU:
+
+{{< figure src="/images/hardware/imc-2001/old_psu.jpg" alt="New PSU" >}}
+
+New PSU replacing the old crusty one (this is a standard replacement PSU for
+Apple \]\[ from [Reactive Micro](https://wiki.reactivemicro.com/Universal_PSU_Kit)):
+
+{{< figure src="/images/hardware/imc-2001/new_psu.jpg" alt="New PSU" >}}
diff --git a/content/hardware/imc-2001-status-todos.md b/content/hardware/imc-2001-status-todos.md
new file mode 100644
index 0000000..9ba7995
--- /dev/null
+++ b/content/hardware/imc-2001-status-todos.md
@@ -0,0 +1,133 @@
++++
+title = "IMC-2001 Status and Todo List"
++++
+
+# Todos
+
+Trying to fix several issues:
+
+- CPM65 works on the machine in 40-character mode (hacked), the
+ Videx card is the next goal. The 40-character mode still is quite
+ unreliable and crashes the machine, the screen TTY driver is still
+ to be done for apple2.
+- the 5V rail is on 4.5V now, causing issues with the keyboard (the
+ length of the cable) and with the paddles. Not clear, whether this
+ is the PSU (which is also showing 4.7V without load) or something
+ on the motherboard. There are two +5V lines on the original PSU and
+ only one on the replacement PSU, maybe that's a problem?
+- the keyboard beeps and issues '=' and '/' characters when connected
+ to a longer serial cable, no problems when connecting the botched
+ wire from the old connector on the keyboard PCB directly to the
+ computer. Some shielding or capacitance issue? It also appeared
+ only after playing with the paddle connectors.
+- the new paddle connector with DIN-5 connectors works somewhat with
+ paddle 0, though the nob is not totally up when on 255. This indicates
+ again a capacitance issue, probably with the cable itself?
+- two new teac drives turned out to have the very wrong connector for
+ an Apple \]\[ disk controller, some adapted has to be designed and
+ a PCB has to be printed.
+- strange issues with floppy images not working in LinApple or also
+ not on the real computer, always bailing out in the monitor in strange
+ locations. Used Fluxengine and ADTPro to get images, they are identical.
+ Checked the RAM of the machine, no errors. Must investigate if boot
+ addresses are the issue (48k floppy masters not working on 64 or similar
+ issues)
+- HGR shows a line on row 0 only partially. This could be an adjustment issue
+ of the CRT image or also bad RAM.
+- the CRT shows some flickering and diagonal effects. Testing on an old TV
+ shows the same issue (so I suspect it's some grounding/shielding issue
+ with the new PSU).
+- the CRT is producing some flickering when turning the brightness nob,
+ this should be fixable with some deoxit.
+- the second floppy drive (the more used one) now sees floppies always as
+ "write protected". Diagnostic tests show alignment issues of the drive, this
+ could be true, or the clone always had a different alignment than a default
+ Apple 2 drive?
+- the paddle wire is self-made on paddle 1 and quit a mess. Doing a rewire
+ with DIN-5 connectors which then lead to a 9-pin DSUB-Apple ][ standard
+ joystick connector, which will go to the 16-pin DIP socket on the motherboard.
+ The original joystick connector has a completely weird layout and is not usable
+ (it has no Apple 2 layout)
+- really bad design to connect DIP 2x8 cables of the joystick and the paddles
+ directly on the motherboard, you pull the cable a little bit too much and
+ you tar out half of the motherboard.
+- possibly much more
+
+# Fixed Issues
+
+- ~~the paddle and the joystick connectors miss some legs for putting them into
+ the sockets on the motherboard~~. No essential pins are missing, will
+ rework this anyway as a 8x2 DIP to 9-DSUB, from there to an adapter
+ where you can connect 2 DIN-5 cables, needs rewiring of both paddles.
+- ~~paddle 0 seems to be a little bit shacky (the button works unreliably)~~.
+ DeOxit in the button helped. Works much better now.
+- ~~the lever moving the contacts between 40-character and 80-character
+ mode for the CRT output is corroded, doesn't always make contact
+ and produces a flickering image~~. The box is heavily sealed and there
+ is no easy way to fix it. Using an audio switch box for switching modes now
+ (the cables are standard audio-like cinch connectors).
+- ~~the floppy drives read floppies (both) but they don't write to floppies
+ (when copying in CP/M or creating a file), they work when formatting
+ a drive on CP/M though. ~~Could be a side-effect of the PSU not working properly.~~
+ The PSU has been replaced, the voltages look ok, so I rule out the PSU.
+ Could be some missing code in the Apple ROM (but that would be weird to
+ call 6502 firmware code from the Z80 CPU). It could also be the write
+ current being to low for writting (but why does formatting a drive work then?!)~~
+ So, yes. DOS 3.3 and CP/M both use some ROM routines from ROM1 to write to disk.
+ Works now.
+- ~~floppies written read/written with Fluxengine don't really work either
+ on the real hardware or the emulator. Suspecting a encoding/decoding issue.~~
+ Updating Fluxengine solved the issue, also choosing 96dpi 5 1/4" for the real
+ floppy drive. :-)
+- ~~the keyboard reset line cannot be taken to ground on the keyboard, works
+ with shrtening ground and reset though just fine. Must be a bug on the
+ ICs of the keyboard controller or a broken trace.~~ Fixed with a botch
+ to bridge the broken ribbon cable between keyboard matrix and the PCB with
+ the controller logic.
+- ~~ROM 1 with BASIC is broken (and gets really hot). This explains
+ the booting issues.. (will be tricky to get a replacement). The
+ board layout doesn't fit to the original ROM sizes too..~~
+ Got an AT28C256, no more frying of chips, Apple Basic prompt appears,
+ tested some commands and it seems fine. The 32k ROM has to be filled in
+ starting from 0x6000 with #E000-$EFFF and from $7000 with $D000-$DFFF.
+ If this ROM is ok we will see.
+- Reseated and deoxied all ICs, some of them were quite corroded, at
+ least 3 more turned out to be bad. ~~Sadly it didn't have an effect on
+ ROM 1 not getting hot (must be something else).~~ The new replacement
+ ROM works fine and doesn't get hot. So I actually blame it on the ROM
+ itself causing the other ICs to fry and not vice-versa.
+- ~~power switch made some hissing noises, it was not the switch, now
+ the original power is dead (and some transformers are humming). Ordered
+ a Apple 2 replacement PSU, waiting for it..~~
+ The new replacement power supply works like a charm, also replaced
+ the power switch, the old one was too unreliable.
+- ~~sometimes I get into the monitor~~
+- ~~lower-nibble bit 3 of the key
+ being pressed is missing, unclear where it is lost, I suspect a
+ bad register on the motherboard holding the current ASCII value of
+ the key pressed or something similar~~. Replaced a bad 74LS257N,
+ works now just fine.
+
+# Not fixed issues:
+
+- ~~The 220V fan no longer works.~~
+ I just disconected it, I don't think, it really helps to cool the system.
+
+# Known things to work:
+
+- The keyboard works electronically (8039 MCS-48 like CPU with a 2K EPROM),
+ has a new serial cable now and is fully functional
+- the Rockwell R6502 CPU has a phase 0 clock and seems to go through
+ address lines and output data (another strong indicator is the 'Apple \]\['
+ sign on the monitor when switching on which indicates 6502, 40-character
+ ROM, video circuit seems to be just fine).
+- Monitor is working just fine (which is sort of amazing for such an old
+ CRT monitor).
+- I can boot from a Apple \]\[ CP/M 56k floppy and I get a prompt, now
+ as the keyboard works and the CP/M on the 80-character card I can also
+ assume the Z80 is working just fine.
+- the 80-columns card (a Videx Videoterm or rather a clone of it) works just fine.
+- the highres graphic mode works just fine, I can run "Peter Anvin Chess" and play it.
+- Applesoft BASIC works fine
+- the new Super Serial Card II I got works fine, though it looses characters
+ (without parity and adding some delay in minicom). Definitely usable.
diff --git a/content/hardware/imc-2001.md b/content/hardware/imc-2001.md
new file mode 100644
index 0000000..608e455
--- /dev/null
+++ b/content/hardware/imc-2001.md
@@ -0,0 +1,18 @@
++++
+title = "IMC-2001"
++++
+
+{{< figure src="/images/hardware/imc-2001/computer_full.jpg" alt="IMC-2001" >}}
+
+This is an old Taiwanese Apple \]\[ / CP/M clone.
+
+- [Status and Todos](/hardware/imc-2001-status-todos)
+- [Keyboard](/hardware/imc-2001-keyboard): keyboard connector and protocol
+- [Power](/hardware/imc-2001-power): PSU and power
+- [Chargen40](/hardware/imc-2001-chargen40): 40-column character mode
+- [Firmware](/hardware/imc-2001-firmware): the monitor, Applesoft ROMs
+- [Documentation](/hardware/imc-2001-documentation): documentation about the machine
+ and peripherals
+- [Images](/hardware/imc-2001-images)
+- [Links](/hardware/imc-2001-links): links to other similar machines
+
diff --git a/content/search/_index.md b/content/search/_index.md
index 80efd10..1c0d6d7 100644
--- a/content/search/_index.md
+++ b/content/search/_index.md
@@ -2,4 +2,6 @@
title = "Search"
+++
-The search is using [ElasticLunr](http://elasticlunr.com/).
+<!-- The search is using [ElasticLunr](http://elasticlunr.com/). -->
+
+The search is using [FTS5 Sqlite3 in sql.js](https://www.skypack.dev/view/sql.js-fts5).
diff --git a/content/slide/_index.md b/content/slide/_index.md
index ce5b956..eab5ab6 100644
--- a/content/slide/_index.md
+++ b/content/slide/_index.md
@@ -6,10 +6,10 @@ title = "Slides"
* [OBS Build System](/slide/obs): how to package C++ software with the
help of the [Open Build Service](http://build.opensuse.org). Used in
- the [Strus](http://project-strus.net) project.
+ the [Strus](http://project-strus.net) project (2015).
## Strus
-* [Strus Web Service](http://eurospider.github.io/strusWebService/doc/slides/strus-webservice.html): a web service written
+* [Strus Web Service](/slide/strus-webservice): a web service written
with [CppCMS](http://cppcms.com) exposing the [Strus](http://project-strus.net)
- APIs as a JSON protocol similar to [Elasticsearch](http://www.elastic.co/products/elasticsearch).
+ APIs as a JSON protocol similar to [Elasticsearch](http://www.elastic.co/products/elasticsearch) (2015, 2016).
diff --git a/content/slide/strus-webservice.md b/content/slide/strus-webservice.md
new file mode 100644
index 0000000..2638e6e
--- /dev/null
+++ b/content/slide/strus-webservice.md
@@ -0,0 +1,411 @@
++++
+title = "strusWebService"
++++
+
+ <div class="reveal">
+
+ <!-- Any section element inside of this container is displayed as a slide -->
+ <div class="slides">
+ <section>
+ <h1>Strus - Web Service</h1>
+ <p>
+ <small>Created by <a href="http://www.andreasbaumann.cc">Andreas Baumann</a></small>
+ </p>
+ <p>
+ <small><a href="http://www.andreasbaumann.cc/slide/strus-webservice">http://www.andreasbaumann.cc/slide/strus-webservice</a></small>
+ </p>
+ <p><small>(C)2015/2016</small></p>
+ </section>
+
+ <section>
+ <h2>Outline</h2>
+ <ul>
+ <li>Have a web service, language independent, for search.</li>
+ <li>The software to the vision exists, it's called <b>Elasticsearch.</b></li>
+ <li>Based on Lucene, so we do the same with Strus</li>
+ <li>Currently there is a Java API which uses this service</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Strus web service</h2>
+ <ul>
+ <li>uses JSON and HTTP GET/POST</li>
+ <li>implemented using <a href="http://cppcms.com/wikipp/en/page/main">CppCMS</a></li>
+ <li>uses only the <a href="http://patrickfrey.github.io/strus/doc/doxygen/html/index.html">Strus core API</a> currently</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Design rationales</h2>
+ <ul>
+ <li>standard technology (HTTP, JSON)</li>
+ <li>CRUD (all basic functions exists for all classes)</lib>
+ <li>proxyable and securable</li>
+ <li>zero-configuration</li>
+ <li>scalable</li>
+ <li>C++</li>
+ <li>MPL v2</li>
+ <li>runs on Linux, OSX, FreeBSD</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Protocol</h2>
+ <ul>
+ <li>Service functions</li>
+ <li>Index functions</li>
+ <li>Document functions</li>
+ <li>Query functions</li>
+ <li>Transactions</li>
+ <li>Statistics</li>
+ <li>Introspection and Configuration</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Protocol</h2>
+ <ul>
+ <li>Manipulate indexes:
+ <pre><code class="hljs" data-trim contenteditable>
+curl -XPOST -H 'Content-Type: application/json'
+http://localhost:8080/strus/index/create/A
+'-d { "params" : { } }'
+
+{"result":"ok"}
+
+curl -XPOST http://localhost:8080/strus/index/delete/A
+{"result":"ok"}
+
+curl -XPOST http://localhost:8080/strus/index/exists/A
+{"exists":false,"result":"ok"}
+
+ </code></pre>
+ </li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Protocol</h2>
+ <ul>
+ <li>Insert document:
+ <pre><code class="hljs" data-trim contenteditable>
+curl -XPOST -H 'Content-Type: application/json'
+http://localhost:8080/strus/document/insert/A
+-d
+{ "doc" : { "docid" : "doc3",
+ "attributes" : [
+ { "key" : "title", "value" : "This is a Hello World Document" },
+ { "key" : "attr1", "value" : "val1" },
+ { "key" : "attr2", "value" : "val2" } ],
+ "metadata" : [
+ { "key" : "doclen", "value" : 23773 }, { "key" : "docweight", "value" : 3.1415 } ],
+ "forward" : [
+ { "type" : "word", "value" : "Hello", "pos": 1 },
+ { "type" : "word", "value" : "World", "pos" : 2 } ],
+ "search" : [
+ { "type" : "Word", "value" : "hello", "pos": 1 },
+ { "type" : "word", "value" : "world", "pos" : 2 } ] }
+}
+ </code></pre>
+ </li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Protocol</h2>
+ <ul>
+ <li>Query:
+ <pre><code class="hljs" data-trim contenteditable>
+curl -XPOST -H 'Content-Type: application/json'
+http://localhost:8080/strus/query/A
+-d
+{ "query": {
+ "first_rank": 0,
+ "nof_ranks": 20,
+ "weighting": {
+ "scheme": {
+ "name": "bm25",
+ "params": [
+ {
+ "key": "b",
+ "value": 0.75
+ },
+ {
+ "key": "k1",
+ "value": 1.0001
+ },
+ {
+ "key": "avgdoclen",
+ "value": 11943
+ }
+ ]
+ }
+ },
+ "summarizer": [
+ {
+ "attribute": "attribute",
+ "name": "attribute",
+ "params": [
+ {
+ "key": "name",
+ "value": "docid"
+ }
+ ]
+ }
+ ],
+ "features": [
+ {
+ "name": "feat",
+ "value": {
+ "term": {
+ "type": "word",
+ "value": "hello"
+ }
+ },
+ "weight": 1
+ },
+ {
+ "name": "sel",
+ "value": {
+ "expression": {
+ "operator": "union",
+ "range": 0,
+ "cardinality": 0,
+ "terms": [
+ {
+ "term": {
+ "type": "word",
+ "value": "hello"
+ }
+ }
+ ]
+ }
+ },
+ "weight": 1
+ }
+ ],
+ "select": [
+ "sel"
+ ]
+}
+
+{
+ "execution_time": 0.000983791,
+ "ranklist": {
+ "documents_ranked": 1,
+ "documents_visited": 1,
+ "passes_evaluated": 0,
+ "ranks": [
+ {
+ "attributes": [
+ {
+ "key": "docid",
+ "value": "doc3"
+ }
+ ],
+ "docno": 1,
+ "weight": 0
+ }
+ ]
+ },
+ "result": "ok"
+}
+ </code></pre>
+ </li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Protocol</h2>
+ <ul>
+ <li>Transactions:
+ <pre><code class="hljs" data-trim contenteditable>
+curl -XPOST -H 'Content-Type: application/json'
+http://localhost:8080/strus/transaction/begin/A/T1
+
+curl -XPOST -H 'Content-Type: application/json'
+http://localhost:8080/strus/document/insert/A
+-d
+{ "transaction" : { "id" : "T1" },
+ "doc" : { "docid" : "doc1",
+ ...
+}
+
+curl -XPOST -H 'Content-Type: application/json'
+http://localhost:8080/strus/transaction/commit/A/T1
+ </code></pre>
+ </li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Protocol</h2>
+ <ul>
+ <li>Introspection (document):
+ <pre><code class="hljs" data-trim contenteditable>
+curl -XPOST -H 'Content-Type: application/json'
+http://localhost:8080/strus/document/get/A/doc3
+
+{
+ "doc": {
+ "attributes": [
+ {
+ "key": "attr1",
+ "value": "val1"
+ },
+ {
+ "key": "attr2",
+ "value": "val2"
+ },
+ {
+ "key": "docid",
+ "value": "doc3"
+ },
+ {
+ "key": "title",
+ "value": "This is a Hello World Document"
+ }
+ ],
+ "docno": 1,
+ "forward": [
+ {
+ "pos": 1,
+ "type": "word",
+ "value": "Hello"
+ },
+ {
+ "pos": 2,
+ "type": "word",
+ "value": "World"
+ }
+ ],
+ "metadata": [
+ {
+ "key": "docweight",
+ "value": 3.141499996185303
+ },
+ {
+ "key": "doclen",
+ "value": 23773
+ },
+ {
+ "key": "date",
+ "value": 0
+ }
+ ],
+ "search": [
+ {
+ "pos": 1,
+ "type": "word",
+ "value": "hello"
+ },
+ {
+ "pos": 2,
+ "type": "word",
+ "value": "world"
+ }
+ ]
+ },
+ "execution_time": 0.00028157,
+ "result": "ok"
+}
+ </code></pre>
+ </li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Protocol</h2>
+ <ul>
+ <li>Statistics and introspection (index):
+ <pre><code class="hljs" data-trim contenteditable>
+curl http://localhost:8080/strus/index/stats/A
+
+{"result":"ok","stats":{"nof_docs":1}}
+
+curl http://localhost:8080/strus/index/config/A
+
+{"config":{
+ "attributes":["attr1","attr2","docid","title"],
+ "metadata":[{"name":"date","type":"UInt16"},{"name":"doclen","type":"UInt16"},{"name":"docweight","type":"Float32"}],
+ "types":["word"]},
+"result":"ok"}
+ </code></pre>
+ </li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Protocol</h2>
+ <ul>
+ <li>Statistics and introspection (system):
+ <pre><code class="hljs" data-trim contenteditable>
+curl http://localhost:8080/strus/config
+{"config":{
+ "posting_join_operators":[
+ "chain","chain_struct","contains","diff","inrange","inrange_struct","intersect","pred","sequence","sequence_struct","succ","union","within","within_struct"],
+ "summarizer_functions":[
+ "accuvariable","attribute","matchphrase","matchpos","matchvariables","metadata"],
+ "weighting_funtions":[
+ "bm25","formula","metadata","td","tf"]},
+"result":"ok"}
+
+ ...
+ "weighting_functions": [
+ {
+ "description": "Calculate the document weight with the weighting scheme \"BM25\"",
+ "name": "bm25",
+ "parameter": [
+ {
+ "description": "defines the query features to weight",
+ "name": "match",
+ "type": "feature"
+ },
+ {
+ "description": "parameter of the BM25 weighting scheme",
+ "name": "k1",
+ "type": "numeric"
+ },
+ ...
+ </code></pre>
+ </li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Strus web service</h2>
+ <h3>Links</h3>
+ <ul>
+ <li><a href="http://github.com/patrickfrey/strusWebService">http://github.com/patrickfrey/strusWebService</a></li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Java API</h2>
+ <ul>
+ <li>Uses latest Java 1.8 (aka requires Java 1.8)</li>
+ <li>Uses Jackson for POJO serialization from/to JSON</li>
+ <li>uses javax.ws.rs.client web service classes for HTTP</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Java API</h2>
+ <p><b>Note:</b> dead, no longer maintained or developed!!</p>
+ <h3>Links</h3>
+ <ul>
+ <li><a href="http://github.com/Eurospider/strusJavaAPI">http://github.com/Eurospider/strusJavaAPI</a></li>
+ <li><a href="http://eurospider.github.io/strusJavaApi/apidocs/index.html">JavaDoc</a></li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Todos and future</h2>
+ <ul>
+ <li>support all functions from all strus APIs, not only small part of query and storage interface</li>
+ <li>reimplementation (C++11, alternatives to cppcms?, HTTP/2.0 support? using new strusBindings)</li>
+ </ul>
+ </section>
+ </div>
+ </div>
diff --git a/content/software/OpenBSD_firewall.md b/content/software/OpenBSD_firewall.md
index a03ec00..d784214 100644
--- a/content/software/OpenBSD_firewall.md
+++ b/content/software/OpenBSD_firewall.md
@@ -8,15 +8,15 @@ description = "OpenBSD firewall via scripts"
Earlier versions of this project were used at Eurospider by Mihai Barbos (https://github.com/mbarbos)
to build corporate-style firewalls with Portwell hardware.
-Newer versions run on Soekris hardware now.
+It ran on a Soekris net6501 for 4 years.
-I merely collected the ideas and updated them to new versions of OpenBSD and cleaned up the repository a little bit. :-)
+Newer versions run on a Network LES of Thomas Krenn now.
-And I'm using it at home.
+I merely collected the ideas and updated them to new versions of OpenBSD and cleaned up the repository a little bit. :-)
-## Github
+And I'm using it at home on an Alix 2D.13.
-The old unsupported version can still be found on https://github.com/Eurospider/OpenBSD-firewall.
+## Git
Further development happens on git://git.andreasbaumann.cc/OpenBSD-firewall.git
or http://git.andreasbaumann.cc/cgit/OpenBSD-firewall/.
@@ -51,11 +51,53 @@ or remotely (after booting from floppy dongle or from hard disk):
## News
+19.10.2023:
+
+ updated to OpenBSD 7.4
+
+20.4.2023:
+
+ updated to OpenBSD 7.3
+
+22.10.2022:
+
+ updated to OpenBSD 7.2
+
+1.5.2022:
+
+ updated to OpenBSD 7.1
+
+24.10.2021:
+
+ updated to OpenBSD 7.0
+
+3.6.2021:
+
+ updated to OpenBSD 6.9
+
+22.10.2020:
+
+ updated to OpenBSD 6.8
+
+5.6.2020:
+
+ updated to OpenBSD 6.7
+
+20.10.2019:
+
+ updated to OpenBSD 6.6
+
+11.05.2019:
+
+ updated to OpenBSD 6.5
+
+28.10.2018:
+
+ updated to OpenBSD 6.4
+
06.05.2018:
- The firewall at Eurospider has not been updated in years and I'm fed up with
- Github and the world in general, so I moved the repo and abandoned the old
- development area on Github.
+ moved repository from Github to a local repository.
15.04.2018:
@@ -127,11 +169,13 @@ At Eurospider we had Portwell NAR-2054 (3 and 5 ethernet port versions),
some have VGA ports and USBs, others only COMs, so make sure we always
get boot output on COM.
-Now at Eurospider we run it on a Soekris net6501, but I'm not going to
-update and test that one anymore.
+It ran on a Soekris net6501 for 4 years, then the Soekris died.
+
+Newer versions run on a Network LES of Thomas Krenn now.
At home I'm running it on an ALIX.2D13 with 3 LAN ports and a WLAN card.
-VirtualBox build and test
+
+## VirtualBox build and test
Create a VMDK wrapper for the disk image built with 'build.sh firewall-test':
diff --git a/content/software/nagios_plugin_curl.md b/content/software/nagios_plugin_curl.md
index bd83c2c..1867b9f 100644
--- a/content/software/nagios_plugin_curl.md
+++ b/content/software/nagios_plugin_curl.md
@@ -3,17 +3,15 @@ title = "Nagios Curl Plugin"
description = "a [Nagios](http://www.nagios.org) plugin replacing check_http"
+++
-In my job I'm sometimes the deputy of the system administrator.
-Using nagios/zabbix/SNMP for monitoring I needed a decent plugin
-for Nagios to do HTTP alive checks. The standard one had some problems
+In my job I'm taking care of a monitoring system using nagios.
+For monitoring web sites I needed a decent plugin for Nagios to do
+HTTP(s) alive checks. The standard 'check_http' plugin had some problems
mainly with chunked transfer encoding, thus I hacked a plugin using the
excellent [libCurl library](http://curl.haxx.se).
Further development goes on as 'check_curl' in
-[monitoring-plugins](https://github.com/monitoring-plugins/monitoring-plugins)
-in branch
-feature_check_curl. If you want help out testing or developing it
-should happen there.
+[monitoring-plugins](https://github.com/monitoring-plugins/monitoring-plugins).
+If you want help out testing or developing it should happen there.
An old archived version of the plugin can be found at
http://git.andreasbaumann.cc/cgit/nagios-plugin-curl/.
diff --git a/content/toolbox/_index.md b/content/toolbox/_index.md
index 5b45780..c4be5f4 100644
--- a/content/toolbox/_index.md
+++ b/content/toolbox/_index.md
@@ -13,8 +13,10 @@ Some things I found to be useful for daily programming.
I use mainly the memory checker and the profiler.
* [KCachegrind](https://kcachegrind.github.io/html/Home.html): graphical
profiler presenting runs of valgrind performance checks in a nice way.
-* [xxdiff](http://furius.ca/xxdiff/): 2 and 3-way graphical diff tool,
+* [xxdiff](https://github.com/blais/xxdiff/): 2 and 3-way graphical diff tool,
I use it because of nostalgia (aka: I got used to it).
+* [entr](http://eradman.com/entrproject/): for executing a command on
+ changed files, e.g. make.
## C Programming
@@ -24,7 +26,9 @@ Some things I found to be useful for daily programming.
## Database Modelling
* [dbmodel](http://oxygene.sk/projects/dbmodel/): a very neat
- database modeller with PDF and image export.
+ database modeller with PDF and image export. (For Qt5 there
+ are fixed versions at http://git.andreasbaumann.cc/cgit/dbmodel/?h=qt5,
+ branch 'qt5' or https://git.eckner.net/Erich/dbmodel/)
## Data processing
@@ -35,9 +39,6 @@ Some things I found to be useful for daily programming.
## Infrastructure
-* [openSUSE Build Service](https://build.opensuse.org/): for building
- release packages in the cloud.
-* [Travis CI](http://travis-ci.org/): for continuous integration on Mac OSX.
* Using [libvirtd](http://libvirt.org) now instead of VirtualBox
(sorry, Oracle). Main reason: it's still a little bit un-ready round
the edges but hey, it's really open source. :-)
@@ -60,21 +61,56 @@ Some things I found to be useful for daily programming.
## Other
-* [Ion3](http://tuomov.iki.fi/software/): tiling window manager with
+* [Ion3](http://tuomov.iki.fi/software/ion/): tiling window manager with
strong keyboard and Lua scripting support. Sadly the original author
got into fights with the open source community :-(
- I'm currently using the fork [Notion](http://notion.sourceforge.net/).
- Read [http://raboof.github.io/notion/tour/](http://raboof.github.io/notion/tour/)
+ I'm currently using the fork [Notion](https://sourceforge.net/projects/notion/).
+ Read [http://raboof.github.io/notion/](http://raboof.github.io/notion/)
if you want to learn how to use such a window manager.
* [Joe](http://en.wikipedia.org/wiki/Joe's_Own_Editor): my editor for
- all quick editing jobs. Having used a lot of Wordstar in my youth,
- **jstar** is the editor I can't get rid of in my brain. :-)
+ all quick editing jobs. Having used a lot of Wordstar and Turbo Pascal IDEs
+ in my youth, **jstar** is the editor I can't get rid of in my brain. :-)
* [meh](http://www.johnhawthorn.com/meh/): as fast and easy an image
- viewer can possibly get.
+ viewer can possibly get. I use a fork which adds QOI support (see
+ https://github.com/andreasbaumann/meh/tree/qoi)
* [MuPDF](http://www.mupdf.com/): an equally fast PDF/XPS viewer.
* [Trojitá](https://en.wikipedia.org/wiki/Trojit%C3%A1): a simplistic
and really fast mail reader for IMAP accounts. For long-term archiving
- of email I'm using a combination of [OfflineIMAP](http://www.offlineimap.org)
- and good old [Mutt](http://mutt.org).
-* [Seamonkey](http://www.seamonkey-project.org/): back to old SeaMonkey,
- fast, no clue what they did to Firefox to make it so slow.
+ of email I'm using [Mutt](http://mutt.org) with POP3 and a maildir
+ directory (proved to be extremely stable over time).
+* [Luakit](https://luakit.github.io/): webkit-based browser, highly customizable
+ with Lua scripting
+* [irssi](https://irssi.org/): for chatting (terminal)
+* [newsboat](https://newsboat.org/): a RSS feed reader looking like mutt
+ (I'm using the old pure-C++/non-Rust version I forked as
+ [newsboat-og](https://github.com/andreasbaumann/newsboat-og))
+* [Wordgrinder](https://cowlark.com/wordgrinder/): really nice text editor
+ if actually all you want to do is writting some text
+* [Suckless](https://suckless.org/): pretty much every software there is
+ 10 times smaller and easier to use than whatever makes up the default
+ Linux user land. I'm a big fan of it.. it only should be the standard
+ on every Linux system.
+* [Ripcord](https://cancel.fm/ripcord/): way faster alternative to
+ Discord (and yes, I also pay for software - Slack), no video capabilities
+ though, just audio and chat but that's usually all I need. The electron
+ based Discord and Slack are just so unbearably slow, if I need that
+ experience I can as well start the browser version.
+
+## Deprecated
+
+The following tools I used in the past, but not anymore:
+
+* [Seamonkey](http://www.seamonkey-project.org/): Seamonkey slowly gets
+ all the "features" of Mozilla (slow, Rust build problems, out-of-memory
+ when building and linking). So I lost interest in it. I replaced it with
+ Luakit and mutt/trojita, irssi, etc..
+* [Librewolf](https://librewolf-community.gitlab.io/): fork of Firefox,
+ without all the built-in stuff from Mozilla nobody needs or asked for.
+ I'm no longer using it, as compiling it is too much of a hazzle with
+ frequent rust incompatibilities..
+* [openSUSE Build Service](https://build.opensuse.org/): for building
+ release packages in the cloud. They deleted my home project and I'm
+ no longer doing software development, really.
+* [Travis CI](http://travis-ci.org/): for continuous integration on Mac OSX.
+ Don't care about building on Apple anymore due to all kind of reasons..
+
diff --git a/search/fts5/README b/search/fts5/README
new file mode 100644
index 0000000..681b425
--- /dev/null
+++ b/search/fts5/README
@@ -0,0 +1,87 @@
+# Search index with Sqlite3 FTS5 Full Text Search
+
+# generate JSON dynamically with a JSON output generator,
+# see https://halfelf.org/2017/hugos-making-json/
+#curl http://localhost:1313/index.json > posts.json
+curl http://www.andreasbaumann.cc/index.json > posts.json
+
+# we need sqlite and FTS5
+# https://www.legendu.net/misc/blog/hands-on-full-text-search-in-sqlite3/
+pacman -S sqlite3
+
+# use posts.json to create entries in the virtual FTS5 table
+rm posts.db
+cat <<EOF | sqlite3 posts.db
+CREATE VIRTUAL TABLE posts USING fts5(uri,title,content);
+EOF
+
+# create post SQL statements from JSON with JQ (https://jqlang.github.io/jq/manual/)
+jq -j '.[] | "INSERT INTO posts(uri, title, content) VALUES (", ( [ .uri, .title, .content // empty ] | map(.|gsub("'"'"'";"`")|gsub("\n";" ")|@sh) | join(",")), ");\n"' \
+ posts.json > posts.sql
+sqlite3 posts.db < posts.sql
+cp posts.db ../../static/index/.
+
+# some test queries
+# https://www.legendu.net/misc/blog/hands-on-full-text-search-in-sqlite3/
+# https://sqlite.org/fts5.html
+sqlite3 posts.db
+sqlite> select uri from posts where posts MATCH 'OpenBSD' ORDER BY bm25(posts);
+sqlite> select uri,highlight(posts, 1, '<b>', '</b>'),snippet(posts, 2, '<b>', '</b>', '...', 50) from posts where posts MATCH 'OpenBSD' ORDER BY bm25(posts) limit 5 offset 0;
+
+# TODO: make a server-side search (search window and result page)
+# this would mean we have to render the hugo and the ranklist part on the server?
+
+# typical "modern" web development craziness.. :-)
+pacman --needed -S sha3sum
+trizen -G emsdk
+cd emdsk && makepkg -sif
+sudo emsdk install latest
+sudo emsdk activate latest
+sudo chown -R abaumann:users /usr/lib/emsdk/
+source /usr/lib/emsdk/emsdk_env.sh
+git clone --recursive https://github.com/jlongster/sql.js
+# add -DSQLITE_ENABLE_FTS5 to CFLAGS in Makefile
+# disable 'sha3sum -c cache/check.txt' (is broken)
+# emcc: error: setting `INLINING_LIMIT` expects `bool` but got `int`
+# set -sINLINING_LIMIT as booelean flag, modern emcc doesn't allow a cost integer here anymore it seems
+make
+#https://github.com/sql-js/sql.js/issues/546
+
+building emscripten2
+/data/INSTALL/emscripten2/src/llvm-project/llvm/include/llvm/Support/Signals.h:119:8: error: variable or field ‘CleanupOnSignal’ declared void
+ 119 | void CleanupOnSignal(uintptr_t Context);
+ | ^~~~~~~~~~~~~~~
+In file included from /data/INSTALL/emscripten2/src/llvm-project/llvm/lib/Support/Signals.cpp:251:
+/data/INSTALL/emscripten2/src/llvm-project/llvm/lib/Support/Unix/Signals.inc:348:44: error: ‘void llvm::sys::CleanupOnSignal(uintptr_t)’ should have been declared inside ‘llvm::sys’
+ 348 | void sys::CleanupOnSignal(uintptr_t Context) {
+
+
+# tons of errors, the containersized version uses VCode and WSL, so this things is
+# hairy to build
+# let's try a precompiled one
+# https://verdicts.listen.dev/npm/sql.js-fts5
+# https://www.skypack.dev/view/sql.js-fts5
+npm install sql.js-fts5
+cp node_modules/sql.js-fts5/dist/sql-wasm.js ../../themes/new_theme/static/js/.
+cp node_modules/sql.js-fts5/dist/sql-wasm.wasm ../../themes/new_theme/static/js/.
+
+# WASM is not read with self-hosted hugo server because of a charset-utf-8 added
+# to application/wasm: https://github.com/gohugoio/hugo/issues/10734
+# => rebuild Hugo with hugo-0.120.1-charset.patch
+
+# https://jlongster.com/future-sql-web
+# https://github.com/jlongster/absurd-sql
+npm install absurd-sql
+cp node_modules/absurd-sql/src/sqlite-fs.js ../../themes/new_theme/static/js/.
+cp node_modules/absurd-sql/dist/indexeddb-backend.js ../../themes/new_theme/static/js/.
+
+# TODO: add as sqlite.js to page with data (local sqlite fts search)
+# https://blog.ouseful.info/2022/04/06/compiling-full-text-search-fts5-into-sqlite-wasm-build/
+# https://github.com/phiresky/sql.js-httpvfs
+# https://github.com/psanford/sqlite3vfshttp
+# https://phiresky.github.io/blog/2021/hosting-sqlite-databases-on-github-pages/
+
+# https://github.com/kbumsik/sqlite-wasm
+sudo pacman -S typescript
+# typescript compile errors
+# 362 this.wasm._free(blobPtr);
diff --git a/search/fts5/hugo-0.120.1-charset.patch b/search/fts5/hugo-0.120.1-charset.patch
new file mode 100644
index 0000000..f22c1a3
--- /dev/null
+++ b/search/fts5/hugo-0.120.1-charset.patch
@@ -0,0 +1,12 @@
+diff -rauN hugo-0.120.1/hugolib/site.go hugo-0.120.1-charset-patch/hugolib/site.go
+--- hugo-0.120.1/hugolib/site.go 2023-10-30 17:44:31.000000000 +0100
++++ hugo-0.120.1-charset-patch/hugolib/site.go 2023-12-12 18:12:53.960153106 +0100
+@@ -400,7 +400,7 @@
+ func (s *Site) RegisterMediaTypes() {
+ for _, mt := range s.conf.MediaTypes.Config {
+ for _, suffix := range mt.Suffixes() {
+- _ = mime.AddExtensionType(mt.Delimiter+suffix, mt.Type+"; charset=utf-8")
++ _ = mime.AddExtensionType(mt.Delimiter+suffix, mt.Type)
+ }
+ }
+ }
diff --git a/static/blog/robots.txt b/static/blog/robots.txt
deleted file mode 100644
index 1f53798..0000000
--- a/static/blog/robots.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-User-agent: *
-Disallow: /
diff --git a/static/contact/aba.pub b/static/contact/aba.pub
index 96e50ed..32bd48f 100644
--- a/static/contact/aba.pub
+++ b/static/contact/aba.pub
@@ -6,25 +6,40 @@ tzehXAMDqBBPyqlL88XZUBpXTIOyHBqC1kDjwTsIla+6AgepIRZQ2KDUaZrpuvDZ
jdnkclNZOIdmJapUfUu37CN4EP0noOkfvLOcsgqedWqtOox0GpGg5zoMFzG//O1H
V8H8yj65hsUa2118wXyy5MJ3+a6UkMuROgW5Hingks7md0QHbjQqG8EZherqdYm7
9Aa74y/O82hhYFHJJzpcRUo5hFrUusF3+uWrABEBAAG0KEFuZHJlYXMgQmF1bWFu
-biA8bWFpbEBhbmRyZWFzYmF1bWFubi5jYz6JAVQEEwEIAD4WIQQ4rKagJtJc3SJ9
-JIMvY5nc0iEhlQUCWaWx+AIbAwUJA8JnAAULCQgHAgYVCAkKCwIEFgIDAQIeAQIX
-gAAKCRAvY5nc0iEhlfnMCADzJPsby7+rBDFmt/QR929SiE35Uod+Q91YWYlC23/E
-o3HxRk01GAUmv6InN9cYJoCZEdcXDYJPtJhHjO/DSURDU2xx5gBd3gWbIFIsTiUi
-ryqqDyeIoq+pMWzQ9LG3eQfdGfIcRu5jLem7k/naPCQvxSpHf6O3YekwHZqng6i3
-yDmwUp5CSNDxDqV7HnwW6d02kHvA+3Q6undDAWQF0XdP7wgm3mlMVLNkTqDmYeQS
-ATptJcOpMEwi8t9mYmuiWYYPwDm492NScK5AoUF0WVK42aG5BEz2Oz9LVtcXKquu
-17Zr6xcuKtgM71paCO3dxnlvef0HbFeHFmOTT6lqu1z2uQENBFmlsfgBCADfP4Se
-cL8GvCKgVWuoM1tOEaZ/eND4jc4RcYTRdEiZYHfGah8S+kNd21Zpep++FSvQbwb+
-PjdQRbCwn+dBdxgpMhrLfZ3zy3Xtd4EEftq0y8Gyi+6ejJjk8eW7Xvl91objJSyh
-J5Fx5v/K9bof9uCTLaWq/aFjcWpovsbbDWrq/OXowp8A69xMPAmJee8zW/Nj7Fv0
-sgQrIGNe3T4BWVncuuzP3YWxCB85ysk99l17joKrQx6w7FaG0e/n+gd1X0YRofYg
-eu2UCpswbwfu7pwiWnNtgCajhaw47Og/9FMpsXGvuQs93pOLon7jLlPn1nsOaX5h
-NkHfmyYabykXlpZBABEBAAGJATwEGAEIACYWIQQ4rKagJtJc3SJ9JIMvY5nc0iEh
-lQUCWaWx+AIbDAUJA8JnAAAKCRAvY5nc0iEhlaMBCADIwsJwRi9XqkxaldehThkx
-giQDp6M99J+quKLsevVRtDKi88tSWEhYRNKNjZLkmfQ8cKcR4eSDEIN9135RTK+w
-mYq+IWgKIAPaFeMGQmBm2vlKTSpR4cuNMUCCToXwq4vUr5e/jRg+TzTf7j2pH7hi
-HIQILaiU74g7KCcR2X8EUxG6Dus1Sk6zcvmnASBirw2M8bgarTBlr8GPpDUxnp7Q
-LilZfyClqM29IfDjGOa+9RvOqHeC4m3xW8pqjIEuKOQeMmSY4xX7B01rFgILqhH4
-+IzlxIwq3xx0kxUup0zNLUtzBg2y9W6KX+VwruO4jH3qG91m3l/+1y1jRnQrtVkf
-=hS12
+biA8bWFpbEBhbmRyZWFzYmF1bWFubi5jYz6JAVQEEwEIAD4CGwMFCwkIBwIGFQgJ
+CgsCBBYCAwECHgECF4AWIQQ4rKagJtJc3SJ9JIMvY5nc0iEhlQUCZTNyywUJDW70
+UwAKCRAvY5nc0iEhleAAB/9M1Evov4qadN3QrU5MT1ZrLYchf+8EZ2zkwZqrxrWR
+natt8bYAl2KGt7ADUC5OlT1g2VnKi0Wp6p8J2C4jnHr1+TnuNwMnUaU5YXuF5JHO
+XGzQCJCucBRRAcrxYlwHdPIQDsjJGw5F54UCaa6FlN8/mLTyzemdcH9uyiZOw1jx
+wiXzm/z49u+olic1al7MgZJ28ih20jSu21wVxCrZoPdXNXTqwoNvYJkzJo3aGfEF
+JAcASvNKOEAQRRDHHJpgp5WKvz7rmzJyyO/v6Emof1Dfi/dCsBaOwLmGH2DVK42o
+IVfr4jG6jZ0DbpA8oi+9aXIv2gBVgj6R/nHLIQ1JlH7YiQFUBBMBCAA+FiEEOKym
+oCbSXN0ifSSDL2OZ3NIhIZUFAlmlsfgCGwMFCQPCZwAFCwkIBwIGFQgJCgsCBBYC
+AwECHgECF4AACgkQL2OZ3NIhIZX5zAgA8yT7G8u/qwQxZrf0EfdvUohN+VKHfkPd
+WFmJQtt/xKNx8UZNNRgFJr+iJzfXGCaAmRHXFw2CT7SYR4zvw0lEQ1NsceYAXd4F
+myBSLE4lIq8qqg8niKKvqTFs0PSxt3kH3RnyHEbuYy3pu5P52jwkL8UqR3+jt2Hp
+MB2ap4Oot8g5sFKeQkjQ8Q6lex58FundNpB7wPt0Orp3QwFkBdF3T+8IJt5pTFSz
+ZE6g5mHkEgE6bSXDqTBMIvLfZmJrolmGD8A5uPdjUnCuQKFBdFlSuNmhuQRM9js/
+S1bXFyqrrte2a+sXLirYDO9aWgjt3cZ5b3n9B2xXhxZjk0+partc9okBVAQTAQgA
+PgIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgBYhBDispqAm0lzdIn0kgy9jmdzS
+ISGVBQJdS9cGBQkHaIwOAAoJEC9jmdzSISGVEAcH/RfoMGcAw4A4GnlwQO3cBXIb
+G6z06H/7gPuAwSwGETBCIh6D3rkpjSw7I8YqXsbpNzWloXOhRoX1jsy3a0Vy5rps
+e6dddBXcyJOPSvTgNw3uWU0FbXQHlqVlwJ/SWQq882aOZZFnXITkaxzYK3TZtqRJ
+p4vgszEHhtaycMfyeXQNmlWQY0SHXA9AVgxYecIvvxkxp1AZ4GrhHXR9KC40FcSY
+CDvXluc6Uuscnl2t2Elxbjl8fpeb2Ifjy34AIUHB8vPPaVqfDfne6MbthYG8gG+s
+92NQPlhYjUCPc/IbWD2IvNJObXbBna9jGYsEg0/rR0DzChkzNA5SxJXb6I8DX0e5
+AQ0EWaWx+AEIAN8/hJ5wvwa8IqBVa6gzW04Rpn940PiNzhFxhNF0SJlgd8ZqHxL6
+Q13bVml6n74VK9BvBv4+N1BFsLCf50F3GCkyGst9nfPLde13gQR+2rTLwbKL7p6M
+mOTx5bte+X3WhuMlLKEnkXHm/8r1uh/24JMtpar9oWNxami+xtsNaur85ejCnwDr
+3Ew8CYl57zNb82PsW/SyBCsgY17dPgFZWdy67M/dhbEIHznKyT32XXuOgqtDHrDs
+VobR7+f6B3VfRhGh9iB67ZQKmzBvB+7unCJac22AJqOFrDjs6D/0Uymxca+5Cz3e
+k4uifuMuU+fWew5pfmE2Qd+bJhpvKReWlkEAEQEAAYkBPAQYAQgAJgIbDBYhBDis
+pqAm0lzdIn0kgy9jmdzSISGVBQJlM3LABQkNbvRIAAoJEC9jmdzSISGV3VsH/2or
+KR4Dvf+KYmdjYRSJmN0qczO7x/IZx9WGCIUrKCj+11d8voDOGCPwleiPlDQ6UO0p
+TknWn9oH0xuJoRLhZCaxCb04p2x1Urbscb09NJA9opibs3g8lbX1Mjdg3ayeUDb3
+5EkpowtI4tyjkX+sqtBYbwxgqg0kGwtt38xhLutilCIxSD8q92Sm92DKePaEAgGi
+NqYf/QUfjWtwswo7B/vhIUNbCBIUk0oWtW9P3HfJ/nQfWyG+N7N9KEvrTXaJ2o0K
+pLo22OY6Cg3qbLvbCkQ0/H30bPRQo7dqm6tvWP7V/Qy6PZX7NOiphka4cRw3uI8W
+Q1qs4ogfoSGjc/IkYyc=
+=co6y
-----END PGP PUBLIC KEY BLOCK-----
diff --git a/static/hardware/imc-2001/chargen.rom b/static/hardware/imc-2001/chargen.rom
new file mode 100644
index 0000000..6c6fed2
--- /dev/null
+++ b/static/hardware/imc-2001/chargen.rom
Binary files differ
diff --git a/static/hardware/imc-2001/manual_imc_2001_2.01.pdf b/static/hardware/imc-2001/manual_imc_2001_2.01.pdf
new file mode 100644
index 0000000..80964a0
--- /dev/null
+++ b/static/hardware/imc-2001/manual_imc_2001_2.01.pdf
Binary files differ
diff --git a/static/images/blog/archlinux-macbook-a1211/macbook-A1211.jpg b/static/images/blog/archlinux-macbook-a1211/macbook-A1211.jpg
new file mode 100644
index 0000000..9e2c206
--- /dev/null
+++ b/static/images/blog/archlinux-macbook-a1211/macbook-A1211.jpg
Binary files differ
diff --git a/static/images/blog/bacula-lto4-backup/fitting.jpg b/static/images/blog/bacula-lto4-backup/fitting.jpg
new file mode 100644
index 0000000..f076c11
--- /dev/null
+++ b/static/images/blog/bacula-lto4-backup/fitting.jpg
Binary files differ
diff --git a/static/images/blog/bacula-lto4-backup/lto4.jpg b/static/images/blog/bacula-lto4-backup/lto4.jpg
new file mode 100644
index 0000000..bd9baf7
--- /dev/null
+++ b/static/images/blog/bacula-lto4-backup/lto4.jpg
Binary files differ
diff --git a/static/images/blog/mail-disaster/ibm.png b/static/images/blog/mail-disaster/ibm.png
new file mode 100644
index 0000000..70cb125
--- /dev/null
+++ b/static/images/blog/mail-disaster/ibm.png
Binary files differ
diff --git a/static/images/blog/mail-disaster/mail-disaster.png b/static/images/blog/mail-disaster/mail-disaster.png
new file mode 100644
index 0000000..a4190ab
--- /dev/null
+++ b/static/images/blog/mail-disaster/mail-disaster.png
Binary files differ
diff --git a/static/images/blog/mail-disaster/zy0_de.png b/static/images/blog/mail-disaster/zy0_de.png
new file mode 100644
index 0000000..8e218a5
--- /dev/null
+++ b/static/images/blog/mail-disaster/zy0_de.png
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-Apple-2.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-Apple-2.jpg
new file mode 100644
index 0000000..e68553d
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-Apple-2.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-FS4.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-FS4.jpg
new file mode 100644
index 0000000..6d5754c
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-FS4.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-IBM-5155.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-IBM-5155.jpg
new file mode 100644
index 0000000..f66bfab
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-IBM-5155.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDF-11.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDF-11.jpg
new file mode 100644
index 0000000..7ac7d15
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDF-11.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDP-11.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDP-11.jpg
new file mode 100644
index 0000000..7ac7d15
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-PDP-11.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-apple-games-book.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-apple-games-book.jpg
new file mode 100644
index 0000000..5de6c4a
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019-apple-games-book.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019.jpg
new file mode 100644
index 0000000..f66bfab
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2019/retro-computing-vintage-computer-festival-zurich-2019.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-BK-0010-01.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-BK-0010-01.jpg
new file mode 100644
index 0000000..c0d4add
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-BK-0010-01.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-agat.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-agat.jpg
new file mode 100644
index 0000000..315e293
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-agat.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-ceres3.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-ceres3.jpg
new file mode 100644
index 0000000..8c04eeb
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-ceres3.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-oberon-books.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-oberon-books.jpg
new file mode 100644
index 0000000..379cfff
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-oberon-books.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-olpc-xo-1.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-olpc-xo-1.jpg
new file mode 100644
index 0000000..b5ae239
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-olpc-xo-1.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-tektronix-4010.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-tektronix-4010.jpg
new file mode 100644
index 0000000..2931935
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021-tektronix-4010.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021.jpg
new file mode 100644
index 0000000..ccba1a4
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2021/retro-computing-vintage-computer-festival-zurich-2021.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-cpm-machines.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-cpm-machines.jpg
new file mode 100644
index 0000000..8c1ecfa
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-cpm-machines.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-electronics-teaching.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-electronics-teaching.jpg
new file mode 100644
index 0000000..8f257c5
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-electronics-teaching.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-front.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-front.jpg
new file mode 100644
index 0000000..4ad762e
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-front.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-harddisk.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-harddisk.jpg
new file mode 100644
index 0000000..f1414a2
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-lisa-harddisk.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-self-made.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-self-made.jpg
new file mode 100644
index 0000000..a7d29f3
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-self-made.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-smaky-100.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-smaky-100.jpg
new file mode 100644
index 0000000..975ffea
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2022/retro-computing-vintage-computer-festival-zurich-2022-smaky-100.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-acorns.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-acorns.jpg
new file mode 100644
index 0000000..5f71a09
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-acorns.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-ibm-convertible.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-ibm-convertible.jpg
new file mode 100644
index 0000000..37652c6
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-ibm-convertible.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-olpcs.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-olpcs.jpg
new file mode 100644
index 0000000..a86a12d
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-olpcs.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-others.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-others.jpg
new file mode 100644
index 0000000..806b1eb
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-others.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-portables.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-portables.jpg
new file mode 100644
index 0000000..4fe8140
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-portables.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpg
new file mode 100644
index 0000000..15f5d4a
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-scrib.jpg
Binary files differ
diff --git a/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-selnau1.jpg b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-selnau1.jpg
new file mode 100644
index 0000000..1c7ecca
--- /dev/null
+++ b/static/images/blog/retro-computing-vintage-computer-festival-zurich-2023/retro-computing-vintage-computer-festival-zurich-2023-selnau1.jpg
Binary files differ
diff --git a/static/images/github.svg b/static/images/github.svg
deleted file mode 100644
index 84c884b..0000000
--- a/static/images/github.svg
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" ?><svg enable-background="new 0 0 64 64" version="1.1" viewBox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="Layer_3"><g><g><path d="M32,0C14.327,0,0,14.327,0,32c0,17.673,14.327,32,32,32s32-14.327,32-32C64,14.327,49.673,0,32,0z" fill="#333333"/></g></g><g id="Outline_Filled"><path d="M38.592,50.166h-4.84h-4.844c0,0,0.014-2.874,0-4.844c-6.629,1.428-8.479-3.633-8.479-3.633 c-1.21-2.423-2.423-3.633-2.423-3.633c-2.423-1.438,0-1.21,0-1.21c2.423,0,3.633,2.423,3.633,2.423 c2.126,3.609,5.908,3.028,7.266,2.423c0-1.21,0.53-3.042,1.21-3.633c-5.29-0.595-9.693-3.633-9.693-9.689s1.216-7.266,2.427-8.479 c-0.244-0.597-1.259-2.805,0.037-6.056c0,0,2.38,0,4.803,3.633c1.2-1.2,4.844-1.21,6.056-1.21c1.208,0,4.854,0.01,6.054,1.21 c2.423-3.633,4.809-3.633,4.809-3.633c1.296,3.251,0.282,5.459,0.037,6.056c1.21,1.21,2.423,2.423,2.423,8.479 s-4.397,9.092-9.689,9.689c0.682,0.591,1.21,2.675,1.21,3.633L38.592,50.166L38.592,50.166z" fill="#FFFFFF" id="Cat_3_"/></g></g></svg> \ No newline at end of file
diff --git a/static/images/hardware/imc-2001/chargen.png b/static/images/hardware/imc-2001/chargen.png
new file mode 100644
index 0000000..4aa85ad
--- /dev/null
+++ b/static/images/hardware/imc-2001/chargen.png
Binary files differ
diff --git a/static/images/hardware/imc-2001/computer_full.jpg b/static/images/hardware/imc-2001/computer_full.jpg
new file mode 100644
index 0000000..00e48ac
--- /dev/null
+++ b/static/images/hardware/imc-2001/computer_full.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/cpm/README b/static/images/hardware/imc-2001/cpm/README
new file mode 100644
index 0000000..8c69856
--- /dev/null
+++ b/static/images/hardware/imc-2001/cpm/README
@@ -0,0 +1 @@
+APDOS: read apple disks
diff --git a/static/images/hardware/imc-2001/cpm/README.MBASIC b/static/images/hardware/imc-2001/cpm/README.MBASIC
new file mode 100644
index 0000000..6d69e8e
--- /dev/null
+++ b/static/images/hardware/imc-2001/cpm/README.MBASIC
@@ -0,0 +1 @@
+SYSTEM return to CP/M
diff --git a/static/images/hardware/imc-2001/cpm_40chars.jpg b/static/images/hardware/imc-2001/cpm_40chars.jpg
new file mode 100644
index 0000000..88517cf
--- /dev/null
+++ b/static/images/hardware/imc-2001/cpm_40chars.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/floppies/README b/static/images/hardware/imc-2001/floppies/README
new file mode 100644
index 0000000..0c4e584
--- /dev/null
+++ b/static/images/hardware/imc-2001/floppies/README
@@ -0,0 +1,12 @@
+40-track, single-sided, 256 bytes-per-sector
+35*256*16 = 143360
+
+We should have mostly 16 track ones. The 13 sector ones come
+from the old Apple ][s in the old Lyceum server room.
+
+links
+-----
+
+https://en.wikipedia.org/wiki/List_of_floppy_disk_formats
+http://cowlark.com/fluxengine/doc/disk-apple2.html
+
diff --git a/static/images/hardware/imc-2001/keyboard_cable.jpg b/static/images/hardware/imc-2001/keyboard_cable.jpg
new file mode 100644
index 0000000..d9f5d97
--- /dev/null
+++ b/static/images/hardware/imc-2001/keyboard_cable.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/keyboard_front.jpg b/static/images/hardware/imc-2001/keyboard_front.jpg
new file mode 100644
index 0000000..02c20d8
--- /dev/null
+++ b/static/images/hardware/imc-2001/keyboard_front.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/keyboard_pcb_controller_prom.jpg b/static/images/hardware/imc-2001/keyboard_pcb_controller_prom.jpg
new file mode 100644
index 0000000..967c7f2
--- /dev/null
+++ b/static/images/hardware/imc-2001/keyboard_pcb_controller_prom.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/manual_ascii_table.jpg b/static/images/hardware/imc-2001/manual_ascii_table.jpg
new file mode 100644
index 0000000..17e598e
--- /dev/null
+++ b/static/images/hardware/imc-2001/manual_ascii_table.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/manual_frontpage.jpg b/static/images/hardware/imc-2001/manual_frontpage.jpg
new file mode 100644
index 0000000..b575539
--- /dev/null
+++ b/static/images/hardware/imc-2001/manual_frontpage.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/motherboard_internal.jpg b/static/images/hardware/imc-2001/motherboard_internal.jpg
new file mode 100644
index 0000000..2d9153a
--- /dev/null
+++ b/static/images/hardware/imc-2001/motherboard_internal.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/new_psu.jpg b/static/images/hardware/imc-2001/new_psu.jpg
new file mode 100644
index 0000000..5187d4b
--- /dev/null
+++ b/static/images/hardware/imc-2001/new_psu.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/old_psu.jpg b/static/images/hardware/imc-2001/old_psu.jpg
new file mode 100644
index 0000000..f85483e
--- /dev/null
+++ b/static/images/hardware/imc-2001/old_psu.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/oscilloscope_serial_keyboard.jpg b/static/images/hardware/imc-2001/oscilloscope_serial_keyboard.jpg
new file mode 100644
index 0000000..26e96f9
--- /dev/null
+++ b/static/images/hardware/imc-2001/oscilloscope_serial_keyboard.jpg
Binary files differ
diff --git a/static/images/hardware/imc-2001/romboard.jpg b/static/images/hardware/imc-2001/romboard.jpg
new file mode 100644
index 0000000..55ad6d9
--- /dev/null
+++ b/static/images/hardware/imc-2001/romboard.jpg
Binary files differ
diff --git a/static/images/twitter.svg b/static/images/twitter.svg
deleted file mode 100644
index 069dad2..0000000
--- a/static/images/twitter.svg
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" ?><svg enable-background="new 0 0 32 32" version="1.1" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="Flat_copy"><g><path d="M16,0C7.163,0,0,7.163,0,16c0,8.836,7.163,16,16,16s16-7.164,16-16C32,7.163,24.837,0,16,0z" fill="#333333"/></g><path d="M18.226,8.886c-1.59,0.579-2.595,2.071-2.481,3.704l0.038,0.63l-0.636-0.077 c-2.315-0.296-4.338-1.299-6.056-2.984l-0.84-0.836L8.036,9.94c-0.458,1.376-0.165,2.83,0.789,3.808 c0.509,0.54,0.394,0.617-0.483,0.296c-0.305-0.103-0.573-0.18-0.598-0.141c-0.089,0.09,0.216,1.26,0.458,1.724 c0.331,0.644,1.005,1.273,1.743,1.647l0.624,0.296L9.83,17.581c-0.712,0-0.738,0.013-0.661,0.284 c0.254,0.836,1.259,1.724,2.379,2.11l0.789,0.27l-0.687,0.412c-1.018,0.593-2.214,0.927-3.41,0.951 c-0.573,0.013-1.044,0.064-1.044,0.103c0,0.128,1.553,0.848,2.455,1.132c2.71,0.836,5.929,0.475,8.346-0.952 c1.718-1.016,3.435-3.036,4.237-4.992c0.433-1.041,0.865-2.945,0.865-3.858c0-0.592,0.038-0.669,0.75-1.376 c0.42-0.412,0.814-0.862,0.891-0.99c0.128-0.245,0.114-0.245-0.534-0.026c-1.081,0.386-1.234,0.335-0.699-0.244 c0.394-0.412,0.865-1.158,0.865-1.376c0-0.038-0.191,0.026-0.407,0.141c-0.229,0.129-0.738,0.322-1.12,0.437l-0.687,0.219 L21.535,9.4c-0.344-0.231-0.826-0.489-1.081-0.566C19.804,8.654,18.812,8.68,18.226,8.886z" fill="#FFFFFF"/></g></svg> \ No newline at end of file
diff --git a/static/text/blog/archlinux-macbook-a1211/radeon_bios-5.7.6.c b/static/text/blog/archlinux-macbook-a1211/radeon_bios-5.7.6.c
new file mode 100644
index 0000000..45984b6
--- /dev/null
+++ b/static/text/blog/archlinux-macbook-a1211/radeon_bios-5.7.6.c
@@ -0,0 +1,759 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Dave Airlie
+ * Alex Deucher
+ * Jerome Glisse
+ */
+
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <drm/drm_device.h>
+
+#include <linux/firmware.h>
+
+#include "atom.h"
+#include "radeon.h"
+#include "radeon_reg.h"
+
+/*
+ * BIOS.
+ */
+
+/* If you boot an IGP board with a discrete card as the primary,
+ * the IGP rom is not accessible via the rom bar as the IGP rom is
+ * part of the system bios. On boot, the system bios puts a
+ * copy of the igp rom at the start of vram if a discrete card is
+ * present.
+ */
+static bool igp_read_bios_from_vram(struct radeon_device *rdev)
+{
+ uint8_t __iomem *bios;
+ resource_size_t vram_base;
+ resource_size_t size = 256 * 1024; /* ??? */
+
+ if (!(rdev->flags & RADEON_IS_IGP))
+ if (!radeon_card_posted(rdev))
+ return false;
+
+ rdev->bios = NULL;
+ vram_base = pci_resource_start(rdev->pdev, 0);
+ bios = ioremap(vram_base, size);
+ if (!bios) {
+ return false;
+ }
+
+ if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+ iounmap(bios);
+ return false;
+ }
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ iounmap(bios);
+ return false;
+ }
+ memcpy_fromio(rdev->bios, bios, size);
+ iounmap(bios);
+ return true;
+}
+
+static bool radeon_read_bios(struct radeon_device *rdev)
+{
+ uint8_t __iomem *bios, val1, val2;
+ size_t size;
+
+ rdev->bios = NULL;
+ /* XXX: some cards may return 0 for rom size? ddx has a workaround */
+ bios = pci_map_rom(rdev->pdev, &size);
+ if (!bios) {
+ return false;
+ }
+
+ val1 = readb(&bios[0]);
+ val2 = readb(&bios[1]);
+
+ if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
+ pci_unmap_rom(rdev->pdev, bios);
+ return false;
+ }
+ rdev->bios = kzalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ pci_unmap_rom(rdev->pdev, bios);
+ return false;
+ }
+ memcpy_fromio(rdev->bios, bios, size);
+ pci_unmap_rom(rdev->pdev, bios);
+ return true;
+}
+
+static bool radeon_read_platform_bios(struct radeon_device *rdev)
+{
+ phys_addr_t rom = rdev->pdev->rom;
+ size_t romlen = rdev->pdev->romlen;
+ void __iomem *bios;
+
+ rdev->bios = NULL;
+
+ if (!rom || romlen == 0)
+ return false;
+
+ rdev->bios = kzalloc(romlen, GFP_KERNEL);
+ if (!rdev->bios)
+ return false;
+
+ bios = ioremap(rom, romlen);
+ if (!bios)
+ goto free_bios;
+
+ memcpy_fromio(rdev->bios, bios, romlen);
+ iounmap(bios);
+
+ if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa)
+ goto free_bios;
+
+ return true;
+free_bios:
+ kfree(rdev->bios);
+ return false;
+}
+
+static bool radeon_read_bios_from_firmware(struct radeon_device *rdev)
+{
+ const uint8_t __iomem *bios;
+ resource_size_t size;
+ const struct firmware *fw = NULL;
+
+ request_firmware(&fw, "radeon/vbios.bin", rdev->dev);
+ if (!fw) {
+ DRM_ERROR("No bios\n");
+ return false;
+ }
+ size = fw->size;
+ bios = fw->data;
+
+ if (!bios) {
+ DRM_ERROR("No bios\n");
+ return false;
+ }
+
+ if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+ DRM_ERROR("wrong sig\n");
+ release_firmware(fw);
+ return false;
+ }
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ DRM_ERROR("alloc fail\n");
+ release_firmware(fw);
+ return false;
+ }
+ memcpy(rdev->bios, bios, size);
+ release_firmware(fw);
+ return true;
+}
+
+#ifdef CONFIG_ACPI
+/* ATRM is used to get the BIOS on the discrete cards in
+ * dual-gpu systems.
+ */
+/* retrieve the ROM in 4k blocks */
+#define ATRM_BIOS_PAGE 4096
+/**
+ * radeon_atrm_call - fetch a chunk of the vbios
+ *
+ * @atrm_handle: acpi ATRM handle
+ * @bios: vbios image pointer
+ * @offset: offset of vbios image data to fetch
+ * @len: length of vbios image data to fetch
+ *
+ * Executes ATRM to fetch a chunk of the discrete
+ * vbios image on PX systems (all asics).
+ * Returns the length of the buffer fetched.
+ */
+static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
+ int offset, int len)
+{
+ acpi_status status;
+ union acpi_object atrm_arg_elements[2], *obj;
+ struct acpi_object_list atrm_arg;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+ atrm_arg.count = 2;
+ atrm_arg.pointer = &atrm_arg_elements[0];
+
+ atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
+ atrm_arg_elements[0].integer.value = offset;
+
+ atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
+ atrm_arg_elements[1].integer.value = len;
+
+ status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
+ return -ENODEV;
+ }
+
+ obj = (union acpi_object *)buffer.pointer;
+ memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
+ len = obj->buffer.length;
+ kfree(buffer.pointer);
+ return len;
+}
+
+static bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+ int ret;
+ int size = 256 * 1024;
+ int i;
+ struct pci_dev *pdev = NULL;
+ acpi_handle dhandle, atrm_handle;
+ acpi_status status;
+ bool found = false;
+
+ /* ATRM is for the discrete card only */
+ if (rdev->flags & RADEON_IS_IGP)
+ return false;
+
+ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+ dhandle = ACPI_HANDLE(&pdev->dev);
+ if (!dhandle)
+ continue;
+
+ status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+ if (!ACPI_FAILURE(status)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
+ dhandle = ACPI_HANDLE(&pdev->dev);
+ if (!dhandle)
+ continue;
+
+ status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+ if (!ACPI_FAILURE(status)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ return false;
+
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (!rdev->bios) {
+ DRM_ERROR("Unable to allocate bios\n");
+ return false;
+ }
+
+ for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
+ ret = radeon_atrm_call(atrm_handle,
+ rdev->bios,
+ (i * ATRM_BIOS_PAGE),
+ ATRM_BIOS_PAGE);
+ if (ret < ATRM_BIOS_PAGE)
+ break;
+ }
+
+ if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+ kfree(rdev->bios);
+ return false;
+ }
+ return true;
+}
+#else
+static inline bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+ return false;
+}
+#endif
+
+static bool ni_read_disabled_bios(struct radeon_device *rdev)
+{
+ u32 bus_cntl;
+ u32 d1vga_control;
+ u32 d2vga_control;
+ u32 vga_render_control;
+ u32 rom_cntl;
+ bool r;
+
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ if (!ASIC_IS_NODCE(rdev)) {
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+ }
+ WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE);
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ if (!ASIC_IS_NODCE(rdev)) {
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ }
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ return r;
+}
+
+static bool r700_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t rom_cntl;
+ uint32_t cg_spll_func_cntl = 0;
+ uint32_t cg_spll_status;
+ bool r;
+
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ if (rdev->family == CHIP_RV730) {
+ cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL);
+
+ /* enable bypass mode */
+ WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl |
+ R600_SPLL_BYPASS_EN));
+
+ /* wait for SPLL_CHG_STATUS to change to 1 */
+ cg_spll_status = 0;
+ while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
+ cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
+
+ WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE));
+ } else
+ WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ if (rdev->family == CHIP_RV730) {
+ WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl);
+
+ /* wait for SPLL_CHG_STATUS to change to 1 */
+ cg_spll_status = 0;
+ while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
+ cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
+ }
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ return r;
+}
+
+static bool r600_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t rom_cntl;
+ uint32_t general_pwrmgt;
+ uint32_t low_vid_lower_gpio_cntl;
+ uint32_t medium_vid_lower_gpio_cntl;
+ uint32_t high_vid_lower_gpio_cntl;
+ uint32_t ctxsw_vid_lower_gpio_cntl;
+ uint32_t lower_gpio_enable;
+ bool r;
+
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+ general_pwrmgt = RREG32(R600_GENERAL_PWRMGT);
+ low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL);
+ medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL);
+ high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL);
+ ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL);
+ lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ WREG32(R600_ROM_CNTL,
+ ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) |
+ (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) |
+ R600_SCK_OVERWRITE));
+
+ WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS));
+ WREG32(R600_LOW_VID_LOWER_GPIO_CNTL,
+ (low_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL,
+ (medium_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL,
+ (high_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL,
+ (ctxsw_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ WREG32(R600_GENERAL_PWRMGT, general_pwrmgt);
+ WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl);
+ WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl);
+ WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl);
+ WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl);
+ WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable);
+ return r;
+}
+
+static bool avivo_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t seprom_cntl1;
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t gpiopad_a;
+ uint32_t gpiopad_en;
+ uint32_t gpiopad_mask;
+ bool r;
+
+ seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(RV370_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+ gpiopad_en = RREG32(RADEON_GPIOPAD_EN);
+ gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK);
+
+ WREG32(RADEON_SEPROM_CNTL1,
+ ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
+ (0xc << RADEON_SCK_PRESCALE_SHIFT)));
+ WREG32(RADEON_GPIOPAD_A, 0);
+ WREG32(RADEON_GPIOPAD_EN, 0);
+ WREG32(RADEON_GPIOPAD_MASK, 0);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+
+ /* enable the rom */
+ WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));
+
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(RV370_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(RADEON_GPIOPAD_A, gpiopad_a);
+ WREG32(RADEON_GPIOPAD_EN, gpiopad_en);
+ WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask);
+ return r;
+}
+
+static bool legacy_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t seprom_cntl1;
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t crtc_gen_cntl;
+ uint32_t crtc2_gen_cntl;
+ uint32_t crtc_ext_cntl;
+ uint32_t fp2_gen_cntl;
+ bool r;
+
+ seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ if (rdev->flags & RADEON_IS_PCIE)
+ bus_cntl = RREG32(RV370_BUS_CNTL);
+ else
+ bus_cntl = RREG32(RADEON_BUS_CNTL);
+ crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
+ crtc2_gen_cntl = 0;
+ crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+ fp2_gen_cntl = 0;
+
+ if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+ }
+
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+ }
+
+ WREG32(RADEON_SEPROM_CNTL1,
+ ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
+ (0xc << RADEON_SCK_PRESCALE_SHIFT)));
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+
+ /* enable the rom */
+ if (rdev->flags & RADEON_IS_PCIE)
+ WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));
+ else
+ WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+
+ /* Turn off mem requests and CRTC for both controllers */
+ WREG32(RADEON_CRTC_GEN_CNTL,
+ ((crtc_gen_cntl & ~RADEON_CRTC_EN) |
+ (RADEON_CRTC_DISP_REQ_EN_B |
+ RADEON_CRTC_EXT_DISP_EN)));
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ WREG32(RADEON_CRTC2_GEN_CNTL,
+ ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) |
+ RADEON_CRTC2_DISP_REQ_EN_B));
+ }
+ /* Turn off CRTC */
+ WREG32(RADEON_CRTC_EXT_CNTL,
+ ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) |
+ (RADEON_CRTC_SYNC_TRISTAT |
+ RADEON_CRTC_DISPLAY_DIS)));
+
+ if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON));
+ }
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ if (rdev->flags & RADEON_IS_PCIE)
+ WREG32(RV370_BUS_CNTL, bus_cntl);
+ else
+ WREG32(RADEON_BUS_CNTL, bus_cntl);
+ WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+ }
+ WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+ if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+ }
+ return r;
+}
+
+static bool radeon_read_disabled_bios(struct radeon_device *rdev)
+{
+ if (rdev->flags & RADEON_IS_IGP)
+ return igp_read_bios_from_vram(rdev);
+ else if (rdev->family >= CHIP_BARTS)
+ return ni_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_RV770)
+ return r700_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_R600)
+ return r600_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_RS600)
+ return avivo_read_disabled_bios(rdev);
+ else
+ return legacy_read_disabled_bios(rdev);
+}
+
+#ifdef CONFIG_ACPI
+static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+ struct acpi_table_header *hdr;
+ acpi_size tbl_size;
+ UEFI_ACPI_VFCT *vfct;
+ unsigned offset;
+
+ if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
+ return false;
+ tbl_size = hdr->length;
+ if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
+ DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
+ return false;
+ }
+
+ vfct = (UEFI_ACPI_VFCT *)hdr;
+ offset = vfct->VBIOSImageOffset;
+
+ while (offset < tbl_size) {
+ GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
+ VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
+
+ offset += sizeof(VFCT_IMAGE_HEADER);
+ if (offset > tbl_size) {
+ DRM_ERROR("ACPI VFCT image header truncated\n");
+ return false;
+ }
+
+ offset += vhdr->ImageLength;
+ if (offset > tbl_size) {
+ DRM_ERROR("ACPI VFCT image truncated\n");
+ return false;
+ }
+
+ if (vhdr->ImageLength &&
+ vhdr->PCIBus == rdev->pdev->bus->number &&
+ vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) &&
+ vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) &&
+ vhdr->VendorID == rdev->pdev->vendor &&
+ vhdr->DeviceID == rdev->pdev->device) {
+ rdev->bios = kmemdup(&vbios->VbiosContent,
+ vhdr->ImageLength,
+ GFP_KERNEL);
+
+ if (!rdev->bios)
+ return false;
+ return true;
+ }
+ }
+
+ DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
+ return false;
+}
+#else
+static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+ return false;
+}
+#endif
+
+bool radeon_get_bios(struct radeon_device *rdev)
+{
+ bool r;
+ uint16_t tmp;
+
+ r = radeon_atrm_get_bios(rdev);
+ if (!r)
+ r = radeon_acpi_vfct_bios(rdev);
+ if (!r)
+ r = igp_read_bios_from_vram(rdev);
+ if (!r)
+ r = radeon_read_bios(rdev);
+ if (!r)
+ r = radeon_read_disabled_bios(rdev);
+ if (!r)
+ r = radeon_read_platform_bios(rdev);
+ if (!r)
+ r = radeon_read_bios_from_firmware(rdev);
+
+ if (!r || rdev->bios == NULL) {
+ DRM_ERROR("Unable to locate a BIOS ROM\n");
+ rdev->bios = NULL;
+ return false;
+ }
+ if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+ printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]);
+ goto free_bios;
+ }
+
+ tmp = RBIOS16(0x18);
+ if (RBIOS8(tmp + 0x14) != 0x0) {
+ DRM_INFO("Not an x86 BIOS ROM, not using.\n");
+ goto free_bios;
+ }
+
+ rdev->bios_header_start = RBIOS16(0x48);
+ if (!rdev->bios_header_start) {
+ goto free_bios;
+ }
+ tmp = rdev->bios_header_start + 4;
+ if (!memcmp(rdev->bios + tmp, "ATOM", 4) ||
+ !memcmp(rdev->bios + tmp, "MOTA", 4)) {
+ rdev->is_atom_bios = true;
+ } else {
+ rdev->is_atom_bios = false;
+ }
+
+ DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM");
+ return true;
+free_bios:
+ kfree(rdev->bios);
+ rdev->bios = NULL;
+ return false;
+}
diff --git a/static/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c b/static/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c
new file mode 100644
index 0000000..b7c099a
--- /dev/null
+++ b/static/text/blog/archlinux-macbook-a1211/radeon_bios-6.3.8.c
@@ -0,0 +1,764 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Dave Airlie
+ * Alex Deucher
+ * Jerome Glisse
+ */
+
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <drm/drm_device.h>
+
+#include <linux/firmware.h>
+
+#include "atom.h"
+#include "radeon.h"
+#include "radeon_reg.h"
+
+/*
+ * BIOS.
+ */
+
+/* If you boot an IGP board with a discrete card as the primary,
+ * the IGP rom is not accessible via the rom bar as the IGP rom is
+ * part of the system bios. On boot, the system bios puts a
+ * copy of the igp rom at the start of vram if a discrete card is
+ * present.
+ */
+static bool igp_read_bios_from_vram(struct radeon_device *rdev)
+{
+ uint8_t __iomem *bios;
+ resource_size_t vram_base;
+ resource_size_t size = 256 * 1024; /* ??? */
+
+ if (!(rdev->flags & RADEON_IS_IGP))
+ if (!radeon_card_posted(rdev))
+ return false;
+
+ rdev->bios = NULL;
+ vram_base = pci_resource_start(rdev->pdev, 0);
+ bios = ioremap(vram_base, size);
+ if (!bios) {
+ return false;
+ }
+
+ if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+ iounmap(bios);
+ return false;
+ }
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ iounmap(bios);
+ return false;
+ }
+ memcpy_fromio(rdev->bios, bios, size);
+ iounmap(bios);
+ return true;
+}
+
+static bool radeon_read_bios(struct radeon_device *rdev)
+{
+ uint8_t __iomem *bios, val1, val2;
+ size_t size;
+
+ rdev->bios = NULL;
+ /* XXX: some cards may return 0 for rom size? ddx has a workaround */
+ bios = pci_map_rom(rdev->pdev, &size);
+ if (!bios) {
+ return false;
+ }
+
+ val1 = readb(&bios[0]);
+ val2 = readb(&bios[1]);
+
+ if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
+ pci_unmap_rom(rdev->pdev, bios);
+ return false;
+ }
+ rdev->bios = kzalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ pci_unmap_rom(rdev->pdev, bios);
+ return false;
+ }
+ memcpy_fromio(rdev->bios, bios, size);
+ pci_unmap_rom(rdev->pdev, bios);
+ return true;
+}
+
+static bool radeon_read_platform_bios(struct radeon_device *rdev)
+{
+ phys_addr_t rom = rdev->pdev->rom;
+ size_t romlen = rdev->pdev->romlen;
+ void __iomem *bios;
+
+ rdev->bios = NULL;
+
+ if (!rom || romlen == 0)
+ return false;
+
+ rdev->bios = kzalloc(romlen, GFP_KERNEL);
+ if (!rdev->bios)
+ return false;
+
+ bios = ioremap(rom, romlen);
+ if (!bios)
+ goto free_bios;
+
+ memcpy_fromio(rdev->bios, bios, romlen);
+ iounmap(bios);
+
+ if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa)
+ goto free_bios;
+
+ return true;
+free_bios:
+ kfree(rdev->bios);
+ return false;
+}
+
+static bool radeon_read_bios_from_firmware(struct radeon_device *rdev)
+{
+ const uint8_t __iomem *bios;
+ resource_size_t size;
+ const struct firmware *fw = NULL;
+
+ request_firmware(&fw, "radeon/vbios.bin", rdev->dev);
+ if (!fw) {
+ DRM_ERROR("No bios\n");
+ return false;
+ }
+ size = fw->size;
+ bios = fw->data;
+
+ if (!bios) {
+ DRM_ERROR("No bios\n");
+ return false;
+ }
+
+ if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+ DRM_ERROR("wrong sig\n");
+ release_firmware(fw);
+ return false;
+ }
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ DRM_ERROR("alloc fail\n");
+ release_firmware(fw);
+ return false;
+ }
+ memcpy(rdev->bios, bios, size);
+ release_firmware(fw);
+ return true;
+}
+
+#ifdef CONFIG_ACPI
+/* ATRM is used to get the BIOS on the discrete cards in
+ * dual-gpu systems.
+ */
+/* retrieve the ROM in 4k blocks */
+#define ATRM_BIOS_PAGE 4096
+/**
+ * radeon_atrm_call - fetch a chunk of the vbios
+ *
+ * @atrm_handle: acpi ATRM handle
+ * @bios: vbios image pointer
+ * @offset: offset of vbios image data to fetch
+ * @len: length of vbios image data to fetch
+ *
+ * Executes ATRM to fetch a chunk of the discrete
+ * vbios image on PX systems (all asics).
+ * Returns the length of the buffer fetched.
+ */
+static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
+ int offset, int len)
+{
+ acpi_status status;
+ union acpi_object atrm_arg_elements[2], *obj;
+ struct acpi_object_list atrm_arg;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+ atrm_arg.count = 2;
+ atrm_arg.pointer = &atrm_arg_elements[0];
+
+ atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
+ atrm_arg_elements[0].integer.value = offset;
+
+ atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
+ atrm_arg_elements[1].integer.value = len;
+
+ status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
+ return -ENODEV;
+ }
+
+ obj = (union acpi_object *)buffer.pointer;
+ memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
+ len = obj->buffer.length;
+ kfree(buffer.pointer);
+ return len;
+}
+
+static bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+ int ret;
+ int size = 256 * 1024;
+ int i;
+ struct pci_dev *pdev = NULL;
+ acpi_handle dhandle, atrm_handle;
+ acpi_status status;
+ bool found = false;
+
+ /* ATRM is for the discrete card only */
+ if (rdev->flags & RADEON_IS_IGP)
+ return false;
+
+ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+ dhandle = ACPI_HANDLE(&pdev->dev);
+ if (!dhandle)
+ continue;
+
+ status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+ if (ACPI_SUCCESS(status)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
+ dhandle = ACPI_HANDLE(&pdev->dev);
+ if (!dhandle)
+ continue;
+
+ status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+ if (ACPI_SUCCESS(status)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ return false;
+ pci_dev_put(pdev);
+
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (!rdev->bios) {
+ DRM_ERROR("Unable to allocate bios\n");
+ return false;
+ }
+
+ for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
+ ret = radeon_atrm_call(atrm_handle,
+ rdev->bios,
+ (i * ATRM_BIOS_PAGE),
+ ATRM_BIOS_PAGE);
+ if (ret < ATRM_BIOS_PAGE)
+ break;
+ }
+
+ if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+ kfree(rdev->bios);
+ return false;
+ }
+ return true;
+}
+#else
+static inline bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+ return false;
+}
+#endif
+
+static bool ni_read_disabled_bios(struct radeon_device *rdev)
+{
+ u32 bus_cntl;
+ u32 d1vga_control;
+ u32 d2vga_control;
+ u32 vga_render_control;
+ u32 rom_cntl;
+ bool r;
+
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ if (!ASIC_IS_NODCE(rdev)) {
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+ }
+ WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE);
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ if (!ASIC_IS_NODCE(rdev)) {
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ }
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ return r;
+}
+
+static bool r700_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t rom_cntl;
+ uint32_t cg_spll_func_cntl = 0;
+ uint32_t cg_spll_status;
+ bool r;
+
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ if (rdev->family == CHIP_RV730) {
+ cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL);
+
+ /* enable bypass mode */
+ WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl |
+ R600_SPLL_BYPASS_EN));
+
+ /* wait for SPLL_CHG_STATUS to change to 1 */
+ cg_spll_status = 0;
+ while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
+ cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
+
+ WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE));
+ } else
+ WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ if (rdev->family == CHIP_RV730) {
+ WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl);
+
+ /* wait for SPLL_CHG_STATUS to change to 1 */
+ cg_spll_status = 0;
+ while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
+ cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
+ }
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ return r;
+}
+
+static bool r600_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t rom_cntl;
+ uint32_t general_pwrmgt;
+ uint32_t low_vid_lower_gpio_cntl;
+ uint32_t medium_vid_lower_gpio_cntl;
+ uint32_t high_vid_lower_gpio_cntl;
+ uint32_t ctxsw_vid_lower_gpio_cntl;
+ uint32_t lower_gpio_enable;
+ bool r;
+
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+ general_pwrmgt = RREG32(R600_GENERAL_PWRMGT);
+ low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL);
+ medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL);
+ high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL);
+ ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL);
+ lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ WREG32(R600_ROM_CNTL,
+ ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) |
+ (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) |
+ R600_SCK_OVERWRITE));
+
+ WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS));
+ WREG32(R600_LOW_VID_LOWER_GPIO_CNTL,
+ (low_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL,
+ (medium_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL,
+ (high_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL,
+ (ctxsw_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ WREG32(R600_GENERAL_PWRMGT, general_pwrmgt);
+ WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl);
+ WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl);
+ WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl);
+ WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl);
+ WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable);
+ return r;
+}
+
+static bool avivo_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t seprom_cntl1;
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t gpiopad_a;
+ uint32_t gpiopad_en;
+ uint32_t gpiopad_mask;
+ bool r;
+
+ seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(RV370_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+ gpiopad_en = RREG32(RADEON_GPIOPAD_EN);
+ gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK);
+
+ WREG32(RADEON_SEPROM_CNTL1,
+ ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
+ (0xc << RADEON_SCK_PRESCALE_SHIFT)));
+ WREG32(RADEON_GPIOPAD_A, 0);
+ WREG32(RADEON_GPIOPAD_EN, 0);
+ WREG32(RADEON_GPIOPAD_MASK, 0);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+
+ /* enable the rom */
+ WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));
+
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(RV370_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(RADEON_GPIOPAD_A, gpiopad_a);
+ WREG32(RADEON_GPIOPAD_EN, gpiopad_en);
+ WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask);
+ return r;
+}
+
+static bool legacy_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t seprom_cntl1;
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t crtc_gen_cntl;
+ uint32_t crtc2_gen_cntl;
+ uint32_t crtc_ext_cntl;
+ uint32_t fp2_gen_cntl;
+ bool r;
+
+ seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ if (rdev->flags & RADEON_IS_PCIE)
+ bus_cntl = RREG32(RV370_BUS_CNTL);
+ else
+ bus_cntl = RREG32(RADEON_BUS_CNTL);
+ crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
+ crtc2_gen_cntl = 0;
+ crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+ fp2_gen_cntl = 0;
+
+ if (rdev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+ }
+
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+ }
+
+ WREG32(RADEON_SEPROM_CNTL1,
+ ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
+ (0xc << RADEON_SCK_PRESCALE_SHIFT)));
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+
+ /* enable the rom */
+ if (rdev->flags & RADEON_IS_PCIE)
+ WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));
+ else
+ WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+
+ /* Turn off mem requests and CRTC for both controllers */
+ WREG32(RADEON_CRTC_GEN_CNTL,
+ ((crtc_gen_cntl & ~RADEON_CRTC_EN) |
+ (RADEON_CRTC_DISP_REQ_EN_B |
+ RADEON_CRTC_EXT_DISP_EN)));
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ WREG32(RADEON_CRTC2_GEN_CNTL,
+ ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) |
+ RADEON_CRTC2_DISP_REQ_EN_B));
+ }
+ /* Turn off CRTC */
+ WREG32(RADEON_CRTC_EXT_CNTL,
+ ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) |
+ (RADEON_CRTC_SYNC_TRISTAT |
+ RADEON_CRTC_DISPLAY_DIS)));
+
+ if (rdev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON));
+ }
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ if (rdev->flags & RADEON_IS_PCIE)
+ WREG32(RV370_BUS_CNTL, bus_cntl);
+ else
+ WREG32(RADEON_BUS_CNTL, bus_cntl);
+ WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+ }
+ WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+ if (rdev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+ }
+ return r;
+}
+
+static bool radeon_read_disabled_bios(struct radeon_device *rdev)
+{
+ if (rdev->flags & RADEON_IS_IGP)
+ return igp_read_bios_from_vram(rdev);
+ else if (rdev->family >= CHIP_BARTS)
+ return ni_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_RV770)
+ return r700_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_R600)
+ return r600_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_RS600)
+ return avivo_read_disabled_bios(rdev);
+ else
+ return legacy_read_disabled_bios(rdev);
+}
+
+#ifdef CONFIG_ACPI
+static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+ struct acpi_table_header *hdr;
+ acpi_size tbl_size;
+ UEFI_ACPI_VFCT *vfct;
+ unsigned offset;
+ bool r = false;
+
+ if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
+ return false;
+ tbl_size = hdr->length;
+ if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
+ DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
+ goto out;
+ }
+
+ vfct = (UEFI_ACPI_VFCT *)hdr;
+ offset = vfct->VBIOSImageOffset;
+
+ while (offset < tbl_size) {
+ GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
+ VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
+
+ offset += sizeof(VFCT_IMAGE_HEADER);
+ if (offset > tbl_size) {
+ DRM_ERROR("ACPI VFCT image header truncated\n");
+ goto out;
+ }
+
+ offset += vhdr->ImageLength;
+ if (offset > tbl_size) {
+ DRM_ERROR("ACPI VFCT image truncated\n");
+ goto out;
+ }
+
+ if (vhdr->ImageLength &&
+ vhdr->PCIBus == rdev->pdev->bus->number &&
+ vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) &&
+ vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) &&
+ vhdr->VendorID == rdev->pdev->vendor &&
+ vhdr->DeviceID == rdev->pdev->device) {
+ rdev->bios = kmemdup(&vbios->VbiosContent,
+ vhdr->ImageLength,
+ GFP_KERNEL);
+ if (rdev->bios)
+ r = true;
+
+ goto out;
+ }
+ }
+
+ DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
+
+out:
+ acpi_put_table(hdr);
+ return r;
+}
+#else
+static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+ return false;
+}
+#endif
+
+bool radeon_get_bios(struct radeon_device *rdev)
+{
+ bool r;
+ uint16_t tmp;
+
+ r = radeon_atrm_get_bios(rdev);
+ if (!r)
+ r = radeon_acpi_vfct_bios(rdev);
+ if (!r)
+ r = igp_read_bios_from_vram(rdev);
+ if (!r)
+ r = radeon_read_bios(rdev);
+ if (!r)
+ r = radeon_read_disabled_bios(rdev);
+ if (!r)
+ r = radeon_read_platform_bios(rdev);
+ if (!r)
+ r = radeon_read_bios_from_firmware(rdev);
+
+ if (!r || rdev->bios == NULL) {
+ DRM_ERROR("Unable to locate a BIOS ROM\n");
+ rdev->bios = NULL;
+ return false;
+ }
+ if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+ printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]);
+ goto free_bios;
+ }
+
+ tmp = RBIOS16(0x18);
+ if (RBIOS8(tmp + 0x14) != 0x0) {
+ DRM_INFO("Not an x86 BIOS ROM, not using.\n");
+ goto free_bios;
+ }
+
+ rdev->bios_header_start = RBIOS16(0x48);
+ if (!rdev->bios_header_start) {
+ goto free_bios;
+ }
+ tmp = rdev->bios_header_start + 4;
+ if (!memcmp(rdev->bios + tmp, "ATOM", 4) ||
+ !memcmp(rdev->bios + tmp, "MOTA", 4)) {
+ rdev->is_atom_bios = true;
+ } else {
+ rdev->is_atom_bios = false;
+ }
+
+ DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM");
+ return true;
+free_bios:
+ kfree(rdev->bios);
+ rdev->bios = NULL;
+ return false;
+}
diff --git a/static/text/blog/archlinux-macbook-a1211/radeon_bios.c b/static/text/blog/archlinux-macbook-a1211/radeon_bios.c
new file mode 100644
index 0000000..e7b7c42
--- /dev/null
+++ b/static/text/blog/archlinux-macbook-a1211/radeon_bios.c
@@ -0,0 +1,749 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Dave Airlie
+ * Alex Deucher
+ * Jerome Glisse
+ */
+#include <drm/drmP.h>
+#include "radeon_reg.h"
+#include "radeon.h"
+#include "atom.h"
+
+#include <linux/slab.h>
+#include <linux/acpi.h>
+
+#include <linux/firmware.h>
+
+/*
+ * BIOS.
+ */
+
+/* If you boot an IGP board with a discrete card as the primary,
+ * the IGP rom is not accessible via the rom bar as the IGP rom is
+ * part of the system bios. On boot, the system bios puts a
+ * copy of the igp rom at the start of vram if a discrete card is
+ * present.
+ */
+static bool igp_read_bios_from_vram(struct radeon_device *rdev)
+{
+ uint8_t __iomem *bios;
+ resource_size_t vram_base;
+ resource_size_t size = 256 * 1024; /* ??? */
+
+ if (!(rdev->flags & RADEON_IS_IGP))
+ if (!radeon_card_posted(rdev))
+ return false;
+
+ rdev->bios = NULL;
+ vram_base = pci_resource_start(rdev->pdev, 0);
+ bios = ioremap(vram_base, size);
+ if (!bios) {
+ DRM_ERROR("No BIOS\n");
+ return false;
+ }
+
+ if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+ iounmap(bios);
+ return false;
+ }
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ DRM_ERROR("alloc fail\n");
+ iounmap(bios);
+ return false;
+ }
+ memcpy_fromio(rdev->bios, bios, size);
+ iounmap(bios);
+ return true;
+}
+
+static bool radeon_read_bios_from_firmware(struct radeon_device *rdev)
+{
+ const uint8_t __iomem *bios;
+ resource_size_t size;
+ const struct firmware *fw = NULL;
+
+ request_firmware(&fw, "radeon/vbios.bin", rdev->dev);
+ if (!fw) {
+ DRM_ERROR("No bios\n");
+ return false;
+ }
+ size = fw->size;
+ bios = fw->data;
+
+ if (!bios) {
+ DRM_ERROR("No bios\n");
+ return false;
+ }
+
+ if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+ DRM_ERROR("wrong sig\n");
+ release_firmware(fw);
+ return false;
+ }
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ DRM_ERROR("alloc fail\n");
+ release_firmware(fw);
+ return false;
+ }
+ memcpy(rdev->bios, bios, size);
+ release_firmware(fw);
+ return true;
+}
+
+static bool radeon_read_bios(struct radeon_device *rdev)
+{
+ uint8_t __iomem *bios, val1, val2;
+ size_t size;
+
+ rdev->bios = NULL;
+ /* XXX: some cards may return 0 for rom size? ddx has a workaround */
+ bios = pci_map_rom(rdev->pdev, &size);
+ if (!bios) {
+ return false;
+ }
+
+ val1 = readb(&bios[0]);
+ val2 = readb(&bios[1]);
+
+ if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
+ pci_unmap_rom(rdev->pdev, bios);
+ return false;
+ }
+ rdev->bios = kzalloc(size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ pci_unmap_rom(rdev->pdev, bios);
+ return false;
+ }
+ memcpy_fromio(rdev->bios, bios, size);
+ pci_unmap_rom(rdev->pdev, bios);
+ return true;
+}
+
+static bool radeon_read_platform_bios(struct radeon_device *rdev)
+{
+ uint8_t __iomem *bios;
+ size_t size;
+
+ rdev->bios = NULL;
+
+ bios = pci_platform_rom(rdev->pdev, &size);
+ if (!bios) {
+ return false;
+ }
+
+ if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+ return false;
+ }
+ rdev->bios = kmemdup(bios, size, GFP_KERNEL);
+ if (rdev->bios == NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+#ifdef CONFIG_ACPI
+/* ATRM is used to get the BIOS on the discrete cards in
+ * dual-gpu systems.
+ */
+/* retrieve the ROM in 4k blocks */
+#define ATRM_BIOS_PAGE 4096
+/**
+ * radeon_atrm_call - fetch a chunk of the vbios
+ *
+ * @atrm_handle: acpi ATRM handle
+ * @bios: vbios image pointer
+ * @offset: offset of vbios image data to fetch
+ * @len: length of vbios image data to fetch
+ *
+ * Executes ATRM to fetch a chunk of the discrete
+ * vbios image on PX systems (all asics).
+ * Returns the length of the buffer fetched.
+ */
+static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
+ int offset, int len)
+{
+ acpi_status status;
+ union acpi_object atrm_arg_elements[2], *obj;
+ struct acpi_object_list atrm_arg;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+ atrm_arg.count = 2;
+ atrm_arg.pointer = &atrm_arg_elements[0];
+
+ atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
+ atrm_arg_elements[0].integer.value = offset;
+
+ atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
+ atrm_arg_elements[1].integer.value = len;
+
+ status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
+ return -ENODEV;
+ }
+
+ obj = (union acpi_object *)buffer.pointer;
+ memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
+ len = obj->buffer.length;
+ kfree(buffer.pointer);
+ return len;
+}
+
+static bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+ int ret;
+ int size = 256 * 1024;
+ int i;
+ struct pci_dev *pdev = NULL;
+ acpi_handle dhandle, atrm_handle;
+ acpi_status status;
+ bool found = false;
+
+ /* ATRM is for the discrete card only */
+ if (rdev->flags & RADEON_IS_IGP)
+ return false;
+
+ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+ dhandle = ACPI_HANDLE(&pdev->dev);
+ if (!dhandle)
+ continue;
+
+ status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+ if (!ACPI_FAILURE(status)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
+ dhandle = ACPI_HANDLE(&pdev->dev);
+ if (!dhandle)
+ continue;
+
+ status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+ if (!ACPI_FAILURE(status)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ return false;
+
+ rdev->bios = kmalloc(size, GFP_KERNEL);
+ if (!rdev->bios) {
+ DRM_ERROR("Unable to allocate bios\n");
+ return false;
+ }
+
+ for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
+ ret = radeon_atrm_call(atrm_handle,
+ rdev->bios,
+ (i * ATRM_BIOS_PAGE),
+ ATRM_BIOS_PAGE);
+ if (ret < ATRM_BIOS_PAGE)
+ break;
+ }
+
+ if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+ kfree(rdev->bios);
+ return false;
+ }
+ return true;
+}
+#else
+static inline bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+ return false;
+}
+#endif
+
+static bool ni_read_disabled_bios(struct radeon_device *rdev)
+{
+ u32 bus_cntl;
+ u32 d1vga_control;
+ u32 d2vga_control;
+ u32 vga_render_control;
+ u32 rom_cntl;
+ bool r;
+
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ if (!ASIC_IS_NODCE(rdev)) {
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+ }
+ WREG32(R600_ROM_CNTL, rom_cntl | R600_SCK_OVERWRITE);
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ if (!ASIC_IS_NODCE(rdev)) {
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ }
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ return r;
+}
+
+static bool r700_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t rom_cntl;
+ uint32_t cg_spll_func_cntl = 0;
+ uint32_t cg_spll_status;
+ bool r;
+
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ if (rdev->family == CHIP_RV730) {
+ cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL);
+
+ /* enable bypass mode */
+ WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl |
+ R600_SPLL_BYPASS_EN));
+
+ /* wait for SPLL_CHG_STATUS to change to 1 */
+ cg_spll_status = 0;
+ while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
+ cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
+
+ WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE));
+ } else
+ WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ if (rdev->family == CHIP_RV730) {
+ WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl);
+
+ /* wait for SPLL_CHG_STATUS to change to 1 */
+ cg_spll_status = 0;
+ while (!(cg_spll_status & R600_SPLL_CHG_STATUS))
+ cg_spll_status = RREG32(R600_CG_SPLL_STATUS);
+ }
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ return r;
+}
+
+static bool r600_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t rom_cntl;
+ uint32_t general_pwrmgt;
+ uint32_t low_vid_lower_gpio_cntl;
+ uint32_t medium_vid_lower_gpio_cntl;
+ uint32_t high_vid_lower_gpio_cntl;
+ uint32_t ctxsw_vid_lower_gpio_cntl;
+ uint32_t lower_gpio_enable;
+ bool r;
+
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(R600_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ rom_cntl = RREG32(R600_ROM_CNTL);
+ general_pwrmgt = RREG32(R600_GENERAL_PWRMGT);
+ low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL);
+ medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL);
+ high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL);
+ ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL);
+ lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+ /* enable the rom */
+ WREG32(R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ WREG32(R600_ROM_CNTL,
+ ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) |
+ (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) |
+ R600_SCK_OVERWRITE));
+
+ WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS));
+ WREG32(R600_LOW_VID_LOWER_GPIO_CNTL,
+ (low_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL,
+ (medium_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL,
+ (high_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL,
+ (ctxsw_vid_lower_gpio_cntl & ~0x400));
+ WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(R600_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(R600_ROM_CNTL, rom_cntl);
+ WREG32(R600_GENERAL_PWRMGT, general_pwrmgt);
+ WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl);
+ WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl);
+ WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl);
+ WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl);
+ WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable);
+ return r;
+}
+
+static bool avivo_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t seprom_cntl1;
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t d1vga_control;
+ uint32_t d2vga_control;
+ uint32_t vga_render_control;
+ uint32_t gpiopad_a;
+ uint32_t gpiopad_en;
+ uint32_t gpiopad_mask;
+ bool r;
+
+ seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ bus_cntl = RREG32(RV370_BUS_CNTL);
+ d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);
+ d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);
+ vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL);
+ gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+ gpiopad_en = RREG32(RADEON_GPIOPAD_EN);
+ gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK);
+
+ WREG32(RADEON_SEPROM_CNTL1,
+ ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
+ (0xc << RADEON_SCK_PRESCALE_SHIFT)));
+ WREG32(RADEON_GPIOPAD_A, 0);
+ WREG32(RADEON_GPIOPAD_EN, 0);
+ WREG32(RADEON_GPIOPAD_MASK, 0);
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+
+ /* enable the rom */
+ WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));
+
+ /* Disable VGA mode */
+ WREG32(AVIVO_D1VGA_CONTROL,
+ (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_D2VGA_CONTROL,
+ (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE |
+ AVIVO_DVGA_CONTROL_TIMING_SELECT)));
+ WREG32(AVIVO_VGA_RENDER_CONTROL,
+ (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ WREG32(RV370_BUS_CNTL, bus_cntl);
+ WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);
+ WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);
+ WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control);
+ WREG32(RADEON_GPIOPAD_A, gpiopad_a);
+ WREG32(RADEON_GPIOPAD_EN, gpiopad_en);
+ WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask);
+ return r;
+}
+
+static bool legacy_read_disabled_bios(struct radeon_device *rdev)
+{
+ uint32_t seprom_cntl1;
+ uint32_t viph_control;
+ uint32_t bus_cntl;
+ uint32_t crtc_gen_cntl;
+ uint32_t crtc2_gen_cntl;
+ uint32_t crtc_ext_cntl;
+ uint32_t fp2_gen_cntl;
+ bool r;
+
+ seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);
+ viph_control = RREG32(RADEON_VIPH_CONTROL);
+ if (rdev->flags & RADEON_IS_PCIE)
+ bus_cntl = RREG32(RV370_BUS_CNTL);
+ else
+ bus_cntl = RREG32(RADEON_BUS_CNTL);
+ crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);
+ crtc2_gen_cntl = 0;
+ crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+ fp2_gen_cntl = 0;
+
+ if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+ }
+
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+ }
+
+ WREG32(RADEON_SEPROM_CNTL1,
+ ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) |
+ (0xc << RADEON_SCK_PRESCALE_SHIFT)));
+
+ /* disable VIP */
+ WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));
+
+ /* enable the rom */
+ if (rdev->flags & RADEON_IS_PCIE)
+ WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));
+ else
+ WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));
+
+ /* Turn off mem requests and CRTC for both controllers */
+ WREG32(RADEON_CRTC_GEN_CNTL,
+ ((crtc_gen_cntl & ~RADEON_CRTC_EN) |
+ (RADEON_CRTC_DISP_REQ_EN_B |
+ RADEON_CRTC_EXT_DISP_EN)));
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ WREG32(RADEON_CRTC2_GEN_CNTL,
+ ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) |
+ RADEON_CRTC2_DISP_REQ_EN_B));
+ }
+ /* Turn off CRTC */
+ WREG32(RADEON_CRTC_EXT_CNTL,
+ ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) |
+ (RADEON_CRTC_SYNC_TRISTAT |
+ RADEON_CRTC_DISPLAY_DIS)));
+
+ if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON));
+ }
+
+ r = radeon_read_bios(rdev);
+
+ /* restore regs */
+ WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);
+ WREG32(RADEON_VIPH_CONTROL, viph_control);
+ if (rdev->flags & RADEON_IS_PCIE)
+ WREG32(RV370_BUS_CNTL, bus_cntl);
+ else
+ WREG32(RADEON_BUS_CNTL, bus_cntl);
+ WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
+ if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
+ WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+ }
+ WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+ if (rdev->ddev->pdev->device == PCI_DEVICE_ID_ATI_RADEON_QY) {
+ WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+ }
+ return r;
+}
+
+static bool radeon_read_disabled_bios(struct radeon_device *rdev)
+{
+ if (rdev->flags & RADEON_IS_IGP)
+ return igp_read_bios_from_vram(rdev);
+ else if (rdev->family >= CHIP_BARTS)
+ return ni_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_RV770)
+ return r700_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_R600)
+ return r600_read_disabled_bios(rdev);
+ else if (rdev->family >= CHIP_RS600)
+ return avivo_read_disabled_bios(rdev);
+ else
+ return legacy_read_disabled_bios(rdev);
+}
+
+#ifdef CONFIG_ACPI
+static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+ struct acpi_table_header *hdr;
+ acpi_size tbl_size;
+ UEFI_ACPI_VFCT *vfct;
+ unsigned offset;
+
+ if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
+ return false;
+ tbl_size = hdr->length;
+ if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
+ DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
+ return false;
+ }
+
+ vfct = (UEFI_ACPI_VFCT *)hdr;
+ offset = vfct->VBIOSImageOffset;
+
+ while (offset < tbl_size) {
+ GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
+ VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
+
+ offset += sizeof(VFCT_IMAGE_HEADER);
+ if (offset > tbl_size) {
+ DRM_ERROR("ACPI VFCT image header truncated\n");
+ return false;
+ }
+
+ offset += vhdr->ImageLength;
+ if (offset > tbl_size) {
+ DRM_ERROR("ACPI VFCT image truncated\n");
+ return false;
+ }
+
+ if (vhdr->ImageLength &&
+ vhdr->PCIBus == rdev->pdev->bus->number &&
+ vhdr->PCIDevice == PCI_SLOT(rdev->pdev->devfn) &&
+ vhdr->PCIFunction == PCI_FUNC(rdev->pdev->devfn) &&
+ vhdr->VendorID == rdev->pdev->vendor &&
+ vhdr->DeviceID == rdev->pdev->device) {
+ rdev->bios = kmemdup(&vbios->VbiosContent,
+ vhdr->ImageLength,
+ GFP_KERNEL);
+
+ if (!rdev->bios)
+ return false;
+ return true;
+ }
+ }
+
+ DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
+ return false;
+}
+#else
+static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+ return false;
+}
+#endif
+
+bool radeon_get_bios(struct radeon_device *rdev)
+{
+ bool r;
+ uint16_t tmp;
+
+ r = radeon_atrm_get_bios(rdev);
+ if (r == false)
+ r = radeon_acpi_vfct_bios(rdev);
+ if (r == false)
+ r = igp_read_bios_from_vram(rdev);
+ if (r == false)
+ r = radeon_read_bios(rdev);
+ if (r == false)
+ r = radeon_read_disabled_bios(rdev);
+ if (r == false)
+ r = radeon_read_platform_bios(rdev);
+ if (r == false)
+ r = radeon_read_bios_from_firmware(rdev);
+ if (r == false || rdev->bios == NULL) {
+ DRM_ERROR("Unable to locate a BIOS ROM\n");
+ rdev->bios = NULL;
+ return false;
+ }
+ if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+ printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]);
+ goto free_bios;
+ }
+
+ tmp = RBIOS16(0x18);
+ if (RBIOS8(tmp + 0x14) != 0x0) {
+ DRM_INFO("Not an x86 BIOS ROM, not using.\n");
+ goto free_bios;
+ }
+
+ rdev->bios_header_start = RBIOS16(0x48);
+ if (!rdev->bios_header_start) {
+ goto free_bios;
+ }
+ tmp = rdev->bios_header_start + 4;
+ if (!memcmp(rdev->bios + tmp, "ATOM", 4) ||
+ !memcmp(rdev->bios + tmp, "MOTA", 4)) {
+ rdev->is_atom_bios = true;
+ } else {
+ rdev->is_atom_bios = false;
+ }
+
+ DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM");
+ return true;
+free_bios:
+ kfree(rdev->bios);
+ rdev->bios = NULL;
+ return false;
+}
diff --git a/sync_backup.sh b/sync_backup.sh
deleted file mode 100755
index c84494f..0000000
--- a/sync_backup.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-rsync -e 'ssh -p 2223' -av \
- --usermap=abaumann:http \
- --groupmap=abaumann:http \
- --delete-after \
- --exclude '*~' \
- public/. root@andreasbaumann.cc:/srv/http/www.andreasbaumann.cc/.
diff --git a/sync_backup_local.sh b/sync_backup_local.sh
deleted file mode 100755
index 52ec79a..0000000
--- a/sync_backup_local.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-rsync -e 'ssh' -av \
- --usermap=abaumann:http \
- --groupmap=abaumann:http \
- --delete-after \
- --exclude '*~' \
- public/. root@eurobuild3:/srv/http/www.andreasbaumann.cc/.
diff --git a/sync_ssl.sh b/sync_ssl.sh
new file mode 100755
index 0000000..0417e8e
--- /dev/null
+++ b/sync_ssl.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+rm -rf ssl-public
+cp -av public ssl-public
+find ssl-public ! -name '*.db' -type f -exec \
+ sed -i 's@http://www\.andreasbaumann\.cc@https://www.andreasbaumann.cc@g' {} \;
+
+rsync -e 'ssh -p 2221' -av \
+ --usermap=abaumann:http \
+ --groupmap=abaumann:http \
+ --delete-after \
+ --exclude '*~' \
+ ssl-public/. root@andreasbaumann.cc:/srv/http/ssl-www.andreasbaumann.cc/.
diff --git a/test.sh b/test.sh
index 5d64e07..e10e2b3 100755
--- a/test.sh
+++ b/test.sh
@@ -1,4 +1,4 @@
#!/bin/sh
-hugo serve --buildDrafts --bind=0.0.0.0 -v --baseURL=http://`hostname -f`:1313
+hugo serve --buildDrafts --buildFuture --buildExpired --bind=0.0.0.0 -v --baseURL=http://`hostname -f`:1313
diff --git a/themes/new_theme/CHANGES b/themes/new_theme/CHANGES
new file mode 100644
index 0000000..79e711f
--- /dev/null
+++ b/themes/new_theme/CHANGES
@@ -0,0 +1,13 @@
+Changes made to https://github.com/Vimux/Mainroad.git
+
+- added slide theme for presentations
+- added an Elasticlunr search widget
+- added a data protection and privacy widget
+- added data protection, location and author to partial footer.html
+- layout for JSON (for search posts.json)
+- list.html has a ranklist partial include (for the embedded search
+ result)
+- list.html: only display list in blog contents, not on toolbox or
+ software section
+- replaced Google fonts with Bunny fonts
+
diff --git a/themes/new_theme/assets/css/style.css b/themes/new_theme/assets/css/style.css
new file mode 100644
index 0000000..545df0d
--- /dev/null
+++ b/themes/new_theme/assets/css/style.css
@@ -0,0 +1,1306 @@
+{{- $highlightColor := .Site.Params.highlightColor | default "#e22d30" -}}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+article,
+aside,
+dialog,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section {
+ display: block;
+}
+
+:focus::-webkit-input-placeholder {
+ color: transparent;
+}
+
+:focus::-moz-placeholder {
+ color: transparent;
+}
+
+:focus:-moz-placeholder {
+ color: transparent;
+}
+
+:focus:-ms-input-placeholder {
+ color: transparent;
+}
+
+/* Structure */
+html {
+ font-size: 100%;
+ -ms-text-size-adjust: none;
+ -webkit-text-size-adjust: none;
+}
+
+body {
+ margin: 0;
+ font-family: "Open Sans", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ font-size: .875rem;
+ line-height: 1.6;
+ word-wrap: break-word;
+ background: #f7f7f7;
+ -webkit-font-smoothing: antialiased;
+}
+
+.container {
+ position: relative;
+ width: 100%;
+ max-width: 1080px;
+ margin: 0 auto;
+}
+
+.container--outer {
+ margin: 25px auto;
+ box-shadow: 0 0 10px rgba(50, 50, 50, .17);
+}
+
+.wrapper {
+ padding: 25px;
+ background: #fff;
+}
+
+.flex {
+ display: -webkit-flex;
+ display: flex;
+}
+
+.primary {
+ -webkit-flex: 1 0 65.83%;
+ flex: 1 0 65.83%;
+ -webkit-order: 1;
+ order: 1;
+ min-width: 0;
+}
+
+.sidebar {
+ -webkit-flex: 1 0 31.66%;
+ flex: 1 0 31.66%;
+ -webkit-order: 2;
+ order: 2;
+ min-width: 0;
+ margin: 0 0 0 2.5%;
+}
+
+.sidebar--left {
+ -webkit-order: 0;
+ order: 0;
+ margin: 0 2.5% 0 0;
+}
+
+.clearfix {
+ display: block;
+}
+
+.clearfix::after {
+ display: block;
+ height: 0;
+ padding: 0;
+ margin: 0;
+ clear: both;
+ line-height: 0;
+ visibility: hidden;
+ content: "";
+}
+
+input,
+button,
+select,
+optgroup,
+textarea {
+ margin: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+
+/* Button */
+.btn {
+ padding: 5px 10px;
+ font-weight: 700;
+ color: #fff;
+ white-space: pre-line;
+ background: #2a2a2a;
+}
+
+.btn:hover {
+ color: #fff;
+ background: {{ $highlightColor }};
+}
+
+/* Animation */
+.menu__item,
+.btn {
+ transition: background-color .25s ease-out;
+}
+
+/* Typography */
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ margin: 0 0 20px;
+ margin: 0 0 1.25rem;
+ font-weight: 700;
+ line-height: 1.3;
+ color: #000;
+}
+
+h1 {
+ font-size: 32px;
+ font-size: 2rem;
+}
+
+h2 {
+ font-size: 24px;
+ font-size: 1.5rem;
+}
+
+h3 {
+ font-size: 20px;
+ font-size: 1.25rem;
+}
+
+h4 {
+ font-size: 18px;
+ font-size: 1.125rem;
+}
+
+h5 {
+ font-size: 16px;
+ font-size: 1rem;
+}
+
+h6 {
+ font-size: 16px;
+ font-size: 1rem;
+}
+
+a {
+ color: #000;
+ text-decoration: none;
+}
+
+a:hover {
+ color: {{ $highlightColor }};
+}
+
+hr {
+ margin: 0 0 20px;
+ border: 0;
+ border-top: 1px solid #dadada;
+}
+
+p {
+ margin: 0 0 20px;
+ margin: 0 0 1.25rem;
+}
+
+b,
+strong {
+ font: inherit;
+ font-weight: 700;
+}
+
+i,
+em {
+ font: inherit;
+ font-style: italic;
+}
+
+ol,
+ul {
+ padding: 0;
+ margin: 0;
+}
+
+small {
+ font-size: 12px;
+ font-size: .75rem;
+}
+
+mark {
+ background-color: #fd5;
+}
+
+figure {
+ margin: 0 0 20px;
+ margin: 0 0 1.25rem;
+}
+
+figcaption {
+ margin-top: 4px;
+ margin-top: .25rem;
+ color: #666;
+}
+
+figcaption h4 {
+ margin: 0;
+ color: inherit;
+}
+
+pre,
+code,
+kbd,
+samp {
+ font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ font-size: inherit;
+}
+
+pre,
+code {
+ background-color: #f5f5f5;
+ border: 1px solid #ebebeb;
+}
+
+code {
+ padding: 0 5px;
+ color: #c33;
+}
+
+pre {
+ display: block;
+ padding: 0;
+ padding: 1.25rem;
+ margin-bottom: 20px;
+ margin-bottom: 1.25rem;
+ overflow: auto;
+ color: #000;
+}
+
+pre code {
+ padding: 0;
+ color: inherit;
+ white-space: inherit;
+ background: inherit;
+ border: 0;
+}
+
+kbd {
+ padding: 2px 3px;
+ color: #fff;
+ background-color: #2a2a2a;
+}
+
+blockquote {
+ display: block;
+ padding: 5px 0 5px 15px;
+ margin: 0 0 20px;
+ margin: 0 0 1.25rem;
+ line-height: 1.6;
+ border-left: 5px solid {{ $highlightColor }};
+}
+
+blockquote p:last-child {
+ margin: 0;
+}
+
+blockquote footer {
+ text-align: right;
+}
+
+sup,
+sub {
+ font-size: 10px;
+ font-size: .625rem;
+ font-style: normal;
+}
+
+sup {
+ vertical-align: super;
+}
+
+sub {
+ vertical-align: sub;
+}
+
+abbr[title] {
+ text-decoration: none;
+ cursor: help;
+ border-bottom: 1px dotted #000;
+}
+
+q {
+ font-style: italic;
+}
+
+address {
+ margin-bottom: 20px;
+ margin-bottom: 1.25rem;
+ font-family: "Consolas", Courier New, Courier, monospace;
+ line-height: 1.5;
+}
+
+dl {
+ margin: 0 0 10px 20px;
+}
+
+dt,
+dd {
+ display: list-item;
+}
+
+dt {
+ font-weight: bold;
+ list-style-type: square;
+}
+
+dd {
+ margin-left: 20px;
+ list-style-type: circle;
+}
+
+select {
+ max-width: 100%;
+}
+
+.warning {
+ padding: 20px 10px;
+ text-align: center;
+ border: 1px solid #ddd;
+}
+
+.warning__icon {
+ margin-bottom: 20px;
+ fill: #ddd;
+}
+
+/* Header */
+.header {
+ background: #fff;
+}
+
+.logo {
+ padding: 25px;
+}
+
+.logo__link {
+ display: inline-block;
+}
+
+.logo__item {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.logo__img {
+ max-height: 256px;
+}
+
+.logo__text {
+ text-transform: uppercase;
+}
+
+.logo--mixed .logo__item {
+ margin: .5rem auto;
+}
+
+.logo--mixed .logo__img {
+ max-width: 128px;
+ max-height: 128px;
+}
+
+.logo--mixed .logo__text {
+ padding: 0 1rem;
+}
+
+.logo__title {
+ font-size: 32px;
+ font-size: 2rem;
+ font-weight: 700;
+ line-height: 1;
+ color: #000;
+}
+
+.logo__tagline {
+ display: inline-block;
+ padding-top: 10px;
+ margin-top: 10px;
+ font-size: 14px;
+ font-size: .875rem;
+ font-weight: 700;
+ line-height: 1;
+ color: {{ $highlightColor }};
+ border-top: 1px solid #ebebeb;
+}
+
+.divider {
+ height: 5px;
+ margin: 0;
+ background: {{ $highlightColor }};
+ border: 0;
+}
+
+/* Main menu */
+.no-js .menu__btn {
+ display: none;
+}
+
+.menu__btn {
+ display: block;
+ width: 100%;
+ padding: 0;
+ font: inherit;
+ color: #fff;
+ background: #2a2a2a;
+ border: 0;
+ outline: 0;
+}
+
+.menu__btn-title {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ padding: .625rem .9375rem;
+ font-weight: 700;
+ text-align: right;
+ text-transform: uppercase;
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+
+:focus > .menu__btn-title {
+ box-shadow: inset 0 0 1px 3px {{ $highlightColor }};
+}
+
+button:not(:-moz-focusring):focus > .menu__btn-title {
+ box-shadow: none;
+}
+
+.menu__btn:focus,
+.menu__btn-title:focus {
+ outline: 0;
+}
+
+.js .menu__btn--active {
+ color: {{ $highlightColor }};
+}
+
+.menu__list {
+ list-style: none;
+ background: #2a2a2a;
+}
+
+.menu__item:hover {
+ background: {{ $highlightColor }};
+}
+
+.menu__item:first-child {
+ border: 0;
+}
+
+.menu__item--active {
+ background: {{ $highlightColor }};
+}
+
+.menu__link {
+ display: block;
+ padding: 10px 15px;
+ padding: .625rem .9375rem;
+ font-weight: 700;
+ color: #fff;
+ text-transform: uppercase;
+}
+
+.menu__link:hover {
+ color: #fff;
+}
+
+.js .menu__list {
+ position: absolute;
+ z-index: 1;
+ width: 100%;
+ visibility: hidden;
+ -webkit-transform: scaleY(0);
+ transform: scaleY(0);
+ -webkit-transform-origin: top left;
+ transform-origin: top left;
+}
+
+.js .menu__list--active {
+ visibility: visible;
+ border-top: 1px solid rgba(255, 255, 255, .1);
+ border-bottom: 1px solid rgba(255, 255, 255, .1);
+ -webkit-transform: scaleY(1);
+ transform: scaleY(1);
+}
+
+.menu__list--transition {
+ transition: visibility .15s ease, transform .15s ease, -webkit-transform .15s ease;
+}
+
+@media screen and (min-width: 767px) {
+ .menu {
+ border-bottom: 5px solid {{ $highlightColor }};
+ }
+
+ .menu__btn {
+ display: none;
+ }
+
+ .menu__list,
+ .js .menu__list {
+ position: relative;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-wrap: wrap;
+ flex-wrap: wrap;
+ visibility: visible;
+ border: 0;
+ -webkit-transform: none;
+ transform: none;
+ }
+
+ .menu__item {
+ border-left: 1px solid rgba(255, 255, 255, .1);
+ }
+}
+
+/* Posts/Pages */
+.post__header,
+.main__header {
+ margin-bottom: 20px;
+ margin-bottom: 1.25rem;
+}
+
+.main__title {
+ font-size: 28px;
+ font-size: 1.75rem;
+}
+
+.main__content {
+ margin-bottom: 20px;
+ margin-bottom: 1.25rem;
+}
+
+.meta {
+ font-size: 13px;
+ font-size: .8125rem;
+ vertical-align: baseline;
+}
+
+.meta,
+.meta a {
+ color: #666;
+}
+
+.meta a:hover {
+ color: {{ $highlightColor }};
+}
+
+.meta__item {
+ display: inline;
+ margin-left: 15px;
+}
+
+.meta__item:first-child {
+ margin-left: 0;
+}
+
+.meta__icon {
+ margin-right: 5px;
+ vertical-align: middle;
+ fill: #c4c4c4;
+}
+
+.meta__text {
+ vertical-align: middle;
+}
+
+.post__title {
+ margin: 0;
+}
+
+.post__meta {
+ padding: 5px 0;
+ margin-top: 10px;
+ margin-top: .625rem;
+ border-top: 1px dotted #ebebeb;
+ border-bottom: 1px dotted #ebebeb;
+}
+
+.post__lead {
+ margin-top: 4px;
+ margin-top: .25rem;
+ margin-bottom: 0;
+ font-size: 16px;
+ font-size: 1rem;
+ font-style: italic;
+}
+
+.post__thumbnail {
+ max-width: 1030px;
+ margin: 0 0 20px;
+ margin-bottom: 0 0 1.25rem;
+}
+
+.post__thumbnail img {
+ width: 100%;
+}
+
+.content a,
+.warning a,
+.authorbox__description a {
+ font-weight: 700;
+ color: {{ $highlightColor }};
+}
+
+.content a:hover,
+.warning a:hover,
+.authorbox__description a:hover {
+ color: {{ $highlightColor }};
+ text-decoration: underline;
+}
+
+.content .alignnone {
+ display: block;
+ margin: 20px 0;
+ margin: 1.25rem 0;
+}
+
+.content .aligncenter {
+ display: block;
+ margin: 20px auto;
+ margin: 1.25rem auto;
+}
+
+.content .alignleft {
+ display: inline;
+ float: left;
+ margin: 5px 20px 20px 0;
+ margin: .3125rem 1.25rem 1.25rem 0;
+}
+
+.content .alignright {
+ display: inline;
+ float: right;
+ margin: 5px 0 20px 20px;
+ margin: .3125rem 0 1.25rem 1.25rem;
+}
+
+.content ul {
+ list-style: square;
+}
+
+.content ol {
+ list-style: decimal;
+}
+
+.content ul,
+.content ol {
+ margin: 0 0 20px 40px;
+}
+
+.content ul ul,
+.content ol ol,
+.content ol ul,
+.content ul ol {
+ margin: 0 0 0 40px;
+}
+
+.content li {
+ margin-bottom: 5px;
+}
+
+.post__footer {
+ margin-top: 20px;
+ margin-top: 1.25rem;
+}
+
+/* Post tags */
+.tags {
+ margin-bottom: 20px;
+ margin-bottom: 1.25rem;
+ font-size: 12px;
+ font-size: .75rem;
+ line-height: 1;
+ color: #fff;
+}
+
+.tags__list {
+ list-style: none;
+}
+
+.tags__item {
+ float: left;
+ margin: 0 6px 6px 0;
+ margin: 0 .375rem .375rem 0;
+ text-transform: uppercase;
+ background: #2a2a2a;
+}
+
+.tags__item:hover {
+ background: {{ $highlightColor }};
+}
+
+.tags__link,
+.tags__link:hover {
+ display: block;
+ padding: 10px 15px;
+}
+
+.tags__badge {
+ float: left;
+ width: 32px;
+ height: 32px;
+ padding: 8px;
+ margin-right: 6px;
+ background: {{ $highlightColor }};
+ fill: #fff;
+}
+
+/* Table of Contents */
+.toc {
+ margin-bottom: 20px;
+ font-weight: 700;
+ color: #7a8288;
+ background: #fff;
+ border-color: #ebebeb;
+ border-style: solid;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 0;
+ border-left-width: 1px;
+}
+
+.toc__title {
+ padding: 5px 10px;
+ color: #fff;
+ text-transform: uppercase;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+ background: #2a2a2a;
+}
+
+.toc__menu ul {
+ margin: 0;
+ list-style: none;
+}
+
+.toc__menu ul ul ul a {
+ padding-left: 25px;
+}
+
+.toc__menu ul ul ul ul a {
+ padding-left: 45px;
+}
+
+.toc__menu ul ul ul ul ul a {
+ padding-left: 65px;
+}
+
+.toc__menu ul ul ul ul ul ul a {
+ padding-left: 85px;
+}
+
+.toc__menu li {
+ margin: 0;
+}
+
+.toc__menu a {
+ display: block;
+ padding: 5px 10px;
+ color: {{ $highlightColor }};
+ border-bottom: 1px solid #ebebeb;
+}
+
+.toc__menu a:hover {
+ text-decoration: underline;
+}
+
+/* Author Box */
+.authorbox {
+ padding: 25px 0;
+ margin-bottom: 25px;
+ line-height: 1.5;
+ border-top: 1px solid #ebebeb;
+ border-bottom: 1px solid #ebebeb;
+}
+
+.authorbox__avatar {
+ float: left;
+ padding: 3px;
+ margin: 0 25px 0 0;
+ border: 1px solid #ebebeb;
+}
+
+.authorbox__header {
+ margin-bottom: 10px;
+}
+
+.authorbox__name {
+ font-size: 16px;
+ font-size: 1rem;
+ font-weight: 700;
+}
+
+/* List content */
+.list__item {
+ padding-bottom: 20px;
+ padding-bottom: 1.25rem;
+ margin-bottom: 20px;
+ margin-bottom: 1.25rem;
+ border-bottom: 1px solid #ebebeb;
+}
+
+.list__header {
+ margin-bottom: 10px;
+ margin-bottom: .625rem;
+}
+
+.list__meta {
+ margin-top: 5px;
+}
+
+.list__thumbnail {
+ float: left;
+ margin: 0 20px 0 0;
+}
+
+.list__thumbnail img {
+ width: 100%;
+ max-width: 235px;
+}
+
+.list__footer-readmore {
+ float: right;
+ margin-top: 10px;
+}
+
+/* Pagination */
+.pagination {
+ margin-top: 20px;
+}
+
+.pagination__item {
+ display: inline-block;
+ padding: 10px 15px;
+ font-weight: 700;
+ color: #000;
+ background: #f5f5f5;
+}
+
+.pagination__item:hover,
+.pagination__item--current {
+ color: #fff;
+ background: {{ $highlightColor }};
+}
+
+/* Pager (prev/next links) navigation */
+.pager {
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+ padding-top: 25px;
+ padding-bottom: 25px;
+ margin-bottom: 25px;
+ border-bottom: 1px solid #ebebeb;
+}
+
+.pager__subtitle {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: 700;
+ line-height: 1;
+ text-transform: uppercase;
+}
+
+.pager__title {
+ margin-bottom: 0;
+ overflow: hidden;
+ font-size: 13px;
+ font-size: .8125rem;
+}
+
+.pager__item {
+ -webkit-flex: 1 1 50%;
+ flex: 1 1 50%;
+ max-width: 48%;
+}
+
+.pager__item--next {
+ margin-left: auto;
+ text-align: right;
+}
+
+.pager__link {
+ display: block;
+}
+
+/* Images / Video */
+img {
+ width: auto\9; /* ie8 */
+ max-width: 100%;
+ height: auto;
+ vertical-align: bottom;
+}
+
+iframe,
+embed,
+object,
+video {
+ max-width: 100%;
+}
+
+/* Table */
+table {
+ width: 100%;
+ margin-bottom: 20px;
+ margin-bottom: 1.25rem;
+ border-spacing: 0;
+ border-collapse: collapse;
+ border-top: 1px solid #ebebeb;
+ border-left: 1px solid #ebebeb;
+}
+
+td,
+th {
+ padding: 5px 10px;
+ border-right: 1px solid #ebebeb;
+ border-bottom: 1px solid #ebebeb;
+}
+
+th {
+ font-weight: 700;
+}
+
+/* Forms */
+input {
+ padding: 5px;
+ font-size: 12px;
+ vertical-align: middle;
+ background: #f5f5f5;
+ border: 1px solid #ebebeb;
+ transition: all .25s ease-in-out;
+}
+
+input[type=text],
+input[type=email],
+input[type=tel],
+input[type=url] {
+ width: 60%;
+}
+
+input[type=text]:hover,
+input[type=email]:hover,
+input[type=tel]:hover,
+input[type=url]:hover,
+textarea:hover {
+ border: 1px solid #aaa;
+}
+
+input[type=submit],
+input[type=reset] {
+ display: inline-block;
+ min-width: 150px;
+ padding: 10px 15px;
+ font-weight: 700;
+ color: #fff;
+ text-transform: uppercase;
+ cursor: pointer;
+ background: #2a2a2a;
+ border: 0;
+ transition: all .1s linear;
+ -webkit-appearance: none;
+}
+
+input[type=submit]:hover,
+input[type=reset]:hover {
+ background: {{ $highlightColor }};
+}
+
+textarea {
+ width: 96%;
+ padding: 5px;
+ overflow: auto;
+ line-height: 1.5;
+ resize: vertical;
+ background: #f5f5f5;
+ border: 1px solid rgba(0, 0, 0, .1);
+}
+
+/* Widgets */
+.widget {
+ margin-bottom: 25px;
+ overflow: hidden;
+}
+
+.widget:last-child {
+ margin-bottom: 0;
+}
+
+.widget__title {
+ position: relative;
+ padding-bottom: 5px;
+ font-size: 16px;
+ font-size: 1rem;
+ text-transform: uppercase;
+ border-bottom: 3px solid {{ $highlightColor }};
+}
+
+.widget__item {
+ display: block;
+ padding: 5px 0;
+ border-bottom: 1px dotted #ebebeb;
+}
+
+.widget__item:first-child {
+ padding-top: 0;
+}
+
+/* Search widget */
+.widget-search__form {
+ display: block;
+ padding: 5%;
+ margin: 0 auto;
+ background: #f5f5f5;
+}
+
+.widget-search__form .widget-search__submit {
+ display: none;
+}
+
+.widget-search__field {
+ position: relative;
+ display: block;
+ width: 90%;
+ padding: 8px;
+ margin: 0 auto;
+ font-size: 11px;
+ cursor: pointer;
+ background: #fff;
+ border: 1px solid #ebebeb;
+ border-radius: 0;
+ outline-offset: -2px;
+ transition: none;
+ -webkit-appearance: none;
+}
+
+.widget-search__field:active,
+.widget-search__field:focus {
+ cursor: text;
+}
+
+/* Social widget */
+.widget-social__item {
+ padding: 0;
+ border: 0;
+}
+
+.widget-social__link {
+ display: block;
+ margin: 0 0 8px;
+ white-space: normal;
+}
+
+.widget-social__link-icon {
+ margin: 0 5px 0 0;
+ vertical-align: middle;
+ fill: #fff;
+}
+
+/* Tags Widget */
+.widget-taglist__link {
+ display: inline-block;
+ margin: 0 4px 8px 0;
+ font-size: 12px;
+ text-transform: uppercase;
+}
+
+/* Languages Widget */
+.widget-languages__link {
+ display: block;
+}
+
+.widget-languages__link:hover .widget-languages__link-btn {
+ color: #fff;
+ background: {{ $highlightColor }};
+}
+
+.widget-languages__link-btn {
+ display: inline-block;
+}
+
+/* Footer */
+.footer {
+ padding: 10px 25px;
+ font-size: 12px;
+ font-size: .75rem;
+ color: #999;
+ background: #2a2a2a;
+ border-top: 3px solid #999;
+}
+
+.footer__container {
+ -webkit-flex-flow: row wrap;
+ flex-flow: row wrap;
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+}
+
+.footer__links {
+ -webkit-order: 1;
+ order: 1;
+}
+
+.footer a {
+ color: #fff;
+}
+
+.footer a:hover {
+ text-decoration: underline;
+}
+
+/* Media Queries */
+@media screen and (max-width: 1475px) {
+ .container--outer {
+ width: 95%;
+ }
+}
+
+@media screen and (max-width: 900px) {
+ .container--outer {
+ width: 100%;
+ margin: 0 auto;
+ }
+
+ .wrapper,
+ .logo {
+ padding: 20px;
+ }
+
+ .widget {
+ margin-bottom: 20px;
+ }
+
+ .footer__container {
+ display: block;
+ }
+
+ .footer__links {
+ padding-bottom: 8px;
+ padding-bottom: 0.5rem;
+ text-align: center;
+ }
+
+ .footer__copyright {
+ text-align: center;
+ }
+}
+
+@media screen and (max-width: 767px) {
+ .wrapper {
+ display: block;
+ }
+
+ .sidebar {
+ float: none;
+ width: 100%;
+ margin: 0;
+ }
+
+ .logo {
+ text-align: center;
+ }
+
+ .logo__link {
+ margin: 0 auto;
+ }
+
+ .logo__title {
+ font-size: 24px;
+ font-size: 1.5rem;
+ }
+
+ .sidebar {
+ margin-top: 20px;
+ }
+}
+
+@media screen and (max-width: 620px) {
+ input[type=text],
+ input[type=email],
+ input[type=tel],
+ input[type=url] {
+ width: 88%;
+ }
+
+ .meta__item {
+ display: block;
+ margin-left: 0;
+ }
+
+ .authorbox {
+ text-align: center;
+ }
+
+ .authorbox__avatar {
+ display: inline-block;
+ float: none;
+ margin: 0 0 20px;
+ }
+
+ .pager {
+ display: block;
+ }
+
+ .pager__item {
+ min-width: 100%;
+ text-align: center;
+ }
+
+ .pager__item--prev {
+ padding-bottom: 25px;
+ }
+
+ .content ul,
+ .content ol {
+ margin: 0 0 20px 20px;
+ }
+
+ .content ul ul,
+ .content ol ol,
+ .content ol ul,
+ .content ul ol {
+ margin: 0 0 0 20px;
+ }
+
+ .list__thumbnail {
+ max-width: 80px;
+ }
+
+ .list__title {
+ font-size: 16px;
+ font-size: 1rem;
+ }
+
+ .list__lead {
+ font-size: 14px;
+ font-size: .875rem;
+ }
+
+ .list__meta {
+ display: block;
+ font-size: 11px;
+ font-size: .6875rem;
+ }
+}
diff --git a/themes/new_theme/i18n/bg.yaml b/themes/new_theme/i18n/bg.yaml
new file mode 100644
index 0000000..ab99714
--- /dev/null
+++ b/themes/new_theme/i18n/bg.yaml
@@ -0,0 +1,94 @@
+# General
+- id: read_more
+ translation: "Чети нататък…"
+
+- id: menu_label
+ translation: "Меню"
+
+- id: sidemenu_title
+ translation: "Меню"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Последна промяна"
+
+- id: meta_translations
+ translation: "Преводи"
+
+# Table of Contents
+- id: toc_title
+ translation: "Съдържание"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Предишна"
+
+- id: post_nav_next
+ translation: "Следваща"
+
+# Authorbox
+- id: authorbox_name
+ translation: "За {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "ПРЕДУПРЕЖДЕНИЕ"
+
+- id: sidebar_recommendation
+ translation: "Моля, активирай поне един блок в страничния панел."
+
+# Search widget
+- id: search_placeholder
+ translation: "ТЪРСЕНЕ..."
+
+# Languages widget
+- id: languages_title
+ translation: "Езици"
+
+# Categories widget
+- id: categories_title
+ translation: "Категории"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Последни писания"
+
+# Social widget
+- id: social_title
+ translation: "Социални"
+
+# Tags List widget
+- id: tags_title
+ translation: "Тагове"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Генерирано с <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> и тема \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Страницата не е намерена"
+
+- id: 404_text
+ translation:
+ "Страницата, която търсите, изглежда е била преместена, изтрита, или не съществува. Моля, използвайте полето за \
+ търсене или отидете на"
+
+- id: 404_linktext
+ translation: "главна страница"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Все още нямаш никакви писания!"
+
+- id: noposts_warning_description
+ translation:
+ "След като запишеш нещо в коя да е поддиректория (секция) на директория <b>content</b>, то ще се появи тук. По \
+ подразбиране само една секция (с най-многото писания) ще се показва на главната страница."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Tip:</b> Можеш да покажеш колкото искаш на брой секции, като ги укажеш в конфигурационния параметър \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b>."
diff --git a/themes/new_theme/i18n/cs.yaml b/themes/new_theme/i18n/cs.yaml
new file mode 100644
index 0000000..a209199
--- /dev/null
+++ b/themes/new_theme/i18n/cs.yaml
@@ -0,0 +1,94 @@
+# General
+- id: read_more
+ translation: "Číst více…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Naposledy upraveno"
+
+- id: meta_translations
+ translation: "Překlady"
+
+# Table of Contents
+- id: toc_title
+ translation: "Obsah stránky"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Předchozí"
+
+- id: post_nav_next
+ translation: "Následující"
+
+# Authorbox
+- id: authorbox_name
+ translation: "O {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "POZOR"
+
+- id: sidebar_recommendation
+ translation: "Prosím aktivujte aspoň jeden widget postranní lišty."
+
+# Search widget
+- id: search_placeholder
+ translation: "Hledat..."
+
+# Languages widget
+- id: languages_title
+ translation: "Jazyky"
+
+# Categories widget
+- id: categories_title
+ translation: "Kategorie"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Poslední příspěvky"
+
+# Social widget
+- id: social_title
+ translation: "Sociální sítě"
+
+# Tags List widget
+- id: tags_title
+ translation: "Štítky"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Vytvořeno pomocí <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> a tématu \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Stránka nebyla nalezena"
+
+- id: 404_text
+ translation:
+ "Požadovaná stránka neexistuje, nebo byla přesunuta či smazána. Využijte, prosím, vyhledávání, nebo pokračujte na"
+
+- id: 404_linktext
+ translation: "hlavní stránka"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Zatím nemáte žádné příspěvky!"
+
+- id: noposts_warning_description
+ translation:
+ "Jakmile vytvoříte příspěvek v libovolném podadresáři (sekci) adresáře <b>content</b>, objeví se zde. Ve výchozím \
+ nastavení je na hlavní stránce zobrazena pouze jedna sekce (s největším množstvím příspěvků)."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Tip:</b> Pomocí parametru \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b> \
+ můžete zobrazit libovolný počet sekcí."
diff --git a/themes/new_theme/i18n/de.yaml b/themes/new_theme/i18n/de.yaml
new file mode 100644
index 0000000..308d3a0
--- /dev/null
+++ b/themes/new_theme/i18n/de.yaml
@@ -0,0 +1,94 @@
+# General
+- id: read_more
+ translation: "Weiterlesen…"
+
+- id: menu_label
+ translation: "Menü"
+
+- id: sidemenu_title
+ translation: "Menü"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Zuletzt geändert"
+
+- id: meta_translations
+ translation: "Übersetzungen"
+
+# Table of Contents
+- id: toc_title
+ translation: "Inhaltsverzeichnis"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Zurück"
+
+- id: post_nav_next
+ translation: "Weiter"
+
+# Authorbox
+- id: authorbox_name
+ translation: "Über {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "WARNUNG"
+
+- id: sidebar_recommendation
+ translation: "Bitte aktivieren sie mindestens ein Widget."
+
+# Search widget
+- id: search_placeholder
+ translation: "Suche..."
+
+# Languages widget
+- id: languages_title
+ translation: "Sprachen"
+
+# Categories widget
+- id: categories_title
+ translation: "Kategorien"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Letzte Beiträge"
+
+# Social widget
+- id: social_title
+ translation: "Soziale Netzwerke"
+
+# Tags List widget
+- id: tags_title
+ translation: "Tags"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Erstellt mit <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> und \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a> Theme."
+
+# 404
+- id: 404_title
+ translation: "404. Seite nicht gefunden"
+
+- id: 404_text
+ translation:
+ "Die gesuchte Seite existiert nicht, wurde verschoben oder gelöscht. Bitte nutzen Sie die Suche oder gehen Sie zur"
+
+- id: 404_linktext
+ translation: "Startseite"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Es gibt noch keine Posts!"
+
+- id: noposts_warning_description
+ translation:
+ "Hier erscheinen Posts, die in einem Unterordner des <b>content/</b> Ordners abgelegt werden (z.B. in \
+ <b>content/post</b>). Standardmäßig werden nur Posts der Gruppe mit den meisten Einträgen angezeigt."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Tipp:</b> Mit dem \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b> \
+ Parameter lassen sich beliebig viele weitere Gruppen konfigurieren."
diff --git a/themes/new_theme/i18n/en.yaml b/themes/new_theme/i18n/en.yaml
new file mode 100644
index 0000000..3084c7b
--- /dev/null
+++ b/themes/new_theme/i18n/en.yaml
@@ -0,0 +1,94 @@
+# General
+- id: read_more
+ translation: "Read more…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Last Modified"
+
+- id: meta_translations
+ translation: "Translations"
+
+# Table of Contents
+- id: toc_title
+ translation: "Page content"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Previous"
+
+- id: post_nav_next
+ translation: "Next"
+
+# Authorbox
+- id: authorbox_name
+ translation: "About {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "WARNING"
+
+- id: sidebar_recommendation
+ translation: "Please activate at least one sidebar widget."
+
+# Search widget
+- id: search_placeholder
+ translation: "SEARCH..."
+
+# Languages widget
+- id: languages_title
+ translation: "Languages"
+
+# Categories widget
+- id: categories_title
+ translation: "Categories"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Recent Posts"
+
+# Social widget
+- id: social_title
+ translation: "Social"
+
+# Tags List widget
+- id: tags_title
+ translation: "Tags"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Generated with <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> and \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a> theme."
+
+# 404
+- id: 404_title
+ translation: "404. Page not found"
+
+- id: 404_text
+ translation:
+ "The page you were looking for appears to have been moved, deleted or does not exist. Please, use search or go to"
+
+- id: 404_linktext
+ translation: "main page"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "You don't have any posts yet!"
+
+- id: noposts_warning_description
+ translation:
+ "Once you post something in any folder (section) under the <b>content</b> directory, it will appear here. Only one \
+ section (with the most posts) will be displayed on the main page by default."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Tip:</b> You can show as many sections as you like with \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b> \
+ config parameter."
diff --git a/themes/new_theme/i18n/es.yaml b/themes/new_theme/i18n/es.yaml
new file mode 100644
index 0000000..47904d7
--- /dev/null
+++ b/themes/new_theme/i18n/es.yaml
@@ -0,0 +1,92 @@
+# General
+- id: read_more
+ translation: "Leer más"
+
+- id: menu_label
+ translation: "Menú"
+
+- id: sidemenu_title
+ translation: "Menú"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Última modificación"
+
+- id: meta_translations
+ translation: "Traducciones"
+
+# Table of Contents
+- id: toc_title
+ translation: "Índice"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Anterior"
+
+- id: post_nav_next
+ translation: "Siguiente"
+
+# Authorbox
+- id: authorbox_name
+ translation: "Sobre el autor {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "Atención"
+
+- id: sidebar_recommendation
+ translation: "Activa al menos un widget en la barra lateral."
+
+# Search widget
+- id: search_placeholder
+ translation: "Buscar..."
+
+# Languages widget
+- id: languages_title
+ translation: "Idiomas"
+
+# Categories widget
+- id: categories_title
+ translation: "Categorías"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Más Recientes"
+
+# Social widget
+- id: social_title
+ translation: "Social"
+
+# Tags List widget
+- id: tags_title
+ translation: "Etiquetas"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Generado con <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> y \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Página no encontrada"
+
+- id: 404_text
+ translation: "La página que estás buscando no aparece, no existe o se ha movido a otro lugar."
+
+- id: 404_linktext
+ translation: "Página principal"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "¡Todavía no hay publicaciones!"
+
+- id: noposts_warning_description
+ translation:
+ "Una vez que publiques algo en cualquier carpeta (sección) dentro del directorio <b>content</b>, se verá aquí. \
+ Sólo una sección (la que tenga más publicaciones) se mostrará por defecto en la página principal."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Aviso:</b> Puedes mostrar tantas secciones como gustes con el parámetro de configuración \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b>."
diff --git a/themes/new_theme/i18n/fr.yaml b/themes/new_theme/i18n/fr.yaml
new file mode 100644
index 0000000..8267d9c
--- /dev/null
+++ b/themes/new_theme/i18n/fr.yaml
@@ -0,0 +1,93 @@
+# General
+- id: read_more
+ translation: "Lire la suite…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Dernière modification"
+
+- id: meta_translations
+ translation: "Traductions"
+
+# Table of Contents
+- id: toc_title
+ translation: "Sommaire"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Précédent"
+
+- id: post_nav_next
+ translation: "Suivant"
+
+# Authorbox
+- id: authorbox_name
+ translation: "À propos {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "Attention"
+
+- id: sidebar_recommendation
+ translation: "Activez au moins un widget pour la barre latérale."
+
+# Search widget
+- id: search_placeholder
+ translation: "Rechercher..."
+
+# Languages widget
+- id: languages_title
+ translation: "Langues"
+
+# Categories widget
+- id: categories_title
+ translation: "Catégories"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Articles récents"
+
+# Social widget
+- id: social_title
+ translation: "Social"
+
+# Tags List widget
+- id: tags_title
+ translation: "Mots-clefs"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Produit par <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> et le thème \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Page introuvable."
+
+- id: 404_text
+ translation: "La page que vous recherchez a apparemment été supprimée, déplacée, ou n'existe pas."
+
+- id: 404_linktext
+ translation: "Accueil"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Vous n'avez pas encore de posts!"
+
+- id: noposts_warning_description
+ translation:
+ "Une fois que vous avez publié quelque chose dans n'importe quel sous-dossier (section) du dossier <b>content</b>, \
+ ça apparaîtra ici. par défaut, une seule section (Celle avec le plus de posts) sera affichée sur la page \
+ principale."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Astuce:</b> Vous pouvez afficher autant de sections que vous voulez avec le paramètre de configuration \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b>."
diff --git a/themes/new_theme/i18n/hu.yaml b/themes/new_theme/i18n/hu.yaml
new file mode 100644
index 0000000..5a54496
--- /dev/null
+++ b/themes/new_theme/i18n/hu.yaml
@@ -0,0 +1,95 @@
+# General
+- id: read_more
+ translation: "Tovább olvas…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Utoljára módosítva"
+
+- id: meta_translations
+ translation: "Fordítások"
+
+# Table of Contents
+- id: toc_title
+ translation: "Az oldal tartalma"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Előző"
+
+- id: post_nav_next
+ translation: "Következő"
+
+# Authorbox
+- id: authorbox_name
+ translation: "A {{ .Count }} -ról"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "FIGYELMEZTETÉS"
+
+- id: sidebar_recommendation
+ translation: "Kérjük, aktiváljon legalább egy oldalsáv-modult."
+
+# Search widget
+- id: search_placeholder
+ translation: "KERES..."
+
+# Languages widget
+- id: languages_title
+ translation: "Nyelvek"
+
+# Categories widget
+- id: categories_title
+ translation: "Kategóriák"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Legutóbbi bejegyzések"
+
+# Social widget
+- id: social_title
+ translation: "Közösség"
+
+# Tags List widget
+- id: tags_title
+ translation: "Cimkék"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Létrehozva <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> és \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a> témával."
+
+# 404
+- id: 404_title
+ translation: "404. Az oldal nem található"
+
+- id: 404_text
+ translation:
+ "Úgy tűnik, hogy a kívánt oldalt áthelyezték, törölték vagy nem létezik. Kérjük, használja a keresést, vagy lépjen \
+ ide"
+
+- id: 404_linktext
+ translation: "főoldal"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Még nincs bejegyzésed!"
+
+- id: noposts_warning_description
+ translation:
+ "Ha valamit a <b>content</b> könyvtár alatti mappába (szakaszba) közzéteszel, az itt jelenik meg. Csak egy szakasz \
+ (a legtöbb hozzászólással) jelenik meg a főoldalon alapértelmezés szerint."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Tipp:</b> Megjeleníthet annyi szakaszt, amennyit csak akar a \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b> \
+ konfigurációs paraméterrel."
diff --git a/themes/new_theme/i18n/it.yaml b/themes/new_theme/i18n/it.yaml
new file mode 100644
index 0000000..583a71c
--- /dev/null
+++ b/themes/new_theme/i18n/it.yaml
@@ -0,0 +1,94 @@
+# General
+- id: read_more
+ translation: "Continua a leggere…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Ultima modifica"
+
+- id: meta_translations
+ translation: "Traduzioni"
+
+# Table of Contents
+- id: toc_title
+ translation: "Indice"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Precedente"
+
+- id: post_nav_next
+ translation: "Prossimo"
+
+# Authorbox
+- id: authorbox_name
+ translation: "Riguardo {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "ATTENZIONE"
+
+- id: sidebar_recommendation
+ translation: "Si prega di attivare almeno un widget della barra laterale."
+
+# Search widget
+- id: search_placeholder
+ translation: "CERCA..."
+
+# Languages widget
+- id: languages_title
+ translation: "Lingue"
+
+# Categories widget
+- id: categories_title
+ translation: "Categorie"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Post recenti"
+
+# Social widget
+- id: social_title
+ translation: "Social"
+
+# Tags List widget
+- id: tags_title
+ translation: "Tag"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Generato con <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> e il tema \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Pagina non trovata"
+
+- id: 404_text
+ translation:
+ "La pagina che stai cercando sembra essere stata spostata, rimossa o non esiste. Si prega di usare la ricerca o \
+ andare alla"
+
+- id: 404_linktext
+ translation: "pagina principale"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Non hai ancora nessun post!"
+
+- id: noposts_warning_description
+ translation:
+ "Una volta pubblicato qualcosa in una qualsiasi cartella (sezione) dentro la directory <b>content</b>, apparirà \
+ qui. Solo una sezione (quella con più post) verrà mostrata in modo predefinito nella pagina principale."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Suggerimento:</b> Puoi mostrare quante sezioni vuoi con il parametro \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b>."
diff --git a/themes/new_theme/i18n/ja.yaml b/themes/new_theme/i18n/ja.yaml
new file mode 100644
index 0000000..67cdffe
--- /dev/null
+++ b/themes/new_theme/i18n/ja.yaml
@@ -0,0 +1,95 @@
+# General
+- id: read_more
+ translation: "続きを読む…"
+
+- id: menu_label
+ translation: "メニュー"
+
+- id: sidemenu_title
+ translation: "メニュー"
+
+# Post meta
+- id: meta_lastmod
+ translation: "最終更新"
+
+- id: meta_translations
+ translation: "翻訳"
+
+# Table of Contents
+- id: toc_title
+ translation: "目次"
+
+# Post nav
+- id: post_nav_prev
+ translation: "前の投稿"
+
+- id: post_nav_next
+ translation: "次の投稿"
+
+# Authorbox
+- id: authorbox_name
+ translation: "{{ .Count }}について"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "警告"
+
+- id: sidebar_recommendation
+ translation: "1つ以上のサイドバーウィジェットを有効にしてください。"
+
+# Search widget
+- id: search_placeholder
+ translation: "検索..."
+
+# Languages widget
+- id: languages_title
+ translation: "言語"
+
+# Categories widget
+- id: categories_title
+ translation: "カテゴリー"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "最近の投稿"
+
+# Social widget
+- id: social_title
+ translation: "ソーシャル"
+
+# Tags List widget
+- id: tags_title
+ translation: "タグ"
+
+# Footer
+- id: footer_credits
+ translation:
+ "このサイトは <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> と \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a> \
+ テーマで生成されています。"
+
+# 404
+- id: 404_title
+ translation: "404. ページが見つかりません"
+
+- id: 404_text
+ translation:
+ "お探しのページは移動されたか削除された、もしくは存在しないようです。検索するか、こちらのページに移動してください: "
+
+- id: 404_linktext
+ translation: "メインページ"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "まだ何も投稿していません!"
+
+- id: noposts_warning_description
+ translation:
+ "<b>content</b> 以下のどこかのディレクトリに投稿を追加するとここに表示されます。デフォルトでは(最も投稿の多い)1つのセクション \
+ だけがメインページに表示されます。"
+
+- id: noposts_warning_tip
+ translation:
+ "<b>ヒント:</b> 設定のパラメーター \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b> \
+ を使って好きな数だけセクションを表示させることもできます。"
diff --git a/themes/new_theme/i18n/nl.yaml b/themes/new_theme/i18n/nl.yaml
new file mode 100644
index 0000000..6ddfcf1
--- /dev/null
+++ b/themes/new_theme/i18n/nl.yaml
@@ -0,0 +1,93 @@
+# General
+- id: read_more
+ translation: "Meer lezen…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Laatst gewijzigd"
+
+- id: meta_translations
+ translation: "Vertalingen"
+
+# Table of Contents
+- id: toc_title
+ translation: "Inhoud"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Vorige"
+
+- id: post_nav_next
+ translation: "Volgende"
+
+# Authorbox
+- id: authorbox_name
+ translation: "Over {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "WAARSCHUWING"
+
+- id: sidebar_recommendation
+ translation: "Activeer minstens één sidebar widget."
+
+# Search widget
+- id: search_placeholder
+ translation: "ZOEKEN..."
+
+# Languages widget
+- id: languages_title
+ translation: "Talen"
+
+# Categories widget
+- id: categories_title
+ translation: "Categorieën"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Recente posts"
+
+# Social widget
+- id: social_title
+ translation: "Social"
+
+# Tags List widget
+- id: tags_title
+ translation: "Tags"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Gegenereerd met <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> en het \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a> theme."
+
+# 404
+- id: 404_title
+ translation: "404. Pagina niet gevonden"
+
+- id: 404_text
+ translation: "De pagina is mogelijk verplaatst, verwijderd of bestaat niet. Gebruik de zoekfunctie of \"ga naar\""
+
+- id: 404_linktext
+ translation: "hoofdpagina"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Er zijn nog geen posts!"
+
+- id: noposts_warning_description
+ translation:
+ "Zodra je iets post in welke map (sectie) dan ook onder de <b>content</b> directory, zal het hier verschijnen. \
+ Slechts één sectie (met de meeste posts) zal standaard getoond worden op de hoofdpagina."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Tip:</b> Je kunt zoveel secties laten zien als je wilt met de \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b> \
+ config parameter."
diff --git a/themes/new_theme/i18n/pt-br.yaml b/themes/new_theme/i18n/pt-br.yaml
new file mode 100644
index 0000000..625865b
--- /dev/null
+++ b/themes/new_theme/i18n/pt-br.yaml
@@ -0,0 +1,93 @@
+# General
+- id: read_more
+ translation: "Leia mais…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Última modificação"
+
+- id: meta_translations
+ translation: "Traduções"
+
+# Table of Contents
+- id: toc_title
+ translation: "Conteúdo da página"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Anterior"
+
+- id: post_nav_next
+ translation: "Próximo"
+
+# Authorbox
+- id: authorbox_name
+ translation: "Sobre {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "ATENÇÃO"
+
+- id: sidebar_recommendation
+ translation: "Ative pelo menos um widget da barra lateral."
+
+# Search widget
+- id: search_placeholder
+ translation: "BUSCAR..."
+
+# Languages widget
+- id: languages_title
+ translation: "Línguas"
+
+# Categories widget
+- id: categories_title
+ translation: "Categorias"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Postagens recentes"
+
+# Social widget
+- id: social_title
+ translation: "Social"
+
+# Tags List widget
+- id: tags_title
+ translation: "Tags"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Gerado com <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> com o tema \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Página não encontrada"
+
+- id: 404_text
+ translation:
+ "A página que você estava procurando parece ter sido excluída ou não existe. Por favor, use a pesquisa ou vá para"
+
+- id: 404_linktext
+ translation: "página principal"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Você ainda não tem nenhuma postagem!"
+
+- id: noposts_warning_description
+ translation:
+ "Quando você criar uma postagem em qualquer pasta (seção) dentro do diretório <b>content</b>, ele vai aparecer aqui. \
+ Apenas uma seção (a que conter mais postagens) será exibida na página principal por padrão."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Dica:</b> Você pode mostrar quantas seções você quiser com o parâmetro de configuração \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b>."
diff --git a/themes/new_theme/i18n/pt.yaml b/themes/new_theme/i18n/pt.yaml
new file mode 100644
index 0000000..625865b
--- /dev/null
+++ b/themes/new_theme/i18n/pt.yaml
@@ -0,0 +1,93 @@
+# General
+- id: read_more
+ translation: "Leia mais…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Última modificação"
+
+- id: meta_translations
+ translation: "Traduções"
+
+# Table of Contents
+- id: toc_title
+ translation: "Conteúdo da página"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Anterior"
+
+- id: post_nav_next
+ translation: "Próximo"
+
+# Authorbox
+- id: authorbox_name
+ translation: "Sobre {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "ATENÇÃO"
+
+- id: sidebar_recommendation
+ translation: "Ative pelo menos um widget da barra lateral."
+
+# Search widget
+- id: search_placeholder
+ translation: "BUSCAR..."
+
+# Languages widget
+- id: languages_title
+ translation: "Línguas"
+
+# Categories widget
+- id: categories_title
+ translation: "Categorias"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Postagens recentes"
+
+# Social widget
+- id: social_title
+ translation: "Social"
+
+# Tags List widget
+- id: tags_title
+ translation: "Tags"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Gerado com <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> com o tema \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Página não encontrada"
+
+- id: 404_text
+ translation:
+ "A página que você estava procurando parece ter sido excluída ou não existe. Por favor, use a pesquisa ou vá para"
+
+- id: 404_linktext
+ translation: "página principal"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Você ainda não tem nenhuma postagem!"
+
+- id: noposts_warning_description
+ translation:
+ "Quando você criar uma postagem em qualquer pasta (seção) dentro do diretório <b>content</b>, ele vai aparecer aqui. \
+ Apenas uma seção (a que conter mais postagens) será exibida na página principal por padrão."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Dica:</b> Você pode mostrar quantas seções você quiser com o parâmetro de configuração \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b>."
diff --git a/themes/new_theme/i18n/ru.yaml b/themes/new_theme/i18n/ru.yaml
new file mode 100644
index 0000000..917780e
--- /dev/null
+++ b/themes/new_theme/i18n/ru.yaml
@@ -0,0 +1,95 @@
+# General
+- id: read_more
+ translation: "Читать далее…"
+
+- id: menu_label
+ translation: "Меню"
+
+- id: sidemenu_title
+ translation: "Меню"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Последнее изменение"
+
+- id: meta_translations
+ translation: "Переводы"
+
+# Table of Contents
+- id: toc_title
+ translation: "Содержимое страницы"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Назад"
+
+- id: post_nav_next
+ translation: "Вперед"
+
+# Authorbox
+- id: authorbox_name
+ translation: "Об авторе {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "ВНИМАНИЕ"
+
+- id: sidebar_recommendation
+ translation: "Пожалуйста, активируйте как минимум один виджет боковой панели."
+
+# Search widget
+- id: search_placeholder
+ translation: "ПОИСК..."
+
+# Languages widget
+- id: languages_title
+ translation: "Языки"
+
+# Categories widget
+- id: categories_title
+ translation: "Категории"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Недавние публикации"
+
+# Social widget
+- id: social_title
+ translation: "Социальные сети"
+
+# Tags List widget
+- id: tags_title
+ translation: "Теги"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Сгенерировано с использованием <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> \
+ и темы <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Страница не найдена"
+
+- id: 404_text
+ translation:
+ "Страница, которую вы искали, по-видимому, была перемещена, удалена или не существовала вообще. Пожалуйста, \
+ используйте поиск или перейдите на"
+
+- id: 404_linktext
+ translation: "главную страницу"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "У вас нет ни одной публикации!"
+
+- id: noposts_warning_description
+ translation:
+ "Как только вы опубликуете что-нибудь в любой папке (разделе) внутри директории <b>content</b>, оно появится \
+ здесь. По-умолчанию на главной странице будет отображаться только один раздел (с наибольшим количеством \
+ публикаций)."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Совет:</b> Вы можете отображать сколько угодно разделов с помощью параметра конфигурации \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b>."
diff --git a/themes/new_theme/i18n/vi.yaml b/themes/new_theme/i18n/vi.yaml
new file mode 100644
index 0000000..16a80f3
--- /dev/null
+++ b/themes/new_theme/i18n/vi.yaml
@@ -0,0 +1,93 @@
+# General
+- id: read_more
+ translation: "Đọc tiếp…"
+
+- id: menu_label
+ translation: "Menu"
+
+- id: sidemenu_title
+ translation: "Menu"
+
+# Post meta
+- id: meta_lastmod
+ translation: "Cập nhật lần cuối"
+
+- id: meta_translations
+ translation: "Bản dịch"
+
+# Table of Contents
+- id: toc_title
+ translation: "Mục lục"
+
+# Post nav
+- id: post_nav_prev
+ translation: "Trước"
+
+- id: post_nav_next
+ translation: "Sau"
+
+# Authorbox
+- id: authorbox_name
+ translation: "Về {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "CÁNH BÁO"
+
+- id: sidebar_recommendation
+ translation: "Vui lòng tạo hoặc kích hoạt tối thiểu một thành phần trong thanh bên."
+
+# Search widget
+- id: search_placeholder
+ translation: "TÌM KIẾM..."
+
+# Languages widget
+- id: languages_title
+ translation: "Ngôn ngữ"
+
+# Categories widget
+- id: categories_title
+ translation: "Chủ đề"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "Bài viết gần đây"
+
+# Social widget
+- id: social_title
+ translation: "Xã hội"
+
+# Tags List widget
+- id: tags_title
+ translation: "Thẻ"
+
+# Footer
+- id: footer_credits
+ translation:
+ "Được tạo từ <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> sử dụng với \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>."
+
+# 404
+- id: 404_title
+ translation: "404. Không tìm thấy trang này"
+
+- id: 404_text
+ translation:
+ "Trang bạn đang tìm kiếm đã bị xoá hoặc không tồn tại. Vui lòng sử dụng chức năng tìm kiếm"
+
+- id: 404_linktext
+ translation: "trang chủ"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "Bạn chưa có bài viết nào!"
+
+- id: noposts_warning_description
+ translation:
+ "Khi bạn xuất bản bất kì bài viết nào trong bất kì thư mục nào trong thư mục <b>content</b>, nó sẽ xuất hiện tại đây.\
+ Mặc định chỉ một phần của bài viết sẽ được xuất hiện trong trang chủ cho hầu hết các bài viết."
+
+- id: noposts_warning_tip
+ translation:
+ "<b>Gợi ý:</b> Bạn có thể hiện bao nhiêu phần tuỳ ý bằng tham số parameter \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b>."
diff --git a/themes/new_theme/i18n/zh-cn.yaml b/themes/new_theme/i18n/zh-cn.yaml
new file mode 100644
index 0000000..e66faae
--- /dev/null
+++ b/themes/new_theme/i18n/zh-cn.yaml
@@ -0,0 +1,92 @@
+# General
+- id: read_more
+ translation: "阅读全文…"
+
+- id: menu_label
+ translation: "菜单"
+
+- id: sidemenu_title
+ translation: "菜单"
+
+# Post meta
+- id: meta_lastmod
+ translation: "最后修改"
+
+- id: meta_translations
+ translation: "翻译"
+
+# Table of Contents
+- id: toc_title
+ translation: "目录"
+
+# Post nav
+- id: post_nav_prev
+ translation: "上一篇"
+
+- id: post_nav_next
+ translation: "下一篇"
+
+# Authorbox
+- id: authorbox_name
+ translation: "关于 {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "警告"
+
+- id: sidebar_recommendation
+ translation: "请至少选择一个侧边栏组件"
+
+# Search widget
+- id: search_placeholder
+ translation: "搜索..."
+
+# Languages widget
+- id: languages_title
+ translation: "语言"
+
+# Categories widget
+- id: categories_title
+ translation: "分类"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "近期文章"
+
+# Social widget
+- id: social_title
+ translation: "社交"
+
+# Tags List widget
+- id: tags_title
+ translation: "标签"
+
+# Footer
+- id: footer_credits
+ translation: "基于 <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> 引擎和 \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>主題"
+
+# 404
+- id: 404_title
+ translation: "404. 抱歉,找不到您要找的页面"
+
+- id: 404_text
+ translation: "您要找的页面可能已经被移除、刪除或不存在,不妨去首页搜索一下吧。"
+
+- id: 404_linktext
+ translation: "回到首页"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "目前还没有任何内容!"
+
+- id: noposts_warning_description
+ translation:
+ "在 <b>content</b> 目录下的任意文件夹(板块)中发布内容后,它就会显示在这里。\
+ 只有一个板块的内容(默认文章最多的文件夹)会显示在主页面上"
+
+- id: noposts_warning_tip
+ translation:
+ "<b>提示:</b> 您可以通过 \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b> \
+ 参数来控制展示您想要展示的板块内容。"
diff --git a/themes/new_theme/i18n/zh-tw.yaml b/themes/new_theme/i18n/zh-tw.yaml
new file mode 100644
index 0000000..4854662
--- /dev/null
+++ b/themes/new_theme/i18n/zh-tw.yaml
@@ -0,0 +1,93 @@
+# General
+- id: read_more
+ translation: "閱讀全文…"
+
+- id: menu_label
+ translation: "選單"
+
+- id: sidemenu_title
+ translation: "選單"
+
+# Post meta
+- id: meta_lastmod
+ translation: "最後修改"
+
+- id: meta_translations
+ translation: "翻譯"
+
+# Table of Contents
+- id: toc_title
+ translation: "內文"
+
+# Post nav
+- id: post_nav_prev
+ translation: "前一則"
+
+- id: post_nav_next
+ translation: "下一則"
+
+# Authorbox
+- id: authorbox_name
+ translation: "關於 {{ .Count }}"
+
+# Sidebar
+- id: sidebar_warning
+ translation: "警告"
+
+- id: sidebar_recommendation
+ translation: "請至少選擇一個側邊欄元件"
+
+# Search widget
+- id: search_placeholder
+ translation: "搜尋..."
+
+# Languages widget
+- id: languages_title
+ translation: "語言"
+
+# Categories widget
+- id: categories_title
+ translation: "分類"
+
+# Recent Posts widget
+- id: recent_title
+ translation: "近期文章"
+
+# Social widget
+- id: social_title
+ translation: "社群"
+
+# Tags List widget
+- id: tags_title
+ translation: "標籤"
+
+# Footer
+- id: footer_credits
+ translation:
+ "使用 <a href=\"https://gohugo.io/\" rel=\"nofollow noopener\" target=\"_blank\">Hugo</a> 技術與 \
+ <a href=\"https://github.com/Vimux/Mainroad/\" rel=\"nofollow noopener\" target=\"_blank\">Mainroad</a>主題"
+
+# 404
+- id: 404_title
+ translation: "404. 糟糕!我們似乎無法找到您要找的頁面。"
+
+- id: 404_text
+ translation: "您要找的頁面可能已經被移除、刪除或是不存在。請回到首頁或是使用搜尋功能。"
+
+- id: 404_linktext
+ translation: "回到首頁"
+
+# No posts empty state
+- id: noposts_warning_title
+ translation: "目前還沒有任何内容!"
+
+- id: noposts_warning_description
+ translation:
+ "在 <b>content</b> 目錄下的任意資料夾(區塊)中發布内容後,就會被顯示在此處。\
+ 其中只有一個區塊的内容(預設是擁有文章數量最多的資料夾)會被顯示在主要頁面上"
+
+- id: noposts_warning_tip
+ translation:
+ "<b>提示:</b> 您可以透過 \
+ <b><a href=\"https://gohugo.io/functions/where/#mainsections\" rel=\"nofollow noopener\" target=\"_blank\">mainSections</a></b> \
+ 參數來控制所要展示的區塊內容。"
diff --git a/themes/new_theme/images/screenshot.png b/themes/new_theme/images/screenshot.png
new file mode 100644
index 0000000..d67e2c0
--- /dev/null
+++ b/themes/new_theme/images/screenshot.png
Binary files differ
diff --git a/themes/new_theme/images/tn.png b/themes/new_theme/images/tn.png
new file mode 100644
index 0000000..cd45c84
--- /dev/null
+++ b/themes/new_theme/images/tn.png
Binary files differ
diff --git a/themes/new_theme/layouts/404.html b/themes/new_theme/layouts/404.html
index 59a1ebf..6e067f0 100644
--- a/themes/new_theme/layouts/404.html
+++ b/themes/new_theme/layouts/404.html
@@ -1,15 +1,8 @@
-{{ partial "header.html" . }}
-
-<div class="main-content content" role="main" itemprop="mainContentOfPage">
- <article class="post">
- <header class="post__header clearfix">
- <h1 class="post__title">{{ .Title }}</h1>
- </header>
- <div class="post__content clearfix">
- Page not found..
- </div>
- </article>
-</div>
-
-{{ partial "sidebar.html" . }}
-{{ partial "footer.html" . }}
+{{ define "main" }}
+<main class="main" role="main">
+ <div class="warning">
+ <h1 class="warning__headline">{{ T "404_title" }}</h1>
+ <p class="warning__text">{{ T "404_text" }} <a href="{{ "" | relLangURL }}">{{ T "404_linktext" }}</a>.</p>
+ </div>
+</main>
+{{ end }}
diff --git a/themes/new_theme/layouts/_default/baseof.html b/themes/new_theme/layouts/_default/baseof.html
new file mode 100644
index 0000000..255aaa3
--- /dev/null
+++ b/themes/new_theme/layouts/_default/baseof.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html class="no-js" lang="{{ .Site.Language.Lang }}">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <title>{{ block "title" . }}{{ if not .IsHome }}{{ .Title }} - {{ end }}{{ .Site.Title }}{{ end }}</title>
+ <script>(function(d,e){d[e]=d[e].replace("no-js","js");})(document.documentElement,"className");</script>
+ <meta name="description" content="{{ if .IsHome }}{{ .Site.Params.description }}{{ else }}{{ .Params.Description }}{{ end }}">
+ {{- if .Site.Params.opengraph }}
+ {{ template "_internal/opengraph.html" . }}
+ {{- end }}
+ {{- if .Site.Params.schema }}
+ {{ template "_internal/schema.html" . }}
+ {{- end }}
+ {{- if .Site.Params.twitter_cards }}
+ {{ template "_internal/twitter_cards.html" . }}
+ {{- end }}
+ <link rel="dns-prefetch" href="//fonts.bunny.net">
+ {{ with .OutputFormats.Get "rss" -}}
+ {{ printf `<link rel="%s" type="%s" href="%s" title="%s">` .Rel .MediaType.Type .RelPermalink $.Site.Title | safeHTML }}
+ {{ end -}}
+ <script src="/js/jquery.js" type="text/javascript"></script>
+ <link rel="stylesheet" href="https://fonts.bunny.net/css?family=Open+Sans:400,400i,700">
+ {{ $style := resources.Get "css/style.css" | resources.ExecuteAsTemplate "css/style.css" . -}}
+ <link rel="stylesheet" href="{{ $style.RelPermalink }}">
+ {{ range .Site.Params.customCSS -}}
+ <link rel="stylesheet" href="{{ . | relURL }}">
+ {{- end }}
+ <link rel="shortcut icon" href="{{ "favicon.ico" | relURL }}">
+ {{- if not .Site.IsServer }}
+ {{ template "_internal/google_analytics_async.html" . }}
+ {{- end }}
+</head>
+<body class="body">
+ <div class="container container--outer">
+ {{ partial "header" . }}
+ <div class="wrapper flex">
+ <div class="primary">
+ {{ block "main" . }}
+ {{ with .Content }}
+ <div class="content main__content clearfix">
+ {{ . }}
+ </div>
+ {{ end }}
+ {{ end }}
+ </div>
+ {{ partial "sidebar.html" . }}
+ </div>
+ {{ partial "footer" . }}
+ </div>
+<script async defer src="{{ "js/menu.js" | relURL }}"></script>
+{{ range .Site.Params.customJS -}}
+<script src="{{ . | relURL }}"></script>
+{{- end }}
+{{- partial "mathjax.html" . -}}
+</body>
+</html>
diff --git a/themes/new_theme/layouts/_default/list.html b/themes/new_theme/layouts/_default/list.html
index 2bc036c..4816514 100644
--- a/themes/new_theme/layouts/_default/list.html
+++ b/themes/new_theme/layouts/_default/list.html
@@ -1,67 +1,22 @@
-{{ partial "header.html" . }}
-
-{{ $section := .Section }}
-
-{{ if and ( ne $section "blog" ) ( ne $section "" ) }}
-<div class="main-content content" role="main" itemprop="mainContentOfPage">
- <article class="post">
- <header class="post__header clearfix">
- <h1 class="post__title">{{ .Title }}</h1>
- </header>
- <div class="post__content clearfix">
- {{ if ( eq $section "search" ) }}
- {{ partial "ranklist.html" . }}
- {{ .Content }}
- {{ else }}
- {{ .Content }}
- {{ end }}
- </div>
- </article>
-</div>
-{{ else }}
- <div class="main-content loop content" role="main">
- {{- if not .IsHome }}
- <header class="page-header">
- <h1 class="page-header__title">{{ .Title }}</h1>
- </header>
- {{- end }}
- {{- range .Pages }}
- <article class="loop__item post clearfix">
- {{- if .Params.thumbnail }}
- <figure class="loop__thumbnail">
- <a href="{{ .Permalink }}">
- <img src="{{ .Params.thumbnail | absURL }}" alt="{{ .Title }}" />
- </a>
- </figure>
- {{- end }}
- <div class="loop__content clearfix">
- <header class="loop__header">
- <h3 class="loop__title post__title ">
- <a href="{{ .Permalink }}" rel="bookmark">{{ .Title }}</a>
- </h3>
- <div class="loop__meta meta">
- <svg class="icon icon-time" height="14" viewBox="0 0 16 16" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m8-.0000003c-4.4 0-8 3.6-8 8 0 4.4000003 3.6 8.0000003 8 8.0000003 4.4 0 8-3.6 8-8.0000003 0-4.4-3.6-8-8-8zm0 14.4000003c-3.52 0-6.4-2.88-6.4-6.4000003 0-3.52 2.88-6.4 6.4-6.4 3.52 0 6.4 2.88 6.4 6.4 0 3.5200003-2.88 6.4000003-6.4 6.4000003zm.4-10.4000003h-1.2v4.8l4.16 2.5600003.64-1.04-3.6-2.1600003z"/></svg>
- <time class="loop__meta-date" datetime="{{ .Date }}">{{.Date.Format "January 02, 2006"}}</time>
- {{- if .Params.categories }}
- <span class="post__meta-categories meta-categories">
- <svg class="icon icon-category" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 2l1 2h8v11h-16v-13z"/></svg>
- {{ range $index, $category := .Params.categories }}{{ if gt $index 0 }}, {{ end }}<a class="meta-categories__link" href="{{ "/categories/" | relLangURL }}{{ . | urlize | lower }}" rel="category">{{ . }}</a>{{ end }}</span>
- {{- end }}
- </div>
- </header>
- <div class="loop__excerpt post__content">
- {{ .Summary }}
- </div>
- <div class="post__content">
- <a href="{{ .URL }}">View full post</a>
- </div>
- </div>
- </article>
- {{- end }}
-
- {{ partial "pagination.html" . }}
+{{ define "main" }}
+<main class="main list" role="main">
+ {{- with .Title }}
+ <header class="main__header">
+ <h1 class="main__title">{{ . }}</h1>
+ </header>
+ {{- end }}
+ {{- with .Content }}
+ <div class="content main__content clearfix">
+ {{ . }}
+ {{ partial "ranklist_fts5.html" . }}
</div>
+ {{- end }}
+ {{ $section := .Section }}
+ {{- if or ( eq $section "blog" ) ( eq $section "" ) ( eq $section "categories" ) }}
+ {{- range .Paginator.Pages }}
+ {{- .Render "summary" }}
+ {{- end }}
+ {{- end }}
+</main>
+{{ partial "pagination.html" . }}
{{ end }}
-
-{{ partial "sidebar.html" . }}
-{{ partial "footer.html" . }}
diff --git a/themes/new_theme/layouts/_default/single.html b/themes/new_theme/layouts/_default/single.html
index 77fbd4a..9c84ca4 100644
--- a/themes/new_theme/layouts/_default/single.html
+++ b/themes/new_theme/layouts/_default/single.html
@@ -1,48 +1,32 @@
-{{ partial "header.html" . }}
-
-{{ $section := .Section }}
-
-{{ if ne $section "blog" }}
-<div class="main-content content" role="main" itemprop="mainContentOfPage">
+{{ define "main" }}
+<main class="main" role="main">
<article class="post">
- <header class="post__header clearfix">
+ <header class="post__header">
<h1 class="post__title">{{ .Title }}</h1>
- </header>
- <div class="post__content clearfix">
- {{ .Content }}
- </div>
- </article>
-</div>
-{{ else }}
-<div class="main-content content" role="main" itemprop="mainContentOfPage">
- <article class="post">
- <header class="post__header clearfix">
- <h1 class="post__title">{{ .Title }}</h1>
- <p class="post__meta meta">
- <svg class="icon icon-time" height="14" viewBox="0 0 16 16" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m8-.0000003c-4.4 0-8 3.6-8 8 0 4.4000003 3.6 8.0000003 8 8.0000003 4.4 0 8-3.6 8-8.0000003 0-4.4-3.6-8-8-8zm0 14.4000003c-3.52 0-6.4-2.88-6.4-6.4000003 0-3.52 2.88-6.4 6.4-6.4 3.52 0 6.4 2.88 6.4 6.4 0 3.5200003-2.88 6.4000003-6.4 6.4000003zm.4-10.4000003h-1.2v4.8l4.16 2.5600003.64-1.04-3.6-2.1600003z"/></svg>
- <time class="post__meta-date" datetime="{{ .Date }}">{{.Date.Format "January 02, 2006"}}</time>
- {{- if .Params.categories }}
- <span class="post__meta-categories meta-categories">
- <svg class="icon icon-category" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 2l1 2h8v11h-16v-13z"/></svg>
- {{ range $index, $category := .Params.categories }}{{ if gt $index 0 }}, {{ end }}<a class="meta-categories__link" href="{{ "/categories/" | relLangURL }}{{ . | urlize | lower }}" rel="category">{{ . }}</a>{{ end }}</span>
- {{- end }}
- </p>
- </header>
- <div class="post__content clearfix">
- {{- if .Params.thumbnail }}
- <figure class="post__thumbnail">
- <img src="{{ .Params.thumbnail | absURL }}" alt="{{ .Title }}">
- </figure>
+ {{- with .Params.lead }}
+ <p class="post__lead">{{ . }}</p>
{{- end }}
+ {{ with partial "post_meta.html" . -}}
+ <div class="post__meta meta">{{ . }}</div>
+ {{- end }}
+ </header>
+ {{- if .Params.thumbnail }}
+ <figure class="post__thumbnail">
+ <img src="{{ .Params.thumbnail | relURL }}" alt="{{ .Title }}">
+ </figure>
+ {{- end }}
+ {{- partial "post_toc.html" . -}}
+ <div class="content post__content clearfix">
{{ .Content }}
</div>
- {{ partial "post_tags.html" . }}
+ {{- if .Params.tags }}
+ <footer class="post__footer">
+ {{ partial "post_tags.html" . }}
+ </footer>
+ {{- end }}
</article>
- {{ partial "authorbox.html" . }}
- {{ partial "post_nav.html" . }}
- {{ partial "comments.html" . }}
-</div>
+</main>
+{{ partial "authorbox.html" . }}
+{{ partial "pager.html" . }}
+{{ partial "comments.html" . }}
{{ end }}
-
-{{ partial "sidebar.html" . }}
-{{ partial "footer.html" . }}
diff --git a/themes/new_theme/layouts/_default/summary.html b/themes/new_theme/layouts/_default/summary.html
new file mode 100644
index 0000000..df7428d
--- /dev/null
+++ b/themes/new_theme/layouts/_default/summary.html
@@ -0,0 +1,32 @@
+<article class="list__item post">
+ {{- if .Params.thumbnail }}
+ <figure class="list__thumbnail">
+ <a href="{{ .Permalink }}">
+ <img src="{{ .Params.thumbnail | relURL }}" alt="{{ .Title }}" />
+ </a>
+ </figure>
+ {{- end }}
+ <header class="list__header">
+ <h3 class="list__title post__title ">
+ <a href="{{ .RelPermalink }}" rel="bookmark">
+ {{ .Title }}
+ </a>
+ </h3>
+ {{- with .Params.lead }}
+ <p class="list__lead post__lead">{{ . }}</p>
+ {{- end }}
+ {{ with partial "post_meta.html" . -}}
+ <div class="list__meta meta">{{ . }}</div>
+ {{- end }}
+ </header>
+ <div class="content list__excerpt post__content clearfix">
+ {{ .Summary }}
+ </div>
+ {{- if .Site.Params.readmore }}
+ {{- if .Truncated }}
+ <div class="list__footer clearfix">
+ <a class="list__footer-readmore btn" href="{{ .RelPermalink }}">{{ T "read_more" }}</a>
+ </div>
+ {{- end }}
+ {{- end }}
+</article> \ No newline at end of file
diff --git a/themes/new_theme/layouts/index.html b/themes/new_theme/layouts/index.html
index 77fbd4a..9250441 100644
--- a/themes/new_theme/layouts/index.html
+++ b/themes/new_theme/layouts/index.html
@@ -1,48 +1,24 @@
-{{ partial "header.html" . }}
-
-{{ $section := .Section }}
-
-{{ if ne $section "blog" }}
-<div class="main-content content" role="main" itemprop="mainContentOfPage">
- <article class="post">
- <header class="post__header clearfix">
- <h1 class="post__title">{{ .Title }}</h1>
- </header>
- <div class="post__content clearfix">
- {{ .Content }}
+{{ define "main" }}
+<main class="main list" role="main">
+ {{- with .Content }}
+ <div class="content main__content clearfix">
+ {{ . }}
+ </div>
+ {{- end }}
+ {{ $paginator := .Paginate (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) }}
+ {{- range $paginator.Pages }}
+ {{- .Render "summary" }}
+ {{- end }}
+ {{- if and (eq $paginator.TotalNumberOfElements 0) (not $.Content) }}
+ <div class="warning">
+ {{ partial "svg/files.svg" (dict "class" "warning__icon") }}
+ <h3 class="warning__headline">{{ T "noposts_warning_title" | safeHTML }}</h3>
+ <div class="warning__text">
+ <p class="warning__description">{{ T "noposts_warning_description" | safeHTML }}</p>
+ <p class="warning__tip">{{ T "noposts_warning_tip" | safeHTML }}</p>
+ </div>
</div>
- </article>
-</div>
-{{ else }}
-<div class="main-content content" role="main" itemprop="mainContentOfPage">
- <article class="post">
- <header class="post__header clearfix">
- <h1 class="post__title">{{ .Title }}</h1>
- <p class="post__meta meta">
- <svg class="icon icon-time" height="14" viewBox="0 0 16 16" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m8-.0000003c-4.4 0-8 3.6-8 8 0 4.4000003 3.6 8.0000003 8 8.0000003 4.4 0 8-3.6 8-8.0000003 0-4.4-3.6-8-8-8zm0 14.4000003c-3.52 0-6.4-2.88-6.4-6.4000003 0-3.52 2.88-6.4 6.4-6.4 3.52 0 6.4 2.88 6.4 6.4 0 3.5200003-2.88 6.4000003-6.4 6.4000003zm.4-10.4000003h-1.2v4.8l4.16 2.5600003.64-1.04-3.6-2.1600003z"/></svg>
- <time class="post__meta-date" datetime="{{ .Date }}">{{.Date.Format "January 02, 2006"}}</time>
- {{- if .Params.categories }}
- <span class="post__meta-categories meta-categories">
- <svg class="icon icon-category" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 2l1 2h8v11h-16v-13z"/></svg>
- {{ range $index, $category := .Params.categories }}{{ if gt $index 0 }}, {{ end }}<a class="meta-categories__link" href="{{ "/categories/" | relLangURL }}{{ . | urlize | lower }}" rel="category">{{ . }}</a>{{ end }}</span>
- {{- end }}
- </p>
- </header>
- <div class="post__content clearfix">
- {{- if .Params.thumbnail }}
- <figure class="post__thumbnail">
- <img src="{{ .Params.thumbnail | absURL }}" alt="{{ .Title }}">
- </figure>
- {{- end }}
- {{ .Content }}
- </div>
- {{ partial "post_tags.html" . }}
- </article>
- {{ partial "authorbox.html" . }}
- {{ partial "post_nav.html" . }}
- {{ partial "comments.html" . }}
-</div>
+ {{ end }}
+</main>
+{{ partial "pagination.html" . }}
{{ end }}
-
-{{ partial "sidebar.html" . }}
-{{ partial "footer.html" . }}
diff --git a/themes/new_theme/layouts/partials/authorbox.html b/themes/new_theme/layouts/partials/authorbox.html
index cfd09c5..29faa5f 100644
--- a/themes/new_theme/layouts/partials/authorbox.html
+++ b/themes/new_theme/layouts/partials/authorbox.html
@@ -1,13 +1,24 @@
-{{- if .Site.Params.authorbox }}
+{{- if .Param "authorbox" }}
<div class="authorbox clearfix">
+ {{- if and (not .Site.Author.avatar) (not .Site.Author.name) (not .Site.Author.bio) }}
+ <p class="authorbox__warning">
+ <strong>WARNING:</strong> Authorbox is activated, but [Author] parameters are not specified.
+ </p>
+ {{- end }}
+ {{- with .Site.Author.avatar }}
<figure class="authorbox__avatar">
- <img alt="{{ .Site.Author.name }} avatar" src="{{ .Site.Author.avatar | absURL }}" class="avatar" height="90" width="90">
+ <img alt="{{ $.Site.Author.name }} avatar" src="{{ $.Site.Author.avatar | relURL }}" class="avatar" height="90" width="90">
</figure>
+ {{- end }}
+ {{- with .Site.Author.name }}
<div class="authorbox__header">
- <span class="authorbox__name">About {{ .Site.Author.name }}</span>
+ <span class="authorbox__name">{{ T "authorbox_name" . }}</span>
</div>
+ {{- end }}
+ {{- with .Site.Author.bio }}
<div class="authorbox__description">
- {{ .Site.Author.bio }}
+ {{ . | markdownify }}
</div>
+ {{- end }}
</div>
-{{- end }} \ No newline at end of file
+{{- end }}
diff --git a/themes/new_theme/layouts/partials/comments.html b/themes/new_theme/layouts/partials/comments.html
index e69de29..b2e619d 100644
--- a/themes/new_theme/layouts/partials/comments.html
+++ b/themes/new_theme/layouts/partials/comments.html
@@ -0,0 +1,5 @@
+{{ if and .Site.DisqusShortname (index .Params "comments" | default "true") (not .Site.IsServer) }}
+<section class="comments">
+ {{ template "_internal/disqus.html" . }}
+</section>
+{{ end }}
diff --git a/themes/new_theme/layouts/partials/footer.html b/themes/new_theme/layouts/partials/footer.html
index d7fce85..092f258 100644
--- a/themes/new_theme/layouts/partials/footer.html
+++ b/themes/new_theme/layouts/partials/footer.html
@@ -1,15 +1,10 @@
+<footer class="footer">
+ <div class="container footer__container flex">
+ {{ partial "footer_links.html" . }}
+ <div class="footer__copyright">
+ &copy; {{ .Site.Params.copyright_years }}, {{ .Site.Params.Location }}, {{ .Site.Params.author }},
+ <span class="footer__copyright-credits">{{ T "footer_credits" | safeHTML }}</span>
+ , read here about <a href="/dataprotection">Data Protection and Privacy</a>
+ </div>
</div>
- <footer class="footer" itemscope="itemscope" itemtype="http://schema.org/WPFooter">
- <div class="container container-inner">
- <p class="footer__copyright">&copy; {{ .Site.Params.copyright_years }}, {{ .Site.Params.Location }}, {{ .Site.Params.author }}. Based on <a href="//wordpress.org/themes/mh-magazine-lite/" target="_blank" rel="nofollow noopener noreferrer">MH Magazine lite</a>, read here about <a href="/dataprotection">Data Protection and Privacy</a></p>
- </div>
- </footer>
- </div><!-- .mh-container-outer -->
-
-<script>
- var navigation = responsiveNav(".menu", {
- navClass: "menu--collapse",
- });
-</script>
-</body>
-</html>
+</footer>
diff --git a/themes/new_theme/layouts/partials/footer_links.html b/themes/new_theme/layouts/partials/footer_links.html
new file mode 100644
index 0000000..04523e8
--- /dev/null
+++ b/themes/new_theme/layouts/partials/footer_links.html
@@ -0,0 +1,8 @@
+{{- with .Site.Menus.footer }}
+<div class="footer__links">
+ {{ range $key, $value := . }}
+ {{- if ne $key 0 }} | {{ end -}}
+ <a class="footer__link" href="{{ $value.Permalink }}">{{ $value.Name }}</a>
+ {{- end }}
+</div>
+{{- end }}
diff --git a/themes/new_theme/layouts/partials/header.html b/themes/new_theme/layouts/partials/header.html
index 8dff6e7..4548177 100644
--- a/themes/new_theme/layouts/partials/header.html
+++ b/themes/new_theme/layouts/partials/header.html
@@ -1,30 +1,6 @@
-<!DOCTYPE html>
-<html lang="{{ .Site.LanguageCode | default "en-us" }}">
-<head>
-<meta charset="UTF-8">
-<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<title>{{ .Title }}</title>
-{{ with .Site.Params.description }}<meta name="description" content="{{ . }}">{{ end }}
-{{ .Hugo.Generator }}
-{{ if .Site.Params.opengraph }}{{ template "_internal/opengraph.html" . }}{{ end }}
-<link rel="dns-prefetch" href="//fonts.googleapis.com" />
-{{ if .RSSLink }}<link rel="alternate" type="application/rss+xml" title="{{ .Site.Title }} Feed" href="{{ .RSSLink }}">{{ end }}
-<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700" type="text/css" media="all" />
-<link rel="stylesheet" href="{{ .Site.BaseURL }}css/magstyle.css" type="text/css" media="all" />
-<link rel="stylesheet" href="{{ .Site.BaseURL }}css/localstyle.css" type="text/css" media="all" />
-<script type="text/javascript" src="{{ .Site.BaseURL }}js/scripts.js"></script>
-</head>
-<body class="body {{ if (.Site.Params.leftsidebar) or (.Params.leftsidebar) }}body-left-sidebar{{ else }}body-right-sidebar{{ end }} mobile" itemscope="itemscope" itemtype="http://schema.org/WebPage">
- <div class="container container-outer">
- <header class="header" itemscope="itemscope" itemtype="http://schema.org/WPHeader">
- <div class="container container-inner clearfix">
- <div class="logo" role="banner" itemscope="itemscope" itemtype="http://schema.org/Brand">
- <a class="logo__link" href="{{ .Site.BaseURL }}" title="{{ .Site.Title }}" rel="home">
- <h1 class="logo__title">{{ .Site.Params.toptitle }}</h1>
- {{ with .Site.Params.subtitle }}<h2 class="logo__tagline">{{ . }}</h2>{{ end }}
- </a>
- </div>
- </div>
- {{ partial "menu.html" . }}
- </header>
- <div class="wrapper clearfix">
+<header class="header">
+ <div class="container header__container">
+ {{ partial "logo.html" . }}
+ {{ partial "menu.html" . }}
+ </div>
+</header>
diff --git a/themes/new_theme/layouts/partials/header_slide.html b/themes/new_theme/layouts/partials/header_slide.html
index 237da66..68e3b60 100644
--- a/themes/new_theme/layouts/partials/header_slide.html
+++ b/themes/new_theme/layouts/partials/header_slide.html
@@ -33,7 +33,7 @@
<script src="/slide/lib/js/html5shiv.js"></script>
{{ "<![endif]-->" | safeHTML }}
- {{ .Hugo.Generator }}
+ {{ hugo.Generator }}
</head>
<body>
diff --git a/themes/new_theme/layouts/partials/logo.html b/themes/new_theme/layouts/partials/logo.html
new file mode 100644
index 0000000..bf7d668
--- /dev/null
+++ b/themes/new_theme/layouts/partials/logo.html
@@ -0,0 +1,24 @@
+{{- $logoTitle := .Site.Params.logo.title | default .Site.Title -}}
+{{- $logoSubtitle := .Site.Params.logo.subtitle | default .Site.Params.subtitle -}}
+{{- $logoImage := .Site.Params.logo.image -}}
+
+{{- if or $logoTitle $logoImage }}
+ {{/* Defined when logo is mixed (image + text) */}}
+ {{- $logoMix := and $logoImage $logoTitle -}}
+
+ <div class="logo{{ with $logoMix }} logo--mixed{{ end }}">
+ <a class="logo__link" href="{{ "" | relLangURL }}"{{ with $logoTitle }} title="{{ . }}"{{ end }} rel="home">
+ {{ with $logoImage -}}
+ <div class="logo__item logo__imagebox">
+ <img class="logo__img" src="{{ . | relURL }}">
+ </div>
+ {{- end -}}
+ {{ with $logoTitle -}}
+ <div class="logo__item logo__text">
+ <div class="logo__title">{{ . }}</div>
+ {{ with $logoSubtitle }}<div class="logo__tagline">{{ . }}</div>{{ end }}
+ </div>
+ {{- end }}
+ </a>
+ </div>
+{{- end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/mathjax.html b/themes/new_theme/layouts/partials/mathjax.html
new file mode 100644
index 0000000..8a5ea04
--- /dev/null
+++ b/themes/new_theme/layouts/partials/mathjax.html
@@ -0,0 +1,3 @@
+{{ if and .IsPage (eq (.Param "mathjax") true) }}
+<script src="{{ .Param "mathjaxPath" | default "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js" }}{{ with .Param "mathjaxConfig" | default "TeX-AMS-MML_HTMLorMML" }}?config={{ . }}{{ end }}" async></script>
+{{ end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/menu.html b/themes/new_theme/layouts/partials/menu.html
index df9c403..34843c4 100644
--- a/themes/new_theme/layouts/partials/menu.html
+++ b/themes/new_theme/layouts/partials/menu.html
@@ -1,12 +1,23 @@
-<nav class="menu" itemscope="itemscope" itemtype="http://schema.org/SiteNavigationElement">
+{{- if .Site.Menus.main }}
+<nav class="menu">
+ <button class="menu__btn" aria-haspopup="true" aria-expanded="false" tabindex="0">
+ <span class="menu__btn-title" tabindex="-1">{{ T "menu_label" }}</span>
+ </button>
<ul class="menu__list">
- {{- if .Site.Menus.main }}
{{- $currentNode := . }}
- {{- range sort .Site.Menus.main }}
- {{- if ( not ( eq .Name "Data Protection And Privacy" ) ) }}
- <li class="menu__item {{if or ($currentNode.IsMenuCurrent "main" .) ($currentNode.HasMenuCurrent "main" .) }}menu__item--active{{end}}"><a class="menu__link" href="{{ .URL }}">{{ .Name | upper }}</a></li>
- {{- end }}
+ {{- range .Site.Menus.main }}
+ {{- if .Name }}
+ <li class="menu__item{{ if or ($currentNode.IsMenuCurrent "main" .) ($currentNode.HasMenuCurrent "main" .) }} menu__item--active{{ end }}">
+ <a class="menu__link" href="{{ .URL }}">
+ {{ .Pre }}
+ <span class="menu__text">{{ .Name }}</span>
+ {{ .Post }}
+ </a>
+ </li>
{{- end }}
{{- end }}
</ul>
</nav>
+{{ else -}}
+<div class="divider"></div>
+{{- end }}
diff --git a/themes/new_theme/layouts/partials/pager.html b/themes/new_theme/layouts/partials/pager.html
new file mode 100644
index 0000000..78cf9d2
--- /dev/null
+++ b/themes/new_theme/layouts/partials/pager.html
@@ -0,0 +1,22 @@
+{{- if .Param "pager" }}
+{{- if or (.PrevInSection) (.NextInSection) }}
+<nav class="pager flex">
+ {{- if .PrevInSection }}
+ <div class="pager__item pager__item--prev">
+ <a class="pager__link" href="{{ .PrevInSection.RelPermalink }}" rel="prev">
+ <span class="pager__subtitle">«&thinsp;{{ T "post_nav_prev" }}</span>
+ <p class="pager__title">{{ .PrevInSection.Title }}</p>
+ </a>
+ </div>
+ {{- end }}
+ {{- if .NextInSection }}
+ <div class="pager__item pager__item--next">
+ <a class="pager__link" href="{{ .NextInSection.RelPermalink }}" rel="next">
+ <span class="pager__subtitle">{{ T "post_nav_next" }}&thinsp;»</span>
+ <p class="pager__title">{{ .NextInSection.Title }}</p>
+ </a>
+ </div>
+ {{- end }}
+</nav>
+{{- end }}
+{{- end }}
diff --git a/themes/new_theme/layouts/partials/pagination.html b/themes/new_theme/layouts/partials/pagination.html
index 82ad195..8cf40d5 100644
--- a/themes/new_theme/layouts/partials/pagination.html
+++ b/themes/new_theme/layouts/partials/pagination.html
@@ -1,11 +1,13 @@
-{{ if or (.Paginator.HasPrev) (.Paginator.HasNext) }}
-<div class="pagination clearfix">
+{{- if or (.Paginator.HasPrev) (.Paginator.HasNext) }}
+<div class="pagination">
{{- if .Paginator.HasPrev }}
- <a class="pagination__item pagination__item--prev" href="{{ .Paginator.Prev.URL }}">«</a>
+ <a class="pagination__item pagination__item--prev btn" href="{{ .Paginator.Prev.URL }}">«</a>
{{- end }}
- <span class="pagination__item pagination__item--current">{{ .Paginator.PageNumber }}/{{ .Paginator.TotalPages }}</span>
+ <span class="pagination__item pagination__item--current">
+ {{- .Paginator.PageNumber }}/{{ .Paginator.TotalPages -}}
+ </span>
{{- if .Paginator.HasNext }}
- <a class="pagination__item pagination__item--next" href="{{ .Paginator.Next.URL }}">»</a>
+ <a class="pagination__item pagination__item--next btn" href="{{ .Paginator.Next.URL }}">»</a>
{{- end }}
</div>
-{{ end }} \ No newline at end of file
+{{- end }}
diff --git a/themes/new_theme/layouts/partials/post_meta.html b/themes/new_theme/layouts/partials/post_meta.html
new file mode 100644
index 0000000..f357ddb
--- /dev/null
+++ b/themes/new_theme/layouts/partials/post_meta.html
@@ -0,0 +1,7 @@
+{{- $root := . -}}
+{{- with .Param "post_meta" -}}
+ {{- range $field := . -}}
+ {{- $p := printf "post_meta/%s.html" $field -}}
+ {{- partial $p $root -}}
+ {{- end -}}
+{{- end -}} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/post_meta/author.html b/themes/new_theme/layouts/partials/post_meta/author.html
new file mode 100644
index 0000000..0ee0fc9
--- /dev/null
+++ b/themes/new_theme/layouts/partials/post_meta/author.html
@@ -0,0 +1,6 @@
+{{- if .Site.Author.name -}}
+<div class="meta__item-author meta__item">
+ {{ partial "svg/author.svg" (dict "class" "meta__icon") -}}
+ <span class="meta__text">{{ .Site.Author.name }}</span>
+</div>
+{{- end -}} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/post_meta/categories.html b/themes/new_theme/layouts/partials/post_meta/categories.html
new file mode 100644
index 0000000..8ab4202
--- /dev/null
+++ b/themes/new_theme/layouts/partials/post_meta/categories.html
@@ -0,0 +1,16 @@
+{{- $taxo := "categories" -}}
+{{- with .Param $taxo -}}
+<div class="meta__item-categories meta__item">
+ {{- partial "svg/category.svg" (dict "class" "meta__icon") -}}
+ <span class="meta__text">
+ {{- range $index, $category := . }}
+ {{- $url := urls.Parse ($category | urlize) -}}
+ {{- $path := $url.Path -}}
+ {{- with $.Site.GetPage (printf "/%s/%s" $taxo $path) }}
+ {{- if gt $index 0 }}, {{ end -}}
+ <a class="meta__link" href="{{ .RelPermalink }}" rel="category">{{ .Title }}</a>
+ {{- end }}
+ {{- end }}
+ </span>
+</div>
+{{- end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/post_meta/date.html b/themes/new_theme/layouts/partials/post_meta/date.html
new file mode 100644
index 0000000..24a6c32
--- /dev/null
+++ b/themes/new_theme/layouts/partials/post_meta/date.html
@@ -0,0 +1,13 @@
+{{- if not .Date.IsZero }}
+<div class="meta__item-datetime meta__item">
+ {{ partial "svg/time.svg" (dict "class" "meta__icon") -}}
+ <time class="meta__text" datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">
+ {{- .Date.Format (.Site.Params.dateformat | default "January 02, 2006") -}}
+ </time>
+ {{- if ne .Date .Lastmod }}
+ <time class="meta__text" datetime="{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}">(
+ {{- T "meta_lastmod" }}: {{ .Lastmod.Format (.Site.Params.dateformat | default "January 02, 2006") -}}
+ )</time>
+ {{- end -}}
+</div>
+{{- end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/post_meta/translations.html b/themes/new_theme/layouts/partials/post_meta/translations.html
new file mode 100644
index 0000000..34d1172
--- /dev/null
+++ b/themes/new_theme/layouts/partials/post_meta/translations.html
@@ -0,0 +1,10 @@
+{{- if .IsTranslated }}
+<div class="meta__item-translations meta__item">
+ <span class="meta__text">
+ {{- T "meta_translations" }}: {{ range $index, $translation := .Translations }}
+ {{- if gt $index 0 }}, {{ end -}}
+ <a class="meta__link" href="{{ .RelPermalink }}">{{ .Lang | upper }}</a>
+ {{- end }}
+ </span>
+</div>
+{{- end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/post_tags.html b/themes/new_theme/layouts/partials/post_tags.html
index 549c76b..f21f372 100644
--- a/themes/new_theme/layouts/partials/post_tags.html
+++ b/themes/new_theme/layouts/partials/post_tags.html
@@ -1,10 +1,14 @@
{{- if .Params.tags }}
<div class="post__tags tags clearfix">
- <svg class="icon icon-tag" width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m4.73135 3.3795002q0-.5597-.39604-.9557-.39604-.3961-.95577-.3961-.55974 0-.95578.3961-.39604.396-.39604.9557 0 .5598.39604.9558.39604.3961.95578.3961.55973 0 .95577-.3961.39604-.396.39604-.9558zm11.26865 6.0832q0 .5596998-.39076.9504998l-5.18548 5.196q-.41188.3908-.9610504.3908-.55974 0-.9505-.3908l-7.5511496-7.5616998q-.40132-.3907-.68119-1.0666-.27987-.6759-.27987-1.2357v-4.3934q0-.54920004.40132-.95050004.40132-.4013.9505-.4013h4.39339q.55974 0 1.23565.2799.67591.2798 1.07723.6812l7.55115 7.54060004q.39076.4118.39076.961z"/></svg>
+ {{ partial "svg/tag.svg" (dict "class" "tags__badge") }}
<ul class="tags__list">
{{- range .Params.tags }}
- <li class="tags__item"><a class="tags__link" href="/tags/{{ . | urlize }}/" rel="tag">{{ . }}</a></li>
+ <li class="tags__item">
+ <a class="tags__link btn" href="{{ "tags/" | relLangURL }}{{ . | urlize }}/" rel="tag">
+ {{- . -}}
+ </a>
+ </li>
{{- end }}
</ul>
</div>
-{{- end }} \ No newline at end of file
+{{- end }}
diff --git a/themes/new_theme/layouts/partials/post_toc.html b/themes/new_theme/layouts/partials/post_toc.html
new file mode 100644
index 0000000..2133247
--- /dev/null
+++ b/themes/new_theme/layouts/partials/post_toc.html
@@ -0,0 +1,8 @@
+{{ if .Param "toc" }}
+<div class="post__toc toc">
+ <div class="toc__title">{{ T "toc_title" }}</div>
+ <div class="toc__menu">
+ {{ .TableOfContents }}
+ </div>
+</div>
+{{ end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/ranklist.html b/themes/new_theme/layouts/partials/ranklist_elasticlunr.html
index 5c7786b..5c7786b 100644
--- a/themes/new_theme/layouts/partials/ranklist.html
+++ b/themes/new_theme/layouts/partials/ranklist_elasticlunr.html
diff --git a/themes/new_theme/layouts/partials/ranklist_fts5.html b/themes/new_theme/layouts/partials/ranklist_fts5.html
new file mode 100644
index 0000000..69c0f39
--- /dev/null
+++ b/themes/new_theme/layouts/partials/ranklist_fts5.html
@@ -0,0 +1,152 @@
+<script src="/js/jquery.js" type="text/javascript"></script>
+<script src="/js/url-search-params.js" type="text/javascript"></script>
+<script src="/js/loadingoverlay.min.js" type="text/javascript"></script>
+<script src="/js/require.js" type="text/javascript"></script>
+
+<script language="Javascript">
+
+ function escapeHtml( text ) {
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;" );
+ }
+
+ function draw_ranklist( query, results ) {
+ var html = '';
+
+ if( results.length == 0 ) {
+ return "<p>No hits for query '" + query + "'...</p>";
+ } else {
+ html += "<p>" + results.length + " hits found</p>";
+ }
+
+ var start = 1;
+ html += "<ol class=\"ranklist\" start=\"" + start + "\">";
+ for( var i = 0; i < results.length; i++ ) {
+ var rank = results[i];
+ var docid = rank['docid'];
+ var abstract = rank['abstract'];
+ var title = rank['title'];
+ if( title == '' ) {
+ title = 'No title';
+ }
+ html += "<li>";
+ html += "<div class='title'>"
+ html += "<a href=\"" + docid + "\">" + title + "</a></div>";
+ if( abstract != '' ) {
+ html += "<div class='abstract'>" + abstract + "</div>";
+ }
+ html += "</li>";
+ }
+ html += "</ol>";
+
+ return html;
+ }
+
+ function submitQuery( ) {
+ try {
+ if( window.location.pathname.includes( "/search/") ) {
+ var q = $( "#query" ).val( );
+ executeQuery( q );
+ return false;
+ } else {
+ return true;
+ }
+ } catch( e ) {
+ alert( e );
+ }
+ }
+
+ var index_loaded = false;
+ var SQL;
+ var db;
+ var stmt;
+
+ function loadIndex( success, fail ) {
+ if( !index_loaded ) {
+ const xhr = new XMLHttpRequest( );
+ xhr.open( 'GET', '/index/posts.db', true );
+ xhr.responseType = 'arraybuffer';
+ xhr.onload = e => {
+ if( ( xhr.status == 0 ) || ( xhr.status == 200 ) ) {
+ const uInt8Array = new Uint8Array( xhr.response );
+ requirejs(["/js/sql-wasm.js"], function(initSqlJs) {
+
+ SQL = initSqlJs( {
+ locateFile: file => `/js/${file}`
+ } );
+
+ initSqlJs( ).then( function( SQL ) {
+ db = new SQL.Database(uInt8Array);
+ stmt = db.prepare( "select uri as docid,title,snippet(posts, 2, '<b>', '</b>', '...', 50) as abstract from posts where posts MATCH @query ORDER BY bm25(posts)" );
+
+ index_loaded = true;
+
+ success( );
+ } );
+ } );
+ } else {
+ const uInt8Array = new Uint8Array( xhr.response );
+ const decoder = new TextDecoder( );
+ const msg = decoder.decode( uInt8Array );
+ fail( xhr.status, xhr.statusText, msg );
+ }
+ }
+ xhr.send( );
+ } else {
+ success( );
+ }
+ }
+
+ function executeQuery( query ) {
+ $( "#query" ).LoadingOverlay( "show" );
+
+ loadIndex(
+ function( ) {
+ stmt.bind( {'@query' : query} );
+
+ var html;
+ try {
+ var results = [];
+ while( stmt.step( ) ) {
+ var row = stmt.getAsObject( );
+ results.push( row );
+ }
+
+ html = draw_ranklist( query, results );
+ } catch( e ) {
+ html = "<pre><font color='red'>There was an error executing the query '" + query + "', reason: " + e + "</font></pre>\n";
+ }
+
+ $( '#ranklist' ).html( html );
+
+ $( "#query" ).LoadingOverlay( "hide" );
+ },
+ function( status, statusText, msg ) {
+ var html = "<pre><font color='red'>There was an error executing the query '" + query + "', reason: " + status + " " + statusText + "</font></pre>\n";
+ $( '#ranklist' ).html( html );
+ $( "#query" ).LoadingOverlay( "hide" );
+ }
+ );
+ }
+
+ $( window ).load( function( ) {
+ var paramsString = window.location.search;
+ var searchParams = new URLSearchParams( paramsString );
+ if( searchParams.has( "q" ) ) {
+ var q = searchParams.get( "q" )
+ $( "#query" ).val( q );
+ executeQuery( q );
+ } else {
+ // TODO: come up with something here
+ } // Show full page LoadingOverlay
+ } );
+
+ $( window ).unload( function( ) {
+ if( index_loaded ) {
+ stmt.free( );
+ db.close( );
+ index_loaded = false;
+ }
+ } );
+</script>
+<div id="ranklist">
+</div>
diff --git a/themes/new_theme/layouts/partials/sidebar.html b/themes/new_theme/layouts/partials/sidebar.html
index 1147dd2..c4fd283 100644
--- a/themes/new_theme/layouts/partials/sidebar.html
+++ b/themes/new_theme/layouts/partials/sidebar.html
@@ -1,10 +1,22 @@
-<aside class="sidebar" itemscope="itemscope" itemtype="http://schema.org/WPSideBar">
- {{ partial "widgets/dataprotection.html" . }}
- {{ partial "widgets/elasticlunr_search.html" . }}
- {{ $section := .Section }}
- {{ if or ( eq $section "blog" ) ( eq $section "" ) }}
- {{ partial "widgets/recent.html" . }}
- {{ partial "widgets/categories.html" . }}
- {{ partial "widgets/taglist.html" . }}
- {{ end }}
+{{- $sidebar := false }}
+{{- if eq .Kind "home" -}}
+ {{ $sidebar = (default .Site.Params.sidebar.home .Params.sidebar) }}
+{{- else if eq .Kind "page" -}}
+ {{ $sidebar = (default .Site.Params.sidebar.single .Params.sidebar) }}
+{{- else -}}
+ {{ $sidebar = (default .Site.Params.sidebar.list .Params.sidebar) }}
+{{ end }}
+
+{{- if $sidebar -}}
+<aside class="sidebar{{ if eq $sidebar "left" }} sidebar--left{{ end }}">
+{{- $root := . }}
+{{- with (default .Site.Params.sidebar.widgets .Params.widgets) -}}
+ {{- range $widget := . }}
+ {{- $p := printf "widgets/%s.html" $widget }}
+ {{- partial $p $root }}
+ {{- end }}
+{{- else }}
+ <p class="sidebar__warning"><strong>{{ T "sidebar_warning" }}:</strong><br>{{ T "sidebar_recommendation" }}</p>
+{{- end }}
</aside>
+{{- end }}
diff --git a/themes/new_theme/layouts/partials/svg/author.svg b/themes/new_theme/layouts/partials/svg/author.svg
new file mode 100644
index 0000000..0be6d81
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/author.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-author" width="16" height="16" viewBox="0 0 12 16"><path d="M6 1c2.2 0 3.5 2 3.5 4.5C9.5 7 8.9 8.2 8 9c2.9.8 4 2.5 4 5v1H0v-1c0-2.5 1.1-4.2 4-5-.9-.8-1.5-2-1.5-3.5C2.5 3 3.8 1 6 1z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/bitbucket.svg b/themes/new_theme/layouts/partials/svg/bitbucket.svg
new file mode 100644
index 0000000..0f10764
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/bitbucket.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-bitbucket" width="24" height="24" viewBox="0 0 256 231"><path d="M8.308 0A8.202 8.202 0 0 0 .106 9.516l34.819 211.373a11.155 11.155 0 0 0 10.909 9.31h167.04a8.202 8.202 0 0 0 8.201-6.89l34.82-213.752a8.202 8.202 0 0 0-8.203-9.514L8.308 0zm146.616 152.768h-53.315l-14.436-75.42h80.67l-12.919 75.42z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/category.svg b/themes/new_theme/layouts/partials/svg/category.svg
new file mode 100644
index 0000000..89f9f21
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/category.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-category" width="16" height="16" viewBox="0 0 16 16"><path d="m7 2l1 2h8v11h-16v-13z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/email.svg b/themes/new_theme/layouts/partials/svg/email.svg
new file mode 100644
index 0000000..8fd8467
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/email.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-mail" width="24" height="24" viewBox="0 0 416 288"><path d="m0 16v256 16h16 384 16v-16-256-16h-16-384-16zm347 16-139 92.5-139-92.5zm-148 125.5 9 5.5 9-5.5 167-111.5v210h-352v-210z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/facebook.svg b/themes/new_theme/layouts/partials/svg/facebook.svg
new file mode 100644
index 0000000..24babe2
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/facebook.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-facebook" width="24" height="24" viewBox="0 0 352 352"><path d="m0 32v288c0 17.5 14.5 32 32 32h288c17.5 0 32-14.5 32-32v-288c0-17.5-14.5-32-32-32h-288c-17.5 0-32 14.5-32 32zm320 0v288h-83v-108h41.5l6-48h-47.5v-31c0-14 3.5-23.5 23.5-23.5h26v-43.5c-4.4-.6-19.8-1.5-37.5-1.5-36.9 0-62 22.2-62 63.5v36h-42v48h42v108h-155v-288z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/files.svg b/themes/new_theme/layouts/partials/svg/files.svg
new file mode 100644
index 0000000..72af481
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/files.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-files" width="96" height="96" viewBox="0 0 384 384"><path d="m368 64h-224-16v16 288 16h16 224 16v-16-288-16zm-16 288h-192v-256h192zm-320-320h192v16h32v-32-16h-16-224-16v16 288 16h16 96v-32h-80zm144 272h160v-32h-160zm0-64h160v-32h-160zm0-64h160v-32h-160zm-128 64h64v-32h-64zm0-64h64v-32h-64zm0-64h64v-32h-64z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/github.svg b/themes/new_theme/layouts/partials/svg/github.svg
new file mode 100644
index 0000000..e694a12
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/github.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-github" width="24" height="24" viewBox="0 0 384 374"><path d="m192 0c-106.1 0-192 85.8-192 191.7 0 84.7 55 156.6 131.3 181.9 9.6 1.8 13.1-4.2 13.1-9.2 0-4.6-.2-16.6-.3-32.6-53.4 11.6-64.7-25.7-64.7-25.7-8.7-22.1-21.3-28-21.3-28-17.4-11.9 1.3-11.6 1.3-11.6 19.3 1.4 29.4 19.8 29.4 19.8 17.1 29.3 44.9 20.8 55.9 15.9 1.7-12.4 6.7-20.8 12.2-25.6-42.6-4.8-87.5-21.3-87.5-94.8 0-20.9 7.5-38 19.8-51.4-2-4.9-8.6-24.3 1.9-50.7 0 0 16.1-5.2 52.8 19.7 15.3-4.2 31.7-6.4 48.1-6.5 16.3.1 32.7 2.2 48.1 6.5 36.7-24.8 52.8-19.7 52.8-19.7 10.5 26.4 3.9 45.9 1.9 50.7 12.3 13.4 19.7 30.5 19.7 51.4 0 73.7-44.9 89.9-87.7 94.6 6.9 5.9 13 17.6 13 35.5 0 25.6-.2 46.3-.2 52.6 0 5.1 3.5 11.1 13.2 9.2 76.2-25.5 131.2-97.3 131.2-182 0-105.9-86-191.7-192-191.7z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/gitlab.svg b/themes/new_theme/layouts/partials/svg/gitlab.svg
new file mode 100644
index 0000000..1efadbe
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/gitlab.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-gitlab" width="24" height="24" viewBox="0 0 265 265"><path d="M128.075 236.075l47.104-144.97H80.97l47.104 144.97z M14.956 91.104L.642 135.16a9.752 9.752 0 0 0 3.542 10.903l123.891 90.012-113.12-144.97z M14.956 91.105H80.97L52.601 3.79c-1.46-4.493-7.816-4.492-9.275 0l-28.37 87.315z M241.194 91.104l14.314 44.056a9.752 9.752 0 0 1-3.543 10.903l-123.89 90.012 113.119-144.97z M241.194 91.105h-66.015l28.37-87.315c1.46-4.493 7.816-4.492 9.275 0l28.37 87.315z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/instagram.svg b/themes/new_theme/layouts/partials/svg/instagram.svg
new file mode 100644
index 0000000..47bed7f
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/instagram.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-instagram" width="24" height="24" viewBox="0 0 256 256"><circle cx="193" cy="59" r="15"/><path fill-rule="evenodd" d="M101 0h54c41 0 58.4 3.9 74.5 17C256.2 37.5 256 74.8 256 97.7v60c0 26.7 0 60.4-26.5 81.4-16 13.4-33.5 16.9-74.5 16.9h-54c-41 0-57.5-3.5-74.5-16.9C1 218.9.5 186.3.1 160.5L0 155V97.7c0-23-.2-60.2 26.5-80.7C45 2 60 0 101 0zm4.9 23h44.3c45.8 0 58.3 3.5 70.3 17.5 11.8 13.2 12 30.1 12.5 62.9V156c.2 20.8.3 45.8-12.5 59.5-12 14-24.5 17.5-70.3 17.5h-44.3c-45.9 0-57.3-3.5-70.4-17.5-12.2-13-12.3-36.5-12.4-56.7v-55.6c.4-32.6.7-49.6 12.4-62.7C48 26.5 60 23 105.9 23zm19.6 144.5a42 42 0 1 0 0-84 42 42 0 0 0 0 84zm0 22.5a64.5 64.5 0 1 0 0-129 64.5 64.5 0 0 0 0 129z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/linkedin.svg b/themes/new_theme/layouts/partials/svg/linkedin.svg
new file mode 100644
index 0000000..4fe2234
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/linkedin.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-linkedin" width="24" height="24" viewBox="0 0 352 352"><path d="M0,40v272c0,21.9,18.1,40,40,40h272c21.9,0,40-18.1,40-40V40c0-21.9-18.1-40-40-40H40C18.1,0,0,18.1,0,40z M312,32 c4.6,0,8,3.4,8,8v272c0,4.6-3.4,8-8,8H40c-4.6,0-8-3.4-8-8V40c0-4.6,3.4-8,8-8H312z M59.5,87c0,15.2,12.3,27.5,27.5,27.5 c15.2,0,27.5-12.3,27.5-27.5c0-15.2-12.3-27.5-27.5-27.5C71.8,59.5,59.5,71.8,59.5,87z M187,157h-1v-21h-45v152h47v-75 c0-19.8,3.9-39,28.5-39c24.2,0,24.5,22.4,24.5,40v74h47v-83.5c0-40.9-8.7-72-56.5-72C208.5,132.5,193.3,145.1,187,157z M64,288h47.5 V136H64V288z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/tag.svg b/themes/new_theme/layouts/partials/svg/tag.svg
new file mode 100644
index 0000000..ccc7d50
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/tag.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-tag" width="16" height="16" viewBox="0 0 32 32"><path d="M32 19c0 1-1 2-1 2L21 31s-1 1-2 1-2-1-2-1L2 16c-1-1-1.4-2-1.4-2S0 12.5 0 11V3C0 1.5.8.8.8.8S1.5 0 3 0h8c1.5 0 3 .6 3 .6S15 1 16 2l15 15s1 1 1 2zM7 10a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/telegram.svg b/themes/new_theme/layouts/partials/svg/telegram.svg
new file mode 100644
index 0000000..c22ab56
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/telegram.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-telegram" width="24" height="24" viewBox="0 0 132 110"><path fill="#ddd" d="M50 103c-4 0-3-1-5-5L34 60l88-52"/><path fill="#aaa" d="M50 103c3 0 4-1 6-3l16-16-20-12"/><path fill="#fff" d="M52 72l48 36c6 3 10 2 11-5l20-93c2-8-3-11-8-9L7 45c-8 4-8 8-1 10l29 9 69-43c3-2 6-1 4 1"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/time.svg b/themes/new_theme/layouts/partials/svg/time.svg
new file mode 100644
index 0000000..b6c6e96
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/time.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-time" width="16" height="14" viewBox="0 0 30 28"><path d="M15 0C7 0 1 6 1 14s6 14 14 14 14-6 14-14S23 0 15 0zm0 25C9 25 4 20 4 14S9 3 15 3s11 5 11 11-5 11-11 11zm1-18h-2v8.4l6.8 4.4L22 18l-6-3.8V7z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/svg/twitter.svg b/themes/new_theme/layouts/partials/svg/twitter.svg
new file mode 100644
index 0000000..a78e073
--- /dev/null
+++ b/themes/new_theme/layouts/partials/svg/twitter.svg
@@ -0,0 +1 @@
+<svg class="{{ with .class }}{{ . }} {{ end }}icon icon-twitter" width="24" height="24" viewBox="0 0 384 312"><path d="m384 36.9c-14.1 6.3-29.3 10.5-45.2 12.4 16.3-9.7 28.8-25.2 34.6-43.6-15.2 9-32.1 15.6-50 19.1-14.4-15.2-34.9-24.8-57.5-24.8-43.5 0-78.8 35.3-78.8 78.8 0 6.2.7 12.2 2 17.9-65.5-3.3-123.5-34.6-162.4-82.3-6.7 11.6-10.6 25.2-10.6 39.6 0 27.3 13.9 51.4 35 65.6-12.9-.4-25.1-4-35.7-9.9v1c0 38.2 27.2 70 63.2 77.2-6.6 1.8-13.6 2.8-20.8 2.8-5.1 0-10-.5-14.8-1.4 10 31.3 39.1 54.1 73.6 54.7-27 21.1-60.9 33.7-97.8 33.7-6.4 0-12.6-.4-18.8-1.1 34.9 22.4 76.3 35.4 120.8 35.4 144.9 0 224.1-120 224.1-224.1 0-3.4-.1-6.8-.2-10.2 15.4-11.1 28.7-25 39.3-40.8z"/></svg> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/widgets/categories.html b/themes/new_theme/layouts/partials/widgets/categories.html
index 7b93a4e..4998c44 100644
--- a/themes/new_theme/layouts/partials/widgets/categories.html
+++ b/themes/new_theme/layouts/partials/widgets/categories.html
@@ -1,16 +1,17 @@
-{{- if .Site.Params.widgets.categories }}
-{{- if isset .Site.Taxonomies "categories" }}
-{{- if not (eq (len .Site.Taxonomies.categories) 0) }}
+{{- $categories := .Site.Taxonomies.categories }}
+{{- if gt (len $categories) 0 }}
<div class="widget-categories widget">
- <h4 class="widget__title">Categories</h4>
+ <h4 class="widget__title">{{ T "categories_title" }}</h4>
<div class="widget__content">
<ul class="widget__list">
- {{- range $name, $items := .Site.Taxonomies.categories }}
- <li class="widget__item"><a class="widget__link" href="{{ $.Site.BaseURL }}categories/{{ $name | urlize | lower }}">{{ $name | title }}</a></li>
+ {{- range $name, $taxonomy := $categories }}
+ {{- with $.Site.GetPage (printf "/categories/%s" $name) }}
+ <li class="widget__item">
+ <a class="widget__link" href="{{ .RelPermalink }}">{{ .Title }}</a>
+ </li>
{{- end }}
+ {{- end }}
</ul>
</div>
</div>
{{- end }}
-{{- end }}
-{{- end }}
diff --git a/themes/new_theme/layouts/partials/widgets/elasticlunr_search.html b/themes/new_theme/layouts/partials/widgets/elasticlunr_search.html
index 9fa5b34..5da7a2a 100644
--- a/themes/new_theme/layouts/partials/widgets/elasticlunr_search.html
+++ b/themes/new_theme/layouts/partials/widgets/elasticlunr_search.html
@@ -1,15 +1,13 @@
-{{- if .Site.Params.widgets.search }}
<h4 class="widget__title">Search</h4>
<div class="widget-search widget">
<form class="widget-search__form" role="search" method="get" action="/search/">
<label>
- <span class="screen-reader-text">Search for:</span>
- <input class="widget-search__field" type="search" autocomplete="off" placeholder="SEARCH..." value="" id="query" name="q">
+ <input class="widget-search__field" type="search" autocomplete="off" placeholder="{{ T "search_placeholder" }}" value="" id="query" name="q" aria-label="{{ T "search_placeholder" }}">
</label>
<input class="widget-search__submit" type="submit" value="Search">
</form>
</div>
-{{- if ( eq .URL "/search/" ) }}
+{{- if ( eq .Permalink "/search/" ) }}
<script language="Javascript">
$( window ).load( function( ) {
var paramsString = window.location.search;
@@ -21,6 +19,3 @@
} );
</script>
{{- end }}
-{{- end }}
-
-
diff --git a/themes/new_theme/layouts/partials/widgets/fts5_search.html b/themes/new_theme/layouts/partials/widgets/fts5_search.html
new file mode 100644
index 0000000..7f58e32
--- /dev/null
+++ b/themes/new_theme/layouts/partials/widgets/fts5_search.html
@@ -0,0 +1,21 @@
+<h4 class="widget__title">Search</h4>
+<div class="widget-search widget">
+ <form id="search_form" class="widget-search__form" role="search" method="get" action="/search/" onsubmit="return submitQuery( );">
+ <label>
+ <input class="widget-search__field" type="search" autocomplete="off" placeholder="{{ T "search_placeholder" }}" value="" id="query" name="q" aria-label="{{ T "search_placeholder" }}">
+ </label>
+ <input class="widget-search__submit" type="submit" value="Search">
+ </form>
+</div>
+{{- if ( eq .Permalink "/search/" ) }}
+<script language="Javascript">
+ $( window ).load( function( ) {
+ var paramsString = window.location.search;
+ var searchParams = new URLSearchParams( paramsString );
+ if( searchParams.has( "q" ) ) {
+ $( "#query" ).val( searchParams.get( "q" ) );
+ $( "#query" ).removeAttr( "placeholder" );
+ }
+ } );
+</script>
+{{- end }}
diff --git a/themes/new_theme/layouts/partials/widgets/languages.html b/themes/new_theme/layouts/partials/widgets/languages.html
new file mode 100644
index 0000000..e54adb1
--- /dev/null
+++ b/themes/new_theme/layouts/partials/widgets/languages.html
@@ -0,0 +1,20 @@
+{{- $translations := .Site.Home.AllTranslations }}
+{{- if and .Site.IsMultiLingual (gt (len $translations) 0) }}
+<div class="widget-languages widget">
+ <h4 class="widget__title">{{ T "languages_title" }}</h4>
+ <div class="widget__content">
+ <ul class="widget__list">
+ {{- range $translations }}
+ <li class="widget__item">
+ <a class="widget-languages__link widget__link" href="{{ .RelPermalink }}">
+ <span class="widget-languages__link-btn widget__link-btn btn">{{ .Language | upper }}</span>
+ {{- with .Language.LanguageName }}
+ <span class="widget-languages__link-text widget__link-text">{{ . | title | humanize }}</span>
+ {{- end }}
+ </a>
+ </li>
+ {{- end }}
+ </ul>
+ </div>
+</div>
+{{- end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/widgets/recent.html b/themes/new_theme/layouts/partials/widgets/recent.html
index 6aaee19..c264062 100644
--- a/themes/new_theme/layouts/partials/widgets/recent.html
+++ b/themes/new_theme/layouts/partials/widgets/recent.html
@@ -1,9 +1,12 @@
-{{- if .Site.Params.widgets.recent_articles }}
+{{- $recent := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
+{{- $recent_num := (.Site.Params.widgets.recent_num | default 10) }}
+
+{{- if $recent }}
<div class="widget-recent widget">
- <h4 class="widget__title">Recent Posts</h4>
+ <h4 class="widget__title">{{ T "recent_title" }}</h4>
<div class="widget__content">
<ul class="widget__list">
- {{- range first 10 (where .Site.Pages "Section" "blog") }}
+ {{- range first $recent_num $recent }}
<li class="widget__item"><a class="widget__link" href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{- end }}
</ul>
diff --git a/themes/new_theme/layouts/partials/widgets/search.html b/themes/new_theme/layouts/partials/widgets/search.html
new file mode 100644
index 0000000..d6b1652
--- /dev/null
+++ b/themes/new_theme/layouts/partials/widgets/search.html
@@ -0,0 +1,9 @@
+<div class="widget-search widget">
+ <form class="widget-search__form" role="search" method="get" action="https://google.com/search">
+ <label>
+ <input class="widget-search__field" type="search" placeholder="{{ T "search_placeholder" }}" value="" name="q" aria-label="{{ T "search_placeholder" }}">
+ </label>
+ <input class="widget-search__submit" type="submit" value="Search">
+ <input type="hidden" name="sitesearch" value="{{ .Site.BaseURL }}" />
+ </form>
+</div> \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/widgets/sidemenu.html b/themes/new_theme/layouts/partials/widgets/sidemenu.html
new file mode 100644
index 0000000..2369233
--- /dev/null
+++ b/themes/new_theme/layouts/partials/widgets/sidemenu.html
@@ -0,0 +1,14 @@
+{{ if .Site.Menus.side }}
+<div class="widget-sidemenu widget">
+ <h4 class="widget__title">{{ T "sidemenu_title" }}</h4>
+ <nav class="widget__content">
+ <ul class="widget__list">
+ {{ range .Site.Menus.side }}
+ <li class="widget__item">
+ <a class="widget__link" href="{{ .URL }}">{{ .Name }}</a>
+ </li>
+ {{ end }}
+ </ul>
+ </nav>
+</div>
+{{ end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/widgets/social.html b/themes/new_theme/layouts/partials/widgets/social.html
new file mode 100644
index 0000000..7f8faa9
--- /dev/null
+++ b/themes/new_theme/layouts/partials/widgets/social.html
@@ -0,0 +1,90 @@
+{{- if .Site.Params.widgets.social }}
+<div class="widget-social widget">
+ <h4 class="widget-social__title widget__title">{{ T "social_title" }}</h4>
+ <div class="widget-social__content widget__content">
+ {{- with .Site.Params.widgets.social.facebook }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="Facebook" rel="noopener noreferrer" href="https://facebook.com/{{ . }}" target="_blank">
+ {{ partial "svg/facebook.svg" (dict "class" "widget-social__link-icon") }}
+ <span>Facebook</span>
+ </a>
+ </div>
+ {{- end }}
+ {{- with .Site.Params.widgets.social.twitter }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="Twitter" rel="noopener noreferrer" href="https://twitter.com/{{ . }}" target="_blank">
+ {{ partial "svg/twitter.svg" (dict "class" "widget-social__link-icon") }}
+ <span>Twitter</span>
+ </a>
+ </div>
+ {{- end }}
+ {{- with .Site.Params.widgets.social.instagram }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="Instagram" rel="noopener noreferrer" href="https://www.instagram.com/{{ . }}" target="_blank">
+ {{ partial "svg/instagram.svg" (dict "class" "widget-social__link-icon") }}
+ <span>Instagram</span>
+ </a>
+ </div>
+ {{- end }}
+ {{- with .Site.Params.widgets.social.linkedin }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="LinkedIn" rel="noopener noreferrer" href="https://linkedin.com/in/{{ . }}" target="_blank">
+ {{ partial "svg/linkedin.svg" (dict "class" "widget-social__link-icon") }}
+ <span>LinkedIn</span>
+ </a>
+ </div>
+ {{- end }}
+ {{- with .Site.Params.widgets.social.telegram }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="Telegram" rel="noopener noreferrer" href="https://t.me/{{ . }}" target="_blank">
+ {{ partial "svg/telegram.svg" (dict "class" "widget-social__link-icon") }}
+ <span>Telegram</span>
+ </a>
+ </div>
+ {{- end }}
+ {{- with .Site.Params.widgets.social.github }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="GitHub" rel="noopener noreferrer" href="https://github.com/{{ . }}" target="_blank">
+ {{ partial "svg/github.svg" (dict "class" "widget-social__link-icon") }}
+ <span>GitHub</span>
+ </a>
+ </div>
+ {{- end }}
+ {{- with .Site.Params.widgets.social.gitlab }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="GitLab" rel="noopener noreferrer" href="https://gitlab.com/{{ . }}" target="_blank">
+ {{ partial "svg/gitlab.svg" (dict "class" "widget-social__link-icon") }}
+ <span>GitLab</span>
+ </a>
+ </div>
+ {{- end }}
+ {{- with .Site.Params.widgets.social.bitbucket }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="Bitbucket" rel="noopener noreferrer" href="https://bitbucket.org/{{ . }}" target="_blank">
+ {{ partial "svg/bitbucket.svg" (dict "class" "widget-social__link-icon") }}
+ <span>Bitbucket</span>
+ </a>
+ </div>
+ {{- end }}
+ {{- with .Site.Params.widgets.social.email }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="Email" href="mailto:{{ . }}">
+ {{ partial "svg/email.svg" (dict "class" "widget-social__link-icon") }}
+ <span>{{ . }}</span>
+ </a>
+ </div>
+ {{- end }}
+
+ {{ range .Site.Params.widgets.social.custom }}
+ <div class="widget-social__item widget__item">
+ <a class="widget-social__link widget__link btn" title="{{ .title }}" rel="noopener noreferrer" href="{{ .url }}" target="_blank">
+ {{- if .icon }}
+ {{ partial .icon (dict "class" "widget-social__link-icon") }}
+ {{- end }}
+ <span>{{ .title }}</span>
+ </a>
+ </div>
+ {{ end }}
+ </div>
+</div>
+{{- end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/partials/widgets/taglist.html b/themes/new_theme/layouts/partials/widgets/taglist.html
index 966205a..9b6046b 100644
--- a/themes/new_theme/layouts/partials/widgets/taglist.html
+++ b/themes/new_theme/layouts/partials/widgets/taglist.html
@@ -1,14 +1,15 @@
-{{- if .Site.Params.widgets.tags }}
-{{- if isset .Site.Taxonomies "tags" }}
-{{- if not (eq (len .Site.Taxonomies.tags) 0) }}
+{{- $tags := .Site.Taxonomies.tags }}
+{{- if gt (len $tags) 0 }}
<div class="widget-taglist widget">
- <h4 class="widget__title">Tags</h4>
+ <h4 class="widget__title">{{ T "tags_title" }}</h4>
<div class="widget__content">
- {{- range $name, $items := .Site.Taxonomies.tags }}
- <a class="widget__link widget__link--taglist" href="{{ $.Site.BaseURL }}tags/{{ $name | urlize | lower }}" title="{{ $name }}">{{ $name }}</a>
+ {{- range $name, $taxonomy := $tags }}
+ {{- with $.Site.GetPage (printf "/tags/%s" $name) }}
+ <a class="widget-taglist__link widget__link btn" href="{{ .RelPermalink }}" title="{{ .Title }}">
+ {{- .Title -}}{{- if .Site.Params.widgets.tags_counter }} ({{ $taxonomy.Count }}){{ end -}}
+ </a>
{{- end }}
+ {{- end }}
</div>
</div>
{{- end }}
-{{- end }}
-{{- end }} \ No newline at end of file
diff --git a/themes/new_theme/layouts/robots.txt b/themes/new_theme/layouts/robots.txt
index bb43e33..981f0df 100644
--- a/themes/new_theme/layouts/robots.txt
+++ b/themes/new_theme/layouts/robots.txt
@@ -1,3 +1,3 @@
User-agent: *
-Disallow: /wiki/
-Disallow: /crux/
+Disallow:
+Sitemap: http://www.andreasbaumann.cc/sitemap.xml
diff --git a/themes/new_theme/layouts/slide/single.html b/themes/new_theme/layouts/slide/single.html
index cd03267..48c1012 100644
--- a/themes/new_theme/layouts/slide/single.html
+++ b/themes/new_theme/layouts/slide/single.html
@@ -1,6 +1,6 @@
{{ partial "header_slide.html" . }}
-{{ .Content }}
+{{ .RawContent | htmlUnescape | safeHTML }}
{{ partial "footer_slide.html" . }}
diff --git a/themes/new_theme/static/apple-touch-icon.png b/themes/new_theme/static/apple-touch-icon.png
new file mode 100644
index 0000000..441def4
--- /dev/null
+++ b/themes/new_theme/static/apple-touch-icon.png
Binary files differ
diff --git a/themes/new_theme/static/favicon.ico b/themes/new_theme/static/favicon.ico
new file mode 100644
index 0000000..b7a49cc
--- /dev/null
+++ b/themes/new_theme/static/favicon.ico
Binary files differ
diff --git a/themes/new_theme/static/img/avatar.png b/themes/new_theme/static/img/avatar.png
new file mode 100644
index 0000000..8afac66
--- /dev/null
+++ b/themes/new_theme/static/img/avatar.png
Binary files differ
diff --git a/themes/new_theme/static/img/placeholder.png b/themes/new_theme/static/img/placeholder.png
new file mode 100644
index 0000000..a3d8535
--- /dev/null
+++ b/themes/new_theme/static/img/placeholder.png
Binary files differ
diff --git a/themes/new_theme/static/js/menu.js b/themes/new_theme/static/js/menu.js
new file mode 100644
index 0000000..16f1d37
--- /dev/null
+++ b/themes/new_theme/static/js/menu.js
@@ -0,0 +1,25 @@
+'use strict';
+
+(function iifeMenu(document, window, undefined) {
+ var menuBtn = document.querySelector('.menu__btn');
+ var menu = document.querySelector('.menu__list');
+
+ function toggleMenu() {
+ menu.classList.toggle('menu__list--active');
+ menu.classList.toggle('menu__list--transition');
+ this.classList.toggle('menu__btn--active');
+ this.setAttribute(
+ 'aria-expanded',
+ this.getAttribute('aria-expanded') === 'true' ? 'false' : 'true'
+ );
+ }
+
+ function removeMenuTransition() {
+ this.classList.remove('menu__list--transition');
+ }
+
+ if (menuBtn && menu) {
+ menuBtn.addEventListener('click', toggleMenu, false);
+ menu.addEventListener('transitionend', removeMenuTransition, false);
+ }
+}(document, window));
diff --git a/themes/new_theme/static/js/require.js b/themes/new_theme/static/js/require.js
new file mode 100644
index 0000000..a4203f0
--- /dev/null
+++ b/themes/new_theme/static/js/require.js
@@ -0,0 +1,5 @@
+/** vim: et:ts=4:sw=4:sts=4
+ * @license RequireJS 2.3.6 Copyright jQuery Foundation and other contributors.
+ * Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE
+ */
+var requirejs,require,define;!function(global,setTimeout){var req,s,head,baseElement,dataMain,src,interactiveScript,currentlyAddingScript,mainScript,subPath,version="2.3.6",commentRegExp=/\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm,cjsRequireRegExp=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,jsSuffixRegExp=/\.js$/,currDirRegExp=/^\.\//,op=Object.prototype,ostring=op.toString,hasOwn=op.hasOwnProperty,isBrowser=!("undefined"==typeof window||"undefined"==typeof navigator||!window.document),isWebWorker=!isBrowser&&"undefined"!=typeof importScripts,readyRegExp=isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,defContextName="_",isOpera="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),contexts={},cfg={},globalDefQueue=[],useInteractive=!1;function commentReplace(e,t){return t||""}function isFunction(e){return"[object Function]"===ostring.call(e)}function isArray(e){return"[object Array]"===ostring.call(e)}function each(e,t){var i;if(e)for(i=0;i<e.length&&(!e[i]||!t(e[i],i,e));i+=1);}function eachReverse(e,t){var i;if(e)for(i=e.length-1;-1<i&&(!e[i]||!t(e[i],i,e));i-=1);}function hasProp(e,t){return hasOwn.call(e,t)}function getOwn(e,t){return hasProp(e,t)&&e[t]}function eachProp(e,t){var i;for(i in e)if(hasProp(e,i)&&t(e[i],i))break}function mixin(i,e,r,n){return e&&eachProp(e,function(e,t){!r&&hasProp(i,t)||(!n||"object"!=typeof e||!e||isArray(e)||isFunction(e)||e instanceof RegExp?i[t]=e:(i[t]||(i[t]={}),mixin(i[t],e,r,n)))}),i}function bind(e,t){return function(){return t.apply(e,arguments)}}function scripts(){return document.getElementsByTagName("script")}function defaultOnError(e){throw e}function getGlobal(e){if(!e)return e;var t=global;return each(e.split("."),function(e){t=t[e]}),t}function makeError(e,t,i,r){var n=new Error(t+"\nhttps://requirejs.org/docs/errors.html#"+e);return n.requireType=e,n.requireModules=r,i&&(n.originalError=i),n}if(void 0===define){if(void 0!==requirejs){if(isFunction(requirejs))return;cfg=requirejs,requirejs=void 0}void 0===require||isFunction(require)||(cfg=require,require=void 0),req=requirejs=function(e,t,i,r){var n,o,a=defContextName;return isArray(e)||"string"==typeof e||(o=e,isArray(t)?(e=t,t=i,i=r):e=[]),o&&o.context&&(a=o.context),(n=getOwn(contexts,a))||(n=contexts[a]=req.s.newContext(a)),o&&n.configure(o),n.require(e,t,i)},req.config=function(e){return req(e)},req.nextTick=void 0!==setTimeout?function(e){setTimeout(e,4)}:function(e){e()},require||(require=req),req.version=version,req.jsExtRegExp=/^\/|:|\?|\.js$/,req.isBrowser=isBrowser,s=req.s={contexts:contexts,newContext:newContext},req({}),each(["toUrl","undef","defined","specified"],function(t){req[t]=function(){var e=contexts[defContextName];return e.require[t].apply(e,arguments)}}),isBrowser&&(head=s.head=document.getElementsByTagName("head")[0],baseElement=document.getElementsByTagName("base")[0],baseElement&&(head=s.head=baseElement.parentNode)),req.onError=defaultOnError,req.createNode=function(e,t,i){var r=e.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");return r.type=e.scriptType||"text/javascript",r.charset="utf-8",r.async=!0,r},req.load=function(t,i,r){var e,n=t&&t.config||{};if(isBrowser)return(e=req.createNode(n,i,r)).setAttribute("data-requirecontext",t.contextName),e.setAttribute("data-requiremodule",i),!e.attachEvent||e.attachEvent.toString&&e.attachEvent.toString().indexOf("[native code")<0||isOpera?(e.addEventListener("load",t.onScriptLoad,!1),e.addEventListener("error",t.onScriptError,!1)):(useInteractive=!0,e.attachEvent("onreadystatechange",t.onScriptLoad)),e.src=r,n.onNodeCreated&&n.onNodeCreated(e,n,i,r),currentlyAddingScript=e,baseElement?head.insertBefore(e,baseElement):head.appendChild(e),currentlyAddingScript=null,e;if(isWebWorker)try{setTimeout(function(){},0),importScripts(r),t.completeLoad(i)}catch(e){t.onError(makeError("importscripts","importScripts failed for "+i+" at "+r,e,[i]))}},isBrowser&&!cfg.skipDataMain&&eachReverse(scripts(),function(e){if(head||(head=e.parentNode),dataMain=e.getAttribute("data-main"))return mainScript=dataMain,cfg.baseUrl||-1!==mainScript.indexOf("!")||(mainScript=(src=mainScript.split("/")).pop(),subPath=src.length?src.join("/")+"/":"./",cfg.baseUrl=subPath),mainScript=mainScript.replace(jsSuffixRegExp,""),req.jsExtRegExp.test(mainScript)&&(mainScript=dataMain),cfg.deps=cfg.deps?cfg.deps.concat(mainScript):[mainScript],!0}),define=function(e,i,t){var r,n;"string"!=typeof e&&(t=i,i=e,e=null),isArray(i)||(t=i,i=null),!i&&isFunction(t)&&(i=[],t.length&&(t.toString().replace(commentRegExp,commentReplace).replace(cjsRequireRegExp,function(e,t){i.push(t)}),i=(1===t.length?["require"]:["require","exports","module"]).concat(i))),useInteractive&&(r=currentlyAddingScript||getInteractiveScript())&&(e||(e=r.getAttribute("data-requiremodule")),n=contexts[r.getAttribute("data-requirecontext")]),n?(n.defQueue.push([e,i,t]),n.defQueueMap[e]=!0):globalDefQueue.push([e,i,t])},define.amd={jQuery:!0},req.exec=function(text){return eval(text)},req(cfg)}function newContext(u){var i,e,l,c,d,g={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},p={},f={},r={},h=[],m={},n={},v={},x=1,b=1;function q(e,t,i){var r,n,o,a,s,u,c,d,p,f,l=t&&t.split("/"),h=g.map,m=h&&h["*"];if(e&&(u=(e=e.split("/")).length-1,g.nodeIdCompat&&jsSuffixRegExp.test(e[u])&&(e[u]=e[u].replace(jsSuffixRegExp,"")),"."===e[0].charAt(0)&&l&&(e=l.slice(0,l.length-1).concat(e)),function(e){var t,i;for(t=0;t<e.length;t++)if("."===(i=e[t]))e.splice(t,1),t-=1;else if(".."===i){if(0===t||1===t&&".."===e[2]||".."===e[t-1])continue;0<t&&(e.splice(t-1,2),t-=2)}}(e),e=e.join("/")),i&&h&&(l||m)){e:for(o=(n=e.split("/")).length;0<o;o-=1){if(s=n.slice(0,o).join("/"),l)for(a=l.length;0<a;a-=1)if((r=getOwn(h,l.slice(0,a).join("/")))&&(r=getOwn(r,s))){c=r,d=o;break e}!p&&m&&getOwn(m,s)&&(p=getOwn(m,s),f=o)}!c&&p&&(c=p,d=f),c&&(n.splice(0,d,c),e=n.join("/"))}return getOwn(g.pkgs,e)||e}function E(t){isBrowser&&each(scripts(),function(e){if(e.getAttribute("data-requiremodule")===t&&e.getAttribute("data-requirecontext")===l.contextName)return e.parentNode.removeChild(e),!0})}function w(e){var t=getOwn(g.paths,e);if(t&&isArray(t)&&1<t.length)return t.shift(),l.require.undef(e),l.makeRequire(null,{skipMap:!0})([e]),!0}function y(e){var t,i=e?e.indexOf("!"):-1;return-1<i&&(t=e.substring(0,i),e=e.substring(i+1,e.length)),[t,e]}function S(e,t,i,r){var n,o,a,s,u=null,c=t?t.name:null,d=e,p=!0,f="";return e||(p=!1,e="_@r"+(x+=1)),u=(s=y(e))[0],e=s[1],u&&(u=q(u,c,r),o=getOwn(m,u)),e&&(u?f=i?e:o&&o.normalize?o.normalize(e,function(e){return q(e,c,r)}):-1===e.indexOf("!")?q(e,c,r):e:(u=(s=y(f=q(e,c,r)))[0],f=s[1],i=!0,n=l.nameToUrl(f))),{prefix:u,name:f,parentMap:t,unnormalized:!!(a=!u||o||i?"":"_unnormalized"+(b+=1)),url:n,originalName:d,isDefine:p,id:(u?u+"!"+f:f)+a}}function k(e){var t=e.id,i=getOwn(p,t);return i||(i=p[t]=new l.Module(e)),i}function M(e,t,i){var r=e.id,n=getOwn(p,r);!hasProp(m,r)||n&&!n.defineEmitComplete?(n=k(e)).error&&"error"===t?i(n.error):n.on(t,i):"defined"===t&&i(m[r])}function O(i,e){var t=i.requireModules,r=!1;e?e(i):(each(t,function(e){var t=getOwn(p,e);t&&(t.error=i,t.events.error&&(r=!0,t.emit("error",i)))}),r||req.onError(i))}function j(){globalDefQueue.length&&(each(globalDefQueue,function(e){var t=e[0];"string"==typeof t&&(l.defQueueMap[t]=!0),h.push(e)}),globalDefQueue=[])}function P(e){delete p[e],delete f[e]}function R(){var e,r,t=1e3*g.waitSeconds,n=t&&l.startTime+t<(new Date).getTime(),o=[],a=[],s=!1,u=!0;if(!i){if(i=!0,eachProp(f,function(e){var t=e.map,i=t.id;if(e.enabled&&(t.isDefine||a.push(e),!e.error))if(!e.inited&&n)w(i)?s=r=!0:(o.push(i),E(i));else if(!e.inited&&e.fetched&&t.isDefine&&(s=!0,!t.prefix))return u=!1}),n&&o.length)return(e=makeError("timeout","Load timeout for modules: "+o,null,o)).contextName=l.contextName,O(e);u&&each(a,function(e){!function n(o,a,s){var e=o.map.id;o.error?o.emit("error",o.error):(a[e]=!0,each(o.depMaps,function(e,t){var i=e.id,r=getOwn(p,i);!r||o.depMatched[t]||s[i]||(getOwn(a,i)?(o.defineDep(t,m[i]),o.check()):n(r,a,s))}),s[e]=!0)}(e,{},{})}),n&&!r||!s||!isBrowser&&!isWebWorker||d||(d=setTimeout(function(){d=0,R()},50)),i=!1}}function a(e){hasProp(m,e[0])||k(S(e[0],null,!0)).init(e[1],e[2])}function o(e,t,i,r){e.detachEvent&&!isOpera?r&&e.detachEvent(r,t):e.removeEventListener(i,t,!1)}function s(e){var t=e.currentTarget||e.srcElement;return o(t,l.onScriptLoad,"load","onreadystatechange"),o(t,l.onScriptError,"error"),{node:t,id:t&&t.getAttribute("data-requiremodule")}}function T(){var e;for(j();h.length;){if(null===(e=h.shift())[0])return O(makeError("mismatch","Mismatched anonymous define() module: "+e[e.length-1]));a(e)}l.defQueueMap={}}return c={require:function(e){return e.require?e.require:e.require=l.makeRequire(e.map)},exports:function(e){if(e.usingExports=!0,e.map.isDefine)return e.exports?m[e.map.id]=e.exports:e.exports=m[e.map.id]={}},module:function(e){return e.module?e.module:e.module={id:e.map.id,uri:e.map.url,config:function(){return getOwn(g.config,e.map.id)||{}},exports:e.exports||(e.exports={})}}},(e=function(e){this.events=getOwn(r,e.id)||{},this.map=e,this.shim=getOwn(g.shim,e.id),this.depExports=[],this.depMaps=[],this.depMatched=[],this.pluginMaps={},this.depCount=0}).prototype={init:function(e,t,i,r){r=r||{},this.inited||(this.factory=t,i?this.on("error",i):this.events.error&&(i=bind(this,function(e){this.emit("error",e)})),this.depMaps=e&&e.slice(0),this.errback=i,this.inited=!0,this.ignore=r.ignore,r.enabled||this.enabled?this.enable():this.check())},defineDep:function(e,t){this.depMatched[e]||(this.depMatched[e]=!0,this.depCount-=1,this.depExports[e]=t)},fetch:function(){if(!this.fetched){this.fetched=!0,l.startTime=(new Date).getTime();var e=this.map;if(!this.shim)return e.prefix?this.callPlugin():this.load();l.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],bind(this,function(){return e.prefix?this.callPlugin():this.load()}))}},load:function(){var e=this.map.url;n[e]||(n[e]=!0,l.load(this.map.id,e))},check:function(){if(this.enabled&&!this.enabling){var t,e,i=this.map.id,r=this.depExports,n=this.exports,o=this.factory;if(this.inited){if(this.error)this.emit("error",this.error);else if(!this.defining){if(this.defining=!0,this.depCount<1&&!this.defined){if(isFunction(o)){if(this.events.error&&this.map.isDefine||req.onError!==defaultOnError)try{n=l.execCb(i,o,r,n)}catch(e){t=e}else n=l.execCb(i,o,r,n);if(this.map.isDefine&&void 0===n&&((e=this.module)?n=e.exports:this.usingExports&&(n=this.exports)),t)return t.requireMap=this.map,t.requireModules=this.map.isDefine?[this.map.id]:null,t.requireType=this.map.isDefine?"define":"require",O(this.error=t)}else n=o;if(this.exports=n,this.map.isDefine&&!this.ignore&&(m[i]=n,req.onResourceLoad)){var a=[];each(this.depMaps,function(e){a.push(e.normalizedMap||e)}),req.onResourceLoad(l,this.map,a)}P(i),this.defined=!0}this.defining=!1,this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else hasProp(l.defQueueMap,i)||this.fetch()}},callPlugin:function(){var u=this.map,c=u.id,e=S(u.prefix);this.depMaps.push(e),M(e,"defined",bind(this,function(e){var o,t,i,r=getOwn(v,this.map.id),n=this.map.name,a=this.map.parentMap?this.map.parentMap.name:null,s=l.makeRequire(u.parentMap,{enableBuildCallback:!0});return this.map.unnormalized?(e.normalize&&(n=e.normalize(n,function(e){return q(e,a,!0)})||""),M(t=S(u.prefix+"!"+n,this.map.parentMap,!0),"defined",bind(this,function(e){this.map.normalizedMap=t,this.init([],function(){return e},null,{enabled:!0,ignore:!0})})),void((i=getOwn(p,t.id))&&(this.depMaps.push(t),this.events.error&&i.on("error",bind(this,function(e){this.emit("error",e)})),i.enable()))):r?(this.map.url=l.nameToUrl(r),void this.load()):((o=bind(this,function(e){this.init([],function(){return e},null,{enabled:!0})})).error=bind(this,function(e){this.inited=!0,(this.error=e).requireModules=[c],eachProp(p,function(e){0===e.map.id.indexOf(c+"_unnormalized")&&P(e.map.id)}),O(e)}),o.fromText=bind(this,function(e,t){var i=u.name,r=S(i),n=useInteractive;t&&(e=t),n&&(useInteractive=!1),k(r),hasProp(g.config,c)&&(g.config[i]=g.config[c]);try{req.exec(e)}catch(e){return O(makeError("fromtexteval","fromText eval for "+c+" failed: "+e,e,[c]))}n&&(useInteractive=!0),this.depMaps.push(r),l.completeLoad(i),s([i],o)}),void e.load(u.name,s,o,g))})),l.enable(e,this),this.pluginMaps[e.id]=e},enable:function(){(f[this.map.id]=this).enabled=!0,this.enabling=!0,each(this.depMaps,bind(this,function(e,t){var i,r,n;if("string"==typeof e){if(e=S(e,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap),this.depMaps[t]=e,n=getOwn(c,e.id))return void(this.depExports[t]=n(this));this.depCount+=1,M(e,"defined",bind(this,function(e){this.undefed||(this.defineDep(t,e),this.check())})),this.errback?M(e,"error",bind(this,this.errback)):this.events.error&&M(e,"error",bind(this,function(e){this.emit("error",e)}))}i=e.id,r=p[i],hasProp(c,i)||!r||r.enabled||l.enable(e,this)})),eachProp(this.pluginMaps,bind(this,function(e){var t=getOwn(p,e.id);t&&!t.enabled&&l.enable(e,this)})),this.enabling=!1,this.check()},on:function(e,t){var i=this.events[e];i||(i=this.events[e]=[]),i.push(t)},emit:function(e,t){each(this.events[e],function(e){e(t)}),"error"===e&&delete this.events[e]}},(l={config:g,contextName:u,registry:p,defined:m,urlFetched:n,defQueue:h,defQueueMap:{},Module:e,makeModuleMap:S,nextTick:req.nextTick,onError:O,configure:function(e){if(e.baseUrl&&"/"!==e.baseUrl.charAt(e.baseUrl.length-1)&&(e.baseUrl+="/"),"string"==typeof e.urlArgs){var i=e.urlArgs;e.urlArgs=function(e,t){return(-1===t.indexOf("?")?"?":"&")+i}}var r=g.shim,n={paths:!0,bundles:!0,config:!0,map:!0};eachProp(e,function(e,t){n[t]?(g[t]||(g[t]={}),mixin(g[t],e,!0,!0)):g[t]=e}),e.bundles&&eachProp(e.bundles,function(e,t){each(e,function(e){e!==t&&(v[e]=t)})}),e.shim&&(eachProp(e.shim,function(e,t){isArray(e)&&(e={deps:e}),!e.exports&&!e.init||e.exportsFn||(e.exportsFn=l.makeShimExports(e)),r[t]=e}),g.shim=r),e.packages&&each(e.packages,function(e){var t;t=(e="string"==typeof e?{name:e}:e).name,e.location&&(g.paths[t]=e.location),g.pkgs[t]=e.name+"/"+(e.main||"main").replace(currDirRegExp,"").replace(jsSuffixRegExp,"")}),eachProp(p,function(e,t){e.inited||e.map.unnormalized||(e.map=S(t,null,!0))}),(e.deps||e.callback)&&l.require(e.deps||[],e.callback)},makeShimExports:function(t){return function(){var e;return t.init&&(e=t.init.apply(global,arguments)),e||t.exports&&getGlobal(t.exports)}},makeRequire:function(o,a){function s(e,t,i){var r,n;return a.enableBuildCallback&&t&&isFunction(t)&&(t.__requireJsBuild=!0),"string"==typeof e?isFunction(t)?O(makeError("requireargs","Invalid require call"),i):o&&hasProp(c,e)?c[e](p[o.id]):req.get?req.get(l,e,o,s):(r=S(e,o,!1,!0).id,hasProp(m,r)?m[r]:O(makeError("notloaded",'Module name "'+r+'" has not been loaded yet for context: '+u+(o?"":". Use require([])")))):(T(),l.nextTick(function(){T(),(n=k(S(null,o))).skipMap=a.skipMap,n.init(e,t,i,{enabled:!0}),R()}),s)}return a=a||{},mixin(s,{isBrowser:isBrowser,toUrl:function(e){var t,i=e.lastIndexOf("."),r=e.split("/")[0];return-1!==i&&(!("."===r||".."===r)||1<i)&&(t=e.substring(i,e.length),e=e.substring(0,i)),l.nameToUrl(q(e,o&&o.id,!0),t,!0)},defined:function(e){return hasProp(m,S(e,o,!1,!0).id)},specified:function(e){return e=S(e,o,!1,!0).id,hasProp(m,e)||hasProp(p,e)}}),o||(s.undef=function(i){j();var e=S(i,o,!0),t=getOwn(p,i);t.undefed=!0,E(i),delete m[i],delete n[e.url],delete r[i],eachReverse(h,function(e,t){e[0]===i&&h.splice(t,1)}),delete l.defQueueMap[i],t&&(t.events.defined&&(r[i]=t.events),P(i))}),s},enable:function(e){getOwn(p,e.id)&&k(e).enable()},completeLoad:function(e){var t,i,r,n=getOwn(g.shim,e)||{},o=n.exports;for(j();h.length;){if(null===(i=h.shift())[0]){if(i[0]=e,t)break;t=!0}else i[0]===e&&(t=!0);a(i)}if(l.defQueueMap={},r=getOwn(p,e),!t&&!hasProp(m,e)&&r&&!r.inited){if(!(!g.enforceDefine||o&&getGlobal(o)))return w(e)?void 0:O(makeError("nodefine","No define call for "+e,null,[e]));a([e,n.deps||[],n.exportsFn])}R()},nameToUrl:function(e,t,i){var r,n,o,a,s,u,c=getOwn(g.pkgs,e);if(c&&(e=c),u=getOwn(v,e))return l.nameToUrl(u,t,i);if(req.jsExtRegExp.test(e))a=e+(t||"");else{for(r=g.paths,o=(n=e.split("/")).length;0<o;o-=1)if(s=getOwn(r,n.slice(0,o).join("/"))){isArray(s)&&(s=s[0]),n.splice(0,o,s);break}a=n.join("/"),a=("/"===(a+=t||(/^data\:|^blob\:|\?/.test(a)||i?"":".js")).charAt(0)||a.match(/^[\w\+\.\-]+:/)?"":g.baseUrl)+a}return g.urlArgs&&!/^blob\:/.test(a)?a+g.urlArgs(e,a):a},load:function(e,t){req.load(l,e,t)},execCb:function(e,t,i,r){return t.apply(r,i)},onScriptLoad:function(e){if("load"===e.type||readyRegExp.test((e.currentTarget||e.srcElement).readyState)){interactiveScript=null;var t=s(e);l.completeLoad(t.id)}},onScriptError:function(e){var i=s(e);if(!w(i.id)){var r=[];return eachProp(p,function(e,t){0!==t.indexOf("_@r")&&each(e.depMaps,function(e){if(e.id===i.id)return r.push(t),!0})}),O(makeError("scripterror",'Script error for "'+i.id+(r.length?'", needed by: '+r.join(", "):'"'),e,[i.id]))}}}).require=l.makeRequire(),l}function getInteractiveScript(){return interactiveScript&&"interactive"===interactiveScript.readyState||eachReverse(scripts(),function(e){if("interactive"===e.readyState)return interactiveScript=e}),interactiveScript}}(this,"undefined"==typeof setTimeout?void 0:setTimeout); \ No newline at end of file
diff --git a/themes/new_theme/static/js/sql-wasm.js b/themes/new_theme/static/js/sql-wasm.js
new file mode 100644
index 0000000..29d2c18
--- /dev/null
+++ b/themes/new_theme/static/js/sql-wasm.js
@@ -0,0 +1,203 @@
+
+// We are modularizing this manually because the current modularize setting in Emscripten has some issues:
+// https://github.com/kripken/emscripten/issues/5820
+// In addition, When you use emcc's modularization, it still expects to export a global object called `Module`,
+// which is able to be used/called before the WASM is loaded.
+// The modularization below exports a promise that loads and resolves to the actual sql.js module.
+// That way, this module can't be used before the WASM is finished loading.
+
+// We are going to define a function that a user will call to start loading initializing our Sql.js library
+// However, that function might be called multiple times, and on subsequent calls, we don't actually want it to instantiate a new instance of the Module
+// Instead, we want to return the previously loaded module
+
+// TODO: Make this not declare a global if used in the browser
+var initSqlJsPromise = undefined;
+
+var initSqlJs = function (moduleConfig) {
+
+ if (initSqlJsPromise){
+ return initSqlJsPromise;
+ }
+ // If we're here, we've never called this function before
+ initSqlJsPromise = new Promise(function (resolveModule, reject) {
+
+ // We are modularizing this manually because the current modularize setting in Emscripten has some issues:
+ // https://github.com/kripken/emscripten/issues/5820
+
+ // The way to affect the loading of emcc compiled modules is to create a variable called `Module` and add
+ // properties to it, like `preRun`, `postRun`, etc
+ // We are using that to get notified when the WASM has finished loading.
+ // Only then will we return our promise
+
+ // If they passed in a moduleConfig object, use that
+ // Otherwise, initialize Module to the empty object
+ var Module = typeof moduleConfig !== 'undefined' ? moduleConfig : {};
+
+ // EMCC only allows for a single onAbort function (not an array of functions)
+ // So if the user defined their own onAbort function, we remember it and call it
+ var originalOnAbortFunction = Module['onAbort'];
+ Module['onAbort'] = function (errorThatCausedAbort) {
+ reject(new Error(errorThatCausedAbort));
+ if (originalOnAbortFunction){
+ originalOnAbortFunction(errorThatCausedAbort);
+ }
+ };
+
+ Module['postRun'] = Module['postRun'] || [];
+ Module['postRun'].push(function () {
+ // When Emscripted calls postRun, this promise resolves with the built Module
+ resolveModule(Module);
+ });
+
+ // There is a section of code in the emcc-generated code below that looks like this:
+ // (Note that this is lowercase `module`)
+ // if (typeof module !== 'undefined') {
+ // module['exports'] = Module;
+ // }
+ // When that runs, it's going to overwrite our own modularization export efforts in shell-post.js!
+ // The only way to tell emcc not to emit it is to pass the MODULARIZE=1 or MODULARIZE_INSTANCE=1 flags,
+ // but that carries with it additional unnecessary baggage/bugs we don't want either.
+ // So, we have three options:
+ // 1) We undefine `module`
+ // 2) We remember what `module['exports']` was at the beginning of this function and we restore it later
+ // 3) We write a script to remove those lines of code as part of the Make process.
+ //
+ // Since those are the only lines of code that care about module, we will undefine it. It's the most straightforward
+ // of the options, and has the side effect of reducing emcc's efforts to modify the module if its output were to change in the future.
+ // That's a nice side effect since we're handling the modularization efforts ourselves
+ module = undefined;
+
+ // The emcc-generated code and shell-post.js code goes below,
+ // meaning that all of it runs inside of this promise. If anything throws an exception, our promise will abort
+
+var e;e||(e=typeof Module !== 'undefined' ? Module : {});null;
+e.onRuntimeInitialized=function(){function a(h,l){this.Ra=h;this.db=l;this.Qa=1;this.lb=[]}function b(h,l){this.db=l;l=ba(h)+1;this.eb=ca(l);if(null===this.eb)throw Error("Unable to allocate memory for the SQL string");k(h,m,this.eb,l);this.jb=this.eb;this.$a=this.pb=null}function c(h){this.filename="dbfile_"+(4294967295*Math.random()>>>0);if(null!=h){var l=this.filename,p=l?r("//"+l):"/";l=da(!0,!0);p=ea(p,(void 0!==l?l:438)&4095|32768,0);if(h){if("string"===typeof h){for(var q=Array(h.length),B=
+0,ha=h.length;B<ha;++B)q[B]=h.charCodeAt(B);h=q}fa(p,l|146);q=v(p,577);ka(q,h,0,h.length,0,void 0);la(q);fa(p,l)}}this.handleError(g(this.filename,d));this.db=x(d,"i32");jc(this.db);this.fb={};this.Xa={}}var d=y(4),f=e.cwrap,g=f("sqlite3_open","number",["string","number"]),n=f("sqlite3_close_v2","number",["number"]),t=f("sqlite3_exec","number",["number","string","number","number","number"]),w=f("sqlite3_changes","number",["number"]),u=f("sqlite3_prepare_v2","number",["number","string","number","number",
+"number"]),C=f("sqlite3_sql","string",["number"]),H=f("sqlite3_normalized_sql","string",["number"]),aa=f("sqlite3_prepare_v2","number",["number","number","number","number","number"]),kc=f("sqlite3_bind_text","number",["number","number","number","number","number"]),qb=f("sqlite3_bind_blob","number",["number","number","number","number","number"]),lc=f("sqlite3_bind_double","number",["number","number","number"]),mc=f("sqlite3_bind_int","number",["number","number","number"]),nc=f("sqlite3_bind_parameter_index",
+"number",["number","string"]),oc=f("sqlite3_step","number",["number"]),pc=f("sqlite3_errmsg","string",["number"]),qc=f("sqlite3_column_count","number",["number"]),rc=f("sqlite3_data_count","number",["number"]),sc=f("sqlite3_column_double","number",["number","number"]),tc=f("sqlite3_column_text","string",["number","number"]),uc=f("sqlite3_column_blob","number",["number","number"]),vc=f("sqlite3_column_bytes","number",["number","number"]),wc=f("sqlite3_column_type","number",["number","number"]),xc=
+f("sqlite3_column_name","string",["number","number"]),yc=f("sqlite3_reset","number",["number"]),zc=f("sqlite3_clear_bindings","number",["number"]),Ac=f("sqlite3_finalize","number",["number"]),Bc=f("sqlite3_create_function_v2","number","number string number number number number number number number".split(" ")),Cc=f("sqlite3_value_type","number",["number"]),Dc=f("sqlite3_value_bytes","number",["number"]),Ec=f("sqlite3_value_text","string",["number"]),Fc=f("sqlite3_value_blob","number",["number"]),
+Gc=f("sqlite3_value_double","number",["number"]),Hc=f("sqlite3_result_double","",["number","number"]),rb=f("sqlite3_result_null","",["number"]),Ic=f("sqlite3_result_text","",["number","string","number","number"]),Jc=f("sqlite3_result_blob","",["number","number","number","number"]),Kc=f("sqlite3_result_int","",["number","number"]),sb=f("sqlite3_result_error","",["number","string","number"]),jc=f("RegisterExtensionFunctions","number",["number"]);a.prototype.bind=function(h){if(!this.Ra)throw"Statement closed";
+this.reset();return Array.isArray(h)?this.Bb(h):null!=h&&"object"===typeof h?this.Cb(h):!0};a.prototype.step=function(){if(!this.Ra)throw"Statement closed";this.Qa=1;var h=oc(this.Ra);switch(h){case 100:return!0;case 101:return!1;default:throw this.db.handleError(h);}};a.prototype.Ib=function(h){null==h&&(h=this.Qa,this.Qa+=1);return sc(this.Ra,h)};a.prototype.Jb=function(h){null==h&&(h=this.Qa,this.Qa+=1);return tc(this.Ra,h)};a.prototype.getBlob=function(h){null==h&&(h=this.Qa,this.Qa+=1);var l=
+vc(this.Ra,h);h=uc(this.Ra,h);for(var p=new Uint8Array(l),q=0;q<l;q+=1)p[q]=z[h+q];return p};a.prototype.get=function(h){null!=h&&this.bind(h)&&this.step();h=[];for(var l=rc(this.Ra),p=0;p<l;p+=1)switch(wc(this.Ra,p)){case 1:case 2:h.push(this.Ib(p));break;case 3:h.push(this.Jb(p));break;case 4:h.push(this.getBlob(p));break;default:h.push(null)}return h};a.prototype.getColumnNames=function(){for(var h=[],l=qc(this.Ra),p=0;p<l;p+=1)h.push(xc(this.Ra,p));return h};a.prototype.getAsObject=function(h){h=
+this.get(h);for(var l=this.getColumnNames(),p={},q=0;q<l.length;q+=1)p[l[q]]=h[q];return p};a.prototype.getSQL=function(){return C(this.Ra)};a.prototype.getNormalizedSQL=function(){return H(this.Ra)};a.prototype.run=function(h){null!=h&&this.bind(h);this.step();return this.reset()};a.prototype.Fb=function(h,l){null==l&&(l=this.Qa,this.Qa+=1);h=ma(h);var p=na(h);this.lb.push(p);this.db.handleError(kc(this.Ra,l,p,h.length-1,0))};a.prototype.Ab=function(h,l){null==l&&(l=this.Qa,this.Qa+=1);var p=na(h);
+this.lb.push(p);this.db.handleError(qb(this.Ra,l,p,h.length,0))};a.prototype.Eb=function(h,l){null==l&&(l=this.Qa,this.Qa+=1);this.db.handleError((h===(h|0)?mc:lc)(this.Ra,l,h))};a.prototype.Db=function(h){null==h&&(h=this.Qa,this.Qa+=1);qb(this.Ra,h,0,0,0)};a.prototype.tb=function(h,l){null==l&&(l=this.Qa,this.Qa+=1);switch(typeof h){case "string":this.Fb(h,l);return;case "number":case "boolean":this.Eb(h+0,l);return;case "object":if(null===h){this.Db(l);return}if(null!=h.length){this.Ab(h,l);return}}throw"Wrong API use : tried to bind a value of an unknown type ("+
+h+").";};a.prototype.Cb=function(h){var l=this;Object.keys(h).forEach(function(p){var q=nc(l.Ra,p);0!==q&&l.tb(h[p],q)});return!0};a.prototype.Bb=function(h){for(var l=0;l<h.length;l+=1)this.tb(h[l],l+1);return!0};a.prototype.reset=function(){return 0===zc(this.Ra)&&0===yc(this.Ra)};a.prototype.freemem=function(){for(var h;void 0!==(h=this.lb.pop());)oa(h)};a.prototype.free=function(){var h=0===Ac(this.Ra);delete this.db.fb[this.Ra];this.Ra=0;return h};b.prototype.next=function(){if(null===this.eb)return{done:!0};
+null!==this.$a&&(this.$a.free(),this.$a=null);if(!this.db.db)throw this.nb(),Error("Database closed");var h=pa(),l=y(4);qa(d);qa(l);try{this.db.handleError(aa(this.db.db,this.jb,-1,d,l));this.jb=x(l,"i32");var p=x(d,"i32");if(0===p)return this.nb(),{done:!0};this.$a=new a(p,this.db);this.db.fb[p]=this.$a;return{value:this.$a,done:!1}}catch(q){throw this.pb=A(this.jb),this.nb(),q;}finally{ra(h)}};b.prototype.nb=function(){oa(this.eb);this.eb=null};b.prototype.getRemainingSQL=function(){return null!==
+this.pb?this.pb:A(this.jb)};"function"===typeof Symbol&&"symbol"===typeof Symbol.iterator&&(b.prototype[Symbol.iterator]=function(){return this});c.prototype.run=function(h,l){if(!this.db)throw"Database closed";if(l){h=this.prepare(h,l);try{h.step()}finally{h.free()}}else this.handleError(t(this.db,h,0,0,d));return this};c.prototype.exec=function(h,l){if(!this.db)throw"Database closed";var p=pa(),q=null;try{var B=ba(h)+1,ha=y(B);k(h,z,ha,B);var D=ha;var ia=y(4);for(h=[];0!==x(D,"i8");){qa(d);qa(ia);
+this.handleError(aa(this.db,D,-1,d,ia));var ja=x(d,"i32");D=x(ia,"i32");if(0!==ja){B=null;q=new a(ja,this);for(null!=l&&q.bind(l);q.step();)null===B&&(B={columns:q.getColumnNames(),values:[]},h.push(B)),B.values.push(q.get());q.free()}}return h}catch(E){throw q&&q.free(),E;}finally{ra(p)}};c.prototype.each=function(h,l,p,q){"function"===typeof l&&(q=p,p=l,l=void 0);h=this.prepare(h,l);try{for(;h.step();)p(h.getAsObject())}finally{h.free()}if("function"===typeof q)return q()};c.prototype.prepare=function(h,
+l){qa(d);this.handleError(u(this.db,h,-1,d,0));h=x(d,"i32");if(0===h)throw"Nothing to prepare";var p=new a(h,this);null!=l&&p.bind(l);return this.fb[h]=p};c.prototype.iterateStatements=function(h){return new b(h,this)};c.prototype["export"]=function(){Object.values(this.fb).forEach(function(l){l.free()});Object.values(this.Xa).forEach(sa);this.Xa={};this.handleError(n(this.db));var h=ta(this.filename);this.handleError(g(this.filename,d));this.db=x(d,"i32");return h};c.prototype.close=function(){null!==
+this.db&&(Object.values(this.fb).forEach(function(h){h.free()}),Object.values(this.Xa).forEach(sa),this.Xa={},this.handleError(n(this.db)),ua("/"+this.filename),this.db=null)};c.prototype.handleError=function(h){if(0===h)return null;h=pc(this.db);throw Error(h);};c.prototype.getRowsModified=function(){return w(this.db)};c.prototype.create_function=function(h,l){Object.prototype.hasOwnProperty.call(this.Xa,h)&&(sa(this.Xa[h]),delete this.Xa[h]);var p=va(function(q,B,ha){for(var D,ia=[],ja=0;ja<B;ja+=
+1){var E=x(ha+4*ja,"i32"),S=Cc(E);if(1===S||2===S)E=Gc(E);else if(3===S)E=Ec(E);else if(4===S){S=E;E=Dc(S);S=Fc(S);for(var vb=new Uint8Array(E),Ba=0;Ba<E;Ba+=1)vb[Ba]=z[S+Ba];E=vb}else E=null;ia.push(E)}try{D=l.apply(null,ia)}catch(Nc){sb(q,Nc,-1);return}switch(typeof D){case "boolean":Kc(q,D?1:0);break;case "number":Hc(q,D);break;case "string":Ic(q,D,-1,-1);break;case "object":null===D?rb(q):null!=D.length?(B=na(D),Jc(q,B,D.length,-1),oa(B)):sb(q,"Wrong API use : tried to return a value of an unknown type ("+
+D+").",-1);break;default:rb(q)}});this.Xa[h]=p;this.handleError(Bc(this.db,h,l.length,1,0,p,0,0,0));return this};e.Database=c};var wa={},F;for(F in e)e.hasOwnProperty(F)&&(wa[F]=e[F]);var xa="./this.program",ya=!1,za=!1,Aa=!1,Ca=!1;ya="object"===typeof window;za="function"===typeof importScripts;Aa="object"===typeof process&&"object"===typeof process.versions&&"string"===typeof process.versions.node;Ca=!ya&&!Aa&&!za;var G="",Da,Ea,Fa,Ga;
+if(Aa)G=za?require("path").dirname(G)+"/":__dirname+"/",Da=function(a,b){Fa||(Fa=require("fs"));Ga||(Ga=require("path"));a=Ga.normalize(a);return Fa.readFileSync(a,b?null:"utf8")},Ea=function(a){a=Da(a,!0);a.buffer||(a=new Uint8Array(a));assert(a.buffer);return a},1<process.argv.length&&(xa=process.argv[1].replace(/\\/g,"/")),process.argv.slice(2),"undefined"!==typeof module&&(module.exports=e),e.inspect=function(){return"[Emscripten Module object]"};else if(Ca)"undefined"!=typeof read&&(Da=function(a){return read(a)}),
+Ea=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");assert("object"===typeof a);return a},"undefined"!==typeof print&&("undefined"===typeof console&&(console={}),console.log=print,console.warn=console.error="undefined"!==typeof printErr?printErr:print);else if(ya||za)za?G=self.location.href:"undefined"!==typeof document&&document.currentScript&&(G=document.currentScript.src),G=0!==G.indexOf("blob:")?G.substr(0,G.lastIndexOf("/")+1):"",Da=function(a){var b=
+new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},za&&(Ea=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)});var Ha=e.print||console.log.bind(console),I=e.printErr||console.warn.bind(console);for(F in wa)wa.hasOwnProperty(F)&&(e[F]=wa[F]);wa=null;e.thisProgram&&(xa=e.thisProgram);var Ia=[],Ja;function sa(a){Ja.delete(J.get(a));Ia.push(a)}
+function va(a){if(!Ja){Ja=new WeakMap;for(var b=0;b<J.length;b++){var c=J.get(b);c&&Ja.set(c,b)}}if(Ja.has(a))a=Ja.get(a);else{if(Ia.length)b=Ia.pop();else{try{J.grow(1)}catch(g){if(!(g instanceof RangeError))throw g;throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.";}b=J.length-1}try{J.set(b,a)}catch(g){if(!(g instanceof TypeError))throw g;if("function"===typeof WebAssembly.Function){var d={i:"i32",j:"i64",f:"f32",d:"f64"},f={parameters:[],results:[]};for(c=1;4>c;++c)f.parameters.push(d["viii"[c]]);
+c=new WebAssembly.Function(f,a)}else{d=[1,0,1,96];f={i:127,j:126,f:125,d:124};d.push(3);for(c=0;3>c;++c)d.push(f["iii"[c]]);d.push(0);d[1]=d.length-2;c=new Uint8Array([0,97,115,109,1,0,0,0].concat(d,[2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0]));c=new WebAssembly.Module(c);c=(new WebAssembly.Instance(c,{e:{f:a}})).exports.f}J.set(b,c)}Ja.set(a,b);a=b}return a}var Ka;e.wasmBinary&&(Ka=e.wasmBinary);var noExitRuntime;e.noExitRuntime&&(noExitRuntime=e.noExitRuntime);"object"!==typeof WebAssembly&&K("no native wasm support detected");
+function qa(a){var b="i32";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":z[a>>0]=0;break;case "i8":z[a>>0]=0;break;case "i16":La[a>>1]=0;break;case "i32":L[a>>2]=0;break;case "i64":M=[0,(N=0,1<=+Math.abs(N)?0<N?(Math.min(+Math.floor(N/4294967296),4294967295)|0)>>>0:~~+Math.ceil((N-+(~~N>>>0))/4294967296)>>>0:0)];L[a>>2]=M[0];L[a+4>>2]=M[1];break;case "float":Ma[a>>2]=0;break;case "double":Na[a>>3]=0;break;default:K("invalid type for setValue: "+b)}}
+function x(a,b){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return z[a>>0];case "i8":return z[a>>0];case "i16":return La[a>>1];case "i32":return L[a>>2];case "i64":return L[a>>2];case "float":return Ma[a>>2];case "double":return Na[a>>3];default:K("invalid type for getValue: "+b)}return null}var Oa,Pa=!1;function assert(a,b){a||K("Assertion failed: "+b)}function Qa(a){var b=e["_"+a];assert(b,"Cannot call unknown function "+a+", make sure it is exported");return b}
+function Ra(a,b,c,d){var f={string:function(u){var C=0;if(null!==u&&void 0!==u&&0!==u){var H=(u.length<<2)+1;C=y(H);k(u,m,C,H)}return C},array:function(u){var C=y(u.length);z.set(u,C);return C}},g=Qa(a),n=[];a=0;if(d)for(var t=0;t<d.length;t++){var w=f[c[t]];w?(0===a&&(a=pa()),n[t]=w(d[t])):n[t]=d[t]}c=g.apply(null,n);c=function(u){return"string"===b?A(u):"boolean"===b?!!u:u}(c);0!==a&&ra(a);return c}var Sa=0,Ta=1;
+function na(a){var b=Sa==Ta?y(a.length):ca(a.length);a.subarray||a.slice?m.set(a,b):m.set(new Uint8Array(a),b);return b}var Ua="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0;
+function Va(a,b,c){var d=b+c;for(c=b;a[c]&&!(c>=d);)++c;if(16<c-b&&a.subarray&&Ua)return Ua.decode(a.subarray(b,c));for(d="";b<c;){var f=a[b++];if(f&128){var g=a[b++]&63;if(192==(f&224))d+=String.fromCharCode((f&31)<<6|g);else{var n=a[b++]&63;f=224==(f&240)?(f&15)<<12|g<<6|n:(f&7)<<18|g<<12|n<<6|a[b++]&63;65536>f?d+=String.fromCharCode(f):(f-=65536,d+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else d+=String.fromCharCode(f)}return d}function A(a,b){return a?Va(m,a,b):""}
+function k(a,b,c,d){if(!(0<d))return 0;var f=c;d=c+d-1;for(var g=0;g<a.length;++g){var n=a.charCodeAt(g);if(55296<=n&&57343>=n){var t=a.charCodeAt(++g);n=65536+((n&1023)<<10)|t&1023}if(127>=n){if(c>=d)break;b[c++]=n}else{if(2047>=n){if(c+1>=d)break;b[c++]=192|n>>6}else{if(65535>=n){if(c+2>=d)break;b[c++]=224|n>>12}else{if(c+3>=d)break;b[c++]=240|n>>18;b[c++]=128|n>>12&63}b[c++]=128|n>>6&63}b[c++]=128|n&63}}b[c]=0;return c-f}
+function ba(a){for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);55296<=d&&57343>=d&&(d=65536+((d&1023)<<10)|a.charCodeAt(++c)&1023);127>=d?++b:b=2047>=d?b+2:65535>=d?b+3:b+4}return b}function Wa(a){var b=ba(a)+1,c=ca(b);c&&k(a,z,c,b);return c}var Xa,z,m,La,L,Ma,Na;
+function Ya(){var a=Oa.buffer;Xa=a;e.HEAP8=z=new Int8Array(a);e.HEAP16=La=new Int16Array(a);e.HEAP32=L=new Int32Array(a);e.HEAPU8=m=new Uint8Array(a);e.HEAPU16=new Uint16Array(a);e.HEAPU32=new Uint32Array(a);e.HEAPF32=Ma=new Float32Array(a);e.HEAPF64=Na=new Float64Array(a)}var J,Za=[],$a=[],ab=[],bb=[];function cb(){var a=e.preRun.shift();Za.unshift(a)}var db=0,eb=null,fb=null;e.preloadedImages={};e.preloadedAudios={};
+function K(a){if(e.onAbort)e.onAbort(a);I(a);Pa=!0;throw new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");}function gb(a){var b=O;return String.prototype.startsWith?b.startsWith(a):0===b.indexOf(a)}function hb(){return gb("data:application/octet-stream;base64,")}var O="sql-wasm.wasm";if(!hb()){var ib=O;O=e.locateFile?e.locateFile(ib,G):G+ib}
+function jb(){var a=O;try{if(a==O&&Ka)return new Uint8Array(Ka);if(Ea)return Ea(a);throw"both async and sync fetching of the wasm failed";}catch(b){K(b)}}function kb(){return Ka||!ya&&!za||"function"!==typeof fetch||gb("file://")?Promise.resolve().then(function(){return jb()}):fetch(O,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+O+"'";return a.arrayBuffer()}).catch(function(){return jb()})}var N,M;
+function lb(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(e);else{var c=b.Hb;"number"===typeof c?void 0===b.mb?J.get(c)():J.get(c)(b.mb):c(void 0===b.mb?null:b.mb)}}}function mb(a){return a.replace(/\b_Z[\w\d_]+/g,function(b){return b===b?b:b+" ["+b+"]"})}
+function nb(){function a(n){return(n=n.toTimeString().match(/\(([A-Za-z ]+)\)$/))?n[1]:"GMT"}if(!ob){ob=!0;var b=(new Date).getFullYear(),c=new Date(b,0,1),d=new Date(b,6,1);b=c.getTimezoneOffset();var f=d.getTimezoneOffset(),g=Math.max(b,f);L[pb()>>2]=60*g;L[tb()>>2]=Number(b!=f);c=a(c);d=a(d);c=Wa(c);d=Wa(d);f<b?(L[ub()>>2]=c,L[ub()+4>>2]=d):(L[ub()>>2]=d,L[ub()+4>>2]=c)}}var ob;
+function wb(a,b){for(var c=0,d=a.length-1;0<=d;d--){var f=a[d];"."===f?a.splice(d,1):".."===f?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c;c--)a.unshift("..");return a}function r(a){var b="/"===a.charAt(0),c="/"===a.substr(-1);(a=wb(a.split("/").filter(function(d){return!!d}),!b).join("/"))||b||(a=".");a&&c&&(a+="/");return(b?"/":"")+a}
+function xb(a){var b=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(a).slice(1);a=b[0];b=b[1];if(!a&&!b)return".";b&&(b=b.substr(0,b.length-1));return a+b}function yb(a){if("/"===a)return"/";a=r(a);a=a.replace(/\/$/,"");var b=a.lastIndexOf("/");return-1===b?a:a.substr(b+1)}
+function zb(){if("object"===typeof crypto&&"function"===typeof crypto.getRandomValues){var a=new Uint8Array(1);return function(){crypto.getRandomValues(a);return a[0]}}if(Aa)try{var b=require("crypto");return function(){return b.randomBytes(1)[0]}}catch(c){}return function(){K("randomDevice")}}
+function Ab(){for(var a="",b=!1,c=arguments.length-1;-1<=c&&!b;c--){b=0<=c?arguments[c]:"/";if("string"!==typeof b)throw new TypeError("Arguments to path.resolve must be strings");if(!b)return"";a=b+"/"+a;b="/"===b.charAt(0)}a=wb(a.split("/").filter(function(d){return!!d}),!b).join("/");return(b?"/":"")+a||"."}var Bb=[];function Cb(a,b){Bb[a]={input:[],output:[],cb:b};Db(a,Eb)}
+var Eb={open:function(a){var b=Bb[a.node.rdev];if(!b)throw new P(43);a.tty=b;a.seekable=!1},close:function(a){a.tty.cb.flush(a.tty)},flush:function(a){a.tty.cb.flush(a.tty)},read:function(a,b,c,d){if(!a.tty||!a.tty.cb.xb)throw new P(60);for(var f=0,g=0;g<d;g++){try{var n=a.tty.cb.xb(a.tty)}catch(t){throw new P(29);}if(void 0===n&&0===f)throw new P(6);if(null===n||void 0===n)break;f++;b[c+g]=n}f&&(a.node.timestamp=Date.now());return f},write:function(a,b,c,d){if(!a.tty||!a.tty.cb.qb)throw new P(60);
+try{for(var f=0;f<d;f++)a.tty.cb.qb(a.tty,b[c+f])}catch(g){throw new P(29);}d&&(a.node.timestamp=Date.now());return f}},Fb={xb:function(a){if(!a.input.length){var b=null;if(Aa){var c=Buffer.zb?Buffer.zb(256):new Buffer(256),d=0;try{d=Fa.readSync(process.stdin.fd,c,0,256,null)}catch(f){if(-1!=f.toString().indexOf("EOF"))d=0;else throw f;}0<d?b=c.slice(0,d).toString("utf-8"):b=null}else"undefined"!=typeof window&&"function"==typeof window.prompt?(b=window.prompt("Input: "),null!==b&&(b+="\n")):"function"==
+typeof readline&&(b=readline(),null!==b&&(b+="\n"));if(!b)return null;a.input=ma(b,!0)}return a.input.shift()},qb:function(a,b){null===b||10===b?(Ha(Va(a.output,0)),a.output=[]):0!=b&&a.output.push(b)},flush:function(a){a.output&&0<a.output.length&&(Ha(Va(a.output,0)),a.output=[])}},Gb={qb:function(a,b){null===b||10===b?(I(Va(a.output,0)),a.output=[]):0!=b&&a.output.push(b)},flush:function(a){a.output&&0<a.output.length&&(I(Va(a.output,0)),a.output=[])}},Q={Va:null,Wa:function(){return Q.createNode(null,
+"/",16895,0)},createNode:function(a,b,c,d){if(24576===(c&61440)||4096===(c&61440))throw new P(63);Q.Va||(Q.Va={dir:{node:{Ua:Q.Na.Ua,Ta:Q.Na.Ta,lookup:Q.Na.lookup,gb:Q.Na.gb,rename:Q.Na.rename,unlink:Q.Na.unlink,rmdir:Q.Na.rmdir,readdir:Q.Na.readdir,symlink:Q.Na.symlink},stream:{Za:Q.Oa.Za}},file:{node:{Ua:Q.Na.Ua,Ta:Q.Na.Ta},stream:{Za:Q.Oa.Za,read:Q.Oa.read,write:Q.Oa.write,sb:Q.Oa.sb,hb:Q.Oa.hb,ib:Q.Oa.ib}},link:{node:{Ua:Q.Na.Ua,Ta:Q.Na.Ta,readlink:Q.Na.readlink},stream:{}},ub:{node:{Ua:Q.Na.Ua,
+Ta:Q.Na.Ta},stream:Hb}});c=Ib(a,b,c,d);R(c.mode)?(c.Na=Q.Va.dir.node,c.Oa=Q.Va.dir.stream,c.Ma={}):32768===(c.mode&61440)?(c.Na=Q.Va.file.node,c.Oa=Q.Va.file.stream,c.Sa=0,c.Ma=null):40960===(c.mode&61440)?(c.Na=Q.Va.link.node,c.Oa=Q.Va.link.stream):8192===(c.mode&61440)&&(c.Na=Q.Va.ub.node,c.Oa=Q.Va.ub.stream);c.timestamp=Date.now();a&&(a.Ma[b]=c);return c},Sb:function(a){if(a.Ma&&a.Ma.subarray){for(var b=[],c=0;c<a.Sa;++c)b.push(a.Ma[c]);return b}return a.Ma},Tb:function(a){return a.Ma?a.Ma.subarray?
+a.Ma.subarray(0,a.Sa):new Uint8Array(a.Ma):new Uint8Array(0)},vb:function(a,b){var c=a.Ma?a.Ma.length:0;c>=b||(b=Math.max(b,c*(1048576>c?2:1.125)>>>0),0!=c&&(b=Math.max(b,256)),c=a.Ma,a.Ma=new Uint8Array(b),0<a.Sa&&a.Ma.set(c.subarray(0,a.Sa),0))},Pb:function(a,b){if(a.Sa!=b)if(0==b)a.Ma=null,a.Sa=0;else{if(!a.Ma||a.Ma.subarray){var c=a.Ma;a.Ma=new Uint8Array(b);c&&a.Ma.set(c.subarray(0,Math.min(b,a.Sa)))}else if(a.Ma||(a.Ma=[]),a.Ma.length>b)a.Ma.length=b;else for(;a.Ma.length<b;)a.Ma.push(0);a.Sa=
+b}},Na:{Ua:function(a){var b={};b.dev=8192===(a.mode&61440)?a.id:1;b.ino=a.id;b.mode=a.mode;b.nlink=1;b.uid=0;b.gid=0;b.rdev=a.rdev;R(a.mode)?b.size=4096:32768===(a.mode&61440)?b.size=a.Sa:40960===(a.mode&61440)?b.size=a.link.length:b.size=0;b.atime=new Date(a.timestamp);b.mtime=new Date(a.timestamp);b.ctime=new Date(a.timestamp);b.Gb=4096;b.blocks=Math.ceil(b.size/b.Gb);return b},Ta:function(a,b){void 0!==b.mode&&(a.mode=b.mode);void 0!==b.timestamp&&(a.timestamp=b.timestamp);void 0!==b.size&&Q.Pb(a,
+b.size)},lookup:function(){throw Jb[44];},gb:function(a,b,c,d){return Q.createNode(a,b,c,d)},rename:function(a,b,c){if(R(a.mode)){try{var d=Kb(b,c)}catch(g){}if(d)for(var f in d.Ma)throw new P(55);}delete a.parent.Ma[a.name];a.name=c;b.Ma[c]=a;a.parent=b},unlink:function(a,b){delete a.Ma[b]},rmdir:function(a,b){var c=Kb(a,b),d;for(d in c.Ma)throw new P(55);delete a.Ma[b]},readdir:function(a){var b=[".",".."],c;for(c in a.Ma)a.Ma.hasOwnProperty(c)&&b.push(c);return b},symlink:function(a,b,c){a=Q.createNode(a,
+b,41471,0);a.link=c;return a},readlink:function(a){if(40960!==(a.mode&61440))throw new P(28);return a.link}},Oa:{read:function(a,b,c,d,f){var g=a.node.Ma;if(f>=a.node.Sa)return 0;a=Math.min(a.node.Sa-f,d);if(8<a&&g.subarray)b.set(g.subarray(f,f+a),c);else for(d=0;d<a;d++)b[c+d]=g[f+d];return a},write:function(a,b,c,d,f,g){b.buffer===z.buffer&&(g=!1);if(!d)return 0;a=a.node;a.timestamp=Date.now();if(b.subarray&&(!a.Ma||a.Ma.subarray)){if(g)return a.Ma=b.subarray(c,c+d),a.Sa=d;if(0===a.Sa&&0===f)return a.Ma=
+b.slice(c,c+d),a.Sa=d;if(f+d<=a.Sa)return a.Ma.set(b.subarray(c,c+d),f),d}Q.vb(a,f+d);if(a.Ma.subarray&&b.subarray)a.Ma.set(b.subarray(c,c+d),f);else for(g=0;g<d;g++)a.Ma[f+g]=b[c+g];a.Sa=Math.max(a.Sa,f+d);return d},Za:function(a,b,c){1===c?b+=a.position:2===c&&32768===(a.node.mode&61440)&&(b+=a.node.Sa);if(0>b)throw new P(28);return b},sb:function(a,b,c){Q.vb(a.node,b+c);a.node.Sa=Math.max(a.node.Sa,b+c)},hb:function(a,b,c,d,f,g){assert(0===b);if(32768!==(a.node.mode&61440))throw new P(43);a=a.node.Ma;
+if(g&2||a.buffer!==Xa){if(0<d||d+c<a.length)a.subarray?a=a.subarray(d,d+c):a=Array.prototype.slice.call(a,d,d+c);d=!0;g=16384*Math.ceil(c/16384);for(b=ca(g);c<g;)z[b+c++]=0;c=b;if(!c)throw new P(48);z.set(a,c)}else d=!1,c=a.byteOffset;return{Ob:c,kb:d}},ib:function(a,b,c,d,f){if(32768!==(a.node.mode&61440))throw new P(43);if(f&2)return 0;Q.Oa.write(a,b,0,d,c,!1);return 0}}},Lb=null,Mb={},T=[],Nb=1,U=null,Ob=!0,V={},P=null,Jb={};
+function W(a,b){a=Ab("/",a);b=b||{};if(!a)return{path:"",node:null};var c={wb:!0,rb:0},d;for(d in c)void 0===b[d]&&(b[d]=c[d]);if(8<b.rb)throw new P(32);a=wb(a.split("/").filter(function(n){return!!n}),!1);var f=Lb;c="/";for(d=0;d<a.length;d++){var g=d===a.length-1;if(g&&b.parent)break;f=Kb(f,a[d]);c=r(c+"/"+a[d]);f.ab&&(!g||g&&b.wb)&&(f=f.ab.root);if(!g||b.Ya)for(g=0;40960===(f.mode&61440);)if(f=Pb(c),c=Ab(xb(c),f),f=W(c,{rb:b.rb}).node,40<g++)throw new P(32);}return{path:c,node:f}}
+function Qb(a){for(var b;;){if(a===a.parent)return a=a.Wa.yb,b?"/"!==a[a.length-1]?a+"/"+b:a+b:a;b=b?a.name+"/"+b:a.name;a=a.parent}}function Rb(a,b){for(var c=0,d=0;d<b.length;d++)c=(c<<5)-c+b.charCodeAt(d)|0;return(a+c>>>0)%U.length}function Sb(a){var b=Rb(a.parent.id,a.name);if(U[b]===a)U[b]=a.bb;else for(b=U[b];b;){if(b.bb===a){b.bb=a.bb;break}b=b.bb}}
+function Kb(a,b){var c;if(c=(c=Tb(a,"x"))?c:a.Na.lookup?0:2)throw new P(c,a);for(c=U[Rb(a.id,b)];c;c=c.bb){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return a.Na.lookup(a,b)}function Ib(a,b,c,d){a=new Ub(a,b,c,d);b=Rb(a.parent.id,a.name);a.bb=U[b];return U[b]=a}function R(a){return 16384===(a&61440)}var Vb={r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090};function Wb(a){var b=["r","w","rw"][a&3];a&512&&(b+="w");return b}
+function Tb(a,b){if(Ob)return 0;if(-1===b.indexOf("r")||a.mode&292){if(-1!==b.indexOf("w")&&!(a.mode&146)||-1!==b.indexOf("x")&&!(a.mode&73))return 2}else return 2;return 0}function Xb(a,b){try{return Kb(a,b),20}catch(c){}return Tb(a,"wx")}function Yb(a,b,c){try{var d=Kb(a,b)}catch(f){return f.Pa}if(a=Tb(a,"wx"))return a;if(c){if(!R(d.mode))return 54;if(d===d.parent||"/"===Qb(d))return 10}else if(R(d.mode))return 31;return 0}
+function Zb(a){var b=4096;for(a=a||0;a<=b;a++)if(!T[a])return a;throw new P(33);}function $b(a,b){ac||(ac=function(){},ac.prototype={});var c=new ac,d;for(d in a)c[d]=a[d];a=c;b=Zb(b);a.fd=b;return T[b]=a}var Hb={open:function(a){a.Oa=Mb[a.node.rdev].Oa;a.Oa.open&&a.Oa.open(a)},Za:function(){throw new P(70);}};function Db(a,b){Mb[a]={Oa:b}}
+function bc(a,b){var c="/"===b,d=!b;if(c&&Lb)throw new P(10);if(!c&&!d){var f=W(b,{wb:!1});b=f.path;f=f.node;if(f.ab)throw new P(10);if(!R(f.mode))throw new P(54);}b={type:a,Ub:{},yb:b,Mb:[]};a=a.Wa(b);a.Wa=b;b.root=a;c?Lb=a:f&&(f.ab=b,f.Wa&&f.Wa.Mb.push(b))}function ea(a,b,c){var d=W(a,{parent:!0}).node;a=yb(a);if(!a||"."===a||".."===a)throw new P(28);var f=Xb(d,a);if(f)throw new P(f);if(!d.Na.gb)throw new P(63);return d.Na.gb(d,a,b,c)}function X(a,b){ea(a,(void 0!==b?b:511)&1023|16384,0)}
+function cc(a,b,c){"undefined"===typeof c&&(c=b,b=438);ea(a,b|8192,c)}function dc(a,b){if(!Ab(a))throw new P(44);var c=W(b,{parent:!0}).node;if(!c)throw new P(44);b=yb(b);var d=Xb(c,b);if(d)throw new P(d);if(!c.Na.symlink)throw new P(63);c.Na.symlink(c,b,a)}
+function ua(a){var b=W(a,{parent:!0}).node,c=yb(a),d=Kb(b,c),f=Yb(b,c,!1);if(f)throw new P(f);if(!b.Na.unlink)throw new P(63);if(d.ab)throw new P(10);try{V.willDeletePath&&V.willDeletePath(a)}catch(g){I("FS.trackingDelegate['willDeletePath']('"+a+"') threw an exception: "+g.message)}b.Na.unlink(b,c);Sb(d);try{if(V.onDeletePath)V.onDeletePath(a)}catch(g){I("FS.trackingDelegate['onDeletePath']('"+a+"') threw an exception: "+g.message)}}
+function Pb(a){a=W(a).node;if(!a)throw new P(44);if(!a.Na.readlink)throw new P(28);return Ab(Qb(a.parent),a.Na.readlink(a))}function ec(a,b){a=W(a,{Ya:!b}).node;if(!a)throw new P(44);if(!a.Na.Ua)throw new P(63);return a.Na.Ua(a)}function fc(a){return ec(a,!0)}function fa(a,b){var c;"string"===typeof a?c=W(a,{Ya:!0}).node:c=a;if(!c.Na.Ta)throw new P(63);c.Na.Ta(c,{mode:b&4095|c.mode&-4096,timestamp:Date.now()})}
+function hc(a){var b;"string"===typeof a?b=W(a,{Ya:!0}).node:b=a;if(!b.Na.Ta)throw new P(63);b.Na.Ta(b,{timestamp:Date.now()})}function ic(a,b){if(0>b)throw new P(28);var c;"string"===typeof a?c=W(a,{Ya:!0}).node:c=a;if(!c.Na.Ta)throw new P(63);if(R(c.mode))throw new P(31);if(32768!==(c.mode&61440))throw new P(28);if(a=Tb(c,"w"))throw new P(a);c.Na.Ta(c,{size:b,timestamp:Date.now()})}
+function v(a,b,c,d){if(""===a)throw new P(44);if("string"===typeof b){var f=Vb[b];if("undefined"===typeof f)throw Error("Unknown file open mode: "+b);b=f}c=b&64?("undefined"===typeof c?438:c)&4095|32768:0;if("object"===typeof a)var g=a;else{a=r(a);try{g=W(a,{Ya:!(b&131072)}).node}catch(n){}}f=!1;if(b&64)if(g){if(b&128)throw new P(20);}else g=ea(a,c,0),f=!0;if(!g)throw new P(44);8192===(g.mode&61440)&&(b&=-513);if(b&65536&&!R(g.mode))throw new P(54);if(!f&&(c=g?40960===(g.mode&61440)?32:R(g.mode)&&
+("r"!==Wb(b)||b&512)?31:Tb(g,Wb(b)):44))throw new P(c);b&512&&ic(g,0);b&=-131713;d=$b({node:g,path:Qb(g),flags:b,seekable:!0,position:0,Oa:g.Oa,Rb:[],error:!1},d);d.Oa.open&&d.Oa.open(d);!e.logReadFiles||b&1||(Lc||(Lc={}),a in Lc||(Lc[a]=1,I("FS.trackingDelegate error on read file: "+a)));try{V.onOpenFile&&(g=0,1!==(b&2097155)&&(g|=1),0!==(b&2097155)&&(g|=2),V.onOpenFile(a,g))}catch(n){I("FS.trackingDelegate['onOpenFile']('"+a+"', flags) threw an exception: "+n.message)}return d}
+function la(a){if(null===a.fd)throw new P(8);a.ob&&(a.ob=null);try{a.Oa.close&&a.Oa.close(a)}catch(b){throw b;}finally{T[a.fd]=null}a.fd=null}function Mc(a,b,c){if(null===a.fd)throw new P(8);if(!a.seekable||!a.Oa.Za)throw new P(70);if(0!=c&&1!=c&&2!=c)throw new P(28);a.position=a.Oa.Za(a,b,c);a.Rb=[]}
+function Oc(a,b,c,d,f){if(0>d||0>f)throw new P(28);if(null===a.fd)throw new P(8);if(1===(a.flags&2097155))throw new P(8);if(R(a.node.mode))throw new P(31);if(!a.Oa.read)throw new P(28);var g="undefined"!==typeof f;if(!g)f=a.position;else if(!a.seekable)throw new P(70);b=a.Oa.read(a,b,c,d,f);g||(a.position+=b);return b}
+function ka(a,b,c,d,f,g){if(0>d||0>f)throw new P(28);if(null===a.fd)throw new P(8);if(0===(a.flags&2097155))throw new P(8);if(R(a.node.mode))throw new P(31);if(!a.Oa.write)throw new P(28);a.seekable&&a.flags&1024&&Mc(a,0,2);var n="undefined"!==typeof f;if(!n)f=a.position;else if(!a.seekable)throw new P(70);b=a.Oa.write(a,b,c,d,f,g);n||(a.position+=b);try{if(a.path&&V.onWriteToFile)V.onWriteToFile(a.path)}catch(t){I("FS.trackingDelegate['onWriteToFile']('"+a.path+"') threw an exception: "+t.message)}return b}
+function ta(a){var b={encoding:"binary"};b=b||{};b.flags=b.flags||0;b.encoding=b.encoding||"binary";if("utf8"!==b.encoding&&"binary"!==b.encoding)throw Error('Invalid encoding type "'+b.encoding+'"');var c,d=v(a,b.flags);a=ec(a).size;var f=new Uint8Array(a);Oc(d,f,0,a,0);"utf8"===b.encoding?c=Va(f,0):"binary"===b.encoding&&(c=f);la(d);return c}
+function Pc(){P||(P=function(a,b){this.node=b;this.Qb=function(c){this.Pa=c};this.Qb(a);this.message="FS error"},P.prototype=Error(),P.prototype.constructor=P,[44].forEach(function(a){Jb[a]=new P(a);Jb[a].stack="<generic error, no stack>"}))}var Qc;function da(a,b){var c=0;a&&(c|=365);b&&(c|=146);return c}
+function Rc(a,b,c){a=r("/dev/"+a);var d=da(!!b,!!c);Sc||(Sc=64);var f=Sc++<<8|0;Db(f,{open:function(g){g.seekable=!1},close:function(){c&&c.buffer&&c.buffer.length&&c(10)},read:function(g,n,t,w){for(var u=0,C=0;C<w;C++){try{var H=b()}catch(aa){throw new P(29);}if(void 0===H&&0===u)throw new P(6);if(null===H||void 0===H)break;u++;n[t+C]=H}u&&(g.node.timestamp=Date.now());return u},write:function(g,n,t,w){for(var u=0;u<w;u++)try{c(n[t+u])}catch(C){throw new P(29);}w&&(g.node.timestamp=Date.now());return u}});
+cc(a,d,f)}var Sc,Y={},ac,Lc,Tc={};
+function Uc(a,b,c){try{var d=a(b)}catch(f){if(f&&f.node&&r(b)!==r(Qb(f.node)))return-54;throw f;}L[c>>2]=d.dev;L[c+4>>2]=0;L[c+8>>2]=d.ino;L[c+12>>2]=d.mode;L[c+16>>2]=d.nlink;L[c+20>>2]=d.uid;L[c+24>>2]=d.gid;L[c+28>>2]=d.rdev;L[c+32>>2]=0;M=[d.size>>>0,(N=d.size,1<=+Math.abs(N)?0<N?(Math.min(+Math.floor(N/4294967296),4294967295)|0)>>>0:~~+Math.ceil((N-+(~~N>>>0))/4294967296)>>>0:0)];L[c+40>>2]=M[0];L[c+44>>2]=M[1];L[c+48>>2]=4096;L[c+52>>2]=d.blocks;L[c+56>>2]=d.atime.getTime()/1E3|0;L[c+60>>2]=
+0;L[c+64>>2]=d.mtime.getTime()/1E3|0;L[c+68>>2]=0;L[c+72>>2]=d.ctime.getTime()/1E3|0;L[c+76>>2]=0;M=[d.ino>>>0,(N=d.ino,1<=+Math.abs(N)?0<N?(Math.min(+Math.floor(N/4294967296),4294967295)|0)>>>0:~~+Math.ceil((N-+(~~N>>>0))/4294967296)>>>0:0)];L[c+80>>2]=M[0];L[c+84>>2]=M[1];return 0}var Vc=void 0;function Wc(){Vc+=4;return L[Vc-4>>2]}function Z(a){a=T[a];if(!a)throw new P(8);return a}var Xc;
+Aa?Xc=function(){var a=process.hrtime();return 1E3*a[0]+a[1]/1E6}:"undefined"!==typeof dateNow?Xc=dateNow:Xc=function(){return performance.now()};var Yc={};function Zc(){if(!$c){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"===typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:xa||"./this.program"},b;for(b in Yc)a[b]=Yc[b];var c=[];for(b in a)c.push(b+"="+a[b]);$c=c}return $c}var $c;
+function Ub(a,b,c,d){a||(a=this);this.parent=a;this.Wa=a.Wa;this.ab=null;this.id=Nb++;this.name=b;this.mode=c;this.Na={};this.Oa={};this.rdev=d}Object.defineProperties(Ub.prototype,{read:{get:function(){return 365===(this.mode&365)},set:function(a){a?this.mode|=365:this.mode&=-366}},write:{get:function(){return 146===(this.mode&146)},set:function(a){a?this.mode|=146:this.mode&=-147}}});Pc();U=Array(4096);bc(Q,"/");X("/tmp");X("/home");X("/home/web_user");
+(function(){X("/dev");Db(259,{read:function(){return 0},write:function(b,c,d,f){return f}});cc("/dev/null",259);Cb(1280,Fb);Cb(1536,Gb);cc("/dev/tty",1280);cc("/dev/tty1",1536);var a=zb();Rc("random",a);Rc("urandom",a);X("/dev/shm");X("/dev/shm/tmp")})();X("/proc");X("/proc/self");X("/proc/self/fd");
+bc({Wa:function(){var a=Ib("/proc/self","fd",16895,73);a.Na={lookup:function(b,c){var d=T[+c];if(!d)throw new P(8);b={parent:null,Wa:{yb:"fake"},Na:{readlink:function(){return d.path}}};return b.parent=b}};return a}},"/proc/self/fd");function ma(a,b){var c=Array(ba(a)+1);a=k(a,c,0,c.length);b&&(c.length=a);return c}$a.push({Hb:function(){ad()}});
+var ed={a:function(a,b,c,d){K("Assertion failed: "+A(a)+", at: "+[b?A(b):"unknown filename",c,d?A(d):"unknown function"])},r:function(a,b){nb();a=new Date(1E3*L[a>>2]);L[b>>2]=a.getSeconds();L[b+4>>2]=a.getMinutes();L[b+8>>2]=a.getHours();L[b+12>>2]=a.getDate();L[b+16>>2]=a.getMonth();L[b+20>>2]=a.getFullYear()-1900;L[b+24>>2]=a.getDay();var c=new Date(a.getFullYear(),0,1);L[b+28>>2]=(a.getTime()-c.getTime())/864E5|0;L[b+36>>2]=-(60*a.getTimezoneOffset());var d=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();
+c=c.getTimezoneOffset();a=(d!=c&&a.getTimezoneOffset()==Math.min(c,d))|0;L[b+32>>2]=a;a=L[ub()+(a?4:0)>>2];L[b+40>>2]=a;return b},E:function(a,b){try{a=A(a);if(b&-8)var c=-28;else{var d;(d=W(a,{Ya:!0}).node)?(a="",b&4&&(a+="r"),b&2&&(a+="w"),b&1&&(a+="x"),c=a&&Tb(d,a)?-2:0):c=-44}return c}catch(f){return"undefined"!==typeof Y&&f instanceof P||K(f),-f.Pa}},I:function(a,b){try{return a=A(a),fa(a,b),0}catch(c){return"undefined"!==typeof Y&&c instanceof P||K(c),-c.Pa}},C:function(a){try{return a=A(a),
+hc(a),0}catch(b){return"undefined"!==typeof Y&&b instanceof P||K(b),-b.Pa}},J:function(a,b){try{var c=T[a];if(!c)throw new P(8);fa(c.node,b);return 0}catch(d){return"undefined"!==typeof Y&&d instanceof P||K(d),-d.Pa}},D:function(a){try{var b=T[a];if(!b)throw new P(8);hc(b.node);return 0}catch(c){return"undefined"!==typeof Y&&c instanceof P||K(c),-c.Pa}},b:function(a,b,c){Vc=c;try{var d=Z(a);switch(b){case 0:var f=Wc();return 0>f?-28:v(d.path,d.flags,0,f).fd;case 1:case 2:return 0;case 3:return d.flags;
+case 4:return f=Wc(),d.flags|=f,0;case 12:return f=Wc(),La[f+0>>1]=2,0;case 13:case 14:return 0;case 16:case 8:return-28;case 9:return L[bd()>>2]=28,-1;default:return-28}}catch(g){return"undefined"!==typeof Y&&g instanceof P||K(g),-g.Pa}},H:function(a,b){try{var c=Z(a);return Uc(ec,c.path,b)}catch(d){return"undefined"!==typeof Y&&d instanceof P||K(d),-d.Pa}},z:function(a,b,c){try{var d=T[a];if(!d)throw new P(8);if(0===(d.flags&2097155))throw new P(28);ic(d.node,c);return 0}catch(f){return"undefined"!==
+typeof Y&&f instanceof P||K(f),-f.Pa}},y:function(a,b){try{if(0===b)return-28;if(b<ba("/")+1)return-68;k("/",m,a,b);return a}catch(c){return"undefined"!==typeof Y&&c instanceof P||K(c),-c.Pa}},x:function(){return 0},d:function(){return 42},G:function(a,b){try{return a=A(a),Uc(fc,a,b)}catch(c){return"undefined"!==typeof Y&&c instanceof P||K(c),-c.Pa}},F:function(a,b){try{return a=A(a),a=r(a),"/"===a[a.length-1]&&(a=a.substr(0,a.length-1)),X(a,b),0}catch(c){return"undefined"!==typeof Y&&c instanceof
+P||K(c),-c.Pa}},i:function(a,b,c,d,f,g){try{a:{g<<=12;var n=!1;if(0!==(d&16)&&0!==a%16384)var t=-28;else{if(0!==(d&32)){var w=cd(16384,b);if(!w){t=-48;break a}dd(w,0,b);n=!0}else{var u=T[f];if(!u){t=-8;break a}var C=g;if(0!==(c&2)&&0===(d&2)&&2!==(u.flags&2097155))throw new P(2);if(1===(u.flags&2097155))throw new P(2);if(!u.Oa.hb)throw new P(43);var H=u.Oa.hb(u,a,b,C,c,d);w=H.Ob;n=H.kb}Tc[w]={Lb:w,Kb:b,kb:n,fd:f,Nb:c,flags:d,offset:g};t=w}}return t}catch(aa){return"undefined"!==typeof Y&&aa instanceof
+P||K(aa),-aa.Pa}},h:function(a,b){try{if(-1===(a|0)||0===b)var c=-28;else{var d=Tc[a];if(d&&b===d.Kb){var f=T[d.fd];if(d.Nb&2){var g=d.flags,n=d.offset,t=m.slice(a,a+b);f&&f.Oa.ib&&f.Oa.ib(f,t,n,b,g)}Tc[a]=null;d.kb&&oa(d.Lb)}c=0}return c}catch(w){return"undefined"!==typeof Y&&w instanceof P||K(w),-w.Pa}},j:function(a,b,c){Vc=c;try{var d=A(a),f=c?Wc():0;return v(d,b,f).fd}catch(g){return"undefined"!==typeof Y&&g instanceof P||K(g),-g.Pa}},v:function(a,b,c){try{a=A(a);if(0>=c)var d=-28;else{var f=
+Pb(a),g=Math.min(c,ba(f)),n=z[b+g];k(f,m,b,c+1);z[b+g]=n;d=g}return d}catch(t){return"undefined"!==typeof Y&&t instanceof P||K(t),-t.Pa}},u:function(a){try{a=A(a);var b=W(a,{parent:!0}).node,c=yb(a),d=Kb(b,c),f=Yb(b,c,!0);if(f)throw new P(f);if(!b.Na.rmdir)throw new P(63);if(d.ab)throw new P(10);try{V.willDeletePath&&V.willDeletePath(a)}catch(g){I("FS.trackingDelegate['willDeletePath']('"+a+"') threw an exception: "+g.message)}b.Na.rmdir(b,c);Sb(d);try{if(V.onDeletePath)V.onDeletePath(a)}catch(g){I("FS.trackingDelegate['onDeletePath']('"+
+a+"') threw an exception: "+g.message)}return 0}catch(g){return"undefined"!==typeof Y&&g instanceof P||K(g),-g.Pa}},f:function(a,b){try{return a=A(a),Uc(ec,a,b)}catch(c){return"undefined"!==typeof Y&&c instanceof P||K(c),-c.Pa}},t:function(a){try{return a=A(a),ua(a),0}catch(b){return"undefined"!==typeof Y&&b instanceof P||K(b),-b.Pa}},l:function(a,b,c){m.copyWithin(a,b,b+c)},c:function(a){a>>>=0;var b=m.length;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);
+d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%65536);a:{try{Oa.grow(Math.min(2147483648,d)-Xa.byteLength+65535>>>16);Ya();var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},p:function(a){for(var b=Xc();Xc()-b<a;);},n:function(a,b){try{var c=0;Zc().forEach(function(d,f){var g=b+c;f=L[a+4*f>>2]=g;for(g=0;g<d.length;++g)z[f++>>0]=d.charCodeAt(g);z[f>>0]=0;c+=d.length+1});return 0}catch(d){return"undefined"!==typeof Y&&d instanceof P||K(d),d.Pa}},o:function(a,b){try{var c=Zc();L[a>>2]=c.length;
+var d=0;c.forEach(function(f){d+=f.length+1});L[b>>2]=d;return 0}catch(f){return"undefined"!==typeof Y&&f instanceof P||K(f),f.Pa}},e:function(a){try{var b=Z(a);la(b);return 0}catch(c){return"undefined"!==typeof Y&&c instanceof P||K(c),c.Pa}},m:function(a,b){try{var c=Z(a);z[b>>0]=c.tty?2:R(c.mode)?3:40960===(c.mode&61440)?7:4;return 0}catch(d){return"undefined"!==typeof Y&&d instanceof P||K(d),d.Pa}},w:function(a,b,c,d){try{a:{for(var f=Z(a),g=a=0;g<c;g++){var n=L[b+(8*g+4)>>2],t=Oc(f,z,L[b+8*g>>
+2],n,void 0);if(0>t){var w=-1;break a}a+=t;if(t<n)break}w=a}L[d>>2]=w;return 0}catch(u){return"undefined"!==typeof Y&&u instanceof P||K(u),u.Pa}},k:function(a,b,c,d,f){try{var g=Z(a);a=4294967296*c+(b>>>0);if(-9007199254740992>=a||9007199254740992<=a)return-61;Mc(g,a,d);M=[g.position>>>0,(N=g.position,1<=+Math.abs(N)?0<N?(Math.min(+Math.floor(N/4294967296),4294967295)|0)>>>0:~~+Math.ceil((N-+(~~N>>>0))/4294967296)>>>0:0)];L[f>>2]=M[0];L[f+4>>2]=M[1];g.ob&&0===a&&0===d&&(g.ob=null);return 0}catch(n){return"undefined"!==
+typeof Y&&n instanceof P||K(n),n.Pa}},B:function(a){try{var b=Z(a);return b.Oa&&b.Oa.fsync?-b.Oa.fsync(b):0}catch(c){return"undefined"!==typeof Y&&c instanceof P||K(c),c.Pa}},s:function(a,b,c,d){try{a:{for(var f=Z(a),g=a=0;g<c;g++){var n=ka(f,z,L[b+8*g>>2],L[b+(8*g+4)>>2],void 0);if(0>n){var t=-1;break a}a+=n}t=a}L[d>>2]=t;return 0}catch(w){return"undefined"!==typeof Y&&w instanceof P||K(w),w.Pa}},g:function(a){var b=Date.now();L[a>>2]=b/1E3|0;L[a+4>>2]=b%1E3*1E3|0;return 0},A:function(a){switch(a){case 30:return 16384;
+case 85:return 131072;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;
+case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1E3;case 89:return 700;case 71:return 256;
+case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:return"object"===typeof navigator?navigator.hardwareConcurrency||1:1}L[bd()>>2]=28;return-1},K:function(a){var b=Date.now()/1E3|0;a&&(L[a>>2]=b);return b},q:function(a,b){if(b){var c=b+8;b=1E3*L[c>>2];b+=L[c+4>>2]/1E3}else b=Date.now();a=A(a);try{var d=W(a,{Ya:!0}).node;d.Na.Ta(d,{timestamp:Math.max(b,b)});var f=0}catch(g){if(!(g instanceof P)){b:{f=Error();if(!f.stack){try{throw Error();
+}catch(n){f=n}if(!f.stack){f="(no stack trace available)";break b}}f=f.stack.toString()}e.extraStackTrace&&(f+="\n"+e.extraStackTrace());f=mb(f);throw g+" : "+f;}f=g.Pa;L[bd()>>2]=f;f=-1}return f}};
+(function(){function a(f){e.asm=f.exports;Oa=e.asm.L;Ya();J=e.asm.M;db--;e.monitorRunDependencies&&e.monitorRunDependencies(db);0==db&&(null!==eb&&(clearInterval(eb),eb=null),fb&&(f=fb,fb=null,f()))}function b(f){a(f.instance)}function c(f){return kb().then(function(g){return WebAssembly.instantiate(g,d)}).then(f,function(g){I("failed to asynchronously prepare wasm: "+g);K(g)})}var d={a:ed};db++;e.monitorRunDependencies&&e.monitorRunDependencies(db);if(e.instantiateWasm)try{return e.instantiateWasm(d,
+a)}catch(f){return I("Module.instantiateWasm callback failed with error: "+f),!1}(function(){return Ka||"function"!==typeof WebAssembly.instantiateStreaming||hb()||gb("file://")||"function"!==typeof fetch?c(b):fetch(O,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,d).then(b,function(g){I("wasm streaming compile failed: "+g);I("falling back to ArrayBuffer instantiation");return c(b)})})})();return{}})();
+var ad=e.___wasm_call_ctors=function(){return(ad=e.___wasm_call_ctors=e.asm.N).apply(null,arguments)},dd=e._memset=function(){return(dd=e._memset=e.asm.O).apply(null,arguments)};e._sqlite3_free=function(){return(e._sqlite3_free=e.asm.P).apply(null,arguments)};var bd=e.___errno_location=function(){return(bd=e.___errno_location=e.asm.Q).apply(null,arguments)};e._sqlite3_finalize=function(){return(e._sqlite3_finalize=e.asm.R).apply(null,arguments)};
+e._sqlite3_reset=function(){return(e._sqlite3_reset=e.asm.S).apply(null,arguments)};e._sqlite3_clear_bindings=function(){return(e._sqlite3_clear_bindings=e.asm.T).apply(null,arguments)};e._sqlite3_value_blob=function(){return(e._sqlite3_value_blob=e.asm.U).apply(null,arguments)};e._sqlite3_value_text=function(){return(e._sqlite3_value_text=e.asm.V).apply(null,arguments)};e._sqlite3_value_bytes=function(){return(e._sqlite3_value_bytes=e.asm.W).apply(null,arguments)};
+e._sqlite3_value_double=function(){return(e._sqlite3_value_double=e.asm.X).apply(null,arguments)};e._sqlite3_value_int=function(){return(e._sqlite3_value_int=e.asm.Y).apply(null,arguments)};e._sqlite3_value_type=function(){return(e._sqlite3_value_type=e.asm.Z).apply(null,arguments)};e._sqlite3_result_blob=function(){return(e._sqlite3_result_blob=e.asm._).apply(null,arguments)};e._sqlite3_result_double=function(){return(e._sqlite3_result_double=e.asm.$).apply(null,arguments)};
+e._sqlite3_result_error=function(){return(e._sqlite3_result_error=e.asm.aa).apply(null,arguments)};e._sqlite3_result_int=function(){return(e._sqlite3_result_int=e.asm.ba).apply(null,arguments)};e._sqlite3_result_int64=function(){return(e._sqlite3_result_int64=e.asm.ca).apply(null,arguments)};e._sqlite3_result_null=function(){return(e._sqlite3_result_null=e.asm.da).apply(null,arguments)};e._sqlite3_result_text=function(){return(e._sqlite3_result_text=e.asm.ea).apply(null,arguments)};
+e._sqlite3_step=function(){return(e._sqlite3_step=e.asm.fa).apply(null,arguments)};e._sqlite3_column_count=function(){return(e._sqlite3_column_count=e.asm.ga).apply(null,arguments)};e._sqlite3_data_count=function(){return(e._sqlite3_data_count=e.asm.ha).apply(null,arguments)};e._sqlite3_column_blob=function(){return(e._sqlite3_column_blob=e.asm.ia).apply(null,arguments)};e._sqlite3_column_bytes=function(){return(e._sqlite3_column_bytes=e.asm.ja).apply(null,arguments)};
+e._sqlite3_column_double=function(){return(e._sqlite3_column_double=e.asm.ka).apply(null,arguments)};e._sqlite3_column_text=function(){return(e._sqlite3_column_text=e.asm.la).apply(null,arguments)};e._sqlite3_column_type=function(){return(e._sqlite3_column_type=e.asm.ma).apply(null,arguments)};e._sqlite3_column_name=function(){return(e._sqlite3_column_name=e.asm.na).apply(null,arguments)};e._sqlite3_bind_blob=function(){return(e._sqlite3_bind_blob=e.asm.oa).apply(null,arguments)};
+e._sqlite3_bind_double=function(){return(e._sqlite3_bind_double=e.asm.pa).apply(null,arguments)};e._sqlite3_bind_int=function(){return(e._sqlite3_bind_int=e.asm.qa).apply(null,arguments)};e._sqlite3_bind_text=function(){return(e._sqlite3_bind_text=e.asm.ra).apply(null,arguments)};e._sqlite3_bind_parameter_index=function(){return(e._sqlite3_bind_parameter_index=e.asm.sa).apply(null,arguments)};e._sqlite3_sql=function(){return(e._sqlite3_sql=e.asm.ta).apply(null,arguments)};
+e._sqlite3_normalized_sql=function(){return(e._sqlite3_normalized_sql=e.asm.ua).apply(null,arguments)};e._sqlite3_errmsg=function(){return(e._sqlite3_errmsg=e.asm.va).apply(null,arguments)};e._sqlite3_exec=function(){return(e._sqlite3_exec=e.asm.wa).apply(null,arguments)};e._sqlite3_prepare_v2=function(){return(e._sqlite3_prepare_v2=e.asm.xa).apply(null,arguments)};e._sqlite3_changes=function(){return(e._sqlite3_changes=e.asm.ya).apply(null,arguments)};
+e._sqlite3_close_v2=function(){return(e._sqlite3_close_v2=e.asm.za).apply(null,arguments)};e._sqlite3_create_function_v2=function(){return(e._sqlite3_create_function_v2=e.asm.Aa).apply(null,arguments)};e._sqlite3_open=function(){return(e._sqlite3_open=e.asm.Ba).apply(null,arguments)};var ca=e._malloc=function(){return(ca=e._malloc=e.asm.Ca).apply(null,arguments)},oa=e._free=function(){return(oa=e._free=e.asm.Da).apply(null,arguments)};
+e._RegisterExtensionFunctions=function(){return(e._RegisterExtensionFunctions=e.asm.Ea).apply(null,arguments)};
+var ub=e.__get_tzname=function(){return(ub=e.__get_tzname=e.asm.Fa).apply(null,arguments)},tb=e.__get_daylight=function(){return(tb=e.__get_daylight=e.asm.Ga).apply(null,arguments)},pb=e.__get_timezone=function(){return(pb=e.__get_timezone=e.asm.Ha).apply(null,arguments)},pa=e.stackSave=function(){return(pa=e.stackSave=e.asm.Ia).apply(null,arguments)},ra=e.stackRestore=function(){return(ra=e.stackRestore=e.asm.Ja).apply(null,arguments)},y=e.stackAlloc=function(){return(y=e.stackAlloc=e.asm.Ka).apply(null,
+arguments)},cd=e._memalign=function(){return(cd=e._memalign=e.asm.La).apply(null,arguments)};e.cwrap=function(a,b,c,d){c=c||[];var f=c.every(function(g){return"number"===g});return"string"!==b&&f&&!d?Qa(a):function(){return Ra(a,b,c,arguments)}};e.UTF8ToString=A;e.stackSave=pa;e.stackRestore=ra;e.stackAlloc=y;var fd;fb=function gd(){fd||hd();fd||(fb=gd)};
+function hd(){function a(){if(!fd&&(fd=!0,e.calledRun=!0,!Pa)){e.noFSInit||Qc||(Qc=!0,Pc(),e.stdin=e.stdin,e.stdout=e.stdout,e.stderr=e.stderr,e.stdin?Rc("stdin",e.stdin):dc("/dev/tty","/dev/stdin"),e.stdout?Rc("stdout",null,e.stdout):dc("/dev/tty","/dev/stdout"),e.stderr?Rc("stderr",null,e.stderr):dc("/dev/tty1","/dev/stderr"),v("/dev/stdin",0),v("/dev/stdout",1),v("/dev/stderr",1));lb($a);Ob=!1;lb(ab);if(e.onRuntimeInitialized)e.onRuntimeInitialized();if(e.postRun)for("function"==typeof e.postRun&&
+(e.postRun=[e.postRun]);e.postRun.length;){var b=e.postRun.shift();bb.unshift(b)}lb(bb)}}if(!(0<db)){if(e.preRun)for("function"==typeof e.preRun&&(e.preRun=[e.preRun]);e.preRun.length;)cb();lb(Za);0<db||(e.setStatus?(e.setStatus("Running..."),setTimeout(function(){setTimeout(function(){e.setStatus("")},1);a()},1)):a())}}e.run=hd;if(e.preInit)for("function"==typeof e.preInit&&(e.preInit=[e.preInit]);0<e.preInit.length;)e.preInit.pop()();noExitRuntime=!0;hd();
+
+
+ // The shell-pre.js and emcc-generated code goes above
+ return Module;
+ }); // The end of the promise being returned
+
+ return initSqlJsPromise;
+} // The end of our initSqlJs function
+
+// This bit below is copied almost exactly from what you get when you use the MODULARIZE=1 flag with emcc
+// However, we don't want to use the emcc modularization. See shell-pre.js
+if (typeof exports === 'object' && typeof module === 'object'){
+ module.exports = initSqlJs;
+ // This will allow the module to be used in ES6 or CommonJS
+ module.exports.default = initSqlJs;
+}
+else if (typeof define === 'function' && define['amd']) {
+ define([], function() { return initSqlJs; });
+}
+else if (typeof exports === 'object'){
+ exports["Module"] = initSqlJs;
+}
diff --git a/themes/new_theme/static/js/sql-wasm.wasm b/themes/new_theme/static/js/sql-wasm.wasm
new file mode 100644
index 0000000..7e9ee94
--- /dev/null
+++ b/themes/new_theme/static/js/sql-wasm.wasm
Binary files differ
diff --git a/themes/new_theme/static/slide/css/theme/beige.css b/themes/new_theme/static/slide/css/theme/beige.css
index be18733..7c2d60a 100644
--- a/themes/new_theme/static/slide/css/theme/beige.css
+++ b/themes/new_theme/static/slide/css/theme/beige.css
@@ -4,7 +4,7 @@
* Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
*/
@import url(../../lib/font/league-gothic/league-gothic.css);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
/*********************************************
* GLOBAL STYLES
*********************************************/
diff --git a/themes/new_theme/static/slide/css/theme/blood.css b/themes/new_theme/static/slide/css/theme/blood.css
index e035ab6..5545466 100644
--- a/themes/new_theme/static/slide/css/theme/blood.css
+++ b/themes/new_theme/static/slide/css/theme/blood.css
@@ -9,7 +9,7 @@
* For other themes, change $codeBackground accordingly.
*
*/
-@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Ubuntu:300,700,300italic,700italic);
/*********************************************
* GLOBAL STYLES
*********************************************/
diff --git a/themes/new_theme/static/slide/css/theme/league.css b/themes/new_theme/static/slide/css/theme/league.css
index fa9f53c..ab5156c 100644
--- a/themes/new_theme/static/slide/css/theme/league.css
+++ b/themes/new_theme/static/slide/css/theme/league.css
@@ -6,7 +6,7 @@
* Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
*/
@import url(../../lib/font/league-gothic/league-gothic.css);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
/*********************************************
* GLOBAL STYLES
*********************************************/
diff --git a/themes/new_theme/static/slide/css/theme/moon.css b/themes/new_theme/static/slide/css/theme/moon.css
index b119576..c9c7ba5 100644
--- a/themes/new_theme/static/slide/css/theme/moon.css
+++ b/themes/new_theme/static/slide/css/theme/moon.css
@@ -3,7 +3,7 @@
* Author: Achim Staebler
*/
@import url(../../lib/font/league-gothic/league-gothic.css);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
/**
* Solarized colors by Ethan Schoonover
*/
diff --git a/themes/new_theme/static/slide/css/theme/night.css b/themes/new_theme/static/slide/css/theme/night.css
index 3d0e3c5..2195d03 100644
--- a/themes/new_theme/static/slide/css/theme/night.css
+++ b/themes/new_theme/static/slide/css/theme/night.css
@@ -3,8 +3,8 @@
*
* Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
*/
-@import url(https://fonts.googleapis.com/css?family=Montserrat:700);
-@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Montserrat:700);
+@import url(https://fonts.bunny.net/css?family=Open+Sans:400,700,400italic,700italic);
/*********************************************
* GLOBAL STYLES
*********************************************/
diff --git a/themes/new_theme/static/slide/css/theme/simple.css b/themes/new_theme/static/slide/css/theme/simple.css
index 20d919d..f84e609 100644
--- a/themes/new_theme/static/slide/css/theme/simple.css
+++ b/themes/new_theme/static/slide/css/theme/simple.css
@@ -5,8 +5,8 @@
* This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed.
* reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
*/
-@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=News+Cycle:400,700);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
/*********************************************
* GLOBAL STYLES
*********************************************/
diff --git a/themes/new_theme/static/slide/css/theme/sky.css b/themes/new_theme/static/slide/css/theme/sky.css
index e762a50..d463791 100644
--- a/themes/new_theme/static/slide/css/theme/sky.css
+++ b/themes/new_theme/static/slide/css/theme/sky.css
@@ -3,8 +3,8 @@
*
* Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
*/
-@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic);
-@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700);
+@import url(https://fonts.bunny.net/css?family=Quicksand:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Open+Sans:400italic,700italic,400,700);
.reveal a {
line-height: 1.3em; }
diff --git a/themes/new_theme/static/slide/css/theme/solarized.css b/themes/new_theme/static/slide/css/theme/solarized.css
index bf2f651..d5dbeff 100644
--- a/themes/new_theme/static/slide/css/theme/solarized.css
+++ b/themes/new_theme/static/slide/css/theme/solarized.css
@@ -3,7 +3,7 @@
* Author: Achim Staebler
*/
@import url(../../lib/font/league-gothic/league-gothic.css);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
/**
* Solarized colors by Ethan Schoonover
*/
diff --git a/themes/new_theme/static/slide/css/theme/source/beige.scss b/themes/new_theme/static/slide/css/theme/source/beige.scss
index 5564f53..7d50903 100644
--- a/themes/new_theme/static/slide/css/theme/source/beige.scss
+++ b/themes/new_theme/static/slide/css/theme/source/beige.scss
@@ -14,7 +14,7 @@
// Include theme-specific fonts
@import url(../../lib/font/league-gothic/league-gothic.css);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
// Override theme settings (see ../template/settings.scss)
diff --git a/themes/new_theme/static/slide/css/theme/source/blood.scss b/themes/new_theme/static/slide/css/theme/source/blood.scss
index d22b53d..9bdf8ee 100644
--- a/themes/new_theme/static/slide/css/theme/source/blood.scss
+++ b/themes/new_theme/static/slide/css/theme/source/blood.scss
@@ -17,7 +17,7 @@
// Include theme-specific fonts
-@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Ubuntu:300,700,300italic,700italic);
// Colors used in the theme
$blood: #a23;
diff --git a/themes/new_theme/static/slide/css/theme/source/league.scss b/themes/new_theme/static/slide/css/theme/source/league.scss
index 46ea04a..09fc446 100644
--- a/themes/new_theme/static/slide/css/theme/source/league.scss
+++ b/themes/new_theme/static/slide/css/theme/source/league.scss
@@ -16,7 +16,7 @@
// Include theme-specific fonts
@import url(../../lib/font/league-gothic/league-gothic.css);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
// Override theme settings (see ../template/settings.scss)
$headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2);
diff --git a/themes/new_theme/static/slide/css/theme/source/moon.scss b/themes/new_theme/static/slide/css/theme/source/moon.scss
index e47e5b5..81f99e8 100644
--- a/themes/new_theme/static/slide/css/theme/source/moon.scss
+++ b/themes/new_theme/static/slide/css/theme/source/moon.scss
@@ -13,7 +13,7 @@
// Include theme-specific fonts
@import url(../../lib/font/league-gothic/league-gothic.css);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
/**
* Solarized colors by Ethan Schoonover
diff --git a/themes/new_theme/static/slide/css/theme/source/night.scss b/themes/new_theme/static/slide/css/theme/source/night.scss
index b0cb57f..d8ae060 100644
--- a/themes/new_theme/static/slide/css/theme/source/night.scss
+++ b/themes/new_theme/static/slide/css/theme/source/night.scss
@@ -12,8 +12,8 @@
// Include theme-specific fonts
-@import url(https://fonts.googleapis.com/css?family=Montserrat:700);
-@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Montserrat:700);
+@import url(https://fonts.bunny.net/css?family=Open+Sans:400,700,400italic,700italic);
// Override theme settings (see ../template/settings.scss)
diff --git a/themes/new_theme/static/slide/css/theme/source/simple.scss b/themes/new_theme/static/slide/css/theme/source/simple.scss
index 84c7d9b..4309b98 100644
--- a/themes/new_theme/static/slide/css/theme/source/simple.scss
+++ b/themes/new_theme/static/slide/css/theme/source/simple.scss
@@ -15,8 +15,8 @@
// Include theme-specific fonts
-@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=News+Cycle:400,700);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
// Override theme settings (see ../template/settings.scss)
diff --git a/themes/new_theme/static/slide/css/theme/source/sky.scss b/themes/new_theme/static/slide/css/theme/source/sky.scss
index 3fee67c..269c501 100644
--- a/themes/new_theme/static/slide/css/theme/source/sky.scss
+++ b/themes/new_theme/static/slide/css/theme/source/sky.scss
@@ -13,8 +13,8 @@
// Include theme-specific fonts
-@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic);
-@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700);
+@import url(https://fonts.bunny.net/css?family=Quicksand:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Open+Sans:400italic,700italic,400,700);
// Override theme settings (see ../template/settings.scss)
diff --git a/themes/new_theme/static/slide/css/theme/source/solarized.scss b/themes/new_theme/static/slide/css/theme/source/solarized.scss
index 912be56..2932d98 100644
--- a/themes/new_theme/static/slide/css/theme/source/solarized.scss
+++ b/themes/new_theme/static/slide/css/theme/source/solarized.scss
@@ -13,7 +13,7 @@
// Include theme-specific fonts
@import url(../../lib/font/league-gothic/league-gothic.css);
-@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+@import url(https://fonts.bunny.net/css?family=Lato:400,700,400italic,700italic);
/**
diff --git a/themes/new_theme/theme.toml b/themes/new_theme/theme.toml
index 902f64e..1745675 100644
--- a/themes/new_theme/theme.toml
+++ b/themes/new_theme/theme.toml
@@ -1,18 +1,18 @@
name = "Mainroad"
license = "GPLv2"
-licenselink = "//github.com/vimux/mainroad/blob/master/LICENSE.md"
+licenselink = "https://github.com/vimux/mainroad/blob/master/LICENSE.md"
description = "Mainroad is a responsive, clean and content-focused Hugo theme."
-homepage = "//github.com/vimux/mainroad/"
-tags = ["blog", "responsive", "widgets", "rss", "disqus", "wordpress"]
+homepage = "https://github.com/vimux/mainroad/"
+tags = ["blog", "responsive", "customizable", "widgets", "rss", "disqus", "google analytics", "wordpress"]
features = ["blog", "responsive", "widgets", "rss", "disqus", "wordpress"]
-min_version = 0.17
+min_version = "0.48"
[author]
name = "Vimux"
- homepage = "//github.com/vimux"
+ homepage = "https://github.com/vimux"
# If porting an existing theme
[original]
name = "MH Magazine lite"
- homepage = "//wordpress.org/themes/mh-magazine-lite/"
- repo = "//themes.trac.wordpress.org/browser/mh-magazine-lite/2.5.6"
+ homepage = "https://wordpress.org/themes/mh-magazine-lite/"
+ repo = "https://themes.trac.wordpress.org/browser/mh-magazine-lite/2.5.6"