├── .all-contributorsrc ├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── PULL_REQUEST_TEMPLATE.md ├── changelog-configuration.json ├── dependabot.yml ├── labeler.yml └── workflows │ ├── cache-clean.yml │ ├── deploy-clean.yml │ ├── gpg-tests.yml │ ├── history-clean.yml │ ├── issues-accept.yml │ ├── issues-new.yml │ ├── issues-scan.yml │ ├── issues-stale.yml │ ├── labels-clean.yml │ ├── labels-create.yml │ ├── ping-developer.yml │ └── release.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── Snippets ├── Alphabetized List 1 │ ├── README.md │ └── images │ │ ├── example_1.gif │ │ ├── example_2.gif │ │ ├── example_3.gif │ │ ├── example_4.gif │ │ ├── example_5.gif │ │ ├── install_1.gif │ │ ├── install_2.png │ │ └── install_3.gif ├── Alphabetized List 2 │ └── code.txt ├── Bad Links 1 │ ├── README.md │ └── images │ │ ├── example_1.png │ │ ├── example_2.gif │ │ ├── example_3.gif │ │ ├── example_4.gif │ │ ├── example_5.gif │ │ ├── install_1.gif │ │ ├── install_2.png │ │ └── install_3.gif ├── Page Cloud 1 │ ├── README.md │ └── images │ │ ├── example_1.gif │ │ ├── install_1.gif │ │ ├── install_2.png │ │ ├── install_3.gif │ │ └── install_4.gif ├── Subfolder Data │ ├── README.md │ ├── images │ │ ├── example_1.gif │ │ ├── install_1.gif │ │ ├── install_2.png │ │ └── install_3.gif │ └── snippet-version3 ├── TOC Version 1 │ ├── README.md │ └── images │ │ ├── example_1.gif │ │ ├── install_1.gif │ │ ├── install_2.png │ │ └── install_3.gif ├── TOC Version 2 │ ├── README.md │ └── images │ │ ├── example_1.gif │ │ ├── install_1.gif │ │ ├── install_2.png │ │ └── install_3.gif ├── Tag Cloud 1 │ ├── README.md │ └── images │ │ ├── example_1.gif │ │ ├── install_1.gif │ │ ├── install_2.png │ │ └── install_3.gif └── Tag Cloud 2 │ ├── README.md │ └── images │ ├── example_1.gif │ ├── install_1.gif │ ├── install_2.png │ ├── install_3.gif │ └── install_4.gif ├── eslint.config.js ├── obs.js ├── package-lock.json └── package.json /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "obsidian-dataview-snippets", 3 | "projectOwner": "Aetherinox", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": ["README.md"], 7 | "imageSize": 40, 8 | "commit": true, 9 | "commitConvention": "angular", 10 | "contributors": [ 11 | { 12 | "login": "Aetherinox", 13 | "name": "Aetherinox", 14 | "avatar_url": "https://avatars.githubusercontent.com/u/118329232?v=4", 15 | "profile": "https://gitlab.com/Aetherinox", 16 | "contributions": ["code", "projectManagement"] 17 | } 18 | ], 19 | "contributorsPerLine": 5, 20 | "linkToUsage": false 21 | } 22 | 23 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | # # 4 | # is top-most EditorConfig file 5 | # # 6 | 7 | root = true 8 | 9 | # # 10 | # All Files 11 | # # 12 | 13 | [*] 14 | indent_style = space 15 | indent_size = 4 16 | end_of_line = lf 17 | charset = utf-8 18 | trim_trailing_whitespace = true 19 | insert_final_newline = true 20 | 21 | # # 22 | # Markdown Files 23 | # # 24 | 25 | [*.md] 26 | trim_trailing_whitespace = false 27 | 28 | # # 29 | # Other 30 | # # 31 | 32 | [{*.nsh,*.yml,*.yaml,*.json}] 33 | indent_style = space 34 | indent_size = 2 35 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.js text eol=lf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ["https://buymeacoffee.com/aetherinox"] 2 | github: # [repo-name, aetherinox] 3 | patreon: # Replace with a single Patreon username 4 | open_collective: # name 5 | ko_fi: # Replace with a single Ko-fi username 6 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 7 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 8 | liberapay: # Replace with a single Liberapay username 9 | issuehunt: # Replace with a single IssueHunt username 10 | otechie: # Replace with a single Otechie username -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | # Pull Request 18 | Check which topic best describes your contribution: 19 | 20 | - [ ] Feature 21 | - [ ] Bug 22 | - [ ] Documentation / Wiki 23 | 24 | --- 25 | 26 | 27 |
28 | 29 | 30 | 31 | ### Description 32 | Explain here what your pull request includes and what you've done 33 | 34 | 35 | 36 |
37 | 38 | --- 39 | 40 |
41 | 42 | 43 | ### Before You Submit 44 | Please ensure you check the following items to indicate that you've read this section and completed each task 45 | 46 | - [ ] My code follows the [Contribution Guidelines](https://github.com/Aetherinox/obsidian-dataview-snippets/blob/main/CONTRIBUTING.md) 47 | - [ ] I give expressed consent for my work to be used in this repo 48 | - [ ] I have tested my work and it functions as intended 49 | - [ ] I have included documentation if the change requires such 50 | -------------------------------------------------------------------------------- /.github/changelog-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [ 3 | { 4 | "title": "\n\n
\n\n#### 🪛 Continuous integration", 5 | "labels": [ "kind/ci", "ci" ] 6 | }, 7 | { 8 | "title": "\n\n
\n\n#### 🚀 Features", 9 | "labels": [ "kind/feature", "feature", "feat" ] 10 | }, 11 | { 12 | "title": "\n\n
\n\n#### 🐛 Bugfixes", 13 | "labels": [ "kind/bug", "fix", "bug" ] 14 | }, 15 | { 16 | "title": "\n\n
\n\n#### 🔧 Changes", 17 | "labels": [ "kind/chore", "change", "chore" ] 18 | }, 19 | { 20 | "title": "\n\n
\n\nn#### ✨ Optimizations", 21 | "labels": [ "kind/perf", "optimization", "perf", "optimize" ] 22 | }, 23 | { 24 | "title": "\n\n
\n\n#### 🚨 Security ", 25 | "labels": [ "kind/security", "security" ] 26 | }, 27 | { 28 | "title": "\n\n
\n\n#### 🧹 Housekeeping", 29 | "labels": [ "kind/refactor", "refactor", "style" ] 30 | }, 31 | { 32 | "title": "\n\n
\n\n#### 🐒 Miscellaneous", 33 | "labels": [ "kind/misc", "misc" ] 34 | }, 35 | { 36 | "title": "\n\n
\n\n#### ⛔ Deprecated", 37 | "labels": [ "kind/deprecate", "deprecate" ] 38 | }, 39 | { 40 | "title": "\n\n
\n\n#### ⛔ Removed", 41 | "labels": [ "kind/remove", "remove" ] 42 | }, 43 | { 44 | "title": "\n\n
\n\n#### 📦 Build & Dependencies", 45 | "labels": [ "kind/build", "build", "dependency", "dep", "package" ] 46 | }, 47 | { 48 | "title": "\n\n
\n\n#### ✏️ Docs", 49 | "labels": [ "kind/docs", "doc", "docs", "wiki" ] 50 | }, 51 | { 52 | "title": "\n\n
\n\n#### 🧪 Tests & Demo Vault", 53 | "labels": [ "kind/test", "test", "tests", "vault" ] 54 | } 55 | ], 56 | "sort": "ASC", 57 | "pr_template": "- ${{TITLE_ONLY}} : #{{MERGE_SHA}} @#{{AUTHOR}}", 58 | "empty_template": "- No major changes to address in this release", 59 | "custom_placeholders": [ 60 | { 61 | "name": "TITLE_ONLY", 62 | "source": "TITLE", 63 | "transformer": { 64 | "method": "regexr", 65 | "pattern": "(\\w+(\\(.+\\))?: ?)?(.+)", 66 | "target": "$2 $3" 67 | } 68 | } 69 | ], 70 | "label_extractor": [ 71 | { 72 | "pattern": "^(build|ci|change|chore|doc|docs|wiki|remove|deprecate|security|dependency|dep|package|feat|feature|fix|bug|perf|optimize|optimization|refactor|style|test|tests|vault):(.*)", 73 | "target": "$1", 74 | "on_property": "title" 75 | }, 76 | { 77 | "pattern": "^(build|ci|change|chore|doc|docs|wiki|remove|deprecate|security|dependency|dep|package|feat|feature|fix|bug|perf|optimize|optimization|refactor|style|test|tests|vault){1}(\\([\\w\\-\\.]+\\))?(!)?:(.*)", 78 | "target": "$1", 79 | "on_property": "title" 80 | } 81 | ], 82 | "duplicate_filter": { 83 | "pattern": "github.*", 84 | "on_property": "author", 85 | "method": "match" 86 | }, 87 | "max_tags_to_fetch": 200, 88 | "max_pull_requests": 200, 89 | "max_back_track_time_days": 365, 90 | "exclude_merge_branches": [], 91 | "tag_resolver": { 92 | "method": "semver" 93 | }, 94 | "base_branches": [] 95 | } 96 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2024 Aetherinox 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | version: 2 24 | updates: 25 | - package-ecosystem: npm 26 | directory: "/" 27 | schedule: 28 | interval: daily 29 | labels: 30 | - "Type ◦ Dependency" 31 | 32 | - package-ecosystem: "github-actions" 33 | directory: "/" 34 | schedule: 35 | interval: "daily" 36 | labels: 37 | - "Type ◦ Git Action" -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # Number of labels to fetch (optional). Defaults to 100 2 | numLabels: 40 3 | # These labels will not be used even if the issue contains them (optional). 4 | # Pass a blank array if no labels are to be excluded. 5 | # excludeLabels: [] 6 | excludeLabels: 7 | - pinned 8 | # custom configuration to override default behaviour 9 | # control explicitly what gets added and when 10 | custom: 11 | - location: title 12 | keywords: 13 | - '[roadmap]' 14 | labels: 15 | - Type ◦ Roadmap 16 | - location: title 17 | keywords: 18 | - '[road-map]' 19 | labels: 20 | - Type ◦ Roadmap 21 | - location: title 22 | keywords: 23 | - '[bug]' 24 | labels: 25 | - Type ◦ Bug 26 | - location: title 27 | keywords: 28 | - '[issue]' 29 | labels: 30 | - Type ◦ Bug 31 | - location: title 32 | keywords: 33 | - '[feature]' 34 | labels: 35 | - Type ◦ Feature 36 | - location: body 37 | keywords: 38 | - 'request feature' 39 | labels: 40 | - Type ◦ Feature 41 | - location: title 42 | keywords: 43 | - '[request]' 44 | labels: 45 | - Type ◦ Feature -------------------------------------------------------------------------------- /.github/workflows/cache-clean.yml: -------------------------------------------------------------------------------- 1 | # # 2 | # @type github workflow 3 | # @author Aetherinox 4 | # @url https://github.com/Aetherinox 5 | # @usage cleans up the cache for a repository. 6 | # 7 | # 8 | # You can view your current cached items by going to Github and going to the page: 9 | # https://github.com/USERNAME/REPO/actions/caches 10 | # 11 | # Caches have branch scope restrictions in place, which means some caches have limited usage options. For more information 12 | # on cache scope restrictions, see Restrictions for accessing a cache, earlier in this article. If caches limited to a specific 13 | # branch are using a lot of storage quota, it may cause caches from the default branch to be created and deleted at a high frequency. 14 | # 15 | # For example, a repository could have many new pull requests opened, each with their own caches that are restricted to that branch. 16 | # These caches could take up the majority of the cache storage for that repository. Once a repository has reached its maximum cache 17 | # storage, the cache eviction policy will create space by deleting the caches in order of last access date, from oldest to most 18 | # recent. In order to prevent cache thrashing when this happens, you can set up workflows to delete caches on a faster cadence than 19 | # the cache eviction policy will. You can use the GitHub CLI to delete caches for specific branches. 20 | # 21 | # @reference https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows#deleting-cache-entries 22 | # 23 | # 24 | # @secrets secrets.SELF_TOKEN self github personal access token (fine-grained) 25 | # secrets.SELF_TOKEN_CL self github personal access token (classic) 26 | # secrets.NPM_TOKEN self npmjs access token 27 | # secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/ 28 | # secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/ 29 | # secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token 30 | # secrets.CODECOV_TOKEN codecov upload token for nodejs projects 31 | # secrets.MAXMIND_GELITE_TOKEN maxmind API token 32 | # secrets.CF_ACCOUNT_ID cloudflare account id 33 | # secrets.CF_ACCOUNT_TOKEN cloudflare account token 34 | # secrets.ORG_TOKEN org github personal access token (fine-grained) 35 | # secrets.ORG_TOKEN_CL org github personal access token (classic) 36 | # secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret 37 | # secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission 38 | # secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK 39 | # secrets.BOT_GPG_KEY_B64 bot gpg private key (binary) converted to base64 40 | # secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase 41 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord 42 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord 43 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord 44 | # 45 | # 46 | # @local these workflows can be tested locally through the use of `act` 47 | # https://github.com/nektos/act 48 | # Extract act to folder 49 | # Add system env var with path to act.exe 50 | # Run the commands: 51 | # git pull https://github.com/username/repo 52 | # act -W .github/workflows/cache-clean.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04 53 | # act -W .github/workflows/cache-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false 54 | # # 55 | 56 | # # 57 | 58 | name: '🧹 Cache › Clean' 59 | run-name: '🧹 Cache › Clean' 60 | 61 | # # 62 | # triggers 63 | # # 64 | 65 | on: 66 | 67 | # # 68 | # Trigger › Workflow Dispatch 69 | # # 70 | 71 | workflow_dispatch: 72 | inputs: 73 | 74 | # # 75 | # Cache › Num Per Page 76 | # 77 | # this is the number of cached items to fetch per page. 78 | # # 79 | 80 | NUM_PER_PAGE: 81 | description: '📦 Number Per Page' 82 | required: true 83 | default: '100' 84 | type: string 85 | 86 | # # 87 | # environment variables 88 | # # 89 | 90 | env: 91 | NUM_PER_PAGE: ${{ github.event.inputs.NUM_PER_PAGE || '100' }} 92 | BOT_NAME_1: EuropaServ 93 | BOT_NAME_2: BinaryServ 94 | BOT_NAME_DEPENDABOT: dependabot[bot] 95 | BOT_NAME_RENOVATE: renovate[bot] 96 | 97 | # # 98 | # jobs 99 | # # 100 | 101 | jobs: 102 | cleanup: 103 | name: >- 104 | 🧹 Cache › Clean 105 | runs-on: ubuntu-latest 106 | # runs-on: apollo-x64 107 | timeout-minutes: 5 108 | permissions: write-all 109 | 110 | steps: 111 | 112 | # # 113 | # Cache › Clean › Checkout 114 | # # 115 | 116 | - name: '☑️ Checkout' 117 | uses: actions/checkout@v4 118 | with: 119 | fetch-depth: 0 120 | 121 | # # 122 | # Cache › Clean › Job Information 123 | # # 124 | 125 | - name: >- 126 | 🔄 Load Job 127 | uses: qoomon/actions--context@v4 128 | id: 'context' 129 | 130 | # # 131 | # Cache › Clean › Start 132 | # # 133 | 134 | - name: >- 135 | ✅ Start 136 | run: | 137 | echo "‎" 138 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 139 | echo " Starting Job ${{ steps.context.outputs.job_name }}" 140 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 141 | 142 | YEAR="$(date +'%Y')" 143 | echo "YEAR=${YEAR}" >> $GITHUB_ENV 144 | 145 | NOW="$(date +'%m-%d-%Y %H:%M:%S')" # 02-25-2025 12:49:48 146 | echo "NOW=${NOW}" >> $GITHUB_ENV 147 | 148 | NOW_SHORT="$(date +'%m-%d-%Y')" # 02-25-2025 149 | echo "NOW_SHORT=${NOW_SHORT}" >> $GITHUB_ENV 150 | 151 | NOW_LONG="$(date +'%m-%d-%Y %H:%M')" # 02-25-2025 12:49 152 | echo "NOW_LONG=${NOW_LONG}" >> $GITHUB_ENV 153 | 154 | NOW_DOCKER="$(date +'%Y%m%d')" # 20250225 155 | echo "NOW_DOCKER=${NOW_DOCKER}" >> $GITHUB_ENV 156 | 157 | NOW_DOCKER_TS="$(date -u +'%FT%T.%3NZ')" # 2025-02-25T12:50:11.569Z 158 | echo "NOW_DOCKER_TS=${NOW_DOCKER_TS}" >> $GITHUB_ENV 159 | 160 | SHA1="$(git rev-parse HEAD)" # 71fad013cfce9116ec62779e4a7e627fe4c33627 161 | echo "SHA1=${SHA1}" >> $GITHUB_ENV 162 | 163 | SHA1_GH="$(echo ${GITHUB_SHA})" # 71fad013cfce9116ec62779e4a7e627fe4c33627 164 | echo "SHA1_GH=${SHA1_GH}" >> $GITHUB_ENV 165 | 166 | PKG_VER_1DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1)" # 3.22 > 3 167 | echo "PKG_VER_1DIGIT=${PKG_VER_1DIGIT}" >> $GITHUB_ENV 168 | 169 | PKG_VER_2DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -f2 -d ":" | cut -c1-3)" # 3.22 > 3.2 170 | echo "PKG_VER_2DIGIT=${PKG_VER_2DIGIT}" >> $GITHUB_ENV 171 | 172 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 173 | echo "‎" 174 | echo "‎" 175 | sudo apt -qq update 176 | sudo apt -qq install tree 177 | echo "‎" 178 | echo "‎" 179 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 180 | echo "‎" 181 | echo "‎" 182 | echo " Runner .............. ${{ runner.name }}" 183 | echo " Workflow ............ ${{ github.workflow }} (#${{ github.workflow_ref }})" 184 | echo " Run Number .......... ${{ github.run_number }}" 185 | echo " Ref ................. ${{ github.ref }}" 186 | echo " Ref Name ............ ${{ github.ref_name }}" 187 | echo " Event Name .......... ${{ github.event_name }}" 188 | echo " Repo ................ ${{ github.repository }}" 189 | echo " Repo Owner .......... ${{ github.repository_owner }}" 190 | echo " Run ID .............. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" 191 | echo " Triggered By ........ ${{ github.actor }}" 192 | echo " SHA 1 (GITHUB_SHA) .. ${GITHUB_SHA}" 193 | echo " SHA 2 (github.sha) .. ${{ github.sha }}" 194 | echo " SHA 3 (env.SHA1) .... ${SHA1}" 195 | echo " SHA 4 (env.SHA1_GH) . ${SHA1_GH}" 196 | echo " Workspace ........... ${{ github.workspace }}" 197 | echo " PWD ................. ${PWD}" 198 | echo " Job Name ............ ${{ steps.context.outputs.job_name }}" 199 | echo " Job ID .............. ${{ steps.context.outputs.job_id }}" 200 | echo " Job URL ............. ${{ steps.context.outputs.job_url }}" 201 | echo " Run ID .............. ${{ steps.context.outputs.run_id }}" 202 | echo " Run Attempt ......... ${{ steps.context.outputs.run_attempt }}" 203 | echo " Run Number .......... ${{ steps.context.outputs.run_number }}" 204 | echo " Run URL ............. ${{ steps.context.outputs.run_url }}" 205 | echo " Run Env ............. ${{ steps.context.outputs.environment }}" 206 | echo " Run Env URL ......... ${{ steps.context.outputs.environment_url }}" 207 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 208 | echo " Run Deployment URL .. ${{ steps.context.outputs.deployment_url }}" 209 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 210 | echo " Run Runner Name ..... ${{ steps.context.outputs.runner_name }}" 211 | echo " Run Runner ID ....... ${{ steps.context.outputs.runner_id }}" 212 | echo " Year ................ ${YEAR}" 213 | echo " Now ................. ${NOW}" 214 | echo " Now (Short) ......... ${NOW_SHORT}" 215 | echo " Now (Long) .......... ${NOW_LONG}" 216 | echo " Now (Docker) ........ ${NOW_DOCKER}" 217 | echo " Now (Docker TS) ..... ${NOW_DOCKER_TS}" 218 | echo "‎" 219 | echo "‎" 220 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 221 | echo "‎" 222 | echo "‎" 223 | tree -I node_modules -I .git 224 | echo "‎" 225 | echo "‎" 226 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 227 | echo "‎" 228 | echo "‎" 229 | 230 | # # 231 | # Cache › Clean › Start 232 | # 233 | # You can view your current cached items by going to Github and going to the page: 234 | # https://github.com/USERNAME/REPO/actions/caches 235 | # 236 | # Caches have branch scope restrictions in place, which means some caches have limited usage options. For more information 237 | # on cache scope restrictions, see Restrictions for accessing a cache, earlier in this article. If caches limited to a specific 238 | # branch are using a lot of storage quota, it may cause caches from the default branch to be created and deleted at a high frequency. 239 | # 240 | # For example, a repository could have many new pull requests opened, each with their own caches that are restricted to that branch. 241 | # These caches could take up the majority of the cache storage for that repository. Once a repository has reached its maximum cache 242 | # storage, the cache eviction policy will create space by deleting the caches in order of last access date, from oldest to most 243 | # recent. In order to prevent cache thrashing when this happens, you can set up workflows to delete caches on a faster cadence than 244 | # the cache eviction policy will. You can use the GitHub CLI to delete caches for specific branches. 245 | # 246 | # @reference https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows#deleting-cache-entries 247 | # # 248 | 249 | - name: >- 250 | 🪣 Cache › Clean 251 | uses: actions/github-script@v7 252 | with: 253 | script: | 254 | try 255 | { 256 | const cacheConf = 257 | { 258 | owner: context.repo.owner, 259 | repo: context.repo.repo, 260 | per_page: ${{ env.NUM_PER_PAGE }}, 261 | }; 262 | 263 | console.log( `✅ Starting to clean cache; showing ${{ env.NUM_PER_PAGE }} cached items per page` ) 264 | const caches = await github.rest.actions.getActionsCacheList( cacheConf ) 265 | 266 | while( caches.data.actions_caches.length ) 267 | { 268 | for ( const cache of caches.data.actions_caches ) 269 | { 270 | console.log( `⚠️ Clearing cache id: ${cache.key} (${cache.id})` ) 271 | const res = await github.rest.actions.deleteActionsCacheById( 272 | { 273 | owner: context.repo.owner, 274 | repo: context.repo.repo, 275 | cache_id: cache.id, 276 | }); 277 | 278 | console.log( `✔️ Cache item ${cache.key} (${cache.id}) cleared at ${new Date().toISOString()}` ) 279 | } 280 | 281 | caches = await github.rest.actions.getActionsCacheList(congif); 282 | console.log( `Getting another ${caches.data.actions_caches.length} caches from github ...` ); 283 | } 284 | 285 | console.log( `✔️ Finished cleaning the cache` ); 286 | } 287 | catch( e ) 288 | { 289 | console.log( `❌ The workflow has terminated with an error:`, e ) 290 | return; 291 | } 292 | 293 | # # 294 | # Cache › Clean › Get Weekly Commits 295 | # # 296 | 297 | - name: >- 298 | 🕛 Get Weekly Commit List 299 | run: | 300 | echo 'WEEKLY_COMMITS<> $GITHUB_ENV 301 | git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV 302 | echo 'EOF' >> $GITHUB_ENV -------------------------------------------------------------------------------- /.github/workflows/deploy-clean.yml: -------------------------------------------------------------------------------- 1 | # # 2 | # @type github workflow 3 | # @author Aetherinox 4 | # @url https://github.com/Aetherinox 5 | # @usage cleans up the list of deployments in the environment history 6 | # edit the 'environment:' to determine which deployment to keep clean 7 | # - can be ran manually 8 | # 9 | # @secrets secrets.SELF_TOKEN self github personal access token (fine-grained) 10 | # secrets.SELF_TOKEN_CL self github personal access token (classic) 11 | # secrets.NPM_TOKEN self npmjs access token 12 | # secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/ 13 | # secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/ 14 | # secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token 15 | # secrets.CODECOV_TOKEN codecov upload token for nodejs projects 16 | # secrets.MAXMIND_GELITE_TOKEN maxmind API token 17 | # secrets.CF_ACCOUNT_ID cloudflare account id 18 | # secrets.CF_ACCOUNT_TOKEN cloudflare account token 19 | # secrets.ORG_TOKEN org github personal access token (fine-grained) 20 | # secrets.ORG_TOKEN_CL org github personal access token (classic) 21 | # secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret 22 | # secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission 23 | # secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK 24 | # secrets.BOT_GPG_KEY_B64 bot gpg private key (binary) converted to base64 25 | # secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase 26 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord 27 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord 28 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord 29 | # 30 | # 31 | # @local these workflows can be tested locally through the use of `act` 32 | # https://github.com/nektos/act 33 | # Extract act to folder 34 | # Add system env var with path to act.exe 35 | # Run the commands: 36 | # git pull https://github.com/username/repo 37 | # act -W .github/workflows/deploy-clean.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04 38 | # act -W .github/workflows/deploy-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false 39 | # # 40 | 41 | # # 42 | 43 | name: '🧹 Deployments › Clean' 44 | run-name: '🧹 Deployments › Clean' 45 | 46 | # # 47 | # triggers 48 | # # 49 | 50 | on: 51 | 52 | # # 53 | # Trigger > Workflow Dispatch 54 | # # 55 | 56 | workflow_dispatch: 57 | inputs: 58 | 59 | # # 60 | # Deployment Environment Name 61 | # 62 | # this is the name of the deployment item 63 | # # 64 | 65 | DEPLOYMENT_ENV: 66 | description: '📦 Deployment Environment' 67 | required: true 68 | default: 'orion' 69 | type: string 70 | 71 | # # 72 | # Delay 73 | # 74 | # Milliseconds to wait between cleaning up each action in history. Avoids secondary rate limit. Default: 500 75 | # # 76 | 77 | DEPLOYMENT_DELAY: 78 | description: '🕛 Delete Delay' 79 | required: true 80 | default: '1000' 81 | type: string 82 | 83 | # # 84 | # environment variables 85 | # # 86 | 87 | env: 88 | DEPLOYMENT_ENV: ${{ github.event.inputs.DEPLOYMENT_ENV || 'orion' }} 89 | DEPLOYMENT_DELAY: ${{ github.event.inputs.DEPLOYMENT_DELAY || '1000' }} 90 | BOT_NAME_1: EuropaServ 91 | BOT_NAME_2: BinaryServ 92 | BOT_NAME_DEPENDABOT: dependabot[bot] 93 | BOT_NAME_RENOVATE: renovate[bot] 94 | 95 | # # 96 | # jobs 97 | # # 98 | 99 | jobs: 100 | cleanup: 101 | name: >- 102 | 🧹 Deployments › Clean 103 | runs-on: ubuntu-latest 104 | # runs-on: apollo-x64 105 | timeout-minutes: 5 106 | permissions: write-all 107 | 108 | steps: 109 | 110 | # # 111 | # Deployments › Clean › Checkout 112 | # # 113 | 114 | - name: '☑️ Checkout' 115 | uses: actions/checkout@v4 116 | with: 117 | fetch-depth: 0 118 | 119 | # # 120 | # Deployments › Clean › Job Information 121 | # # 122 | 123 | - name: >- 124 | 🔄 Load Job 125 | uses: qoomon/actions--context@v4 126 | id: 'context' 127 | 128 | # # 129 | # Deployments › Clean › Start 130 | # # 131 | 132 | - name: >- 133 | ✅ Start 134 | run: | 135 | echo "‎" 136 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 137 | echo " Starting Job ${{ steps.context.outputs.job_name }}" 138 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 139 | 140 | YEAR="$(date +'%Y')" 141 | echo "YEAR=${YEAR}" >> $GITHUB_ENV 142 | 143 | NOW="$(date +'%m-%d-%Y %H:%M:%S')" # 02-25-2025 12:49:48 144 | echo "NOW=${NOW}" >> $GITHUB_ENV 145 | 146 | NOW_SHORT="$(date +'%m-%d-%Y')" # 02-25-2025 147 | echo "NOW_SHORT=${NOW_SHORT}" >> $GITHUB_ENV 148 | 149 | NOW_LONG="$(date +'%m-%d-%Y %H:%M')" # 02-25-2025 12:49 150 | echo "NOW_LONG=${NOW_LONG}" >> $GITHUB_ENV 151 | 152 | NOW_DOCKER="$(date +'%Y%m%d')" # 20250225 153 | echo "NOW_DOCKER=${NOW_DOCKER}" >> $GITHUB_ENV 154 | 155 | NOW_DOCKER_TS="$(date -u +'%FT%T.%3NZ')" # 2025-02-25T12:50:11.569Z 156 | echo "NOW_DOCKER_TS=${NOW_DOCKER_TS}" >> $GITHUB_ENV 157 | 158 | SHA1="$(git rev-parse HEAD)" # 71fad013cfce9116ec62779e4a7e627fe4c33627 159 | echo "SHA1=${SHA1}" >> $GITHUB_ENV 160 | 161 | SHA1_GH="$(echo ${GITHUB_SHA})" # 71fad013cfce9116ec62779e4a7e627fe4c33627 162 | echo "SHA1_GH=${SHA1_GH}" >> $GITHUB_ENV 163 | 164 | PKG_VER_1DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1)" # 3.22 > 3 165 | echo "PKG_VER_1DIGIT=${PKG_VER_1DIGIT}" >> $GITHUB_ENV 166 | 167 | PKG_VER_2DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -f2 -d ":" | cut -c1-3)" # 3.22 > 3.2 168 | echo "PKG_VER_2DIGIT=${PKG_VER_2DIGIT}" >> $GITHUB_ENV 169 | 170 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 171 | echo "‎" 172 | echo "‎" 173 | sudo apt -qq update 174 | sudo apt -qq install tree 175 | echo "‎" 176 | echo "‎" 177 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 178 | echo "‎" 179 | echo "‎" 180 | echo " Runner .............. ${{ runner.name }}" 181 | echo " Workflow ............ ${{ github.workflow }} (#${{ github.workflow_ref }})" 182 | echo " Run Number .......... ${{ github.run_number }}" 183 | echo " Ref ................. ${{ github.ref }}" 184 | echo " Ref Name ............ ${{ github.ref_name }}" 185 | echo " Event Name .......... ${{ github.event_name }}" 186 | echo " Repo ................ ${{ github.repository }}" 187 | echo " Repo Owner .......... ${{ github.repository_owner }}" 188 | echo " Run ID .............. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" 189 | echo " Triggered By ........ ${{ github.actor }}" 190 | echo " SHA 1 (GITHUB_SHA) .. ${GITHUB_SHA}" 191 | echo " SHA 2 (github.sha) .. ${{ github.sha }}" 192 | echo " SHA 3 (env.SHA1) .... ${SHA1}" 193 | echo " SHA 4 (env.SHA1_GH) . ${SHA1_GH}" 194 | echo " Workspace ........... ${{ github.workspace }}" 195 | echo " PWD ................. ${PWD}" 196 | echo " Job Name ............ ${{ steps.context.outputs.job_name }}" 197 | echo " Job ID .............. ${{ steps.context.outputs.job_id }}" 198 | echo " Job URL ............. ${{ steps.context.outputs.job_url }}" 199 | echo " Run ID .............. ${{ steps.context.outputs.run_id }}" 200 | echo " Run Attempt ......... ${{ steps.context.outputs.run_attempt }}" 201 | echo " Run Number .......... ${{ steps.context.outputs.run_number }}" 202 | echo " Run URL ............. ${{ steps.context.outputs.run_url }}" 203 | echo " Run Env ............. ${{ steps.context.outputs.environment }}" 204 | echo " Run Env URL ......... ${{ steps.context.outputs.environment_url }}" 205 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 206 | echo " Run Deployment URL .. ${{ steps.context.outputs.deployment_url }}" 207 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 208 | echo " Run Runner Name ..... ${{ steps.context.outputs.runner_name }}" 209 | echo " Run Runner ID ....... ${{ steps.context.outputs.runner_id }}" 210 | echo " Year ................ ${YEAR}" 211 | echo " Now ................. ${NOW}" 212 | echo " Now (Short) ......... ${NOW_SHORT}" 213 | echo " Now (Long) .......... ${NOW_LONG}" 214 | echo " Now (Docker) ........ ${NOW_DOCKER}" 215 | echo " Now (Docker TS) ..... ${NOW_DOCKER_TS}" 216 | echo "‎" 217 | echo "‎" 218 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 219 | echo "‎" 220 | echo "‎" 221 | tree -I node_modules -I .git 222 | echo "‎" 223 | echo "‎" 224 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 225 | echo "‎" 226 | echo "‎" 227 | 228 | # # 229 | # Deployments › Clean › Start 230 | # # 231 | 232 | - name: >- 233 | ⚙️ Deployments › Clean 234 | uses: Aetherinox/delete-deploy-env-action@v3 235 | with: 236 | token: ${{ secrets.SELF_TOKEN_CL }} 237 | environment: '${{ env.DEPLOYMENT_ENV }}' 238 | onlyRemoveDeployments: true 239 | delay: "${{ env.DEPLOYMENT_DELAY }}" 240 | 241 | # # 242 | # Deployments › Clean › Get Weekly Commits 243 | # # 244 | 245 | - name: >- 246 | 🕛 Get Weekly Commit List 247 | run: | 248 | echo 'WEEKLY_COMMITS<> $GITHUB_ENV 249 | git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV 250 | echo 'EOF' >> $GITHUB_ENV 251 | 252 | -------------------------------------------------------------------------------- /.github/workflows/gpg-tests.yml: -------------------------------------------------------------------------------- 1 | # # 2 | # @type github workflow 3 | # @author Aetherinox 4 | # @url https://github.com/Aetherinox 5 | # @usage tests gpg keys 6 | # 7 | # @secrets secrets.SELF_TOKEN self github personal access token (fine-grained) 8 | # secrets.SELF_TOKEN_CL self github personal access token (classic) 9 | # secrets.NPM_TOKEN self npmjs access token 10 | # secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/ 11 | # secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/ 12 | # secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token 13 | # secrets.CODECOV_TOKEN codecov upload token for nodejs projects 14 | # secrets.MAXMIND_GELITE_TOKEN maxmind API token 15 | # secrets.CF_ACCOUNT_ID cloudflare account id 16 | # secrets.CF_ACCOUNT_TOKEN cloudflare account token 17 | # secrets.ORG_TOKEN org github personal access token (fine-grained) 18 | # secrets.ORG_TOKEN_CL org github personal access token (classic) 19 | # secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret 20 | # secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission 21 | # secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK 22 | # secrets.BOT_GPG_KEY_B64 bot gpg private key (binary) converted to base64 23 | # secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase 24 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord 25 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord 26 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord 27 | # 28 | # @local these workflows can be tested locally through the use of `act` 29 | # https://github.com/nektos/act 30 | # Extract act to folder 31 | # Add system env var with path to act.exe 32 | # Run the commands: 33 | # git pull https://github.com/username/repo 34 | # act -W .github/workflows/gpg-tests.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04 35 | # act -W .github/workflows/gpg-tests.yml -s TOKEN_CL=XXXXXXXXXX --pull=false 36 | # # 37 | 38 | name: '🔑 GPG › Tests' 39 | run-name: '🔑 GPG › Tests' 40 | 41 | # # 42 | # triggers 43 | # # 44 | 45 | on: 46 | workflow_dispatch: 47 | inputs: 48 | 49 | # # 50 | # Name of the plugin to use when creating the release zip filename 51 | # e.g: ntfy-desktop-v1.0.0.zip 52 | # # 53 | 54 | PROJECT_NAME: 55 | description: '📦 Name of App' 56 | required: true 57 | default: 'ntfy-desktop' 58 | type: string 59 | 60 | # # 61 | # environment variables 62 | # # 63 | 64 | env: 65 | PROJECT_NAME: ${{ github.event.inputs.PROJECT_NAME || 'ntfy-desktop' }} 66 | ASSIGN_USER: Aetherinox 67 | BOT_NAME_1: EuropaServ 68 | BOT_NAME_2: BinaryServ 69 | BOT_NAME_DEPENDABOT: dependabot[bot] 70 | BOT_NAME_RENOVATE: renovate[bot] 71 | GPG_KEY_BASE64: ${{ secrets.ADMINSERV_GPG_KEY_B64 }} 72 | GPG_KEY_PASSPHRASE: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }} 73 | 74 | # # 75 | # Jobs 76 | # # 77 | 78 | jobs: 79 | 80 | # # 81 | # JOB > INITIALIZE 82 | # # 83 | 84 | job-initialize: 85 | name: >- 86 | 🔑 GPG › Tests 87 | runs-on: ubuntu-latest 88 | # runs-on: apollo-x64 89 | timeout-minutes: 5 90 | outputs: 91 | package_version: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }} 92 | permissions: 93 | contents: write 94 | packages: write 95 | steps: 96 | 97 | # # 98 | # GPG › Checkout 99 | # # 100 | 101 | - name: '☑️ Checkout' 102 | uses: actions/checkout@v4 103 | with: 104 | fetch-depth: 0 105 | 106 | # # 107 | # GPG › Job Information 108 | # # 109 | 110 | - name: >- 111 | 🔄 Load Job 112 | uses: qoomon/actions--context@v4 113 | id: 'context' 114 | 115 | # # 116 | # GPG › Start 117 | # # 118 | 119 | - name: >- 120 | ✅ Start 121 | run: | 122 | echo "‎" 123 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 124 | echo " Starting Job ${{ steps.context.outputs.job_name }}" 125 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 126 | 127 | YEAR="$(date +'%Y')" 128 | echo "YEAR=${YEAR}" >> $GITHUB_ENV 129 | 130 | NOW="$(date +'%m-%d-%Y %H:%M:%S')" # 02-25-2025 12:49:48 131 | echo "NOW=${NOW}" >> $GITHUB_ENV 132 | 133 | NOW_SHORT="$(date +'%m-%d-%Y')" # 02-25-2025 134 | echo "NOW_SHORT=${NOW_SHORT}" >> $GITHUB_ENV 135 | 136 | NOW_LONG="$(date +'%m-%d-%Y %H:%M')" # 02-25-2025 12:49 137 | echo "NOW_LONG=${NOW_LONG}" >> $GITHUB_ENV 138 | 139 | NOW_DOCKER="$(date +'%Y%m%d')" # 20250225 140 | echo "NOW_DOCKER=${NOW_DOCKER}" >> $GITHUB_ENV 141 | 142 | NOW_DOCKER_TS="$(date -u +'%FT%T.%3NZ')" # 2025-02-25T12:50:11.569Z 143 | echo "NOW_DOCKER_TS=${NOW_DOCKER_TS}" >> $GITHUB_ENV 144 | 145 | SHA1="$(git rev-parse HEAD)" # 71fad013cfce9116ec62779e4a7e627fe4c33627 146 | echo "SHA1=${SHA1}" >> $GITHUB_ENV 147 | 148 | SHA1_GH="$(echo ${GITHUB_SHA})" # 71fad013cfce9116ec62779e4a7e627fe4c33627 149 | echo "SHA1_GH=${SHA1_GH}" >> $GITHUB_ENV 150 | 151 | PKG_VER_1DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1)" # 3.22 > 3 152 | echo "PKG_VER_1DIGIT=${PKG_VER_1DIGIT}" >> $GITHUB_ENV 153 | 154 | PKG_VER_2DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -f2 -d ":" | cut -c1-3)" # 3.22 > 3.2 155 | echo "PKG_VER_2DIGIT=${PKG_VER_2DIGIT}" >> $GITHUB_ENV 156 | 157 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 158 | echo "‎" 159 | echo "‎" 160 | sudo apt -qq update 161 | sudo apt -qq install tree 162 | echo "‎" 163 | echo "‎" 164 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 165 | echo "‎" 166 | echo "‎" 167 | echo " Runner .............. ${{ runner.name }}" 168 | echo " Workflow ............ ${{ github.workflow }} (#${{ github.workflow_ref }})" 169 | echo " Run Number .......... ${{ github.run_number }}" 170 | echo " Ref ................. ${{ github.ref }}" 171 | echo " Ref Name ............ ${{ github.ref_name }}" 172 | echo " Event Name .......... ${{ github.event_name }}" 173 | echo " Repo ................ ${{ github.repository }}" 174 | echo " Repo Owner .......... ${{ github.repository_owner }}" 175 | echo " Run ID .............. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" 176 | echo " Triggered By ........ ${{ github.actor }}" 177 | echo " SHA 1 (GITHUB_SHA) .. ${GITHUB_SHA}" 178 | echo " SHA 2 (github.sha) .. ${{ github.sha }}" 179 | echo " SHA 3 (env.SHA1) .... ${SHA1}" 180 | echo " SHA 4 (env.SHA1_GH) . ${SHA1_GH}" 181 | echo " Workspace ........... ${{ github.workspace }}" 182 | echo " PWD ................. ${PWD}" 183 | echo " Job Name ............ ${{ steps.context.outputs.job_name }}" 184 | echo " Job ID .............. ${{ steps.context.outputs.job_id }}" 185 | echo " Job URL ............. ${{ steps.context.outputs.job_url }}" 186 | echo " Run ID .............. ${{ steps.context.outputs.run_id }}" 187 | echo " Run Attempt ......... ${{ steps.context.outputs.run_attempt }}" 188 | echo " Run Number .......... ${{ steps.context.outputs.run_number }}" 189 | echo " Run URL ............. ${{ steps.context.outputs.run_url }}" 190 | echo " Run Env ............. ${{ steps.context.outputs.environment }}" 191 | echo " Run Env URL ......... ${{ steps.context.outputs.environment_url }}" 192 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 193 | echo " Run Deployment URL .. ${{ steps.context.outputs.deployment_url }}" 194 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 195 | echo " Run Runner Name ..... ${{ steps.context.outputs.runner_name }}" 196 | echo " Run Runner ID ....... ${{ steps.context.outputs.runner_id }}" 197 | echo " Year ................ ${YEAR}" 198 | echo " Now ................. ${NOW}" 199 | echo " Now (Short) ......... ${NOW_SHORT}" 200 | echo " Now (Long) .......... ${NOW_LONG}" 201 | echo " Now (Docker) ........ ${NOW_DOCKER}" 202 | echo " Now (Docker TS) ..... ${NOW_DOCKER_TS}" 203 | echo "‎" 204 | echo "‎" 205 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 206 | echo "‎" 207 | echo "‎" 208 | tree -I node_modules -I .git 209 | echo "‎" 210 | echo "‎" 211 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 212 | echo "‎" 213 | echo "‎" 214 | 215 | # # 216 | # GPG › Get version from package.json VERSION value 217 | # # 218 | 219 | - name: '👁️‍🗨️ Get Package Version' 220 | id: task_initialize_package_getversion 221 | run: | 222 | VER=$(cat package.json | jq -r '.version') 223 | echo "PACKAGE_VERSION=$VER" >> $GITHUB_OUTPUT 224 | 225 | - name: '👁️‍🗨️ Get Package Version › Print' 226 | id: task_initialize_package_getversion_debug 227 | run: | 228 | echo "VERSION: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}" 229 | 230 | # # 231 | # GPG › Import Key (No Passphrase) 232 | # 233 | # requires your GPG private key, converted to base64 binary .gpg (not armored .asc) 234 | # # 235 | 236 | - name: '🪪 GPG › Import Signing Key › W/o Passphrase' 237 | if: env.GPG_KEY_BASE64 != '' && env.GPG_KEY_PASSPHRASE == '' 238 | run: | 239 | echo "$GPG_KEY_BASE64" | base64 -di | gpg --import 240 | 241 | # # 242 | # GPG › Import Key (With Passphrase) 243 | # 244 | # requires your GPG private key, converted to base64 binary .gpg (not armored .asc) 245 | # # 246 | 247 | - name: '🪪 GPG › Import Signing Key › w/ Passphrase' 248 | if: env.GPG_KEY_BASE64 != '' && env.GPG_KEY_PASSPHRASE != '' 249 | run: | 250 | echo "$GPG_KEY_BASE64" | base64 -di > /tmp/signing-key.gpg 251 | echo "$GPG_KEY_PASSPHRASE" | gpg --pinentry-mode loopback --passphrase-fd 0 --import /tmp/signing-key.gpg 252 | (echo "$GPG_KEY_PASSPHRASE"; echo; echo) | gpg --command-fd 0 --pinentry-mode loopback --change-passphrase $(gpg --list-secret-keys --with-colons 2> /dev/null | grep '^sec:' | cut --delimiter ':' --fields 5 | tail -n 1) 253 | 254 | # # 255 | # GPG › Checksum › Stable 256 | # # 257 | 258 | - name: '🆔 Checksum › Stable' 259 | run: | 260 | # windows 261 | file_1_example="package.json" 262 | file_2_example="package-lock.json" 263 | 264 | 265 | # get sha1 and sha256 for .json 266 | find . -maxdepth 1 \( -name '*.json' -o -name '*.gz' \) -printf '%P\n' | xargs -r sha1sum | gpg --digest-algo sha256 --clearsign > sha1sum.txt.asc 267 | find . -maxdepth 1 \( -name '*.json' -o -name '*.gz' \) -printf '%P\n' | xargs -r sha256sum | gpg --digest-algo sha256 --clearsign > sha256sum.txt.asc 268 | 269 | 270 | # SHA1SUM 271 | sha1sum_file_1="$(shasum --algorithm 1 ${file_1_example} | awk '{ print $1 }')" 272 | echo "SHA1SUM_FILE_1=${sha1sum_file_1}" >> $GITHUB_ENV 273 | 274 | sha1sum_file_2="$(shasum --algorithm 1 ${file_2_example} | awk '{ print $1 }')" 275 | echo "SHA1SUM_FILE_2=${sha1sum_file_2}" >> $GITHUB_ENV 276 | 277 | 278 | # SHA256SUM 279 | sha256sum_file_1="$(shasum --algorithm 256 ${file_1_example} | awk '{ print $1 }')" 280 | echo "SHA256SUM_FILE_1=${sha256sum_file_1}" >> $GITHUB_ENV 281 | 282 | sha256sum_file_2="$(shasum --algorithm 256 ${file_2_example} | awk '{ print $1 }')" 283 | echo "SHA256SUM_FILE_2=${sha256sum_file_2}" >> $GITHUB_ENV 284 | 285 | 286 | # no longer needed, replaced by find . command 287 | # shasum --algorithm 256 ${file_file_1} > SHA256SUMS.txt 288 | echo "FILE_1_EXAMPLE=${file_1_example}" >> $GITHUB_ENV 289 | echo "FILE_2_EXAMPLE=${file_2_example}" >> $GITHUB_ENV 290 | 291 | 292 | # generate sha256sum.sig from sha256sum.txt.asc file 293 | gpg --batch --yes --quiet --armor --detach-sig --sign --output sha256sum.sig sha256sum.txt.asc 294 | 295 | # # 296 | # GPG › Verbose › Print Results 297 | # # 298 | 299 | - name: '⚙️ Verbose › Print Results' 300 | run: | 301 | echo "‎" 302 | echo "‎" 303 | echo "‎" 304 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 305 | echo -e " 🌲 Tree" 306 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 307 | tree -I node_modules 308 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 309 | echo "‎" 310 | echo "‎" 311 | echo "‎" 312 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 313 | echo -e " 📄 sha256sum.txt.asc" 314 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 315 | cat sha256sum.txt.asc 316 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 317 | echo "‎" 318 | echo "‎" 319 | echo "‎" 320 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 321 | echo -e " 📄 sha1sum.txt.asc" 322 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 323 | cat sha1sum.txt.asc 324 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 325 | echo "‎" 326 | echo "‎" 327 | echo "‎" 328 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 329 | echo -e " 📄 sha256sum.sig" 330 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 331 | cat sha256sum.sig 332 | echo "‎" 333 | echo "‎" 334 | echo "‎" 335 | echo "Running command gpg --verify sha256sum.sig sha256sum.txt.asc" 336 | echo "‎" 337 | gpg --verify sha256sum.sig sha256sum.txt.asc 338 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 339 | echo "‎" 340 | echo "‎" 341 | echo "‎" 342 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 343 | echo -e " 🔑 List GPG Keys" 344 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 345 | gpg --list-keys --keyid-format=long --fingerprint --with-fingerprint 346 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 347 | echo "‎" 348 | echo "‎" 349 | echo "‎" 350 | 351 | # # 352 | # GPG › Checksum › Print 353 | # # 354 | 355 | - name: '🆔 Checksum › Print' 356 | run: | 357 | echo "‎" 358 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 359 | echo " Checksums" 360 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 361 | echo "‎" 362 | echo " ${{ env.FILE_1_EXAMPLE }} ${{ env.SHA256SUM_FILE_1 }}" 363 | echo " ${{ env.FILE_2_EXAMPLE }} ${{ env.SHA256SUM_FILE_2 }}" 364 | echo "‎" 365 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 366 | echo "‎" 367 | -------------------------------------------------------------------------------- /.github/workflows/history-clean.yml: -------------------------------------------------------------------------------- 1 | # # 2 | # @type github workflow 3 | # @author Aetherinox 4 | # @url https://github.com/Aetherinox 5 | # @usage cleans all commit history for a repository 6 | # edit the 'environment:' to determine which deployment to keep clean 7 | # - can be ran manually 8 | # 9 | # @secrets secrets.SELF_TOKEN self github personal access token (fine-grained) 10 | # secrets.SELF_TOKEN_CL self github personal access token (classic) 11 | # secrets.NPM_TOKEN self npmjs access token 12 | # secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/ 13 | # secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/ 14 | # secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token 15 | # secrets.CODECOV_TOKEN codecov upload token for nodejs projects 16 | # secrets.MAXMIND_GELITE_TOKEN maxmind API token 17 | # secrets.CF_ACCOUNT_ID cloudflare account id 18 | # secrets.CF_ACCOUNT_TOKEN cloudflare account token 19 | # secrets.ORG_TOKEN org github personal access token (fine-grained) 20 | # secrets.ORG_TOKEN_CL org github personal access token (classic) 21 | # secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret 22 | # secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission 23 | # secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK 24 | # secrets.BOT_GPG_KEY_B64 bot gpg private key (binary) converted to base64 25 | # secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase 26 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord 27 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord 28 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord 29 | # 30 | # 31 | # @local these workflows can be tested locally through the use of `act` 32 | # https://github.com/nektos/act 33 | # Extract act to folder 34 | # Add system env var with path to act.exe 35 | # Run the commands: 36 | # git pull https://github.com/username/repo 37 | # act -W .github/workflows/history-clean.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04 38 | # act -W .github/workflows/history-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false 39 | # # 40 | 41 | name: '🧹 History › Clean' 42 | run-name: '🧹 History › Clean' 43 | 44 | # # 45 | # triggers 46 | # # 47 | 48 | on: 49 | 50 | # # 51 | # Trigger > Workflow Dispatch 52 | # # 53 | 54 | workflow_dispatch: 55 | inputs: 56 | 57 | # # 58 | # Commit Label 59 | # 60 | # the label to use when repository is cleaned 61 | # # 62 | 63 | COMMIT_LABEL: 64 | description: '🏷️ Commit Label' 65 | required: true 66 | default: 'cleanup' 67 | type: string 68 | 69 | # # 70 | # Branch 71 | # 72 | # select branch to clean 73 | # you must also run the workflow from that branch 74 | # # 75 | 76 | BRANCH: 77 | description: '🌳 Branch' 78 | required: true 79 | default: 'main' 80 | type: string 81 | 82 | # # 83 | # environment variables 84 | # # 85 | 86 | env: 87 | COMMIT_LABEL: ${{ github.event.inputs.COMMIT_LABEL || 'cleanup' }} 88 | BRANCH: ${{ github.event.inputs.BRANCH || 'main' }} 89 | BOT_NAME_1: EuropaServ 90 | BOT_NAME_2: BinaryServ 91 | BOT_NAME_DEPENDABOT: dependabot[bot] 92 | BOT_NAME_RENOVATE: renovate[bot] 93 | 94 | # # 95 | # jobs 96 | # # 97 | 98 | jobs: 99 | history-clean: 100 | name: >- 101 | 🧹 History › Clean 102 | runs-on: ubuntu-latest 103 | # runs-on: apollo-x64 104 | timeout-minutes: 15 105 | permissions: 106 | contents: write 107 | steps: 108 | 109 | # # 110 | # History › Clean › Checkout 111 | # # 112 | 113 | - name: '☑️ Checkout' 114 | uses: actions/checkout@v4 115 | with: 116 | ref: ${{ env.BRANCH }} 117 | 118 | # # 119 | # History › Clean › Job Information 120 | # # 121 | 122 | - name: >- 123 | 🔄 Load Job 124 | uses: qoomon/actions--context@v4 125 | id: 'context' 126 | 127 | # # 128 | # History › Clean › Start 129 | # # 130 | 131 | - name: >- 132 | ✅ Start 133 | run: | 134 | echo "‎" 135 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 136 | echo " Starting Job ${{ steps.context.outputs.job_name }}" 137 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 138 | 139 | YEAR="$(date +'%Y')" 140 | echo "YEAR=${YEAR}" >> $GITHUB_ENV 141 | 142 | NOW="$(date +'%m-%d-%Y %H:%M:%S')" # 02-25-2025 12:49:48 143 | echo "NOW=${NOW}" >> $GITHUB_ENV 144 | 145 | NOW_SHORT="$(date +'%m-%d-%Y')" # 02-25-2025 146 | echo "NOW_SHORT=${NOW_SHORT}" >> $GITHUB_ENV 147 | 148 | NOW_LONG="$(date +'%m-%d-%Y %H:%M')" # 02-25-2025 12:49 149 | echo "NOW_LONG=${NOW_LONG}" >> $GITHUB_ENV 150 | 151 | NOW_DOCKER="$(date +'%Y%m%d')" # 20250225 152 | echo "NOW_DOCKER=${NOW_DOCKER}" >> $GITHUB_ENV 153 | 154 | NOW_DOCKER_TS="$(date -u +'%FT%T.%3NZ')" # 2025-02-25T12:50:11.569Z 155 | echo "NOW_DOCKER_TS=${NOW_DOCKER_TS}" >> $GITHUB_ENV 156 | 157 | SHA1="$(git rev-parse HEAD)" # 71fad013cfce9116ec62779e4a7e627fe4c33627 158 | echo "SHA1=${SHA1}" >> $GITHUB_ENV 159 | 160 | SHA1_GH="$(echo ${GITHUB_SHA})" # 71fad013cfce9116ec62779e4a7e627fe4c33627 161 | echo "SHA1_GH=${SHA1_GH}" >> $GITHUB_ENV 162 | 163 | PKG_VER_1DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1)" # 3.22 > 3 164 | echo "PKG_VER_1DIGIT=${PKG_VER_1DIGIT}" >> $GITHUB_ENV 165 | 166 | PKG_VER_2DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -f2 -d ":" | cut -c1-3)" # 3.22 > 3.2 167 | echo "PKG_VER_2DIGIT=${PKG_VER_2DIGIT}" >> $GITHUB_ENV 168 | 169 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 170 | echo "‎" 171 | echo "‎" 172 | sudo apt -qq update 173 | sudo apt -qq install tree 174 | echo "‎" 175 | echo "‎" 176 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 177 | echo "‎" 178 | echo "‎" 179 | echo " Runner .............. ${{ runner.name }}" 180 | echo " Workflow ............ ${{ github.workflow }} (#${{ github.workflow_ref }})" 181 | echo " Run Number .......... ${{ github.run_number }}" 182 | echo " Ref ................. ${{ github.ref }}" 183 | echo " Ref Name ............ ${{ github.ref_name }}" 184 | echo " Event Name .......... ${{ github.event_name }}" 185 | echo " Repo ................ ${{ github.repository }}" 186 | echo " Repo Owner .......... ${{ github.repository_owner }}" 187 | echo " Run ID .............. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" 188 | echo " Triggered By ........ ${{ github.actor }}" 189 | echo " SHA 1 (GITHUB_SHA) .. ${GITHUB_SHA}" 190 | echo " SHA 2 (github.sha) .. ${{ github.sha }}" 191 | echo " SHA 3 (env.SHA1) .... ${SHA1}" 192 | echo " SHA 4 (env.SHA1_GH) . ${SHA1_GH}" 193 | echo " Workspace ........... ${{ github.workspace }}" 194 | echo " PWD ................. ${PWD}" 195 | echo " Job Name ............ ${{ steps.context.outputs.job_name }}" 196 | echo " Job ID .............. ${{ steps.context.outputs.job_id }}" 197 | echo " Job URL ............. ${{ steps.context.outputs.job_url }}" 198 | echo " Run ID .............. ${{ steps.context.outputs.run_id }}" 199 | echo " Run Attempt ......... ${{ steps.context.outputs.run_attempt }}" 200 | echo " Run Number .......... ${{ steps.context.outputs.run_number }}" 201 | echo " Run URL ............. ${{ steps.context.outputs.run_url }}" 202 | echo " Run Env ............. ${{ steps.context.outputs.environment }}" 203 | echo " Run Env URL ......... ${{ steps.context.outputs.environment_url }}" 204 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 205 | echo " Run Deployment URL .. ${{ steps.context.outputs.deployment_url }}" 206 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 207 | echo " Run Runner Name ..... ${{ steps.context.outputs.runner_name }}" 208 | echo " Run Runner ID ....... ${{ steps.context.outputs.runner_id }}" 209 | echo " Year ................ ${YEAR}" 210 | echo " Now ................. ${NOW}" 211 | echo " Now (Short) ......... ${NOW_SHORT}" 212 | echo " Now (Long) .......... ${NOW_LONG}" 213 | echo " Now (Docker) ........ ${NOW_DOCKER}" 214 | echo " Now (Docker TS) ..... ${NOW_DOCKER_TS}" 215 | echo "‎" 216 | echo "‎" 217 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 218 | echo "‎" 219 | echo "‎" 220 | tree -I node_modules -I .git 221 | echo "‎" 222 | echo "‎" 223 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 224 | echo "‎" 225 | echo "‎" 226 | 227 | # # 228 | # History › Clean › Git Identify 229 | # # 230 | 231 | - name: >- 232 | 🪪 Configure Git Identity 233 | run: | 234 | git config --local user.email "github-actions[bot]@users.noreply.github.com" 235 | git config --local user.name "github-actions[bot]" 236 | 237 | # # 238 | # History › Clean › Pre-Commit 239 | # # 240 | 241 | - name: >- 242 | 📦 Commit › Pre-commit 243 | run: | 244 | now=$(date -u '+%m/%d/%Y %H:%M') 245 | commit_label="${{ env.COMMIT_LABEL }}" >> $GITHUB_ENV 246 | echo -e "$commit_label" 247 | commit_message="chore(maint): \\\`️️🧹 $commit_label 🧹\\\` \\\`$now UTC\\\`" >> $GITHUB_ENV 248 | echo -e "$commit_message" 249 | echo "COMMIT_MESSAGE=$(echo $commit_message)" >> $GITHUB_ENV 250 | echo "NOW=$(echo $now)" >> $GITHUB_ENV 251 | 252 | # # 253 | # History › Clean › Pre-Commit › Debug 254 | # # 255 | 256 | - name: >- 257 | 📦 Commit › Pre-commit › Debug 258 | run: | 259 | echo -e "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 260 | echo -e " Printing Values" 261 | echo -e "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 262 | echo -e " env.COMMIT_LABEL .................... ${{ env.COMMIT_LABEL }}" 263 | echo -e " env.COMMIT_MESSAGE .................. ${{ env.COMMIT_MESSAGE }}" 264 | echo -e " env.NOW ............................. ${{ env.NOW }}" 265 | 266 | # # 267 | # History › Clean › Start 268 | # # 269 | 270 | - name: >- 271 | 🧹 Clean Repo History 272 | run: | 273 | # Create a new orphan branch 274 | git checkout --orphan temp-branch 275 | 276 | # Add all files to the new branch 277 | git add -A 278 | 279 | # Commit the files to the new branch 280 | git commit -m "${{ env.COMMIT_MESSAGE }}" 281 | 282 | # Delete the old main branch 283 | git branch -D ${{ env.BRANCH }} 284 | 285 | # Rename the new orphan branch to main 286 | git branch -m ${{ env.BRANCH }} 287 | 288 | # Force push the new main branch to the remote repository 289 | git push -f origin ${{ env.BRANCH }} 290 | 291 | # # 292 | # History › Clean › References 293 | # # 294 | 295 | - name: >- 296 | 🗑️ Garbage Collection (Aggressive) 297 | run: | 298 | # Remove remote-tracking references to deleted branches (optional) 299 | git fetch origin --prune 300 | git repack 301 | git prune-packed 302 | git reflog expire --expire=now --all 303 | git gc --prune=now --aggressive 304 | 305 | # # 306 | # History › Clean › Commit 307 | # # 308 | 309 | - name: >- 310 | 📦 Commit › Execute 311 | uses: stefanzweifel/git-auto-commit-action@v6 312 | with: 313 | commit_message: ${{ env.COMMIT_MESSAGE }} 314 | -------------------------------------------------------------------------------- /.github/workflows/issues-accept.yml: -------------------------------------------------------------------------------- 1 | # # 2 | # @type github workflow 3 | # @author Aetherinox 4 | # @url https://github.com/Aetherinox 5 | # @usage adds a label to a PR when the command "/accept" is typed in the issue comments 6 | # do not attempt to use env variables in if condition. 7 | # do not accept to change GITHUB_TOKEN. 8 | # 9 | # @notes requires the following labels to be created in your repo: 10 | # - bug 11 | # - feature 12 | # - urgent 13 | # - roadmap 14 | # 15 | # @secrets secrets.SELF_TOKEN self github personal access token (fine-grained) 16 | # secrets.SELF_TOKEN_CL self github personal access token (classic) 17 | # secrets.NPM_TOKEN self npmjs access token 18 | # secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/ 19 | # secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/ 20 | # secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token 21 | # secrets.CODECOV_TOKEN codecov upload token for nodejs projects 22 | # secrets.MAXMIND_GELITE_TOKEN maxmind API token 23 | # secrets.CF_ACCOUNT_ID cloudflare account id 24 | # secrets.CF_ACCOUNT_TOKEN cloudflare account token 25 | # secrets.ORG_TOKEN org github personal access token (fine-grained) 26 | # secrets.ORG_TOKEN_CL org github personal access token (classic) 27 | # secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret 28 | # secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission 29 | # secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK 30 | # secrets.BOT_GPG_KEY_B64 bot gpg private key (binary) converted to base64 31 | # secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase 32 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord 33 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord 34 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord 35 | # 36 | # @local these workflows can be tested locally through the use of `act` 37 | # https://github.com/nektos/act 38 | # Extract act to folder 39 | # Add system env var with path to act.exe 40 | # Run the commands: 41 | # git pull https://github.com/username/repo 42 | # act -W .github/workflows/issues-accept.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04 43 | # act -W .github/workflows/issues-accept.yml -s TOKEN_CL=XXXXXXXXXX --pull=false 44 | # # 45 | 46 | name: '🎫 Issue › Accept' 47 | run-name: '🎫 Issue › Accept' 48 | 49 | # # 50 | # triggers 51 | # # 52 | 53 | on: 54 | issue_comment: 55 | types: [created] 56 | 57 | # # 58 | # environment variables 59 | # # 60 | 61 | env: 62 | LABEL_ACCEPT: 'Status › Accepted' 63 | DEPLOYMENT_ENV: ${{ github.event.inputs.DEPLOYMENT_ENV || 'orion' }} 64 | BOT_NAME_1: EuropaServ 65 | BOT_NAME_2: BinaryServ 66 | BOT_NAME_DEPENDABOT: dependabot[bot] 67 | BOT_NAME_RENOVATE: renovate[bot] 68 | 69 | # # 70 | # jobs 71 | # # 72 | 73 | jobs: 74 | 75 | # # 76 | # Issues › Accept 77 | # # 78 | 79 | issues-accept: 80 | name: >- 81 | 🎫 Issue › Accept 82 | if: | 83 | contains(github.event.comment.body, '/accept') && github.event.comment.user.login == 'Aetherinox' 84 | runs-on: ubuntu-latest 85 | # runs-on: apollo-x64 86 | timeout-minutes: 5 87 | steps: 88 | 89 | # # 90 | # Issues › Accept › Set TImestamps 91 | # # 92 | 93 | - name: >- 94 | 🕛 Get Timestamp 95 | id: task_issues_accept_set_timestamp 96 | run: | 97 | echo "YEAR=$(date +'%Y')" >> $GITHUB_ENV 98 | echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV 99 | echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV 100 | echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV 101 | echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV 102 | 103 | # # 104 | # Issues › Accept › Add Label to accepted PR 105 | # # 106 | 107 | - name: >- 108 | 🏷️ Assign Label › ${{ env.LABEL_ACCEPT }} 109 | run: | 110 | gh issue edit "$NUMBER" --add-label "$LABELS" 111 | env: 112 | GITHUB_TOKEN: ${{ secrets.SELF_TOKEN_CL }} 113 | GH_REPO: ${{ github.repository }} 114 | NUMBER: ${{ github.event.issue.number }} 115 | LABELS: ${{ env.LABEL_ACCEPT }} 116 | 117 | # # 118 | # Issues › Accept › Add assignee to accepted PR 119 | # # 120 | 121 | - name: >- 122 | 🏷️ Assign Assignee › ${{ github.repository_owner }} 123 | run: | 124 | gh issue edit "$NUMBER" --add-assignee "$ASSIGNEE" 125 | env: 126 | GITHUB_TOKEN: ${{ secrets.SELF_TOKEN_CL }} 127 | GH_REPO: ${{ github.repository }} 128 | NUMBER: ${{ github.event.issue.number }} 129 | ASSIGNEE: ${{ github.repository_owner }} 130 | -------------------------------------------------------------------------------- /.github/workflows/labels-create.yml: -------------------------------------------------------------------------------- 1 | # # 2 | # @type github workflow 3 | # @author Aetherinox 4 | # @url https://github.com/Aetherinox 5 | # @usage manually activated workflow to create issue labels 6 | # 7 | # @secrets secrets.SELF_TOKEN self github personal access token (fine-grained) 8 | # secrets.SELF_TOKEN_CL self github personal access token (classic) 9 | # secrets.NPM_TOKEN self npmjs access token 10 | # secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/ 11 | # secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/ 12 | # secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token 13 | # secrets.CODECOV_TOKEN codecov upload token for nodejs projects 14 | # secrets.MAXMIND_GELITE_TOKEN maxmind API token 15 | # secrets.CF_ACCOUNT_ID cloudflare account id 16 | # secrets.CF_ACCOUNT_TOKEN cloudflare account token 17 | # secrets.ORG_TOKEN org github personal access token (fine-grained) 18 | # secrets.ORG_TOKEN_CL org github personal access token (classic) 19 | # secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret 20 | # secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission 21 | # secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK 22 | # secrets.BOT_GPG_KEY_B64 bot gpg private key (binary) converted to base64 23 | # secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase 24 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord 25 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord 26 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord 27 | # 28 | # @local these workflows can be tested locally through the use of `act` 29 | # https://github.com/nektos/act 30 | # Extract act to folder 31 | # Add system env var with path to act.exe 32 | # Run the commands: 33 | # git pull https://github.com/username/repo 34 | # act -W .github/workflows/labels-create.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04 35 | # act -W .github/workflows/labels-create.yml -s TOKEN_CL=XXXXXXXXXX --pull=false 36 | # # 37 | 38 | name: '🎫 Labels › Create' 39 | run-name: '🎫 Labels › Create' 40 | 41 | # # 42 | # triggers 43 | # # 44 | 45 | on: 46 | workflow_dispatch: 47 | 48 | # # 49 | # environment variables 50 | # # 51 | 52 | env: 53 | ASSIGN_USER: Aetherinox 54 | BOT_NAME_1: EuropaServ 55 | BOT_NAME_2: BinaryServ 56 | BOT_NAME_DEPENDABOT: dependabot[bot] 57 | BOT_NAME_RENOVATE: renovate[bot] 58 | 59 | LABELS_JSON: | 60 | [ 61 | { "name": "AC › Changes Made", "color": "8F1784", "description": "Requested changes have been made and are pending a re-scan" }, 62 | { "name": "AC › Changes Required", "color": "8F1784", "description": "Requires changes to be made to the package before being accepted" }, 63 | { "name": "AC › Failed", "color": "a61f2d", "description": "Autocheck failed to run through a complete cycle, requires investigation" }, 64 | { "name": "AC › Needs Rebase", "color": "8F1784", "description": "Due to the permissions on the requesting repo, this pull request must be rebased by the author" }, 65 | { "name": "AC › Passed", "color": "146b4a", "description": "Ready to be reviewed" }, 66 | { "name": "AC › Review Required", "color": "8F1784", "description": "PR needs to be reviewed by another person, after the requested changes have been made" }, 67 | { "name": "AC › Security Warning", "color": "761620", "description": "Does not conform to developer policies, or includes potentially dangerous code" }, 68 | { "name": "AC › Skipped Scan", "color": "8F1784", "description": "Author has skipped code scan" }, 69 | { "name": "Status › Duplicate", "color": "75536b", "description": "Issue or pull request already exists" }, 70 | { "name": "Status › Accepted", "color": "2e7539", "description": "This pull request has been accepted" }, 71 | { "name": "Status › Autoclosed", "color": "3E0915", "description": "Originally stale and was autoclosed for no activity" }, 72 | { "name": "Status › Denied", "color": "ba4058", "description": "Pull request has been denied" }, 73 | { "name": "Status › Locked", "color": "550F45", "description": "Automatically locked by AdminServ for a prolonged period of inactivity" }, 74 | { "name": "Status › Need Info", "color": "2E3C4C", "description": "Not enough information to resolve" }, 75 | { "name": "Status › No Action", "color": "030406", "description": "Closed without any action being taken" }, 76 | { "name": "Status › Pending", "color": "984b12", "description": "Pending pull request" }, 77 | { "name": "Status › Released", "color": "1b6626", "description": "Issues or PR has been implemented and is now live" }, 78 | { "name": "Status › Reopened", "color": "8a6f14", "description": "A previously closed PR which has been re-opened" }, 79 | { "name": "Status › Review", "color": "9e1451", "description": "Currently pending review" }, 80 | { "name": "Status › Stale", "color": "928282", "description": "Has not had any activity in over 30 days" }, 81 | { "name": "Type › Bug", "color": "9a2c2c", "description": "Something isn't working" }, 82 | { "name": "Type › Dependency", "color": "243759", "description": "Item is associated to dependency" }, 83 | { "name": "Type › Lock Maintenance", "color": "FBCA04", "description": "Sync package-lock.json" }, 84 | { "name": "Type › Docs", "color": "0e588d", "description": "Improvements or modifications to docs" }, 85 | { "name": "Type › Feature", "color": "3c4e93", "description": "Feature request" }, 86 | { "name": "Type › Git Action", "color": "030406", "description": "GitHub Action / workflow" }, 87 | { "name": "Type › Pull Request", "color": "8F1784", "description": "Normal pull request" }, 88 | { "name": "Type › Roadmap", "color": "8F1784", "description": "Feature or bug currently planned for implementation" }, 89 | { "name": "Type › Internal", "color": "A51994", "description": "Assigned items are for internal developer use" }, 90 | { "name": "Build › Desktop", "color": "c7ca4a", "description": "Specific to desktop" }, 91 | { "name": "Build › Linux", "color": "c7ca4a", "description": "Specific to Linux" }, 92 | { "name": "Build › MacOS", "color": "c7ca4a", "description": "Specific to MacOS" }, 93 | { "name": "Build › Mobile", "color": "c7ca4a", "description": "Specific to mobile" }, 94 | { "name": "Build › Web", "color": "c7ca4a", "description": "Specific to web" }, 95 | { "name": "Build › Windows", "color": "c7ca4a", "description": "Specific to Windows" }, 96 | { "name": "› API", "color": "F99B50", "description": "Plugin API, CLI, browser JS API" }, 97 | { "name": "› Auto-type", "color": "9141E0", "description": "Auto-type functionality in desktop apps" }, 98 | { "name": "› Browser", "color": "9141E0", "description": "Browser plugins and passing data to <=> from app" }, 99 | { "name": "› Customization", "color": "E3F0FC", "description": "Customizations: plugins, themes, configs" }, 100 | { "name": "› Design", "color": "FA70DE", "description": "Design related queries" }, 101 | { "name": "› Dist", "color": "FA70DE", "description": "Installers and other forms of software distribution" }, 102 | { "name": "› Enterprise", "color": "11447a", "description": "Issues about collaboration, administration, and so on" }, 103 | { "name": "› Hardware", "color": "5a7503", "description": "YubiKey, other tokens, biometrics" }, 104 | { "name": "› Import/Export", "color": "F5FFCC", "description": "Import from and export to different file formats" }, 105 | { "name": "› Improvement", "color": "185c98", "description": "Enhance an existing feature" }, 106 | { "name": "› Performance", "color": "006b75", "description": "Web and desktop performance issues" }, 107 | { "name": "› Plugin Request", "color": "FCE9CA", "description": "Requested changes should be implemented as a plugin" }, 108 | { "name": "› Security", "color": "F75D39", "description": "Security issues" }, 109 | { "name": "› Self-Hosting", "color": "fad8c7", "description": "Self-hosting installations and configs" }, 110 | { "name": "› Storage", "color": "5319e7", "description": "Storage providers: Dropbox, Google, WebDAV, etc." }, 111 | { "name": "› Updater", "color": "1BADDE", "description": "Auto-updater issues" }, 112 | { "name": "› UX", "color": "1BADDE", "description": "UX and usability" }, 113 | { "name": "› Website", "color": "fef2c0", "description": "Website related issues" }, 114 | { "name": "⚠ Urgent", "color": "a8740e", "description": "Requires urgent attention" }, 115 | { "name": "⚠ Announcement", "color": "DB4712", "description": "Announcements" }, 116 | { "name": "📰 Progress Report", "color": "392297", "description": "Development updates" }, 117 | { "name": "📦 Release", "color": "277542", "description": "Release announcements" }, 118 | { "name": "✔️ Poll", "color": "972255", "description": "Community polls" }, 119 | { "name": "❔ Question", "color": "FFFFFF", "description": "All questions" } 120 | ] 121 | 122 | # # 123 | # jobs 124 | # # 125 | 126 | jobs: 127 | 128 | # # 129 | # Job [ Verify / Create Labels ] 130 | # 131 | # This job will ensure you have labels already created in your repo. 132 | # All labels come from the JSON table LABELS_JSON. 133 | # # 134 | 135 | issues-labels-create: 136 | name: >- 137 | 🎫 Labels › Create 138 | runs-on: ubuntu-latest 139 | # runs-on: apollo-x64 140 | timeout-minutes: 3 141 | permissions: 142 | contents: 'read' 143 | id-token: 'write' 144 | issues: 'write' 145 | steps: 146 | 147 | # # 148 | # Labels › Create › Checkout 149 | # # 150 | 151 | - name: '☑️ Checkout' 152 | uses: actions/checkout@v4 153 | with: 154 | fetch-depth: 0 155 | 156 | # # 157 | # Labels › Create › Job Information 158 | # # 159 | 160 | - name: >- 161 | 🔄 Load Job 162 | uses: qoomon/actions--context@v4 163 | id: 'context' 164 | 165 | # # 166 | # Labels › Create › Start 167 | # # 168 | 169 | - name: >- 170 | ✅ Start 171 | run: | 172 | echo "‎" 173 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 174 | echo " Starting Job ${{ steps.context.outputs.job_name }}" 175 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 176 | 177 | YEAR="$(date +'%Y')" 178 | echo "YEAR=${YEAR}" >> $GITHUB_ENV 179 | 180 | NOW="$(date +'%m-%d-%Y %H:%M:%S')" # 02-25-2025 12:49:48 181 | echo "NOW=${NOW}" >> $GITHUB_ENV 182 | 183 | NOW_SHORT="$(date +'%m-%d-%Y')" # 02-25-2025 184 | echo "NOW_SHORT=${NOW_SHORT}" >> $GITHUB_ENV 185 | 186 | NOW_LONG="$(date +'%m-%d-%Y %H:%M')" # 02-25-2025 12:49 187 | echo "NOW_LONG=${NOW_LONG}" >> $GITHUB_ENV 188 | 189 | NOW_DOCKER="$(date +'%Y%m%d')" # 20250225 190 | echo "NOW_DOCKER=${NOW_DOCKER}" >> $GITHUB_ENV 191 | 192 | NOW_DOCKER_TS="$(date -u +'%FT%T.%3NZ')" # 2025-02-25T12:50:11.569Z 193 | echo "NOW_DOCKER_TS=${NOW_DOCKER_TS}" >> $GITHUB_ENV 194 | 195 | SHA1="$(git rev-parse HEAD)" # 71fad013cfce9116ec62779e4a7e627fe4c33627 196 | echo "SHA1=${SHA1}" >> $GITHUB_ENV 197 | 198 | SHA1_GH="$(echo ${GITHUB_SHA})" # 71fad013cfce9116ec62779e4a7e627fe4c33627 199 | echo "SHA1_GH=${SHA1_GH}" >> $GITHUB_ENV 200 | 201 | PKG_VER_1DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1)" # 3.22 > 3 202 | echo "PKG_VER_1DIGIT=${PKG_VER_1DIGIT}" >> $GITHUB_ENV 203 | 204 | PKG_VER_2DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -f2 -d ":" | cut -c1-3)" # 3.22 > 3.2 205 | echo "PKG_VER_2DIGIT=${PKG_VER_2DIGIT}" >> $GITHUB_ENV 206 | 207 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 208 | echo "‎" 209 | echo "‎" 210 | sudo apt -qq update 211 | sudo apt -qq install tree 212 | echo "‎" 213 | echo "‎" 214 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 215 | echo "‎" 216 | echo "‎" 217 | echo " Runner .............. ${{ runner.name }}" 218 | echo " Workflow ............ ${{ github.workflow }} (#${{ github.workflow_ref }})" 219 | echo " Run Number .......... ${{ github.run_number }}" 220 | echo " Ref ................. ${{ github.ref }}" 221 | echo " Ref Name ............ ${{ github.ref_name }}" 222 | echo " Event Name .......... ${{ github.event_name }}" 223 | echo " Repo ................ ${{ github.repository }}" 224 | echo " Repo Owner .......... ${{ github.repository_owner }}" 225 | echo " Run ID .............. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" 226 | echo " Triggered By ........ ${{ github.actor }}" 227 | echo " SHA 1 (GITHUB_SHA) .. ${GITHUB_SHA}" 228 | echo " SHA 2 (github.sha) .. ${{ github.sha }}" 229 | echo " SHA 3 (env.SHA1) .... ${SHA1}" 230 | echo " SHA 4 (env.SHA1_GH) . ${SHA1_GH}" 231 | echo " Workspace ........... ${{ github.workspace }}" 232 | echo " PWD ................. ${PWD}" 233 | echo " Job Name ............ ${{ steps.context.outputs.job_name }}" 234 | echo " Job ID .............. ${{ steps.context.outputs.job_id }}" 235 | echo " Job URL ............. ${{ steps.context.outputs.job_url }}" 236 | echo " Run ID .............. ${{ steps.context.outputs.run_id }}" 237 | echo " Run Attempt ......... ${{ steps.context.outputs.run_attempt }}" 238 | echo " Run Number .......... ${{ steps.context.outputs.run_number }}" 239 | echo " Run URL ............. ${{ steps.context.outputs.run_url }}" 240 | echo " Run Env ............. ${{ steps.context.outputs.environment }}" 241 | echo " Run Env URL ......... ${{ steps.context.outputs.environment_url }}" 242 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 243 | echo " Run Deployment URL .. ${{ steps.context.outputs.deployment_url }}" 244 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 245 | echo " Run Runner Name ..... ${{ steps.context.outputs.runner_name }}" 246 | echo " Run Runner ID ....... ${{ steps.context.outputs.runner_id }}" 247 | echo " Year ................ ${YEAR}" 248 | echo " Now ................. ${NOW}" 249 | echo " Now (Short) ......... ${NOW_SHORT}" 250 | echo " Now (Long) .......... ${NOW_LONG}" 251 | echo " Now (Docker) ........ ${NOW_DOCKER}" 252 | echo " Now (Docker TS) ..... ${NOW_DOCKER_TS}" 253 | echo "‎" 254 | echo "‎" 255 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 256 | echo "‎" 257 | echo "‎" 258 | tree -I node_modules -I .git 259 | echo "‎" 260 | echo "‎" 261 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 262 | echo "‎" 263 | echo "‎" 264 | 265 | # # 266 | # Labels › Create › Verify Existing Labels 267 | # # 268 | 269 | - name: >- 270 | 🏷️ Verify Existing Labels 271 | id: task_label_verify_existing 272 | uses: actions/github-script@v7 273 | with: 274 | github-token: ${{ secrets.ADMINSERV_TOKEN_CL || github.token }} 275 | script: | 276 | const labels = JSON.parse( process.env.LABELS_JSON ); 277 | let result = Object.keys(labels).length; 278 | for ( const label of labels ) 279 | { 280 | try 281 | { 282 | await github.rest.issues.createLabel( 283 | { 284 | owner: context.repo.owner, 285 | repo: context.repo.repo, 286 | name: label.name, 287 | description: label.description || '', 288 | color: label.color 289 | }); 290 | } 291 | catch ( err ) 292 | { 293 | if ( err.status === 422 ) 294 | { 295 | console.log( `Label '${label.name}' already exists. Skipping.` ); 296 | } 297 | else 298 | { 299 | console.error( `Error creating label '${label.name}': ${err}` ); 300 | } 301 | } 302 | } 303 | 304 | console.log("[Success]: Added " + result + " labels to repo"); 305 | 306 | return result 307 | 308 | # # 309 | # Labels › Create › Get Weekly Commits 310 | # # 311 | 312 | - name: >- 313 | 🕛 Get Weekly Commit List 314 | id: task_label_set_weekly_commit_list 315 | run: | 316 | echo 'WEEKLY_COMMITS<> $GITHUB_ENV 317 | git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV 318 | echo 'EOF' >> $GITHUB_ENV 319 | 320 | -------------------------------------------------------------------------------- /.github/workflows/ping-developer.yml: -------------------------------------------------------------------------------- 1 | # # 2 | # @type github workflow 3 | # @author Aetherinox 4 | # @url https://github.com/Aetherinox 5 | # @usage pings the developer when an issue comment is made 6 | # 7 | # @secrets secrets.SELF_TOKEN self github personal access token (fine-grained) 8 | # secrets.SELF_TOKEN_CL self github personal access token (classic) 9 | # secrets.NPM_TOKEN self npmjs access token 10 | # secrets.PYPI_API_TOKEN self Pypi API token (production site) - https://pypi.org/ 11 | # secrets.PYPI_API_TEST_TOKEN self Pypi API token (test site) - https://test.pypi.org/ 12 | # secrets.SELF_DOCKERHUB_TOKEN self Dockerhub token 13 | # secrets.CODECOV_TOKEN codecov upload token for nodejs projects 14 | # secrets.MAXMIND_GELITE_TOKEN maxmind API token 15 | # secrets.CF_ACCOUNT_ID cloudflare account id 16 | # secrets.CF_ACCOUNT_TOKEN cloudflare account token 17 | # secrets.ORG_TOKEN org github personal access token (fine-grained) 18 | # secrets.ORG_TOKEN_CL org github personal access token (classic) 19 | # secrets.ORG_DOCKERHUB_TOKEN org dockerhub secret 20 | # secrets.ORG_GITEA_TOKEN org gitea personal access token (classic) with package:write permission 21 | # secrets.BOT_GPG_KEY_ASC bot gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK 22 | # secrets.BOT_GPG_KEY_B64 bot gpg private key (binary) converted to base64 23 | # secrets.BOT_GPG_PASSPHRASE bot gpg private key passphrase 24 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_RELEASES discord webhook to report release notifications from github to discord 25 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_WORKFLOWS discord webhook to report workflow notifications from github to discord 26 | # secrets.DISCORD_WEBHOOK_CHAN_GITHUB_UPDATES discord webhook to report activity notifications from github to discord 27 | # 28 | # @local these workflows can be tested locally through the use of `act` 29 | # https://github.com/nektos/act 30 | # Extract act to folder 31 | # Add system env var with path to act.exe 32 | # Run the commands: 33 | # git pull https://github.com/username/repo 34 | # act -W .github/workflows/ping-developer.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04 35 | # act -W .github/workflows/ping-developer.yml -s TOKEN_CL=XXXXXXXXXX --pull=false 36 | # # 37 | 38 | name: '💬 Ping › Developer' 39 | run-name: '💬 Ping › Developer' 40 | 41 | # # 42 | # triggers 43 | # # 44 | 45 | on: 46 | issue_comment: 47 | types: [created] 48 | 49 | # # 50 | # environment variables 51 | # # 52 | 53 | env: 54 | DEPLOYMENT_ENV: ${{ github.event.inputs.DEPLOYMENT_ENV || 'orion' }} 55 | BOT_NAME_1: EuropaServ 56 | BOT_NAME_2: BinaryServ 57 | BOT_NAME_DEPENDABOT: dependabot[bot] 58 | BOT_NAME_RENOVATE: renovate[bot] 59 | 60 | # # 61 | # jobs 62 | # 63 | # env not available for job.if 64 | # # 65 | 66 | jobs: 67 | deploy: 68 | name: >- 69 | 💬 Issue › Accept 70 | runs-on: ubuntu-latest 71 | # runs-on: apollo-x64 72 | timeout-minutes: 5 73 | if: | 74 | contains(github.event.comment.body, '/ping') 75 | steps: 76 | 77 | # # 78 | # Ping › Checkout 79 | # # 80 | 81 | - name: '☑️ Checkout' 82 | uses: actions/checkout@v4 83 | with: 84 | fetch-depth: 0 85 | 86 | # # 87 | # Ping › Job Information 88 | # # 89 | 90 | - name: >- 91 | 🔄 Load Job 92 | uses: qoomon/actions--context@v4 93 | id: 'context' 94 | 95 | # # 96 | # Ping › Start 97 | # # 98 | 99 | - name: >- 100 | ✅ Start 101 | run: | 102 | echo "‎" 103 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 104 | echo " Starting Job ${{ steps.context.outputs.job_name }}" 105 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 106 | 107 | YEAR="$(date +'%Y')" 108 | echo "YEAR=${YEAR}" >> $GITHUB_ENV 109 | 110 | NOW="$(date +'%m-%d-%Y %H:%M:%S')" # 02-25-2025 12:49:48 111 | echo "NOW=${NOW}" >> $GITHUB_ENV 112 | 113 | NOW_SHORT="$(date +'%m-%d-%Y')" # 02-25-2025 114 | echo "NOW_SHORT=${NOW_SHORT}" >> $GITHUB_ENV 115 | 116 | NOW_LONG="$(date +'%m-%d-%Y %H:%M')" # 02-25-2025 12:49 117 | echo "NOW_LONG=${NOW_LONG}" >> $GITHUB_ENV 118 | 119 | NOW_DOCKER="$(date +'%Y%m%d')" # 20250225 120 | echo "NOW_DOCKER=${NOW_DOCKER}" >> $GITHUB_ENV 121 | 122 | NOW_DOCKER_TS="$(date -u +'%FT%T.%3NZ')" # 2025-02-25T12:50:11.569Z 123 | echo "NOW_DOCKER_TS=${NOW_DOCKER_TS}" >> $GITHUB_ENV 124 | 125 | SHA1="$(git rev-parse HEAD)" # 71fad013cfce9116ec62779e4a7e627fe4c33627 126 | echo "SHA1=${SHA1}" >> $GITHUB_ENV 127 | 128 | SHA1_GH="$(echo ${GITHUB_SHA})" # 71fad013cfce9116ec62779e4a7e627fe4c33627 129 | echo "SHA1_GH=${SHA1_GH}" >> $GITHUB_ENV 130 | 131 | PKG_VER_1DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1)" # 3.22 > 3 132 | echo "PKG_VER_1DIGIT=${PKG_VER_1DIGIT}" >> $GITHUB_ENV 133 | 134 | PKG_VER_2DIGIT="$(echo ${{ env.IMAGE_VERSION }} | cut -f2 -d ":" | cut -c1-3)" # 3.22 > 3.2 135 | echo "PKG_VER_2DIGIT=${PKG_VER_2DIGIT}" >> $GITHUB_ENV 136 | 137 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 138 | echo "‎" 139 | echo "‎" 140 | sudo apt -qq update 141 | sudo apt -qq install tree 142 | echo "‎" 143 | echo "‎" 144 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 145 | echo "‎" 146 | echo "‎" 147 | echo " Runner .............. ${{ runner.name }}" 148 | echo " Workflow ............ ${{ github.workflow }} (#${{ github.workflow_ref }})" 149 | echo " Run Number .......... ${{ github.run_number }}" 150 | echo " Ref ................. ${{ github.ref }}" 151 | echo " Ref Name ............ ${{ github.ref_name }}" 152 | echo " Event Name .......... ${{ github.event_name }}" 153 | echo " Repo ................ ${{ github.repository }}" 154 | echo " Repo Owner .......... ${{ github.repository_owner }}" 155 | echo " Run ID .............. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" 156 | echo " Triggered By ........ ${{ github.actor }}" 157 | echo " SHA 1 (GITHUB_SHA) .. ${GITHUB_SHA}" 158 | echo " SHA 2 (github.sha) .. ${{ github.sha }}" 159 | echo " SHA 3 (env.SHA1) .... ${SHA1}" 160 | echo " SHA 4 (env.SHA1_GH) . ${SHA1_GH}" 161 | echo " Workspace ........... ${{ github.workspace }}" 162 | echo " PWD ................. ${PWD}" 163 | echo " Job Name ............ ${{ steps.context.outputs.job_name }}" 164 | echo " Job ID .............. ${{ steps.context.outputs.job_id }}" 165 | echo " Job URL ............. ${{ steps.context.outputs.job_url }}" 166 | echo " Run ID .............. ${{ steps.context.outputs.run_id }}" 167 | echo " Run Attempt ......... ${{ steps.context.outputs.run_attempt }}" 168 | echo " Run Number .......... ${{ steps.context.outputs.run_number }}" 169 | echo " Run URL ............. ${{ steps.context.outputs.run_url }}" 170 | echo " Run Env ............. ${{ steps.context.outputs.environment }}" 171 | echo " Run Env URL ......... ${{ steps.context.outputs.environment_url }}" 172 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 173 | echo " Run Deployment URL .. ${{ steps.context.outputs.deployment_url }}" 174 | echo " Run Deployment ...... ${{ steps.context.outputs.deployment_id }}" 175 | echo " Run Runner Name ..... ${{ steps.context.outputs.runner_name }}" 176 | echo " Run Runner ID ....... ${{ steps.context.outputs.runner_id }}" 177 | echo " Year ................ ${YEAR}" 178 | echo " Now ................. ${NOW}" 179 | echo " Now (Short) ......... ${NOW_SHORT}" 180 | echo " Now (Long) .......... ${NOW_LONG}" 181 | echo " Now (Docker) ........ ${NOW_DOCKER}" 182 | echo " Now (Docker TS) ..... ${NOW_DOCKER_TS}" 183 | echo "‎" 184 | echo "‎" 185 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 186 | echo "‎" 187 | echo "‎" 188 | tree -I node_modules -I .git 189 | echo "‎" 190 | echo "‎" 191 | echo "―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――" 192 | echo "‎" 193 | echo "‎" 194 | 195 | # # 196 | # Ping › Developer › Send Mail 197 | # 198 | # Add Label to accepted PR 199 | # 200 | # port 465 201 | # server_port: 465 202 | # secure: true 203 | # ignore_cert: false 204 | # 205 | # port 587 206 | # server_port: 587 207 | # secure: false 208 | # # 209 | 210 | - name: >- 211 | 📨 Send mail 212 | id: task_ping_developer_mail 213 | uses: dawidd6/action-send-mail@v6 214 | with: 215 | server_address: ${{ secrets.EMAIL_SMTP }} 216 | server_port: 465 217 | secure: true 218 | username: ${{ secrets.EMAIL_FROM }} 219 | password: ${{ secrets.EMAIL_KEY }} 220 | subject: "Github: Ping notification from ${{ github.repository }}" 221 | to: ${{ secrets.EMAIL_TO }} 222 | from: ${{ secrets.EMAIL_FROM }} 223 | html_body: | 224 | 225 | 226 | 227 | 228 | Title 229 | 230 | 249 | 250 | 251 | 252 |
253 |
254 |
255 | 256 |
257 |
258 | 259 |
260 |

[Github] Dear ${{github.repository_owner}},

261 |


You have received a ping notification from ${{ github.repository }} by ${{ github.event.comment.user.login }}.

262 |
263 |
264 |
265 | 266 | 267 | 268 | 270 | 271 | 272 | 273 | 275 | 276 | 277 | 278 | 280 | 281 | 282 | 283 | 285 | 286 | 287 | 288 | 290 | 291 | 292 | 293 |
Repository${{ github.repository }}
Date${{ env.NOW }}
Commenter${{ github.event.comment.user.login }}
Issue #${{ github.event.issue.number }}
ActionNotification
294 |
295 | 296 |

297 | 298 |
299 |
300 | 301 | 304 | 305 |
306 |
307 | 308 |

 

309 |


~ Github 310 |

311 |
312 | 313 |

314 | 315 |
316 | Copyright © ${{ env.YEAR }} 317 |
318 |
319 | 320 | 321 | ignore_cert: true 322 | convert_markdown: true 323 | priority: normal 324 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # # 2 | # Ignore everything 3 | # # 4 | 5 | /* 6 | 7 | # # 8 | # [WL]: Git Base Folders/Files 9 | # # 10 | 11 | !/.github 12 | !/.gitea 13 | !*README.md 14 | !*CHANGELOG.md 15 | !*CONTRIBUTE.md 16 | !*CONTRIBUTING.md 17 | 18 | # # 19 | # [WL]: Electron 20 | # # 21 | 22 | !/electron 23 | 24 | # # 25 | # [WL]: Test Folder 26 | # # 27 | 28 | !/Tests 29 | 30 | # # 31 | # [WL]: Manifest Folders 32 | # # 33 | 34 | !/Manifest 35 | 36 | # # 37 | # [WL]: Tools Folders 38 | # # 39 | 40 | !/Tools 41 | 42 | # # 43 | # [WL]: Dist 44 | # # 45 | 46 | !/dist 47 | 48 | # # 49 | # [WL]: assets 50 | # # 51 | 52 | !/assets 53 | 54 | # # 55 | # [WL]: Gitignore File 56 | # # 57 | 58 | !.gitignore 59 | 60 | # # 61 | # [WL]: Docs Folder 62 | # # 63 | 64 | !/docs 65 | 66 | # # 67 | # [WL]: Source Folder 68 | # # 69 | 70 | !/src 71 | 72 | # # 73 | # [WL]: Dist Folder 74 | # # 75 | 76 | !/dist 77 | 78 | # # 79 | # [WL]: Base Files 80 | # # 81 | 82 | !*.all-contributorsrc 83 | !*.editorconfig 84 | !*gistr.js 85 | !*manifest.json 86 | !*package.json 87 | !*package-lock.json 88 | !*rollup.config.js 89 | !*rollup.config.mjs 90 | !*tsconfig.json 91 | !*versions.json 92 | !sign.bat 93 | !*SHA*.asc 94 | !*SHA*.sig 95 | !*styles.css 96 | !*eslint.config.js 97 | !*.prettierignore 98 | !*.prettierrc 99 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .all-contributorsrc 2 | .github 3 | .gitea 4 | CONTRIBUTING 5 | CONTRIBUTING.md 6 | README 7 | README.md 8 | LICENSE 9 | node_modules 10 | coverage 11 | dist 12 | tests 13 | docs 14 | manifest.json 15 | tsconfig.json 16 | styles.css 17 | rollup.config.mjs 18 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | # 2 | # Try prettier's new ternary formatting before it becomes the 3 | # default behavior. 4 | # 5 | # only in prettier v3.x 6 | # 7 | # Moves the ? in multiline ternaries to the end of the first line 8 | # instead of the start of the second, along with several related 9 | # changes. 10 | # 11 | # @default : false 12 | # @ref : https://prettier.io/docs/en/options.html 13 | # https://prettier.io/docs/en/options.html#experimental-ternaries 14 | # https://github.com/prettier/prettier/pull/13183 15 | # # 16 | 17 | # experimentalTernaries: false 18 | 19 | # # 20 | # Specify the line length that the printer will wrap on. 21 | # 22 | # @default : 80 23 | # @ref : https://prettier.io/docs/en/options.html#print-width 24 | # # 25 | 26 | printWidth: 120 27 | 28 | # # 29 | # Specify the number of spaces per indentation-level. 30 | # 31 | # @default : 2 32 | # @ref : https://prettier.io/docs/en/options.html#tab-width 33 | # # 34 | 35 | tabWidth: 4 36 | 37 | # # 38 | # Indent lines with tabs instead of spaces. 39 | # 40 | # @default : false 41 | # @ref : https://prettier.io/docs/en/options.html#tabs 42 | # # 43 | 44 | useTabs: false 45 | 46 | # # 47 | # Print semicolons at the ends of statements. 48 | # 49 | # true : Add a semicolon at the end of every statement. 50 | # false : Only add semicolons at the beginning of lines that 51 | # may introduce ASI failures. 52 | # 53 | # @default : true 54 | # @ref : https://prettier.io/docs/en/options.html#semicolons 55 | # # 56 | 57 | semi: false 58 | 59 | # # 60 | # Use single quotes instead of double quotes. 61 | # 62 | # @default : false 63 | # @ref : https://prettier.io/docs/en/options.html#quotes 64 | # # 65 | 66 | singleQuote: true 67 | 68 | # # 69 | # Change when properties in objects are quoted. 70 | # 71 | # "as-needed" : Only add quotes around object properties where required. 72 | # "consistent" : If at least one property in an object requires quotes, quote all properties. 73 | # "preserve" : Respect the input use of quotes in object properties. 74 | # 75 | # 76 | # @default : "as-needed" 77 | # @ref : https://prettier.io/docs/en/options.html#quote-props 78 | # # 79 | 80 | quoteProps: 'preserve' 81 | 82 | # # 83 | # Use single quotes instead of double quotes in JSX. 84 | # 85 | # @default : false 86 | # @ref : https://prettier.io/docs/en/options.html#jsx-quotes 87 | # # 88 | 89 | jsxSingleQuote: true 90 | 91 | # # 92 | # Print trailing commas wherever possible in multi-line comma-separated 93 | # syntactic structures. 94 | # 95 | # (A single-line array, for example, never gets trailing commas.) 96 | # 97 | # Default value changed from es5 to all in v3.0.0 98 | # 99 | # "all" : Trailing commas wherever possible (including 100 | # function parameters and calls). To run, JavaScript 101 | # code formatted this way needs an engine that 102 | # supports ES2017 (Node.js 8+ or a modern browser) 103 | # or downlevel compilation. This also enables 104 | # trailing commas in type parameters in TypeScript 105 | # (supported since TypeScript 2.7 released in January 2018). 106 | # 107 | # "es5" : Trailing commas where valid in ES5 (objects, arrays, etc.). 108 | # 109 | # Trailing commas in type parameters in TypeScript and Flow. 110 | # "none" : No trailing commas. 111 | # 112 | # 113 | # @default : "all" 114 | # @ref : https://prettier.io/docs/en/options.html#trailing-commas 115 | # # 116 | 117 | trailingComma: none 118 | 119 | # # 120 | # Print spaces between brackets in object literals. 121 | # 122 | # true : Example: { foo: bar }. 123 | # false : Example: {foo: bar}. 124 | # 125 | # @default : true 126 | # @ref : https://prettier.io/docs/en/options.html#bracket-spacing 127 | # # 128 | 129 | bracketSpacing: true 130 | 131 | # # 132 | # Put the > of a multi-line HTML (HTML, JSX, Vue, Angular) element at the end of the 133 | # last line instead of being alone on the next line (does not apply to self closing 134 | # elements). 135 | # 136 | # true : Example: 137 | # 138 | # 144 | # 145 | # false : Example: 146 | # 147 | # 154 | # 155 | # @default : false 156 | # @ref : https://prettier.io/docs/en/options.html#bracket-line 157 | # # 158 | 159 | bracketSameLine: false 160 | 161 | # # 162 | # Include parentheses around a sole arrow function parameter. 163 | # 164 | # First available in v1.9.0, default value changed from avoid to always in v2.0.0 165 | # 166 | # "always" : Always include parens. Example: (x) => x 167 | # "avoid" : Omit parens when possible. Example: x => x 168 | # 169 | # 170 | # @default : "always" 171 | # @ref : https://prettier.io/docs/en/options.html#arrow-function-parentheses 172 | # # 173 | 174 | arrowParens: always 175 | 176 | # # 177 | # By default, Prettier will not change wrapping in markdown text since some services 178 | # use a linebreak-sensitive renderer, e.g. GitHub comments and BitBucket. To have 179 | # Prettier wrap prose to the print width, change this option to "always". If you want 180 | # Prettier to force all prose blocks to be on a single line and rely on editor/viewer 181 | # soft wrapping instead, you can use "never". 182 | # 183 | # First available in v1.8.2 184 | # 185 | # "always" : Wrap prose if it exceeds the print width. 186 | # "never" : Un-wrap each block of prose into one line. 187 | # "preserve" : Do nothing, leave prose as-is. First available in v1.9.0 188 | # 189 | # 190 | # @default : "preserve" 191 | # @ref : https://prettier.io/docs/en/options.html#prose-wrap 192 | # # 193 | 194 | proseWrap: 'preserve' 195 | 196 | # # 197 | # Specify the global whitespace sensitivity for HTML, Vue, Angular, and Handlebars. 198 | # See whitespace-sensitive formatting for more info. 199 | # 200 | # First available in v1.15.0. First available for Handlebars in 2.3.0 201 | # 202 | # "css" : Respect the default value of CSS display property. 203 | # For Handlebars treated same as strict. 204 | # "strict" : Whitespace (or the lack of it) around all tags is considered significant. 205 | # "ignore" : Whitespace (or the lack of it) around all tags is considered insignificant. 206 | # 207 | # 208 | # @default : "css" 209 | # @ref : https://prettier.io/docs/en/options.html#html-whitespace-sensitivity 210 | # https://prettier.io/blog/2018/11/07/1.15.0.html#whitespace-sensitive-formatting 211 | # # 212 | 213 | htmlWhitespaceSensitivity: 'ignore' 214 | 215 | # # 216 | # For historical reasons, there exist two common flavors of line endings in text 217 | # files. That is: 218 | # - \n (or LF for Line Feed) 219 | # - \r\n (or CRLF for Carriage Return + Line Feed). 220 | # 221 | # The former is common on Linux and macOS, while the latter is prevalent on Windows. 222 | # Some details explaining why it is so can be found on Wikipedia. 223 | # 224 | # When people collaborate on a project from different operating systems, it becomes 225 | # easy to end up with mixed line endings in a shared git repository. It is also possible 226 | # for Windows users to accidentally change line endings in a previously committed file 227 | # from LF to CRLF. Doing so produces a large git diff and thus makes the line-by-line 228 | # history for a file (git blame) harder to explore. 229 | # 230 | # All modern text editors in all operating systems are able to correctly display line 231 | # endings when \n (LF) is used. However, old versions of Notepad for Windows will visually 232 | # squash such lines into one as they can only deal with \r\n (CRLF). 233 | # 234 | # First available in v1.15.0, default value changed from auto to lf in v2.0.0 235 | # 236 | # "lf" : Line Feed only (\n), common on Linux and macOS as well as inside git repos 237 | # "crlf" : Carriage Return + Line Feed characters (\r\n), common on Windows 238 | # "cr" : Carriage Return character only (\r), used very rarely 239 | # "auto" : Maintain existing line endings (mixed values within one file are normalised 240 | # by looking at what’s used after the first line) 241 | # 242 | # @default : "lf" 243 | # @ref : https://prettier.io/docs/en/options.html#end-of-line 244 | # # 245 | 246 | endOfLine: 'auto' 247 | 248 | # # 249 | # Control whether Prettier formats quoted code embedded in the file. 250 | # 251 | # When Prettier identifies cases where it looks like you've placed some code it knows 252 | # how to format within a string in another file, like in a tagged template in 253 | # JavaScript with a tag named html or in code blocks in Markdown, it will by default try 254 | # to format that code. 255 | # 256 | # Sometimes this behavior is undesirable, particularly in cases where you might not have 257 | # intended the string to be interpreted as code. This option allows you to switch between 258 | # the default behavior (auto) and disabling this feature entirely (off). 259 | # 260 | # First available in v2.1.0 261 | # 262 | # "auto" : Format embedded code if Prettier can automatically identify it. 263 | # "off" : Never automatically format embedded code. 264 | # 265 | # @default : "auto" 266 | # @ref : https://prettier.io/docs/en/options.html#embedded-language-formatting 267 | # # 268 | 269 | embeddedLanguageFormatting: 'auto' 270 | 271 | # # 272 | # Enforce single attribute per line in HTML, Vue and JSX. 273 | # 274 | # true : Enforce single attribute per line. 275 | # false : Do not enforce single attribute per line. 276 | # 277 | # @default : false 278 | # @ref : https://prettier.io/docs/en/options.html#single-attribute-per-line 279 | # # 280 | 281 | singleAttributePerLine: false 282 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Aetherinox 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
Dataview Snippets
3 |

⭕ Obsidian Snippet Collection ⭕

4 | 5 |
6 | 7 |

A collection of dataview scripts which can be utilized within your Obsidian.md notes to perform various tasks and display data.

8 | 9 |
10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 | [![Version][github-version-img]][github-version-uri] 18 | [![Build Status][github-build-img]][github-build-uri] 19 | [![Downloads][github-downloads-img]][github-downloads-uri] 20 | [![Size][github-size-img]][github-size-img] 21 | [![Last Commit][github-commit-img]][github-commit-img] 22 | [![Contributors][contribs-all-img]](#contributors-) 23 | 24 | 25 |
26 | 27 |
28 | 29 | --- 30 | 31 |
32 | 33 | - [About](#about) 34 | - [Snippets](#snippets) 35 | - [Table of Contents: Version 1](#table-of-contents-version-1) 36 | - [Table of Contents: Version 2](#table-of-contents-version-2) 37 | - [Subfolder Data](#subfolder-data) 38 | - [Bad Links: Version 1](#bad-links-version-1) 39 | - [Tag Cloud: Version 1](#tag-cloud-version-1) 40 | - [Tag Cloud: Version 2](#tag-cloud-version-2) 41 | - [Page Cloud: Version 1](#page-cloud-version-1) 42 | - [Alphabetized List: Version 1](#alphabetized-list-version-1) 43 | - [Contributors ✨](#contributors-) 44 | 45 |
46 | 47 | --- 48 | 49 |
50 | 51 | ## About 52 | This repo originally started a single **Table of Contents** script which displays at the top of your obsidian note. However, numerous other scripts have been added since then. 53 | 54 | The snippets in this repo require you to download and install the following: 55 | - [Obsidian.md](obsidian.md/) 56 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 57 | 58 |
59 | 60 | --- 61 | 62 |
63 | 64 | ## Snippets 65 | The following snippets are available in this repo 66 | 67 |
68 | 69 | ### Table of Contents: Version 1 70 | 71 |

72 | 73 | The `Table of Contents: Version 1` snippet displays a table of contents. It compiles a list of all your folder's current subpages and pulls the headers from each page to display in a simple and neat list. 74 | 75 |
76 | 77 | For this version, you will need to create a new **Folder Note** using the [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes), and then paste the provided code at the top of the new folder note. 78 | 79 |
80 | 81 | This version requires you to install the following: 82 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 83 | - [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) 84 | 85 |
86 | 87 |
88 | 89 | [![View](https://img.shields.io/badge/%20-%20View%20Readme-%20%23de2343?style=for-the-badge&logo=github&logoColor=FFFFFF)](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/TOC%20Version%201) 90 | 91 |
92 | 93 |

94 | 95 | --- 96 | 97 |

98 | 99 | ### Table of Contents: Version 2 100 | 101 |

102 | 103 | The `Table of Contents: Version 2` snippet displays a table of contents. It compiles a list of all your folder's current subpages and pulls the headers from each page to display in a simple and neat list. 104 | 105 |
106 | 107 | To use this snippet, paste the provided table of contents code at the top of a regular Obsidian note. It will fetch all of the headers which exist on that same page and display them in an unordered list at the top. 108 | 109 |
110 | 111 | This version requires you to install the following: 112 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 113 | 114 |
115 | 116 |
117 | 118 | [![View](https://img.shields.io/badge/%20-%20View%20Readme-%20%23de2343?style=for-the-badge&logo=github&logoColor=FFFFFF)](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/TOC%20Version%202) 119 | 120 |
121 | 122 |

123 | 124 | --- 125 | 126 |

127 | 128 | ### Subfolder Data 129 | 130 |

131 | 132 | The `Subfolder Data` snippet displays a table of contents listing based on a specified subfolder. This is useful if you want to pull a list of headers which exist on a page that is not associated to the current folder you are working in. 133 | 134 | The other snippets above also support subpages, but this one is a bit more customized for subfolder management. 135 | 136 |
137 | 138 | This version **requires** you to install the following: 139 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 140 | 141 | The following plugins are **optional**: 142 | - [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) 143 | 144 |
145 | 146 |
147 | 148 | [![View](https://img.shields.io/badge/%20-%20View%20Readme-%20%23de2343?style=for-the-badge&logo=github&logoColor=FFFFFF)](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Subfolder%20Data) 149 | 150 |
151 | 152 |

153 | 154 | --- 155 | 156 |

157 | 158 | ### Bad Links: Version 1 159 | 160 |

161 | 162 | The `Bad Links: Version 1` snippet displays a list of internal links within your vault that lead nowhere (are broken). 163 | 164 | To fix these, you can delete the link on the associated page, or you can click each item in the list and create a new page. Once the link has been fixed, it will be removed from the list. 165 | 166 |
167 | 168 | This version **requires** you to install the following: 169 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 170 | 171 |
172 | 173 |
174 | 175 | [![View](https://img.shields.io/badge/%20-%20View%20Readme-%20%23de2343?style=for-the-badge&logo=github&logoColor=FFFFFF)](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Bad%20Links%201) 176 | 177 |
178 | 179 |

180 | 181 | --- 182 | 183 |

184 | 185 | ### Tag Cloud: Version 1 186 | 187 |

188 | 189 | The `Tag Cloud: Version 1` snippet fetches a list of tags associated to your vault and displays them in a series of columns. 190 | 191 | Each tag can be clicked on, which will open the Search interface and display all other pages associated to the selected tag. 192 | 193 | The functionality of `Version 1` and `Version 2` are the same. Both just have difference appearances. 194 | 195 | 196 |
197 | 198 | This version **requires** you to install the following: 199 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 200 | 201 |
202 | 203 |
204 | 205 | [![View](https://img.shields.io/badge/%20-%20View%20Readme-%20%23de2343?style=for-the-badge&logo=github&logoColor=FFFFFF)](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Tag%20Cloud%201) 206 | 207 |
208 | 209 |

210 | 211 | --- 212 | 213 |

214 | 215 | ### Tag Cloud: Version 2 216 | 217 |

218 | 219 | The `Tag Cloud: Version 2` snippet fetches a list of tags associated to your vault and displays them in a series of columns. 220 | 221 | Each tag can be clicked on, which will open the Search interface and display all other pages associated to the selected tag. 222 | 223 | The functionality of `Version 1` and `Version 2` are the same. Both just have difference appearances. 224 | 225 |
226 | 227 | This version **requires** you to install the following: 228 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 229 | 230 |
231 | 232 |
233 | 234 | [![View](https://img.shields.io/badge/%20-%20View%20Readme-%20%23de2343?style=for-the-badge&logo=github&logoColor=FFFFFF)](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Tag%20Cloud%202) 235 | 236 |
237 | 238 |

239 | 240 | --- 241 | 242 |

243 | 244 | ### Page Cloud: Version 1 245 | 246 |

247 | 248 | The `Page Cloud: Version 1` snippet fetches a list of pages within your vault and displays them in a cloud structure. 249 | 250 | Each page can be clicked on which will re-direct you to that particular page. Page titles also support the frontmatter values: 251 | - name 252 | - title 253 | - alias 254 | 255 | The functionality of `Version 1` and `Version 2` are the same. Both just have difference appearances. 256 | 257 |
258 | 259 | This version **requires** you to install the following: 260 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 261 | 262 |
263 | 264 |
265 | 266 | [![View](https://img.shields.io/badge/%20-%20View%20Readme-%20%23de2343?style=for-the-badge&logo=github&logoColor=FFFFFF)](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Page%20Cloud%201) 267 | 268 |
269 | 270 |

271 | 272 | --- 273 | 274 |

275 | 276 | ### Alphabetized List: Version 1 277 | 278 |

279 | 280 | The `Alphabetized List: Version 1` snippet fetches a list of pages within your vault and displays them in a alphabetized list. 281 | 282 | Each page can be clicked on which will re-direct you to that particular page. Page titles also support the frontmatter values: 283 | - name 284 | - title 285 | - alias 286 | 287 |
288 | 289 | This version **requires** you to install the following: 290 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 291 | 292 |
293 | 294 |
295 | 296 | [![View](https://img.shields.io/badge/%20-%20View%20Readme-%20%23de2343?style=for-the-badge&logo=github&logoColor=FFFFFF)](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/Alphabetized%20List%201) 297 | 298 |
299 | 300 |
301 | 302 | --- 303 | 304 |
305 | 306 | ## Contributors ✨ 307 | We are always looking for contributors. If you feel that you can provide something useful to Gistr, then we'd love to review your suggestion. Before submitting your contribution, please review the following resources: 308 | 309 | - [Pull Request Procedure](.github/PULL_REQUEST_TEMPLATE.md) 310 | - [Contributor Policy](CONTRIBUTING.md) 311 | 312 |
313 | 314 | Want to help but can't write code? 315 | - Review [active questions by our community](https://github.com/Aetherinox/obsidian-dataview-snippets/labels/help%20wanted) and answer the ones you know. 316 | 317 |
318 | 319 | The following people have helped get this project going: 320 | 321 |
322 | 323 |
324 | 325 | 326 | [![Contributors][contribs-all-img]](#contributors-) 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 |
Aetherinox
Aetherinox

💻 📆 🔍
339 |
340 | 341 | 342 | 343 | 344 |
345 |
346 | 347 | 348 | 349 | 350 | 351 | [general-npmjs-uri]: https://npmjs.com 352 | [general-nodejs-uri]: https://nodejs.org 353 | [general-npmtrends-uri]: http://npmtrends.com/obsidian-dataview-snippets 354 | 355 | 356 | [github-version-img]: https://img.shields.io/github/v/tag/Aetherinox/obsidian-dataview-snippets?logo=GitHub&label=Version&color=ba5225 357 | [github-version-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases 358 | 359 | 360 | [npm-version-img]: https://img.shields.io/npm/v/obsidian-dataview-snippets?logo=npm&label=Version&color=ba5225 361 | [npm-version-uri]: https://npmjs.com/package/obsidian-dataview-snippets 362 | 363 | 364 | [pypi-version-img]: https://img.shields.io/pypi/v/obsidian-dataview-snippets-plugin 365 | [pypi-version-uri]: https://pypi.org/project/obsidian-dataview-snippets-plugin/ 366 | 367 | 368 | [license-mit-img]: https://img.shields.io/badge/MIT-FFF?logo=creativecommons&logoColor=FFFFFF&label=License&color=9d29a0 369 | [license-mit-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/blob/main/LICENSE 370 | 371 | 372 | [github-downloads-img]: https://img.shields.io/github/downloads/Aetherinox/obsidian-dataview-snippets/total?logo=github&logoColor=FFFFFF&label=Downloads&color=376892 373 | [github-downloads-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases 374 | 375 | 376 | [npmjs-downloads-img]: https://img.shields.io/npm/dw/%40aetherinox%2Fmkdocs-link-embeds?logo=npm&&label=Downloads&color=376892 377 | [npmjs-downloads-uri]: https://npmjs.com/package/obsidian-dataview-snippets 378 | 379 | 380 | [github-size-img]: https://img.shields.io/github/repo-size/Aetherinox/obsidian-dataview-snippets?logo=github&label=Size&color=59702a 381 | [github-size-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/releases 382 | 383 | 384 | [npmjs-size-img]: https://img.shields.io/npm/unpacked-size/obsidian-dataview-snippets/latest?logo=npm&label=Size&color=59702a 385 | [npmjs-size-uri]: https://npmjs.com/package/obsidian-dataview-snippets 386 | 387 | 388 | [codecov-coverage-img]: https://img.shields.io/codecov/c/github/Aetherinox/obsidian-dataview-snippets?token=MPAVASGIOG&logo=codecov&logoColor=FFFFFF&label=Coverage&color=354b9e 389 | [codecov-coverage-uri]: https://codecov.io/github/Aetherinox/obsidian-dataview-snippets 390 | 391 | 392 | [contribs-all-img]: https://img.shields.io/github/all-contributors/Aetherinox/obsidian-dataview-snippets?logo=contributorcovenant&color=de1f6f&label=contributors 393 | [contribs-all-uri]: https://github.com/all-contributors/all-contributors 394 | 395 | 396 | [github-build-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/release.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30 397 | [github-build-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/release.yml 398 | 399 | 400 | [github-build-pypi-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/release-pypi.yml?logo=github&logoColor=FFFFFF&label=Build&color=%23278b30 401 | [github-build-pypi-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/pypi-release.yml 402 | 403 | 404 | [github-tests-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/obsidian-dataview-snippets/npm-tests.yml?logo=github&label=Tests&color=2c6488 405 | [github-tests-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/actions/workflows/npm-tests.yml 406 | 407 | 408 | [github-commit-img]: https://img.shields.io/github/last-commit/Aetherinox/obsidian-dataview-snippets?logo=conventionalcommits&logoColor=FFFFFF&label=Last%20Commit&color=313131 409 | [github-commit-uri]: https://github.com/Aetherinox/obsidian-dataview-snippets/commits/main/ 410 | 411 | 412 | 413 | -------------------------------------------------------------------------------- /Snippets/Alphabetized List 1/images/example_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Alphabetized List 1/images/example_1.gif -------------------------------------------------------------------------------- /Snippets/Alphabetized List 1/images/example_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Alphabetized List 1/images/example_2.gif -------------------------------------------------------------------------------- /Snippets/Alphabetized List 1/images/example_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Alphabetized List 1/images/example_3.gif -------------------------------------------------------------------------------- /Snippets/Alphabetized List 1/images/example_4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Alphabetized List 1/images/example_4.gif -------------------------------------------------------------------------------- /Snippets/Alphabetized List 1/images/example_5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Alphabetized List 1/images/example_5.gif -------------------------------------------------------------------------------- /Snippets/Alphabetized List 1/images/install_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Alphabetized List 1/images/install_1.gif -------------------------------------------------------------------------------- /Snippets/Alphabetized List 1/images/install_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Alphabetized List 1/images/install_2.png -------------------------------------------------------------------------------- /Snippets/Alphabetized List 1/images/install_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Alphabetized List 1/images/install_3.gif -------------------------------------------------------------------------------- /Snippets/Alphabetized List 2/code.txt: -------------------------------------------------------------------------------- 1 | dv.container.className += ' atx-alv1-dataview' 2 | 3 | var html = ""; 4 | let arrAlphabet = []; 5 | let arrPages = dv.pages( "" ) 6 | .forEach( p => 7 | { 8 | const file = p.file 9 | const file_path = file.path; 10 | const file_name = file.name; 11 | const file_label = file.frontmatter.name || file.frontmatter.title || file.frontmatter.alias || file_name; 12 | 13 | const letter = file_label.charAt( 0 ).toUpperCase( ); 14 | let index = arrAlphabet.findIndex( ( item ) => item.name === letter ); 15 | 16 | if ( index === -1 ) 17 | arrAlphabet.push( { name: letter, pages: [ { name: file_name, label: file_label, path: file_path } ] } ); 18 | else 19 | { 20 | var item = arrAlphabet.find( item => item.name == letter ); 21 | let arr = item.pages; 22 | 23 | arr.push( { name: file_name, label: file_label, path: file_path } ); 24 | } 25 | 26 | arrAlphabet.sort( ( a, b ) => a.name.localeCompare( b.name ) ) 27 | }); 28 | 29 | const ulAlphabet = dv.el( 'ul', '', { container: dv.container } ); 30 | 31 | dv.list( 32 | dv.array( arrAlphabet ) 33 | .forEach( obj => 34 | { 35 | const arrPages = obj.pages; 36 | const liAlphabet = dv.el( 'li', obj.name, { container: ulAlphabet } ); 37 | const ulPages = dv.el( 'ul', '', { container: liAlphabet }); 38 | 39 | Promise.all( arrPages.map( async ( pages ) => 40 | { 41 | const page_path = pages.path; 42 | const page_name = pages.name; 43 | const page_label = pages.label; 44 | 45 | const file_link = dv.fileLink( page_path, false, page_label ); 46 | 47 | dv.el( 'li', file_link, { container: ulPages } ); 48 | 49 | } 50 | )); 51 | }) 52 | ) 53 | 54 | const divClose = dv.el( 'div', html, { container: dv.container, cls: 'atx-alv1-close' } ); -------------------------------------------------------------------------------- /Snippets/Bad Links 1/images/example_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Bad Links 1/images/example_1.png -------------------------------------------------------------------------------- /Snippets/Bad Links 1/images/example_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Bad Links 1/images/example_2.gif -------------------------------------------------------------------------------- /Snippets/Bad Links 1/images/example_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Bad Links 1/images/example_3.gif -------------------------------------------------------------------------------- /Snippets/Bad Links 1/images/example_4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Bad Links 1/images/example_4.gif -------------------------------------------------------------------------------- /Snippets/Bad Links 1/images/example_5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Bad Links 1/images/example_5.gif -------------------------------------------------------------------------------- /Snippets/Bad Links 1/images/install_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Bad Links 1/images/install_1.gif -------------------------------------------------------------------------------- /Snippets/Bad Links 1/images/install_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Bad Links 1/images/install_2.png -------------------------------------------------------------------------------- /Snippets/Bad Links 1/images/install_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Bad Links 1/images/install_3.gif -------------------------------------------------------------------------------- /Snippets/Page Cloud 1/images/example_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Page Cloud 1/images/example_1.gif -------------------------------------------------------------------------------- /Snippets/Page Cloud 1/images/install_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Page Cloud 1/images/install_1.gif -------------------------------------------------------------------------------- /Snippets/Page Cloud 1/images/install_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Page Cloud 1/images/install_2.png -------------------------------------------------------------------------------- /Snippets/Page Cloud 1/images/install_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Page Cloud 1/images/install_3.gif -------------------------------------------------------------------------------- /Snippets/Page Cloud 1/images/install_4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Page Cloud 1/images/install_4.gif -------------------------------------------------------------------------------- /Snippets/Subfolder Data/README.md: -------------------------------------------------------------------------------- 1 | # Obsidian: Subfolder Data 2 | This snippet requires a copy of [Obsidian.md](obsidian.md/) 3 |
4 | This snippet requires the [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview). 5 | 6 |

7 | 8 | ## About 9 | The `Subfolder Data` snippet displays a table of contents listing based on a specified subfolder. This is useful if you want to pull a list of headers which exist on a page that is not associated to the current folder you are working in. 10 | 11 |
12 | 13 | At the time of writing this script, I am using the following: 14 | 15 | | Software | Version | 16 | | --- | --- | 17 | | [Obsidian.md](https://obsidian.md/) | ![GitHub release](https://img.shields.io/github/v/release/obsidianmd/obsidian-releases?label=v&color=ba0f56) | 18 | | [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) | ![GitHub release](https://img.shields.io/github/v/release/blacksmithgu/obsidian-dataview?label=v&color=ba0f56) | 19 | | [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) | ![GitHub release](https://img.shields.io/github/v/release/LostPaul/obsidian-folder-notes?label=v&color=ba0f56) | 20 | 21 |
22 | 23 | ### Previews 24 | The following are preview images of what the snippet will do and appear like: 25 | 26 |
27 | 28 |

29 | 30 |
31 | 32 |

33 | 34 | --- 35 | 36 |

37 | 38 | ## Usage 39 | 40 | - Install [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 41 | - Install [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) *(if wanting to use notes*) 42 | - Copy the code below and paste it in a note. 43 | 44 |
45 | 46 | ````shell 47 | ```dataviewjs 48 | /* 49 | Table of Contents Script > Version 3 50 | 51 | This version allows for pulling subfolder notes to 52 | another table of contents page. 53 | 54 | Excludes any subfolder table of contents pages 55 | labeled FOLDERNAME/FOLDERNAME.md 56 | 57 | Change "General" to the subpage you are wanting to target 58 | */ 59 | 60 | const path_sub = "General" 61 | 62 | let count = 0; 63 | const path_base = dv.current().file.path 64 | const path_targ = path_base.substr(0, path_base.lastIndexOf("/")); 65 | const path_fnote_excl = path_sub + ".md" 66 | const filter_page = '"' + path_targ + "/" + path_sub + '"'; 67 | const filter_folder = path_targ + "/" + path_sub; 68 | 69 | let p = dv.pages(filter_page) 70 | .where(p => p.file.name != dv.current().file.name) // Filter out the current page 71 | .where(p => p.file.folder == filter_folder) // Filter out folders 72 | .where(p => !p.file.path.endsWith(path_fnote_excl) ) // Filter folder note index 73 | .sort(p => p.file.path) 74 | .forEach(p => 75 | { 76 | dv.header(4, p.file.name); // display page name as header 77 | const cache = this.app.metadataCache.getCache(p.file.path); 78 | 79 | if (cache) 80 | { 81 | const headings = cache.headings; // get headings from cache 82 | 83 | if (headings) 84 | { 85 | const houtput = headings.slice(1) // exclude the first heading 86 | .filter(h => h.level <= 6) 87 | .map(h => 88 | { 89 | var file_head = h.heading 90 | var header_skip = file_head.replace(/ /g,"_").toLowerCase(); 91 | if (header_skip === "table_of_contents" || header_skip === "toc") 92 | { 93 | return "" 94 | } 95 | 96 | count++; 97 | 98 | // Determine indentation based on heading level 99 | let indent = " ".repeat(h.level); 100 | var file_name = p.file.name; 101 | 102 | // remove backticks and tag symbols 103 | var file_head = file_head.replace(/`/g, ''); 104 | var file_head = file_head.replace(/#/g, ''); 105 | var file_title = h.heading.split('#')[0]; 106 | 107 | let objLink = "[[" + file_name + "#" + file_head + "|" + file_title + "]]"; 108 | 109 | if ( h.level == 1 ) 110 | return indent + "- " + objLink + ""; 111 | else if ( h.level == 2 ) 112 | return indent + " - " + objLink + ""; 113 | else if ( h.level == 3 ) 114 | return indent + " - " + objLink + ""; 115 | else if ( h.level == 4 ) 116 | return indent + " - " + objLink + ""; 117 | else if ( h.level == 5 ) 118 | return indent + " - " + objLink + ""; 119 | else if ( h.level == 6 ) 120 | return indent + " - " + objLink + ""; 121 | else 122 | return indent + "- " + objLink; 123 | }) 124 | .join("\n") 125 | 126 | dv.el("div", houtput); 127 | dv.el("div", "
"); 128 | } 129 | } 130 | }); 131 | 132 | /* 133 | display NO RESULTS 134 | */ 135 | 136 | if (count === 0) 137 | { 138 | const rootNode = dv.el("div", "No results", { cls: "toc_results_none" }); 139 | rootNode.setAttribute("style", "text-align:center;"); 140 | } 141 | ``` 142 | ```` 143 | 144 |
145 | 146 | Ensure you change the path to the **subfolder** you want to target: 147 | 148 | ```javascript 149 | const path_sub = "General" 150 | ``` 151 | 152 |
153 | 154 | In the screenshot example, I changed it `Plugins` because the Plugins folder is a subfolder of what I wanted to target and build a table of contents from. You can use an entirely different path to whatever folder you want to generate a list of headers from. 155 | 156 | ```javascript 157 | const path_sub = "Plugins" 158 | ``` 159 | 160 |
161 | 162 | Next, you need to add some custom CSS. 163 | Open Obsidian Settings, click **Appearance**, and then scroll all the way down. (See image below). 164 | 165 | Click the mini folder icon to open your **Obsidian Snippets folder**. 166 | 167 |
168 | 169 |

170 | 171 |
172 | 173 | Create a new file named whatever (`toc.css` in our example). 174 | 175 | Copy the code below and paste it into the new `toc.css` file which should be in `YourVaultName/.obsidian/snippets/toc.css` 176 | 177 |
178 | 179 |

180 | 181 |
182 | 183 | ```css 184 | /* 185 | Snippet: Table of Contents 186 | */ 187 | 188 | /* 189 | toc > header 2 190 | */ 191 | 192 | .toc_h2 a 193 | { 194 | color: #7fa8f5 !important; 195 | font-size: 10pt; 196 | font-weight: lighter; 197 | line-height: 20px; 198 | } 199 | 200 | /* 201 | toc > header 3 202 | */ 203 | 204 | .toc_h3 a 205 | { 206 | color: #f85289 !important; 207 | font-size: 9pt; 208 | font-weight: lighter; 209 | line-height: 20px; 210 | } 211 | 212 | /* 213 | toc > header 4, 5, 6 214 | */ 215 | 216 | .toc_h4 a, .toc_h5 a, .toc_h6 a 217 | { 218 | color: #969696 !important; 219 | font-size: 8pt; 220 | font-weight: normal; 221 | line-height: 20px; 222 | } 223 | 224 | /* 225 | toc > bad links > path 226 | */ 227 | 228 | .toc_badpaths_path, .toc_badpaths_path a 229 | { 230 | color: #adadad !important; 231 | font-size: 8pt; 232 | font-weight: normal; 233 | line-height: 20px; 234 | } 235 | 236 | /* 237 | toc > no results 238 | */ 239 | 240 | .toc_results_none 241 | { 242 | text-align: center; 243 | font-size: 12pt; 244 | } 245 | ``` 246 | 247 |
248 | 249 | Save the file and go back to **Obsidian Settings** -> **Appearance**. Scroll all the way down and enable the checkbox to the right of `toc.css`. 250 | 251 |

252 | 253 |
254 | 255 | You should see a table of contents which is populated with the headings of your subfolders. -------------------------------------------------------------------------------- /Snippets/Subfolder Data/images/example_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Subfolder Data/images/example_1.gif -------------------------------------------------------------------------------- /Snippets/Subfolder Data/images/install_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Subfolder Data/images/install_1.gif -------------------------------------------------------------------------------- /Snippets/Subfolder Data/images/install_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Subfolder Data/images/install_2.png -------------------------------------------------------------------------------- /Snippets/Subfolder Data/images/install_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Subfolder Data/images/install_3.gif -------------------------------------------------------------------------------- /Snippets/Subfolder Data/snippet-version3: -------------------------------------------------------------------------------- 1 | ```dataviewjs 2 | /* 3 | Table of Contents Script > Version 3 4 | 5 | This version allows for pulling subfolder notes to 6 | another table of contents page. 7 | 8 | Excludes any subfolder table of contents pages 9 | labeled FOLDERNAME/FOLDERNAME.md 10 | 11 | change "General" to the subpage you are wanting to target 12 | */ 13 | 14 | const path_sub = "General" 15 | 16 | let count = 0; 17 | const path_base = dv.current().file.path 18 | const path_targ = path_base.substr(0, path_base.lastIndexOf("/")); 19 | const path_fnote_excl = path_sub + ".md" 20 | const filter_page = '"' + path_targ + "/" + path_sub + '"'; 21 | const filter_folder = path_targ + "/" + path_sub; 22 | 23 | let p = dv.pages(filter_page) 24 | .where(p => p.file.name != dv.current().file.name) // Filter out the current page 25 | .where(p => p.file.folder == filter_folder) // Filter out folders 26 | .where(p => !p.file.path.endsWith(path_fnote_excl) ) // Filter folder note index 27 | .sort(p => p.file.path) 28 | .forEach(p => 29 | { 30 | dv.header(4, p.file.name); // display page name as header 31 | const cache = this.app.metadataCache.getCache(p.file.path); 32 | 33 | if (cache) 34 | { 35 | const headings = cache.headings; // get headings from cache 36 | 37 | if (headings) 38 | { 39 | const houtput = headings.slice(1) // exclude the first heading 40 | .filter(h => h.level <= 6) 41 | .map(h => 42 | { 43 | count++; 44 | 45 | // Determine indentation based on heading level 46 | let indent = " ".repeat(h.level); 47 | var file_name = p.file.name; 48 | 49 | // remove backticks and tag symbols 50 | var file_head = h.heading 51 | var file_head = file_head.replace(/`/g, ''); 52 | var file_head = file_head.replace(/#/g, ''); 53 | var file_title = h.heading.split('#')[0]; 54 | 55 | let objLink = "[[" + file_name + "#" + file_head + "|" + file_title + "]]"; 56 | 57 | if ( h.level == 1 ) 58 | return indent + "- " + objLink + ""; 59 | else if ( h.level == 2 ) 60 | return indent + " - " + objLink + ""; 61 | else if ( h.level == 3 ) 62 | return indent + " - " + objLink + ""; 63 | else if ( h.level == 4 ) 64 | return indent + " - " + objLink + ""; 65 | else if ( h.level == 5 ) 66 | return indent + " - " + objLink + ""; 67 | else if ( h.level == 6 ) 68 | return indent + " - " + objLink + ""; 69 | else 70 | return indent + "- " + objLink; 71 | }) 72 | .join("\n") 73 | 74 | dv.el("div", houtput); 75 | dv.el("div", "
"); 76 | } 77 | } 78 | }); 79 | 80 | /* 81 | display NO RESULTS 82 | */ 83 | 84 | if (count === 0) 85 | { 86 | const rootNode = dv.el("div", "No results", { cls: "toc-results-none" }); 87 | rootNode.setAttribute("style", "text-align:center;"); 88 | } 89 | ``` -------------------------------------------------------------------------------- /Snippets/TOC Version 1/README.md: -------------------------------------------------------------------------------- 1 |
2 |

📃 Table of Contents: Version 1 📃

3 |
4 |

A dataview script which displays a table of contents. It compiles a list of all your folder's current subpages and pulls the headers from each page to display in a simple and neat list.

5 | 6 |
7 | 8 |
9 | 10 | > [!NOTE] 11 | > Need a table of contents snippet which does **not** require the [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes)? 12 | > 13 | > Click here to install [Table of Contents: Version 2](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/TOC%20Version%202) 14 | 15 |
16 | 17 | ## About 18 | 19 | This snippet requires you to have: 20 | - [Obsidian.md](obsidian.md/) 21 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 22 | - [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) 23 | 24 |
25 | 26 | The code for this version should be pasted inside a **Folder Note**. It will fetch all of the files that exist inside that folder. 27 | 28 |
29 | 30 | At the time of writing this script, I am using the following: 31 | 32 | | Software | Version | 33 | | --- | --- | 34 | | [Obsidian.md](https://obsidian.md/) | ![GitHub release](https://img.shields.io/github/v/release/obsidianmd/obsidian-releases?label=v&color=ba0f56) | 35 | | [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) | ![GitHub release](https://img.shields.io/github/v/release/blacksmithgu/obsidian-dataview?label=v&color=ba0f56) | 36 | | [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) | ![GitHub release](https://img.shields.io/github/v/release/LostPaul/obsidian-folder-notes?label=v&color=ba0f56) | 37 | 38 |
39 | 40 | ### Previews 41 | The following are preview images of what the snippet will do and appear like: 42 | 43 |
44 | 45 |

46 | 47 |
48 | 49 |

50 | 51 | --- 52 | 53 |

54 | 55 | ## Usage 56 | 57 | - Install [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 58 | - Install [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes) 59 | - Right-click on a folder, select `Folder Note Commands` and select `Create Folder Note` 60 | - Copy the code below and paste in Obsidian folder note: 61 | 62 |
63 | 64 | ````javascript 65 | ```dataviewjs 66 | 67 | /* 68 | Table of Contents Script > Version 1 69 | 70 | This version requires the plugins: 71 | https://github.com/LostPaul/obsidian-folder-notes 72 | https://github.com/blacksmithgu/obsidian-dataview 73 | 74 | Create a new folder, right-click, and create folder note. 75 | Click inside the folder note and paste the code below. 76 | 77 | Inside that folder, place the files you want the table of 78 | contents to display. Make sure each file contains headers. 79 | */ 80 | 81 | let count = 0; 82 | const path_base = dv.current().file.path 83 | const path_targ = path_base.substr(0, path_base.lastIndexOf("/")); 84 | const path_sub = "" 85 | 86 | const filter_page = '"' + path_targ + "" + path_sub + '"'; 87 | const filter_folder = path_targ + path_sub; 88 | 89 | let p = dv.pages(filter_page) 90 | .where(p => p.file.name != dv.current().file.name) // Filter out the current page 91 | .where(p => p.file.folder == filter_folder) // Filter out folders 92 | .sort(p => p.file.path) 93 | .forEach(p => 94 | { 95 | dv.header(4, p.file.name); // display page name as header 96 | const cache = this.app.metadataCache.getCache(p.file.path); 97 | 98 | if (cache) 99 | { 100 | const headings = cache.headings; // get headings from cache 101 | 102 | if ( typeof headings === 'undefined') { 103 | dv.el("div", '⭕ No Subheaders Found', { cls: "toc_results_none_subheader" }); 104 | dv.el("div", "
"); 105 | return; 106 | } 107 | 108 | if (headings) 109 | { 110 | const houtput = headings.slice(0) // exclude the first heading 111 | .filter(h => h.level <= 6) 112 | .map(h => 113 | { 114 | let file_head = h.heading 115 | const header_skip = file_head.replace(/ /g,"_").toLowerCase(); 116 | if (header_skip === "table_of_contents" || header_skip === "toc") 117 | { 118 | return "" 119 | } 120 | 121 | count++; 122 | 123 | // Determine indentation based on heading level 124 | let indent = " ".repeat(h.level); 125 | const file_name = p.file.name; 126 | 127 | // remove backticks and tag symbols 128 | file_head = file_head.replace(/`/g, ''); 129 | file_head = file_head.replace(/#/g, ''); 130 | const file_title = h.heading.split('#')[0]; 131 | 132 | let objLink = "[[" + file_name + "#" + file_head + "|" + file_title + "]]"; 133 | 134 | if ( h.level == 1 ) 135 | return indent + "- " + objLink + ""; 136 | else if ( h.level == 2 ) 137 | return indent + " - " + objLink + ""; 138 | else if ( h.level == 3 ) 139 | return indent + " - " + objLink + ""; 140 | else if ( h.level == 4 ) 141 | return indent + " - " + objLink + ""; 142 | else if ( h.level == 5 ) 143 | return indent + " - " + objLink + ""; 144 | else if ( h.level == 6 ) 145 | return indent + " - " + objLink + ""; 146 | else 147 | return 'No Result' 148 | }) 149 | .join("\n") 150 | 151 | dv.el("div", houtput); 152 | dv.el("div", "
"); 153 | } 154 | } 155 | }); 156 | 157 | /* 158 | display NO RESULTS 159 | */ 160 | 161 | if (count === 0) 162 | { 163 | const rootNode = dv.el("div", "No results", { cls: "toc_results_none" }); 164 | rootNode.setAttribute("style", "text-align:center;"); 165 | } 166 | ``` 167 | ```` 168 | 169 |
170 | 171 | If you want to target a subfolder / path, you can modify the variable `path_sub`. If you leave it blank, it will target the folder you paste the code in. 172 | 173 | ```javascript 174 | const path_sub = "Path/To/Subfolder" 175 | ``` 176 | 177 |
178 | 179 | Next, you need to add some custom CSS. 180 | Open Obsidian Settings, click **Appearance**, and then scroll all the way down. (See image below). 181 | 182 | Click the mini folder icon to open your **Obsidian Snippets folder**. 183 | 184 |
185 | 186 |

187 | 188 |
189 | 190 | Create a new file named whatever (`toc.css` in our example). 191 | 192 | Copy the code below and paste it into the new `toc.css` file which should be in `YourVaultName/.obsidian/snippets/toc.css` 193 | 194 |
195 | 196 |

197 | 198 |
199 | 200 | ```css 201 | /* 202 | Snippet: Table of Contents 203 | */ 204 | 205 | /* 206 | header 2 207 | */ 208 | 209 | .toc_h2 a 210 | { 211 | color: #7fa8f5 !important; 212 | font-size: 10pt; 213 | font-weight: lighter; 214 | line-height: 20px; 215 | } 216 | 217 | /* 218 | header 3 219 | */ 220 | 221 | .toc_h3 a 222 | { 223 | color: #f85289 !important; 224 | font-size: 9pt; 225 | font-weight: lighter; 226 | line-height: 20px; 227 | } 228 | 229 | /* 230 | header 4, 5, 6 231 | */ 232 | 233 | .toc_h4 a, .toc_h5 a, .toc_h6 a 234 | { 235 | color: #969696 !important; 236 | font-size: 8pt; 237 | font-weight: normal; 238 | line-height: 20px; 239 | } 240 | 241 | /* 242 | bad links > path 243 | */ 244 | 245 | .toc_badpaths_path, .toc_badpaths_path a 246 | { 247 | color: #adadad !important; 248 | font-size: 8pt; 249 | font-weight: normal; 250 | line-height: 20px; 251 | } 252 | 253 | /* 254 | no results > total 255 | */ 256 | 257 | .toc_results_none 258 | { 259 | text-align: center; 260 | font-size: 12pt; 261 | } 262 | 263 | /* 264 | no results > subheader 265 | */ 266 | 267 | .toc_results_none_subheader 268 | { 269 | padding-left: 12px; 270 | font-size: 10pt; 271 | } 272 | ``` 273 | 274 |
275 | 276 | Save the file and go back to **Obsidian Settings** -> **Appearance**. Scroll all the way down and enable the checkbox to the right of `toc.css`. 277 | 278 |

279 | 280 |
281 | 282 | You should see a table of contents which is populated with the headings of your subfolders. 283 | 284 |

285 | 286 | --- 287 | 288 |

289 | 290 | ## Customization 291 | ### How to make page title above the each list appear bigger 292 | In your code, locate 293 | ```javascript 294 | dv.header(4, p.file.name); 295 | ``` 296 | 297 | The `4` stands for `H4` or header 4. To make the text bigger, change that number to `3 or lower`. Overall, it accepts any number between `1 - 6`, with 1 being the biggest and 6 being the smallest text size. 298 | 299 |
300 |
301 | 302 | ### Make each page title not display as a listed item 303 | Locate the code toward the top: 304 | ```javascript 305 | dv.header(4, p.file.name); 306 | ``` 307 | and replace it with: 308 | ```javascript 309 | dv.el("div", p.file.name); 310 | ``` 311 | 312 | This will force each page title to display in a `div` and not as header object. 313 | 314 |
315 |
316 | 317 | ### My list is cutting off the first header of each page 318 | Locate the following code: 319 | ```javascript 320 | const houtput = headings.slice(1) 321 | ``` 322 | 323 | The number `1` represents how many headers on the page that should be excluded from the first going from the top down. If you enter the number `0`, then no headers will be filtered out / all will show in the list. If you enter `3`, then the first three headers of each page will not appear in the table of contents list. 324 | 325 | To disable any headers from being excluded in the list, change the code above to the following: 326 | ```javascript 327 | const houtput = headings.slice(0) 328 | ``` 329 | 330 |
331 |
332 | 333 | ### Exclude certain headers from appearing in the list 334 | Much like the example above which allows you to filter from from the top, you can also filter exactly which headers display in the list with the following code: 335 | ```javascript 336 | .filter(h => h.level <= 6) 337 | ``` 338 | 339 | The number `6` represents which headers will be included in the list. If you change the value to a `4`, that means any sections of your page with headers 5 or 6 will not show. 340 | ``` 341 | ##### This is H5 342 | ###### This is H6 343 | ``` 344 | 345 |
346 |
347 | 348 | ### Making the gap between each list smaller/bigger 349 | You need to modify the following: 350 | ```javascript 351 | dv.el("div", "

"); 352 | ``` 353 | Each `
` is a line break. The more breaks you add, the larger the gap between each list. Remove each break to make the gap smaller. 354 | 355 |
356 |
-------------------------------------------------------------------------------- /Snippets/TOC Version 1/images/example_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/TOC Version 1/images/example_1.gif -------------------------------------------------------------------------------- /Snippets/TOC Version 1/images/install_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/TOC Version 1/images/install_1.gif -------------------------------------------------------------------------------- /Snippets/TOC Version 1/images/install_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/TOC Version 1/images/install_2.png -------------------------------------------------------------------------------- /Snippets/TOC Version 1/images/install_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/TOC Version 1/images/install_3.gif -------------------------------------------------------------------------------- /Snippets/TOC Version 2/README.md: -------------------------------------------------------------------------------- 1 |
2 |

📃 Table of Contents: Version 2 📃

3 |
4 |

A dataview script which displays a table of contents. The code within this page should be pasted at the top of your Obsidian note which contains headers and subheaders. It will populate a list of all the headers and show them in a list.

5 | 6 |
7 | 8 |
9 | 10 | > [!NOTE] 11 | > Want a table of contents which is compatible with the [Folder Notes Plugin](https://github.com/LostPaul/obsidian-folder-notes)? 12 | > 13 | > Click here to install [Table of Contents: Version 1](https://github.com/Aetherinox/obsidian-dataview-snippets/tree/main/Snippets/TOC%20Version%201) 14 | 15 |
16 | 17 | ## About 18 | 19 | This snippet requires you to have: 20 | - [Obsidian.md](obsidian.md/) 21 | - [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 22 | 23 |
24 | 25 | The code for this version should be pasted at the top of a note. It will fetch all of the headers that exist on that page and display them in an unordered list at the top. 26 | 27 |
28 | 29 | At the time of writing this script, I am using the following: 30 | 31 | | Software | Version | 32 | | --- | --- | 33 | | [Obsidian.md](https://obsidian.md/) | ![GitHub release](https://img.shields.io/github/v/release/obsidianmd/obsidian-releases?label=v&color=ba0f56) | 34 | | [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) | ![GitHub release](https://img.shields.io/github/v/release/blacksmithgu/obsidian-dataview?label=v&color=ba0f56) | 35 | 36 |
37 | 38 | ### Previews 39 | The following are preview images of what the snippet will do and appear like: 40 | 41 |
42 | 43 |

44 | 45 |
46 | 47 |

48 | 49 | --- 50 | 51 |

52 | 53 | ## Usage 54 | 55 | - Install [Dataview Plugin](https://github.com/blacksmithgu/obsidian-dataview) 56 | - Copy the code below and paste it at the top of a note you want to display a list of headers for: 57 | 58 |
59 | 60 | ````javascript 61 | ```dataviewjs 62 | 63 | /* 64 | Table of Contents Script > Version 2 65 | 66 | Should be pasted at the top of the page to outline 67 | all of the headers you want to list on the same page 68 | 69 | For this script, "path_sub" should not be edited. 70 | */ 71 | 72 | let count = 0; 73 | const path_base = dv.current().file.path 74 | const path_targ = path_base.substr(0, path_base.lastIndexOf(".md")); 75 | const path_sub = "" 76 | 77 | const filter_page = '"' + path_targ + "" + path_sub + '"'; 78 | const filter_folder = path_targ + path_sub; 79 | 80 | let p = dv.pages(filter_page) 81 | .sort(p => p.file.path) 82 | .forEach(p => 83 | { 84 | // dv.header(4, p.file.name); // display page name as header 85 | const cache = this.app.metadataCache.getCache(p.file.path); 86 | 87 | if (cache) 88 | { 89 | const headings = cache.headings; // get headings from cache 90 | 91 | if (headings) 92 | { 93 | const houtput = headings.slice(0) // exclude the first heading 94 | .filter(h => h.level <= 6) 95 | .map(h => 96 | { 97 | let file_head = h.heading 98 | const header_skip = file_head.replace(/ /g,"_").toLowerCase(); 99 | if (header_skip === "table_of_contents" || header_skip === "toc") 100 | { 101 | return "" 102 | } 103 | 104 | count++; 105 | 106 | // Determine indentation based on heading level 107 | let indent = " ".repeat(h.level); 108 | const file_name = p.file.name; 109 | 110 | // remove backticks and tag symbols 111 | file_head = file_head.replace(/`/g, ''); 112 | file_head = file_head.replace(/#/g, ''); 113 | const file_title = h.heading.split('#')[0]; 114 | 115 | let objLink = "[[" + file_name + "#" + file_head + "|" + file_title + "]]"; 116 | 117 | if ( h.level == 1 ) 118 | return indent + "- " + objLink + ""; 119 | else if ( h.level == 2 ) 120 | return indent + " - " + objLink + ""; 121 | else if ( h.level == 3 ) 122 | return indent + " - " + objLink + ""; 123 | else if ( h.level == 4 ) 124 | return indent + " - " + objLink + ""; 125 | else if ( h.level == 5 ) 126 | return indent + " - " + objLink + ""; 127 | else if ( h.level == 6 ) 128 | return indent + " - " + objLink + ""; 129 | else 130 | return indent + "- " + objLink; 131 | }) 132 | .join("\n") 133 | 134 | dv.el("div", houtput); 135 | dv.el("div", "
"); 136 | } 137 | } 138 | }); 139 | 140 | /* 141 | display NO RESULTS 142 | */ 143 | 144 | if (count === 0) 145 | { 146 | const rootNode = dv.el("div", "No results", { cls: "toc_results_none" }); 147 | rootNode.setAttribute("style", "text-align:center;"); 148 | } 149 | ``` 150 | ```` 151 | 152 |
153 | 154 | If you want to target a subfolder / path, you can modify the variable `path_sub`. If you leave it blank, it will target the folder you paste the code in. 155 | 156 | ```javascript 157 | const path_sub = "Path/To/Subfolder" 158 | ``` 159 | 160 |
161 | 162 | Next, you need to add some custom CSS. 163 | Open Obsidian Settings, click **Appearance**, and then scroll all the way down. (See image below). 164 | 165 | Click the mini folder icon to open your **Obsidian Snippets folder**. 166 | 167 |
168 | 169 |

170 | 171 |
172 | 173 | Create a new file named whatever (`toc.css` in our example). 174 | 175 | Copy the code below and paste it into the new `toc.css` file which should be in `YourVaultName/.obsidian/snippets/toc.css` 176 | 177 |
178 | 179 |

180 | 181 |
182 | 183 | ```css 184 | /* 185 | Snippet: Table of Contents > v2 186 | */ 187 | 188 | /* 189 | toc > header 2 190 | */ 191 | 192 | .toc_h2 a 193 | { 194 | color: #7fa8f5 !important; 195 | font-size: 10pt; 196 | font-weight: lighter; 197 | line-height: 20px; 198 | } 199 | 200 | /* 201 | toc > header 3 202 | */ 203 | 204 | .toc_h3 a 205 | { 206 | color: #f85289 !important; 207 | font-size: 9pt; 208 | font-weight: lighter; 209 | line-height: 20px; 210 | } 211 | 212 | /* 213 | toc > header 4, 5, 6 214 | */ 215 | 216 | .toc_h4 a, .toc_h5 a, .toc_h6 a 217 | { 218 | color: #969696 !important; 219 | font-size: 8pt; 220 | font-weight: normal; 221 | line-height: 20px; 222 | } 223 | 224 | /* 225 | toc > bad links > path 226 | */ 227 | 228 | .toc_badpaths_path, .toc_badpaths_path a 229 | { 230 | color: #adadad !important; 231 | font-size: 8pt; 232 | font-weight: normal; 233 | line-height: 20px; 234 | } 235 | 236 | /* 237 | toc > no results 238 | */ 239 | 240 | .toc_results_none 241 | { 242 | text-align: center; 243 | font-size: 12pt; 244 | } 245 | ``` 246 | 247 |
248 | 249 | Save the file and go back to **Obsidian Settings** -> **Appearance**. Scroll all the way down and enable the checkbox to the right of `toc.css`. 250 | 251 |

252 | 253 |
254 | 255 | You should see a table of contents which is populated with the headings of your subfolders. 256 | 257 |

258 | 259 | --- 260 | 261 |

262 | 263 | ## Customization 264 | ### How to make page title above the each list appear bigger 265 | In your code, locate 266 | ```javascript 267 | dv.header(4, p.file.name); 268 | ``` 269 | 270 | The `4` stands for `H4` or header 4. To make the text bigger, change that number to `3 or lower`. Overall, it accepts any number between `1 - 6`, with 1 being the biggest and 6 being the smallest text size. 271 | 272 |
273 |
274 | 275 | ### Make each page title not display as a listed item 276 | Locate the code toward the top: 277 | ```javascript 278 | dv.header(4, p.file.name); 279 | ``` 280 | and replace it with: 281 | ```javascript 282 | dv.el("div", p.file.name); 283 | ``` 284 | 285 | This will force each page title to display in a `div` and not as header object. 286 | 287 |
288 |
289 | 290 | ### My list is cutting off the first header of each page 291 | Locate the following code: 292 | ```javascript 293 | const houtput = headings.slice(1) 294 | ``` 295 | 296 | The number `1` represents how many headers on the page that should be excluded from the first going from the top down. If you enter the number `0`, then no headers will be filtered out / all will show in the list. If you enter `3`, then the first three headers of each page will not appear in the table of contents list. 297 | 298 | To disable any headers from being excluded in the list, change the code above to the following: 299 | ```javascript 300 | const houtput = headings.slice(0) 301 | ``` 302 | 303 |
304 |
305 | 306 | ### Exclude certain headers from appearing in the list 307 | Much like the example above which allows you to filter from from the top, you can also filter exactly which headers display in the list with the following code: 308 | ```javascript 309 | .filter(h => h.level <= 6) 310 | ``` 311 | 312 | The number `6` represents which headers will be included in the list. If you change the value to a `4`, that means any sections of your page with headers 5 or 6 will not show. 313 | ``` 314 | ##### This is H5 315 | ###### This is H6 316 | ``` 317 | 318 |
319 |
320 | 321 | ### Making the gap between each list smaller/bigger 322 | You need to modify the following: 323 | ```javascript 324 | dv.el("div", "

"); 325 | ``` 326 | Each `
` is a line break. The more breaks you add, the larger the gap between each list. Remove each break to make the gap smaller. 327 | 328 |
329 |
-------------------------------------------------------------------------------- /Snippets/TOC Version 2/images/example_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/TOC Version 2/images/example_1.gif -------------------------------------------------------------------------------- /Snippets/TOC Version 2/images/install_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/TOC Version 2/images/install_1.gif -------------------------------------------------------------------------------- /Snippets/TOC Version 2/images/install_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/TOC Version 2/images/install_2.png -------------------------------------------------------------------------------- /Snippets/TOC Version 2/images/install_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/TOC Version 2/images/install_3.gif -------------------------------------------------------------------------------- /Snippets/Tag Cloud 1/images/example_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 1/images/example_1.gif -------------------------------------------------------------------------------- /Snippets/Tag Cloud 1/images/install_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 1/images/install_1.gif -------------------------------------------------------------------------------- /Snippets/Tag Cloud 1/images/install_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 1/images/install_2.png -------------------------------------------------------------------------------- /Snippets/Tag Cloud 1/images/install_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 1/images/install_3.gif -------------------------------------------------------------------------------- /Snippets/Tag Cloud 2/images/example_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 2/images/example_1.gif -------------------------------------------------------------------------------- /Snippets/Tag Cloud 2/images/install_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 2/images/install_1.gif -------------------------------------------------------------------------------- /Snippets/Tag Cloud 2/images/install_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 2/images/install_2.png -------------------------------------------------------------------------------- /Snippets/Tag Cloud 2/images/install_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 2/images/install_3.gif -------------------------------------------------------------------------------- /Snippets/Tag Cloud 2/images/install_4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aetherinox/obsidian-dataview-snippets/bf4bbc7cf4777909a2a0035db9f9f05ca2ddcd37/Snippets/Tag Cloud 2/images/install_4.gif -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | const tsParser = require('@typescript-eslint/parser'); 2 | const js = require('@eslint/js'); 3 | const globals = require('globals'); 4 | const ts = require('@typescript-eslint/eslint-plugin'); 5 | const eslintConfigPrettier = require('eslint-config-prettier'); 6 | const prettier = require('eslint-plugin-prettier'); 7 | const stylisticJs = require('@stylistic/eslint-plugin-js'); 8 | const stylisticTs = require('@stylistic/eslint-plugin-ts'); 9 | const stylisticPlus = require('@stylistic/eslint-plugin-plus') 10 | 11 | module.exports = [ 12 | { 13 | files: [ 14 | '**/*.ts', 15 | './src/**/*.ts', 16 | './test/**/*.ts' 17 | ], 18 | plugins: { 19 | '@typescript-eslint': ts, 20 | 'prettier': prettier, 21 | '@stylistic/js': stylisticJs, 22 | '@stylistic/ts': stylisticTs, 23 | '@stylistic/plus': stylisticPlus 24 | }, 25 | languageOptions: { 26 | parser: tsParser, 27 | globals: { 28 | ...globals.browser, 29 | }, 30 | parserOptions: { 31 | project: ['tsconfig.json'], 32 | }, 33 | }, 34 | rules: { 35 | ...js.configs.recommended.rules, 36 | ...ts.configs['stylistic-type-checked'].rules, 37 | // eslint/js rules 38 | 'indent': [1, 4], 39 | 'space-before-function-paren': 0, 40 | 'prefer-const': 1, 41 | 'comma-dangle': 0, 42 | 'keyword-spacing': ['error', { before: true, after: true }], 43 | 'comma-spacing': ['error', { before: false, after: true }], 44 | 'indent': 0, 45 | 'prefer-spread': 1, 46 | 'eqeqeq': ['error', 'smart'], 47 | 'no-unexpected-multiline': 0, 48 | 'no-prototype-builtins': 0, 49 | 'no-useless-escape': 1, 50 | 'no-mixed-operators': 1, 51 | 'no-control-regex': 0, 52 | 'no-console': 2, 53 | 'no-var': 2, 54 | 'no-undef': 0, 55 | 'no-redeclare': 'error', 56 | 'no-unused-vars': [ 57 | 'error', 58 | { 59 | 'argsIgnorePattern': '^_', 60 | 'varsIgnorePattern': '^_', 61 | 'ignoreRestSiblings': true 62 | } 63 | ], 64 | 65 | '@stylistic/js/no-multi-spaces': [ 0, { ignoreEOLComments: true } ], 66 | '@stylistic/js/arrow-spacing': [ 'error', { before: true, after: true } ], 67 | '@stylistic/js/arrow-parens': [ 'error', 'always' ], 68 | 69 | '@stylistic/js/block-spacing': [ 'error', 'always' ], 70 | '@stylistic/ts/block-spacing': [ 'error', 'always' ], 71 | 72 | '@stylistic/js/brace-style': [ 'error', 'allman', { allowSingleLine: true } ], 73 | '@stylistic/ts/brace-style': [ 'error', 'allman', { allowSingleLine: true } ], 74 | 75 | '@stylistic/js/comma-dangle': [ 'error', 'never' ], 76 | '@stylistic/ts/comma-dangle': [ 'error', 'never' ], 77 | 78 | '@stylistic/js/comma-spacing': [ 'error', { before: false, after: true }], 79 | '@stylistic/ts/comma-spacing': [ 'error', { before: false, after: true }], 80 | 81 | '@stylistic/js/keyword-spacing': [ 'error', { 82 | before: true, 83 | after: true, 84 | 'overrides': 85 | { 86 | return: { before: true, after: true }, 87 | throw: { before: true, after: true }, 88 | case: { before: true, after: true }, 89 | as: { before: true, after: true }, 90 | if: { before: true, after: true }, 91 | for: { before: true, after: true }, 92 | while: { before: true, after: true }, 93 | static: { before: true, after: true } 94 | }, 95 | }], 96 | 97 | '@stylistic/ts/keyword-spacing': ['error', { 98 | before: true, 99 | after: true, 100 | 'overrides': 101 | { 102 | return: { before: true, after: true }, 103 | throw: { before: true, after: true }, 104 | case: { before: true, after: true }, 105 | as: { before: true, after: true }, 106 | if: { before: true, after: true }, 107 | for: { before: true, after: true }, 108 | while: { before: true, after: true }, 109 | static: { before: true, after: true } 110 | }, 111 | }], 112 | 113 | '@stylistic/js/computed-property-spacing': ['error', 'always'], 114 | '@stylistic/js/eol-last': ['error', 'always'], 115 | '@stylistic/js/jsx-quotes': ['error', 'prefer-single'], 116 | '@stylistic/js/linebreak-style': ['error', 'unix'], 117 | '@stylistic/js/no-mixed-spaces-and-tabs': ['error'], 118 | '@stylistic/js/no-tabs': ['error'], 119 | '@stylistic/js/no-trailing-spaces': ['error', { 'skipBlankLines': true, 'ignoreComments': true }], 120 | '@stylistic/js/no-whitespace-before-property': ['error'], 121 | 122 | '@stylistic/js/object-curly-spacing': ['error', 'always'], 123 | '@stylistic/ts/object-curly-spacing': ['error', 'always'], 124 | 125 | '@stylistic/js/quote-props': ['error', 'as-needed'], 126 | '@stylistic/ts/quote-props': ['error', 'as-needed'], 127 | 128 | '@stylistic/js/quotes': ['error', 'single', { 'allowTemplateLiterals': true }], 129 | '@stylistic/ts/quotes': ['error', 'single', { 'allowTemplateLiterals': true }], 130 | 131 | '@stylistic/js/semi': ['error', 'never'], 132 | '@stylistic/ts/semi': ['error', 'never'], 133 | 134 | '@stylistic/js/space-in-parens': ['error', 'always'], 135 | 136 | '@stylistic/js/space-infix-ops': ['error'], 137 | '@stylistic/ts/space-infix-ops': ['error'], 138 | 139 | '@stylistic/js/spaced-comment': ['error', 'always'], 140 | '@stylistic/js/template-curly-spacing': ['error', 'always'], 141 | '@stylistic/js/template-tag-spacing': ['error', 'always'], 142 | '@stylistic/js/wrap-iife': [2, "inside", { functionPrototypeMethods: true }], 143 | 144 | '@stylistic/plus/type-named-tuple-spacing': ["error"], 145 | '@stylistic/plus/type-generic-spacing': ["error"], 146 | 147 | // 'prettier/prettier': ['error'], 148 | // @typescript-eslint rules 149 | '@typescript-eslint/prefer-nullish-coalescing': 'off' // require `strictNullChecks` 150 | }, 151 | }]; 152 | -------------------------------------------------------------------------------- /obs.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* eslint-disable @typescript-eslint/no-var-requires */ 3 | 4 | /* 5 | build obs by running 6 | npm run build 7 | 8 | guid and uuid will be automatically generated and placed 9 | inside .env file which will then be read by the github workflow 10 | build script. 11 | */ 12 | 13 | /* 14 | This script handles the following: 15 | - read package.json 16 | - create .env file 17 | - return uuid, guid, version 18 | 19 | can be called with the following external commands: 20 | - node obs.js returns version of obs 21 | - node obs.js generate generates uuid / guid and shows all env vars in console 22 | - node obs.js uuid returns obs uuid 23 | - node obs.js guid returns obs guid 24 | - node obs.js versiom returns version of obs 25 | 26 | can be called with the following obs commands: 27 | - npm run obs 28 | - npm run obs:generate 29 | - npm run env-obs 30 | - npm run env-uuid 31 | - npm run env-guid 32 | - npm run env-version 33 | */ 34 | 35 | const fs = require('fs'); 36 | const { v5: uuid } = require('uuid'); 37 | 38 | /* 39 | * declrations > package.json 40 | */ 41 | 42 | const { version, repository } = JSON.parse(fs.readFileSync('package.json')); 43 | const args = process.argv.slice(2, process.argv.length); 44 | const action = args[0]; 45 | // const a = args[ 1 ]; 46 | // const b = args[ 2 ]; 47 | 48 | if (action === 'guid') { 49 | console.log(`${process.env.GUID}`); 50 | } else if (action === 'setup') { 51 | fs.writeFileSync('.env', '', (err) => { 52 | if (err) { 53 | console.error(err); 54 | } else { 55 | console.log(`Wrote to .env successfully`); 56 | } 57 | }); 58 | } else if (action === 'generate') { 59 | const buildGuid = uuid(`${repository.url}`, uuid.URL); 60 | const buildUuid = uuid(version, buildGuid); 61 | 62 | const ids = ` 63 | VERSION=${version} 64 | GUID=${buildGuid} 65 | UUID=${buildUuid} 66 | `; 67 | 68 | console.log(version); 69 | console.log(buildGuid); 70 | console.log(buildUuid); 71 | 72 | fs.writeFileSync('.env', ids, (err) => { 73 | if (err) { 74 | console.error(`Could not write env vars: ${err}`); 75 | } else { 76 | console.log(`Wrote env vars to .env`); 77 | } 78 | }); 79 | } else if (action === 'uuid') { 80 | console.log(`${process.env.UUID}`); 81 | } else { 82 | console.log(version); 83 | } 84 | 85 | process.exit(0); 86 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aetherinox/obsidian-dataview-snippets", 3 | "version": "1.4.3", 4 | "description": "A collection of Obsidian.md scripts to be used in combination with the dataview plugin.", 5 | "homepage": "https://github.com/Aetherinox/obsidian-dataview-snippets", 6 | "author": "Aetherinox ", 7 | "license": "MIT", 8 | "contributors": [ 9 | { 10 | "name": "Aetherinox", 11 | "email": "118329232+Aetherinox@users.noreply.github.com", 12 | "url": "https://github.com/Aetherinox" 13 | }, 14 | { 15 | "name": "EuropaServ", 16 | "email": "161414668+EuropaServ@users.noreply.github.com", 17 | "url": "https://github.com/EuropaServ" 18 | } 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/Aetherinox/obsidian-dataview-snippets.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/Aetherinox/obsidian-dataview-snippets/issues" 26 | }, 27 | "build": { 28 | "appId": "com.obsidian.dataview.snippets.id" 29 | }, 30 | "funding": [ 31 | { 32 | "type": "individual", 33 | "url": "https://buymeacoffee.com/aetherinox" 34 | } 35 | ], 36 | "keywords": [ 37 | "obsidian", 38 | "dataview", 39 | "folder_notes", 40 | "snippets", 41 | "scripts", 42 | "notes" 43 | ], 44 | "scripts": { 45 | "pretest": "npm run lint", 46 | "lint": "eslint src/**/*.ts", 47 | "lint:fix": "eslint --fix src/**/*.ts", 48 | "pretty": "prettier . --check", 49 | "pretty:fix": "prettier . --write", 50 | "pretty:ignore": "prettier . --write --ignore-unknown", 51 | "obs": "node obs.js", 52 | "contrib:add": "all-contributors add", 53 | "contrib:generate": "all-contributors generate", 54 | "root": "node obs.js", 55 | "root:generate": "node obs.js generate", 56 | "env:obs": "npx --quiet env-cmd --no-override node obs.js", 57 | "env:uuid": "npx --quiet env-cmd --no-override node obs.js uuid", 58 | "env:guid": "npx --quiet env-cmd --no-override node obs.js guid", 59 | "env:version": "node -p require('./package.json').version;" 60 | }, 61 | "devDependencies": { 62 | "eslint-plugin-prettier": "^5.2.1", 63 | "typescript-eslint": "^7.14.0", 64 | "@typescript-eslint/parser": "^7.16.0", 65 | "@typescript-eslint/eslint-plugin": "^7.16.0", 66 | "@stylistic/eslint-plugin-js": "^2.3.0", 67 | "@stylistic/eslint-plugin-ts": "^2.3.0", 68 | "@stylistic/eslint-plugin-plus": "^2.3.0", 69 | "prettier": "^3.2.5", 70 | "@rollup/plugin-commonjs": "^26.0.1", 71 | "@rollup/plugin-image": "^3.0.3", 72 | "@rollup/plugin-node-resolve": "^15.2.3", 73 | "@rollup/plugin-replace": "^5.0.7", 74 | "@rollup/plugin-terser": "^0.4.4", 75 | "@rollup/plugin-typescript": "^11.1.6", 76 | "rollup-plugin-license": "^3.5.2", 77 | "@types/semver": "^7.5.8", 78 | "@types/uuid": "^10.0.0", 79 | "obsidian": "^1.7.2", 80 | "rollup": "^4.24.0", 81 | "semver": "^7.6.3", 82 | "uuid": "^10.0.0", 83 | "all-contributors-cli": "^6.26.1" 84 | } 85 | } 86 | --------------------------------------------------------------------------------