diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..fb615c8 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: ['https://www.buymeacoffee.com/jimmycai'] \ No newline at end of file diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..fcca4ea --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,31 @@ +name-template: 'v$RESOLVED_VERSION 🌈' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: '🧰 Maintenance' + label: 'chore' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + patch: + labels: + - 'patch' + default: patch +template: | + ## Changes + + $CHANGES diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..2c30bcd --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,16 @@ +name: Release Drafter + +on: + push: + # branches to consider in the event; optional, defaults to all + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 69bd657..e871020 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ## Documentation & more information -[Documentation](https://www.notion.so/jimmycai/Hugo-Theme-Stack-511aec5b9ed845ce9b6e3ae0bf7fb6d4) | [中文文档](https://www.notion.so/jimmycai/Hugo-Theme-Stack-511aec5b9ed845ce9b6e3ae0bf7fb6d4) +[Documentation](https://docs.stack.jimmycai.com/) | [中文文档](https://docs.stack.jimmycai.com/v/zh-cn/) ## Introduction @@ -35,7 +35,12 @@ The only JavaScript library being used is [node-vibrant](https://github.com/Vibr This theme uses SCSS and TypeScript. For that reason, it's necessary to use **Hugo ≥ 0.74.0**. -**Note**: You'll need Hugo Extended version to edit SCSS files +Use Hugo Extended version if you want to: + +* Use the latest feature/fix from `master` branch +* Edit SCSS files + +**Compiled CSS are updated once per release.** ## Installation @@ -51,6 +56,14 @@ Please do not remove the "*Theme Stack designed by Jimmy*" text and link. If you want to port this theme to another blogging platform, please let me know🙏. +## Sponsoring + +If you like this theme, consider supporting its development: + +Buy Me A Coffee + +Your support is greatly appreciated :) + ## Thanks to - [Vibrant-Colors/node-vibrant](https://github.com/Vibrant-Colors/node-vibrant) @@ -62,4 +75,4 @@ If you want to port this theme to another blogging platform, please let me know - [artchen/hexo-theme-element](https://github.com/artchen/hexo-theme-element) - [MunifTanjim/minimo](https://github.com/MunifTanjim/minimo) - [lepture/yue.css](https://github.com/lepture/yue.css) - - Markdown gallery syntax from [Typlog](https://typlog.com/) \ No newline at end of file + - Markdown gallery syntax from [Typlog](https://typlog.com/) diff --git a/assets/icons/search.svg b/assets/icons/search.svg new file mode 100644 index 0000000..a0b0ddc --- /dev/null +++ b/assets/icons/search.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/scss/custom.scss b/assets/scss/custom.scss new file mode 100644 index 0000000..61fa80f --- /dev/null +++ b/assets/scss/custom.scss @@ -0,0 +1 @@ +/* Place your custom SCSS in HUGO_SITE_FOLDER/assets/scss/custom.scss */ \ No newline at end of file diff --git a/assets/scss/grid.scss b/assets/scss/grid.scss new file mode 100644 index 0000000..73fcdfc --- /dev/null +++ b/assets/scss/grid.scss @@ -0,0 +1,119 @@ +.container { + margin-left: auto; + margin-right: auto; + + &.extended { + @media (min-width: $on-phone) { + max-width: 800px; + + .left-sidebar { + width: 25%; + } + } + + @media (min-width: $on-tablet) { + max-width: 972px; + + .right-sidebar { + width: 25%; + } + } + + @media (min-width: $on-desktop) { + max-width: 1200px; + + .left-sidebar { + width: 20%; + } + + .right-sidebar { + width: 25%; + } + } + + @media (min-width: $on-desktop-large) { + max-width: 1536px; + + .left-sidebar { + width: 15%; + } + } + } + + &.compact { + @media (min-width: $on-phone) { + max-width: 800px; + + .left-sidebar { + width: 25%; + } + } + + @media (min-width: $on-tablet) { + max-width: 972px; + } + + @media (min-width: $on-desktop) { + max-width: 1050px; + + .left-sidebar { + width: 20%; + } + } + + @media (min-width: $on-desktop-large) { + max-width: 1300px; + } + } +} + +.flex { + display: flex; + flex-direction: row; + + &.column { + flex-direction: column; + } + + &.on-phone--column { + @media (max-width: $on-phone) { + flex-direction: column; + } + } + + &.align-items--flex-start { + align-items: flex-start; + } + + .grow { + flex-grow: 1; + } + + .do-not-shrink { + flex-shrink: 0; + } + + .do-not-overflow { + min-width: 0; + flex-shrink: 1; + max-width: 100%; + } + + .full-width { + width: 100%; + } +} + +main.main { + min-width: 0; + padding: 0 15px; + max-width: 100%; + flex-grow: 1; + padding-top: var(--main-top-padding); +} + +.main-grid { + @media (max-width: $on-phone) { + flex-direction: column; + } +} diff --git a/assets/scss/partials/article.scss b/assets/scss/partials/article.scss index bcc10c1..1f40673 100644 --- a/assets/scss/partials/article.scss +++ b/assets/scss/partials/article.scss @@ -11,8 +11,8 @@ border-radius: var(--card-border-radius); overflow: hidden; - transition: box-shadow .3s ease; - + transition: box-shadow 0.3s ease; + &:hover { box-shadow: var(--shadow-l2); } @@ -53,7 +53,7 @@ flex-direction: column; justify-content: center; - padding: var(--content-padding); + padding: var(--card-padding); } .article-category { @@ -75,10 +75,14 @@ } .article-title { - font-size: 2.4rem; font-weight: 600; margin: 10px 0; color: var(--card-text-color-main); + font-size: 2.2rem; + + @media (min-width: $on-desktop-large) { + font-size: 2.4rem; + } a { color: var(--card-text-color-main); @@ -88,14 +92,6 @@ } } - @media (min-width: $on-desktop-large) { - font-size: 2.4rem; - } - - @media (max-width: $on-desktop) { - font-size: 2rem; - } - & + .article-subtitle { margin-top: 0; } @@ -103,18 +99,14 @@ .article-subtitle { font-weight: normal; - font-size: 1.8rem; color: var(--card-text-color-secondary); margin: 5px 0; line-height: 1.5; + font-size: 1.75rem; @media (min-width: $on-desktop-large) { font-size: 2rem; } - - @media (max-width: $on-desktop) { - font-size: 1.6rem; - } } .article-time { @@ -125,9 +117,10 @@ svg { vertical-align: middle; - margin-right: 8px; + margin-right: 15px; width: 20px; height: 20px; + stroke-width: 1.33; } time { @@ -159,24 +152,32 @@ border-radius: var(--card-border-radius); box-shadow: var(--shadow-l1); background-color: var(--card-background); + --image-size: 60px; + + @media (max-width: $on-tablet) { + --image-size: 50px; + } & + .pagination { margin-top: var(--section-separation); } article { - display: flex; - align-items: center; - padding: var(--small-card-padding); + & > a { + display: flex; + align-items: center; + padding: var(--small-card-padding); + } &:not(:last-of-type) { - border-bottom: 2px solid var(--card-separator-color); + border-bottom: 1.5px solid var(--card-separator-color); } .article-details { flex-grow: 1; padding: 0; padding-right: 15px; + min-height: var(--image-size); } .article-title { @@ -190,10 +191,21 @@ .article-image { img { - width: 60px; - height: 60px; + width: var(--image-size); + height: var(--image-size); } } + + .article-time { + font-size: 1.4rem; + } + + .article-preview{ + font-size: 1.4rem; + color: var(--card-text-color-tertiary); + margin-top: 10px; + line-height: 1.5; + } } } diff --git a/assets/scss/partials/layout/404.scss b/assets/scss/partials/layout/404.scss index c1c0db1..d9d8752 100644 --- a/assets/scss/partials/layout/404.scss +++ b/assets/scss/partials/layout/404.scss @@ -2,5 +2,5 @@ background-color: var(--card-background); box-shadow: var(--shadow-l1); border-radius: var(--card-border-radius); - padding: var(--content-padding); + padding: var(--card-padding); } diff --git a/assets/scss/partials/layout/archives.scss b/assets/scss/partials/layout/archives.scss index 569348e..2ac3836 100644 --- a/assets/scss/partials/layout/archives.scss +++ b/assets/scss/partials/layout/archives.scss @@ -1,15 +1,5 @@ .archives-group { margin-bottom: var(--section-separation); - .archives-date { - text-transform: uppercase; - margin-bottom: 10px; - font-size: 1.6rem; - font-weight: bold; - - a { - color: var(--body-text-color); - } - } } .template-archives { diff --git a/assets/scss/partials/layout/article.scss b/assets/scss/partials/layout/article.scss index 76e0fad..c76fcce 100644 --- a/assets/scss/partials/layout/article.scss +++ b/assets/scss/partials/layout/article.scss @@ -43,7 +43,7 @@ } } - article { + .main-article { background: var(--card-background); border-radius: var(--card-border-radius); box-shadow: var(--shadow-l1); @@ -64,13 +64,13 @@ } .article-details { - padding: var(--content-padding); + padding: var(--card-padding); padding-bottom: 0; } } .article-content { - margin: var(--content-padding) 0; + margin: var(--card-padding) 0; color: var(--card-text-color-main); img { @@ -80,11 +80,11 @@ } .article-footer { - padding: var(--content-padding); - padding-top: 0; + margin: var(--card-padding); + margin-top: 0; section:not(:first-child) { - margin-top: var(--content-padding); + margin-top: var(--card-padding); } section { @@ -104,6 +104,7 @@ .article-tags { flex-wrap: wrap; + text-transform: unset; } } } @@ -192,7 +193,7 @@ & > p { margin: 1.5em 0; - padding: 0 var(--content-padding); + padding: 0 var(--card-padding); } h1, @@ -201,7 +202,7 @@ h4, h5, h6 { - padding: 0 calc(var(--content-padding) - var(--heading-border-size)); + padding: 0 calc(var(--card-padding) - var(--heading-border-size)); border-left: var(--heading-border-size) solid var(--accent-color); } @@ -219,13 +220,13 @@ position: relative; margin: 10px 0; border-left: var(--blockquote-border-size) solid var(--card-separator-color); - padding: 15px calc(var(--content-padding) - var(--blockquote-border-size)); + padding: 15px calc(var(--card-padding) - var(--blockquote-border-size)); background-color: var(--blockquote-background-color); } & > ul, & > ol { - margin: 1em var(--content-padding); + margin: 1em var(--card-padding); } hr { @@ -270,7 +271,7 @@ font-family: var(--code-font-family); line-height: 1.428571429; word-break: break-all; - padding: var(--content-padding); + padding: var(--card-padding); code { color: unset; @@ -281,9 +282,9 @@ } table { - margin: 0 var(--content-padding); + margin: 0 var(--card-padding); width: 100%; - max-width: calc(100% - var(--content-padding) * 2); + max-width: calc(100% - var(--card-padding) * 2); border-collapse: collapse; border-spacing: 0; margin-bottom: 1.5em; diff --git a/assets/scss/partials/layout/search.scss b/assets/scss/partials/layout/search.scss new file mode 100644 index 0000000..b390a7b --- /dev/null +++ b/assets/scss/partials/layout/search.scss @@ -0,0 +1,82 @@ +.search-form { + margin-bottom: var(--section-separation); + position: relative; + --button-size: 80px; + + &.widget { + --button-size: 60px; + + label { + font-size: 1.3rem; + top: 10px; + } + + input { + font-size: 1.5rem; + padding: 30px 20px 15px 20px; + } + } + + p { + position: relative; + margin: 0; + } + + label { + position: absolute; + top: 15px; + left: 20px; + font-size: 1.4rem; + color: var(--card-text-color-tertiary); + } + + input { + padding: 40px 20px 20px; + border-radius: var(--card-border-radius); + background-color: var(--card-background); + box-shadow: var(--shadow-l1); + color: var(--card-text-color-main); + width: 100%; + border: 0; + -webkit-appearance: none; + + transition: box-shadow 0.3s ease; + + font-size: 1.8rem; + + &:focus { + outline: 0; + box-shadow: var(--shadow-l2); + } + } + + button { + position: absolute; + right: 0; + top: 0; + height: 100%; + width: var(--button-size); + cursor: pointer; + background-color: transparent; + border: 0; + + padding: 0 10px; + + &:focus { + outline: 0; + + svg { + stroke-width: 2; + color: var(--accent-color); + } + } + + svg { + color: var(--card-text-color-secondary); + stroke-width: 1.33; + transition: all 0.3s ease; + width: 20px; + height: 20px; + } + } +} \ No newline at end of file diff --git a/assets/scss/partials/layout/taxonomy.scss b/assets/scss/partials/layout/taxonomy.scss index d594b23..4575a20 100644 --- a/assets/scss/partials/layout/taxonomy.scss +++ b/assets/scss/partials/layout/taxonomy.scss @@ -1,11 +1,3 @@ -.taxonomy-type { - text-transform: uppercase; - color: var(--body-text-color); - font-weight: bold; - margin-bottom: 5px; - font-size: 1.6rem; -} - .taxonomy-card { border-radius: var(--card-border-radius); background-color: var(--card-background); diff --git a/assets/scss/partials/menu.scss b/assets/scss/partials/menu.scss index 7cb7e83..7aa5acd 100644 --- a/assets/scss/partials/menu.scss +++ b/assets/scss/partials/menu.scss @@ -126,9 +126,11 @@ list-style: none; display: flex; flex-direction: column; - margin-top: 25px; + margin-top: var(--sidebar-element-separation); + margin-bottom: 0; overflow-y: auto; flex-grow: 1; + font-size: 1.5rem; @media (min-width: $on-desktop-large) { margin-top: 30px; @@ -180,6 +182,11 @@ height: 25px; stroke-width: 1.33; margin-right: 40px; + + @media (max-width: $on-desktop-large) { + width: 20px; + height: 20px; + } } a { @@ -187,9 +194,8 @@ display: inline-flex; align-items: center; color: var(--body-text-color); - font-size: 1.5rem; - @media (max-width: $on-desktop) { + @media (max-width: $on-desktop-large) { font-size: 1.4rem; } } diff --git a/assets/scss/partials/sidebar.scss b/assets/scss/partials/sidebar.scss index c1ddeb1..c967879 100644 --- a/assets/scss/partials/sidebar.scss +++ b/assets/scss/partials/sidebar.scss @@ -12,6 +12,14 @@ flex-direction: column; flex-shrink: 0; + --sidebar-avatar-size: 150px; + --sidebar-element-separation: 25px; + + @media (max-width: $on-desktop-large) { + --sidebar-avatar-size: 120px; + --sidebar-element-separation: 20px; + } + @media (max-width: $on-phone) { width: 100%; padding: 30px 0; @@ -23,19 +31,10 @@ } @media (min-width: $on-phone + 1) { - width: 25%; margin-right: 1%; padding: var(--main-top-padding) 15px; height: 100vh; } - - @media (min-width: $on-desktop) { - width: 20%; - } - - @media (min-width: $on-desktop-large) { - width: 15%; - } } .right-sidebar { @@ -50,19 +49,15 @@ } @media (min-width: $on-tablet) { - width: 25%; margin-left: 1%; - padding-top: 50px; - } - - @media (min-width: $on-desktop + 1) { - width: 25%; + padding-top: var(--main-top-padding); } } .site-info { z-index: 1; transition: box-shadow 0.5s ease; + @media (max-width: $on-phone) { padding: 15px 30px; } @@ -70,14 +65,10 @@ .site-avatar { position: relative; margin: 0; - margin-bottom: 25px; - width: 150px; - height: 150px; + width: var(--sidebar-avatar-size); + height: var(--sidebar-avatar-size); - @media (max-width: $on-desktop-large) { - height: 120px; - width: 120px; - } + margin-bottom: var(--sidebar-element-separation); .site-logo { width: 100%; @@ -131,16 +122,15 @@ .sidebar { .widget { - &:not(:last-of-type) { - margin-bottom: var(--section-separation); - &:after { - content: ""; - width: 100px; - height: 2px; - background-color: var(--body-text-color); - display: block; - margin-top: var(--section-separation); - } + margin-bottom: var(--section-separation); + + &:not(:last-of-type):after { + content: ""; + width: 100px; + height: 2px; + background-color: var(--body-text-color); + display: block; + margin-top: var(--section-separation); } } } diff --git a/assets/scss/partials/widgets.scss b/assets/scss/partials/widgets.scss index c80c8ad..33a02dd 100644 --- a/assets/scss/partials/widgets.scss +++ b/assets/scss/partials/widgets.scss @@ -1,13 +1,4 @@ .widget { - .widget-title { - text-transform: uppercase; - color: var(--body-text-color); - font-weight: bold; - margin: 0; - margin-bottom: 10px; - font-size: 1.6rem; - } - .widget-icon { svg { width: 32px; @@ -45,28 +36,26 @@ /* Archives widget */ .widget.archives { + .widget-archive--list { + border-radius: var(--card-border-radius); + box-shadow: var(--shadow-l1); + background-color: var(--card-background); + } + .archives-year { - margin-bottom: 10px; + &:not(:last-of-type) { + border-bottom: 1.5px solid var(--card-separator-color); + } + a { - background-color: var(--card-background); - padding: 15px 25px; - border-radius: var(--card-border-radius); - box-shadow: var(--shadow-l1); + font-size: 1.4rem; + padding: 18px 25px; display: flex; - transition: box-shadow 0.3s ease; - - &:hover { - box-shadow: var(--shadow-l2); - } - - @media (max-width: $on-desktop-large) { - padding: 12px 20px; - font-size: 1.4rem; - } span.year { flex: 1; color: var(--card-text-color-main); + font-weight: bold; } span.count { diff --git a/assets/scss/style.scss b/assets/scss/style.scss index 908be5e..3e4b56a 100644 --- a/assets/scss/style.scss +++ b/assets/scss/style.scss @@ -8,6 +8,7 @@ @import "breakpoints.scss"; @import "variables.scss"; +@import "grid.scss"; @import "external/normalize.scss"; @@ -22,6 +23,9 @@ @import "partials/layout/article.scss"; @import "partials/layout/taxonomy.scss"; @import "partials/layout/404.scss"; +@import "partials/layout/search.scss"; + +@import "custom.scss"; a { text-decoration: none; @@ -41,96 +45,16 @@ a { } } -.container { - margin-left: auto; - margin-right: auto; +.section-title { + text-transform: uppercase; + margin-top: 0; + margin-bottom: 10px; + display: block; + font-size: 1.6rem; + font-weight: bold; + color: var(--body-text-color); - &.extended { - @media (min-width: $on-phone) { - max-width: 800px; - } - - @media (min-width: $on-tablet) { - max-width: 972px; - } - - @media (min-width: $on-desktop) { - max-width: 1200px; - } - - @media (min-width: $on-desktop-large) { - max-width: 1536px; - } - } -} - -main.main { - min-width: 0; - padding: 0 15px; - max-width: 100%; - flex-grow: 1; - padding-top: var(--main-top-padding); -} - -.main-grid { - @media (max-width: $on-phone) { - flex-direction: column; - } -} - -.flex { - display: flex; - flex-direction: row; - - &.column { - flex-direction: column; - } - - &.on-phone--column { - @media (max-width: $on-phone) { - flex-direction: column; - } - } - - &.align-items--flex-start { - align-items: flex-start; - } - - .grow { - flex-grow: 1; - } - - .do-not-shrink { - flex-shrink: 0; - } - - .do-not-overflow { - min-width: 0; - flex-shrink: 1; - max-width: 100%; - } - - .full-width { - width: 100%; - } -} - -.alert { - position: fixed; - right: 20px; - bottom: 20px; - z-index: 5; - background: var(--card-background); - max-width: 400px; - padding: 15px 20px; - border-radius: var(--card-border-radius); - line-height: 1.75; - color: var(--card-text-color-secondary); - box-shadow: var(--shadow-l2); - - @media (max-width: $on-phone) { - max-width: 100vw; - width: calc(100% - 30px); - left: 15px; + a { + color: var(--body-text-color); } } diff --git a/assets/scss/variables.scss b/assets/scss/variables.scss index 3e886fb..495ef1a 100644 --- a/assets/scss/variables.scss +++ b/assets/scss/variables.scss @@ -6,9 +6,14 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff; */ :root { @media (min-width: $on-phone + 1) { + --main-top-padding: 35px; + } + + @media (min-width: $on-desktop-large) { --main-top-padding: 50px; } + --body-background: #f5f5fa; --accent-color: #34495e; @@ -54,15 +59,18 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff; --card-border-radius: 10px; - --content-padding: 30px; + --card-padding: 30px; @media (max-width: $on-desktop-large) { - --content-padding: 25px; + --card-padding: 25px; } @media (max-width: $on-tablet) { - --content-padding: 20px; + --card-padding: 20px; } --small-card-padding: 25px; + @media (max-width: $on-tablet) { + --small-card-padding: 25px 20px; + } .theme-dark { --card-background: #424242; diff --git a/assets/ts/createElement.ts b/assets/ts/createElement.ts new file mode 100644 index 0000000..3a1e85e --- /dev/null +++ b/assets/ts/createElement.ts @@ -0,0 +1,34 @@ +/** + * createElement + * Edited from: + * @link https://stackoverflow.com/a/42405694 + */ +function createElement(tag, attrs, children) { + var element = document.createElement(tag); + + for (let name in attrs) { + if (name && attrs.hasOwnProperty(name)) { + let value = attrs[name]; + + if (name == "dangerouslySetInnerHTML") { + element.innerHTML = value.__html; + } + else if (value === true) { + element.setAttribute(name, name); + } else if (value !== false && value != null) { + element.setAttribute(name, value.toString()); + } + } + } + for (let i = 2; i < arguments.length; i++) { + let child = arguments[i]; + if (child) { + element.appendChild( + child.nodeType == null ? + document.createTextNode(child.toString()) : child); + } + } + return element; +} + +export default createElement; \ No newline at end of file diff --git a/assets/ts/gallery.ts b/assets/ts/gallery.ts index b9871ff..41fba8e 100644 --- a/assets/ts/gallery.ts +++ b/assets/ts/gallery.ts @@ -236,10 +236,10 @@ function wrap(gallery: HTMLElement[]) { */ function loadPhotoSwipe() { const tasks = [ - loadScript("https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"), - loadScript("https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"), - loadStyle("https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.css"), - loadStyle("https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.min.css") + loadScript("https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"), + loadScript("https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"), + loadStyle("https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css"), + loadStyle("https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css") ]; return Promise.all(tasks); diff --git a/assets/ts/main.ts b/assets/ts/main.ts index 8d60b07..168f16b 100644 --- a/assets/ts/main.ts +++ b/assets/ts/main.ts @@ -10,6 +10,7 @@ import { createGallery } from "./gallery" import { getColor } from './color'; import menu from './menu'; import darkmode from "./darkmode"; +import createElement from './createElement'; let Stack = { init: () => { @@ -68,29 +69,6 @@ let Stack = { observer.observe(articleTile) } - }, - alert: (content, time = 5000, animationSpeed = 500) => { - const alert = document.createElement('div'); - alert.innerHTML = content; - alert.className = 'alert'; - alert.style.visibility = 'hidden'; - document.body.appendChild(alert); - - alert.style.transform = `translateY(${alert.clientHeight + 50}px)`; - alert.style.transition = `transform ${animationSpeed / 1000}s ease`; - - setTimeout(() => { - alert.style.removeProperty('visibility'); - alert.style.transform = `translateY(0)`; - }, animationSpeed); - - setTimeout(() => { - alert.style.transform = `translateY(${alert.clientHeight + 50}px)`; - }, animationSpeed + time); - - setTimeout(() => { - alert.remove(); - }, 2 * animationSpeed + time); } } @@ -100,4 +78,12 @@ window.addEventListener('load', () => { }, 0); }) -window.Stack = Stack; \ No newline at end of file +declare global { + interface Window { + createElement: any; + Stack: any + } +} + +window.Stack = Stack; +window.createElement = createElement; \ No newline at end of file diff --git a/assets/ts/search.tsx b/assets/ts/search.tsx new file mode 100644 index 0000000..8e4eb6f --- /dev/null +++ b/assets/ts/search.tsx @@ -0,0 +1,263 @@ +interface pageData { + title: string, + date: string, + permalink: string, + content: string, + image?: string, + preview: string, + matchCount: number +} + +/** + * Escape HTML tags as HTML entities + * Edited from: + * @link https://stackoverflow.com/a/5499821 + */ +const tagsToReplace = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '…': '…' +}; + +function replaceTag(tag) { + return tagsToReplace[tag] || tag; +} + +function replaceHTMLEnt(str) { + return str.replace(/[&<>"]/g, replaceTag); +} + +function escapeRegExp(string) { + return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); +} + +class Search { + private data: pageData[]; + private form: HTMLFormElement; + private input: HTMLInputElement; + private list: HTMLDivElement; + private resultTitle: HTMLHeadElement; + private resultTitleTemplate: string; + + constructor({ form, input, list, resultTitle, resultTitleTemplate }) { + this.form = form; + this.input = input; + this.list = list; + this.resultTitle = resultTitle; + this.resultTitleTemplate = resultTitleTemplate; + + this.handleQueryString(); + this.bindQueryStringChange(); + this.bindSearchForm(); + } + + private async searchKeywords(keywords: string[]) { + const rawData = await this.getData(); + let results: pageData[] = []; + + /// Sort keywords by their length + keywords.sort((a, b) => { + return b.length - a.length + }); + + for (const item of rawData) { + let result = { + ...item, + preview: '', + matchCount: 0 + } + + let matched = false; + + for (const keyword of keywords) { + if (keyword === '') continue; + + const regex = new RegExp(escapeRegExp(replaceHTMLEnt(keyword)), 'gi'); + + const contentMatch = regex.exec(result.content); + regex.lastIndex = 0; /// Reset regex + + const titleMatch = regex.exec(result.title); + regex.lastIndex = 0; /// Reset regex + + if (titleMatch) { + result.title = result.title.replace(regex, Search.marker); + } + + if (titleMatch || contentMatch) { + matched = true; + ++result.matchCount; + + let start = 0, + end = 100; + + if (contentMatch) { + start = contentMatch.index - 20; + end = contentMatch.index + 80 + + if (start < 0) start = 0; + } + + if (result.preview.indexOf(keyword) !== -1) { + result.preview = result.preview.replace(regex, Search.marker); + } + else { + if (start !== 0) result.preview += `[...] `; + result.preview += `${result.content.slice(start, end).replace(regex, Search.marker)} `; + } + } + } + + if (matched) { + result.preview += '[...]'; + results.push(result); + } + } + + /** Result with more matches appears first */ + return results.sort((a, b) => { + return b.matchCount - a.matchCount; + }); + } + + public static marker(match) { + return '' + match + ''; + } + + private async doSearch(keywords: string[]) { + const startTime = performance.now(); + + const results = await this.searchKeywords(keywords); + this.clear(); + + for (const item of results) { + this.list.append(Search.render(item)); + } + + const endTime = performance.now(); + + this.resultTitle.innerText = this.generateResultTitle(results.length, ((endTime - startTime) / 1000).toPrecision(1)); + } + + private generateResultTitle(resultLen, time) { + return this.resultTitleTemplate.replace("#PAGES_COUNT", resultLen).replace("#TIME_SECONDS", time); + } + + public async getData() { + if (!this.data) { + /// Not fetched yet + const jsonURL = this.form.dataset.json; + this.data = await fetch(jsonURL).then(res => res.json()); + } + + return this.data; + } + + private bindSearchForm() { + let lastSearch = ''; + + const eventHandler = (e) => { + e.preventDefault(); + const keywords = this.input.value; + + Search.updateQueryString(keywords, true); + + if (keywords === '') { + return this.clear(); + } + + if (lastSearch === keywords) return; + lastSearch = keywords; + + this.doSearch(keywords.split(' ')); + } + + this.input.addEventListener('input', eventHandler); + this.input.addEventListener('compositionend', eventHandler); + } + + private clear() { + this.list.innerHTML = ''; + this.resultTitle.innerText = ''; + } + + private bindQueryStringChange() { + window.addEventListener('popstate', (e) => { + this.handleQueryString() + }) + } + + private handleQueryString() { + const pageURL = new URL(window.location.toString()); + const keywords = pageURL.searchParams.get('keyword'); + this.input.value = keywords; + + if (keywords) { + this.doSearch(keywords.split(' ')); + } + else { + this.clear() + } + } + + private static updateQueryString(keywords: string, replaceState = false) { + const pageURL = new URL(window.location.toString()); + + if (keywords === '') { + pageURL.searchParams.delete('keyword') + } + else { + pageURL.searchParams.set('keyword', keywords); + } + + if (replaceState) { + window.history.replaceState('', '', pageURL.toString()); + } + else { + window.history.pushState('', '', pageURL.toString()); + } + } + + public static render(item: pageData) { + return
+ +
+

+ +
+ {item.image && +
+ +
+ } +
+
; + } +} + +declare global { + interface Window { + searchResultTitleTemplate: string; + } +} + +window.addEventListener('load', () => { + setTimeout(function () { + const searchForm = document.querySelector('.search-form') as HTMLFormElement, + searchInput = searchForm.querySelector('input') as HTMLInputElement, + searchResultList = document.querySelector('.search-result--list') as HTMLDivElement, + searchResultTitle = document.querySelector('.search-result--title') as HTMLHeadingElement; + + new Search({ + form: searchForm, + input: searchInput, + list: searchResultList, + resultTitle: searchResultTitle, + resultTitleTemplate: window.searchResultTitleTemplate + }); + }, 0); +}) + +export default Search; \ No newline at end of file diff --git a/exampleSite/config.toml b/exampleSite/config.toml deleted file mode 100644 index d554f8c..0000000 --- a/exampleSite/config.toml +++ /dev/null @@ -1,92 +0,0 @@ -baseurl = "https://example.com" -languageCode = "en-us" -theme = "hugo-theme-stack" -paginate = 5 -title = "Example Site" -disqusShortname = "hugo-theme-stack" # Change it to your Disqus shortname before using -DefaultContentLanguage = "en" # Theme i18n support - -[permalinks] - post = "/p/:slug/" - page = "/:slug/" - -[params] - mainSections = ["post"] - featuredImageField = "image" - [params.dateFormat] - published = "Jan 02, 2006" - lastUpdated = "Jan 02, 2006 15:04 MST" - [params.sidebar] - emoji = "🍥" - avatar = "img/avatar.png" - subtitle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - [params.article] - [params.article.license] - enabled = true - default = "Licenced under CC BY-NC-SA 4.0" - [params.comments] - enabled = true - # Only Disqus is available so far - provider = "disqus" - [params.widgets] - enabled = ['archives', 'tag-cloud'] - [params.widgets.archives] - limit = 5 - ### Archives page relative URL - path = "archives" - [params.widgets.tagCloud] - limit = 10 - [params.opengraph] - [params.opengraph.twitter] - site = "" - card = "summary_large_image" - [params.defaultImage] - [params.defaultImage.article] - enabled = false - local = false - src = "" - [params.defaultImage.articleList] - enabled = false - local = true - src = "" - [params.defaultImage.opengraph] - enabled = false - local = false - src = "" - -[menu] - [[menu.main]] - identifier = "home" - name = "Home" - url = "/" - weight = -100 - pre = "home" - [[menu.main]] - identifier = "about-cn" - name = "About" - url = "about" - weight = -90 - pre = "user" - [[menu.main]] - identifier = "archives" - name = "Archives" - url = "archives" - weight = -70 - pre = "archives" - -[related] - includeNewer = true - threshold = 60 - toLower = false - - [[related.indices]] - name = "tags" - weight = 100 - - [[related.indices]] - name = "categories" - weight = 200 - -[markup] - [markup.highlight] - noClasses = false \ No newline at end of file diff --git a/exampleSite/config.yaml b/exampleSite/config.yaml new file mode 100644 index 0000000..7367a49 --- /dev/null +++ b/exampleSite/config.yaml @@ -0,0 +1,113 @@ +baseurl: https://example.com +languageCode: en-us +theme: hugo-theme-stack +paginate: 5 +title: Example Site + +# Change it to your Disqus shortname before using +disqusShortname: hugo-theme-stack + +# Theme i18n support +# Available values: en, fr, id, ja, ko, pt-br, zh-cn +DefaultContentLanguage: en + +permalinks: + post: /p/:slug/ + page: /:slug/ + +params: + mainSections: + - post + featuredImageField: image + rssFullContent: true + + dateFormat: + published: Jan 02, 2006 + lastUpdated: Jan 02, 2006 15:04 MST + + sidebar: + emoji: 🍥 + subtitle: Lorem ipsum dolor sit amet, consectetur adipiscing elit. + avatar: + local: true + src: img/avatar.png + + article: + math: false + license: + enabled: true + default: Licensed under CC BY-NC-SA 4.0 + + comments: + enabled: true + provider: disqus + utterances: + repo: + issueTerm: pathname + label: + theme: preferred-color-scheme + + widgets: + enabled: + - search + - archives + - tag-cloud + + archives: + limit: 5 + path: archives + + tagCloud: + limit: 10 + + opengraph: + twitter: + site: + card: summary_large_image + + defaultImage: + opengraph: + enabled: false + local: false + src: + +menu: + main: + - identifier: home + name: Home + url: / + weight: -100 + pre: home + + - identifier: about + name: About + url: about + weight: -90 + pre: user + + - identifier: archives + name: Archives + url: archives + weight: -70 + pre: archives + + - identifier: search + name: Search + url: search + weight: -60 + pre: search + +related: + includeNewer: true + threshold: 60 + toLower: false + indices: + - name: tags + weight: 100 + + - name: categories + weight: 200 + +markup: + highlight: + noClasses: false diff --git a/exampleSite/content/page/about.md b/exampleSite/content/page/about.md index 46a3b3e..8a8789f 100644 --- a/exampleSite/content/page/about.md +++ b/exampleSite/content/page/about.md @@ -5,6 +5,7 @@ date = "2019-02-28" aliases = ["about-us", "about-hugo", "contact"] author = "Hugo Authors" license = "CC BY-NC-ND" +lastmod = "2020-10-09" +++ Written in Go, Hugo is an open source static site generator available under the [Apache Licence 2.0.](https://github.com/gohugoio/hugo/blob/master/LICENSE) Hugo supports TOML, YAML and JSON data file types, Markdown and HTML content files and uses shortcodes to add rich content. Other notable features are taxonomies, multilingual mode, image processing, custom output formats, HTML/CSS/JS minification and support for Sass SCSS workflows. diff --git a/exampleSite/content/page/search.md b/exampleSite/content/page/search.md new file mode 100644 index 0000000..0363546 --- /dev/null +++ b/exampleSite/content/page/search.md @@ -0,0 +1,8 @@ +--- +title: "Search" +slug: "search" +layout: "search" +outputs: + - html + - json +--- \ No newline at end of file diff --git a/exampleSite/content/post/chinese-test/index.md b/exampleSite/content/post/chinese-test/index.md index f58b38f..5249ef8 100644 --- a/exampleSite/content/post/chinese-test/index.md +++ b/exampleSite/content/post/chinese-test/index.md @@ -1,11 +1,12 @@ --- -title: 中文文章内容测试 +title: Chinese Test description: 这是一个副标题 date: 2020-09-09 slug: test-chinese image: helena-hertz-wWZzXlDpMog-unsplash.jpg categories: - Test + - 测试 --- ## 正文测试 diff --git a/exampleSite/content/post/placeholder-text/index.md b/exampleSite/content/post/placeholder-text/index.md index 8ac7350..280197e 100644 --- a/exampleSite/content/post/placeholder-text/index.md +++ b/exampleSite/content/post/placeholder-text/index.md @@ -4,11 +4,13 @@ title = "Placeholder Text" date = "2019-03-09" description = "Lorem Ipsum Dolor Si Amet" categories = [ - "Test" + "Test", + "Test with whitespaces" ] tags = [ "markdown", "text", + "tag with whitespaces" ] image = "matt-le-SJSpo9hQf7s-unsplash.jpg" +++ diff --git a/exampleSite/content/post/rich-content/index.md b/exampleSite/content/post/rich-content/index.md index 5ff41d7..407c539 100644 --- a/exampleSite/content/post/rich-content/index.md +++ b/exampleSite/content/post/rich-content/index.md @@ -13,14 +13,6 @@ Hugo ships with several [Built-in Shortcodes](https://gohugo.io/content-manageme --- -## Instagram Simple Shortcode - -{{< instagram_simple BGvuInzyFAe hidecaption >}} - -
- ---- - ## YouTube Privacy Enhanced Shortcode {{< youtube ZJthWmvUzzc >}} diff --git a/i18n/en.toml b/i18n/en.toml deleted file mode 100644 index f00f938..0000000 --- a/i18n/en.toml +++ /dev/null @@ -1,26 +0,0 @@ -[toggleMenu] - other = "Toggle Menu" - -[relatedContents] - other = "Related contents" - -[lastUpdatedOn] - other ="Last updated on {{ .Count }}" - -[widgetArchivesTitle] - other = "Archives" - -[widgetArchivesMore] - other = "More" - -[widgetTagCloudTitle] - other = "Tags" - -[notFoundTitle] - other = "Not Found" - -[notFoundSubtitle] - other = "This page does not exist." - -[darkModeToggle] - other = "Dark Mode" \ No newline at end of file diff --git a/i18n/en.yaml b/i18n/en.yaml new file mode 100644 index 0000000..1adc0d2 --- /dev/null +++ b/i18n/en.yaml @@ -0,0 +1,46 @@ +toggleMenu: + other: Toggle Menu + +darkMode: + toggle: + other: Dark Mode + +archives: + categories: + other: Categories + +article: + relatedContents: + other: Related contents + lastUpdatedOn: + other: Last updated on + +notFound: + title: + other: Not Found + subtitle: + other: This page does not exist. + +widget: + archives: + title: + other: Archives + more: + other: More + tagCloud: + title: + other: Tags + +search: + title: + other: Search + placeholder: + other: Type something... + resultTitle: + other: "#PAGES_COUNT pages (#TIME_SECONDS seconds)" + +footer: + builtWith: + other: Built with {{ .Generator }} + designedBy: + other: Theme {{ .Theme }} designed by {{ .DesignedBy }} diff --git a/i18n/fr.yaml b/i18n/fr.yaml new file mode 100644 index 0000000..59cc111 --- /dev/null +++ b/i18n/fr.yaml @@ -0,0 +1,38 @@ +toggleMenu: + other: Afficher le menu + +article: + relatedContents: + other: Contenus liés + lastUpdatedOn: + other: Dernière mise à jour le + +notFound: + title: + other: Page non trouvée + subtitle: + other: Cette page n'existe pas. + +widget: + archives: + title: + other: Archives + more: + other: Autres + tagCloud: + title: + other: Mots clés + +search: + title: + other: Rechercher + placeholder: + other: Cherchez un article, une publication, etc. + resultTitle: + other: "#PAGES_COUNT pages (#TIME_SECONDS secondes)" + +footer: + builtWith: + other: Généré avec {{ .Generator }} + designedBy: + other: Thème {{ .Theme }} conçu par {{ .DesignedBy }} diff --git a/i18n/id.yaml b/i18n/id.yaml new file mode 100644 index 0000000..31cea39 --- /dev/null +++ b/i18n/id.yaml @@ -0,0 +1,38 @@ +toggleMenu: + other: Tampilkan Menu + +article: + relatedContents: + other: Konten terkait + lastUpdatedOn: + other: Terakhir diperbarui pada + +notFound: + title: + other: Not Found + subtitle: + other: Halaman ini tidak ada. + +widget: + archives: + title: + other: Arsip + more: + other: Lebih + tagCloud: + title: + other: Tag + +search: + title: + other: Cari + placeholder: + other: Ketik sesuatu... + resultTitle: + other: "#PAGES_COUNT halaman (#TIME_SECONDS detik)" + +footer: + builtWith: + other: Dibangun dengan {{ .Generator }} + designedBy: + other: Tema {{ .Theme }} dirancang oleh {{ .DesignedBy }} diff --git a/i18n/ja.yaml b/i18n/ja.yaml new file mode 100644 index 0000000..e982ce3 --- /dev/null +++ b/i18n/ja.yaml @@ -0,0 +1,24 @@ +toggleMenu: + other: メニューを開く・閉じる + +article: + relatedContents: + other: 関連するコンテンツ + lastUpdatedOn: + other: 最終更新 + +notFound: + title: + other: 404 Not Found + subtitle: + other: 指定されたページは存在しません。 + +widget: + archives: + title: + other: アーカイブ + more: + other: さらに見る + tagCloud: + title: + other: タグ diff --git a/i18n/ko.yaml b/i18n/ko.yaml new file mode 100644 index 0000000..d9916cd --- /dev/null +++ b/i18n/ko.yaml @@ -0,0 +1,38 @@ +toggleMenu: + other: 메뉴 여닫기 + +article: + relatedContents: + other: 관련 글 + lastUpdatedOn: + other: "마지막 수정: " + +notFound: + title: + other: 찾을 수 없음 + subtitle: + other: 페이지를 찾을 수 없습니다. + +widget: + archives: + title: + other: 보관함 + more: + other: 더보기 + tagCloud: + title: + other: 태그 + +search: + title: + other: 검색 + placeholder: + other: 검색어를 입력하세요... + resultTitle: + other: "#PAGES_COUNT 페이지 (#TIME_SECONDS 초)" + +footer: + builtWith: + other: "{{ .Generator }}로 만듦" + designedBy: + other: "{{ .DesignedBy }}의 {{ .Theme }} 테마 사용 중" diff --git a/i18n/pt-BR.yaml b/i18n/pt-BR.yaml new file mode 100644 index 0000000..5380c68 --- /dev/null +++ b/i18n/pt-BR.yaml @@ -0,0 +1,42 @@ +toggleMenu: + other: Alternar Menu + +archives: + categories: + other: Categorias + +article: + relatedContents: + other: Conteúdos Relacionados + lastUpdatedOn: + other: Última atualização em + +notFound: + title: + other: Não Encontrado + subtitle: + other: Esta página não existe. + +widget: + archives: + title: + other: Arquivos + more: + other: Mais + tagCloud: + title: + other: Tags + +search: + title: + other: Busca + placeholder: + other: Digite algo... + resultTitle: + other: "#PAGES_COUNT páginas (#TIME_SECONDS segundos)" + +footer: + builtWith: + other: Criado com {{ .Generator }} + designedBy: + other: Tema {{ .Theme }} desenvolvido por {{ .DesignedBy }} diff --git a/i18n/zh-CN.toml b/i18n/zh-CN.toml deleted file mode 100644 index a4e280c..0000000 --- a/i18n/zh-CN.toml +++ /dev/null @@ -1,26 +0,0 @@ -[toggleMenu] - other = "切换菜单" - -[relatedContents] - other = "相关文章" - -[lastUpdatedOn] - other ="最后更新于 {{ .Count }}" - -[widgetArchivesTitle] - other = "归档" - -[widgetArchivesMore] - other = "更多" - -[widgetTagCloudTitle] - other = "标签云" - -[notFoundTitle] - other = "404 错误" - -[notFoundSubtitle] - other = "页面不存在" - -[darkModeToggle] - other = "暗色模式" \ No newline at end of file diff --git a/i18n/zh-CN.yaml b/i18n/zh-CN.yaml new file mode 100644 index 0000000..44b7dc8 --- /dev/null +++ b/i18n/zh-CN.yaml @@ -0,0 +1,40 @@ +toggleMenu: + other: 切换菜单 + +darkMode: + toggle: + other: 暗色模式 + +archives: + categories: + other: 分类 + +article: + relatedContents: + other: 相关文章 + lastUpdatedOn: + other: 最后更新于 + +notFound: + title: + other: 404 错误 + subtitle: + other: 页面不存在 + +widget: + archives: + title: + other: 归档 + more: + other: 更多 + tagCloud: + title: + other: 标签云 + +search: + title: + other: 搜索 + placeholder: + other: 输入关键词... + resultTitle: + other: "#PAGES_COUNT 个结果 (用时 #TIME_SECONDS 秒)" diff --git a/layouts/404.html b/layouts/404.html index dd5e49d..b89d2b6 100644 --- a/layouts/404.html +++ b/layouts/404.html @@ -1,7 +1,7 @@ {{ define "main" }}
-

{{ T "notFoundTitle" }}

-

{{ T "notFoundSubtitle" }}

+

{{ T "notFound.title" }}

+

{{ T "notFound.subtitle" }}

{{ partialCached "footer/footer" . }} {{ end }} \ No newline at end of file diff --git a/layouts/_default/archives.html b/layouts/_default/archives.html index cf9ef94..1a681e9 100644 --- a/layouts/_default/archives.html +++ b/layouts/_default/archives.html @@ -2,14 +2,12 @@ {{ define "main" }} {{ $categories := ($.Site.GetPage "taxonomyTerm" "categories").Pages }} {{ if $categories }} -
-

Categories

-
-
- {{ range $categories }} - {{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "taxonomy") }} - {{ end }} -
+

{{ T "archives.categories" }}

+
+
+ {{ range $categories }} + {{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "taxonomy") }} + {{ end }}
{{ end }} @@ -21,7 +19,7 @@ {{ range $filtered.GroupByDate "2006" }} {{ $id := lower (replace .Key " " "-") }}
-

{{ .Key }}

+

{{ .Key }}

{{ range .Pages }} {{ partial "article-list/compact" . }} @@ -31,4 +29,4 @@ {{ end }} {{ partialCached "footer/footer" . }} -{{ end }} \ No newline at end of file +{{ end }} diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 21cdb4e..f4ad263 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -1,6 +1,9 @@ - {{- partial "head/head.html" . -}} + + {{- partial "head/head.html" . -}} + {{- block "head" . -}}{{ end }} + -
+
{{ partial "sidebar/left.html" . }}
{{- block "main" . }}{{- end }} diff --git a/layouts/_default/term.html b/layouts/_default/term.html index 3189e9a..3bfcc28 100644 --- a/layouts/_default/term.html +++ b/layouts/_default/term.html @@ -1,5 +1,5 @@ {{ define "main" }} -

{{ .Type | singularize | humanize }}

+

{{ .Type | singularize | humanize }}

{{ len .Pages }} post{{ if gt (len .Pages) 1 }}s{{ end }}

diff --git a/layouts/index.html b/layouts/index.html index 1811bd2..b04b926 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -15,5 +15,5 @@ {{ end }} {{ define "right-sidebar" }} - {{ partialCached "sidebar/right.html" . }} + {{ partial "sidebar/right.html" . }} {{ end }} \ No newline at end of file diff --git a/layouts/page/search.html b/layouts/page/search.html new file mode 100644 index 0000000..259d398 --- /dev/null +++ b/layouts/page/search.html @@ -0,0 +1,31 @@ +{{ define "body-class" }}template-search{{ end }} +{{ define "head" }} + {{- with .OutputFormats.Get "json" -}} + + {{- end -}} +{{ end }} +{{ define "main" }} +
+

+ + +

+ + +
+ +

+
+ + + +{{- $opts := dict "minify" hugo.IsProduction "JSXFactory" "createElement" -}} +{{- $searchScript := resources.Get "ts/search.tsx" | js.Build $opts -}} + + +{{ partialCached "footer/footer" . }} +{{ end }} \ No newline at end of file diff --git a/layouts/page/search.json b/layouts/page/search.json new file mode 100644 index 0000000..ce09a79 --- /dev/null +++ b/layouts/page/search.json @@ -0,0 +1,20 @@ +{{- $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections -}} +{{- $notHidden := where .Site.RegularPages "Params.hidden" "!=" true -}} +{{- $filtered := ($pages | intersect $notHidden) -}} + +{{- $result := slice -}} + +{{- range $filtered -}} + {{- $data := dict "title" .Title "date" .Date "permalink" .Permalink "content" (.Plain) -}} + + {{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}} + {{- if and $image.exists $image.resource -}} + {{- $thumbnail := $image.resource.Fill "120x120" -}} + {{- $image := dict "image" (absURL $thumbnail.Permalink) -}} + {{- $data = merge $data $image -}} + {{ end }} + + {{- $result = $result | append $data -}} +{{- end -}} + +{{ jsonify $result }} \ No newline at end of file diff --git a/layouts/partials/article-list/compact.html b/layouts/partials/article-list/compact.html index e9fa77d..cedef2a 100644 --- a/layouts/partials/article-list/compact.html +++ b/layouts/partials/article-list/compact.html @@ -1,27 +1,27 @@
-
-

- + +
+

{{- .Title -}} - -

-
- -
-
- - {{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}} - {{ if $image.exists }} -
- {{ if $image.resource }} - {{- $thumbnail := $image.resource.Fill "120x120" -}} - - {{ else }} - Featured image of post {{ .Title }} - {{ end }} +

+
+ +
- {{ end }} + + {{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}} + {{ if $image.exists }} +
+ {{ if $image.resource }} + {{- $thumbnail := $image.resource.Fill "120x120" -}} + + {{ else }} + Featured image of post {{ .Title }} + {{ end }} +
+ {{ end }} +
\ No newline at end of file diff --git a/layouts/partials/article-list/default.html b/layouts/partials/article-list/default.html index 106d8d6..aeb5bb1 100644 --- a/layouts/partials/article-list/default.html +++ b/layouts/partials/article-list/default.html @@ -2,7 +2,7 @@
{{ if $image.exists }}
- + {{ if $image.resource }} {{- $thumbnail := $image.resource.Fill "800x250" -}} {{- $thumbnailRetina := $image.resource.Fill "1600x500" -}} diff --git a/layouts/partials/article-list/tile.html b/layouts/partials/article-list/tile.html index 0edf2e5..f76f596 100644 --- a/layouts/partials/article-list/tile.html +++ b/layouts/partials/article-list/tile.html @@ -1,6 +1,6 @@ {{ $image := partialCached "helper/image" (dict "Context" .context "Type" .Type) .context.RelPermalink .Type }} \ No newline at end of file diff --git a/layouts/partials/article/components/details.html b/layouts/partials/article/components/details.html index 016e9d6..7650704 100644 --- a/layouts/partials/article/components/details.html +++ b/layouts/partials/article/components/details.html @@ -1,25 +1,28 @@ {{ $image := partialCached "helper/image" (dict "Context" . "Type" "article") .RelPermalink "article" }} {{- $context := . -}} -{{- $categories := .Params.categories -}}
- {{ if $categories }} + {{ if .Params.categories }} {{ end }}

- + {{- .Title -}}

@@ -32,7 +35,7 @@ {{- if not .Date.IsZero -}}