diff --git a/src/demo/css/style.css b/src/demo/css/style.css index 852763a6..2c11b900 100644 --- a/src/demo/css/style.css +++ b/src/demo/css/style.css @@ -311,6 +311,20 @@ input:focus:invalid { word-break: break-all; } +.output .workflow { + word-break: normal; + overflow-x: auto; +} + +.output .workflow code { + white-space: pre; +} + +.workflow-note { + font-size: 0.9em; + line-height: 1.5; +} + .output .btn { margin-top: 16px; } diff --git a/src/demo/index.php b/src/demo/index.php index c3d44bfe..e9ca781e 100644 --- a/src/demo/index.php +++ b/src/demo/index.php @@ -264,6 +264,20 @@ function gtag() { Copy To Clipboard + +
+

GitHub Actions Workflow

+

+ Create .github/workflows/streak-stats.yml in your profile repository. For private contributions, create a repository secret named STREAK_STATS_TOKEN and use it in place of GITHUB_TOKEN. +

+
+ +
+ + +
diff --git a/src/demo/js/script.js b/src/demo/js/script.js index 465614a5..fafcbb8e 100644 --- a/src/demo/js/script.js +++ b/src/demo/js/script.js @@ -34,10 +34,7 @@ const preview = { params.hide_longest_streak = String(!params.sections.includes("longest")); delete params.sections; // convert parameters to query string - const query = Object.keys(params) - .filter((key) => params[key] !== this.defaults[key]) - .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`) - .join("&"); + const query = this.toQueryString(params); // generate links and markdown const imageURL = `${window.location.origin}?${query}`; const demoImageURL = `preview.php?${query}`; @@ -66,6 +63,7 @@ const preview = { document.querySelector(".output .json").style.display = "block"; document.querySelector(".copy-json").parentElement.style.display = "block"; } + document.querySelector(".workflow code").innerText = this.generateWorkflow(params); // disable copy button if username is invalid const copyButtons = document.querySelectorAll(".copy-button"); copyButtons.forEach((button) => { @@ -76,6 +74,65 @@ const preview = { clearButton.disabled = !document.querySelectorAll(".minus").length; }, + /** + * Convert parameters to a query string without default values. + * @param {Object} params - the parameters to convert + * @param {string[]} ignoredKeys - keys to exclude from the query string + * @returns {string} the encoded query string + */ + toQueryString(params, ignoredKeys = []) { + return Object.keys(params) + .filter((key) => !ignoredKeys.includes(key)) + .filter((key) => params[key] !== this.defaults[key]) + .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`) + .join("&"); + }, + + /** + * Generate a GitHub Actions workflow file from the current parameters. + * @param {Object} params - the current card parameters + * @returns {string} the workflow file content + */ + generateWorkflow(params) { + const repositoryOwner = ["$", "{{ ", "github.repository_owner", " }}"].join(""); + const githubToken = ["$", "{{ ", "secrets.GITHUB_TOKEN", " }}"].join(""); + const options = this.toQueryString(params, ["type"]) || `user=${repositoryOwner}`; + + return `name: Update streak stats + +on: + schedule: + - cron: "0 3 * * *" + push: + paths: + - ".github/workflows/streak-stats.yml" + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + + - name: Generate streak stats + uses: DenverCoder1/github-readme-streak-stats@main + with: + options: ${options} + path: profile/streak.svg + token: ${githubToken} + + - name: Commit streak stats + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add profile/streak.svg + git commit -m "Update streak stats" || exit 0 + git push`; + }, + /** * Add a property in the advanced section * @param {string} property - the name of the property, selected element is used if not provided @@ -398,6 +455,8 @@ const clipboard = { input.value = document.querySelector(".html code").innerText; } else if (el.classList.contains("copy-json")) { input.value = document.querySelector(".json code").innerText; + } else if (el.classList.contains("copy-workflow")) { + input.value = document.querySelector(".workflow code").innerText; } document.body.appendChild(input); // select all