├── .eslintignore ├── .eslintrc ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── assets ├── fonts │ ├── Roboto-Medium.woff │ ├── Roboto-Medium.woff2 │ ├── Roboto-Regular.woff │ ├── Roboto-Regular.woff2 │ ├── Roboto-RegularItalic.woff │ ├── Roboto-RegularItalic.woff2 │ ├── fa-brands-400.eot │ ├── fa-brands-400.svg │ ├── fa-brands-400.ttf │ ├── fa-brands-400.woff │ ├── fa-brands-400.woff2 │ ├── fa-regular-400.eot │ ├── fa-regular-400.svg │ ├── fa-regular-400.ttf │ ├── fa-regular-400.woff │ ├── fa-regular-400.woff2 │ ├── fa-solid-900.eot │ ├── fa-solid-900.svg │ ├── fa-solid-900.ttf │ ├── fa-solid-900.woff │ ├── fa-solid-900.woff2 │ ├── lg.eot │ ├── lg.svg │ ├── lg.ttf │ └── lg.woff ├── img │ ├── fa-brands-400.svg │ ├── fa-regular-400.svg │ ├── fa-solid-900.svg │ ├── lg.svg │ ├── loading.gif │ ├── photo-1523980669340-3d154e47d5fd.jpg │ ├── sven-scheuermeier-178631-unsplash.jpg │ ├── video-play.png │ ├── vimeo-play.png │ └── youtube-play.png ├── scripts │ ├── grid.js │ ├── main-vendors.js │ ├── main-vendors.js.LICENSE.txt │ ├── main.js │ └── post.js └── styles │ ├── main.css │ └── post.css ├── author.hbs ├── babel.config.js ├── default.hbs ├── error-404.hbs ├── error.hbs ├── index.hbs ├── package.json ├── page.hbs ├── partials ├── byline-multiple.hbs ├── byline-single.hbs ├── feed-card.hbs ├── floating-header.hbs ├── footer.hbs ├── google_adsense.hbs ├── google_analytics.hbs ├── header.hbs ├── icons │ ├── avatar.hbs │ ├── facebook.hbs │ ├── ghost-logo.hbs │ ├── infinity.hbs │ ├── location.hbs │ ├── point.hbs │ ├── rss.hbs │ ├── twitter.hbs │ └── website.hbs ├── navigation.hbs ├── pagination.hbs ├── post-card.hbs ├── search.hbs ├── share-post.hbs ├── site-nav.hbs ├── spinkit.hbs └── subscribe_form.hbs ├── post.hbs ├── renovate.json ├── src ├── build │ ├── postcss.config.js │ ├── webpack.config.dev.js │ ├── webpack.config.js │ └── webpack.config.prod.js ├── img │ ├── credits.txt │ ├── photo-1523980669340-3d154e47d5fd.jpg │ └── sven-scheuermeier-178631-unsplash.jpg ├── scripts │ ├── app.ts │ ├── createScrollManager.ts │ ├── grid.ts │ ├── particles.json │ ├── post.ts │ └── search.ts ├── styles │ ├── _settings.scss │ ├── components │ │ ├── ads.scss │ │ ├── error.scss │ │ ├── fonts.scss │ │ ├── footer.scss │ │ ├── general.scss │ │ ├── header.scss │ │ ├── koenig.scss │ │ ├── lightbox.scss │ │ ├── main-content.scss │ │ ├── mixins.scss │ │ ├── pagination.scss │ │ ├── placeholder.scss │ │ ├── post-feed.scss │ │ ├── posts-list.scss │ │ ├── prismjs.scss │ │ ├── search.scss │ │ ├── spinkit.scss │ │ ├── tags.scss │ │ └── top-bar.scss │ ├── main.scss │ └── post.scss └── typings │ ├── @tryghost │ ├── content-api │ │ └── index.d.ts │ └── index.d.ts │ ├── colorthief │ └── index.d.ts │ ├── custom │ └── index.d.ts │ ├── ghost-search │ └── index.d.ts │ ├── ghost │ └── index.d.ts │ ├── lightgallery │ └── index.d.ts │ └── particles.js │ └── index.d.ts ├── tag.hbs ├── tsconfig.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | build/ 2 | babel.config.js -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "ecmaFeatures": { 5 | "jsx": false 6 | }, 7 | "ecmaVersion": 6, 8 | "tsconfigRootDir": ".", 9 | "project": "./tsconfig.json" 10 | }, 11 | "env": { 12 | "es6": true, 13 | "node": true, 14 | "browser": true, 15 | "jquery": true 16 | }, 17 | "plugins": ["@typescript-eslint", "prettier"], 18 | "extends": [ 19 | "jquery", 20 | "airbnb-base", 21 | "plugin:@typescript-eslint/recommended", 22 | "plugin:import/typescript", 23 | "plugin:prettier/recommended", 24 | "prettier/@typescript-eslint" 25 | ], 26 | "rules": { 27 | "indent": [ 28 | "error", 29 | 4 30 | ], 31 | "no-console": 0, 32 | "no-param-reassign": 0, 33 | "no-plusplus": [ 34 | "error", 35 | { 36 | "allowForLoopAfterthoughts": true 37 | } 38 | ], 39 | "spaced-comment": ["error", "always", { 40 | "line": { 41 | "markers": ["/"], 42 | "exceptions": ["-", "+"] 43 | }, 44 | "block": { 45 | "markers": ["!"], 46 | "exceptions": ["*"], 47 | "balanced": true 48 | } 49 | }], 50 | "no-unused-expressions": ["warn", { 51 | "allowShortCircuit": true, 52 | "allowTernary": true 53 | }], // https://eslint.org/docs/rules/no-unused-expressions 54 | "no-trailing-spaces": [2, { "skipBlankLines": true }], 55 | "prefer-template": 0, 56 | "import/extensions": 0, 57 | "lines-between-class-members": 0, 58 | "@typescript-eslint/prefer-interface": "off", // also want to use "type" 59 | "@typescript-eslint/explicit-function-return-type": "off", // annoying to force return type 60 | "@typescript-eslint/explicit-member-accessibility": "off", 61 | "@typescript-eslint/no-non-null-assertion": "off", 62 | "@typescript-eslint/no-var-requires": "off", 63 | "@typescript-eslint/ban-ts-ignore": "off" 64 | } 65 | } -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node: [ '12' ] 14 | name: Node ${{ matrix.node }} 15 | steps: 16 | - uses: actions/checkout@v1 17 | - name: Cache node modules 18 | uses: actions/cache@v1 19 | with: 20 | path: node_modules 21 | key: ${{ runner.OS }}-build-${{ hashFiles('**/yarn.lock') }} 22 | restore-keys: | 23 | ${{ runner.OS }}-build-${{ env.cache-name }}- 24 | ${{ runner.OS }}-build- 25 | ${{ runner.OS }}- 26 | - name: Setup node 27 | uses: actions/setup-node@v1 28 | with: 29 | node-version: ${{ matrix.node }} 30 | - run: npm install yarn 31 | - run: yarn install 32 | - run: yarn lint 33 | - run: yarn build 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Cruft 2 | *~ 3 | *# 4 | .#* 5 | .DS_Store 6 | 7 | # Logs 8 | logs 9 | *.log 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | .firebase 20 | 21 | # dependencies 22 | /node_modules 23 | /.pnp 24 | .pnp.js 25 | 26 | # testing 27 | tests/__coverage__/ 28 | tests/**/*.jsx 29 | 30 | # production 31 | /dist 32 | /build 33 | /scenarios 34 | src/**/*.jsx 35 | 36 | # misc 37 | .DS_Store 38 | .env.local 39 | .env.development.local 40 | .env.test.local 41 | .env.production.local 42 | 43 | npm-debug.log* 44 | yarn-debug.log* 45 | yarn-error.log* 46 | package-lock.json 47 | 48 | # Editor 49 | .idea/ 50 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | assets/ 2 | src/build/ 3 | node_modules/ 4 | package-lock.json 5 | yarn.lock 6 | package.json 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 4, 4 | "singleQuote": true, 5 | "htmlWhitespaceSensitivity": "css", 6 | "jsxBracketSameLine": true, 7 | "overrides": [ 8 | { 9 | "files": "*.css", 10 | "options": { 11 | "tabWidth": 2 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 William Díaz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CUSCA 2 | 3 | [](https://opensource.org/licenses/MIT) 4 | [](https://github.com/wdiazux/cusca/actions?query=workflow%3ATest) 5 | [](https://paypal.me/wdiazux) 6 | 7 | A responsive theme for [Ghost 3.x](https://ghost.org). 8 | 9 | **What that mean CUSCA?** 10 | 11 | Is the abbreviation for Cuscatlán, it was the name of El Salvador before the conquest and means "the land of precious things" in Nahuatl. 12 | 13 | --- 14 | 15 | ## Introduction 16 | 17 | Cusca was development using [Foundation](http://foundation.zurb.com) as base, the style is generated with 18 | [Sass](https://sass-lang.com) and the javascript is generated with [Typescript](https://www.typescriptlang.org) and 19 | other cool stuff that comes from different libraries: 20 | 21 | - [Shuffle](https://vestride.github.io/Shuffle/) 22 | - [LightGallery.js](https://sachinchoolur.github.io/lightgallery.js/) 23 | - [FontAwesome](http://fontawesome.io) 24 | - [Prism.js](http://prismjs.com) 25 | - [Color Thief](https://lokeshdhakar.com/projects/color-thief/) 26 | - [Particles.js](https://vincentgarreau.com/particles.js/) 27 | - [Ghost Search](https://github.com/HauntedThemes/ghost-search) 28 | 29 | All the help to contribute to the development or improvement of the theme is welcomed. 30 | 31 | ## Installation 32 | 33 | Inside the Ghost themes folder (content/themes) you have to clone the repository or download the last version: 34 | 35 | :anchor: [Last release](https://github.com/wdiazux/cusca/releases/latest) 36 | 37 | ```bash 38 | git clone https://github.com/wdiazux/cusca.git 39 | ``` 40 | 41 | ## Setup 42 | 43 | ### Disqus 44 | 45 | Inside the `post.hbs` file you need to replace `[your-disqus-name]` with your Disqus name: 46 | 47 | ```javascript 48 | (function() { // DON'T EDIT BELOW THIS LINE 49 | var d = document, s = d.createElement('script'); 50 | s.async = true; 51 | s.src = 'https://[your-disqus-name].disqus.com/embed.js'; 52 | s.setAttribute('data-timestamp', +new Date()); 53 | (d.head || d.body).appendChild(s); 54 | })(); 55 | ``` 56 | 57 | Do the same for `partials/loop.hbs`: 58 | 59 | ```html 60 | 61 | ``` 62 | 63 | ### Search 64 | 65 | The new release of the Ghost API v3, require extra steps that are **NECESSARY** for the 66 | search functionality: 67 | 68 | - Go in your Ghost's dashboard -> Integrations -> Add custom integration 69 | - Set a name: Themes Search 70 | - Get the `Content API Key` and replace the demo key with this one 71 | - Do the same with the `API URL` 72 | 73 | The file to modify with this credentials is `src/scripts/app.ts` 74 | and at the end of the document is the Search section, and the parameter you 75 | need to change are the URL and Key from the GhostSearch class. 76 | 77 | ```javascript 78 | const ghostSearch = new GhostSearch({ 79 | url: 'http://localhost:2368', 80 | key: '4f1476d8df3a9cd277b2273b6e', 81 | }); 82 | ``` 83 | 84 | You will need to rebuild the theme to make it work after modifying the parameters. In 85 | the end of this page you will find the commands that you need to do it. 86 | 87 | ### Social Icons 88 | 89 | Inside the `partials/footer.hbs` file replace `[your-user]` with your user names for each social network: 90 | 91 | ```html 92 |
Ref: {{ref}}
42 |Message: {{message}}
43 | {{/foreach}} 44 |{{excerpt words="15"}}[...]
34 |{{excerpt words="33"}}
36 |styles for code cards with captions */ 109 | 110 | .kg-code-card { 111 | width: 100%; 112 | 113 | pre { 114 | margin: 0; 115 | } 116 | } 117 | 118 | .kg-bookmark-card { 119 | width: 100%; 120 | background: var(--white); 121 | } 122 | 123 | .kg-card + .kg-bookmark-card { 124 | margin-top: 0; 125 | } 126 | 127 | .post-full-content .kg-bookmark-container { 128 | display: flex; 129 | min-height: 148px; 130 | color: var(--darkgrey); 131 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; 132 | text-decoration: none; 133 | border-radius: 3px; 134 | box-shadow: 0 2px 5px -1px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0, 0, 0, 0.09); 135 | 136 | &:hover { 137 | color: var(--darkgrey); 138 | text-decoration: none; 139 | box-shadow: 0 2px 5px -1px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0, 0, 0, 0.09); 140 | } 141 | } 142 | 143 | .kg-bookmark-content { 144 | flex-grow: 1; 145 | display: flex; 146 | flex-direction: column; 147 | justify-content: flex-start; 148 | align-items: flex-start; 149 | padding: 20px; 150 | } 151 | 152 | .kg-bookmark-title { 153 | color: color(var(--midgrey) l(-30%)); 154 | font-size: 1.6rem; 155 | line-height: 1.5em; 156 | font-weight: 600; 157 | transition: color 0.2s ease-in-out; 158 | } 159 | 160 | .post-full-content .kg-bookmark-container:hover .kg-bookmark-title { 161 | color: var(--blue); 162 | } 163 | 164 | .kg-bookmark-description { 165 | display: -webkit-box; 166 | overflow-y: hidden; 167 | margin-top: 12px; 168 | max-height: 48px; 169 | color: color(var(--midgrey) l(-10%)); 170 | font-size: 1.5rem; 171 | line-height: 1.5em; 172 | font-weight: 400; 173 | -webkit-line-clamp: 2; 174 | -webkit-box-orient: vertical; 175 | } 176 | 177 | .kg-bookmark-thumbnail { 178 | position: relative; 179 | min-width: 33%; 180 | max-height: 100%; 181 | 182 | img { 183 | position: absolute; 184 | top: 0; 185 | left: 0; 186 | width: 100%; 187 | height: 100%; 188 | border-radius: 0 3px 3px 0; 189 | object-fit: cover; 190 | } 191 | } 192 | 193 | .kg-bookmark-metadata { 194 | display: flex; 195 | flex-wrap: wrap; 196 | align-items: center; 197 | margin-top: 14px; 198 | color: color(var(--midgrey) l(-10%)); 199 | font-size: 1.5rem; 200 | font-weight: 400; 201 | } 202 | 203 | .post-full-content .kg-bookmark-icon { 204 | margin-right: 8px; 205 | width: 22px; 206 | height: 22px; 207 | } 208 | 209 | .kg-bookmark-author { 210 | line-height: 1.5em; 211 | 212 | &:after { 213 | content: "•"; 214 | margin: 0 6px; 215 | } 216 | } 217 | 218 | .kg-bookmark-publisher { 219 | overflow: hidden; 220 | max-width: 240px; 221 | line-height: 1.5em; 222 | text-overflow: ellipsis; 223 | white-space: nowrap; 224 | } 225 | 226 | @media (max-width: 800px) { 227 | .post-full-content { 228 | figure { 229 | margin: 0.2em 0 1.3em; 230 | } 231 | 232 | h1 + figure, h2 + figure, h3 + figure, h4 + figure { 233 | margin-top: 0.9em; 234 | } 235 | } 236 | } 237 | 238 | @media (max-width: 500px) { 239 | .post-full-content { 240 | .kg-width-wide, .kg-width-full { 241 | margin-right: -5vw; 242 | margin-left: -5vw; 243 | } 244 | 245 | figcaption { 246 | margin-bottom: 0.4em; 247 | } 248 | 249 | .kg-bookmark-container { 250 | flex-direction: column; 251 | } 252 | } 253 | 254 | .kg-bookmark-title, .kg-bookmark-description, .kg-bookmark-metadata { 255 | font-size: 1.4rem; 256 | line-height: 1.5em; 257 | } 258 | 259 | .post-full-content .kg-bookmark-icon { 260 | width: 18px; 261 | height: 18px; 262 | } 263 | 264 | .kg-bookmark-thumbnail { 265 | order: 1; 266 | min-height: 160px; 267 | width: 100%; 268 | 269 | img { 270 | border-radius: 3px 3px 0 0; 271 | } 272 | } 273 | 274 | .kg-bookmark-content { 275 | order: 2; 276 | } 277 | } -------------------------------------------------------------------------------- /src/styles/components/lightbox.scss: -------------------------------------------------------------------------------- 1 | // Fancybox 2 | // -------- 3 | 4 | $lg-path-fonts: '~lightgallery.js/src/fonts'; 5 | $lg-path-images: '~lightgallery.js/src/img'; 6 | 7 | @import '~lightgallery.js/src/sass/lightgallery'; 8 | 9 | .lightbox { 10 | display: inline-block; 11 | max-width: 100%; 12 | 13 | img { 14 | flex-shrink: 0; 15 | cursor: pointer; 16 | cursor: -moz-zoom-in; 17 | cursor: zoom-in; 18 | } 19 | } -------------------------------------------------------------------------------- /src/styles/components/main-content.scss: -------------------------------------------------------------------------------- 1 | .main-content { 2 | padding: 3rem 0 3rem 0; 3 | background: #f0f0f0; 4 | } 5 | 6 | .post-template .main-content, 7 | .page-template .main-content { 8 | background: #fff; 9 | } 10 | 11 | .post-template .main-content { 12 | padding: 3rem 0 0 0; 13 | } 14 | -------------------------------------------------------------------------------- /src/styles/components/mixins.scss: -------------------------------------------------------------------------------- 1 | %body-color-anchor { 2 | color: $body-font-color; 3 | &:hover, 4 | &:focus { 5 | color: $anchor-color-hover; 6 | } 7 | } 8 | @mixin word-wrap() { 9 | overflow-wrap: break-word; 10 | word-wrap: break-word; 11 | -ms-word-break: break-all; 12 | word-break: break-all; 13 | word-break: break-word; 14 | -ms-hyphens: auto; 15 | -moz-hyphens: auto; 16 | -webkit-hyphens: auto; 17 | hyphens: auto; 18 | } 19 | -------------------------------------------------------------------------------- /src/styles/components/pagination.scss: -------------------------------------------------------------------------------- 1 | // Pagination 2 | // --------- 3 | 4 | .pagination-ct { 5 | align-items: center; 6 | justify-content: center; 7 | } 8 | 9 | %arrow-prev { 10 | &:after { 11 | content: ""; 12 | position: absolute; 13 | top: 0; 14 | left: -22px; 15 | width: 0; 16 | height: 0; 17 | border-top: 22px solid transparent; 18 | border-bottom: 22px solid transparent; 19 | border-right: 22px solid #fff; 20 | transition: all 0.2s linear; 21 | } 22 | } 23 | 24 | %arrow-next { 25 | &:after { 26 | content: ""; 27 | position: absolute; 28 | top: 0; 29 | right: -22px; 30 | width: 0; 31 | height: 0; 32 | border-top: 22px solid transparent; 33 | border-bottom: 22px solid transparent; 34 | border-left: 22px solid #fff; 35 | transition: all 0.2s linear; 36 | } 37 | } 38 | .pagination { 39 | display: inline-flex; 40 | margin: 2rem 0 2rem 0; 41 | 42 | a, 43 | button, 44 | .current, 45 | .disabled { 46 | padding: rem-calc(9 15); 47 | } 48 | 49 | li { 50 | position: relative; 51 | margin-right: - rem-calc(2); 52 | font-size: rem-calc(16); 53 | 54 | a { 55 | display: inline-block; 56 | position: relative; 57 | border: 1px solid #ddd; 58 | background: $white; 59 | transition: all 0.2s linear; 60 | } 61 | 62 | &:not(:last-child) { 63 | border-right: 1px solid $medium-gray; 64 | } 65 | &:not(:first-child) { 66 | a { 67 | margin-left: -1px; 68 | } 69 | } 70 | &.pagination-previous { 71 | border-top-left-radius: 2px; 72 | border-bottom-left-radius: 2px; 73 | } 74 | &.pagination-next { 75 | border-top-right-radius: 2px; 76 | border-bottom-right-radius: 2px; 77 | } 78 | &.current { 79 | z-index: 2; 80 | } 81 | &.ellipsis { 82 | padding: rem-calc(9 5); 83 | background: $white; 84 | border: 1px solid #ddd; 85 | } 86 | } 87 | 88 | // Previous arrow 89 | .pagination-previous { 90 | a, 91 | &.disabled { 92 | &:before { 93 | content: ""; 94 | } 95 | margin-left: 22px; 96 | @extend %arrow-prev; 97 | } 98 | a:hover { 99 | &:after { 100 | border-right: 22px solid $pagination-item-background-hover; 101 | } 102 | } 103 | &.disabled { 104 | background: $white; 105 | } 106 | } 107 | 108 | // Next arrow 109 | .pagination-next { 110 | a, 111 | &.disabled { 112 | &:before { 113 | content: ""; 114 | } 115 | margin-right: 22px; 116 | @extend %arrow-next; 117 | } 118 | 119 | a:hover { 120 | &:after { 121 | border-left: 22px solid $pagination-item-background-hover; 122 | } 123 | } 124 | &.disabled { 125 | background: $white; 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/styles/components/placeholder.scss: -------------------------------------------------------------------------------- 1 | %animated-background { 2 | position: absolute; 3 | background: #dcdcdc; 4 | background: linear-gradient(to right, #dcdcdc 8%, #d1d1d1 18%, #dcdcdc 33%); 5 | background-size: 800px 104px; 6 | z-index: 5; 7 | animation-duration: 1.25s; 8 | animation-fill-mode: forwards; 9 | animation-iteration-count: infinite; 10 | animation-name: placeHolderShimmer; 11 | animation-timing-function: linear; 12 | } 13 | 14 | .placeholder { 15 | @extend %animated-background; 16 | } 17 | 18 | .placeholder-featured-image { 19 | width: 100%; 20 | height: 100%; 21 | min-height: 220px; 22 | top: 0; 23 | left: 0; 24 | } 25 | 26 | .placeholder-content-ct { 27 | position: absolute; 28 | width: 100%; 29 | height: 100%; 30 | padding: .75rem; 31 | min-height: 180px; 32 | top: 0; 33 | left: 0; 34 | background: #fff; 35 | z-index: 5; 36 | } 37 | 38 | .placeholder-content-inner { 39 | position: relative; 40 | width: 100%; 41 | height: 100%; 42 | } 43 | 44 | .placeholder-title { 45 | @extend %animated-background; 46 | width: 80%; 47 | height: rem-calc(25); 48 | } 49 | 50 | .placeholder-text { 51 | @extend %animated-background; 52 | width: 100%; 53 | height: rem-calc(17); 54 | } 55 | 56 | .placeholder-text1 { 57 | top: rem-calc(40); 58 | } 59 | 60 | .placeholder-text2 { 61 | top: rem-calc(70); 62 | } 63 | 64 | .placeholder-text3 { 65 | width: 40%; 66 | top: rem-calc(100); 67 | } 68 | 69 | .placeholder-author { 70 | @extend %animated-background; 71 | width: 80px; 72 | height: rem-calc(15); 73 | bottom: 0; 74 | left: 0; 75 | } 76 | 77 | .placeholder-date { 78 | @extend %animated-background; 79 | width: 80px; 80 | height: rem-calc(15); 81 | bottom: 0; 82 | right: 0; 83 | } 84 | 85 | // Animation 86 | @keyframes placeHolderShimmer { 87 | 0% { 88 | background-position: -468px 0 89 | } 90 | 100% { 91 | background-position: 468px 0 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/styles/components/post-feed.scss: -------------------------------------------------------------------------------- 1 | .read-next { 2 | .post-card { 3 | display: flex; 4 | position: relative; 5 | margin: 0 0 2rem 0; 6 | flex: 1 1 250px; 7 | flex-direction: column; 8 | 9 | @include breakpoint(medium) { 10 | &:first-child { 11 | margin: 0 2rem 2rem 0; 12 | } 13 | &:last-child { 14 | margin: 0 0 2rem 0; 15 | } 16 | } 17 | @include breakpoint(large) { 18 | margin: 0 2rem 2rem 0; 19 | 20 | &:last-child { 21 | margin: 0 0 2rem 0; 22 | } 23 | } 24 | } 25 | .post-card-content, 26 | .post-card-inner { 27 | display: flex; 28 | flex-grow: 1; 29 | flex-direction: column; 30 | justify-content: space-between; 31 | } 32 | 33 | 34 | .post-card-featured-image { 35 | &:hover, 36 | &:focus { 37 | .post-card-image { 38 | img { 39 | transform: matrix(1.2,0,0,1.2,0,0) translateY(-50%); 40 | } 41 | } 42 | } 43 | .tags { 44 | max-height: calc(100% - 10px); 45 | } 46 | } 47 | .post-card-image { 48 | height: 135px; 49 | img { 50 | position: absolute; 51 | top: 50%; 52 | transform: translateY(-50%); 53 | } 54 | } 55 | } 56 | 57 | .read-next-card { 58 | color: $white; 59 | border-radius: 5px; 60 | overflow: hidden; 61 | 62 | &:before { 63 | content: ""; 64 | position: absolute; 65 | top: 0; 66 | right: 0; 67 | bottom: 0; 68 | left: 0; 69 | display: block; 70 | background: linear-gradient(135deg, rgba(26,41,64,.95), rgba(26,41,64,.85)); 71 | } 72 | .post-card-inner { 73 | background: none; 74 | } 75 | a { 76 | color: $white; 77 | 78 | &:hover, 79 | &:focus { 80 | color: $white; 81 | } 82 | } 83 | } 84 | 85 | .related-articles { 86 | display: flex; 87 | flex-flow: row wrap; 88 | } 89 | 90 | .read-next-card-header-title { 91 | text-align: center; 92 | text-transform: uppercase; 93 | font-weight: 500; 94 | 95 | i { 96 | font-size: 70%; 97 | } 98 | } 99 | .read-next-card-content { 100 | ul { 101 | margin: 0; 102 | list-style: none; 103 | > li { 104 | a { 105 | display: block; 106 | max-width: 86%; 107 | margin-left: 7%; 108 | padding: rem-calc(15 0); 109 | text-align: center; 110 | font-weight: 500; 111 | border-bottom: 1px solid hsla(0,0%,100%,.3); 112 | white-space: nowrap; 113 | overflow: hidden; 114 | text-overflow: ellipsis; 115 | } 116 | } 117 | } 118 | } 119 | 120 | .read-next-card-footer { 121 | position: relative; 122 | margin: rem-calc(15 0 3); 123 | text-align: center; 124 | } 125 | -------------------------------------------------------------------------------- /src/styles/components/posts-list.scss: -------------------------------------------------------------------------------- 1 | .post-card { 2 | a { 3 | @extend %body-color-anchor; 4 | } 5 | } 6 | .post-card-content { 7 | position: relative; 8 | padding: 0.75rem; 9 | } 10 | .post-card-inner { 11 | position: relative; 12 | border-radius: 5px; 13 | overflow: hidden; 14 | } 15 | .post-card-meta { 16 | display: flex; 17 | flex-flow: row wrap; 18 | justify-content: space-between; 19 | align-items: flex-end; 20 | font-size: rem-calc(13); 21 | 22 | > * { 23 | flex: 0 0 auto; 24 | } 25 | } 26 | .post-card-inner { 27 | background: $white; 28 | } 29 | .post-card-featured-image { 30 | position: relative; 31 | &:hover, 32 | &:focus { 33 | .post-card-image { 34 | img { 35 | transform: matrix(1.2,0,0,1.2,0,0) 36 | } 37 | &:before { 38 | opacity: 1; 39 | } 40 | } 41 | } 42 | } 43 | .post-card-image { 44 | position: relative; 45 | overflow: hidden; 46 | width: 100%; 47 | 48 | img { 49 | display: block; 50 | width: 100%; 51 | height: auto; 52 | outline: 0; 53 | border: none; 54 | transition: all 0.3s ease-in-out; 55 | } 56 | 57 | &:before { 58 | position: absolute; 59 | content: " "; 60 | top: 0; 61 | left: 0; 62 | width: 100%; 63 | height: 100%; 64 | opacity: 0; 65 | z-index: 1; 66 | background: rgba(0, 0, 0, 0.6); 67 | transition: all 0.3s ease-in-out; 68 | } 69 | } 70 | .loading-cards .post-card-featured-image { 71 | min-height: 220px; 72 | } 73 | .loading-cards .post-card-content { 74 | min-height: 180px; 75 | } 76 | .post-card-ex { 77 | position: absolute; 78 | opacity: 0; 79 | visibility: hidden; 80 | max-height: 10px; 81 | z-index: -100; 82 | } 83 | .author-list { 84 | display: inline-flex; 85 | margin: 0; 86 | } 87 | .author-list-item { 88 | display: inline-flex; 89 | position: relative; 90 | margin-right: rem-calc(5); 91 | 92 | &:last-child { 93 | margin-right: 0; 94 | } 95 | 96 | > a { 97 | display: inline-flex; 98 | position: relative; 99 | align-items: center; 100 | } 101 | } 102 | .static-avatar { 103 | display: inline-block; 104 | margin: 0 5px 0 0; 105 | width: 16px; 106 | height: 16px; 107 | border-radius: 50%; 108 | overflow: hidden; 109 | background: $primary-color; 110 | } 111 | 112 | // Animation 113 | // --------- 114 | 115 | .post-feed { 116 | position: relative; 117 | min-height: 200px; 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/styles/components/prismjs.scss: -------------------------------------------------------------------------------- 1 | // PrismJS 2 | // ------- 3 | 4 | @import "~prismjs/plugins/line-highlight/prism-line-highlight"; 5 | @import "~prismjs/themes/prism-tomorrow"; 6 | 7 | // Variables 8 | // --------- 9 | 10 | $code-color: #e83e8c; 11 | $code-font-size: 90%; 12 | 13 | 14 | // pre code 15 | // -------- 16 | 17 | pre:not([class*=language-]), 18 | pre[class*=language-] { 19 | margin-top: 0; 20 | } 21 | 22 | pre:not([class*=language-]) { 23 | @extend pre[class*="language-"]; 24 | padding: rem-calc(12 16); 25 | font-family: inherit; 26 | 27 | code { 28 | background-color: transparent; 29 | color: inherit; 30 | } 31 | } 32 | 33 | pre > code { 34 | font-size: $code-font-size; 35 | padding: 0; 36 | } 37 | 38 | 39 | // Code 40 | // ---- 41 | :not(pre) > code { 42 | word-break: break-word; 43 | font-size: $code-font-size; 44 | } 45 | -------------------------------------------------------------------------------- /src/styles/components/search.scss: -------------------------------------------------------------------------------- 1 | $header-background: #1a2940; 2 | $header-font-color: #91a2bd; 3 | 4 | .search { 5 | display: none; 6 | position: fixed; 7 | top: 0; 8 | left: 0; 9 | width: 100%; 10 | height: 100%; 11 | overflow: hidden; 12 | background: rgba($header-background, 0.96); 13 | z-index: 500; 14 | } 15 | 16 | .close-search { 17 | position: absolute; 18 | padding: 5px; 19 | width: 55px; 20 | height: 60px; 21 | top: 0; 22 | right: 0; 23 | font-size: 30px; 24 | color: $white; 25 | text-align: center; 26 | } 27 | .close-overlay { 28 | position: absolute; 29 | width: 100%; 30 | height: 100%; 31 | top: 0; 32 | left: 0; 33 | cursor: pointer; 34 | background: rgba(255, 255, 255, 0); 35 | } 36 | 37 | .search-container { 38 | position: absolute; 39 | width: 100%; 40 | max-width: 90%; 41 | top: 50%; 42 | left: 0; 43 | right: 0; 44 | margin: 0 auto; 45 | transform: translateY(-50%); 46 | transition: all 0.8s ease; 47 | 48 | @include breakpoint(medium) { 49 | max-width: 35rem; 50 | } 51 | @include breakpoint(large) { 52 | max-width: 50rem; 53 | } 54 | } 55 | .search-container.dirty { 56 | height: 65%; 57 | } 58 | .search-wrapper { 59 | display: flex; 60 | flex-flow: column nowrap; 61 | align-items: center; 62 | justify-content: center; 63 | max-height: 100%; 64 | } 65 | .search-input-ct { 66 | position: relative; 67 | width: 100%; 68 | 69 | &:before { 70 | position: absolute; 71 | top: 0.9rem; 72 | left: 0.8rem; 73 | font-size: 1.5rem; 74 | font-family: "Font Awesome 5 Free"; 75 | font-weight: 900; 76 | content: "\f002"; 77 | color: $header-font-color; 78 | } 79 | } 80 | .search-input { 81 | height: 4rem; 82 | padding: 1rem 1rem 1rem 3rem; 83 | color: $white; 84 | background: rgba(0, 0, 0, 0.1); 85 | border: 1px solid $header-font-color; 86 | 87 | &:hover, 88 | &:focus { 89 | background: rgba(0, 0, 0, 0.1); 90 | border: 1px solid $header-font-color; 91 | } 92 | &::placeholder { 93 | color: $header-font-color; 94 | } 95 | } 96 | .search-results { 97 | display: flex; 98 | width: 100%; 99 | overflow-y: auto; 100 | } 101 | .results-list { 102 | width: 100%; 103 | margin: 0; 104 | list-style: none; 105 | 106 | li { 107 | &:last-child > a { 108 | border-bottom: none; 109 | } 110 | } 111 | 112 | a { 113 | display: block; 114 | padding: rem-calc(15); 115 | text-align: center; 116 | color: $header-font-color; 117 | border-bottom: 1px solid $header-font-color; 118 | background-color: rgba(255, 255, 255, 0); 119 | transition: background-color 0.5s ease; 120 | 121 | &:hover, 122 | &:focus { 123 | color: $white; 124 | background-color: rgba(255, 255, 255, 0.14); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/styles/components/spinkit.scss: -------------------------------------------------------------------------------- 1 | .sk-cube-grid { 2 | position: absolute; 3 | width: 40px; 4 | height: 40px; 5 | left: 0; 6 | right: 0; 7 | margin: 0 auto; 8 | opacity: 1; 9 | transition: opacity 0.6s ease; 10 | 11 | .sk-cube { 12 | width: 33%; 13 | height: 33%; 14 | background-color: #1a2940; 15 | float: left; 16 | animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out; 17 | } 18 | .sk-cube1 { 19 | animation-delay: 0.2s; 20 | } 21 | .sk-cube2 { 22 | animation-delay: 0.3s; 23 | } 24 | .sk-cube3 { 25 | animation-delay: 0.4s; 26 | } 27 | .sk-cube4 { 28 | animation-delay: 0.1s; 29 | } 30 | .sk-cube5 { 31 | animation-delay: 0.2s; 32 | } 33 | .sk-cube6 { 34 | animation-delay: 0.3s; 35 | } 36 | .sk-cube7 { 37 | animation-delay: 0s; 38 | } 39 | .sk-cube8 { 40 | animation-delay: 0.1s; 41 | } 42 | .sk-cube9 { 43 | animation-delay: 0.2s; 44 | } 45 | } 46 | .post-feed .sk-cube-grid { 47 | position: absolute; 48 | top: 4rem; 49 | left: 0; 50 | right: 0; 51 | margin: 0 auto; 52 | } 53 | .post-full-image .sk-cube-grid { 54 | top: 50%; 55 | transform: translateY(-50%); 56 | } 57 | 58 | .loaded .sk-cube-grid { 59 | opacity: 0; 60 | } 61 | 62 | @keyframes sk-cubeGridScaleDelay { 63 | 0%, 70%, 100% { 64 | transform: scale3D(1, 1, 1); 65 | } 66 | 67 | 35% { 68 | transform: scale3D(0, 0, 1); 69 | } 70 | } -------------------------------------------------------------------------------- /src/styles/components/tags.scss: -------------------------------------------------------------------------------- 1 | .tags { 2 | display: block; 3 | position: relative; 4 | margin: 0 0 10px 0; 5 | list-style: none; 6 | font-weight: 700; 7 | z-index: 2; 8 | 9 | li { 10 | display: inline-block; 11 | margin: 0 4px 2px 0; 12 | transition: all 0.3s ease-in-out; 13 | 14 | &:last-child { 15 | margin: 0; 16 | } 17 | 18 | a { 19 | display: inline-block; 20 | padding: 2px 5px; 21 | border: 1px solid rgba($body-font-color, .8); 22 | border-radius: 2px; 23 | font-size: rem-calc(11); 24 | text-transform: uppercase; 25 | color: rgba($body-font-color, .8); 26 | text-decoration: none; 27 | transition: all 0.3s ease-in-out; 28 | 29 | &:hover, 30 | &:focus { 31 | color: $white; 32 | background: rgba($body-font-color, .8); 33 | } 34 | } 35 | } 36 | } 37 | 38 | .post-card-tags-ct { 39 | display: flex; 40 | width: 100%; 41 | } 42 | 43 | .post-card-featured-image .tags { 44 | display: inline-block; 45 | position: absolute; 46 | margin: 0; 47 | top: 10px; 48 | left: 10px; 49 | overflow: hidden; 50 | max-width: calc(100% - 50px); 51 | max-height: calc(100% - 50px); 52 | 53 | &:hover { 54 | overflow-y: auto; 55 | } 56 | 57 | li { 58 | display: list-item; 59 | opacity: 0; 60 | visibility: hidden; 61 | 62 | &:first-child { 63 | opacity: 1; 64 | visibility: visible; 65 | } 66 | 67 | a { 68 | border: 1px solid $white; 69 | color: $white; 70 | text-decoration: none; 71 | background: rgba(0,0,0,0.2); 72 | 73 | &:hover, 74 | &:focus { 75 | color: $black; 76 | background: $white; 77 | } 78 | } 79 | } 80 | } 81 | 82 | .post-card-featured-image:hover .tags li, 83 | .post-card-featured-image:focus .tags li { 84 | opacity: 1; 85 | visibility: visible; 86 | } 87 | -------------------------------------------------------------------------------- /src/styles/components/top-bar.scss: -------------------------------------------------------------------------------- 1 | // Variables 2 | // --------- 3 | $header-background: #1a2940; 4 | $header-font-color: #91a2bd; 5 | 6 | .sticky { 7 | width: 100%; 8 | top: 0 !important; 9 | 10 | &.is-stuck { 11 | z-index: 100; 12 | } 13 | &.is-anchored { 14 | position: fixed; 15 | } 16 | } 17 | 18 | .top-bar { 19 | color: $header-font-color; 20 | transition: transform 1ms ease-out; 21 | z-index: 100; 22 | 23 | a, 24 | .bar-icon, 25 | .search-icon { 26 | color: $header-font-color; 27 | 28 | &:focus, 29 | &:hover { 30 | color: $white; 31 | } 32 | } 33 | 34 | .top-bar-title { 35 | opacity: 0; 36 | visibility: hidden; 37 | transition: all 0.3s ease; 38 | } 39 | 40 | .site-logo { 41 | height: 35px; 42 | } 43 | 44 | .mobile-buttons { 45 | display: block; 46 | 47 | @include breakpoint(large up) { 48 | display: none; 49 | } 50 | } 51 | 52 | .bar-icon, 53 | .mobile-buttons .search-icon { 54 | font-size: rem-calc(25); 55 | cursor: pointer; 56 | } 57 | 58 | .search-hot { 59 | text-align: center; 60 | text-transform: uppercase; 61 | font-weight: 700; 62 | cursor: pointer; 63 | user-select: none; 64 | 65 | &:hover, 66 | &:focus { 67 | color: #fff; 68 | } 69 | } 70 | 71 | .mobile-buttons .search-hot { 72 | margin-right: rem-calc(0); 73 | } 74 | 75 | .search-icon { 76 | padding: .7rem 1rem; 77 | cursor: pointer; 78 | } 79 | 80 | @include breakpoint(large) { 81 | .search-menu-text { 82 | display: none; 83 | } 84 | } 85 | } 86 | 87 | 88 | .bg .top-bar { 89 | background: rgba($header-background, 0.95); 90 | 91 | .top-bar-title { 92 | opacity: 1; 93 | visibility: visible; 94 | } 95 | } 96 | 97 | .top-bar-left, 98 | .top-bar-right { 99 | padding: rem-calc(10 0); 100 | } 101 | 102 | .top-bar-left { 103 | display: flex; 104 | justify-content: space-between; 105 | align-items: center; 106 | } 107 | 108 | .top-bar-right { 109 | max-height: 200px; 110 | overflow-y: auto; 111 | 112 | @include breakpoint(medium down) { 113 | display: none; 114 | padding-top: 0; 115 | } 116 | } 117 | 118 | .top-menu { 119 | justify-content: flex-end; 120 | 121 | .menu-item { 122 | a { 123 | text-transform: uppercase; 124 | font-weight: bold; 125 | } 126 | 127 | @include breakpoint(medium down) { 128 | &.nav-search { 129 | display: none; 130 | } 131 | a { 132 | text-align: center; 133 | border-bottom: 1px solid $header-font-color; 134 | 135 | &:hover, 136 | &:focus { 137 | border-color: $white; 138 | } 139 | } 140 | &:first-child a { 141 | padding-top: 0; 142 | } 143 | &:nth-last-child(2) a { 144 | border-bottom: none; 145 | } 146 | } 147 | } 148 | } 149 | 150 | .top-bar .top-bar-title { 151 | color: $white; 152 | font-size: rem-calc(24); 153 | font-weight: bold; 154 | } 155 | -------------------------------------------------------------------------------- /src/styles/main.scss: -------------------------------------------------------------------------------- 1 | /* Table of Contents 2 | /* ------------------------------------------------------------ 3 | 4 | This is a development CSS file which is built to a minified 5 | production stylesheet in assets/built/screen.css 6 | 7 | 1. Global Styles 8 | 2. Layout 9 | 3. Special Templates 10 | 4. Site Header 11 | 5. Site Navigation 12 | 6. Post Feed 13 | 7. Single Post 14 | 7.1. Subscribe Form 15 | 7.2. Post Footer 16 | 7.2.1 Single Author Byline 17 | 7.2.2 Multiple Author Byline 18 | 7.3. Comments 19 | 7.4. Related Posts 20 | 7.5. Floating Header 21 | 7.6. Koenig Styles 22 | 8. Author Template 23 | 9. Error Template 24 | 10. Subscribe Overlay 25 | 11. Site Footer 26 | 27 | */ 28 | 29 | @import 'components/fonts'; 30 | @import 'settings'; 31 | @import 'foundation'; 32 | 33 | // Global styles 34 | @include foundation-global-styles; 35 | @include foundation-forms; 36 | @include foundation-typography; 37 | 38 | // Grids 39 | @include foundation-xy-grid-classes; 40 | 41 | // Generic components 42 | @include foundation-button; 43 | @include foundation-button-group; 44 | @include foundation-close-button; 45 | @include foundation-label; 46 | //@include foundation-progress-bar; 47 | //@include foundation-slider; 48 | //@include foundation-switch; 49 | @include foundation-table; 50 | // Basic components 51 | //@include foundation-badge; 52 | //@include foundation-breadcrumbs; 53 | @include foundation-callout; 54 | //@include foundation-card; 55 | //@include foundation-dropdown; 56 | @include foundation-pagination; 57 | @include foundation-tooltip; 58 | 59 | // Containers 60 | //@include foundation-accordion; 61 | @include foundation-media-object; 62 | //@include foundation-orbit; 63 | @include foundation-responsive-embed; 64 | //@include foundation-tabs; 65 | @include foundation-thumbnail; 66 | // Menu-based containers 67 | @include foundation-menu; 68 | @include foundation-menu-icon; 69 | //@include foundation-accordion-menu; 70 | //@include foundation-drilldown-menu; 71 | //@include foundation-dropdown-menu; 72 | 73 | // Layout components 74 | //@include foundation-off-canvas; 75 | //@include foundation-reveal; 76 | @include foundation-sticky; 77 | @include foundation-title-bar; 78 | //@include foundation-top-bar; 79 | 80 | // Helpers 81 | //@include foundation-float-classes; 82 | // @include foundation-flex-classes; 83 | @include foundation-visibility-classes; 84 | 85 | // Custom theme ghost style 86 | // ------------------------ 87 | @import 'components/mixins'; 88 | @import 'components/general'; 89 | @import 'components/koenig'; 90 | @import 'components/tags'; 91 | @import 'components/main-content'; 92 | @import 'components/footer'; 93 | @import 'components/placeholder'; 94 | @import 'components/posts-list'; 95 | @import 'components/top-bar'; 96 | @import 'components/pagination'; 97 | @import 'components/header'; 98 | @import 'components/search'; 99 | @import 'components/ads'; 100 | @import 'components/error'; 101 | -------------------------------------------------------------------------------- /src/styles/post.scss: -------------------------------------------------------------------------------- 1 | @import 'settings'; 2 | @import '_global'; 3 | @import 'util/unit'; 4 | @import 'util/breakpoint'; 5 | @import 'xy-grid/_xy-grid'; 6 | @import 'components/spinkit'; 7 | @import 'components/post-feed'; 8 | @import 'components/lightbox'; 9 | @import 'components/prismjs'; 10 | 11 | .comments, 12 | .read-next { 13 | background: #f0f0f0; 14 | } 15 | .read-next { 16 | padding: 2rem; 17 | } 18 | .comments { 19 | padding-bottom: 3rem; 20 | } 21 | 22 | %rectangle { 23 | position: absolute; 24 | content: ''; 25 | top: 0; 26 | z-index: 1; 27 | background: rgba(255, 255, 255, 0.05); 28 | border: 1px solid rgba(255, 255, 255, 0.1); 29 | } 30 | 31 | .post-full-image { 32 | display: block; 33 | position: relative; 34 | margin-bottom: 2rem; 35 | width: 100%; 36 | height: 500px; 37 | overflow: hidden; 38 | text-align: center; 39 | border-top-left-radius: 5px; 40 | border-top-right-radius: 5px; 41 | background: rgb(241, 241, 241); 42 | 43 | &:before { 44 | @extend %rectangle; 45 | width: 250px; 46 | height: 250px; 47 | left: 6%; 48 | transform: rotate(45deg); 49 | } 50 | &:after { 51 | @extend %rectangle; 52 | width: 250px; 53 | height: 250px; 54 | left: 12%; 55 | transform: rotate(135deg); 56 | } 57 | 58 | @include breakpoint(medium) { 59 | &:before { 60 | width: 350px; 61 | height: 350px; 62 | } 63 | &:after { 64 | width: 350px; 65 | height: 350px; 66 | } 67 | } 68 | @include breakpoint(large) { 69 | &:before { 70 | width: 500px; 71 | height: 500px; 72 | } 73 | &:after { 74 | width: 500px; 75 | height: 500px; 76 | } 77 | } 78 | 79 | img { 80 | position: absolute; 81 | max-width: 90%; 82 | max-height: 87%; 83 | top: 50%; 84 | left: 0; 85 | right: 0; 86 | margin: 0 auto; 87 | border-radius: 10px; 88 | z-index: 4; 89 | transform: translateY(-40%); 90 | } 91 | &.loaded img { 92 | transform: translateY(-53%); 93 | } 94 | 95 | @include breakpoint(medium down) { 96 | height: 350px; 97 | } 98 | @include breakpoint(small down) { 99 | height: 250px; 100 | } 101 | 102 | img, 103 | .post-full-image-background, 104 | .post-full-meta-feature { 105 | opacity: 0; 106 | transition-property: transform,opacity; 107 | transition-duration: 0.6s; 108 | transition-timing-function: ease-in; 109 | } 110 | 111 | &.loaded { 112 | img, 113 | .post-full-image-background, 114 | .post-full-meta-feature { 115 | opacity: 1; 116 | } 117 | } 118 | } 119 | 120 | .post-full-image-background { 121 | display: block; 122 | position: absolute; 123 | width: 100%; 124 | height: 100%; 125 | top: 0; 126 | left: 0; 127 | background: rgba(255, 255, 255, 0) 128 | } 129 | 130 | %meta { 131 | display: flex; 132 | padding: rem-calc(5 10); 133 | width: 100%; 134 | font-size: 85%; 135 | text-align: left; 136 | font-weight: 500; 137 | flex-flow: row wrap; 138 | justify-content: space-between; 139 | 140 | .post-date { 141 | margin-right: rem-calc(15); 142 | } 143 | .post-full-meta-date { 144 | text-transform: uppercase; 145 | } 146 | } 147 | 148 | .post-full-meta { 149 | @extend %meta; 150 | position: relative; 151 | margin-bottom: rem-calc(25); 152 | background: $lightest-gray; 153 | 154 | .fa, 155 | .far, 156 | .fas { 157 | font-size: 80%; 158 | } 159 | 160 | .meta-tag { 161 | text-transform: uppercase; 162 | color: $body-font-color; 163 | } 164 | } 165 | .post-full-meta-feature { 166 | @extend %meta; 167 | position: absolute; 168 | bottom: 0; 169 | left: 0; 170 | color: $white; 171 | background: rgba(0, 0, 0, 0.8); 172 | z-index: 20; 173 | 174 | .fa, 175 | .far, 176 | .fas { 177 | font-size: 80%; 178 | } 179 | 180 | .meta-tag { 181 | text-transform: uppercase; 182 | color: $white; 183 | 184 | &:hover, 185 | &:focus { 186 | color: $white; 187 | } 188 | } 189 | } 190 | 191 | .post-full-title { 192 | text-align: center; 193 | margin-bottom: 2rem; 194 | } 195 | 196 | .title-wrapper, 197 | .post-content, 198 | .comments-container, 199 | .post-full-meta, 200 | .post-full-footer { 201 | @include breakpoint(medium) { 202 | @include xy-cell(9 of 11); 203 | @include xy-cell-offset(1, $gutters: $grid-margin-gutters, $gutter-type: margin); 204 | } 205 | @include breakpoint(large) { 206 | @include xy-cell(8); 207 | @include xy-cell-offset(2, $gutters: $grid-margin-gutters, $gutter-type: margin); 208 | } 209 | } 210 | 211 | // Images (required by Ghost) 212 | // -------------------------- 213 | 214 | /* Preventing full-width image overlap with post image. */ 215 | .post-full-image + .post-full-content .kg-content *:first-child .kg-image { 216 | width: 100%; 217 | } 218 | 219 | .post-content { 220 | .kg-width-wide .kg-image { 221 | max-width: 100%; 222 | //TODO 223 | } 224 | .kg-width-full .kg-image { 225 | max-width: 100%; 226 | //TODO 227 | } 228 | } 229 | 230 | .kg-gallery-container { 231 | display: flex; 232 | flex-direction: column; 233 | max-width: 100%; // TODO 234 | } 235 | 236 | .kg-gallery-row { 237 | display: flex; 238 | flex-direction: row; 239 | justify-content: center; 240 | 241 | &:not(:first-of-type) { 242 | margin: 0.75em 0 0 0; 243 | } 244 | } 245 | 246 | .kg-gallery-image { 247 | img { 248 | display: block; 249 | margin: 0; 250 | width: 100%; 251 | height: 100%; 252 | } 253 | &:not(:first-of-type) { 254 | margin: 0 0 0 0.75em; 255 | } 256 | } 257 | 258 | .kg-card { 259 | margin: rem-calc(0 0 16); 260 | 261 | > * { 262 | margin: 0 auto !important; 263 | } 264 | } 265 | 266 | // Author 267 | // ------ 268 | 269 | .post-full-footer { 270 | display: flex; 271 | align-items: center; 272 | justify-content: center; 273 | margin-top: 4rem; 274 | } 275 | 276 | .post-full-container { 277 | display: inline-flex; 278 | position: relative; 279 | padding: rem-calc(6 3 3 3); 280 | flex-flow: row wrap; 281 | background: #f0f0f0; 282 | max-height: 70px; 283 | 284 | .author-list-item, 285 | > section:first-child { 286 | margin-right: rem-calc(10); 287 | } 288 | 289 | &:before { 290 | display: block; 291 | position: absolute; 292 | content: " "; 293 | width: 0; 294 | height: 0; 295 | top: 0; 296 | left: -70px; 297 | border-bottom: 70px solid #f0f0f0; 298 | border-left: 70px solid transparent; 299 | } 300 | &:after { 301 | display: block; 302 | position: absolute; 303 | content: " "; 304 | width: 0; 305 | height: 0; 306 | top: 0; 307 | right: -70px; 308 | border-bottom: 70px solid #f0f0f0; 309 | border-right: 70px solid transparent; 310 | } 311 | } 312 | 313 | .author-list { 314 | li:last-child { 315 | margin-right: 0; 316 | } 317 | } 318 | 319 | %circles { 320 | display: inline-block; 321 | position: relative; 322 | width: 50px; 323 | height: 50px; 324 | border-radius: 50%; 325 | overflow: hidden; 326 | background: $primary-color; 327 | text-align: center; 328 | } 329 | 330 | .author-card { 331 | a { 332 | border-bottom: none; 333 | } 334 | .author-profile-image { 335 | @extend %circles; 336 | } 337 | } 338 | .share-icon { 339 | @extend %circles; 340 | color: $white; 341 | font-size: rem-calc(25); 342 | 343 | > i { 344 | padding: rem-calc(12); 345 | } 346 | } 347 | .open-share { 348 | display: block; 349 | position: absolute; 350 | width: 100%; 351 | height: 100%; 352 | top: 0; 353 | left: 0; 354 | cursor: pointer; 355 | background: rgba(255, 255, 255, 0); 356 | } 357 | .share-post { 358 | position: relative; 359 | 360 | &:hover, 361 | &:focus { 362 | .share-post-ct { 363 | opacity: 1; 364 | visibility: visible; 365 | } 366 | } 367 | } 368 | 369 | .share-post-ct { 370 | position: absolute; 371 | flex-flow: row nowrap; 372 | bottom: 125%; 373 | left: 50%; 374 | opacity: 0; 375 | visibility: hidden; 376 | transform: translateX(-50%); 377 | transition: visibility 0.2s linear, opacity 0.2s linear; 378 | z-index: 80; 379 | } 380 | .share-icons { 381 | position: relative; 382 | flex-flow: row nowrap; 383 | padding: .75rem; 384 | border-radius: 0; 385 | background-color: #0a0a0a; 386 | 387 | &::before { 388 | display: block; 389 | position: absolute; 390 | content: " "; 391 | width: 0; 392 | height: 0; 393 | top: 100%; 394 | left: 0; 395 | right: 0; 396 | margin: 0 auto; 397 | bottom: auto; 398 | border: inset 0.75rem; 399 | border-bottom-width: 0; 400 | border-top-style: solid; 401 | border-color: #0a0a0a transparent transparent; 402 | } 403 | 404 | > li:not(:last-child) { 405 | margin-right: rem-calc(7); 406 | } 407 | } 408 | 409 | %social-circle { 410 | display: inline-block; 411 | position: relative; 412 | padding: rem-calc(6); 413 | width: 35px; 414 | height: 35px; 415 | border-radius: 50%; 416 | overflow: hidden; 417 | text-align: center; 418 | color: $white; 419 | cursor: pointer; 420 | 421 | &:hover, 422 | &:focus { 423 | color: $white; 424 | } 425 | } 426 | .social-icon { 427 | @extend %social-circle; 428 | } 429 | .icon-twitter { 430 | background-color: #56ADEE; 431 | &:hover, &:focus { 432 | background-color: darken(#56ADEE, 20%); 433 | } 434 | } 435 | .icon-facebook { 436 | background-color: #4862A2; 437 | 438 | &:hover, &:focus { 439 | background-color: darken(#4862A2, 20%); 440 | } 441 | } 442 | .icon-google-plus { 443 | background-color: #DB4437; 444 | 445 | &:hover, &:focus { 446 | background-color: darken(#DB4437, 20%); 447 | } 448 | } 449 | .icon-reddit { 450 | background-color: #ff4500; 451 | 452 | &:hover, &:focus { 453 | background-color: darken(#ff4500, 20%); 454 | } 455 | } 456 | .icon-linkedin { 457 | background-color: #0071ad; 458 | 459 | &:hover, &:focus { 460 | background-color: darken(#0071ad, 10%); 461 | } 462 | } 463 | .icon-flipboard { 464 | background-color: #ff2a31; 465 | 466 | &:hover, &:focus { 467 | background-color: darken(#ff2a31, 20%); 468 | } 469 | } 470 | .tooltip { 471 | z-index: 80; 472 | } 473 | -------------------------------------------------------------------------------- /src/typings/@tryghost/content-api/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@tryghost/content-api'; 2 | interface GhostApi { 3 | url: string; 4 | key: string; 5 | version: string; 6 | } 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | declare function GhostContentAPI(apiParams: GhostApi): any; 9 | -------------------------------------------------------------------------------- /src/typings/@tryghost/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@tryghost'; 2 | -------------------------------------------------------------------------------- /src/typings/colorthief/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'colorthief'; 2 | -------------------------------------------------------------------------------- /src/typings/custom/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg'; 2 | declare module '*.png'; 3 | declare module '*.jpg'; 4 | declare module '*.jpeg'; 5 | declare module '*.gif'; 6 | declare module '*.bmp'; 7 | declare module '*.tiff'; 8 | declare module '*.webp'; 9 | declare module '*.json'; 10 | -------------------------------------------------------------------------------- /src/typings/ghost-search/index.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 2 | export default function GhostSearch(args: any): void; 3 | export as namespace GhostSearch; 4 | -------------------------------------------------------------------------------- /src/typings/ghost/index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace ghost { 2 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 3 | function init(options: any): void; 4 | namespace url { 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 6 | function api(resource: string, parameter: Record): any; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/typings/lightgallery/index.d.ts: -------------------------------------------------------------------------------- 1 | // Lightgallery.js 2 | 3 | interface Window { 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 5 | lightGallery: (el: Element, options: any) => void; 6 | } 7 | -------------------------------------------------------------------------------- /src/typings/particles.js/index.d.ts: -------------------------------------------------------------------------------- 1 | // particlesJS 2 | 3 | interface Window { 4 | // eslint-disable-next-line @typescript-eslint/camelcase,@typescript-eslint/no-explicit-any 5 | particlesJS: (tag_id: string, params: any) => void; 6 | } 7 | -------------------------------------------------------------------------------- /tag.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | {{!-- The tag above means - insert everything in this file into the {body} of the default.hbs template --}} 3 | 4 | {{#tag}} 5 | {{#contentFor "styles"}} 6 | 51 | {{/contentFor}} 52 | {{/tag}} 53 | 54 | {{!-- The main content area --}} 55 | 56 | 67 | 68 | {{#contentFor "scripts"}} 69 | 70 | {{/contentFor}} 71 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "baseUrl": "./", 7 | "outDir": "assets", 8 | "strict": true, 9 | "sourceMap": true, 10 | "removeComments": true, 11 | "noImplicitAny": true, 12 | "resolveJsonModule": true, 13 | "esModuleInterop": true, 14 | "allowJs": true, 15 | "types": [ 16 | "jquery", 17 | "webpack-env" 18 | ], 19 | "typeRoots": [ 20 | "./node_modules/@types", 21 | "./src/typings" 22 | ], 23 | "lib": [ 24 | "dom", 25 | "es5", 26 | "es2015.core", 27 | "es2015.promise", 28 | "scripthost" 29 | ] 30 | }, 31 | "include": [ 32 | "./src/**/*" 33 | ], 34 | "exclude": [ 35 | "node_modules", 36 | "assets", 37 | "src/build", 38 | "src/img", 39 | "src/styles" 40 | ], 41 | "awesomeTypescriptLoaderOptions": { 42 | "reportFiles": [ 43 | "./src/**/*" 44 | ] 45 | } 46 | } 47 | --------------------------------------------------------------------------------57 |66 |58 | 59 | {{#foreach posts}} 60 | {{!-- The tag below includes the markup for each post - partials/post-card.hbs --}} 61 | {{> "post-card"}} 62 | {{/foreach}} 63 |64 | {{pagination}} 65 |
Comments:
150 | 151 | 152 | 165 | 166 |