diff --git a/.all-contributorsrc b/.all-contributorsrc index 7a9fd3886..6e8d23087 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -29,6 +29,10 @@ "translation-ru": { "symbol": "🇷🇺", "description": "Translate in Russian" + }, + "translation-ch": { + "symbol": "🇨🇳", + "description": "Translate in Chinese" } }, "contributors": [ @@ -304,6 +308,70 @@ "contributions": [ "bug" ] + }, + { + "login": "EnochGao", + "name": "Enoch Gao", + "avatar_url": "https://avatars.githubusercontent.com/u/41459067?v=4", + "profile": "https://enochgao.github.io/", + "contributions": [ + "doc", + "translation-ch" + ] + }, + { + "login": "fpalmab", + "name": "Francisco Palma", + "avatar_url": "https://avatars.githubusercontent.com/u/7729812?v=4", + "profile": "https://github.com/fpalmab", + "contributions": [ + "bug" + ] + }, + { + "login": "michalgrzegorczyk-dev", + "name": "Michał Grzegorczyk", + "avatar_url": "https://avatars.githubusercontent.com/u/47832176?v=4", + "profile": "https://github.com/michalgrzegorczyk-dev", + "contributions": [ + "doc" + ] + }, + { + "login": "tamim36", + "name": "Tamim Arefin Anik", + "avatar_url": "https://avatars.githubusercontent.com/u/42251521?v=4", + "profile": "https://github.com/tamim36", + "contributions": [ + "bug" + ] + }, + { + "login": "WhoisBsa", + "name": "Matheus B.", + "avatar_url": "https://avatars.githubusercontent.com/u/36895235?v=4", + "profile": "https://github.com/WhoisBsa", + "contributions": [ + "bug" + ] + }, + { + "login": "StefH", + "name": "Stef Heyenrath", + "avatar_url": "https://avatars.githubusercontent.com/u/249938?v=4", + "profile": "https://sourcerer.io/stefh", + "contributions": [ + "doc" + ] + }, + { + "login": "mathisvester", + "name": "mathisvester", + "avatar_url": "https://avatars.githubusercontent.com/u/26164587?v=4", + "profile": "https://github.com/mathisvester", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/.eslintrc.json b/.eslintrc.json index 3bd2a22fb..de9b234b6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,6 +6,7 @@ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { + "@angular-eslint/no-host-metadata-property": "off", "@nx/enforce-module-boundaries": [ "error", { @@ -18,12 +19,6 @@ } ] } - ], - "@angular-eslint/no-host-metadata-property": [ - "error", - { - "allowStatic": true - } ] } }, diff --git a/.github/copilot-guidelines.md b/.github/copilot-guidelines.md new file mode 100644 index 000000000..e1b11d43a --- /dev/null +++ b/.github/copilot-guidelines.md @@ -0,0 +1,46 @@ +# GitHub Copilot Custom Guidelines + +You are an expert in TypeScript, Angular, and scalable web application development. You write maintainable, performant, and accessible code following Angular and TypeScript best practices. + +## TypeScript Best Practices + +- Use strict type checking +- Prefer type inference when the type is obvious +- Avoid the `any` type; use `unknown` when type is uncertain + +## Angular Best Practices + +- Always use standalone components over NgModules +- Don't use explicit `standalone: true` (it is implied by default) +- Use signals for state management +- Implement lazy loading for feature routes +- Use `NgOptimizedImage` for all static images. + +## Components + +- Keep components small and focused on a single responsibility +- Use `input()` and `output()` functions instead of decorators +- Use `computed()` for derived state +- Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator +- Prefer inline templates for small components +- Prefer Reactive forms instead of Template-driven ones +- Do NOT use `ngClass`, use `class` bindings instead +- DO NOT use `ngStyle`, use `style` bindings instead + +## State Management + +- Use signals for local component state +- Use `computed()` for derived state +- Keep state transformations pure and predictable + +## Templates + +- Keep templates simple and avoid complex logic +- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch` +- Use the async pipe to handle observables + +## Services + +- Design services around a single responsibility +- Use the `providedIn: 'root'` option for singleton services +- Use the `inject()` function instead of constructor injection diff --git a/.github/github-action/contributors.js b/.github/github-action/contributors.js index 50d4c3917..9555e6633 100644 --- a/.github/github-action/contributors.js +++ b/.github/github-action/contributors.js @@ -9,9 +9,24 @@ const contributors = [ 'kabrunko-dev', 'Sanjar1304', 'tsironis13', + 'EnochGao', ]; -const sponsors = ['ddotx', 'LMFinney', 'alannelucq', 'SidV2']; +const sponsors = [ + 'ddotx', + 'LMFinney', + 'alannelucq', + 'SidV2', + 'fpalmab', + 'CivilEngeneer', + 'apalaio', + 'amosISA', + 'michalgrzegorczyk-dev', + 'zealotrahl', + 'DzoeL123', + 'allan1989', + 'pchessah', +]; module.exports = { contributors, diff --git a/.github/workflows/close-inactive-pr.yml b/.github/workflows/close-inactive-pr.yml index 66d984d5f..d5e0e9c95 100644 --- a/.github/workflows/close-inactive-pr.yml +++ b/.github/workflows/close-inactive-pr.yml @@ -17,8 +17,8 @@ jobs: stale-issue-label: 'stale' stale-issue-message: 'This issue is stale because it has been open for 15 days with no activity.' exempt-issue-labels: 'long-term' - days-before-pr-stale: 10 - days-before-pr-close: 2 + days-before-pr-stale: 20 + days-before-pr-close: 7 stale-pr-label: 'stale' stale-pr-message: 'This pull request is stale because it has been open for 15 days with no activity.' close-pr-message: 'This pull request was closed because it has been inactive for 5 days since being marked as stale.' diff --git a/.github/workflows/label-issue.yml b/.github/workflows/label-issue.yml index 6918818fd..a5fd40632 100644 --- a/.github/workflows/label-issue.yml +++ b/.github/workflows/label-issue.yml @@ -2,9 +2,25 @@ name: Add Labels on: pull_request_target: - types: [ opened ] + types: [ opened, edited, synchronize ] jobs: + check-title: + runs-on: ubuntu-latest + steps: + - name: Check PR title + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + echo "Checking PR Title: '$PR_TITLE'" + if [[ ! "$PR_TITLE" =~ ^Answer: ]]; then + echo "❌ PR title should start with 'Answer:[#challenge number]'" + echo "### ❌ PR title should start with 'Answer:[#challenge number]'" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "✅ PR title format is correct." + echo "### ✅ PR title format is correct." >> $GITHUB_STEP_SUMMARY + fi add_labels: runs-on: ubuntu-latest if: ${{ startsWith(github.event.pull_request.title, 'Answer') }} diff --git a/.gitignore b/.gitignore index 5472d6bdf..0647ff22f 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,8 @@ Thumbs.db TODO.md .nx/cache +.nx/workspace-data + +.cursorrules +.cursor/rules/nx-rules.mdc +.github/instructions/nx.instructions.md diff --git a/.prettierignore b/.prettierignore index ab639d33d..a4684ea74 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,4 +5,5 @@ .angular -/.nx/cache \ No newline at end of file +/.nx/cache +/.nx/workspace-data \ No newline at end of file diff --git a/README.md b/README.md index 9b4cd8e6d..6ae4aa91b 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ If you would like to propose a challenge, this project is open source, so feel f ## Challenges -Check [all 55 challenges](https://angular-challenges.vercel.app/) +Check [all 60 challenges](https://angular-challenges.vercel.app/) ## Contributors ✨ @@ -69,6 +69,15 @@ Check [all 55 challenges](https://angular-challenges.vercel.app/)
-
- {{ col }} - | + @for (col of displayedColumns; track $index) { ++ {{ col }} + | + }
---|