├── .circleci ├── config.yml └── workflows.yml ├── .devcontainer └── devcontainer.json ├── .docker ├── dockerfiles │ ├── blog.Dockerfile │ ├── ci.Dockerfile │ ├── devcontainer.Dockerfile │ └── tests.Dockerfile └── scripts │ ├── blog.docker-entrypoint.sh │ ├── ci.docker-entrypoint.sh │ ├── devcontainer.docker-entrypoint.sh │ └── tests.docker-entrypoint.sh ├── .githooks └── pre-commit ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug.md │ └── feature.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .gitmodules ├── .hugo_build.lock ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE_CC_BY_4.0 ├── LICENSE_MIT ├── Makefile ├── README.md ├── README_DOCKER_HUB.md ├── SECURITY.md ├── archetypes └── default.md ├── assets ├── .gitkeep └── css │ ├── .gitkeep │ └── extended │ ├── main.css │ └── menu.css ├── config.yaml ├── content ├── about.md ├── archives.md ├── offline.md ├── posts │ ├── foss │ │ ├── awesome-steam-deck.md │ │ └── building-anally-fast-stuff.md │ ├── green-bytes │ │ └── less-feetpics-less-footprint.md │ ├── life │ │ └── if-gael-had-turned-back.md │ └── molivair │ │ └── welcome-molivair.md └── search.md ├── data └── info.toml ├── docker-compose.yml ├── i18n └── en.yaml ├── layouts ├── _default │ ├── rss.xml │ └── search.html ├── offline │ └── single.html └── partials │ ├── extend_footer.html │ ├── extend_head.html │ ├── footer.html │ └── header.html ├── netlify.toml ├── scripts ├── bats.sh ├── ci │ ├── build.sh │ ├── deploy.sh │ └── verify.sh ├── devcontainer │ ├── safeness.sh │ ├── setup.sh │ ├── teardown.sh │ └── verify.sh ├── docker │ ├── build.sh │ ├── login.sh │ └── push.sh ├── install │ ├── bash.sh │ ├── bats.sh │ ├── circleci-cli.sh │ ├── curl.sh │ ├── devcontainer-cli.sh │ ├── docker-cli.sh │ ├── git.sh │ ├── gpp.sh │ ├── hugo.sh │ ├── make.sh │ ├── netlify-cli.sh │ ├── npm.sh │ └── python3.sh ├── shared │ └── git-submodules.sh ├── tests │ └── base.sh └── update.sh ├── static ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon-114x114.png ├── apple-touch-icon-120x120.png ├── apple-touch-icon-144x144.png ├── apple-touch-icon-152x152.png ├── apple-touch-icon-180x180.png ├── apple-touch-icon-57x57.png ├── apple-touch-icon-60x60.png ├── apple-touch-icon-72x72.png ├── apple-touch-icon-76x76.png ├── apple-touch-icon.png ├── browserconfig.xml ├── css │ └── offline.css ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── images │ ├── cover-analscript.png │ ├── gael.png │ ├── less-feetpics-less-footprint.png │ ├── logo-steam-deck.png │ └── woman-with-a-parasol.png ├── js │ ├── menu.js │ └── notifications │ │ ├── dictionary.js │ │ ├── i18n.js │ │ ├── main.js │ │ └── worker.js ├── logo-256x256.png ├── logo-512x512.png ├── logo-open-graph.png ├── logo.svg ├── manifest.json ├── maskable-android-chrome-192x192.png ├── maskable-android-chrome-512x512.png ├── mstile-144x144.png ├── mstile-150x150.png ├── mstile-310x150.png ├── mstile-310x310.png ├── mstile-70x70.png ├── safari-pinned-tab.svg ├── search.svg └── sw.js └── tests ├── _.bats ├── install.bats ├── mocks.sh └── shared.bats /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | setup: true 4 | 5 | orbs: 6 | continuation: circleci/continuation@0.3.1 7 | path-filtering: circleci/path-filtering@0.1.3 8 | 9 | workflows: 10 | setup: 11 | jobs: 12 | - path-filtering/filter: 13 | name: workflows 14 | base-revision: main 15 | resource_class: small 16 | config-path: .circleci/workflows.yml 17 | 18 | mapping: | 19 | data/.* build true 20 | i18n/.* build true 21 | tests/.* tests true 22 | static/.* build true 23 | content/.* build true 24 | layouts/.* build true 25 | resources/.* build true 26 | archetypes/.* build true 27 | config.toml/.* build true 28 | 29 | - continuation/continue: 30 | configuration_path: .circleci/workflows.yml 31 | 32 | parameters: '{ 33 | "build": false, 34 | "tests": false, 35 | "deploy": false, 36 | "verify": false 37 | }' 38 | 39 | filters: 40 | tags: 41 | only: 42 | - /.*/ 43 | 44 | branches: 45 | ignore: /.*/ 46 | -------------------------------------------------------------------------------- /.circleci/workflows.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | parameters: 4 | verify: 5 | type: boolean 6 | default: true 7 | 8 | tests: 9 | type: boolean 10 | default: false 11 | 12 | build: 13 | type: boolean 14 | default: false 15 | 16 | deploy: 17 | type: boolean 18 | default: true 19 | 20 | publish: 21 | type: boolean 22 | default: true 23 | 24 | executors: 25 | base: 26 | docker: 27 | - image: alpine:3.22 28 | 29 | commands: 30 | setup: 31 | steps: 32 | - run: 33 | name: Setup 34 | 35 | command: | 36 | sh scripts/update.sh 37 | sh scripts/install/bash.sh 38 | bash scripts/install/make.sh 39 | 40 | setup-git: 41 | steps: 42 | - install-git 43 | 44 | - run: 45 | name: Setup Git 46 | command: make git-submodules environment=$CI_ENVIRONMENT 47 | 48 | setup-netlify: 49 | steps: 50 | - install-npm 51 | - install-netlify-cli 52 | 53 | install-git: 54 | steps: 55 | - run: 56 | name: "Install Git" 57 | command: make install-git environment=$CI_ENVIRONMENT 58 | 59 | install-npm: 60 | steps: 61 | - run: 62 | name: Install npm 63 | command: make install-npm 64 | 65 | install-hugo: 66 | steps: 67 | - run: 68 | name: Install Hugo 69 | command: make install-hugo 70 | 71 | install-bats: 72 | steps: 73 | - run: 74 | name: Install Bats 75 | command: make install-bats 76 | 77 | install-docker-cli: 78 | steps: 79 | - run: 80 | name: Install Docker CLI 81 | command: make install-docker-cli 82 | 83 | install-netlify-cli: 84 | steps: 85 | - run: 86 | name: Install Netlify CLI 87 | command: make install-netlify-cli 88 | 89 | jobs: 90 | verify: 91 | executor: base 92 | resource_class: small 93 | 94 | steps: 95 | - checkout 96 | - setup 97 | 98 | - run: 99 | name: Verify Base 100 | command: make ci-verify environment=base 101 | 102 | verify-build: 103 | executor: base 104 | resource_class: small 105 | 106 | steps: 107 | - checkout 108 | - setup 109 | - setup-git 110 | - install-hugo 111 | 112 | - run: 113 | name: Verify Build 114 | command: make ci-verify environment=build 115 | 116 | verify-deploy: 117 | executor: base 118 | resource_class: small 119 | 120 | steps: 121 | - checkout 122 | - setup 123 | - setup-netlify 124 | 125 | - run: 126 | name: Verify Deploy 127 | command: make ci-verify environment=deploy 128 | 129 | verify-publish: 130 | executor: base 131 | resource_class: small 132 | 133 | steps: 134 | - checkout 135 | - setup 136 | - install-docker-cli 137 | 138 | - run: 139 | name: Verify Publish 140 | command: make ci-verify environment=publish 141 | 142 | tests: 143 | executor: base 144 | resource_class: small 145 | 146 | steps: 147 | - checkout 148 | - setup 149 | - setup-git 150 | - install-npm 151 | - install-bats 152 | 153 | - run: 154 | name: Run Tests 155 | command: make tests-base 156 | 157 | build: 158 | executor: base 159 | resource_class: medium 160 | 161 | steps: 162 | - checkout 163 | - setup 164 | - setup-git 165 | - install-hugo 166 | 167 | - run: 168 | name: Build Site 169 | command: make ci-build 170 | 171 | - when: 172 | condition: 173 | equal: [ main, << pipeline.git.branch >>] 174 | 175 | steps: 176 | - persist_to_workspace: 177 | root: . 178 | 179 | paths: 180 | - ./public 181 | 182 | deploy: 183 | executor: base 184 | resource_class: small 185 | 186 | steps: 187 | - checkout 188 | - setup 189 | - setup-netlify 190 | 191 | - attach_workspace: 192 | at: . 193 | 194 | - run: 195 | name: Deploy To Netlify 196 | command: > 197 | make ci-deploy 198 | id=$NETLIFY_SITE_ID 199 | token=$NETLIFY_ACCESS_TOKEN 200 | 201 | publish: 202 | executor: base 203 | resource_class: small 204 | 205 | steps: 206 | - checkout 207 | - setup 208 | - install-docker-cli 209 | 210 | - setup_remote_docker: 211 | docker_layer_caching: true 212 | version: 20.10.14 213 | 214 | - run: 215 | name: Publish To Docker Hub 216 | command: > 217 | make ci-publish 218 | tag=$CIRCLE_TAG 219 | username=$DOCKER_USERNAME 220 | token=$DOCKER_ACCESS_TOKEN 221 | 222 | workflows: 223 | verify: 224 | when: << pipeline.parameters.verify >> 225 | 226 | jobs: 227 | - verify 228 | 229 | tests: 230 | when: << pipeline.parameters.tests >> 231 | 232 | jobs: 233 | - tests 234 | 235 | build: 236 | when: << pipeline.parameters.build >> 237 | 238 | jobs: 239 | - verify-build 240 | 241 | - build: 242 | requires: 243 | - verify-build 244 | 245 | deploy: 246 | when: << pipeline.parameters.deploy >> 247 | 248 | jobs: 249 | - verify-build: 250 | filters: 251 | branches: 252 | only: 253 | - main 254 | 255 | - build: 256 | requires: 257 | - verify-build 258 | 259 | filters: 260 | branches: 261 | only: 262 | - main 263 | 264 | - verify-deploy: 265 | filters: 266 | branches: 267 | only: 268 | - main 269 | 270 | - deploy: 271 | requires: 272 | - build 273 | - verify-deploy 274 | 275 | filters: 276 | branches: 277 | only: 278 | - main 279 | 280 | publish: 281 | when: << pipeline.parameters.publish >> 282 | 283 | jobs: 284 | - verify-publish: 285 | filters: 286 | tags: 287 | only: 288 | - /.*/ 289 | 290 | branches: 291 | ignore: /.*/ 292 | 293 | - publish: 294 | requires: 295 | - verify-publish 296 | 297 | filters: 298 | tags: 299 | only: 300 | - /.*/ 301 | 302 | branches: 303 | ignore: /.*/ 304 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "overrideCommand": false, 3 | "name": "airscript-devcontainer", 4 | "image": "docker:28.2.2-dind-alpine3.21", 5 | "postCreateCommand": "sh scripts/devcontainer/setup.sh", 6 | 7 | "forwardPorts": [ 8 | 25001 9 | ], 10 | 11 | "runArgs": [ 12 | "--init", 13 | "--privileged", 14 | "--name", "airscript-devcontainer" 15 | ], 16 | 17 | "extensions": [ 18 | "ms-azuretools.vscode-docker" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.docker/dockerfiles/blog.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS builder 2 | ARG BLOG_BUILD_ENVIRONMENT=docker 3 | WORKDIR /home 4 | COPY . . 5 | 6 | RUN \ 7 | sh scripts/update.sh && \ 8 | sh scripts/install/bash.sh && \ 9 | bash scripts/install/make.sh 10 | 11 | RUN \ 12 | make install-git environment=${BLOG_BUILD_ENVIRONMENT} && \ 13 | make git-submodules environment=${BLOG_BUILD_ENVIRONMENT} 14 | 15 | FROM alpine:3.22 AS runner 16 | LABEL maintainer="Airscript " 17 | ENV BLOG_PORT=25001 18 | ENV BLOG_INTERFACE=0.0.0.0 19 | WORKDIR /home 20 | COPY --from=builder /home ./ 21 | 22 | RUN \ 23 | sh scripts/update.sh && \ 24 | sh scripts/install/bash.sh && \ 25 | bash scripts/install/make.sh && \ 26 | make install-hugo 27 | 28 | ENTRYPOINT [".docker/scripts/blog.docker-entrypoint.sh"] 29 | CMD ["hugo"] 30 | EXPOSE ${BLOG_PORT} 31 | -------------------------------------------------------------------------------- /.docker/dockerfiles/ci.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS runner 2 | LABEL maintainer="Airscript " 3 | WORKDIR /tmp 4 | COPY tmp/ /tmp/ 5 | 6 | RUN \ 7 | sh scripts/update.sh && \ 8 | sh scripts/install/bash.sh && \ 9 | bash scripts/install/make.sh && \ 10 | make install-curl && \ 11 | make install-circleci-cli 12 | 13 | ENTRYPOINT [ ".docker/scripts/ci.docker-entrypoint.sh" ] 14 | CMD ["circleci"] 15 | -------------------------------------------------------------------------------- /.docker/dockerfiles/devcontainer.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker:28.2.2-dind-alpine3.21 AS runner 2 | LABEL maintainer="Airscript " 3 | WORKDIR /home 4 | COPY tmp/ /home/ 5 | 6 | RUN \ 7 | sh scripts/update.sh && \ 8 | sh scripts/install/bash.sh && \ 9 | bash scripts/install/make.sh && \ 10 | make install-npm && \ 11 | make install-python3 && \ 12 | make install-gpp && \ 13 | make install-devcontainer-cli 14 | 15 | ENTRYPOINT [ ".docker/scripts/devcontainer.docker-entrypoint.sh" ] 16 | CMD ["devcontainer"] -------------------------------------------------------------------------------- /.docker/dockerfiles/tests.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 AS runner 2 | LABEL maintainer="Airscript " 3 | WORKDIR /tmp 4 | COPY tmp/ /tmp/ 5 | 6 | RUN \ 7 | sh scripts/update.sh && \ 8 | sh scripts/install/bash.sh && \ 9 | bash scripts/install/make.sh && \ 10 | make install-npm && \ 11 | make install-bats 12 | 13 | ENTRYPOINT [".docker/scripts/tests.docker-entrypoint.sh"] 14 | CMD ["bats"] 15 | -------------------------------------------------------------------------------- /.docker/scripts/blog.docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ "$1" = 'hugo' ]; then 5 | hugo server --bind $BLOG_INTERFACE --port $BLOG_PORT 6 | 7 | else 8 | exec "$@" 9 | fi 10 | -------------------------------------------------------------------------------- /.docker/scripts/ci.docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ "$1" = 'circleci' ]; then 5 | circleci config validate .circleci/config.yml 6 | circleci config validate .circleci/workflows.yml 7 | 8 | else 9 | exec "$@" 10 | fi 11 | -------------------------------------------------------------------------------- /.docker/scripts/devcontainer.docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ "$1" = 'devcontainer' ]; then 5 | bash ./scripts/devcontainer/verify.sh 6 | 7 | else 8 | exec "$@" 9 | fi 10 | -------------------------------------------------------------------------------- /.docker/scripts/tests.docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ "$1" = 'bats' ]; then 5 | make tests-base 6 | 7 | else 8 | exec "$@" 9 | fi -------------------------------------------------------------------------------- /.githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PREFIX="pre-commit:" 3 | STAGED_FILES=$(git diff --diff-filter=d --cached --name-only) 4 | CI_FILES=$(echo "$STAGED_FILES" | grep .circleci) 5 | TESTS_FILES=$(echo "$STAGED_FILES" | grep tests) 6 | DEVCONTAINER_FILES=$(echo "$STAGED_FILES" | grep .devcontainer) 7 | 8 | if [ ${#CI_FILES} -gt 0 ]; then 9 | if ! make all-ci; then 10 | echo "$PREFIX Error during CI files validation." 11 | exit 1 12 | fi 13 | fi 14 | 15 | if [ ${#TESTS_FILES} -gt 0 ]; then 16 | if ! make all-tests; then 17 | echo "$PREFIX Error during tests validation." 18 | exit 1 19 | fi 20 | fi 21 | 22 | if [ ${#DEVCONTAINER_FILES} -gt 0 ]; then 23 | if ! make all-devcontainer; then 24 | echo "$PREFIX Error during devcontainer validation." 25 | exit 1 26 | fi 27 | fi 28 | 29 | echo "$PREFIX Run successfully." 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [airscripts] 2 | ko_fi: airscript 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: Airscripts 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature 6 | assignees: Airscripts 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Pull Request 2 | Compile all the informations written below to send a legitimate pull request to the repository! 3 | 4 | ## Label: 5 | 6 | ### This PR is labeled as: 7 | *Choose only one and remember to select the label even on the right.* 8 | 9 | - [ ] Feature 10 | - [ ] Bug 11 | - [ ] Other 12 | 13 | ## Linked Issue 14 | 15 | ### This PR has the following linked issues: 16 | - Closes #; 17 | - ... 18 | 19 | ## Solution 20 | 21 | ### My solution is explained as follows: 22 | Write your solution here... 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | tmp 3 | public 4 | resources -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "themes/PaperMod"] 2 | path = themes/PaperMod 3 | url = https://github.com/adityatelange/hugo-PaperMod.git 4 | 5 | [submodule "tests/bats"] 6 | path = tests/bats 7 | url = https://github.com/bats-core/bats-core.git 8 | 9 | [submodule "tests/libraries/bats-support"] 10 | path = tests/libraries/bats-support 11 | url = https://github.com/bats-core/bats-support.git 12 | 13 | [submodule "tests/libraries/bats-assert"] 14 | path = tests/libraries/bats-assert 15 | url = https://github.com/bats-core/bats-assert.git 16 | -------------------------------------------------------------------------------- /.hugo_build.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/.hugo_build.lock -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) with some edits, 4 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 5 | 6 | # 1.11.0 7 | 8 | ## What's Changed 9 | * refactor!: remove italian language 10 | 11 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.10.0...1.11.0 12 |   13 | 14 | # 1.10.0 15 | 16 | ## What's Changed 17 | * feat: automatic devcontainers.json verify by @Airscripts in https://github.com/Airscripts/blog/pull/44 18 | 19 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.9.0...1.10.0 20 |   21 | 22 | # 1.9.0 23 | 24 | ## What's Changed 25 | * feat: add dev container setup by @Airscripts 26 | * feat: add dev container teardown by @Airscripts 27 | 28 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.8.0...1.9.0 29 |   30 | 31 | # 1.8.0 32 | 33 | ## What's Changed 34 | * feat: add hamburger menu support by @Airscripts 35 | 36 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.7.0...1.8.0 37 |   38 | 39 | # 1.7.0 40 | 41 | ## What's Changed 42 | * fix: add identifier in order to use keyboard shortcut for search by @Airscripts in https://github.com/Airscripts/blog/pull/36 43 | * feat: add push notifications support by @Airscripts in https://github.com/Airscripts/blog/pull/37 44 | * feat: add http security headers by @Airscripts in https://github.com/Airscripts/blog/pull/38 45 | 46 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.6.0...1.7.0 47 |   48 | 49 | # 1.6.0 50 | 51 | ## What's Changed 52 | * feat(hooks): add pre-commit git hook by @Airscripts in https://github.com/Airscripts/blog/pull/33 53 | * feat: add pwa support by @Airscripts in https://github.com/Airscripts/blog/pull/34 54 | 55 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.5.0...1.6.0 56 |   57 | 58 | # 1.5.0 59 | 60 | ## What's Changed 61 | * feat: implement use of make by @Airscripts in https://github.com/Airscripts/blog/pull/22 62 | * feat(ci): add automatic tests by @Airscripts in https://github.com/Airscripts/blog/pull/23 63 | * refactor(ci): reorganize jobs by @Airscripts in https://github.com/Airscripts/blog/pull/25 64 | * refactor(docker): collapse tests Dockerfiles into single one by @Airscripts in https://github.com/Airscripts/blog/pull/26 65 | * feat(ci): specify resource classes in CI's jobs by @Airscripts in https://github.com/Airscripts/blog/pull/27 66 | * feat(ci): add resource_class to setup workflow job by @Airscripts in https://github.com/Airscripts/blog/pull/28 67 | * refactor(docker): refactor both blog and tests Dockerfiles by @Airscripts in https://github.com/Airscripts/blog/pull/29 68 | * feat(docker): add ci Dockerfile by @Airscripts in https://github.com/Airscripts/blog/pull/30 69 | * feat: add JP's quote in home by @spagno in https://github.com/Airscripts/blog/pull/31 70 | 71 | ## New Contributors 72 | * @spagno made their first contribution in https://github.com/Airscripts/blog/pull/31 73 | 74 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.4.0...1.5.0 75 |   76 | 77 | # 1.4.0 78 | 79 | ## What's Changed 80 | * fix(docker): fix missing submodules inside docker-compose by @Airscripts in https://github.com/Airscripts/blog/pull/20 81 | 82 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.3.0...1.4.0 83 |   84 | 85 | # 1.3.0 86 | 87 | ## What's Changed 88 | * fix(content): add missing link to github repository by @Airscripts in https://github.com/Airscripts/blog/pull/17 89 | * feat: add home page by @Airscripts in https://github.com/Airscripts/blog/pull/18 90 | 91 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.2.1...1.3.0 92 |   93 | 94 | # 1.2.1 95 | 96 | ## What's Changed 97 | - fix(docker): temporarily remove git submodule from Dockerfile 98 | 99 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.2.0...1.2.1 100 |   101 | 102 | # 1.2.0 103 | 104 | ## What's Changed 105 | * refactor: change base image for blog.Dockerfile by @Airscripts in https://github.com/Airscripts/blog/pull/12 106 | 107 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.1.0...1.2.0 108 |   109 | 110 | # 1.1.0 111 | 112 | ## What's Changed 113 | * feat: add logo and favicon by @Airscripts in https://github.com/Airscripts/blog/pull/8 114 | * refactor(ci): add persistency to build job by @Airscripts in https://github.com/Airscripts/blog/pull/9 115 | * fix(ci): add missing attach workspace to deploy job by @Airscripts in https://github.com/Airscripts/blog/pull/10 116 | * feat(docker): add docker support and publish workflow by @Airscripts in https://github.com/Airscripts/blog/pull/11 117 | 118 | **Full Changelog**: https://github.com/Airscripts/blog/compare/1.0.0...1.1.0 119 |   120 | 121 | # 1.0.0 122 | 123 | ## What's Changed 124 | * chore: add circleci config.yml by @Airscripts in https://github.com/Airscripts/blog/pull/1 125 | * chore(ci): add verify, build and deploy workflows by @Airscripts in https://github.com/Airscripts/blog/pull/3 126 | * fix(ci): add missing update on git submodules in deploy workflow by @Airscripts in https://github.com/Airscripts/blog/pull/4 127 | * chore: add various files to repo such as CONTRIBUTING.md and others by @Airscripts in https://github.com/Airscripts/blog/pull/5 128 | * chore(ci): add update on git submodules in build job by @Airscripts in https://github.com/Airscripts/blog/pull/6 129 | * repo: initialize repository 130 | 131 | ## New Contributors 132 | * @Airscripts made their first contribution in https://github.com/Airscripts/blog/pull/1 133 | 134 | **Full Changelog**: https://github.com/Airscripts/blog/commits/1.0.0 135 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available 126 | at [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository, ensuring you follow the [Code of Conduct](https://github.com/Airscripts/blog/blob/main/CODE_OF_CONDUCT.md). 3 | -------------------------------------------------------------------------------- /LICENSE_CC_BY_4.0: -------------------------------------------------------------------------------- 1 | Attribution 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution 4.0 International Public License 58 | 59 | By exercising the Licensed Rights (defined below), You accept and agree 60 | to be bound by the terms and conditions of this Creative Commons 61 | Attribution 4.0 International Public License ("Public License"). To the 62 | extent this Public License may be interpreted as a contract, You are 63 | granted the Licensed Rights in consideration of Your acceptance of 64 | these terms and conditions, and the Licensor grants You such rights in 65 | consideration of benefits the Licensor receives from making the 66 | Licensed Material available under these terms and conditions. 67 | 68 | 69 | Section 1 -- Definitions. 70 | 71 | a. Adapted Material means material subject to Copyright and Similar 72 | Rights that is derived from or based upon the Licensed Material 73 | and in which the Licensed Material is translated, altered, 74 | arranged, transformed, or otherwise modified in a manner requiring 75 | permission under the Copyright and Similar Rights held by the 76 | Licensor. For purposes of this Public License, where the Licensed 77 | Material is a musical work, performance, or sound recording, 78 | Adapted Material is always produced where the Licensed Material is 79 | synched in timed relation with a moving image. 80 | 81 | b. Adapter's License means the license You apply to Your Copyright 82 | and Similar Rights in Your contributions to Adapted Material in 83 | accordance with the terms and conditions of this Public License. 84 | 85 | c. Copyright and Similar Rights means copyright and/or similar rights 86 | closely related to copyright including, without limitation, 87 | performance, broadcast, sound recording, and Sui Generis Database 88 | Rights, without regard to how the rights are labeled or 89 | categorized. For purposes of this Public License, the rights 90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 91 | Rights. 92 | 93 | d. Effective Technological Measures means those measures that, in the 94 | absence of proper authority, may not be circumvented under laws 95 | fulfilling obligations under Article 11 of the WIPO Copyright 96 | Treaty adopted on December 20, 1996, and/or similar international 97 | agreements. 98 | 99 | e. Exceptions and Limitations means fair use, fair dealing, and/or 100 | any other exception or limitation to Copyright and Similar Rights 101 | that applies to Your use of the Licensed Material. 102 | 103 | f. Licensed Material means the artistic or literary work, database, 104 | or other material to which the Licensor applied this Public 105 | License. 106 | 107 | g. Licensed Rights means the rights granted to You subject to the 108 | terms and conditions of this Public License, which are limited to 109 | all Copyright and Similar Rights that apply to Your use of the 110 | Licensed Material and that the Licensor has authority to license. 111 | 112 | h. Licensor means the individual(s) or entity(ies) granting rights 113 | under this Public License. 114 | 115 | i. Share means to provide material to the public by any means or 116 | process that requires permission under the Licensed Rights, such 117 | as reproduction, public display, public performance, distribution, 118 | dissemination, communication, or importation, and to make material 119 | available to the public including in ways that members of the 120 | public may access the material from a place and at a time 121 | individually chosen by them. 122 | 123 | j. Sui Generis Database Rights means rights other than copyright 124 | resulting from Directive 96/9/EC of the European Parliament and of 125 | the Council of 11 March 1996 on the legal protection of databases, 126 | as amended and/or succeeded, as well as other essentially 127 | equivalent rights anywhere in the world. 128 | 129 | k. You means the individual or entity exercising the Licensed Rights 130 | under this Public License. Your has a corresponding meaning. 131 | 132 | 133 | Section 2 -- Scope. 134 | 135 | a. License grant. 136 | 137 | 1. Subject to the terms and conditions of this Public License, 138 | the Licensor hereby grants You a worldwide, royalty-free, 139 | non-sublicensable, non-exclusive, irrevocable license to 140 | exercise the Licensed Rights in the Licensed Material to: 141 | 142 | a. reproduce and Share the Licensed Material, in whole or 143 | in part; and 144 | 145 | b. produce, reproduce, and Share Adapted Material. 146 | 147 | 2. Exceptions and Limitations. For the avoidance of doubt, where 148 | Exceptions and Limitations apply to Your use, this Public 149 | License does not apply, and You do not need to comply with 150 | its terms and conditions. 151 | 152 | 3. Term. The term of this Public License is specified in Section 153 | 6(a). 154 | 155 | 4. Media and formats; technical modifications allowed. The 156 | Licensor authorizes You to exercise the Licensed Rights in 157 | all media and formats whether now known or hereafter created, 158 | and to make technical modifications necessary to do so. The 159 | Licensor waives and/or agrees not to assert any right or 160 | authority to forbid You from making technical modifications 161 | necessary to exercise the Licensed Rights, including 162 | technical modifications necessary to circumvent Effective 163 | Technological Measures. For purposes of this Public License, 164 | simply making modifications authorized by this Section 2(a) 165 | (4) never produces Adapted Material. 166 | 167 | 5. Downstream recipients. 168 | 169 | a. Offer from the Licensor -- Licensed Material. Every 170 | recipient of the Licensed Material automatically 171 | receives an offer from the Licensor to exercise the 172 | Licensed Rights under the terms and conditions of this 173 | Public License. 174 | 175 | b. No downstream restrictions. You may not offer or impose 176 | any additional or different terms or conditions on, or 177 | apply any Effective Technological Measures to, the 178 | Licensed Material if doing so restricts exercise of the 179 | Licensed Rights by any recipient of the Licensed 180 | Material. 181 | 182 | 6. No endorsement. Nothing in this Public License constitutes or 183 | may be construed as permission to assert or imply that You 184 | are, or that Your use of the Licensed Material is, connected 185 | with, or sponsored, endorsed, or granted official status by, 186 | the Licensor or others designated to receive attribution as 187 | provided in Section 3(a)(1)(A)(i). 188 | 189 | b. Other rights. 190 | 191 | 1. Moral rights, such as the right of integrity, are not 192 | licensed under this Public License, nor are publicity, 193 | privacy, and/or other similar personality rights; however, to 194 | the extent possible, the Licensor waives and/or agrees not to 195 | assert any such rights held by the Licensor to the limited 196 | extent necessary to allow You to exercise the Licensed 197 | Rights, but not otherwise. 198 | 199 | 2. Patent and trademark rights are not licensed under this 200 | Public License. 201 | 202 | 3. To the extent possible, the Licensor waives any right to 203 | collect royalties from You for the exercise of the Licensed 204 | Rights, whether directly or through a collecting society 205 | under any voluntary or waivable statutory or compulsory 206 | licensing scheme. In all other cases the Licensor expressly 207 | reserves any right to collect such royalties. 208 | 209 | 210 | Section 3 -- License Conditions. 211 | 212 | Your exercise of the Licensed Rights is expressly made subject to the 213 | following conditions. 214 | 215 | a. Attribution. 216 | 217 | 1. If You Share the Licensed Material (including in modified 218 | form), You must: 219 | 220 | a. retain the following if it is supplied by the Licensor 221 | with the Licensed Material: 222 | 223 | i. identification of the creator(s) of the Licensed 224 | Material and any others designated to receive 225 | attribution, in any reasonable manner requested by 226 | the Licensor (including by pseudonym if 227 | designated); 228 | 229 | ii. a copyright notice; 230 | 231 | iii. a notice that refers to this Public License; 232 | 233 | iv. a notice that refers to the disclaimer of 234 | warranties; 235 | 236 | v. a URI or hyperlink to the Licensed Material to the 237 | extent reasonably practicable; 238 | 239 | b. indicate if You modified the Licensed Material and 240 | retain an indication of any previous modifications; and 241 | 242 | c. indicate the Licensed Material is licensed under this 243 | Public License, and include the text of, or the URI or 244 | hyperlink to, this Public License. 245 | 246 | 2. You may satisfy the conditions in Section 3(a)(1) in any 247 | reasonable manner based on the medium, means, and context in 248 | which You Share the Licensed Material. For example, it may be 249 | reasonable to satisfy the conditions by providing a URI or 250 | hyperlink to a resource that includes the required 251 | information. 252 | 253 | 3. If requested by the Licensor, You must remove any of the 254 | information required by Section 3(a)(1)(A) to the extent 255 | reasonably practicable. 256 | 257 | 4. If You Share Adapted Material You produce, the Adapter's 258 | License You apply must not prevent recipients of the Adapted 259 | Material from complying with this Public License. 260 | 261 | 262 | Section 4 -- Sui Generis Database Rights. 263 | 264 | Where the Licensed Rights include Sui Generis Database Rights that 265 | apply to Your use of the Licensed Material: 266 | 267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 268 | to extract, reuse, reproduce, and Share all or a substantial 269 | portion of the contents of the database; 270 | 271 | b. if You include all or a substantial portion of the database 272 | contents in a database in which You have Sui Generis Database 273 | Rights, then the database in which You have Sui Generis Database 274 | Rights (but not its individual contents) is Adapted Material; and 275 | 276 | c. You must comply with the conditions in Section 3(a) if You Share 277 | all or a substantial portion of the contents of the database. 278 | 279 | For the avoidance of doubt, this Section 4 supplements and does not 280 | replace Your obligations under this Public License where the Licensed 281 | Rights include other Copyright and Similar Rights. 282 | 283 | 284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 285 | 286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 296 | 297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 306 | 307 | c. The disclaimer of warranties and limitation of liability provided 308 | above shall be interpreted in a manner that, to the extent 309 | possible, most closely approximates an absolute disclaimer and 310 | waiver of all liability. 311 | 312 | 313 | Section 6 -- Term and Termination. 314 | 315 | a. This Public License applies for the term of the Copyright and 316 | Similar Rights licensed here. However, if You fail to comply with 317 | this Public License, then Your rights under this Public License 318 | terminate automatically. 319 | 320 | b. Where Your right to use the Licensed Material has terminated under 321 | Section 6(a), it reinstates: 322 | 323 | 1. automatically as of the date the violation is cured, provided 324 | it is cured within 30 days of Your discovery of the 325 | violation; or 326 | 327 | 2. upon express reinstatement by the Licensor. 328 | 329 | For the avoidance of doubt, this Section 6(b) does not affect any 330 | right the Licensor may have to seek remedies for Your violations 331 | of this Public License. 332 | 333 | c. For the avoidance of doubt, the Licensor may also offer the 334 | Licensed Material under separate terms or conditions or stop 335 | distributing the Licensed Material at any time; however, doing so 336 | will not terminate this Public License. 337 | 338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 339 | License. 340 | 341 | 342 | Section 7 -- Other Terms and Conditions. 343 | 344 | a. The Licensor shall not be bound by any additional or different 345 | terms or conditions communicated by You unless expressly agreed. 346 | 347 | b. Any arrangements, understandings, or agreements regarding the 348 | Licensed Material not stated herein are separate from and 349 | independent of the terms and conditions of this Public License. 350 | 351 | 352 | Section 8 -- Interpretation. 353 | 354 | a. For the avoidance of doubt, this Public License does not, and 355 | shall not be interpreted to, reduce, limit, restrict, or impose 356 | conditions on any use of the Licensed Material that could lawfully 357 | be made without permission under this Public License. 358 | 359 | b. To the extent possible, if any provision of this Public License is 360 | deemed unenforceable, it shall be automatically reformed to the 361 | minimum extent necessary to make it enforceable. If the provision 362 | cannot be reformed, it shall be severed from this Public License 363 | without affecting the enforceability of the remaining terms and 364 | conditions. 365 | 366 | c. No term or condition of this Public License will be waived and no 367 | failure to comply consented to unless expressly agreed to by the 368 | Licensor. 369 | 370 | d. Nothing in this Public License constitutes or may be interpreted 371 | as a limitation upon, or waiver of, any privileges and immunities 372 | that apply to the Licensor or You, including from the legal 373 | processes of any jurisdiction or authority. 374 | 375 | 376 | ======================================================================= 377 | 378 | Creative Commons is not a party to its public 379 | licenses. Notwithstanding, Creative Commons may elect to apply one of 380 | its public licenses to material it publishes and in those instances 381 | will be considered the “Licensor.” The text of the Creative Commons 382 | public licenses is dedicated to the public domain under the CC0 Public 383 | Domain Dedication. Except for the limited purpose of indicating that 384 | material is shared under a Creative Commons public license or as 385 | otherwise permitted by the Creative Commons policies published at 386 | creativecommons.org/policies, Creative Commons does not authorize the 387 | use of the trademark "Creative Commons" or any other trademark or logo 388 | of Creative Commons without its prior written consent including, 389 | without limitation, in connection with any unauthorized modifications 390 | to any of its public licenses or any other arrangements, 391 | understandings, or agreements concerning use of licensed material. For 392 | the avoidance of doubt, this paragraph does not form part of the 393 | public licenses. 394 | 395 | Creative Commons may be contacted at creativecommons.org. 396 | -------------------------------------------------------------------------------- /LICENSE_MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Airscript 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. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | 3 | CI_IMAGE_NAME = airscript/ci:base 4 | TESTS_IMAGE_NAME = airscript/tests:base 5 | BLOG_IMAGE_NAME = airscript/blog:compose 6 | DIND_IMAGE_NAME = docker:28.2.2-dind-alpine3.21 7 | 8 | DEVCONTAINER_NAME = airscript-devcontainer-base 9 | DEVCONTAINER_IMAGE_NAME = airscript/devcontainer:base 10 | DEVCONTAINER_CLI_IMAGE_NAME = airscript/devcontainer:cli 11 | 12 | .SUFFIXES: 13 | .SUFFIXES: .sh 14 | 15 | .PHONY: all 16 | all: setup build run 17 | 18 | .PHONY: setup 19 | setup: 20 | git config --local core.hooksPath .githooks/ 21 | 22 | .PHONY: clean 23 | clean: 24 | docker compose down 25 | docker rmi $(BLOG_IMAGE_NAME) 26 | cd ./themes/PaperMod && find . -name "*" -delete 27 | cd ./tests/bats && find . -name "*" -delete 28 | cd ./tests/libraries/bats-assert && find . -name "*" -delete 29 | cd ./tests/libraries/bats-support && find . -name "*" -delete 30 | 31 | .PHONY: hash 32 | hash: 33 | cat static/css/offline.css | openssl dgst -sha512 -binary | openssl base64 -A 34 | cat static/js/notifications/dictionary.js | openssl dgst -sha512 -binary | openssl base64 -A 35 | cat static/js/notifications/i18n.js | openssl dgst -sha512 -binary | openssl base64 -A 36 | cat static/js/notifications/main.js | openssl dgst -sha512 -binary | openssl base64 -A 37 | 38 | .PHONY: build 39 | build: git-submodules 40 | docker compose build 41 | 42 | .PHONY: run 43 | run: 44 | docker compose up -d 45 | 46 | .PHONY: all-tests 47 | all-tests: build-tests run-tests 48 | 49 | .PHONY: clean-tests 50 | clean-tests: 51 | docker rmi $(TESTS_IMAGE_NAME) 52 | 53 | .PHONY: build-tests 54 | build-tests: 55 | mkdir -p tmp && \ 56 | cp -r .git .docker scripts tests Makefile tmp && \ 57 | docker build -f .docker/dockerfiles/tests.Dockerfile -t $(TESTS_IMAGE_NAME) .; \ 58 | rm -rf tmp 59 | 60 | .PHONY: run-tests 61 | run-tests: 62 | docker run --rm $(TESTS_IMAGE_NAME) && \ 63 | docker rmi $(TESTS_IMAGE_NAME) 64 | 65 | .PHONY: all-ci 66 | all-ci: build-ci run-ci 67 | 68 | .PHONY: clean-ci 69 | clean-ci: 70 | docker rmi $(CI_IMAGE_NAME) 71 | 72 | .PHONY: build-ci 73 | build-ci: 74 | mkdir -p tmp && \ 75 | cp -r .circleci .docker scripts Makefile tmp && \ 76 | docker build -f .docker/dockerfiles/ci.Dockerfile -t $(CI_IMAGE_NAME) .; \ 77 | rm -rf tmp 78 | 79 | .PHONY: run-ci 80 | run-ci: 81 | docker run --rm $(CI_IMAGE_NAME) && \ 82 | docker rmi $(CI_IMAGE_NAME) 83 | 84 | .PHONY: all-devcontainer 85 | all-devcontainer: build-devcontainer run-devcontainer 86 | 87 | .PHONY: build-devcontainer 88 | build-devcontainer: 89 | mkdir -p tmp 90 | cp -r .devcontainer .docker scripts Makefile tmp 91 | 92 | docker build \ 93 | -f .docker/dockerfiles/devcontainer.Dockerfile \ 94 | -t $(DEVCONTAINER_IMAGE_NAME) . 95 | 96 | rm -rf tmp 97 | 98 | .PHONY: run-devcontainer 99 | run-devcontainer: 100 | docker run \ 101 | --rm \ 102 | --name $(DEVCONTAINER_NAME) \ 103 | --volume /var/run/docker.sock:/var/run/docker.sock \ 104 | $(DEVCONTAINER_IMAGE_NAME) 105 | 106 | make clean-devcontainer 107 | 108 | .PHONY: clean-devcontainer 109 | clean-devcontainer: 110 | docker rmi $(DIND_IMAGE_NAME) || true 111 | docker rmi $(DEVCONTAINER_IMAGE_NAME) 112 | docker rmi $(DEVCONTAINER_CLI_IMAGE_NAME) 113 | 114 | .PHONY: teardown-devcontainer 115 | teardown-devcontainer: 116 | sh ./scripts/devcontainer/teardown.sh 117 | 118 | .PHONY: install-bash 119 | install-bash: 120 | sh ./scripts/install/bash.sh 121 | 122 | .PHONY: install-bats 123 | install-bats: 124 | sh ./scripts/install/bats.sh 125 | 126 | .PHONY: install-npm 127 | install-npm: 128 | bash ./scripts/install/npm.sh 129 | 130 | .PHONY: install-curl 131 | install-curl: 132 | bash ./scripts/install/curl.sh 133 | 134 | .PHONY: install-hugo 135 | install-hugo: 136 | bash ./scripts/install/hugo.sh 137 | 138 | .PHONY: install-git 139 | install-git: 140 | bash ./scripts/install/git.sh $(environment) 141 | 142 | .PHONY: install-docker-cli 143 | install-docker-cli: 144 | bash ./scripts/install/docker-cli.sh 145 | 146 | .PHONY: install-circleci-cli 147 | install-circleci-cli: 148 | bash ./scripts/install/circleci-cli.sh 149 | 150 | .PHONY: install-netlify-cli 151 | install-netlify-cli: 152 | bash ./scripts/install/netlify-cli.sh 153 | 154 | .PHONY: install-python3 155 | install-python3: 156 | bash ./scripts/install/python3.sh 157 | 158 | .PHONY: install-gpp 159 | install-gpp: 160 | bash ./scripts/install/gpp.sh 161 | 162 | .PHONY: install-devcontainer-cli 163 | install-devcontainer-cli: 164 | bash ./scripts/install/devcontainer-cli.sh 165 | 166 | .PHONY: ci-verify 167 | ci-verify: 168 | bash ./scripts/ci/verify.sh $(environment) 169 | 170 | .PHONY: ci-build 171 | ci-build: 172 | bash ./scripts/ci/build.sh 173 | 174 | .PHONY: ci-deploy 175 | ci-deploy: 176 | bash ./scripts/ci/deploy.sh $(id) $(token) 177 | 178 | .PHONY: ci-publish 179 | ci-publish: docker-login docker-build docker-push 180 | 181 | .PHONY: git-submodules 182 | git-submodules: 183 | bash ./scripts/shared/git-submodules.sh $(environment) 184 | 185 | .PHONY: docker-login 186 | docker-login: 187 | bash ./scripts/docker/login.sh $(username) $(token) 188 | 189 | .PHONY: docker-build 190 | docker-build: 191 | bash ./scripts/docker/build.sh $(tag) 192 | 193 | .PHONY: docker-push 194 | docker-push: 195 | bash ./scripts/docker/push.sh $(tag) 196 | 197 | .PHONY: tests-base 198 | tests-base: 199 | bash scripts/tests/base.sh 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blog 2 | This repository contains source code and content of my blog hosted on [blog.airscript.it](https://blog.airscript.it). 3 | 4 | ## Contents 5 | - [Installation](#installation) 6 | - [Usage](#usage) 7 | - [Resources](#resources) 8 | - [Contributing](#contributing) 9 | - [Support](#support) 10 | - [License](#license) 11 | 12 | ## Installation 13 | In order to contribute to this project, you need an up and running development environment. 14 | Follow the steps below in order to have one fully functional. 15 | Please note that only one path between *Classic* and *Dev Container* has to be followed. 16 | 17 | ### Classic 18 | Make sure to have these dependencies installed on your machine: 19 | - [Bash](https://www.gnu.org/software/bash/) 20 | - [Make](https://www.gnu.org/software/make/) 21 | - [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) 22 | - [Docker](https://docs.docker.com/get-docker/) 23 | - [Docker Compose](https://docs.docker.com/compose/install/) 24 | 25 | Then, clone this repository: 26 | ```bash 27 | git clone https://github.com/Airscripts/blog.git 28 | ``` 29 | 30 | ### Dev Container 31 | Make sure to have these dependencies installed on your machine: 32 | - [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) 33 | - [Bash](https://www.gnu.org/software/bash/) 34 | - [Docker](https://docs.docker.com/get-docker/) 35 | - [Visual Studio Code](https://code.visualstudio.com/Download) 36 | - [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) 37 | 38 | Then, clone this repository: 39 | ```bash 40 | git clone https://github.com/Airscripts/blog.git 41 | ``` 42 | 43 | ## Usage 44 | To use this project, you have also two different possibilities: 45 | 46 | ### Classic 47 | Run the following commands in the repository's root folder: 48 | ```bash 49 | make all 50 | ``` 51 | 52 | Everything should be set up and running on port 25001. 53 | 54 | ### Dev Container 55 | Open it in Visual Studio Code and then confirm the will to open it into a devcontainer. 56 | To make it work here, be sure to have installed *Dev Containers* extension. 57 | 58 | Run the following commands in the repository's root folder: 59 | ```bash 60 | make all 61 | ``` 62 | 63 | Everything should be set up and running on port 25001. 64 | 65 | ## Resources 66 | - [PageSpeed Insights Report](https://pagespeed.web.dev/report?url=https%3A%2F%2Fblog.airscript.it%2F) 67 | - [Mozilla Observatory](https://observatory.mozilla.org/analyze/blog.airscript.it) 68 | - [Security Headers](https://securityheaders.com/?q=blog.airscript.it&hide=on&followRedirects=on) 69 | 70 | ## Contributing 71 | Contributions and suggestions about how to improve the blog are welcome! 72 | 73 | ## Support 74 | If you want to support my work you can do it by following me, leaving a star, sharing my projects or also donating at the links below. 75 | Choose what you find more suitable for you: 76 | 77 | 78 | GitHub Sponsors 79 |   80 | 81 | Kofi 82 | 83 | 84 | ## License 85 | This repository has dual-licensing. 86 | This means that for its source code [MIT License](https://github.com/airscripts/blog/blob/main/LICENSE_MIT) applies and for blog posts [Creative Commons Attribution 4.0 International](https://github.com/airscripts/blog/blob/main/LICENSE_CC_BY_4.0) is applied. 87 | -------------------------------------------------------------------------------- /README_DOCKER_HUB.md: -------------------------------------------------------------------------------- 1 | # Quick Reference 2 | - Maintained by: 3 | [Airscript](https://github.com/airscripts) 4 | 5 | - Where to get help: 6 | [GitHub Repository](https://github.com/Airscripts/blog/issues/) 7 | 8 | # Supported Tags 9 | Latest tag supported only. 10 | 11 | # About 12 | This is my personal blog where I write posts about computer science, motivation and much more. 13 | It is open source so that anybody can improve it freely or just take inspiration. 14 | 15 | # License 16 | This repository has dual-licensing. 17 | This means that for its source code [MIT License](https://github.com/Airscripts/blog/blob/main/LICENSE_MIT) applies and for blog posts [Creative Commons Attribution 4.0 International](https://github.com/Airscripts/blog/blob/main/LICENSE_CC_BY_4.0) is applied. 18 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | | Version | Supported | 5 | | ------- | ------------------ | 6 | | 1.x.x | :white_check_mark: | 7 | 8 | ## Reporting a Vulnerability 9 | To report a vulnerability, open an [issue](https://github.com/Airscripts/blog/issues/new/choose). 10 | -------------------------------------------------------------------------------- /archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/assets/.gitkeep -------------------------------------------------------------------------------- /assets/css/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/assets/css/.gitkeep -------------------------------------------------------------------------------- /assets/css/extended/main.css: -------------------------------------------------------------------------------- 1 | html { 2 | min-width: 320px; 3 | } -------------------------------------------------------------------------------- /assets/css/extended/menu.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | display: flex; 3 | list-style: none; 4 | overflow-x: auto; 5 | white-space: nowrap; 6 | word-break: keep-all; 7 | margin: auto var(--gap); 8 | } 9 | 10 | .menu a { 11 | font-size: 16px; 12 | } 13 | 14 | .menu li+li { 15 | margin-inline-start: var(--gap); 16 | } 17 | 18 | .menu .active { 19 | font-weight: 500; 20 | border-bottom: 2px solid currentColor; 21 | } 22 | 23 | #menu-trigger { 24 | display: none; 25 | } 26 | 27 | @media screen and (max-width: 768px) { 28 | .menu { 29 | right: 0; 30 | z-index: 5; 31 | display: block; 32 | list-style: none; 33 | line-height: 2.5; 34 | position: absolute; 35 | padding: var(--gap); 36 | margin-bottom: var(--gap); 37 | background: var(--code-bg); 38 | border-radius: var(--radius); 39 | border: 2px solid var(--tertiary); 40 | margin: calc(var(--header-height) - var(--gap)) var(--gap); 41 | } 42 | 43 | .menu li+li { 44 | margin-inline-start: 0; 45 | } 46 | 47 | .menu.hidden { 48 | display: none; 49 | } 50 | 51 | .list .menu { 52 | background: var(--entry); 53 | } 54 | 55 | #menu-trigger { 56 | float: right; 57 | display: block; 58 | font-size: 30px; 59 | position: relative; 60 | margin: auto var(--gap); 61 | } 62 | } -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | theme: "PaperMod" 2 | enableEmoji: true 3 | title: "airscript.it" 4 | enableRobotsTXT: true 5 | pygmentsUseClasses: true 6 | copyright: "airscript.it" 7 | enableInlineShortcodes: true 8 | baseURL: "https://blog.airscript.it" 9 | 10 | pagination: 11 | pagerSize: 10 12 | 13 | menu: 14 | main: 15 | - weight: 5 16 | name: "Archive" 17 | url: "archives/" 18 | 19 | - weight: 10 20 | name: "About" 21 | url: "about/" 22 | pageRef: "about" 23 | identifier: "About" 24 | 25 | - weight: 15 26 | name: "Search" 27 | url: "search/" 28 | pageRef: "search" 29 | identifier: "Search" 30 | 31 | taxonomies: 32 | tag: "tags" 33 | category: "categories" 34 | 35 | markup: 36 | highlight: 37 | style: "dracula" 38 | 39 | params: 40 | showToc: true 41 | showWordCount: true 42 | 43 | homeInfoParams: 44 | title: "Hey there!" 45 | 46 | content: | 47 | I am Francesco known as Airscript on the web and I warmly welcome you on my blog! 48 | Here you'll find articles related to open source, motivation and much more. 49 | If you want, you can support me through the links below or leaving a star at my [blog on GitHub](https://github.com/Airscripts/blog.airscript.it). 50 |   51 | Spared no expense! 52 | *John Hammond, Jurassic Park.* 53 | 54 | label: 55 | icon: "logo.svg" 56 | iconWidth: 30 57 | iconHeight: 30 58 | 59 | defaultTheme: "auto" 60 | showReadingTime: true 61 | showShareButtons: false 62 | showCodeCopyButtons: true 63 | disableLanguageSwitch: true 64 | 65 | assets: 66 | disableHLJS: true 67 | theme_color: "#0f94d2" 68 | msapplication_TileColor: "#2b5797" 69 | 70 | images: 71 | - "/logo-512x512" 72 | 73 | customStyles: 74 | - file: "/css/offline.css" 75 | integrity: "sha512-+R/cu1jJ/RrydyUhKhXI1QczU3TRLLLHAQyYHi1vXFAEF8lK4MxJiWgjIckiCegJ80aIB6icc6lSoLn1YY/OSA==" 76 | 77 | notificationsScripts: 78 | - file: "/js/notifications/dictionary.js" 79 | integrity: "sha512-tOZZsofKwRGHAcQVGMed077Q0y4hnPvTv0Nw8L9VYWKlQgWcQZznMXZTTNID39Q0+Dumx+kHl7PlP7K+cGn6nQ==" 80 | - file: "/js/notifications/i18n.js" 81 | integrity: "sha512-eNnuCLQ8noOgoy620xyZxApQlMLSJZze6Qe/h/uKQIynxfvYfmL29FimkcLho1i7AGeG+tkh0WM5pnBcIn82Hg==" 82 | - file: "/js/notifications/main.js" 83 | integrity: "sha512-SAID9CBhh48e0EabUHvgvRrh2FiCmBh5Xb+fX2sv5P9IhYvRC73fYNHWg6usTYMyEOvJ6uEuP9y7nTQIgr0f7w==" 84 | 85 | menuScripts: 86 | - file: "/js/menu.js" 87 | integrity: "sha512-XF6O1Z7tmFdMKJug1taoTIEN5erd8st9wgg3kujj3zIB9ErdmlzR499Eup9AKwDXeI2O6BnABt/6fWqvmzkOJw==" 88 | 89 | socialIcons: 90 | - name: "github" 91 | url: "https://github.com/sponsors/Airscripts" 92 | - name: "KoFi" 93 | url: "https://ko-fi.com/airscript" 94 | - name: "RSS" 95 | url: "https://blog.airscript.it/index.xml" 96 | 97 | editPost: 98 | appendFilePath: false 99 | text: "Suggest Changes" 100 | url: "https://github.com/Airscripts/blog/tree/main/content" 101 | 102 | customScripts: [] 103 | 104 | outputs: 105 | home: 106 | - "HTML" 107 | - "RSS" 108 | - "JSON" 109 | -------------------------------------------------------------------------------- /content/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "About" 3 | layout: "about" 4 | date: "2022-08-12" 5 | author: "Airscript" 6 | categories: ["general"] 7 | tags: ["airscript", "about"] 8 | images: ["/logo-open-graph.png"] 9 | summary: "Blog's about page where I tell about who I am, what I do and the objectives of the blog." 10 | --- 11 | > To make something special, you just have to believe it's special. 12 | > *Mr. Ping, Kung Fu Panda* 13 | 14 | ## Hello World! 15 | Welcome to my blog! 16 | I’m Francesco, known online as **Airscript**. 17 | 18 | Since I was a kid, I’ve always been curious about the world around me—videogames, sports, cinematography—just to name a few of the countless things that fascinate me. 19 | 20 | Oh, and let’s not forget paleontology—especially **dinosaurs**. 21 | *Between us, I didn’t really forget them. I just wanted to make sure they got the spotlight they deserve.* 22 | 23 | But out of everything, computer science is what stuck with me the most. 24 | The idea that I could build tools to improve people's lives through code got me hooked early on. What started as a spark turned into a full-blown **passion**, and eventually, my **career**. 25 | 26 | Today, I work as a **freelance software engineer**, helping bring ideas to life through technology. 27 | 28 | But enough introductions—let me tell you why I decided to start this blog. 29 | 30 | --- 31 | 32 | ## Why a Blog? 33 | In 2022, I made a decision: I wanted to put myself out there and connect with others in my field. 34 | The spark? Discovering [Progetto Happiness][progetto-happiness]. 35 | 36 | If you haven’t heard of it, it’s an initiative exploring what happiness really is—through questions asked to some truly incredible people. 37 | 38 | So here I am! 39 | Like Giuseppe from the project, I want to share the beauty I see every day in the people around me. 40 | 41 | This past year has given me so much, and now I’d love to give something back—by writing about it here. 42 | 43 | --- 44 | 45 | ## What Can I Read? 46 | Since I’m a huge fan of computer science, that’ll be the main theme. But I’ll explore it my way. 47 | 48 | How? With a pinch of **philosophy** and **simplicity**—just like me. 49 | 50 | That said, I want to connect with you, the reader. So from time to time, you’ll also find more personal posts—stories from my daily adventures, lessons learned, and maybe a few random thoughts too. 51 | 52 | --- 53 | 54 | ## Who’s It For? 55 | This blog is for anyone looking for a fresh perspective. 56 | For anyone who loves to question things—or just wants to learn something new. 57 | 58 | And hey, even if you’re just curious about why I go by `airscript`, you’re in the right place. 59 | 60 | --- 61 | 62 | ## Where Can I Find You? 63 | Want to follow along? I’ve dropped some helpful links below. 64 | 65 | But first—a quick note. This blog is **fully open source**. 66 | That means you can contribute to its development, collaborate on articles, or simply draw inspiration from it. 67 | 68 | If you'd like to support the project, feel free to leave a star on [GitHub][github-blog]—I'd really appreciate it! 69 | 70 | And now, as promised, here are the links: 71 | - [airscript.it][airscript-it] — your hub for all my social links and updates. 72 | - [GitHub][github] — where you’ll find all my open source projects. 73 | 74 | [airscript-it]: https://airscript.it 75 | [github]: https://github.com/airscripts 76 | [github-blog]: https://github.com/Airscripts/blog 77 | [progetto-happiness]: https://progettohappiness.com/il-progetto/ 78 | -------------------------------------------------------------------------------- /content/archives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Archive" 3 | layout: "archives" 4 | summary: "Blog's archives." 5 | --- -------------------------------------------------------------------------------- /content/offline.md: -------------------------------------------------------------------------------- 1 | --- 2 | type: "offline" 3 | layout: "offline" 4 | searchHidden: true 5 | robotsNoIndex: true 6 | title: "You are offline" 7 | --- 8 | Looks like you're offline. -------------------------------------------------------------------------------- /content/posts/foss/awesome-steam-deck.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: "2023-07-17" 3 | author: "Airscript" 4 | title: "Awesome Steam Deck" 5 | categories: ["foss"] 6 | tags: ["airscript", "open source", "steam deck"] 7 | images: ["/images/logo-steam-deck.png", "/logo-open-graph.png"] 8 | summary: "A presentation of a new open source Awesome List for Steam Deck." 9 | --- 10 | 11 | ![name](/images/logo-steam-deck.png#center) 12 | 13 | ## Introduction 14 | Hey there! I am Francesco known as Airscript on the web. 15 | Today with this blog post I want to share with you a new open source project that I'm developing: [Awesome Steam Deck][awesome-steam-deck]. 16 | 17 | --- 18 | 19 | ## Why An Awesome List? 20 | I've recently bought a Steam Deck and as always, I just started learning everything that I could learn about it. 21 | So I've gathered information around all the web: from Reddit, independent blogs or even videos. 22 | 23 | After all this research, something clicked in my mind and I told myself: "Maybe there is an Awesome List for this!" 24 | I was wrong. Inside [Awesome][awesome] I didn't find out something related. Only a few projects around GitHub but not updated anymore. 25 | So I've decided to try in doing one myself, because I wanted to be of help to others and contribute to this wonderful ecosystem that Valve made. 26 | 27 | --- 28 | 29 | ## How Have You Started? 30 | I started from looking at the [guidelines][guidelines] of an Awesome List. 31 | You need a lot of things to be compliant with Awesome, so I decided to learn about how to start properly first. 32 | Next to this, I needed to gather information. Since I am familiar with interacting with communities, I found out one on Telegram called [Steam Deck Italia][steam-deck-italia]. 33 | Here I have found some marvelous people that shared knowledge freely and I've later decided to do a partnership with them to give thanks for the indirect help they gave. 34 | 35 | After I had a small basis, I tried to reach out a bigger audience on Reddit. What I found there was mindblowing. 36 | The project has been loved by many and a few people also gave me their projects in order to be included and maintained by me into my GitHub repository. 37 | That's where I just made the final changes and findings for the list. 38 | People has started to share the list each other finding it useful and that just filled me up with happiness. 39 | 40 | --- 41 | 42 | ## What's Next? 43 | In order to be a certified Awesome List, the list itself has to be as complete as possible and at least 30 days old. 44 | Right now we're in the second week of life so there's much time ahead. 45 | I've set some goals to reach before this three weeks finish up: 46 | - Reach 100 stars: it would be an awesome welcome ticket for Awesome; 47 | - Internationalize the project: accessibility is key for knowledge like this; 48 | - Make it as viral as possible: the purpose of this is to help, so the main thing is this. 49 | 50 | --- 51 | 52 | ## Conclusion 53 | So this is my new project. We have seen together why and how I started it and what goals I've set for it. 54 | I'm looking forward to have contributors both for the list itself and for the internationalization part. 55 | If you know spanish, french or german, it would be awesome and well appreciated your pull request. 56 | Otherwise other types of contributions are always welcome, you know that. 57 | Thank you kindly for reading this article! 58 | 59 | --- 60 | 61 | ## Support 62 | If you have liked this post, just come and tell me! 63 | Are you too shy for doing this? No problem. Just visit [airscript.it][airscript-it] and share your support following me on your preferred social platform. 64 | If you want to make me even more happier, just follow, share or star me and my projects on [GitHub][github]. 65 | 66 | [airscript-it]: https://airscript.it 67 | [github]: https://github.com/airscripts 68 | [steam-deck-italia]: https://t.me/SteamDeckIta 69 | [awesome]: https://github.com/sindresorhus/awesome 70 | [awesome-steam-deck]: https://github.com/airscripts/awesome-steam-deck 71 | [guidelines]: https://github.com/sindresorhus/awesome/blob/main/create-list.md 72 | -------------------------------------------------------------------------------- /content/posts/foss/building-anally-fast-stuff.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: "2023-07-31" 3 | author: "Airscript" 4 | title: "Building Anally Fast Stuff" 5 | categories: ["foss"] 6 | tags: ["airscript", "open source", "esolangs"] 7 | images: ["/images/cover-analscript.png", "/logo-open-graph.png"] 8 | summary: "A modern approach for writing anally fast stuff with Analscript." 9 | --- 10 | 11 | ![name](/images/cover-analscript.png#center) 12 | 13 | ## Introduction 14 | Hey there! I am Francesco known as Airscript on the web. 15 | Today I want to share with you my first experience building a joke [esoteric programming language][esolangs-org]: [Analscript](https://github.com/airscripts/analscript). 16 | We will go through how I have started, what I have learned and how I have realized all of this. 17 | 18 | --- 19 | 20 | ## History Behind The Joke 21 | All started the day I've decided to give my GitHub sponsors some perks. 22 | One of those perks is the possibility to have their usernames written in a large variety of esolangs. 23 | So, when a new sponsor came up, I had to ask for which esolang the username would be written it in...and then a wild AnalLang appeared. 24 | Yes, you heard it right: [AnalLang][anallang]. 25 | 26 | --- 27 | 28 | ## The Dad Of Analscript 29 | I jumped right into the action and read about AnalLang onto the [bible of esolangs][esolangs]. 30 | The thing that jumps right in my face, during the lecture, is that the project got deleted. And with it also its creator. 31 | All gone. Everything. 32 | I tried to recover it from [npm][npm-js] but nothing was working, even if I had found the original project. 33 | I took it personally and decided to make a new AnalLang, something that had everything his father had but with a modern approach. 34 | And that is how my journey begins. 35 | 36 | --- 37 | 38 | ## Anal-yzing The Project 39 | The first thing that I did was to learn how AnalLang worked, or at least how was intended to work originally. 40 | It is very simple: you convert the characters to their corresponding [ASCII][ascii] code and then simply write N times this emoji combination: 🍑🍆. 41 | This is, basically, AnalLang. Simple, right? 42 | 43 | --- 44 | 45 | ## Writing Down The Foundation 46 | Now that I had a good idea about how everything worked, I just jumped out making some decisions. 47 | The goal here was to give everything daddy had, even the basic runtime he used: [Node.js][node-js]. 48 | I've scaffolded a project with the latest LTS as of this time, v18, and jumped right in making the standard library. 49 | The first thing I've worked on were the two main functions: **anallify** and **stringify**. Respectively one for transforming string to anal content and the other to reverse them. 50 | Once done this, I was literally at a good point with the language. 51 | 52 | --- 53 | 54 | ## Exposing Everything 55 | Once I had the standard library, I needed to choose first how users could consume this language. 56 | I thought to start with two simple ways: a CLI and a simple import as a libary. 57 | For the latter, it was really easy: I have just exposed the modules I wanted through the use of [ES Modules][javascript-modules]. 58 | The CLI was a little bit more interesting to do. 59 | Did you know that you can add a bin key into your package.json and that just makes a binary for your lib? It is literally amazing. 60 | 61 | ```json 62 | { 63 | "bin": { 64 | "analscript": "analscript.js" 65 | } 66 | } 67 | ``` 68 | > With this simple line, when bundling the project, you will have a fantastic binary to run everything from. 69 | 70 | Once done this, I had to choose the commands to expose and everything was set. 71 | At the end I've chosen to expose anallify and stringify for doing [JIT][jit] encoding and decoding for various use cases. Like making stuff in a simple pipeline for example. 72 | Then I've added two special commands that gave us the power to use .anal files: run and compile. 73 | Compile just compiles everything you give it into an .anal compliant file. Run...you can imagine or try it by yourself. 74 | 75 | --- 76 | 77 | ## Wrapping The Whole Package 78 | At the end of the day, I wanted to give some robustness to everything. 79 | My main goals were: testing, documentation, listing, automation and inclusion. 80 | - **Testing**: this one was really simple to accomplish and I have just used vitest for writing all the unit tests. 81 | With the help of [@mateonunez][mateo-nunez], we also improved code coverage of the whole project. 82 | - **Documentation**: with this step I am still working. I have decided to make use of [Docusaurus][docusaurus], just to keep everything inside JavaScript ecosystem and of course to keep it comprehensible for future Analscripters. 83 | - **Listing**: the world had to knew who is the new boss in the city. For this reason, I have added [Analscript to esolangs.org][esolangs-analscript]. 84 | - **Automation**: who doesn't love automation? Analscript for sure loves it. Thanks to [CircleCI][circleci] I was able to setup a fantastic workflow for running automated tests. And this closes the Circle...CI. 85 | - **Inclusion**: what if I don't know how to run this project on my machine or am I having problems with it? Simple: I left a [container image][docker-hub-analscript] ready for you. Nothing more to say. 86 | 87 | --- 88 | 89 | ## What I Have Learned 90 | After creating Analscript I learned something valuable, beside all the technical knowledge that I gathered from it: even the simplest project can be valuable if you give it the possibility to do it. 91 | So just do what you want to do! Even if it is a simple Hello World. 92 | You can always learn something new and obtain a lesson from it. 93 | 94 | --- 95 | 96 | ## Conclusion 97 | So wrapping things up, we have seen the history behind the idea, what was AnalLang, how I've built everything and the main aspects that I have focused on when completing the project. 98 | In the end everything has a lesson so why don't just share it with you too? 99 | I hope that this post was fun and informative for you. I will see you in undefined days. Thank you kindly. 100 | 101 | --- 102 | 103 | ## Support 104 | If you have liked this post, just come and tell me! 105 | Are you too shy for doing this? No problem. Just visit [airscript.it][airscript-it] and share your support following me on your preferred social platform. 106 | If you want to make me even more happier, just follow, share or star me and my projects on [GitHub][github]. 107 | 108 | [node-js]: https://nodejs.org 109 | [npm-js]: https://npmjs.com 110 | [circleci]: https://circleci.com 111 | [docusaurus]: https://docusaurus.io/ 112 | [airscript-it]: https://airscript.it 113 | [esolangs-org]: https://esolangs.org 114 | [github]: https://github.com/airscripts 115 | [ascii]: https://en.wikipedia.org/wiki/ASCII 116 | [mateo-nunez]: https://github.com/mateonunez 117 | [anallang]: https://esolangs.org/wiki/AnalLang 118 | [jit]: https://en.wikipedia.org/wiki/Lean_manufacturing 119 | [esolangs-analscript]: https://esolangs.org/wiki/Analscript 120 | [esolang]: https://esolangs.org/wiki/Esoteric_programming_language 121 | [docker-hub-analscript]: https://hub.docker.com/r/airscript/analscript 122 | [javascript-modules]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules 123 | -------------------------------------------------------------------------------- /content/posts/green-bytes/less-feetpics-less-footprint.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: "2024-12-18" 3 | author: "Airscript" 4 | title: "Less Feetpics, Less Footprint" 5 | categories: ["green bytes"] 6 | tags: ["airscript", "green bytes", "data"] 7 | images: ["/images/less-feetpics-less-footprint.png", "/logo-open-graph.png"] 8 | summary: "Cutting back on data? It's not that bad after all, and it helps the planet." 9 | --- 10 | 11 | ![name](/images/less-feetpics-less-footprint.png#center) 12 | 13 | > The data mentioned in this article, including comparisons between streaming emissions and car travel, is presented as a narrative example to highlight the environmental impact of digital consumption. While these numbers serve to illustrate the broader issue, they may not reflect the most current data available. The landscape of digital energy consumption and carbon emissions is constantly evolving, and figures referenced may have changed since they were first cited. For the most up-to-date information, we encourage readers to consult recent studies and reports from trusted sources. 14 | 15 | ## Introduction 16 | In today's world, it’s hard to imagine a day without using data — from streaming media and browsing the web to posting on social media. While these digital experiences add convenience and entertainment to our lives, the environmental cost is often overlooked. Every time we consume data, whether by streaming a video or browsing Instagram, we contribute to the carbon footprint of the internet. 17 | 18 | As a software engineer, I've become more conscious of this issue, especially after I had to manage my data usage with a limited data plan from my internet provider. That experience made me realize how much data we consume without even thinking about it — and the ecological impact that comes with it. But here’s the good news: by tracking and reducing our data consumption, we can make a tangible difference. Let’s dive into how small changes, like using data-saving features in apps, can help conserve resources and reduce environmental impact. 19 | 20 | --- 21 | 22 | ## The Ecological Cost of Data Consumption 23 | It’s easy to forget that behind every click, swipe, and download, there’s a significant amount of energy being used to store and transmit that data. The internet relies on vast networks of servers and data centers that require substantial power to operate. As the digital economy continues to grow, the ecological cost is becoming increasingly apparent. In fact, the Shift Project reports that the digital economy contributes about [4% of global CO2 emissions][shift-project-report] — and this figure is only expected to rise. 24 | 25 | Streaming services and social media platforms, which are heavy data consumers, play a major role in this issue. For example, streaming an hour of high-definition video can emit the same amount of [CO2 as driving a car for 10 miles][iea-co2-source]. As more people engage with these services, the demand for data centers grows, which directly contributes to higher carbon emissions. 26 | 27 | --- 28 | 29 | ## Why Data-Saving Features Matter 30 | As someone in the software field, I’ve spent a lot of time considering how we can improve efficiency in app development. One of the simplest ways to reduce your environmental impact as a user is by leveraging the data-saving features that most apps offer today. These features are designed to reduce the amount of data consumed, which in turn decreases the energy needed by data centers. 31 | 32 | Take Instagram, for example. The platform has a “Data Saver” mode that lowers the quality of images and videos when you’re browsing or watching content. This not only helps save your mobile data but also reduces the energy consumed by the app, benefiting both your wallet and the environment. Other apps like Facebook and YouTube have similar features, making it easier than ever to reduce your data usage without sacrificing the user experience. 33 | 34 | Another area where we can save data is with video podcasts. While watching video podcasts can be enjoyable, the reality is that video quality isn’t always necessary for the content to be valuable. Consider switching to audio-only modes for podcasts, which not only saves data but also provides a more focused experience. It’s a small change, but it’s an easy way to minimize data consumption without losing the essence of the content. 35 | 36 | --- 37 | 38 | ## Tracking Your Data Usage for Sustainability 39 | When I was limited by a data cap, I started paying much closer attention to my usage. Tracking how much data I was consuming really opened my eyes to how quickly it can add up. Luckily, most mobile carriers and apps provide tools to monitor your data usage, which can help you spot areas where you can cut back. 40 | 41 | It might sound like a small thing, but something as simple as switching from high-definition streaming to standard-definition can make a noticeable difference. Also, adopting a more mindful approach to digital habits, like reducing unnecessary notifications or cutting down on endless scrolling, can help conserve data while also promoting a more focused, intentional use of technology. 42 | 43 | One area where this mindset can be applied is when downloading new video games. With next-gen games being larger than ever, downloading a game without doing proper research on whether you’ll actually enjoy it can result in unnecessary data usage. A more sustainable approach would be to only download those games you’re truly excited about and have researched thoroughly beforehand. This way, you're not only saving data but also reducing the environmental impact of storing and streaming those large files. 44 | 45 | --- 46 | 47 | ## How Companies and Developers Can Lead the Way 48 | While individual action is essential, app developers and companies must also prioritize sustainability. As a software engineer, I know firsthand how important it is to design apps that are efficient, power-conscious, and optimized for lower data usage. This includes using techniques like data compression, minimizing unnecessary data transfers, and improving the overall performance of apps to use less energy. 49 | 50 | Big tech companies and data centers are starting to adopt more eco-friendly practices too, such as using renewable energy sources and building energy-efficient infrastructure. Supporting these initiatives — whether by choosing services that prioritize sustainability or by advocating for greener practices — can help accelerate the shift to a more environmentally responsible digital landscape. 51 | 52 | --- 53 | 54 | ## The Role of Data-Saving in Sustainable Digital Practices 55 | Data-saving isn’t just about reducing costs or managing mobile data; it’s an important part of promoting sustainable digital practices. By using features like Data Saver modes in apps such as Instagram, YouTube, and Facebook, we can minimize the load on data centers, which in turn helps lower carbon emissions. 56 | 57 | The more we adopt these habits, the more we can help reduce the overall environmental impact of the digital world. Whether you’re a software engineer like me or just someone who wants to make more eco-conscious choices, there are simple actions we can all take to make a difference. 58 | 59 | --- 60 | 61 | ## Conclusion 62 | As we become more connected, the environmental cost of our digital activities is only going to increase. But by making small changes, like enabling data-saving features or tracking our data usage, we can significantly reduce our carbon footprints. It’s not just about saving data — it’s about being mindful of how our habits impact the planet. 63 | 64 | So, take a minute today to enable data-saving modes on your favorite apps, track your data consumption, and share these tips with others. We may be living in a digital age, but that doesn’t mean we can’t make it more sustainable for the future. 65 | 66 | --- 67 | 68 | ## Support 69 | If you enjoyed this post, I’d love to hear from you! 70 | Not ready to speak up? No worries — just head over to [airscript.it][airscript-it] and show your support by following me on your favorite social platform. 71 | Want to make my day even better? Follow, share, or star my projects on [GitHub][github] to help me grow and keep creating. Your support means the world! 72 | 73 | [airscript-it]: https://airscript.it 74 | [github]: https://github.com/airscripts 75 | [shift-project-report]: https://theshiftproject.org/wp-content/uploads/2019/03/Lean-ICT-Report_The-Shift-Project_2019.pdf 76 | [iea-co2-source]: https://www.iea.org/commentaries/the-carbon-footprint-of-streaming-video-fact-checking-the-headlines 77 | -------------------------------------------------------------------------------- /content/posts/life/if-gael-had-turned-back.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: "2025-06-03" 3 | author: "Airscript" 4 | title: "If Gael Had Turned Back" 5 | categories: ["life"] 6 | tags: ["airscript", "life", "dark souls"] 7 | images: ["/images/gael.png", "/logo-open-graph.png"] 8 | summary: "I chased something I thought would save me — but found something else instead." 9 | --- 10 | 11 | ![name](/images/gael.png#center) 12 | 13 | ## Introduction 14 | 15 | Hey there! 16 | It has been quite some time since my last writing. 17 | This time I'm here to give a little life update — the first one over here. 18 | In the last year a lot has happened, and I'd like to talk openly about it since it makes me feel better in the first place. 19 | But before starting, I have to add a note: this post will interlace my life update with a character from *Dark Souls* that I like a lot, called Gael. 20 | Why though? Because I felt like him in recent times, connecting the dots looking backwards. 21 | So without any further ado, let's deep dive into my story. 22 | 23 | --- 24 | 25 | ## At The Gates Of The Ringed City 26 | 27 | This chapter is called *"At The Gates Of The Ringed City"*, a place where Gael goes during a certain moment in history in order to find what he was looking for: the Dark Soul. 28 | This special thing would allow him — and an important person to him — to make a painting of a world. 29 | A new world where people could just... live. 30 | Yes, live, because the world in which the game is set is full of pain and death. 31 | 32 | Now, we can think about this soul just like something to make also my own painting: not necessarily a new world, but a paintbrush to change something in this one we live in and add something we can call value. A deep value. 33 | 34 | So in the last year, I've reached my personal Ringed City — a company that I co-founded and to which I put my dreams, hopes, and effort to make it bloom as the paintbrush we've been talking about a little earlier. 35 | 36 | --- 37 | 38 | ## The Long Walk Through Ash 39 | 40 | With all set up, I started taking this long walk through what was meant as the right path. 41 | I put the work in, faced struggles of various types (not only technical), and tried to form what was the best path possible in conjunction with who I was at the time and what I could do. 42 | 43 | Just like Gael: a simple slave, trying to save the world with what he could afford. 44 | The thing is that not every walk leads to a beautiful ending or panorama. 45 | Sometimes, like how it happens to be in *Dark Souls*, this long road shows the truth that your eyes can't see: an infinite land of ash with just... nothing. Only emptiness. 46 | 47 | And how many times does that happen to all of us, right? 48 | We pursue a road that we think is the best for us, but sooner or later we realize that the magic was only in our eyes... painting a world full of colors. 49 | 50 | --- 51 | 52 | ## The Moment Before The Blood 53 | 54 | When you reach this exact moment in your life, life itself gives you a choice. 55 | You can turn around, retrace your steps, learn from failures and find another way — or you can simply drink what remains of what you were looking for. 56 | You just settle for the drops. And that's what Gael did. 57 | 58 | Arrived at this gigantic land of ash, he decided to take what's left of the Dark Soul (its blood) and drink it for the pain of the reality proposed to him. 59 | Later on, that blood will corrupt him — just like society tries to do to us with what's meant to be right in the work world. 60 | 61 | At this time, I stopped and tried to think about a different ending. 62 | Do I need to end corrupted as Gael or... is there another way? 63 | So I parted ways from what in principle I thought was the best for me and decided to find an alternative paintbrush. An alternative Dark Soul. 64 | 65 | --- 66 | 67 | ## Another Painting 68 | 69 | At the moment of writing, I still don't know what this other painting I'm trying to bring to life will be, but as I like to say (thanks *Jurassic Park*): 70 | *"Life finds a way."* 71 | And so do I. 72 | 73 | But here's what I do know: I want this painting to reflect who I am when no one's watching. 74 | Not who I’m expected to be, not what a title says I should be, and not the shape someone else carved for me. 75 | 76 | I want this painting to be made of: 77 | - **quiet mornings** without anxiety, 78 | - **curiosity that doesn’t burn me out**, 79 | - **projects that don’t bleed purpose dry**, 80 | - and **connections that nourish, not drain**. 81 | 82 | It may take time. It may not be grand. But it’ll be mine. 83 | 84 | Maybe your brush looks different. Maybe you're still in the ashlands. But if you’ve got anything left — even just a spark — you can still choose to paint something better. 85 | Even Gael, in all his madness, made something beautiful in the end. 86 | I just don't want to die to do it. 87 | 88 | --- 89 | 90 | ## Conclusion 91 | 92 | Without entering into deeply personal details, I wanted to write about this life experience for various reasons. 93 | The main one is to share with you a deep thinking I had and to which I know a lot of you can relate, since I'm not the only one looking for a better world out there. 94 | We all live pain, we are all being misunderstood at some point in our lives by someone, but the key here is to find meaning in ourselves and not try to find the *capro espiatorio* to lighten our burden. 95 | Keep being beautiful as you are and when you're facing reality, don't necessarily do as Gael: turn back and look at how wonderful the world can still be. 96 | 97 | --- 98 | 99 | ## Support 100 | If you enjoyed this post, I’d love to hear from you! 101 | Not ready to speak up? No worries — just head over to [airscript.it][airscript-it] and show your support by following me on your favorite social platform. 102 | Want to make my day even better? Follow, share, or star my projects on [GitHub][github] to help me grow and keep creating. Your support means the world! 103 | 104 | [airscript-it]: https://airscript.it 105 | [github]: https://github.com/airscripts 106 | -------------------------------------------------------------------------------- /content/posts/molivair/welcome-molivair.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: "2022-10-12" 3 | author: "Airscript" 4 | title: "Welcome, Molivair" 5 | categories: ["molivair"] 6 | tags: ["airscript", "molivair", "ai"] 7 | images: ["/images/woman-with-a-parasol.png", "/logo-open-graph.png"] 8 | summary: "What is Molivair and what the Outpaintings project consists of." 9 | --- 10 | 11 | ![name](/images/woman-with-a-parasol.png#center) 12 | 13 | ## Introduction 14 | Hey, there! 15 | It has been a while since the last time! 16 | I've finally completed a project that I couldn't wait to share. 17 | But first let's start from the beginning. I've co-founded **Molivair**. 18 | 19 | --- 20 | 21 | ## What Is Molivair? 22 | Molivair was born with the goal of making our surroundings more colorful. 23 | How it does it it's very simple. 24 | You have most likely come across art generated with the help of Artificial Intelligence. At Molivair we do just that! 25 | We generate art that will then be shared and auctioned on dedicated marketplaces. 26 | 27 | --- 28 | 29 | ## How It Was Born? 30 | It all started with a simple message on Telegram a few months ago. 31 | Marco, the mastermind behind it all, had had a wonderful idea that he decided to share with me. 32 | After learning about it, we immediately set to work. 33 | 34 | The idea he told me about, however, **will not** be covered in this post. 35 | > There is a time and place for everything, but not now. 36 | > *Professor Oak, Pokémon* 37 | 38 | ## What Are You Going To Talk To Us About, Then? 39 | Of course, I didn't come here empty-handed. 40 | If you've been paying attention, I actually mentioned a project at the beginning. 41 | 42 | What I am going to tell you about is **Outpaintings**. 43 | Born from the inspiration of some creations found around, Outpaintings is a collection of ten famous expanded paintings. The name comes from this very expansion, which leads us to visually imagine what lies beyond the boundaries of a painting. 44 | Let me tell you: it is truly fascinating. 45 | 46 | This collection was made as a springboard for the main project from which this all started. We wanted to get a feel for the market, understand how the tools involved work, and spread the word about Molivair. 47 | We hope you will enjoy it as much as it was with us as we generated each and every pixel. 48 | 49 | --- 50 | 51 | ## How Did You Generate The Paintings? 52 | If you are interested in knowing the process behind the creation of the paintings, you can let me know via the contact information I will leave at the end of the post. I would love to write something about it! 53 | 54 | --- 55 | 56 | ## Where Can I Find Outpaintings? 57 | If you'd like to check it out, you can find it on [OpenSea][opensea-molivair-outpaintings]. 58 | 59 | --- 60 | 61 | ## Conclusion 62 | We have seen what is Molivair, how it is born and where you can find the first art collection: Outpaintings. 63 | 64 | --- 65 | 66 | ## Support 67 | If you have liked this post, just come and tell me! 68 | Are you too shy for doing this? No problem. Just visit [airscript.it][airscript-it] and share your support following me on your preferred social platform. 69 | If you want to make me even more happier, just follow, share or star me and my projects on [GitHub][github]. 70 | 71 | [airscript-it]: https://airscript.it 72 | [github]: https://github.com/airscripts 73 | [opensea-molivair-outpaintings]: https://opensea.io/collection/molivair-outpaintings 74 | -------------------------------------------------------------------------------- /content/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Search" 3 | layout: "search" 4 | summary: "Search something on my blog!" 5 | robotsNoIndex: true 6 | --- -------------------------------------------------------------------------------- /data/info.toml: -------------------------------------------------------------------------------- 1 | version = "1.11.0" 2 | phrase = "Sharing happiness with code." -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | blog: 3 | tty: true 4 | restart: always 5 | image: airscript/blog:compose 6 | container_name: airscript-blog 7 | 8 | ports: 9 | - "25001:25001/tcp" 10 | 11 | volumes: 12 | - .:/home 13 | 14 | networks: 15 | default: 16 | aliases: 17 | - blognet 18 | 19 | build: 20 | context: . 21 | dockerfile: ".docker/dockerfiles/blog.Dockerfile" 22 | 23 | args: 24 | BLOG_BUILD_ENVIRONMENT: compose -------------------------------------------------------------------------------- /i18n/en.yaml: -------------------------------------------------------------------------------- 1 | - id: prev_page 2 | translation: "Previous Page" 3 | 4 | - id: next_page 5 | translation: "Next Page" 6 | 7 | - id: read_time 8 | translation: 9 | one : "1 minute" 10 | other: "{{ .Count }} minutes" 11 | 12 | - id: words 13 | translation: 14 | one : "word" 15 | other: "{{ .Count }} words" 16 | 17 | - id: toc 18 | translation: "Table of Contents" 19 | 20 | - id: translations 21 | translation: "Translations" 22 | 23 | - id: home 24 | translation: "Home" 25 | 26 | - id: edit_post 27 | translation: "Edit" 28 | 29 | - id: code_copy 30 | translation: "Copy" 31 | 32 | - id: code_copied 33 | translation: "Copied!" 34 | -------------------------------------------------------------------------------- /layouts/_default/rss.xml: -------------------------------------------------------------------------------- 1 | {{- $pctx := . -}} 2 | {{- if .IsHome -}}{{ $pctx = site }}{{- end -}} 3 | {{- $pages := slice -}} 4 | {{- if or $.IsHome $.IsSection -}} 5 | {{- $pages = $pctx.RegularPages -}} 6 | {{- else -}} 7 | {{- $pages = $pctx.Pages -}} 8 | {{- end -}} 9 | {{- $limit := site.Config.Services.RSS.Limit -}} 10 | {{- if ge $limit 1 -}} 11 | {{- $pages = $pages | first $limit -}} 12 | {{- end -}} 13 | {{- printf "" | safeHTML }} 14 | 15 | 16 | {{ if eq .Title site.Title }}{{ site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ site.Title }}{{ end }} 17 | {{ .Permalink }} 18 | Recent content {{ if ne .Title site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ site.Title }} 19 | {{- with site.Params.images }} 20 | 21 | {{ index . 0 | absURL }} 22 | {{ index . 0 | absURL }} 23 | 24 | {{- end }} 25 | Hugo -- gohugo.io{{ with site.LanguageCode }} 26 | {{.}}{{end}}{{ with site.Author.email }} 27 | {{.}}{{ with site.Author.name }} ({{.}}){{end}}{{end}}{{ with site.Author.email }} 28 | {{.}}{{ with site.Author.name }} ({{.}}){{end}}{{end}}{{ with site.Copyright }} 29 | {{.}}{{end}}{{ if not .Date.IsZero }} 30 | {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}{{ end }} 31 | {{- with .OutputFormats.Get "RSS" -}} 32 | {{ printf "" .Permalink .MediaType | safeHTML }} 33 | {{- end -}} 34 | {{ range $pages }} 35 | {{- if and (ne .Layout `search`) (ne .Layout `archives`) (ne .Layout `offline`) }} 36 | 37 | {{ .Title }} 38 | {{ .Permalink }} 39 | {{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }} 40 | {{ with site.Author.email }}{{.}}{{ with site.Author.name }} ({{.}}){{end}}{{end}} 41 | {{ .Permalink }} 42 | {{ with .Description | html }}{{ . }}{{ else }}{{ .Summary | html }}{{ end -}} 43 | {{- if site.Params.ShowFullTextinRSS }} 44 | {{ (printf "" .Content) | safeHTML }} 45 | {{- end }} 46 | 47 | {{- end }} 48 | {{ end }} 49 | 50 | 51 | -------------------------------------------------------------------------------- /layouts/_default/search.html: -------------------------------------------------------------------------------- 1 | {{- define "main" }} 2 | 3 | 16 | 17 | 22 | 23 | {{- end }}{{/* end main */}} 24 | -------------------------------------------------------------------------------- /layouts/offline/single.html: -------------------------------------------------------------------------------- 1 | {{- define "main" }} 2 |
3 |

{{ .Title }}

4 | {{ .Content }} 5 |
6 | {{- end }}{{/* end main */ -}} 7 | -------------------------------------------------------------------------------- /layouts/partials/extend_footer.html: -------------------------------------------------------------------------------- 1 | 14 | 15 | {{ range $id, $element := .Site.Params.menuScripts -}} 16 | 22 | {{- end }} -------------------------------------------------------------------------------- /layouts/partials/extend_head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {{ range $id, $element := .Site.Params.customStyles -}} 22 | 28 | {{- end }} 29 | 30 | {{ range $id, $element := .Site.Params.customScripts -}} 31 | 37 | {{- end }} 38 | 39 | {{ range $id, $element := .Site.Params.notificationsScripts -}} 40 | 46 | {{- end }} -------------------------------------------------------------------------------- /layouts/partials/footer.html: -------------------------------------------------------------------------------- 1 | {{- if not (.Param "hideFooter") }} 2 |
3 | {{- if not site.Params.footer.hideCopyright }} 4 | {{- if site.Copyright }} 5 | © {{ now.Year }} {{ site.Copyright | markdownify }} ({{ site.Data.info.version }}) | {{ site.Data.info.phrase }} 6 | {{- else }} 7 | © {{ now.Year }}, {{ site.Title }} 8 | {{- end }} 9 | {{- end }} 10 | 11 | {{- with site.Params.footer.text }} 12 | {{ . | markdownify }} 13 | {{- print " · "}} 14 | {{- end }} 15 |
16 | {{- end }} 17 | 18 | {{- if (not site.Params.disableScrollToTop) }} 19 | 27 | 32 | 33 | 34 | 35 | {{- end }} 36 | 37 | {{- partial "extend_footer.html" . }} 38 | 39 | 75 | 76 | {{- if (not site.Params.disableScrollToTop) }} 77 | 90 | {{- end }} 91 | 92 | {{- if (not site.Params.disableThemeToggle) }} 93 | 104 | {{- end }} 105 | 106 | {{- if (and (eq .Kind "page") (ne .Layout "archives") (ne .Layout "search") (.Param "ShowCodeCopyButtons")) }} 107 | 160 | {{- end }} 161 | -------------------------------------------------------------------------------- /layouts/partials/header.html: -------------------------------------------------------------------------------- 1 | {{- /* theme-toggle is enabled */}} 2 | {{- if (not site.Params.disableThemeToggle) }} 3 | 4 | {{- /* theme is light */}} 5 | {{- if (eq site.Params.defaultTheme "light") }} 6 | 11 | 12 | {{- /* theme is dark */}} 13 | {{- else if (eq site.Params.defaultTheme "dark") }} 14 | 19 | 20 | {{- else }} 21 | {{- /* theme is auto */}} 22 | 31 | {{- end }} 32 | 33 | {{- /* theme-toggle is disabled and theme is auto */}} 34 | {{- else if (and (ne site.Params.defaultTheme "light") (ne site.Params.defaultTheme "dark"))}} 35 | 40 | {{- end }} 41 | 42 |
43 | 195 |
-------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "exit 0" 3 | 4 | [[headers]] 5 | for = "/*" 6 | 7 | [headers.values] 8 | Content-Security-Policy = "default-src 'none'; connect-src https://blog.airscript.it https://www.blog.airscript.it https://airscripts-blog.netlify.app https://onesignal.com https://cdn.onesignal.com https://img.onesignal.com; img-src https://blog.airscript.it https://www.blog.airscript.it https://airscripts-blog.netlify.app https://img.onesignal.com; manifest-src https://blog.airscript.it https://www.blog.airscript.it https://airscripts-blog.netlify.app; form-action 'none'; style-src https://blog.airscript.it https://www.blog.airscript.it https://airscripts-blog.netlify.app https://onesignal.com https://cdn.onesignal.com; style-src-elem https://blog.airscript.it https://www.blog.airscript.it https://airscripts-blog.netlify.app https://onesignal.com https://cdn.onesignal.com; base-uri https://blog.airscript.it https://www.blog.airscript.it https://airscripts-blog.netlify.app; frame-ancestors 'none'; object-src 'none'; script-src https://blog.airscript.it https://www.blog.airscript.it https://airscripts-blog.netlify.app https://onesignal.com https://cdn.onesignal.com 'nonce-lDzeJvDugA9sau9Xv6dxmVnUadEL8V6C' 'nonce-QtTSjB_e5ad2iZ2Q84S6BcxqeB1DmnAY' 'nonce-NcAFUH6ON6dCQB8HZnnDkNzAgRB08vhS' 'nonce-Xuebtprq4k7XN6IXusvnqsoNdcihTojj' 'nonce-QXYOmUnOeTfI3IuRJ8j-jhQ2SLLd33Vc' 'nonce-2WhN6wkNuTCFdLlUVj1i606JqVCb7W5_' 'nonce-apNXv-1NY9eUB90KmEczs3GDiTip8uau' 'nonce-DFSCyWW7U_2kbOmnIO1XWHPqDrWoN8Op' 'nonce-4AvlIY9LqiAVG__NHaYzjrDcEypdGTmf' 'sha256-YPIAQZwhKKusCORgJv+3ws0o8a2C+2G0Mwm5Ed5sB9A=' 'sha256-18OJdeGxaqdolTGAJtZ8LKg6Qa5DuUGQQaiY+s00cgs=' 'sha256-vu66FILRzvC+aLE8Gel5KXXtKU8cMG6IFs9D+ISvNzA=' 'sha256-ivWbCN5KkjztNBqwts0+7/S9nhLJtJcTyynhkocJF7Y=' 'sha256-X5avg43RTxt2cSum+E3xICbowEMaOBxeBiNh05CXDTY=' 'sha256-gutHTLMHA1OVQaXSfROJDMXVr1Yz9kL7TSRma0/5iEg=' 'sha256-D8MKnYBqld5PNmJygaEW3V0xeDmNy1/DwkPKbQ7vp0Q=' 'sha256-BP15bSdtw8sM55mndmgvtpF1U+Bb8rmFvF/o7KrR2G0=' 'sha512-tOZZsofKwRGHAcQVGMed077Q0y4hnPvTv0Nw8L9VYWKlQgWcQZznMXZTTNID39Q0+Dumx+kHl7PlP7K+cGn6nQ==' 'sha512-eNnuCLQ8noOgoy620xyZxApQlMLSJZze6Qe/h/uKQIynxfvYfmL29FimkcLho1i7AGeG+tkh0WM5pnBcIn82Hg==' 'sha512-SAID9CBhh48e0EabUHvgvRrh2FiCmBh5Xb+fX2sv5P9IhYvRC73fYNHWg6usTYMyEOvJ6uEuP9y7nTQIgr0f7w==' 'sha512-+R/cu1jJ/RrydyUhKhXI1QczU3TRLLLHAQyYHi1vXFAEF8lK4MxJiWgjIckiCegJ80aIB6icc6lSoLn1YY/OSA==' 'sha512-XF6O1Z7tmFdMKJug1taoTIEN5erd8st9wgg3kujj3zIB9ErdmlzR499Eup9AKwDXeI2O6BnABt/6fWqvmzkOJw=='; script-src-elem https://blog.airscript.it https://onesignal.com https://cdn.onesignal.com 'nonce-lDzeJvDugA9sau9Xv6dxmVnUadEL8V6C' 'nonce-QtTSjB_e5ad2iZ2Q84S6BcxqeB1DmnAY' 'nonce-NcAFUH6ON6dCQB8HZnnDkNzAgRB08vhS' 'nonce-Xuebtprq4k7XN6IXusvnqsoNdcihTojj' 'nonce-QXYOmUnOeTfI3IuRJ8j-jhQ2SLLd33Vc' 'nonce-2WhN6wkNuTCFdLlUVj1i606JqVCb7W5_' 'nonce-apNXv-1NY9eUB90KmEczs3GDiTip8uau' 'nonce-DFSCyWW7U_2kbOmnIO1XWHPqDrWoN8Op' 'nonce-4AvlIY9LqiAVG__NHaYzjrDcEypdGTmf' 'sha256-YPIAQZwhKKusCORgJv+3ws0o8a2C+2G0Mwm5Ed5sB9A=' 'sha256-18OJdeGxaqdolTGAJtZ8LKg6Qa5DuUGQQaiY+s00cgs=' 'sha256-vu66FILRzvC+aLE8Gel5KXXtKU8cMG6IFs9D+ISvNzA=' 'sha256-ivWbCN5KkjztNBqwts0+7/S9nhLJtJcTyynhkocJF7Y=' 'sha256-X5avg43RTxt2cSum+E3xICbowEMaOBxeBiNh05CXDTY=' 'sha256-gutHTLMHA1OVQaXSfROJDMXVr1Yz9kL7TSRma0/5iEg=' 'sha256-D8MKnYBqld5PNmJygaEW3V0xeDmNy1/DwkPKbQ7vp0Q=' 'sha256-BP15bSdtw8sM55mndmgvtpF1U+Bb8rmFvF/o7KrR2G0=' 'sha512-tOZZsofKwRGHAcQVGMed077Q0y4hnPvTv0Nw8L9VYWKlQgWcQZznMXZTTNID39Q0+Dumx+kHl7PlP7K+cGn6nQ==' 'sha512-eNnuCLQ8noOgoy620xyZxApQlMLSJZze6Qe/h/uKQIynxfvYfmL29FimkcLho1i7AGeG+tkh0WM5pnBcIn82Hg==' 'sha512-SAID9CBhh48e0EabUHvgvRrh2FiCmBh5Xb+fX2sv5P9IhYvRC73fYNHWg6usTYMyEOvJ6uEuP9y7nTQIgr0f7w==' 'sha512-+R/cu1jJ/RrydyUhKhXI1QczU3TRLLLHAQyYHi1vXFAEF8lK4MxJiWgjIckiCegJ80aIB6icc6lSoLn1YY/OSA==' 'sha512-XF6O1Z7tmFdMKJug1taoTIEN5erd8st9wgg3kujj3zIB9ErdmlzR499Eup9AKwDXeI2O6BnABt/6fWqvmzkOJw=='" 9 | Referrer-Policy = "strict-origin-when-cross-origin" 10 | X-Content-Type-Options = "nosniff" 11 | X-Frame-Options = "DENY" 12 | X-XSS-Protection = "1; mode=block" 13 | Permissions-Policy = "accelerometer=(self), autoplay=(self), camera=(self), cross-origin-isolated=(self), display-capture=(self), document-domain=(self), encrypted-media=(self), fullscreen=(self), geolocation=(self), gyroscope=(self), keyboard-map=(self), magnetometer=(self), microphone=(self), midi=(self), payment=(self), picture-in-picture=(self), publickey-credentials-get=(self), screen-wake-lock=(self), sync-xhr=(self), usb=(self), xr-spatial-tracking=(self)" 14 | -------------------------------------------------------------------------------- /scripts/bats.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Bats is working correctly." 3 | -------------------------------------------------------------------------------- /scripts/ci/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | hugo --gc --minify 3 | -------------------------------------------------------------------------------- /scripts/ci/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | netlify deploy --site $1 --auth $2 --prod --dir=public 3 | -------------------------------------------------------------------------------- /scripts/ci/verify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "$1" = "base" ]; then 3 | apk --version 4 | 5 | elif [ "$1" = "build" ]; then 6 | apk --version 7 | git --version 8 | hugo version 9 | 10 | elif [ "$1" = "deploy" ]; then 11 | apk --version 12 | node -v 13 | npm -v 14 | netlify -v 15 | 16 | elif [ "$1" = "publish" ]; then 17 | apk --version 18 | docker -v 19 | 20 | else 21 | echo ERROR: Environment not found. 22 | exit 1 23 | fi -------------------------------------------------------------------------------- /scripts/devcontainer/safeness.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git config --global --add safe.directory /workspaces/blog 3 | git config --global --add safe.directory /workspaces/blog/tests/bats 4 | git config --global --add safe.directory /workspaces/blog/themes/PaperMod 5 | git config --global --add safe.directory /workspaces/blog/tests/libraries/bats-assert 6 | git config --global --add safe.directory /workspaces/blog/tests/libraries/bats-support -------------------------------------------------------------------------------- /scripts/devcontainer/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | apk update && \ 3 | 4 | sh scripts/install/bash.sh && \ 5 | bash scripts/install/git.sh && \ 6 | bash scripts/install/make.sh && \ 7 | 8 | bash scripts/devcontainer/safeness.sh -------------------------------------------------------------------------------- /scripts/devcontainer/teardown.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | DEVCONTAINER_NAME="airscript-devcontainer" 3 | DIND_IMAGE_NAME="docker:20.10.22-dind-alpine3.17" 4 | 5 | docker stop $DEVCONTAINER_NAME 6 | docker rm $DEVCONTAINER_NAME 7 | docker rmi $DIND_IMAGE_NAME -------------------------------------------------------------------------------- /scripts/devcontainer/verify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | devcontainer build --workspace-folder . --image-name airscript/devcontainer:cli -------------------------------------------------------------------------------- /scripts/docker/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Building Docker image..." 3 | docker build -f .docker/dockerfiles/blog.Dockerfile -t airscript/blog:$1 . -------------------------------------------------------------------------------- /scripts/docker/login.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Logging into Docker Hub..." 3 | docker login --username $1 --password $2 4 | -------------------------------------------------------------------------------- /scripts/docker/push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Pushing image to Docker Hub..." 3 | docker push airscript/blog:$1 -------------------------------------------------------------------------------- /scripts/install/bash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | apk add bash 3 | 4 | bash --version && \ 5 | echo "Bash installed successfully." 6 | -------------------------------------------------------------------------------- /scripts/install/bats.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | npm install -g bats && \ 3 | echo "Bats installed successfully." 4 | -------------------------------------------------------------------------------- /scripts/install/circleci-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | bash && \ 3 | echo "CircleCI CLI installed successfully." 4 | -------------------------------------------------------------------------------- /scripts/install/curl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apk add curl && \ 3 | echo "curl installed successfully." 4 | -------------------------------------------------------------------------------- /scripts/install/devcontainer-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | npm install -g @devcontainers/cli && \ 3 | echo "devcontainer CLI installed successfully." -------------------------------------------------------------------------------- /scripts/install/docker-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apk add docker-cli 3 | 4 | docker --version && \ 5 | echo "Docker CLI installed successfully." 6 | -------------------------------------------------------------------------------- /scripts/install/git.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! "$1" = "compose" ]; then 3 | apk add git && \ 4 | echo "Git installed successfully." 5 | 6 | else 7 | echo "Git installation has been skipped." 8 | fi 9 | -------------------------------------------------------------------------------- /scripts/install/gpp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apk add g++ && \ 3 | echo "gpp installed successfully." 4 | -------------------------------------------------------------------------------- /scripts/install/hugo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apk add hugo && \ 3 | echo "Hugo installed successfully." 4 | -------------------------------------------------------------------------------- /scripts/install/make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apk add make && \ 3 | echo "Make installed successfully." -------------------------------------------------------------------------------- /scripts/install/netlify-cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | npm install -g netlify-cli && \ 3 | echo "Netlify CLI installed successfully." -------------------------------------------------------------------------------- /scripts/install/npm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apk add npm && \ 3 | echo "npm installed successfully." 4 | -------------------------------------------------------------------------------- /scripts/install/python3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apk add python3 && \ 3 | echo "python3 installed successfully." -------------------------------------------------------------------------------- /scripts/shared/git-submodules.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! "$1" = "compose" ]; then 3 | git submodule update --init --recursive && \ 4 | echo "Git submodule update executed." 5 | 6 | else 7 | echo "Git submodule update skipped." 8 | fi -------------------------------------------------------------------------------- /scripts/tests/base.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bats tests/* 3 | -------------------------------------------------------------------------------- /scripts/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | apk update 3 | -------------------------------------------------------------------------------- /static/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/android-chrome-192x192.png -------------------------------------------------------------------------------- /static/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/android-chrome-512x512.png -------------------------------------------------------------------------------- /static/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /static/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /static/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /static/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /static/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /static/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /static/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /static/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /static/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /static/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/apple-touch-icon.png -------------------------------------------------------------------------------- /static/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | #000000 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /static/css/offline.css: -------------------------------------------------------------------------------- 1 | #offline-content { 2 | left: 0; 3 | right: 0; 4 | display: flex; 5 | position: absolute; 6 | align-items: center; 7 | flex-direction: column; 8 | justify-content: center; 9 | height: calc(100vh - var(--header-height) - var(--footer-height)); 10 | } -------------------------------------------------------------------------------- /static/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/favicon-16x16.png -------------------------------------------------------------------------------- /static/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/favicon-32x32.png -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/favicon.ico -------------------------------------------------------------------------------- /static/images/cover-analscript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/images/cover-analscript.png -------------------------------------------------------------------------------- /static/images/gael.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/images/gael.png -------------------------------------------------------------------------------- /static/images/less-feetpics-less-footprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/images/less-feetpics-less-footprint.png -------------------------------------------------------------------------------- /static/images/logo-steam-deck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/images/logo-steam-deck.png -------------------------------------------------------------------------------- /static/images/woman-with-a-parasol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/images/woman-with-a-parasol.png -------------------------------------------------------------------------------- /static/js/menu.js: -------------------------------------------------------------------------------- 1 | console.log("Attaching events to menu..."); 2 | 3 | let efMenu = document.querySelector(".menu"); 4 | let efTrigger = document.querySelector("#menu-trigger"); 5 | 6 | efTrigger.addEventListener("click", function () { 7 | efMenu.classList.toggle("hidden"); 8 | }); 9 | 10 | document.body.addEventListener('click', function (event) { 11 | if (!efTrigger.contains(event.target)) { 12 | efMenu.classList.add("hidden"); 13 | } 14 | }); 15 | 16 | console.log("Events attached!"); -------------------------------------------------------------------------------- /static/js/notifications/dictionary.js: -------------------------------------------------------------------------------- 1 | const dictionary = { 2 | it: { 3 | accept: "Accetta", 4 | cancel: "Più tardi", 5 | title: "Benvenuto", 6 | message: "Grazie per esserti iscritto! 🎉", 7 | 8 | action: 9 | "Vuoi ricevere una notifica non appena un nuovo articolo viene pubblicato?", 10 | }, 11 | 12 | en: { 13 | accept: "Allow", 14 | cancel: "Later", 15 | title: "Welcome", 16 | message: "Thanks for subscribing! 🎉", 17 | action: "Do you want to be notified as soon as a new article is published?", 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /static/js/notifications/i18n.js: -------------------------------------------------------------------------------- 1 | function getTranslation(language, key) { 2 | if (!Object.keys(dictionary).includes(language)) language = "en"; 3 | 4 | return dictionary[language][key] 5 | ? dictionary[language][key] 6 | : "Oops, missing translation."; 7 | } 8 | -------------------------------------------------------------------------------- /static/js/notifications/main.js: -------------------------------------------------------------------------------- 1 | const locale = 2 | navigator.languages && navigator.languages.length 3 | ? navigator.languages[0] 4 | : navigator.language; 5 | 6 | const defaultLanguage = "en"; 7 | const language = locale ? locale.split("-")[0] : defaultLanguage; 8 | var OneSignal = window.OneSignal || []; 9 | 10 | OneSignal.push(function () { 11 | OneSignal.SERVICE_WORKER_PARAM = { scope: "/js/notifications/" }; 12 | OneSignal.SERVICE_WORKER_PATH = "js/notifications/worker.js"; 13 | OneSignal.SERVICE_WORKER_UPDATER_PATH = "js/notifications/worker.js"; 14 | 15 | OneSignal.init({ 16 | persistNotification: true, 17 | notificationClickHandlerAction: "navigate", 18 | appId: "b11e178e-35e4-4e25-ba77-18c2fb03fc8a", 19 | safari_web_id: "web.onesignal.auto.364542e4-0165-4e49-b6eb-0136f3f4eaa9", 20 | 21 | welcomeNotification: { 22 | title: getTranslation(language, "title"), 23 | message: getTranslation(language, "message"), 24 | }, 25 | 26 | promptOptions: { 27 | slidedown: { 28 | prompts: [ 29 | { 30 | type: "push", 31 | autoPrompt: true, 32 | 33 | text: { 34 | acceptButton: getTranslation(language, "accept"), 35 | cancelButton: getTranslation(language, "cancel"), 36 | actionMessage: getTranslation(language, "action"), 37 | }, 38 | 39 | delay: { 40 | pageViews: 1, 41 | timeDelay: 3, 42 | }, 43 | }, 44 | ], 45 | }, 46 | }, 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /static/js/notifications/worker.js: -------------------------------------------------------------------------------- 1 | importScripts('https://cdn.onesignal.com/sdks/OneSignalSDKWorker.js'); 2 | -------------------------------------------------------------------------------- /static/logo-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/logo-256x256.png -------------------------------------------------------------------------------- /static/logo-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/logo-512x512.png -------------------------------------------------------------------------------- /static/logo-open-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/logo-open-graph.png -------------------------------------------------------------------------------- /static/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blog.airscript.it", 3 | "short_name": "blog.airscript.it", 4 | "theme_color": "#0f94d2", 5 | "background_color": "#ffffff", 6 | "display": "standalone", 7 | "scope": "/", 8 | "start_url": "/", 9 | 10 | "icons": [ 11 | { 12 | "src": "android-chrome-192x192.png", 13 | "sizes": "192x192", 14 | "type": "image/png" 15 | }, 16 | 17 | { 18 | "src": "maskable-android-chrome-192x192.png", 19 | "sizes": "192x192", 20 | "type": "image/png", 21 | "purpose": "maskable" 22 | }, 23 | 24 | { 25 | "src": "android-chrome-512x512.png", 26 | "sizes": "512x512", 27 | "type": "image/png" 28 | }, 29 | 30 | { 31 | "src": "maskable-android-chrome-512x512.png", 32 | "sizes": "512x512", 33 | "type": "image/png", 34 | "purpose": "maskable" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /static/maskable-android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/maskable-android-chrome-192x192.png -------------------------------------------------------------------------------- /static/maskable-android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/maskable-android-chrome-512x512.png -------------------------------------------------------------------------------- /static/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/mstile-144x144.png -------------------------------------------------------------------------------- /static/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/mstile-150x150.png -------------------------------------------------------------------------------- /static/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/mstile-310x150.png -------------------------------------------------------------------------------- /static/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/mstile-310x310.png -------------------------------------------------------------------------------- /static/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airscripts/blog/a7d4828c38cd78a7f2ef14232e2762fd6196cd3e/static/mstile-70x70.png -------------------------------------------------------------------------------- /static/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | Created by potrace 1.14, written by Peter Selinger 2001-2017 -------------------------------------------------------------------------------- /static/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/sw.js: -------------------------------------------------------------------------------- 1 | const CACHE_VERSION = "1.11.0"; 2 | const SUPPORTED_METHODS = ["GET"]; 3 | const NOT_FOUND_PAGE = "/404.html"; 4 | const OFFLINE_PAGE = "/offline/index.html"; 5 | const NOT_FOUND_CACHE_FILES = ["/404.html"]; 6 | const SITE_URL = "https://blog.airscript.it"; 7 | const OFFLINE_CACHE_FILES = ["/offline/index.html"]; 8 | 9 | const BASE_CACHE_FILES = [ 10 | "/logo.svg", 11 | "/logo-256x256.png", 12 | "/logo-512x512.png", 13 | "/favicon.ico", 14 | "/manifest.json", 15 | "/mstile-70x70.png", 16 | "/mstile-144x144.png", 17 | "/mstile-150x150.png", 18 | "/mstile-310x150.png", 19 | "/mstile-310x310.png", 20 | "/favicon-16x16.png", 21 | "/favicon-32x32.png", 22 | "/browserconfig.xml", 23 | "/apple-touch-icon.png", 24 | "/safari-pinned-tab.svg", 25 | "/android-chrome-192x192.png", 26 | "/android-chrome-512x512.png", 27 | "/maskable-android-chrome-192x192.png", 28 | "/maskable-android-chrome-512x512.png", 29 | ]; 30 | 31 | const CACHE_VERSIONS = { 32 | notFound: "404-v" + CACHE_VERSION, 33 | assets: "assets-v" + CACHE_VERSION, 34 | content: "content-v" + CACHE_VERSION, 35 | offline: "offline-v" + CACHE_VERSION, 36 | }; 37 | 38 | const MAX_TTL = { 39 | "/": 3600, 40 | js: 86400, 41 | html: 3600, 42 | css: 86400, 43 | json: 86400, 44 | }; 45 | 46 | const CACHE_BLACKLIST = [ 47 | // (str) => { 48 | // return !str.startsWith(SITE_URL) && !str.startsWith("http://localhost"); 49 | // }, 50 | ]; 51 | 52 | function isBlacklisted(url) { 53 | return CACHE_BLACKLIST.length > 0 54 | ? !CACHE_BLACKLIST.filter((rule) => { 55 | return typeof rule === "function" ? !rule(url) : false; 56 | }).length 57 | : false; 58 | } 59 | 60 | function getFileExtension(url) { 61 | let extension = url.split(".").reverse()[0].split("?")[0]; 62 | return extension.endsWith("/") ? "/" : extension; 63 | } 64 | 65 | function getTTL(url) { 66 | let extension = getFileExtension(url); 67 | 68 | return typeof url === "string" 69 | ? typeof MAX_TTL[extension] === "number" 70 | ? MAX_TTL[extension] 71 | : null 72 | : null; 73 | } 74 | 75 | function installServiceWorker() { 76 | return Promise.all([ 77 | caches.open(CACHE_VERSIONS.assets).then((cache) => { 78 | return cache.addAll(BASE_CACHE_FILES); 79 | }), 80 | 81 | caches.open(CACHE_VERSIONS.offline).then((cache) => { 82 | return cache.addAll(OFFLINE_CACHE_FILES); 83 | }), 84 | 85 | caches.open(CACHE_VERSIONS.notFound).then((cache) => { 86 | return cache.addAll(NOT_FOUND_CACHE_FILES); 87 | }), 88 | ]).then(() => { 89 | return self.skipWaiting(); 90 | }); 91 | } 92 | 93 | function cleanupCache(keys) { 94 | Promise.all( 95 | keys.map((key) => { 96 | return caches.delete(key); 97 | }) 98 | ) 99 | .then(() => { 100 | resolve(); 101 | }) 102 | 103 | .catch((err) => { 104 | reject(err); 105 | }); 106 | } 107 | 108 | function cleanupLegacyCache() { 109 | let currentCaches = Object.keys(CACHE_VERSIONS).map((key) => { 110 | return CACHE_VERSIONS[key]; 111 | }); 112 | 113 | return new Promise((resolve, reject) => { 114 | caches 115 | .keys() 116 | 117 | .then((keys) => { 118 | return (legacyKeys = keys.filter((key) => { 119 | return !~currentCaches.indexOf(key); 120 | })); 121 | }) 122 | 123 | .then((legacy) => { 124 | legacy.length ? cleanup(legacy) : resolve(); 125 | }) 126 | 127 | .catch(() => { 128 | reject(); 129 | }); 130 | }); 131 | } 132 | 133 | function precacheUrl(url) { 134 | if (!isBlacklisted(url)) { 135 | caches.open(CACHE_VERSIONS.content).then((cache) => { 136 | cache 137 | .match(url) 138 | 139 | .then((response) => { 140 | return !response ? fetch(url) : null; 141 | }) 142 | 143 | .then((response) => { 144 | return response ? cache.put(url, response.clone()) : null; 145 | }); 146 | }); 147 | } 148 | } 149 | 150 | self.addEventListener("install", (event) => { 151 | event.waitUntil(Promise.all([installServiceWorker(), self.skipWaiting()])); 152 | }); 153 | 154 | self.addEventListener("activate", (event) => { 155 | event.waitUntil( 156 | Promise.all([ 157 | cleanupLegacyCache(), 158 | self.clients.claim(), 159 | self.skipWaiting(), 160 | ]).catch(() => { 161 | self.skipWaiting(); 162 | }) 163 | ); 164 | }); 165 | 166 | self.addEventListener("fetch", (event) => { 167 | event.respondWith( 168 | caches.open(CACHE_VERSIONS.content).then((cache) => { 169 | return cache 170 | .match(event.request) 171 | 172 | .then((response) => { 173 | if (!response) return null; 174 | let date = null; 175 | let headers = response.headers.entries(); 176 | 177 | for (let pair of headers) { 178 | if (pair[0] === "date") date = new Date(pair[1]); 179 | } 180 | 181 | if (!date) return response; 182 | let ttl = getTTL(event.request.url); 183 | let age = parseInt((new Date().getTime() - date.getTime()) / 1000); 184 | if (!ttl || age <= ttl) return response; 185 | 186 | return new Promise((resolve) => { 187 | return fetch(event.request.clone()) 188 | .then((res) => { 189 | if (res) cache.put(event.request, res.clone()), resolve(res); 190 | else resolve(response); 191 | }) 192 | 193 | .catch(() => { 194 | resolve(response); 195 | }); 196 | }).catch(() => { 197 | return response; 198 | }); 199 | }) 200 | 201 | .then((response) => { 202 | if (response) return response; 203 | else { 204 | return fetch(event.request.clone()) 205 | .then((response) => { 206 | if (response.status < 400) { 207 | let isMethodSupported = ~SUPPORTED_METHODS.indexOf( 208 | event.request.method 209 | ); 210 | 211 | if (isMethodSupported && !isBlacklisted(event.request.url)) { 212 | cache.put(event.request, response.clone()); 213 | } 214 | 215 | return response; 216 | } else { 217 | return caches.open(CACHE_VERSIONS.notFound).then((cache) => { 218 | return cache.match(NOT_FOUND_PAGE); 219 | }); 220 | } 221 | }) 222 | 223 | .then((response) => { 224 | if (response) return response; 225 | }) 226 | 227 | .catch(() => { 228 | return caches 229 | .open(CACHE_VERSIONS.offline) 230 | 231 | .then((offlineCache) => { 232 | return offlineCache.match(OFFLINE_PAGE); 233 | }); 234 | }); 235 | } 236 | }) 237 | 238 | .catch((error) => { 239 | console.error("Error in fetch handler:", error); 240 | throw error; 241 | }); 242 | }) 243 | ); 244 | }); 245 | 246 | self.addEventListener("message", (event) => { 247 | if (typeof event.data === "object" && typeof event.data.action === "string") { 248 | switch (event.data.action) { 249 | case "cache": 250 | precacheUrl(event.data.url); 251 | break; 252 | 253 | default: 254 | console.log("Unknown action: " + event.data.action); 255 | break; 256 | } 257 | } 258 | }); 259 | -------------------------------------------------------------------------------- /tests/_.bats: -------------------------------------------------------------------------------- 1 | #!./tests/bats/bin/bats 2 | 3 | setup() { 4 | load 'libraries/bats-support/load' 5 | load 'libraries/bats-assert/load' 6 | source ./tests/mocks.sh 7 | } 8 | 9 | @test "Run Script" { 10 | run ./scripts/bats.sh 11 | } 12 | 13 | @test "Install Bash" { 14 | run ./scripts/install/bash.sh 15 | assert_output --partial "$INSTALL_BASH" 16 | refute_output --partial "ERROR" 17 | } -------------------------------------------------------------------------------- /tests/install.bats: -------------------------------------------------------------------------------- 1 | #!./tests/bats/bin/bats 2 | 3 | setup() { 4 | load 'libraries/bats-support/load' 5 | load 'libraries/bats-assert/load' 6 | source ./tests/mocks.sh 7 | } 8 | 9 | @test "Install Docker CLI" { 10 | run ./scripts/install/docker-cli.sh 11 | assert_output --partial "$INSTALL_DOCKER_CLI" 12 | refute_output --partial "ERROR" 13 | } 14 | 15 | @test "Install Git" { 16 | run ./scripts/install/git.sh 17 | assert_output --partial "$INSTALL_GIT" 18 | refute_output --partial "ERROR" 19 | refute_output --partial "$SKIP_INSTALL_GIT" 20 | } 21 | 22 | @test "Skip install Git" { 23 | run ./scripts/install/git.sh compose 24 | assert_output --partial "$SKIP_INSTALL_GIT" 25 | refute_output --partial "ERROR" 26 | refute_output --partial "$INSTALL_GIT" 27 | } 28 | 29 | @test "Install Hugo" { 30 | run ./scripts/install/hugo.sh 31 | assert_output --partial "$INSTALL_HUGO" 32 | refute_output --partial "ERROR" 33 | } 34 | 35 | @test "Install Make" { 36 | run ./scripts/install/make.sh 37 | assert_output --partial "$INSTALL_MAKE" 38 | refute_output --partial "ERROR" 39 | } 40 | 41 | @test "Install gpp" { 42 | run ./scripts/install/gpp.sh 43 | assert_output --partial "$INSTALL_GPP" 44 | refute_output --partial "ERROR" 45 | } 46 | 47 | @test "Install python3" { 48 | run ./scripts/install/python3.sh 49 | assert_output --partial "$INSTALL_PYTHON3" 50 | refute_output --partial "ERROR" 51 | } 52 | 53 | @test "Install npm" { 54 | run ./scripts/install/npm.sh 55 | assert_output --partial "$INSTALL_NPM" 56 | refute_output --partial "ERROR" 57 | } 58 | 59 | @test "Install Netlify CLI" { 60 | run ./scripts/install/netlify-cli.sh 61 | assert_output --partial "$INSTALL_NETLIFY_CLI" 62 | refute_output --partial "ERR!" 63 | } 64 | 65 | @test "Install devcontainer CLI" { 66 | run ./scripts/install/devcontainer-cli.sh 67 | assert_output --partial "$INSTALL_DEVCONTAINER_CLI" 68 | refute_output --partial "ERR!" 69 | } 70 | 71 | @test "Install Bats" { 72 | run ./scripts/install/bats.sh 73 | assert_output --partial "$INSTALL_BATS" 74 | refute_output --partial "ERR!" 75 | } 76 | 77 | @test "Install curl" { 78 | run ./scripts/install/curl.sh 79 | assert_output --partial "$INSTALL_CURL" 80 | refute_output --partial "ERROR" 81 | } 82 | 83 | @test "Install CircleCI CLI" { 84 | run ./scripts/install/circleci-cli.sh 85 | assert_output --partial "$INSTALL_CIRCLECI_CLI" 86 | refute_output --partial "404" 87 | } 88 | -------------------------------------------------------------------------------- /tests/mocks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | readonly INSTALL_NPM="npm installed successfully." 3 | readonly INSTALL_GIT="Git installed successfully." 4 | readonly INSTALL_GPP="gpp installed successfully." 5 | readonly INSTALL_BATS="Bats installed successfully." 6 | readonly INSTALL_HUGO="Hugo installed successfully." 7 | readonly INSTALL_MAKE="Make installed successfully." 8 | readonly INSTALL_CURL="curl installed successfully." 9 | readonly INSTALL_BASH="Bash installed successfully." 10 | readonly INSTALL_PYTHON3="python3 installed successfully." 11 | readonly INSTALL_DOCKER_CLI="Docker CLI installed successfully." 12 | readonly INSTALL_NETLIFY_CLI="Netlify CLI installed successfully." 13 | readonly INSTALL_CIRCLECI_CLI="CircleCI CLI installed successfully." 14 | readonly INSTALL_DEVCONTAINER_CLI="devcontainer CLI installed successfully." 15 | 16 | readonly SKIP_INSTALL_GIT="Git installation has been skipped." 17 | readonly ADD_GIT_SUBMODULE_SKIPPED="Git submodule update skipped." 18 | readonly ADD_GIT_SUBMODULE_EXECUTED="Git submodule update executed." 19 | -------------------------------------------------------------------------------- /tests/shared.bats: -------------------------------------------------------------------------------- 1 | #!./tests/bats/bin/bats 2 | 3 | setup() { 4 | load 'libraries/bats-support/load' 5 | load 'libraries/bats-assert/load' 6 | source ./tests/mocks.sh 7 | apk add git 8 | } 9 | 10 | @test "Add Git Submodules" { 11 | run ./scripts/shared/git-submodules.sh 12 | assert_output --partial "$ADD_GIT_SUBMODULE_EXECUTED" 13 | } 14 | 15 | @test "Skip Git Submodules" { 16 | run ./scripts/shared/git-submodules.sh compose 17 | assert_output "$ADD_GIT_SUBMODULE_SKIPPED" 18 | } --------------------------------------------------------------------------------