diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 76a259c..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "hugo-theme-minos"] - path = hugo-theme-minos - url = https://github.com/carsonip/hugo-theme-minos diff --git a/hugo-theme-minos b/hugo-theme-minos deleted file mode 160000 index ebac3b3..0000000 --- a/hugo-theme-minos +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ebac3b34438e13a1370890d29fce541e661819d0 diff --git a/themes/hugo-theme-minos/.gitignore b/themes/hugo-theme-minos/.gitignore new file mode 100644 index 0000000..054fb78 --- /dev/null +++ b/themes/hugo-theme-minos/.gitignore @@ -0,0 +1,3 @@ +.idea +*~ +.DS_Store diff --git a/themes/hugo-theme-minos/LICENSE.md b/themes/hugo-theme-minos/LICENSE.md new file mode 100644 index 0000000..315bcec --- /dev/null +++ b/themes/hugo-theme-minos/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2017 YOUR_NAME_HERE + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/themes/hugo-theme-minos/README.md b/themes/hugo-theme-minos/README.md new file mode 100644 index 0000000..c4565a5 --- /dev/null +++ b/themes/hugo-theme-minos/README.md @@ -0,0 +1,145 @@ +# Minos + +**_A simple and retro styled theme, concentrated more on your ideas._** + +Minos is a Hugo theme ported from Hexo theme [Minos](https://github.com/ppoffice/hexo-theme-minos). Requires Hugo v0.59+. + +## Screenshots + +![Home](https://cdn.rawgit.com/carsonip/hugo-theme-minos/cb2cdd88/images/screenshot.png) +![Article](https://cdn.rawgit.com/carsonip/hugo-theme-minos/cb2cdd88/images/article.png) +![Tag](https://cdn.rawgit.com/carsonip/hugo-theme-minos/cb2cdd88/images/tag.png) + +## Features + +* Everything in the original Mino theme, except + * Gallery (fancybox) + * Duoshuo comment + * Search box + * Hierarchical categories (since this isn't supported in Hugo) +* Smart table of contents (will highlight and expand current section in TOC) +* Disqus +* Google Analytics +* [KaTeX](https://github.com/Khan/KaTeX) +* Syntax highlighting using [highlight.js](https://github.com/isagalaev/highlight.js) + +## Installation + +To install Minos as your theme, first clone this repository in the `themes/` directory: + +``` +$ cd themes/ +$ git clone --depth 1 https://github.com/carsonip/hugo-theme-minos +``` + +Second, specify `hugo-theme-minos` as your default theme in the config.toml file. Just add the line + +``` +theme = "hugo-theme-minos" +``` + +## Options + +### Pagination +``` +paginate = 10 +``` + +### Smart TOC +``` +[params] + smartToc = true +``` + +### Post Navigation +``` +[params] + noPostNavigation = true +``` + +This option disables links to next and previous post at the bottom of posts. + +### Disqus +``` +disqusShortname = "xxxxxx" +``` + +### Google Analytics +``` +googleAnalytics = "UA-123-45" +``` + +### KaTeX +``` +[params] + katex = true +``` + +This option enables the KaTeX auto-render extension. To render block math, use `$$ ... $$`. For inline math, use `\\( ... \\)`. For more details, please refer to https://github.com/KaTeX/KaTeX/blob/v0.7.1/contrib/auto-render/auto-render.js#L73 . + +### Custom CSS +``` +[params] + customCss = ["css/foo.css"] +``` + +### Others + +For other configuration variables, visit [Hugo documentation](https://gohugo.io/overview/configuration/#configuration-variables). + +## Post Params + +### Featured Image displayed in index.html +``` ++++ +featuredImage = "img/foobar.jpg" ++++ +``` + +### Hide the post from index.html +This can be used when creating an "About me"-page. +``` ++++ +hidden = true ++++ +``` + +### Enable KaTeX for this post +Enable KaTeX for a specific post without enabling the global switch. +``` ++++ +katex = true ++++ +``` + +### Suppress date in an article +Hide the date from an article, e.g. because it's just an index: +``` ++++ +omitDate = true ++++ +``` + +## Contributing + +1. Fork it! +2. Create your feature branch: `git checkout -b my-new-feature` +3. Commit your changes: `git commit -am 'Add some feature'` +4. Push to the branch: `git push origin my-new-feature` +5. Submit a pull request :D + +## Original Author + +PPOffice + +* https://github.com/ppoffice + +## Ported by + +Carson Ip + +* https://github.com/carsonip + +## License + +Licensed under the MIT License. See the [LICENSE](https://github.com/carsonip/hugo-theme-minos/blob/master/LICENSE.md) file for more details. diff --git a/themes/hugo-theme-minos/archetypes/default.md b/themes/hugo-theme-minos/archetypes/default.md new file mode 100644 index 0000000..c204843 --- /dev/null +++ b/themes/hugo-theme-minos/archetypes/default.md @@ -0,0 +1,6 @@ ++++ +Description = "" +Tags = ["development", "golang"] +Categories = ["Development", "Golang"] +menu = "" ++++ diff --git a/themes/hugo-theme-minos/i18n/en.toml b/themes/hugo-theme-minos/i18n/en.toml new file mode 100644 index 0000000..f890265 --- /dev/null +++ b/themes/hugo-theme-minos/i18n/en.toml @@ -0,0 +1,14 @@ +[Contents] +other = "Contents" + +[Comments] +other = "Comments" + +[ReadMore] +other = "Read More" + +[Prev] +other = "Prev" + +[Next] +other = "Next" diff --git a/themes/hugo-theme-minos/i18n/it.toml b/themes/hugo-theme-minos/i18n/it.toml new file mode 100644 index 0000000..d623ca9 --- /dev/null +++ b/themes/hugo-theme-minos/i18n/it.toml @@ -0,0 +1,14 @@ +[Contents] +other = "Indice" + +[Comments] +other = "Commenti" + +[ReadMore] +other = "Continua a leggere" + +[Prev] +other = "Precedente" + +[Next] +other = "Successivo" diff --git a/themes/hugo-theme-minos/images/article.png b/themes/hugo-theme-minos/images/article.png new file mode 100644 index 0000000..6ed999d Binary files /dev/null and b/themes/hugo-theme-minos/images/article.png differ diff --git a/themes/hugo-theme-minos/images/screenshot.png b/themes/hugo-theme-minos/images/screenshot.png new file mode 100644 index 0000000..170417a Binary files /dev/null and b/themes/hugo-theme-minos/images/screenshot.png differ diff --git a/themes/hugo-theme-minos/images/tag.png b/themes/hugo-theme-minos/images/tag.png new file mode 100644 index 0000000..3951b12 Binary files /dev/null and b/themes/hugo-theme-minos/images/tag.png differ diff --git a/themes/hugo-theme-minos/images/tn.png b/themes/hugo-theme-minos/images/tn.png new file mode 100644 index 0000000..e6df085 Binary files /dev/null and b/themes/hugo-theme-minos/images/tn.png differ diff --git a/themes/hugo-theme-minos/layouts/404.html b/themes/hugo-theme-minos/layouts/404.html new file mode 100644 index 0000000..e69de29 diff --git a/themes/hugo-theme-minos/layouts/_default/list.html b/themes/hugo-theme-minos/layouts/_default/list.html new file mode 100644 index 0000000..ff4152a --- /dev/null +++ b/themes/hugo-theme-minos/layouts/_default/list.html @@ -0,0 +1,20 @@ +{{ partial "head.html" . }} + +
+ {{ partial "header.html" . }} +
+
+
+ {{ .Title }} +
+
+ {{- range .Paginator.Pages }} + {{ partial "li.html" . }} + {{- end -}} +
+ {{ partial "pagination.html" . }} +
+ {{ partial "footer.html" . }} +
+ + diff --git a/themes/hugo-theme-minos/layouts/_default/single.html b/themes/hugo-theme-minos/layouts/_default/single.html new file mode 100644 index 0000000..8dc1ad0 --- /dev/null +++ b/themes/hugo-theme-minos/layouts/_default/single.html @@ -0,0 +1,15 @@ +{{ partial "head.html" . }} + + +
+ {{ partial "header.html" . }} +
+ {{ partial "article.html" . }} + {{ if and (not .Params.nocomment) .Site.DisqusShortname }} + {{ template "_internal/disqus.html" . }} + {{ end }} +
+ {{ partial "footer.html" . }} +
+ + diff --git a/themes/hugo-theme-minos/layouts/_default/terms.html b/themes/hugo-theme-minos/layouts/_default/terms.html new file mode 100644 index 0000000..7fcae0c --- /dev/null +++ b/themes/hugo-theme-minos/layouts/_default/terms.html @@ -0,0 +1,27 @@ +{{ partial "head.html" . }} + +
+ {{ partial "header.html" . }} +
+
+
+ {{ .Title }} +
+
+ {{ $site := .Site }} + {{ $data := .Data }} +
    + {{ range $key, $value := .Data.Terms.Alphabetical }} +
  • + {{ $value.Name }}({{ $value.Count }}) +
  • + {{ end }} +
+
+ +
+
+ {{ partial "footer.html" . }} +
+ + \ No newline at end of file diff --git a/themes/hugo-theme-minos/layouts/index.html b/themes/hugo-theme-minos/layouts/index.html new file mode 100644 index 0000000..441b06b --- /dev/null +++ b/themes/hugo-theme-minos/layouts/index.html @@ -0,0 +1,77 @@ +{{ partial "head.html" . }} + + + +
+ {{ partial "header.html" . }} +
+ {{ range where .Paginator.Pages "Params.hidden" "ne" "true" }} +
+
+ + {{ if .Title }} +
+

{{ .Title }}

+
+ {{ end }} + +
+ {{ if .Params.featuredImage }} +
+ + + +
+ {{ end }} +

+ {{ .Summary }} +

+

+ {{ T "ReadMore" }} +

+
+ + {{ if .Params.tags }} + + {{ end }} +
+
+ {{ end }} + + {{ partial "pagination.html" . }} +
+ {{ partial "footer.html" . }} +
+ + diff --git a/themes/hugo-theme-minos/layouts/partials/article.html b/themes/hugo-theme-minos/layouts/partials/article.html new file mode 100644 index 0000000..d343a23 --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/article.html @@ -0,0 +1,101 @@ +
+
+ {{ if .Title }} +
+

{{ .Title }}

+
+ {{ end }} + +
+ {{ .Content }} +
+ + {{ if not .Params.notoc }} + {{ if .TableOfContents }} +
+

{{ T "Contents" }}

+ {{ .TableOfContents }} +
+ {{ end }} + {{ end }} + + {{ if .Site.Params.SmartToc }} + + + {{ end }} + + + {{ if .Params.tags }} + + {{ end }} +
+ {{ partial "nav.html" . }} +
diff --git a/themes/hugo-theme-minos/layouts/partials/footer.html b/themes/hugo-theme-minos/layouts/partials/footer.html new file mode 100644 index 0000000..427736f --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/footer.html @@ -0,0 +1,40 @@ + diff --git a/themes/hugo-theme-minos/layouts/partials/head.html b/themes/hugo-theme-minos/layouts/partials/head.html new file mode 100644 index 0000000..f3dcdfc --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/head.html @@ -0,0 +1,24 @@ + + + + {{ .Title }}{{ if ne .Title .Site.Title }} // {{ .Site.Title }}{{ end }} + + {{ partial "meta.html" . }} + {{ partial "og.html" . }} + + {{- with .OutputFormats.Get "rss" -}} + + {{- end }} + + + + + + + {{ range .Site.Params.customCss -}} + + {{- end }} + + + {{ hugo.Generator }} + diff --git a/themes/hugo-theme-minos/layouts/partials/header.html b/themes/hugo-theme-minos/layouts/partials/header.html new file mode 100644 index 0000000..31a3f03 --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/header.html @@ -0,0 +1,17 @@ + diff --git a/themes/hugo-theme-minos/layouts/partials/li.html b/themes/hugo-theme-minos/layouts/partials/li.html new file mode 100644 index 0000000..af59671 --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/li.html @@ -0,0 +1,12 @@ +
+
+
+ +

+ {{ .Title }} +

+
+
+
\ No newline at end of file diff --git a/themes/hugo-theme-minos/layouts/partials/meta.html b/themes/hugo-theme-minos/layouts/partials/meta.html new file mode 100644 index 0000000..a61298b --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/meta.html @@ -0,0 +1,8 @@ + {{- $description := or (.Description) (.Site.Params.Description) -}} + {{- $keywords := or (.Keywords) (.Site.Params.Keywords) -}} + + + + {{ with .Site.Params.Author -}}{{- end }} + {{ if $description -}} {{- end }} + {{ if $keywords -}} {{- end }} diff --git a/themes/hugo-theme-minos/layouts/partials/nav.html b/themes/hugo-theme-minos/layouts/partials/nav.html new file mode 100644 index 0000000..f42ec15 --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/nav.html @@ -0,0 +1,16 @@ +{{ if not .Site.Params.NoPostNavigation }} + +{{ end }} diff --git a/themes/hugo-theme-minos/layouts/partials/og.html b/themes/hugo-theme-minos/layouts/partials/og.html new file mode 100644 index 0000000..3f63c85 --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/og.html @@ -0,0 +1,8 @@ + + + + + + {{ if .Params.ogimage -}} + + {{- end }} diff --git a/themes/hugo-theme-minos/layouts/partials/pagination.html b/themes/hugo-theme-minos/layouts/partials/pagination.html new file mode 100644 index 0000000..481c47f --- /dev/null +++ b/themes/hugo-theme-minos/layouts/partials/pagination.html @@ -0,0 +1,19 @@ +{{ $pag := $.Paginator }} +{{ if gt $pag.TotalPages 1 }} + +{{ end }} diff --git a/themes/hugo-theme-minos/layouts/taxonomy/tag.html b/themes/hugo-theme-minos/layouts/taxonomy/tag.html new file mode 100644 index 0000000..f82ed40 --- /dev/null +++ b/themes/hugo-theme-minos/layouts/taxonomy/tag.html @@ -0,0 +1,20 @@ +{{ partial "head.html" . }} + +
+ {{ partial "header.html" . }} +
+
+
+ #{{ .Title | lower }} +
+
+ {{ range .Paginator.Pages }} + {{ partial "li.html" . }} + {{ end }} +
+ {{ partial "pagination.html" . }} +
+ {{ partial "footer.html" . }} +
+ + diff --git a/themes/hugo-theme-minos/static/Mac48.png b/themes/hugo-theme-minos/static/Mac48.png new file mode 100644 index 0000000..d07c73a Binary files /dev/null and b/themes/hugo-theme-minos/static/Mac48.png differ diff --git a/themes/hugo-theme-minos/static/css/fonts/FontAwesome.otf b/themes/hugo-theme-minos/static/css/fonts/FontAwesome.otf new file mode 100644 index 0000000..8b0f54e Binary files /dev/null and b/themes/hugo-theme-minos/static/css/fonts/FontAwesome.otf differ diff --git a/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.eot b/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..7c79c6a Binary files /dev/null and b/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.eot differ diff --git a/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.svg b/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..45fdf33 --- /dev/null +++ b/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.ttf b/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..e89738d Binary files /dev/null and b/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.ttf differ diff --git a/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.woff b/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..8c1748a Binary files /dev/null and b/themes/hugo-theme-minos/static/css/fonts/fontawesome-webfont.woff differ diff --git a/themes/hugo-theme-minos/static/css/style.css b/themes/hugo-theme-minos/static/css/style.css new file mode 100644 index 0000000..c6a3e96 --- /dev/null +++ b/themes/hugo-theme-minos/static/css/style.css @@ -0,0 +1,1102 @@ +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-family: inherit; + font-size: 100%; + vertical-align: baseline; +} +body { + line-height: 1; + color: #000; + background: #fff; +} +ol, +ul { + list-style: none; +} +table { + border-collapse: separate; + border-spacing: 0; + vertical-align: middle; +} +caption, +th, +td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} +a img { + border: none; +} +input, +button { + margin: 0; + padding: 0; + font: 16px 'PT Serif', 'STZhongsong', '华文中宋', 'Microsoft Yahei', serif; +} +input::-moz-focus-inner, +button::-moz-focus-inner { + border: 0; + padding: 0; +} +@font-face { + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + font-display: swap; + src: url("fonts/fontawesome-webfont.eot?v=#4.0.3"); + src: url("fonts/fontawesome-webfont.eot?#iefix&v=#4.0.3") format("embedded-opentype"), url("fonts/fontawesome-webfont.woff?v=#4.0.3") format("woff"), url("fonts/fontawesome-webfont.ttf?v=#4.0.3") format("truetype"), url("fonts/fontawesome-webfont.svg#fontawesomeregular?v=#4.0.3") format("svg"); +} +html, +body, +#container { + height: 100%; +} +body { + background: #fff; + font: 16px 'PT Serif', 'STZhongsong', '华文中宋', 'Microsoft Yahei', serif; + -webkit-text-size-adjust: 100%; +} +.outer { + max-width: 800px; + margin: 0 auto; +} +.outer:before, +.outer:after { + content: ""; + display: table; +} +.outer:after { + clear: both; +} +@media screen and (max-width: 839px) { + .outer { + padding: 0 20px; + } +} +.left, +.alignleft { + float: left; +} +.right, +.alignright { + float: right; +} +.clear { + clear: both; +} +#container { + position: relative; +} +.logo { + width: 94px; + height: 57px; + background-image: url("images/logo.png"); + -webkit-background-size: 74px 28px; + -moz-background-size: 74px 28px; + background-size: 74px 28px; + background-position: left center; + background-repeat: no-repeat; +} +.logo-text { + width: auto; + color: #000; + font-size: 24px; + font-weight: 700; + line-height: 57px; + margin-right: 25px; + text-decoration: none; + background-image: none; +} +.article-meta a, +a.article-title, +.article-entry a, +.article-more-link a, +#comments a, +.archive-year-wrap a, +.archive-category-wrap a, +.archive-tag-wrap a, +.archive-article-title, +#page-nav a, +#footer a, +.article-entry .gist .gist-file .gist-meta a, +.layout-wrap-inner .category-list a, +.tag-cloud a { + color: #111; + text-decoration: none; + border-bottom: 1px dotted transparent; +} +.article-meta a:hover, +a.article-title:hover, +.article-entry a:hover, +.article-more-link a:hover, +#comments a:hover, +.archive-year-wrap a:hover, +.archive-category-wrap a:hover, +.archive-tag-wrap a:hover, +.archive-article-title:hover, +#page-nav a:hover, +#footer a:hover, +.article-entry .gist .gist-file .gist-meta a:hover, +.layout-wrap-inner .category-list a:hover, +.tag-cloud a:hover { + border-bottom-color: #000; +} +.article-entry a { + border-bottom: 1px dotted #000; +} +.article-entry h1 { + font-size: 2em; +} +.article-entry h2 { + font-size: 1.5em; +} +.article-entry h3 { + font-size: 1.3em; +} +.article-entry h4 { + font-size: 1.2em; +} +.article-entry h5 { + font-size: 1em; +} +.article-entry h6 { + font-size: 1em; + color: #939393; +} +.article-entry hr { + border: 1px dashed #ddd; +} +.article-entry strong { + font-weight: bold; +} +.article-entry em, +.article-entry cite { + font-style: italic; +} +.article-entry sup, +.article-entry sub { + font-size: 0.75em; + line-height: 0; + position: relative; + vertical-align: baseline; +} +.article-entry sup { + top: -0.5em; +} +.article-entry sub { + bottom: -0.2em; +} +.article-entry small { + font-size: 0.85em; +} +.article-entry acronym, +.article-entry abbr { + border-bottom: 1px dotted; +} +.article-entry ul, +.article-entry ol, +.article-entry dl { + margin: 0 25px; + line-height: 1.4em; +} +.article-entry ul ul, +.article-entry ol ul, +.article-entry ul ol, +.article-entry ol ol { + margin-top: 0; + margin-bottom: 0; +} +.article-entry ul { + list-style: disc; +} +.article-entry ol { + list-style: decimal; +} +.article-entry dt { + font-weight: bold; +} +#header { + font-size: 14px; + position: relative; + border-bottom: 1px solid #ddd; +} +#header.mobile-on #main-nav, +#header.mobile-on #sub-nav { + display: block; +} +#header-outer { + height: 100%; + position: relative; +} +#header-inner { + position: relative; + overflow: hidden; +} +#main-nav { + float: left; + margin-left: -15px; +} +.main-nav-link, +#main-nav-toggle, +.search-form-submit { + float: left; + color: #000; + text-decoration: none; + -webkit-transition: opacity 0.2s; + -moz-transition: opacity 0.2s; + -ms-transition: opacity 0.2s; + transition: opacity 0.2s; + display: block; + padding: 20px 15px; +} +.main-nav-link { + font-weight: 600; +} +@media screen and (max-width: 839px) { + .main-nav-link { + float: none; + text-align: center; + } +} +#main-nav-toggle { + display: none; + font-size: 16px; + margin-left: -15px; + font-family: FontAwesome; +} +#main-nav-toggle:before { + content: "\f0c9"; +} +@media screen and (max-width: 839px) { + #main-nav-toggle { + display: block; + } +} +#logo { + float: left; +} +@media screen and (max-width: 839px) { + #logo { + float: none; + margin: 0 auto; + display: block; + background-position: center; + } +} +#sub-nav { + float: right; +} +@media screen and (max-width: 839px) { + #main-nav, + #sub-nav { + display: none; + float: none; + } +} +#search-form-wrap { + top: 15px; + padding: 20px 15px; +} +@media screen and (max-width: 839px) { + #search-form-wrap { + text-align: center; + } +} +.search-form:before, +.search-form:after { + content: ""; + display: table; +} +.search-form:after { + clear: both; +} +@media screen and (max-width: 839px) { + .search-form { + display: inline-block; + } +} +.search-form-input { + width: 150px; + border: none; + float: left; + font-size: 14px; + background: none; + color: #111; + outline: none; +} +.search-form-input::-webkit-search-results-decoration, +.search-form-input::-webkit-search-cancel-button { + -webkit-appearance: none; +} +.search-form-submit { + float: left; + padding: 0; + font-family: FontAwesome; + border: none; + background: none; + cursor: pointer; +} +.article { + margin: 50px 0; + border-bottom: 1px solid #ddd; +} +.article-inner { + margin-bottom: 15px; + overflow: hidden; +} +.article-meta:before, +.article-meta:after { + content: ""; + display: table; +} +.article-meta:after { + clear: both; +} +.article-meta a { + color: #939393; +} +.article-date { + float: left; +} +.article-category { + float: left; + margin-left: 8px; + color: #939393; +} +.article-category:before { + content: "\2022"; +} +.article-category span { + margin-left: 8px; +} +.article-category-link { + margin-left: 8px; +} +.article-comment-link-wrap { + float: left; + margin-left: 8px; + color: #939393; +} +.article-comment-link-wrap:before { + content: "\2022"; +} +.article-comment-link { + margin-left: 8px; +} +.article-header { + margin-bottom: 10px; +} +.article-title { + font-size: 2em; + font-weight: 700; + line-height: 1em; +} +.article-entry { + color: #111; + padding: 0; +} +.article-entry:before, +.article-entry:after { + content: ""; + display: table; +} +.article-entry:after { + clear: both; +} +.article-entry p, +.article-entry table { + line-height: 1.4em; + margin: 1.4em 0; +} +.article-entry h1, +.article-entry h2, +.article-entry h3, +.article-entry h4, +.article-entry h5, +.article-entry h6 { + font-weight: 600; + line-height: 1.4em; + margin: 1em 0; +} +.article-entry ul, +.article-entry ol, +.article-entry dl { + margin-top: 1.4em; + margin-bottom: 1.4em; +} +.article-entry img, +.article-entry video { + max-width: 100%; + height: auto; + display: block; + margin: auto; +} +.article-entry iframe { + border: none; +} +.article-entry table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; +} +.article-entry th { + font-weight: 600; + border-bottom: 3px solid #ddd; + padding-bottom: 0.5em; +} +.article-entry td { + border-bottom: 1px solid #ddd; + padding: 10px 0; +} +.article-entry blockquote { + font-family: 'PT Serif', 'STZhongsong', '华文中宋', 'Microsoft Yahei', serif; + font-size: 1.4em; + margin: 1.4em 20px; + text-align: center; +} +.article-entry blockquote footer { + font-size: 16px; + margin: 1.4em 0; + font-family: font-sans; +} +.article-entry blockquote footer cite:before { + content: "—"; + padding: 0 0.5em; +} +.article-entry .pullquote { + text-align: left; + width: 45%; + margin: 0; +} +.article-entry .pullquote.left { + margin-left: 0.5em; + margin-right: 1em; +} +.article-entry .pullquote.right { + margin-right: 0.5em; + margin-left: 1em; +} +.article-entry .caption { + color: #939393; + display: block; + font-size: 0.9em; + margin-top: 0.5em; + position: relative; + text-align: center; +} +.article-entry .video-container { + position: relative; + padding-top: 56.25%; + height: 0; + overflow: hidden; +} +.article-entry .video-container iframe, +.article-entry .video-container object, +.article-entry .video-container embed { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + margin-top: 0; +} +.article-more-link a { + color: #939393; + border-bottom-color: #939393; +} +.article-footer { + font-size: 0.85em; + padding: 1.4em 0; + line-height: 1.4em; + margin: 0; +} +.article-footer:before, +.article-footer:after { + content: ""; + display: table; +} +.article-footer:after { + clear: both; +} +.article-footer a { + color: #939393; + text-decoration: none; +} +.article-footer a:hover { + color: #111; +} +.article-tag-list-item { + float: left; + margin-right: 10px; +} +.article-tag-list-link:before { + content: "#"; +} +#article-nav { + position: relative; + margin: 20px 0; +} +#article-nav:before, +#article-nav:after { + content: ""; + display: table; +} +#article-nav:after { + clear: both; +} +.article-nav-link-wrap { + text-decoration: none; + text-shadow: 0 1px #fff; + color: #939393; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + text-align: center; + display: block; +} +.article-nav-link-wrap:hover { + color: #111; +} +@media screen and (min-width: 840px) { + .article-nav-link-wrap { + width: 50%; + margin-top: 0; + margin-top: 50px; + } +} +#article-nav-newer { + float: left; + text-align: left; +} +#article-nav-older { + float: right; + text-align: right; +} +.article-nav-caption { + text-transform: uppercase; + letter-spacing: 2px; + color: #ddd; + line-height: 1em; + font-weight: 600; +} +#article-nav-newer .article-nav-caption { + margin-right: -2px; +} +.article-nav-title { + font-size: 0.85em; + line-height: 1.4em; + margin-top: 0.5em; +} +.article-gallery { + background: #000; + position: relative; +} +.article-gallery-photos { + position: relative; + overflow: hidden; +} +.article-gallery-img { + display: none; + max-width: 100%; +} +.article-gallery-img:first-child { + display: block; +} +.article-gallery-img.loaded { + position: absolute; + display: block; +} +.article-gallery-img img { + display: block; + max-width: 100%; + margin: 0 auto; +} +.article-toc { + display: none; + position: fixed; + left: 50%; + top: 110px; + font-size: 0.9em; + width: 260px; + margin-left: 400px; + padding-left: 20px; + overflow-y: auto; + line-height: 1.4em; + max-height: 85%; +} +.article-toc h3 { + font-weight: bold; + margin-left: 20px; +} +.article-toc li { + list-style: none; + margin-left: 20px; + margin-top: 2px; +} +.article-toc li a { + color: #000; + text-decoration: none; +} +.article-toc li a.active { + font-weight: bold; +} +@media screen and (min-width: 1400px) { + .article-toc { + display: block; + } +} +#comments { + margin: 50px 0; +} +.archives-wrap { + margin: 50px 0; +} +.archives:before, +.archives:after { + content: ""; + display: table; +} +.archives:after { + clear: both; +} +.archive-year-wrap, +.archive-category-wrap, +.archive-tag-wrap { + font-size: 1.4em; + margin-bottom: 1em; +} +.archives { + margin-left: 5px; + border-left: 1px solid #ddd; +} +.archive-article-inner { + padding: 10px 10px 10px 12px; + margin: 15px 0 15px -2px; + border-left: 3px solid transparent; +} +.archive-article-inner:hover { + border-left-color: #000; +} +.archive-article-footer { + margin-top: 1em; +} +.archive-article-date { + color: #939393; + text-decoration: none; + font-size: 0.85em; + line-height: 1em; + margin-bottom: 0.5em; + display: block; +} +#page-nav { + margin: 50px auto; + text-align: center; + overflow: hidden; +} +#page-nav:before, +#page-nav:after { + content: ""; + display: table; +} +#page-nav:after { + clear: both; +} +#page-nav a, +#page-nav span { + width: 36px; + height: 36px; + margin: 0 5px; + line-height: 36px; + text-align: center; +} +#page-nav a.prev, +#page-nav a.next { + margin: 0; + width: auto; +} +#page-nav .prev { + float: left; +} +#page-nav .next { + float: right; +} +#page-nav .page-number { + display: inline-block; +} +#page-nav .current { + color: #fff; + border-radius: 18px; + background-color: #000; +} +#page-nav .space { + color: #ddd; +} +#footer { + padding: 50px 0; + text-align: center; +} +#footer a { + font-weight: 600; +} +#footer-info { + line-height: 1.4em; + font-size: 0.85em; +} +.article-entry pre, +.article-entry .highlight { + margin: 0; + font-size: 14px; + background: #23241f; + padding: 15px 0; + overflow: auto; + color: #fff; + line-height: 22.4px; +} +.article-entry .highlight .gutter pre, +.article-entry .gist .gist-file .gist-data .line-numbers { + color: #666; + font-size: 0.85em; +} +.article-entry pre, +.article-entry code { + font-family: "Source Code Pro", Consolas, Monaco, Menlo, Consolas, monospace, '华文中宋'; +} +.article-entry code { + background: #f2f2f2; + padding: 0 0.3em; +} +.article-entry pre { + padding: 20px; +} +.article-entry pre code { + background: none; + text-shadow: none; + padding: 0; +} +.article-entry pre .highlight { + padding: 0; +} +.article-entry .highlight pre { + border: none; + margin: 0; + padding: 0 20px; +} +.article-entry .highlight table { + margin: 0; + width: auto; +} +.article-entry .highlight td { + border: none; + padding: 0; +} +.article-entry .highlight figcaption { + font-size: 0.85em; + color: highlight-comment; + line-height: 1em; + margin-bottom: 1em; +} +.article-entry .highlight figcaption:before, +.article-entry .highlight figcaption:after { + content: ""; + display: table; +} +.article-entry .highlight figcaption:after { + clear: both; +} +.article-entry .highlight figcaption a { + float: right; +} +.article-entry .highlight .gutter pre { + text-align: right; +} +.article-entry .highlight .line { + height: 22.4px; +} +.article-entry .gist { + margin: 0; + padding: 15px 0; +} +.article-entry .gist .gist-file { + border: none; + font-family: "Source Code Pro", Consolas, Monaco, Menlo, Consolas, monospace, '华文中宋'; + margin: 0; +} +.article-entry .gist .gist-file .gist-data { + background: none; + border: none; +} +.article-entry .gist .gist-file .gist-data .line-numbers { + background: none; + border: none; + padding: 0 20px 0 0; +} +.article-entry .gist .gist-file .gist-data .line-data { + padding: 0 !important; +} +.article-entry .gist .gist-file .highlight { + margin: 0; + padding: 0; + border: none; +} +.article-entry .gist .gist-file .gist-meta { + background: highlight-background; + color: highlight-comment; + font: 0.85em font-sans; + text-shadow: 0 0; + padding: 0; + margin-top: 1em; +} +.article-entry .gist .gist-file .gist-meta a { + font-weight: normal; +} +.feature-image a { + text-decoration: none; + border:none; +} +.feature-image { + margin-top: 1.5em +} +.article-entry .gist .gist-file .gist-meta a:hover { + text-decoration: underline; +} +pre .tag, +pre .css .rules, +pre .css .value, +pre .css .function, +pre .preprocessor, +pre .pragma { + color: #f8f8f2; +} +pre .strongemphasis, +pre .strong, +pre .emphasis { + color: #a8a8a2; +} +pre .bullet, +pre .blockquote, +pre .horizontal_rule, +pre .number, +pre .regexp, +pre .alias .keyword, +pre .literal, +pre .hexcolor { + color: #ae81ff; +} +pre .tag .value, +pre .code, +pre .title, +pre .css .class, +pre .class .title:last-child { + color: #a6e22e; +} +pre .link_url { + font-size: 80%; +} +pre .strong, +pre .strongemphasis { + font-weight: bold; +} +pre .emphasis, +pre .strongemphasis, +pre .class .title:last-child { + font-style: italic; +} +pre .keyword, +pre .function, +pre .change, +pre .winutils, +pre .flow, +pre .nginx .title, +pre .tex .special, +pre .header, +pre .attribute, +pre .symbol, +pre .symbol .string, +pre .tag .title, +pre .value, +pre .alias .keyword:first-child, +pre .css .tag, +pre .css .unit, +pre .css .important { + color: #f92672; +} +pre .function .keyword, +pre .class .keyword:first-child, +pre .constant, +pre .css .attribute { + color: #66d9ef; +} +pre .variable, +pre .params, +pre .class .title { + color: #f8f8f2; +} +pre .string, +pre .css .id, +pre .subst, +pre .type, +pre .ruby .class .parent, +pre .built_in, +pre .django .template_tag, +pre .django .variable, +pre .smalltalk .class, +pre .django .filter .argument, +pre .smalltalk .localvars, +pre .smalltalk .array, +pre .attr_selector, +pre .pseudo, +pre .addition, +pre .stream, +pre .envvar, +pre .apache .tag, +pre .apache .cbracket, +pre .tex .command, +pre .prompt, +pre .link_label, +pre .link_url { + color: #e6db74; +} +pre .comment, +pre .javadoc, +pre .annotation, +pre .decorator, +pre .template_comment, +pre .pi, +pre .doctype, +pre .deletion, +pre .shebang, +pre .apache .sqbracket, +pre .tex .formula { + color: #75715e; +} +pre .coffeescript .javascript, +pre .javascript .xml, +pre .tex .formula, +pre .xml .javascript, +pre .xml .vbscript, +pre .xml .css, +pre .xml .cdata, +pre .xml .php, +pre .php .xml { + opacity: 0.5; +} +.layout-wrap { + margin: 50px 0; +} +.layout-title { + font-size: 1.4em; + margin-bottom: 1em; +} +.layout-wrap-inner .category-list, +.layout-wrap-inner .category-list-child { + line-height: 1.8em; +} +.layout-wrap-inner .category-list:before, +.layout-wrap-inner .category-list-child:before, +.layout-wrap-inner .category-list:after, +.layout-wrap-inner .category-list-child:after { + content: ""; + display: table; +} +.layout-wrap-inner .category-list:after, +.layout-wrap-inner .category-list-child:after { + clear: both; +} +.layout-wrap-inner .category-list-child { + margin-left: 24px; +} +.layout-wrap-inner li:before { + content: '>'; + float: left; + padding: 0 16px 0 0; +} +.layout-wrap-inner .category-list-count { + margin-left: 8px; + color: #939393; +} +.layout-wrap-inner .category-list-count:before { + content: '('; +} +.layout-wrap-inner .category-list-count:after { + content: ')'; +} +.tag-cloud a { + margin-right: 8px; +} +.tag-cloud a:before { + content: '#'; +} +.fancybox-skin { + padding: 0 !important; + border-radius: 0; + font-family: 'PT Serif', 'STZhongsong', '华文中宋', 'Microsoft Yahei', serif; +} +.fancybox-skin .fancybox-title .child { + background: none; + font-weight: 400; + font-size: 16px; + font-family: 'PT Serif', 'STZhongsong', '华文中宋', 'Microsoft Yahei', serif; + text-shadow: 1px 3px 3px rgba(0,0,0,0.5); +} diff --git a/themes/hugo-theme-minos/static/home.png b/themes/hugo-theme-minos/static/home.png new file mode 100644 index 0000000..43fda6d Binary files /dev/null and b/themes/hugo-theme-minos/static/home.png differ diff --git a/themes/hugo-theme-minos/static/js/.gitkeep b/themes/hugo-theme-minos/static/js/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/themes/hugo-theme-minos/static/js/as-dithered-image.js b/themes/hugo-theme-minos/static/js/as-dithered-image.js new file mode 100644 index 0000000..aa7b85d --- /dev/null +++ b/themes/hugo-theme-minos/static/js/as-dithered-image.js @@ -0,0 +1,310 @@ +const DITHERED_IMAGE_STYLE = ` +.ditheredImageStyle { + width: 100%; + height: 100%; + padding: 0; + margin: 0; + image-rendering: crisp-edges; +} +` + +const workerPath = document.currentScript.src.replace("as-dithered-image.js", "ditherworker.js") + +class ASDitheredImage extends HTMLElement { + constructor() { + super() + + this.original_image_ = undefined + this.force_refresh_ = false + this.crunchFactor_ = this.getAutoCrunchFactor() + this.canvas_ = undefined + this.context_ = undefined + this.image_loading_ = false + this.ignore_next_resize_ = false + this.worker_ = new Worker(workerPath) + this.cutoff_ = 0.5 + this.darkrgba_ = [0, 0, 0, 255] + this.lightrgba_ = [255, 255, 255, 255] + + this.worker_.onmessage = ((e) => { + const imageData = e.data.imageData + this.context_.putImageData(imageData, 0, 0) + }).bind(this) + + this.resizing_timeout_ = undefined + + this.last_draw_state_ = { width: 0, height: 0, crunchFactor: 0, imageSrc: "" } + } + + connectedCallback() { + if (!this.isConnected) { + return + } + + const shadowDOM = this.attachShadow({ mode: "open" }) + + const style = document.createElement("style") + style.innerHTML = DITHERED_IMAGE_STYLE + shadowDOM.appendChild(style) + + this.canvas_ = document.createElement("canvas") + this.canvas_.setAttribute("role", "image") + this.canvas_.setAttribute("aria-label", this.getAttribute("alt")) + this.canvas_.classList.add("ditheredImageStyle") + shadowDOM.appendChild(this.canvas_) + + this.context_ = this.canvas_.getContext("2d", { willReadFrequently: true }) + + const resizeObserver = new ResizeObserver(((entries) => { + // browsers generated lots of resize events but we don't want to start refreshing until + // the user has stopped resizing the page + + if (entries.length > 0) { + if (entries[0].contentBoxSize) { + + if (this.ignore_next_resize_ == true) { + this.ignore_next_resize_ = false + return + } + if (this.resizing_timeout_ != undefined) { + clearTimeout(this.resizing_timeout_) + } + this.resizing_timeout_ = setTimeout((() => { + this.resizing_timeout_ = undefined + this.force_refresh_ = true + this.requestUpdate() + }).bind(this), 200) + } + + } + }).bind(this)) + + resizeObserver.observe(this.canvas_) + + // since we avoid drawing the image if the element of far offscreen we need to use + // an IntersectionObserver to notify use when the element is likely to be displayed + const intersectionObserver = new IntersectionObserver(((intersections) => { + if (intersections.length > 0) { + if (intersections[0].isIntersecting) { + this.force_refresh_ = true + this.requestUpdate() + } + } + }).bind(this), { root: null, rootMargin: "1000px", threshold: [0] }) + intersectionObserver.observe(this) + + this.force_refresh_ = true + this.requestUpdate() + } + + static get observedAttributes() { return ["src", "crunch", "alt", "cutoff", "darkrgba", "lightrgba"] } + + + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue === newValue) return + + if ((name === "src")) { + this.force_refresh_ = true + this.original_image_ = undefined + this.requestUpdate() + } else if (name === "crunch") { + if (newValue === "auto") { + this.crunchFactor_ = this.getAutoCrunchFactor() + } else if (newValue === "pixel") { + this.crunchFactor_ = 1.0 / this.getDevicePixelRatio() + } else { + this.crunchFactor_ = parseInt(newValue, 10) + if (isNaN(this.crunchFactor_)) { + this.crunchFactor_ = this.getAutoCrunchFactor() + } + } + this.force_refresh_ = true + this.requestUpdate() + } else if (name === "alt") { + this.altText = newValue; + if (this.canvas != undefined) { + let currentAltText = this.canvas.getAttribute("aria-label") + if (currentAltText != newValue) { + this.canvas.setAttribute("aria-label", newValue) + } + } + } else if (name === "cutoff") { + this.cutoff_ = parseFloat(newValue) + if (isNaN(this.cutoff_)) { + this.cutoff_ = 0.5 + } + this.cutoff_ = Math.min(1.0, Math.max(0.0, this.cutoff_)) + this.force_refresh_ = true + this.requestUpdate() + } else if (name === "darkrgba") { + // must be in the form "rgba(10, 10, 10, 255)" + this.darkrgba_ = this.parseRGBA(newValue) + this.force_refresh_ = true + this.requestUpdate() + } + else if (name === "lightrgba") { + this.lightrgba_ = this.parseRGBA(newValue) + this.force_refresh_ = true + this.requestUpdate() + } + + } + + // The crunch factor defaults 1 css pixel to 1 dither pixel which I think looks best when the device pixel ratio is 1 or 2 + // If the pixel ratio is 3 or above (like on my iPhone) then even css pixels are too small to make dithering + // look effective, so I double the pixels again + getAutoCrunchFactor() { + if (this.getDevicePixelRatio() < 3) { + return 1 + } else { + return 2 + } + } + + getDevicePixelRatio() { + // this should always be an integer for the dithering code to work + return window.devicePixelRatio + } + + isInOrNearViewport() { + // this only handles vertical scrolling, could be extended later to handle horizontal + // but it probably doesn't matter + const margin = 1500 + const r = this.getBoundingClientRect() + + const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight) + const above = r.bottom + margin < 0 + const below = r.top - margin > viewHeight + + return (!above && !below) + } + + // all drawing is funneled through requestUpdate so that multiple calls are coalesced to prevent + // processing the image multiple times for no good reason + requestUpdate() { + + if (this.original_image_ != undefined) { + if (this.isInOrNearViewport() == false) { + return // suppress update, the intersection observer will call us back as the element scrolls into view + } + } + + window.requestAnimationFrame(((timestamp) => { + if ((this.force_refresh_ == false)) { + return + } + if (this.original_image_ == undefined) { + this.loadImage() + return + } + if (this.force_refresh_) { + this.repaintImage() + } + + }).bind(this)) + } + + loadImage() { + if (this.image_loading_ == true) { + return + } + this.image_loading_ = true + const image = new Image() + image.src = this.getAttribute("src") + + // image.onerror is old and (literally) busted - it does not file on decode errors (ie if the src does not point to a valid image) + // The new way is promise based - possibly better + image.decode().then((() => { + this.original_image_ = image + this.ignore_next_resize_ = true + this.canvas_.style.aspectRatio = this.original_image_.width + "/" + this.original_image_.height + this.force_refresh_ = true + this.requestUpdate() + }).bind(this)) + .catch(((decodeError) => { + console.log("Error decoding image: ", decodeError) + this.original_image_ = undefined + }).bind(this)) + .finally((() => { + this.image_loading_ = false + }).bind(this)) + } + + parseRGBA(s) { + var matches = s.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*(\d+)\s*\)$/i); + if (matches) { + return [matches[1], matches[2], matches[3], matches[4]] + } + else { + return [255, 255, 255, 255] + } + } + + repaintImage() { + const rect = this.canvas_.getBoundingClientRect() + let screenPixelsToBackingStorePixels = this.getDevicePixelRatio() + let fractionalPart = screenPixelsToBackingStorePixels - Math.floor(screenPixelsToBackingStorePixels) + + // that's it! I am officially giving up on trying to account for all the weird pixelDeviceRatios that Chrome likes + // to serve up at different zoom levels. I can understand nice fractions like 2.5 but 1.110004 and 0.89233 are just stupid + // If the fractional part doesn't make sense then just ignore it. This will give incorrect results but they still look + // pretty good if you don't look too closely. + if (this.getAttribute("crunch") == "pixel") { + this.crunchFactor_ = 1.0 / this.getDevicePixelRatio() + } + + if ((1.0 / fractionalPart) > 3) { + fractionalPart = 0 + screenPixelsToBackingStorePixels = Math.round(screenPixelsToBackingStorePixels) + } + if (fractionalPart != 0) { + screenPixelsToBackingStorePixels = Math.round(screenPixelsToBackingStorePixels * Math.round(1.0 / fractionalPart)) + } + + const calculatedWidth = Math.round(rect.width * screenPixelsToBackingStorePixels) + const calculatedHeight = Math.round(rect.height * screenPixelsToBackingStorePixels) + let adjustedPixelSize = Math.round(screenPixelsToBackingStorePixels * this.crunchFactor_) + + // double check - we may have already painted this image + if ((this.last_draw_state_.width == calculatedWidth) && + (this.last_draw_state_.height == calculatedHeight) && + (this.last_draw_state_.adjustedPixelSize == adjustedPixelSize) && + (this.last_draw_state_.imageSrc == this.original_image_.currentSrc) && + (this.last_draw_state_.cutoff == this.cutoff_) && + (this.last_draw_state_.darkrgba == this.darkrgba_) && + (this.last_draw_state_.lightrgba == this.lightrgba_) + ) { + return; // nothing to do + } + + this.canvas_.width = calculatedWidth + this.canvas_.height = calculatedHeight + + this.last_draw_state_.width = this.canvas_.width + this.last_draw_state_.height = this.canvas_.height + this.last_draw_state_.adjustedPixelSize = adjustedPixelSize + this.last_draw_state_.imageSrc = this.original_image_.currentSrc + this.last_draw_state_.cutoff = this.cutoff_ + this.last_draw_state_.darkrgba = this.darkrgba_ + this.last_draw_state_.lightrgba = this.lightrgba_ + + + this.context_.imageSmoothingEnabled = true + this.context_.drawImage(this.original_image_, 0, 0, this.canvas_.width / adjustedPixelSize, this.canvas_.height / adjustedPixelSize) + const originalData = this.context_.getImageData(0, 0, this.canvas_.width / adjustedPixelSize, this.canvas_.height / adjustedPixelSize) + this.context_.clearRect(0, 0, this.canvas_.width, this.canvas_.height) + // TODO: look at transferring the data in a different datastructure to prevent copying + // unfortunately Safari has poor support for createImageBitmap - using it with ImageData doesn't work + const msg = {} + msg.imageData = originalData + msg.pixelSize = adjustedPixelSize + msg.cutoff = this.cutoff_ + msg.blackRGBA = this.darkrgba_ + msg.whiteRGBA = this.lightrgba_ + this.worker_.postMessage(msg) + + this.force_refresh_ = false + } +} + +window.customElements.define('as-dithered-image', ASDitheredImage); diff --git a/themes/hugo-theme-minos/static/js/ditherworker.js b/themes/hugo-theme-minos/static/js/ditherworker.js new file mode 100644 index 0000000..7e84f00 --- /dev/null +++ b/themes/hugo-theme-minos/static/js/ditherworker.js @@ -0,0 +1,73 @@ +onmessage = function (e) { + + const result = dither(e.data.imageData, e.data.pixelSize, e.data.cutoff, e.data.blackRGBA, e.data.whiteRGBA) + const reply = {} + reply.imageData = result + reply.pixelSize = e.data.pixelSize + reply.cutoff = e.data.cutoff + postMessage(reply) +} + +function getRGBAArrayBuffer(color) { + let buffer = new ArrayBuffer(4) + for (let i = 0; i < 4; ++i) { + buffer[i] = color[i] + } + return buffer +} + +function dither(imageData, scaleFactor, cutoff, blackRGBA, whiteRGBA) { + const blackRGBABuffer = getRGBAArrayBuffer(blackRGBA) + const whiteRGBABuffer = getRGBAArrayBuffer(whiteRGBA) + let output = new ImageData(imageData.width * scaleFactor, imageData.height * scaleFactor) + for (let i = 0; i < imageData.data.length; i += 4) { + imageData.data[i] = imageData.data[i + 1] = imageData.data[i + 2] = Math.floor(imageData.data[i] * 0.3 + imageData.data[i + 1] * 0.59 + imageData.data[i + 2] * 0.11) + } + + // most implementations I see just distribute error into the existing image, wrapping around edge pixels + // this implementation uses a sliding window of floats for more accuracy (probably not needed really) + + let slidingErrorWindow = [new Float32Array(imageData.width), new Float32Array(imageData.width), new Float32Array(imageData.width)] + const offsets = [[1, 0], [2, 0], [-1, 1], [0, 1], [1, 1], [0, 2]] + + for (let y = 0, limY = imageData.height; y < limY; ++y) { + for (let x = 0, limX = imageData.width; x < limX; ++x) { + let i = ((y * limX) + x) * 4; + let accumulatedError = Math.floor(slidingErrorWindow[0][x]) + let expectedMono = imageData.data[i] + accumulatedError + let monoValue = expectedMono + if (monoValue <= Math.floor(cutoff * 255)) { + monoValue = 0 + } else { + monoValue = 255 + } + let error = (expectedMono - monoValue) / 8.0 + for (let q = 0; q < offsets.length; ++q) { + let offsetX = offsets[q][0] + x + let offsetY = offsets[q][1] + y + if ((offsetX >= 0) && (offsetX < slidingErrorWindow[0].length)) + slidingErrorWindow[offsets[q][1]][offsetX] += error + } + + // this is stupid but we have to do the pixel scaling ourselves because safari insists on interpolating putImageData + // which gives us blurry pixels (and it doesn't support the createImageBitmap call with an ImageData instance which + // would make this easy) + let rgba = (monoValue == 0) ? blackRGBABuffer : whiteRGBABuffer + + for (let scaleY = 0; scaleY < scaleFactor; ++scaleY) { + let pixelOffset = (((y * scaleFactor + scaleY) * output.width) + (x * scaleFactor)) * 4 + for (let scaleX = 0; scaleX < scaleFactor; ++scaleX) { + output.data[pixelOffset] = rgba[0] + output.data[pixelOffset + 1] = rgba[1] + output.data[pixelOffset + 2] = rgba[2] + output.data[pixelOffset + 3] = rgba[3] + pixelOffset += 4 + } + } + } + // move the sliding window + slidingErrorWindow.push(slidingErrorWindow.shift()) + slidingErrorWindow[2].fill(0, 0, slidingErrorWindow[2].length) + } + return output +} \ No newline at end of file diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2 new file mode 100644 index 0000000..1a5bfca Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2 new file mode 100644 index 0000000..a7b49ea Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2 new file mode 100644 index 0000000..6a14f5f Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2 new file mode 100644 index 0000000..474fdb9 Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2 new file mode 100644 index 0000000..1470dde Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2 new file mode 100644 index 0000000..687594f Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2 new file mode 100644 index 0000000..6da7149 Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2 new file mode 100644 index 0000000..656fd91 Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2 new file mode 100644 index 0000000..800eb75 Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2 new file mode 100644 index 0000000..c5e4bbd Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2 new file mode 100644 index 0000000..971b07a Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2 b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2 new file mode 100644 index 0000000..c757934 Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/ptserif/fonts/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/ptserif/main.css b/themes/hugo-theme-minos/static/webfonts/ptserif/main.css new file mode 100644 index 0000000..cf31ab0 --- /dev/null +++ b/themes/hugo-theme-minos/static/webfonts/ptserif/main.css @@ -0,0 +1,108 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('PT Serif'), local('PTSerif-Regular'), url(fonts/5hX15RUpPERmeybVlLQEWBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('PT Serif'), local('PTSerif-Regular'), url(fonts/fU0HAfLiPHGlZhZpY6M7dBTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('PT Serif'), local('PTSerif-Regular'), url(fonts/CPRt--GVMETgA6YEaoGitxTbgVql8nDJpwnrE27mub0.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('PT Serif'), local('PTSerif-Regular'), url(fonts/I-OtoJZa3TeyH6D9oli3ifesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(fonts/QABk9IxT-LFTJ_dQzv7xpDTOQ_MqJVwkKsUn0wKzc2I.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(fonts/QABk9IxT-LFTJ_dQzv7xpDUj_cnvWIuuBMVgbX098Mw.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(fonts/QABk9IxT-LFTJ_dQzv7xpCYE0-AqJ3nfInTTiDXDjU4.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local('PT Serif Bold'), local('PTSerif-Bold'), url(fonts/QABk9IxT-LFTJ_dQzv7xpI4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} +/* cyrillic-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(fonts/O_WhD9hODL16N4KLHLX7xSEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; +} +/* cyrillic */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(fonts/3Nwg9VzlwLXPq3fNKwVRMCEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* latin-ext */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(fonts/b31S45a_TNgaBApZhTgE6CEAvth_LlrfE80CYdSH47w.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'PT Serif'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: local('PT Serif Italic'), local('PTSerif-Italic'), url(fonts/03aPdn7fFF3H6ngCgAlQzPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} diff --git a/themes/hugo-theme-minos/static/webfonts/source-code-pro/fonts/mrl8jkM18OlOQN8JLgasD9V_2ngZ8dMf8fLgjYEouxg.woff2 b/themes/hugo-theme-minos/static/webfonts/source-code-pro/fonts/mrl8jkM18OlOQN8JLgasD9V_2ngZ8dMf8fLgjYEouxg.woff2 new file mode 100644 index 0000000..ea28ed1 Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/source-code-pro/fonts/mrl8jkM18OlOQN8JLgasD9V_2ngZ8dMf8fLgjYEouxg.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/source-code-pro/fonts/mrl8jkM18OlOQN8JLgasDy2Q8seG17bfDXYR_jUsrzg.woff2 b/themes/hugo-theme-minos/static/webfonts/source-code-pro/fonts/mrl8jkM18OlOQN8JLgasDy2Q8seG17bfDXYR_jUsrzg.woff2 new file mode 100644 index 0000000..7e01391 Binary files /dev/null and b/themes/hugo-theme-minos/static/webfonts/source-code-pro/fonts/mrl8jkM18OlOQN8JLgasDy2Q8seG17bfDXYR_jUsrzg.woff2 differ diff --git a/themes/hugo-theme-minos/static/webfonts/source-code-pro/main.css b/themes/hugo-theme-minos/static/webfonts/source-code-pro/main.css new file mode 100644 index 0000000..169d2fc --- /dev/null +++ b/themes/hugo-theme-minos/static/webfonts/source-code-pro/main.css @@ -0,0 +1,18 @@ +/* latin-ext */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('Source Code Pro'), local('SourceCodePro-Regular'), url(fonts/mrl8jkM18OlOQN8JLgasDy2Q8seG17bfDXYR_jUsrzg.woff2) format('woff2'); + unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local('Source Code Pro'), local('SourceCodePro-Regular'), url(fonts/mrl8jkM18OlOQN8JLgasD9V_2ngZ8dMf8fLgjYEouxg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; +} diff --git a/themes/hugo-theme-minos/theme.toml b/themes/hugo-theme-minos/theme.toml new file mode 100644 index 0000000..6f22c18 --- /dev/null +++ b/themes/hugo-theme-minos/theme.toml @@ -0,0 +1,21 @@ +# theme.toml template for a Hugo theme +# See https://github.com/spf13/hugoThemes#themetoml for an example + +name = "Minos" +license = "MIT" +licenselink = "https://github.com/carsonip/hugo-theme-minos/blob/master/LICENSE.md" +description = "A simple and retro styled theme ported from Hexo" +homepage = "https://github.com/carsonip/hugo-theme-minos" +tags = ["blog", "minimal"] +features = ["blog", ""] +min_version = 0.20 + +[author] + name = "Carson Ip" + homepage = "https://github.com/carsonip" + +# If porting an existing theme +[original] + name = "Minos" + homepage = "https://github.com/ppoffice/hexo-theme-minos" + repo = "https://github.com/ppoffice/hexo-theme-minos" diff --git a/themes/hugo-tufte.7z b/themes/hugo-tufte.7z new file mode 100644 index 0000000..5b166a4 Binary files /dev/null and b/themes/hugo-tufte.7z differ