diff --git a/.all-contributorsrc b/.all-contributorsrc index a6566ffe9..6f2f57401 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -12,7 +12,27 @@ "types": { "challenge": { "symbol": "🧩", - "description": "Created a challenge" + "description": "Create a challenge" + }, + "translation-es": { + "symbol": "🇪🇸", + "description": "Translate in Spanish" + }, + "translation-fr": { + "symbol": "🇫🇷", + "description": "Translate in French" + }, + "translation-pt": { + "symbol": "🇵🇹", + "description": "Translate in Portuguese" + }, + "translation-ru": { + "symbol": "🇷🇺", + "description": "Translate in Russian" + }, + "translation-ch": { + "symbol": "🇨🇳", + "description": "Translate in Chinese" } }, "contributors": [ @@ -27,9 +47,91 @@ "doc", "content", "ideas", + "design", + "translation-fr" + ] + }, + { + "login": "svenson95", + "name": "Sven Brodny", + "avatar_url": "https://avatars.githubusercontent.com/u/46655156?v=4", + "profile": "https://svenson95.github.io/sb-portfolio/", + "contributions": [ + "doc", + "challenge", + "content", "design" ] }, + { + "login": "jdegand", + "name": "J. Degand", + "avatar_url": "https://avatars.githubusercontent.com/u/70610011?v=4", + "profile": "https://github.com/jdegand", + "contributions": [ + "doc", + "content", + "code" + ] + }, + { + "login": "DeveshChau", + "name": "Devesh Chaudhari", + "avatar_url": "https://avatars.githubusercontent.com/u/9509673?v=4", + "profile": "https://github.com/DeveshChau", + "contributions": [ + "code", + "bug", + "challenge" + ] + }, + { + "login": "stillst", + "name": "stillst", + "avatar_url": "https://avatars.githubusercontent.com/u/1463098?v=4", + "profile": "https://github.com/stillst", + "contributions": [ + "challenge", + "translation-ru" + ] + }, + { + "login": "wandri", + "name": "Wandrille", + "avatar_url": "https://avatars.githubusercontent.com/u/15016833?v=4", + "profile": "https://wandrille-guesdon.com/", + "contributions": [ + "challenge" + ] + }, + { + "login": "alcaidio", + "name": "Timothy Alcaide", + "avatar_url": "https://avatars.githubusercontent.com/u/17033036?v=4", + "profile": "https://twitter.com/alcaidio", + "contributions": [ + "challenge" + ] + }, + { + "login": "LMFinney", + "name": "Lance Finney", + "avatar_url": "https://avatars.githubusercontent.com/u/6683747?v=4", + "profile": "https://github.com/LMFinney", + "contributions": [ + "doc", + "challenge" + ] + }, + { + "login": "tsironis13", + "name": "Tsironis Ioannis", + "avatar_url": "https://avatars.githubusercontent.com/u/7561447?v=4", + "profile": "https://github.com/tsironis13", + "contributions": [ + "challenge" + ] + }, { "login": "alan-bio", "name": "Alan Dragicevich", @@ -78,39 +180,186 @@ ] }, { - "login": "jdegand", - "name": "J. Degand", - "avatar_url": "https://avatars.githubusercontent.com/u/70610011?v=4", - "profile": "https://github.com/jdegand", + "login": "dmmishchenko", + "name": "Dmitriy Mishchenko", + "avatar_url": "https://avatars.githubusercontent.com/u/51910160?v=4", + "profile": "https://github.com/dmmishchenko", "contributions": [ "doc" ] }, { - "login": "DeveshChau", - "name": "Devesh Chaudhari", - "avatar_url": "https://avatars.githubusercontent.com/u/9509673?v=4", - "profile": "https://github.com/DeveshChau", + "login": "Sagardevkota", + "name": "Sagar Devkota", + "avatar_url": "https://avatars.githubusercontent.com/u/30800393?v=4", + "profile": "http://www.sagardev.com.np/", + "contributions": [ + "doc", + "code" + ] + }, + { + "login": "nelsongutidev", + "name": "Nelson Gutierrez", + "avatar_url": "https://avatars.githubusercontent.com/u/62297014?v=4", + "profile": "https://nelsonguti.dev/", + "contributions": [ + "translation-es" + ] + }, + { + "login": "ho-ssain", + "name": "Hossain K. M.", + "avatar_url": "https://avatars.githubusercontent.com/u/61125174?v=4", + "profile": "https://github.com/ho-ssain", + "contributions": [ + "doc" + ] + }, + { + "login": "kabrunko-dev", + "name": "Diogo Nishikawa", + "avatar_url": "https://avatars.githubusercontent.com/u/142346548?v=4", + "profile": "https://github.com/kabrunko-dev/", "contributions": [ "code", - "bug", - "challenge" + "translation-pt", + "doc" ] }, { - "login": "dmmishchenko", - "name": "Dmitriy Mishchenko", - "avatar_url": "https://avatars.githubusercontent.com/u/51910160?v=4", - "profile": "https://github.com/dmmishchenko", + "login": "ErickRodrCodes", + "name": "Erick Rodriguez", + "avatar_url": "https://avatars.githubusercontent.com/u/1978642?v=4", + "profile": "http://www.streamoverlaypro.com/", + "contributions": [ + "translation-es" + ] + }, + { + "login": "eduardoRoth", + "name": "Eduardo Roth", + "avatar_url": "https://avatars.githubusercontent.com/u/5419161?v=4", + "profile": "https://eduardoroth.dev/", + "contributions": [ + "doc", + "translation-es" + ] + }, + { + "login": "1fbr", + "name": "Fernando Bello", + "avatar_url": "https://avatars.githubusercontent.com/u/63980689?v=4", + "profile": "https://github.com/1fbr", "contributions": [ "doc" ] }, { - "login": "Sagardevkota", - "name": "Sagar Devkota", - "avatar_url": "https://avatars.githubusercontent.com/u/30800393?v=4", - "profile": "http://www.sagardev.com.np/", + "login": "webbomj", + "name": "Лапин Андрей (Lapin Andrey)", + "avatar_url": "https://avatars.githubusercontent.com/u/86595717?v=4", + "profile": "https://github.com/webbomj", + "contributions": [ + "translation-ru" + ] + }, + { + "login": "Dinozavvvr", + "name": "Dinar Shagaliev", + "avatar_url": "https://avatars.githubusercontent.com/u/45518871?v=4", + "profile": "https://github.com/Dinozavvvr", + "contributions": [ + "translation-ru" + ] + }, + { + "login": "vimulatus", + "name": "Vimulatus", + "avatar_url": "https://avatars.githubusercontent.com/u/63696128?v=4", + "profile": "https://github.com/vimulatus", + "contributions": [ + "doc" + ] + }, + { + "login": "alannelucq", + "name": "Arthur LANNELUCQ", + "avatar_url": "https://avatars.githubusercontent.com/u/44091408?v=4", + "profile": "https://github.com/alannelucq", + "contributions": [ + "translation-fr" + ] + }, + { + "login": "fixedmichal", + "name": "fixed_michal", + "avatar_url": "https://avatars.githubusercontent.com/u/26270192?v=4", + "profile": "https://github.com/fixedmichal", + "contributions": [ + "bug" + ] + }, + { + "login": "Tenessy", + "name": "Tenessy", + "avatar_url": "https://avatars.githubusercontent.com/u/65855673?v=4", + "profile": "https://github.com/Tenessy", + "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" ] diff --git a/.eslintrc.json b/.eslintrc.json index c222fb084..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,24 +19,24 @@ } ] } - ], - "@angular-eslint/no-host-metadata-property": [ - "error", - { - "allowStatic": true - } ] } }, { "files": ["*.ts", "*.tsx"], "extends": ["plugin:@nx/typescript"], - "rules": {} + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off" + } }, { "files": ["*.js", "*.jsx"], "extends": ["plugin:@nx/javascript"], - "rules": {} + "rules": { + "@typescript-eslint/no-extra-semi": "error", + "no-extra-semi": "off" + } }, { "files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"], diff --git a/.github/funding.yml b/.github/funding.yml new file mode 100644 index 000000000..f1327048f --- /dev/null +++ b/.github/funding.yml @@ -0,0 +1 @@ +github: [tomalaforge] diff --git a/.github/github-action/action.yml b/.github/github-action/action.yml new file mode 100644 index 000000000..8019592af --- /dev/null +++ b/.github/github-action/action.yml @@ -0,0 +1,14 @@ +name: 'Hello World' +description: 'Greet someone and record the time' +inputs: + github_token: + description: A GitHub token. + required: false + default: ${{ github.token }} + repo: + description: The owner and repository name. + required: false + default: ${{ github.repository }} +runs: + using: 'node20' + main: 'index.js' diff --git a/.github/github-action/contributors.js b/.github/github-action/contributors.js new file mode 100644 index 000000000..cea002096 --- /dev/null +++ b/.github/github-action/contributors.js @@ -0,0 +1,33 @@ +const contributors = [ + 'alcaidio', + 'svenson95', + 'jdegand', + 'DeveshChau', + 'stillst', + 'wandri', + 'webbomj', + 'kabrunko-dev', + 'Sanjar1304', + 'tsironis13', + 'EnochGao', +]; + +const sponsors = [ + 'ddotx', + 'LMFinney', + 'alannelucq', + 'SidV2', + 'fpalmab', + 'CivilEngeneer', + 'apalaio', + 'amosISA', + 'michalgrzegorczyk-dev', + 'zealotrahl', + 'DzoeL123', + 'allan1989', +]; + +module.exports = { + contributors, + sponsors, +}; diff --git a/.github/github-action/index.js b/.github/github-action/index.js new file mode 100644 index 000000000..a73e6c293 --- /dev/null +++ b/.github/github-action/index.js @@ -0,0 +1,45 @@ +const github = require('@actions/github'); +const core = require('@actions/core'); +const { contributors, sponsors } = require('./contributors'); + +async function run() { + try { + const title = github.context.payload.pull_request.title; + const labels = ['answer']; + + const match = title.match(/Answer(:?)\s*(\d+)/); + if (match) { + labels.push(String(parseInt(match[2], 10))); + } + + const actor = github.context.actor; + if (contributors.includes(actor)) { + labels.push('contributor'); + labels.push('to be reviewed'); + } + + if (sponsors.includes(actor)) { + labels.push('sponsor'); + labels.push('to be reviewed'); + } + + const githubToken = core.getInput('github_token'); + + const number = github.context.payload.pull_request.number; + + const octokit = github.getOctokit(githubToken); + await octokit.rest.issues.addLabels({ + labels, + owner: github.context.repo.owner, + repo: github.context.repo.repo, + issue_number: number, + }); + } catch (e) { + if (e instanceof Error) { + core.error(e); + core.setFailed(e.message); + } + } +} + +run(); diff --git a/.github/workflows/close-inactive-pr.yml b/.github/workflows/close-inactive-pr.yml new file mode 100644 index 000000000..d5e0e9c95 --- /dev/null +++ b/.github/workflows/close-inactive-pr.yml @@ -0,0 +1,28 @@ +name: Close inactive issues +on: + schedule: + - cron: '0 0 * * *' + +jobs: + close-issues: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v9 + with: + days-before-issue-stale: 20 + days-before-issue-close: -1 + 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: 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.' + only-pr-labels: 'answer' + exempt-pr-labels: 'challenge-creation, long-term, to be reviewed' + remove-pr-stale-when-updated: true + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/label-issue-update.yml b/.github/workflows/label-issue-update.yml new file mode 100644 index 000000000..5f79b0568 --- /dev/null +++ b/.github/workflows/label-issue-update.yml @@ -0,0 +1,21 @@ +name: updates Labels + +on: + push: + branches-ignore: + - main + +jobs: + update_labels: + runs-on: ubuntu-latest + if: | + contains(github.event.pull_request.labels.*.name, 'sponsor') || + contains(github.event.pull_request.labels.*.name, 'contributor') + steps: + - name: checkout + uses: actions/checkout@v2 + + - name: Add labels + uses: actions-ecosystem/action-add-labels@v1 + with: + labels: to be reviewed/update diff --git a/.github/workflows/label-issue.yml b/.github/workflows/label-issue.yml new file mode 100644 index 000000000..a5fd40632 --- /dev/null +++ b/.github/workflows/label-issue.yml @@ -0,0 +1,37 @@ +name: Add Labels + +on: + pull_request_target: + 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') }} + steps: + - name: checkout + uses: actions/checkout@v2 + + - name: Install dependencies + run: npm i @actions/core @actions/github + + - name: Add labels + uses: ./.github/github-action/ + with: + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index b0decd9ac..cad0abc01 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,6 @@ node_modules # IDE - VSCode .vscode/* -!.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json @@ -41,4 +40,7 @@ Thumbs.db .angular TODO.md -.nx/cache \ No newline at end of file +.nx/cache +.nx/workspace-data + +.cursorrules \ No newline at end of file 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/.prettierrc b/.prettierrc index dea17d419..810823b36 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,6 @@ { "singleQuote": true, - "bracketSameLine": true + "bracketSameLine": true, + "htmlWhitespaceSensitivity": "ignore", + "plugins": ["prettier-plugin-organize-imports", "prettier-plugin-tailwindcss"] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 1471fb96f..e0a129166 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,6 @@ { - "eslint.validate": ["json"] + "eslint.validate": [ + "json" + ], + "cSpell.language": "en,es-ES" } diff --git a/README.md b/README.md index 747cd700d..2965ecc08 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 39 challenges](https://angular-challenges.vercel.app/) +Check [all 59 challenges](https://angular-challenges.vercel.app/) ## Contributors ✨ @@ -34,18 +34,48 @@ Check [all 39 challenges](https://angular-challenges.vercel.app/) - + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -66,6 +96,8 @@ Check [all 39 challenges](https://angular-challenges.vercel.app/) Contributions of any kind are welcome. -## Licensev +If I have forgotten to add you as a contributor, please reach out to me. 🙏 + +## License MIT diff --git a/apps/angular/projection/.eslintrc.json b/apps/angular/1-projection/.eslintrc.json similarity index 100% rename from apps/angular/projection/.eslintrc.json rename to apps/angular/1-projection/.eslintrc.json diff --git a/apps/angular/1-projection/README.md b/apps/angular/1-projection/README.md new file mode 100644 index 000000000..781198ead --- /dev/null +++ b/apps/angular/1-projection/README.md @@ -0,0 +1,13 @@ +# Projection + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-projection +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/1-projection/). diff --git a/apps/angular/1-projection/jest.config.ts b/apps/angular/1-projection/jest.config.ts new file mode 100644 index 000000000..8eb2510a9 --- /dev/null +++ b/apps/angular/1-projection/jest.config.ts @@ -0,0 +1,23 @@ +/* eslint-disable */ +export default { + displayName: 'angular-projection', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../../coverage/apps/angular/1-projection', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/1-projection/project.json b/apps/angular/1-projection/project.json new file mode 100644 index 000000000..d40912c35 --- /dev/null +++ b/apps/angular/1-projection/project.json @@ -0,0 +1,84 @@ +{ + "name": "angular-projection", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/1-projection/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/1-projection", + "index": "apps/angular/1-projection/src/index.html", + "main": "apps/angular/1-projection/src/main.ts", + "polyfills": ["apps/angular/1-projection/src/polyfills.ts"], + "tsConfig": "apps/angular/1-projection/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/1-projection/src/favicon.ico", + "apps/angular/1-projection/src/assets" + ], + "styles": ["apps/angular/1-projection/src/styles.scss"], + "scripts": [], + "allowedCommonJsDependencies": ["seedrandom"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-projection:build:production" + }, + "development": { + "buildTarget": "angular-projection:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-projection:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/1-projection/src/app/app.component.ts b/apps/angular/1-projection/src/app/app.component.ts new file mode 100644 index 000000000..df654bbc2 --- /dev/null +++ b/apps/angular/1-projection/src/app/app.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { CityCardComponent } from './component/city-card/city-card.component'; +import { StudentCardComponent } from './component/student-card/student-card.component'; +import { TeacherCardComponent } from './component/teacher-card/teacher-card.component'; + +@Component({ + selector: 'app-root', + template: ` +
+ + + +
+ `, + imports: [TeacherCardComponent, StudentCardComponent, CityCardComponent], +}) +export class AppComponent {} diff --git a/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts b/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts new file mode 100644 index 000000000..8895c8c84 --- /dev/null +++ b/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts @@ -0,0 +1,9 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'app-city-card', + template: 'TODO City', + imports: [], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class CityCardComponent {} diff --git a/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts b/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts new file mode 100644 index 000000000..bdfa4abd4 --- /dev/null +++ b/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts @@ -0,0 +1,40 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + OnInit, +} from '@angular/core'; +import { FakeHttpService } from '../../data-access/fake-http.service'; +import { StudentStore } from '../../data-access/student.store'; +import { CardType } from '../../model/card.model'; +import { CardComponent } from '../../ui/card/card.component'; + +@Component({ + selector: 'app-student-card', + template: ` + + `, + styles: [ + ` + ::ng-deep .bg-light-green { + background-color: rgba(0, 250, 0, 0.1); + } + `, + ], + imports: [CardComponent], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class StudentCardComponent implements OnInit { + private http = inject(FakeHttpService); + private store = inject(StudentStore); + + students = this.store.students; + cardType = CardType.STUDENT; + + ngOnInit(): void { + this.http.fetchStudents$.subscribe((s) => this.store.addAll(s)); + } +} diff --git a/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts b/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts new file mode 100644 index 000000000..adf0ad3c1 --- /dev/null +++ b/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts @@ -0,0 +1,34 @@ +import { Component, inject, OnInit } from '@angular/core'; +import { FakeHttpService } from '../../data-access/fake-http.service'; +import { TeacherStore } from '../../data-access/teacher.store'; +import { CardType } from '../../model/card.model'; +import { CardComponent } from '../../ui/card/card.component'; + +@Component({ + selector: 'app-teacher-card', + template: ` + + `, + styles: [ + ` + ::ng-deep .bg-light-red { + background-color: rgba(250, 0, 0, 0.1); + } + `, + ], + imports: [CardComponent], +}) +export class TeacherCardComponent implements OnInit { + private http = inject(FakeHttpService); + private store = inject(TeacherStore); + + teachers = this.store.teachers; + cardType = CardType.TEACHER; + + ngOnInit(): void { + this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t)); + } +} diff --git a/apps/angular/1-projection/src/app/data-access/city.store.ts b/apps/angular/1-projection/src/app/data-access/city.store.ts new file mode 100644 index 000000000..a8b523569 --- /dev/null +++ b/apps/angular/1-projection/src/app/data-access/city.store.ts @@ -0,0 +1,21 @@ +import { Injectable, signal } from '@angular/core'; +import { City } from '../model/city.model'; + +@Injectable({ + providedIn: 'root', +}) +export class CityStore { + private cities = signal([]); + + addAll(cities: City[]) { + this.cities.set(cities); + } + + addOne(city: City) { + this.cities.set([...this.cities(), city]); + } + + deleteOne(id: number) { + this.cities.set(this.cities().filter((s) => s.id !== id)); + } +} diff --git a/apps/angular/projection/src/app/data-access/fake-http.service.ts b/apps/angular/1-projection/src/app/data-access/fake-http.service.ts similarity index 88% rename from apps/angular/projection/src/app/data-access/fake-http.service.ts rename to apps/angular/1-projection/src/app/data-access/fake-http.service.ts index e21ce0336..82a8f1813 100644 --- a/apps/angular/projection/src/app/data-access/fake-http.service.ts +++ b/apps/angular/1-projection/src/app/data-access/fake-http.service.ts @@ -12,14 +12,14 @@ import { import { map, timer } from 'rxjs'; import { City } from '../model/city.model'; import { Student } from '../model/student.model'; -import { subject, Teacher } from '../model/teacher.model'; +import { Teacher, subject } from '../model/teacher.model'; const factoryTeacher = incrementalNumber(); export const randTeacher = () => ({ id: factoryTeacher(), - firstname: randFirstName(), - lastname: randLastName(), + firstName: randFirstName(), + lastName: randLastName(), subject: rand(subject), }); @@ -34,8 +34,8 @@ const factoryStudent = incrementalNumber(); export const randStudent = (): Student => ({ id: factoryStudent(), - firstname: randFirstName(), - lastname: randLastName(), + firstName: randFirstName(), + lastName: randLastName(), mainTeacher: teachers[randNumber({ max: teachers.length - 1 })], school: randWord(), }); diff --git a/apps/angular/1-projection/src/app/data-access/student.store.ts b/apps/angular/1-projection/src/app/data-access/student.store.ts new file mode 100644 index 000000000..6e7f57022 --- /dev/null +++ b/apps/angular/1-projection/src/app/data-access/student.store.ts @@ -0,0 +1,21 @@ +import { Injectable, signal } from '@angular/core'; +import { Student } from '../model/student.model'; + +@Injectable({ + providedIn: 'root', +}) +export class StudentStore { + public students = signal([]); + + addAll(students: Student[]) { + this.students.set(students); + } + + addOne(student: Student) { + this.students.set([...this.students(), student]); + } + + deleteOne(id: number) { + this.students.set(this.students().filter((s) => s.id !== id)); + } +} diff --git a/apps/angular/1-projection/src/app/data-access/teacher.store.ts b/apps/angular/1-projection/src/app/data-access/teacher.store.ts new file mode 100644 index 000000000..5f6dae989 --- /dev/null +++ b/apps/angular/1-projection/src/app/data-access/teacher.store.ts @@ -0,0 +1,21 @@ +import { Injectable, signal } from '@angular/core'; +import { Teacher } from '../model/teacher.model'; + +@Injectable({ + providedIn: 'root', +}) +export class TeacherStore { + public teachers = signal([]); + + addAll(teachers: Teacher[]) { + this.teachers.set(teachers); + } + + addOne(teacher: Teacher) { + this.teachers.set([...this.teachers(), teacher]); + } + + deleteOne(id: number) { + this.teachers.set(this.teachers().filter((t) => t.id !== id)); + } +} diff --git a/apps/angular/projection/src/app/model/card.model.ts b/apps/angular/1-projection/src/app/model/card.model.ts similarity index 100% rename from apps/angular/projection/src/app/model/card.model.ts rename to apps/angular/1-projection/src/app/model/card.model.ts diff --git a/apps/angular/projection/src/app/model/city.model.ts b/apps/angular/1-projection/src/app/model/city.model.ts similarity index 100% rename from apps/angular/projection/src/app/model/city.model.ts rename to apps/angular/1-projection/src/app/model/city.model.ts diff --git a/apps/angular/1-projection/src/app/model/student.model.ts b/apps/angular/1-projection/src/app/model/student.model.ts new file mode 100644 index 000000000..bc18e464a --- /dev/null +++ b/apps/angular/1-projection/src/app/model/student.model.ts @@ -0,0 +1,9 @@ +import { Teacher } from './teacher.model'; + +export interface Student { + id: number; + firstName: string; + lastName: string; + mainTeacher: Teacher; + school: string; +} diff --git a/apps/angular/1-projection/src/app/model/teacher.model.ts b/apps/angular/1-projection/src/app/model/teacher.model.ts new file mode 100644 index 000000000..34b4241be --- /dev/null +++ b/apps/angular/1-projection/src/app/model/teacher.model.ts @@ -0,0 +1,15 @@ +export const subject = [ + 'Sciences', + 'History', + 'English', + 'Maths', + 'Sport', +] as const; +export type Subject = (typeof subject)[number]; + +export interface Teacher { + id: number; + firstName: string; + lastName: string; + subject: Subject; +} diff --git a/apps/angular/1-projection/src/app/ui/card/card.component.ts b/apps/angular/1-projection/src/app/ui/card/card.component.ts new file mode 100644 index 000000000..1a6c3648c --- /dev/null +++ b/apps/angular/1-projection/src/app/ui/card/card.component.ts @@ -0,0 +1,58 @@ +import { NgOptimizedImage } from '@angular/common'; +import { Component, inject, input } from '@angular/core'; +import { randStudent, randTeacher } from '../../data-access/fake-http.service'; +import { StudentStore } from '../../data-access/student.store'; +import { TeacherStore } from '../../data-access/teacher.store'; +import { CardType } from '../../model/card.model'; +import { ListItemComponent } from '../list-item/list-item.component'; + +@Component({ + selector: 'app-card', + template: ` +
+ @if (type() === CardType.TEACHER) { + + } + @if (type() === CardType.STUDENT) { + + } + +
+ @for (item of list(); track item) { + + } +
+ + +
+ `, + imports: [ListItemComponent, NgOptimizedImage], +}) +export class CardComponent { + private teacherStore = inject(TeacherStore); + private studentStore = inject(StudentStore); + + readonly list = input(null); + readonly type = input.required(); + readonly customClass = input(''); + + CardType = CardType; + + addNewItem() { + const type = this.type(); + if (type === CardType.TEACHER) { + this.teacherStore.addOne(randTeacher()); + } else if (type === CardType.STUDENT) { + this.studentStore.addOne(randStudent()); + } + } +} diff --git a/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts b/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts new file mode 100644 index 000000000..cffabb451 --- /dev/null +++ b/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts @@ -0,0 +1,40 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + input, +} from '@angular/core'; +import { StudentStore } from '../../data-access/student.store'; +import { TeacherStore } from '../../data-access/teacher.store'; +import { CardType } from '../../model/card.model'; + +@Component({ + selector: 'app-list-item', + template: ` +
+ {{ name() }} + +
+ `, + standalone: true, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ListItemComponent { + private teacherStore = inject(TeacherStore); + private studentStore = inject(StudentStore); + + readonly id = input.required(); + readonly name = input.required(); + readonly type = input.required(); + + delete(id: number) { + const type = this.type(); + if (type === CardType.TEACHER) { + this.teacherStore.deleteOne(id); + } else if (type === CardType.STUDENT) { + this.studentStore.deleteOne(id); + } + } +} diff --git a/apps/angular/anchor-scrolling/src/assets/.gitkeep b/apps/angular/1-projection/src/assets/.gitkeep similarity index 100% rename from apps/angular/anchor-scrolling/src/assets/.gitkeep rename to apps/angular/1-projection/src/assets/.gitkeep diff --git a/apps/angular/1-projection/src/assets/img/city.png b/apps/angular/1-projection/src/assets/img/city.png new file mode 100644 index 000000000..c600f4455 Binary files /dev/null and b/apps/angular/1-projection/src/assets/img/city.png differ diff --git a/apps/angular/projection/src/assets/img/student.webp b/apps/angular/1-projection/src/assets/img/student.webp similarity index 100% rename from apps/angular/projection/src/assets/img/student.webp rename to apps/angular/1-projection/src/assets/img/student.webp diff --git a/apps/angular/projection/src/assets/img/teacher.png b/apps/angular/1-projection/src/assets/img/teacher.png similarity index 100% rename from apps/angular/projection/src/assets/img/teacher.png rename to apps/angular/1-projection/src/assets/img/teacher.png diff --git a/apps/angular/projection/src/assets/svg/trash.svg b/apps/angular/1-projection/src/assets/svg/trash.svg similarity index 100% rename from apps/angular/projection/src/assets/svg/trash.svg rename to apps/angular/1-projection/src/assets/svg/trash.svg diff --git a/apps/angular/anchor-scrolling/src/favicon.ico b/apps/angular/1-projection/src/favicon.ico similarity index 100% rename from apps/angular/anchor-scrolling/src/favicon.ico rename to apps/angular/1-projection/src/favicon.ico diff --git a/apps/angular/1-projection/src/index.html b/apps/angular/1-projection/src/index.html new file mode 100644 index 000000000..bb9c8bc84 --- /dev/null +++ b/apps/angular/1-projection/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-projection + + + + + + + + diff --git a/apps/angular/context-outlet-type/src/main.ts b/apps/angular/1-projection/src/main.ts similarity index 100% rename from apps/angular/context-outlet-type/src/main.ts rename to apps/angular/1-projection/src/main.ts diff --git a/apps/angular/context-outlet-type/src/polyfills.ts b/apps/angular/1-projection/src/polyfills.ts similarity index 100% rename from apps/angular/context-outlet-type/src/polyfills.ts rename to apps/angular/1-projection/src/polyfills.ts diff --git a/apps/angular/projection/src/styles.scss b/apps/angular/1-projection/src/styles.scss similarity index 100% rename from apps/angular/projection/src/styles.scss rename to apps/angular/1-projection/src/styles.scss diff --git a/apps/angular/anchor-scrolling/src/test-setup.ts b/apps/angular/1-projection/src/test-setup.ts similarity index 100% rename from apps/angular/anchor-scrolling/src/test-setup.ts rename to apps/angular/1-projection/src/test-setup.ts diff --git a/apps/angular/anchor-scrolling/tailwind.config.js b/apps/angular/1-projection/tailwind.config.js similarity index 100% rename from apps/angular/anchor-scrolling/tailwind.config.js rename to apps/angular/1-projection/tailwind.config.js diff --git a/apps/angular/context-outlet-type/tsconfig.app.json b/apps/angular/1-projection/tsconfig.app.json similarity index 100% rename from apps/angular/context-outlet-type/tsconfig.app.json rename to apps/angular/1-projection/tsconfig.app.json diff --git a/apps/angular/projection/tsconfig.editor.json b/apps/angular/1-projection/tsconfig.editor.json similarity index 100% rename from apps/angular/projection/tsconfig.editor.json rename to apps/angular/1-projection/tsconfig.editor.json diff --git a/apps/angular/crud/tsconfig.json b/apps/angular/1-projection/tsconfig.json similarity index 100% rename from apps/angular/crud/tsconfig.json rename to apps/angular/1-projection/tsconfig.json diff --git a/apps/angular/projection/tsconfig.spec.json b/apps/angular/1-projection/tsconfig.spec.json similarity index 100% rename from apps/angular/projection/tsconfig.spec.json rename to apps/angular/1-projection/tsconfig.spec.json diff --git a/apps/angular/crud/.eslintrc.json b/apps/angular/10-utility-wrapper-pipe/.eslintrc.json similarity index 100% rename from apps/angular/crud/.eslintrc.json rename to apps/angular/10-utility-wrapper-pipe/.eslintrc.json diff --git a/apps/angular/10-utility-wrapper-pipe/README.md b/apps/angular/10-utility-wrapper-pipe/README.md new file mode 100644 index 000000000..aac426271 --- /dev/null +++ b/apps/angular/10-utility-wrapper-pipe/README.md @@ -0,0 +1,13 @@ +# Utility Wrapper Pipe + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-utility-wrapper-pipe +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/10-pipe-utility/). diff --git a/apps/angular/10-utility-wrapper-pipe/project.json b/apps/angular/10-utility-wrapper-pipe/project.json new file mode 100644 index 000000000..233fc183d --- /dev/null +++ b/apps/angular/10-utility-wrapper-pipe/project.json @@ -0,0 +1,72 @@ +{ + "name": "angular-utility-wrapper-pipe", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/10-utility-wrapper-pipe/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/10-utility-wrapper-pipe", + "index": "apps/angular/10-utility-wrapper-pipe/src/index.html", + "main": "apps/angular/10-utility-wrapper-pipe/src/main.ts", + "polyfills": "apps/angular/10-utility-wrapper-pipe/src/polyfills.ts", + "tsConfig": "apps/angular/10-utility-wrapper-pipe/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/10-utility-wrapper-pipe/src/favicon.ico", + "apps/angular/10-utility-wrapper-pipe/src/assets" + ], + "styles": ["apps/angular/10-utility-wrapper-pipe/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-utility-wrapper-pipe:build:production" + }, + "development": { + "buildTarget": "angular-utility-wrapper-pipe:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-utility-wrapper-pipe:build" + } + } + } +} diff --git a/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts b/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts new file mode 100644 index 000000000..764d4b9d0 --- /dev/null +++ b/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts @@ -0,0 +1,35 @@ +import { NgFor } from '@angular/common'; +import { Component } from '@angular/core'; +import { PersonUtils } from './person.utils'; + +@Component({ + imports: [NgFor], + selector: 'app-root', + template: ` +
+ {{ activity.name }} : +
+ {{ showName(person.name, index) }} + {{ isAllowed(person.age, isFirst, activity.minimumAge) }} +
+
+ `, +}) +export class AppComponent { + persons = [ + { name: 'Toto', age: 10 }, + { name: 'Jack', age: 15 }, + { name: 'John', age: 30 }, + ]; + + activities = [ + { name: 'biking', minimumAge: 12 }, + { name: 'hiking', minimumAge: 25 }, + { name: 'dancing', minimumAge: 1 }, + ]; + + showName = PersonUtils.showName; + + isAllowed = PersonUtils.isAllowed; +} diff --git a/apps/angular/pipe-hard/src/app/person.utils.ts b/apps/angular/10-utility-wrapper-pipe/src/app/person.utils.ts similarity index 100% rename from apps/angular/pipe-hard/src/app/person.utils.ts rename to apps/angular/10-utility-wrapper-pipe/src/app/person.utils.ts diff --git a/apps/angular/bug-cd/src/assets/.gitkeep b/apps/angular/10-utility-wrapper-pipe/src/assets/.gitkeep similarity index 100% rename from apps/angular/bug-cd/src/assets/.gitkeep rename to apps/angular/10-utility-wrapper-pipe/src/assets/.gitkeep diff --git a/apps/angular/bug-cd/src/favicon.ico b/apps/angular/10-utility-wrapper-pipe/src/favicon.ico similarity index 100% rename from apps/angular/bug-cd/src/favicon.ico rename to apps/angular/10-utility-wrapper-pipe/src/favicon.ico diff --git a/apps/angular/10-utility-wrapper-pipe/src/index.html b/apps/angular/10-utility-wrapper-pipe/src/index.html new file mode 100644 index 000000000..01d31a163 --- /dev/null +++ b/apps/angular/10-utility-wrapper-pipe/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-utility-wrapper-pipe + + + + + + + + diff --git a/apps/angular/decoupling/src/main.ts b/apps/angular/10-utility-wrapper-pipe/src/main.ts similarity index 100% rename from apps/angular/decoupling/src/main.ts rename to apps/angular/10-utility-wrapper-pipe/src/main.ts diff --git a/apps/angular/crud/src/polyfills.ts b/apps/angular/10-utility-wrapper-pipe/src/polyfills.ts similarity index 100% rename from apps/angular/crud/src/polyfills.ts rename to apps/angular/10-utility-wrapper-pipe/src/polyfills.ts diff --git a/apps/angular/context-outlet-type/src/styles.scss b/apps/angular/10-utility-wrapper-pipe/src/styles.scss similarity index 100% rename from apps/angular/context-outlet-type/src/styles.scss rename to apps/angular/10-utility-wrapper-pipe/src/styles.scss diff --git a/apps/angular/crud/tsconfig.app.json b/apps/angular/10-utility-wrapper-pipe/tsconfig.app.json similarity index 100% rename from apps/angular/crud/tsconfig.app.json rename to apps/angular/10-utility-wrapper-pipe/tsconfig.app.json diff --git a/apps/angular/context-outlet-type/tsconfig.editor.json b/apps/angular/10-utility-wrapper-pipe/tsconfig.editor.json similarity index 100% rename from apps/angular/context-outlet-type/tsconfig.editor.json rename to apps/angular/10-utility-wrapper-pipe/tsconfig.editor.json diff --git a/apps/angular/context-outlet-type/tsconfig.json b/apps/angular/10-utility-wrapper-pipe/tsconfig.json similarity index 100% rename from apps/angular/context-outlet-type/tsconfig.json rename to apps/angular/10-utility-wrapper-pipe/tsconfig.json diff --git a/apps/angular/anchor-scrolling/.eslintrc.json b/apps/angular/13-highly-customizable-css/.eslintrc.json similarity index 100% rename from apps/angular/anchor-scrolling/.eslintrc.json rename to apps/angular/13-highly-customizable-css/.eslintrc.json diff --git a/apps/angular/13-highly-customizable-css/README.md b/apps/angular/13-highly-customizable-css/README.md new file mode 100644 index 000000000..d63171ae6 --- /dev/null +++ b/apps/angular/13-highly-customizable-css/README.md @@ -0,0 +1,13 @@ +# Highly Customizable CSS + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-highly-customizable-css +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/13-styling/). diff --git a/apps/angular/13-highly-customizable-css/project.json b/apps/angular/13-highly-customizable-css/project.json new file mode 100644 index 000000000..8bdda5dba --- /dev/null +++ b/apps/angular/13-highly-customizable-css/project.json @@ -0,0 +1,72 @@ +{ + "name": "angular-highly-customizable-css", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/13-highly-customizable-css/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/13-highly-customizable-css", + "index": "apps/angular/13-highly-customizable-css/src/index.html", + "main": "apps/angular/13-highly-customizable-css/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/13-highly-customizable-css/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/13-highly-customizable-css/src/favicon.ico", + "apps/angular/13-highly-customizable-css/src/assets" + ], + "styles": ["apps/angular/13-highly-customizable-css/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-highly-customizable-css:build:production" + }, + "development": { + "buildTarget": "angular-highly-customizable-css:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-highly-customizable-css:build" + } + } + } +} diff --git a/apps/angular/13-highly-customizable-css/src/app/page.component.ts b/apps/angular/13-highly-customizable-css/src/app/page.component.ts new file mode 100644 index 000000000..029ca52d2 --- /dev/null +++ b/apps/angular/13-highly-customizable-css/src/app/page.component.ts @@ -0,0 +1,16 @@ +/* eslint-disable @angular-eslint/component-selector */ +import { Component } from '@angular/core'; +import { TextStaticComponent } from './static-text.component'; +import { TextComponent } from './text.component'; + +@Component({ + selector: 'page', + imports: [TextStaticComponent, TextComponent], + template: ` + + + + This is a blue text + `, +}) +export class PageComponent {} diff --git a/apps/angular/styling/src/app/static-text.component.ts b/apps/angular/13-highly-customizable-css/src/app/static-text.component.ts similarity index 97% rename from apps/angular/styling/src/app/static-text.component.ts rename to apps/angular/13-highly-customizable-css/src/app/static-text.component.ts index cdfd1c19f..70d57d9a3 100644 --- a/apps/angular/styling/src/app/static-text.component.ts +++ b/apps/angular/13-highly-customizable-css/src/app/static-text.component.ts @@ -6,7 +6,6 @@ export type StaticTextType = 'normal' | 'warning' | 'error'; @Component({ selector: 'static-text', - standalone: true, imports: [TextComponent], template: ` This is a static text diff --git a/apps/angular/styling/src/app/text.component.ts b/apps/angular/13-highly-customizable-css/src/app/text.component.ts similarity index 100% rename from apps/angular/styling/src/app/text.component.ts rename to apps/angular/13-highly-customizable-css/src/app/text.component.ts diff --git a/apps/angular/crud/src/assets/.gitkeep b/apps/angular/13-highly-customizable-css/src/assets/.gitkeep similarity index 100% rename from apps/angular/crud/src/assets/.gitkeep rename to apps/angular/13-highly-customizable-css/src/assets/.gitkeep diff --git a/apps/angular/context-outlet-type/src/favicon.ico b/apps/angular/13-highly-customizable-css/src/favicon.ico similarity index 100% rename from apps/angular/context-outlet-type/src/favicon.ico rename to apps/angular/13-highly-customizable-css/src/favicon.ico diff --git a/apps/angular/13-highly-customizable-css/src/index.html b/apps/angular/13-highly-customizable-css/src/index.html new file mode 100644 index 000000000..e4a84b456 --- /dev/null +++ b/apps/angular/13-highly-customizable-css/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-highly-customizable-css + + + + + + + + diff --git a/apps/angular/styling/src/main.ts b/apps/angular/13-highly-customizable-css/src/main.ts similarity index 100% rename from apps/angular/styling/src/main.ts rename to apps/angular/13-highly-customizable-css/src/main.ts diff --git a/apps/angular/ngfor-enhancement/src/styles.scss b/apps/angular/13-highly-customizable-css/src/styles.scss similarity index 100% rename from apps/angular/ngfor-enhancement/src/styles.scss rename to apps/angular/13-highly-customizable-css/src/styles.scss diff --git a/apps/angular/anchor-scrolling/tsconfig.app.json b/apps/angular/13-highly-customizable-css/tsconfig.app.json similarity index 100% rename from apps/angular/anchor-scrolling/tsconfig.app.json rename to apps/angular/13-highly-customizable-css/tsconfig.app.json diff --git a/apps/angular/di/tsconfig.editor.json b/apps/angular/13-highly-customizable-css/tsconfig.editor.json similarity index 100% rename from apps/angular/di/tsconfig.editor.json rename to apps/angular/13-highly-customizable-css/tsconfig.editor.json diff --git a/apps/angular/decoupling/tsconfig.json b/apps/angular/13-highly-customizable-css/tsconfig.json similarity index 100% rename from apps/angular/decoupling/tsconfig.json rename to apps/angular/13-highly-customizable-css/tsconfig.json diff --git a/apps/angular/di/.eslintrc.json b/apps/angular/16-master-dependency-injection/.eslintrc.json similarity index 100% rename from apps/angular/di/.eslintrc.json rename to apps/angular/16-master-dependency-injection/.eslintrc.json diff --git a/apps/angular/16-master-dependency-injection/README.md b/apps/angular/16-master-dependency-injection/README.md new file mode 100644 index 000000000..be19c1ba3 --- /dev/null +++ b/apps/angular/16-master-dependency-injection/README.md @@ -0,0 +1,13 @@ +# Master Dependancy Injection + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-master-dependency-injection +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/16-di/). diff --git a/apps/angular/16-master-dependency-injection/project.json b/apps/angular/16-master-dependency-injection/project.json new file mode 100644 index 000000000..280ed3df4 --- /dev/null +++ b/apps/angular/16-master-dependency-injection/project.json @@ -0,0 +1,74 @@ +{ + "name": "angular-master-dependency-injection", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/16-master-dependency-injection/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/16-master-dependency-injection", + "index": "apps/angular/16-master-dependency-injection/src/index.html", + "main": "apps/angular/16-master-dependency-injection/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/16-master-dependency-injection/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/16-master-dependency-injection/src/favicon.ico", + "apps/angular/16-master-dependency-injection/src/assets" + ], + "styles": [ + "apps/angular/16-master-dependency-injection/src/styles.scss" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-master-dependency-injection:build:production" + }, + "development": { + "buildTarget": "angular-master-dependency-injection:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-master-dependency-injection:build" + } + } + } +} diff --git a/apps/angular/16-master-dependency-injection/src/app/app.component.ts b/apps/angular/16-master-dependency-injection/src/app/app.component.ts new file mode 100644 index 000000000..5bb91c2b2 --- /dev/null +++ b/apps/angular/16-master-dependency-injection/src/app/app.component.ts @@ -0,0 +1,52 @@ +import { TableComponent } from '@angular-challenges/shared/ui'; +import { AsyncPipe, NgFor } from '@angular/common'; +import { Component, Directive } from '@angular/core'; +import { CurrencyPipe } from './currency.pipe'; +import { CurrencyService } from './currency.service'; +import { Product, products } from './product.model'; + +interface ProductContext { + $implicit: Product; +} + +@Directive({ + selector: 'ng-template[product]', + standalone: true, +}) +export class ProductDirective { + static ngTemplateContextGuard( + dir: ProductDirective, + ctx: unknown, + ): ctx is ProductContext { + return true; + } +} + +@Component({ + imports: [TableComponent, CurrencyPipe, AsyncPipe, NgFor, ProductDirective], + providers: [CurrencyService], + selector: 'app-root', + template: ` +
Laforge Thomas
Laforge Thomas

🧩 💻 📖 🖋 🤔 🎨
Laforge Thomas
Laforge Thomas

🧩 💻 📖 🖋 🤔 🎨 🇫🇷
Sven Brodny
Sven Brodny

📖 🧩 🖋 🎨
J. Degand
J. Degand

📖 🖋 💻
Devesh Chaudhari
Devesh Chaudhari

💻 🐛 🧩
stillst
stillst

🧩 🇷🇺
Wandrille
Wandrille

🧩
Timothy Alcaide
Timothy Alcaide

🧩
Lance Finney
Lance Finney

📖 🧩
Tsironis Ioannis
Tsironis Ioannis

🧩
Alan Dragicevich
Alan Dragicevich

📖
Michel EDIGHOFFER
Michel EDIGHOFFER

📖
Gerardo Sebastian Gonzalez
Gerardo Sebastian Gonzalez

📖
Evseev Yuriy
Evseev Yuriy

🐛
Tomer953
Tomer953

🐛 📖 💻
J. Degand
J. Degand

📖
Devesh Chaudhari
Devesh Chaudhari

💻 🐛 🧩
Dmitriy Mishchenko
Dmitriy Mishchenko

📖
Sagar Devkota
Sagar Devkota

📖
Sagar Devkota
Sagar Devkota

📖 💻
Nelson Gutierrez
Nelson Gutierrez

🇪🇸
Hossain K. M.
Hossain K. M.

📖
Diogo Nishikawa
Diogo Nishikawa

💻 🇵🇹 📖
Erick Rodriguez
Erick Rodriguez

🇪🇸
Eduardo Roth
Eduardo Roth

📖 🇪🇸
Fernando Bello
Fernando Bello

📖
Лапин Андрей (Lapin Andrey)
Лапин Андрей (Lapin Andrey)

🇷🇺
Dinar Shagaliev
Dinar Shagaliev

🇷🇺
Vimulatus
Vimulatus

📖
Arthur LANNELUCQ
Arthur LANNELUCQ

🇫🇷
fixed_michal
fixed_michal

🐛
Tenessy
Tenessy

🐛
Enoch Gao
Enoch Gao

📖 🇨🇳
Francisco Palma
Francisco Palma

🐛
Michał Grzegorczyk
Michał Grzegorczyk

📖
Tamim Arefin Anik
Tamim Arefin Anik

🐛
Matheus B.
Matheus B.

🐛
Stef Heyenrath
Stef Heyenrath

📖
+ + + + + + + + + + + + + +
+ {{ col }} +
{{ product.name }}{{ product.priceA | currency | async }}{{ product.priceB | currency | async }}{{ product.priceC | currency | async }}
+ `, +}) +export class AppComponent { + products = products; + displayedColumns = ['name', 'priceA', 'priceB', 'priceC']; +} diff --git a/apps/angular/16-master-dependency-injection/src/app/currency.pipe.ts b/apps/angular/16-master-dependency-injection/src/app/currency.pipe.ts new file mode 100644 index 000000000..9d90e52f1 --- /dev/null +++ b/apps/angular/16-master-dependency-injection/src/app/currency.pipe.ts @@ -0,0 +1,17 @@ +import { inject, Pipe, PipeTransform } from '@angular/core'; +import { map } from 'rxjs'; +import { CurrencyService } from './currency.service'; + +@Pipe({ + name: 'currency', + standalone: true, +}) +export class CurrencyPipe implements PipeTransform { + currencyService = inject(CurrencyService); + + transform(price: number) { + return this.currencyService.symbol$.pipe( + map((s) => `${String(price)}${s}`), + ); + } +} diff --git a/apps/angular/16-master-dependency-injection/src/app/currency.service.ts b/apps/angular/16-master-dependency-injection/src/app/currency.service.ts new file mode 100644 index 000000000..38b403e48 --- /dev/null +++ b/apps/angular/16-master-dependency-injection/src/app/currency.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { ComponentStore } from '@ngrx/component-store'; +import { map } from 'rxjs'; + +export interface Currency { + name: string; + code: string; + symbol: string; +} + +export const currency: Currency[] = [ + { name: 'Euro', code: 'EUR', symbol: '€' }, + { name: 'Dollar US', code: 'USD', symbol: 'US$' }, + { name: 'Dollar Autralien', code: 'AUD', symbol: 'AU$' }, + { name: 'Livre Sterling', code: 'GBP', symbol: '£' }, + { name: 'Dollar Canadien', code: 'CAD', symbol: 'CAD' }, +]; + +@Injectable() +export class CurrencyService extends ComponentStore<{ code: string }> { + readonly code$ = this.select((state) => state.code); + readonly symbol$ = this.code$.pipe( + map((code) => currency.find((c) => c.code === code)?.symbol ?? code), + ); + + constructor() { + super({ code: 'EUR' }); + } +} diff --git a/apps/angular/di/src/app/product.model.ts b/apps/angular/16-master-dependency-injection/src/app/product.model.ts similarity index 100% rename from apps/angular/di/src/app/product.model.ts rename to apps/angular/16-master-dependency-injection/src/app/product.model.ts diff --git a/apps/angular/decoupling/src/assets/.gitkeep b/apps/angular/16-master-dependency-injection/src/assets/.gitkeep similarity index 100% rename from apps/angular/decoupling/src/assets/.gitkeep rename to apps/angular/16-master-dependency-injection/src/assets/.gitkeep diff --git a/apps/angular/crud/src/favicon.ico b/apps/angular/16-master-dependency-injection/src/favicon.ico similarity index 100% rename from apps/angular/crud/src/favicon.ico rename to apps/angular/16-master-dependency-injection/src/favicon.ico diff --git a/apps/angular/16-master-dependency-injection/src/index.html b/apps/angular/16-master-dependency-injection/src/index.html new file mode 100644 index 000000000..be35bf8c8 --- /dev/null +++ b/apps/angular/16-master-dependency-injection/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-master-dependancy-injection + + + + + + + + diff --git a/apps/angular/di/src/main.ts b/apps/angular/16-master-dependency-injection/src/main.ts similarity index 100% rename from apps/angular/di/src/main.ts rename to apps/angular/16-master-dependency-injection/src/main.ts diff --git a/apps/angular/di/src/styles.scss b/apps/angular/16-master-dependency-injection/src/styles.scss similarity index 100% rename from apps/angular/di/src/styles.scss rename to apps/angular/16-master-dependency-injection/src/styles.scss diff --git a/apps/angular/bug-cd/tsconfig.app.json b/apps/angular/16-master-dependency-injection/tsconfig.app.json similarity index 100% rename from apps/angular/bug-cd/tsconfig.app.json rename to apps/angular/16-master-dependency-injection/tsconfig.app.json diff --git a/apps/angular/router-input/tsconfig.editor.json b/apps/angular/16-master-dependency-injection/tsconfig.editor.json similarity index 100% rename from apps/angular/router-input/tsconfig.editor.json rename to apps/angular/16-master-dependency-injection/tsconfig.editor.json diff --git a/apps/angular/di/tsconfig.json b/apps/angular/16-master-dependency-injection/tsconfig.json similarity index 100% rename from apps/angular/di/tsconfig.json rename to apps/angular/16-master-dependency-injection/tsconfig.json diff --git a/apps/angular/bug-cd/.eslintrc.json b/apps/angular/21-anchor-navigation/.eslintrc.json similarity index 100% rename from apps/angular/bug-cd/.eslintrc.json rename to apps/angular/21-anchor-navigation/.eslintrc.json diff --git a/apps/angular/21-anchor-navigation/README.md b/apps/angular/21-anchor-navigation/README.md new file mode 100644 index 000000000..3683899ba --- /dev/null +++ b/apps/angular/21-anchor-navigation/README.md @@ -0,0 +1,13 @@ +# Anchor Navigation + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-anchor-navigation +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/21-achor-scrolling/). diff --git a/apps/angular/21-anchor-navigation/jest.config.ts b/apps/angular/21-anchor-navigation/jest.config.ts new file mode 100644 index 000000000..7347f70b5 --- /dev/null +++ b/apps/angular/21-anchor-navigation/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'anchor-navigation-anchor-navigation', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/21-anchor-navigation', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/21-anchor-navigation/project.json b/apps/angular/21-anchor-navigation/project.json new file mode 100644 index 000000000..b8ba74b04 --- /dev/null +++ b/apps/angular/21-anchor-navigation/project.json @@ -0,0 +1,83 @@ +{ + "name": "angular-anchor-navigation", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/21-anchor-navigation/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/21-anchor-navigation", + "index": "apps/angular/21-anchor-navigation/src/index.html", + "main": "apps/angular/21-anchor-navigation/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/21-anchor-navigation/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/21-anchor-navigation/src/favicon.ico", + "apps/angular/21-anchor-navigation/src/assets" + ], + "styles": ["apps/angular/21-anchor-navigation/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-anchor-navigation:build:production" + }, + "development": { + "buildTarget": "angular-anchor-navigation:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-anchor-navigation:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/21-anchor-navigation/src/app/app.component.ts b/apps/angular/21-anchor-navigation/src/app/app.component.ts new file mode 100644 index 000000000..5caca0271 --- /dev/null +++ b/apps/angular/21-anchor-navigation/src/app/app.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet], + selector: 'app-root', + template: ` + + `, +}) +export class AppComponent {} diff --git a/apps/angular/anchor-scrolling/src/app/app.config.ts b/apps/angular/21-anchor-navigation/src/app/app.config.ts similarity index 100% rename from apps/angular/anchor-scrolling/src/app/app.config.ts rename to apps/angular/21-anchor-navigation/src/app/app.config.ts diff --git a/apps/angular/anchor-scrolling/src/app/app.routes.ts b/apps/angular/21-anchor-navigation/src/app/app.routes.ts similarity index 100% rename from apps/angular/anchor-scrolling/src/app/app.routes.ts rename to apps/angular/21-anchor-navigation/src/app/app.routes.ts diff --git a/apps/angular/21-anchor-navigation/src/app/foo.component.ts b/apps/angular/21-anchor-navigation/src/app/foo.component.ts new file mode 100644 index 000000000..6744c3662 --- /dev/null +++ b/apps/angular/21-anchor-navigation/src/app/foo.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { NavButtonComponent } from './nav-button.component'; + +@Component({ + imports: [NavButtonComponent], + selector: 'app-foo', + template: ` + Welcome to foo page + Home Page +
section 1
+
section 2
+ `, +}) +export class FooComponent {} diff --git a/apps/angular/21-anchor-navigation/src/app/home.component.ts b/apps/angular/21-anchor-navigation/src/app/home.component.ts new file mode 100644 index 000000000..6ef9bc2b6 --- /dev/null +++ b/apps/angular/21-anchor-navigation/src/app/home.component.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { NavButtonComponent } from './nav-button.component'; + +@Component({ + imports: [NavButtonComponent], + selector: 'app-home', + template: ` + Foo Page +
+ Empty + Scroll Bottom +
+
+ I want to scroll each + Scroll Top +
+ `, +}) +export class HomeComponent {} diff --git a/apps/angular/anchor-scrolling/src/app/nav-button.component.ts b/apps/angular/21-anchor-navigation/src/app/nav-button.component.ts similarity index 100% rename from apps/angular/anchor-scrolling/src/app/nav-button.component.ts rename to apps/angular/21-anchor-navigation/src/app/nav-button.component.ts diff --git a/apps/angular/di/src/assets/.gitkeep b/apps/angular/21-anchor-navigation/src/assets/.gitkeep similarity index 100% rename from apps/angular/di/src/assets/.gitkeep rename to apps/angular/21-anchor-navigation/src/assets/.gitkeep diff --git a/apps/angular/decoupling/src/favicon.ico b/apps/angular/21-anchor-navigation/src/favicon.ico similarity index 100% rename from apps/angular/decoupling/src/favicon.ico rename to apps/angular/21-anchor-navigation/src/favicon.ico diff --git a/apps/angular/21-anchor-navigation/src/index.html b/apps/angular/21-anchor-navigation/src/index.html new file mode 100644 index 000000000..06a706a0a --- /dev/null +++ b/apps/angular/21-anchor-navigation/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-anchor-navigation + + + + + + + + diff --git a/apps/angular/21-anchor-navigation/src/main.ts b/apps/angular/21-anchor-navigation/src/main.ts new file mode 100644 index 000000000..7961924bf --- /dev/null +++ b/apps/angular/21-anchor-navigation/src/main.ts @@ -0,0 +1,8 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; + +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/anchor-scrolling/src/styles.scss b/apps/angular/21-anchor-navigation/src/styles.scss similarity index 100% rename from apps/angular/anchor-scrolling/src/styles.scss rename to apps/angular/21-anchor-navigation/src/styles.scss diff --git a/apps/angular/projection/src/test-setup.ts b/apps/angular/21-anchor-navigation/src/test-setup.ts similarity index 100% rename from apps/angular/projection/src/test-setup.ts rename to apps/angular/21-anchor-navigation/src/test-setup.ts diff --git a/apps/angular/bug-cd/tailwind.config.js b/apps/angular/21-anchor-navigation/tailwind.config.js similarity index 100% rename from apps/angular/bug-cd/tailwind.config.js rename to apps/angular/21-anchor-navigation/tailwind.config.js diff --git a/apps/angular/decoupling/tsconfig.app.json b/apps/angular/21-anchor-navigation/tsconfig.app.json similarity index 100% rename from apps/angular/decoupling/tsconfig.app.json rename to apps/angular/21-anchor-navigation/tsconfig.app.json diff --git a/apps/angular/anchor-scrolling/tsconfig.editor.json b/apps/angular/21-anchor-navigation/tsconfig.editor.json similarity index 100% rename from apps/angular/anchor-scrolling/tsconfig.editor.json rename to apps/angular/21-anchor-navigation/tsconfig.editor.json diff --git a/apps/angular/anchor-scrolling/tsconfig.json b/apps/angular/21-anchor-navigation/tsconfig.json similarity index 100% rename from apps/angular/anchor-scrolling/tsconfig.json rename to apps/angular/21-anchor-navigation/tsconfig.json diff --git a/apps/angular/anchor-scrolling/tsconfig.spec.json b/apps/angular/21-anchor-navigation/tsconfig.spec.json similarity index 100% rename from apps/angular/anchor-scrolling/tsconfig.spec.json rename to apps/angular/21-anchor-navigation/tsconfig.spec.json diff --git a/apps/angular/decoupling/.eslintrc.json b/apps/angular/22-router-input/.eslintrc.json similarity index 100% rename from apps/angular/decoupling/.eslintrc.json rename to apps/angular/22-router-input/.eslintrc.json diff --git a/apps/angular/22-router-input/README.md b/apps/angular/22-router-input/README.md new file mode 100644 index 000000000..0aad6c326 --- /dev/null +++ b/apps/angular/22-router-input/README.md @@ -0,0 +1,13 @@ +# @RouterInput() + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-router-input +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/22-router-input/). diff --git a/apps/angular/22-router-input/project.json b/apps/angular/22-router-input/project.json new file mode 100644 index 000000000..58cd889c5 --- /dev/null +++ b/apps/angular/22-router-input/project.json @@ -0,0 +1,71 @@ +{ + "name": "angular-router-input", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/22-router-input/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/22-router-input", + "index": "apps/angular/22-router-input/src/index.html", + "main": "apps/angular/22-router-input/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/22-router-input/tsconfig.app.json", + "assets": [ + "apps/angular/22-router-input/src/favicon.ico", + "apps/angular/22-router-input/src/assets" + ], + "styles": ["apps/angular/22-router-input/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-router-input:build:production" + }, + "development": { + "buildTarget": "angular-router-input:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-router-input:build" + } + } + } +} diff --git a/apps/angular/22-router-input/src/app/app.component.ts b/apps/angular/22-router-input/src/app/app.component.ts new file mode 100644 index 000000000..9dfc11200 --- /dev/null +++ b/apps/angular/22-router-input/src/app/app.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { RouterLink, RouterModule } from '@angular/router'; + +@Component({ + imports: [RouterLink, RouterModule, ReactiveFormsModule], + selector: 'app-root', + template: ` + + + + + + + + `, +}) +export class AppComponent { + userName = new FormControl(); + testId = new FormControl(); +} diff --git a/apps/angular/router-input/src/app/app.config.ts b/apps/angular/22-router-input/src/app/app.config.ts similarity index 100% rename from apps/angular/router-input/src/app/app.config.ts rename to apps/angular/22-router-input/src/app/app.config.ts diff --git a/apps/angular/22-router-input/src/app/app.routes.ts b/apps/angular/22-router-input/src/app/app.routes.ts new file mode 100644 index 000000000..f5d3487c4 --- /dev/null +++ b/apps/angular/22-router-input/src/app/app.routes.ts @@ -0,0 +1,15 @@ +import { Route } from '@angular/router'; + +export const appRoutes: Route[] = [ + { + path: '', + loadComponent: () => import('./home.component'), + }, + { + path: 'subscription/:testId', + loadComponent: () => import('./test.component'), + data: { + permission: 'admin', + }, + }, +]; diff --git a/apps/angular/22-router-input/src/app/home.component.ts b/apps/angular/22-router-input/src/app/home.component.ts new file mode 100644 index 000000000..0ddc1501d --- /dev/null +++ b/apps/angular/22-router-input/src/app/home.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; +@Component({ + selector: 'app-home', + imports: [], + template: ` +
Home
+ `, +}) +export default class HomeComponent {} diff --git a/apps/angular/router-input/src/app/test.component.ts b/apps/angular/22-router-input/src/app/test.component.ts similarity index 93% rename from apps/angular/router-input/src/app/test.component.ts rename to apps/angular/22-router-input/src/app/test.component.ts index 56ac3f722..747ab4483 100644 --- a/apps/angular/router-input/src/app/test.component.ts +++ b/apps/angular/22-router-input/src/app/test.component.ts @@ -2,9 +2,9 @@ import { AsyncPipe } from '@angular/common'; import { Component, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { map } from 'rxjs'; + @Component({ - selector: 'app-test', - standalone: true, + selector: 'app-subscription', imports: [AsyncPipe], template: `
TestId: {{ testId$ | async }}
diff --git a/apps/angular/injection-token/src/assets/.gitkeep b/apps/angular/22-router-input/src/assets/.gitkeep similarity index 100% rename from apps/angular/injection-token/src/assets/.gitkeep rename to apps/angular/22-router-input/src/assets/.gitkeep diff --git a/apps/angular/di/src/favicon.ico b/apps/angular/22-router-input/src/favicon.ico similarity index 100% rename from apps/angular/di/src/favicon.ico rename to apps/angular/22-router-input/src/favicon.ico diff --git a/apps/angular/22-router-input/src/index.html b/apps/angular/22-router-input/src/index.html new file mode 100644 index 000000000..30e74f7b4 --- /dev/null +++ b/apps/angular/22-router-input/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-router-input + + + + + + + + diff --git a/apps/angular/22-router-input/src/main.ts b/apps/angular/22-router-input/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/22-router-input/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/pipe-easy/src/styles.scss b/apps/angular/22-router-input/src/styles.scss similarity index 100% rename from apps/angular/pipe-easy/src/styles.scss rename to apps/angular/22-router-input/src/styles.scss diff --git a/apps/angular/di/tsconfig.app.json b/apps/angular/22-router-input/tsconfig.app.json similarity index 100% rename from apps/angular/di/tsconfig.app.json rename to apps/angular/22-router-input/tsconfig.app.json diff --git a/apps/angular/styling/tsconfig.editor.json b/apps/angular/22-router-input/tsconfig.editor.json similarity index 100% rename from apps/angular/styling/tsconfig.editor.json rename to apps/angular/22-router-input/tsconfig.editor.json diff --git a/apps/angular/module-to-standalone/tsconfig.json b/apps/angular/22-router-input/tsconfig.json similarity index 100% rename from apps/angular/module-to-standalone/tsconfig.json rename to apps/angular/22-router-input/tsconfig.json diff --git a/apps/angular/ngfor-enhancement/.eslintrc.json b/apps/angular/3-directive-enhancement/.eslintrc.json similarity index 100% rename from apps/angular/ngfor-enhancement/.eslintrc.json rename to apps/angular/3-directive-enhancement/.eslintrc.json diff --git a/apps/angular/3-directive-enhancement/README.md b/apps/angular/3-directive-enhancement/README.md new file mode 100644 index 000000000..f89eb48bd --- /dev/null +++ b/apps/angular/3-directive-enhancement/README.md @@ -0,0 +1,13 @@ +# Directive Enhancement + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-directive-enhancement +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/3-directive-enhancement/). diff --git a/apps/angular/3-directive-enhancement/project.json b/apps/angular/3-directive-enhancement/project.json new file mode 100644 index 000000000..f16c4d7a1 --- /dev/null +++ b/apps/angular/3-directive-enhancement/project.json @@ -0,0 +1,72 @@ +{ + "name": "angular-directive-enhancement", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/3-directive-enhancement/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/3-directive-enhancement", + "index": "apps/angular/3-directive-enhancement/src/index.html", + "main": "apps/angular/3-directive-enhancement/src/main.ts", + "polyfills": "apps/angular/3-directive-enhancement/src/polyfills.ts", + "tsConfig": "apps/angular/3-directive-enhancement/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/3-directive-enhancement/src/favicon.ico", + "apps/angular/3-directive-enhancement/src/assets" + ], + "styles": ["apps/angular/3-directive-enhancement/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-directive-enhancement:build:production" + }, + "development": { + "buildTarget": "angular-directive-enhancement:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-directive-enhancement:build" + } + } + } +} diff --git a/apps/angular/3-directive-enhancement/src/app/app.component.ts b/apps/angular/3-directive-enhancement/src/app/app.component.ts new file mode 100644 index 000000000..8d37369a1 --- /dev/null +++ b/apps/angular/3-directive-enhancement/src/app/app.component.ts @@ -0,0 +1,24 @@ +import { NgFor, NgIf } from '@angular/common'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +interface Person { + name: string; +} + +@Component({ + imports: [NgFor, NgIf], + selector: 'app-root', + template: ` + +
+ {{ person.name }} +
+
+ The list is empty !! + `, + styles: [], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent { + persons: Person[] = []; +} diff --git a/apps/angular/interop-rxjs-signal/src/assets/.gitkeep b/apps/angular/3-directive-enhancement/src/assets/.gitkeep similarity index 100% rename from apps/angular/interop-rxjs-signal/src/assets/.gitkeep rename to apps/angular/3-directive-enhancement/src/assets/.gitkeep diff --git a/apps/angular/injection-token/src/favicon.ico b/apps/angular/3-directive-enhancement/src/favicon.ico similarity index 100% rename from apps/angular/injection-token/src/favicon.ico rename to apps/angular/3-directive-enhancement/src/favicon.ico diff --git a/apps/angular/3-directive-enhancement/src/index.html b/apps/angular/3-directive-enhancement/src/index.html new file mode 100644 index 000000000..28def4ef2 --- /dev/null +++ b/apps/angular/3-directive-enhancement/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-directive-enhancement + + + + + + + + diff --git a/apps/angular/ngfor-enhancement/src/main.ts b/apps/angular/3-directive-enhancement/src/main.ts similarity index 100% rename from apps/angular/ngfor-enhancement/src/main.ts rename to apps/angular/3-directive-enhancement/src/main.ts diff --git a/apps/angular/ngfor-enhancement/src/polyfills.ts b/apps/angular/3-directive-enhancement/src/polyfills.ts similarity index 100% rename from apps/angular/ngfor-enhancement/src/polyfills.ts rename to apps/angular/3-directive-enhancement/src/polyfills.ts diff --git a/apps/angular/pipe-hard/src/styles.scss b/apps/angular/3-directive-enhancement/src/styles.scss similarity index 100% rename from apps/angular/pipe-hard/src/styles.scss rename to apps/angular/3-directive-enhancement/src/styles.scss diff --git a/apps/angular/ngfor-enhancement/tsconfig.app.json b/apps/angular/3-directive-enhancement/tsconfig.app.json similarity index 100% rename from apps/angular/ngfor-enhancement/tsconfig.app.json rename to apps/angular/3-directive-enhancement/tsconfig.app.json diff --git a/apps/angular/crud/tsconfig.editor.json b/apps/angular/3-directive-enhancement/tsconfig.editor.json similarity index 100% rename from apps/angular/crud/tsconfig.editor.json rename to apps/angular/3-directive-enhancement/tsconfig.editor.json diff --git a/apps/angular/ngfor-enhancement/tsconfig.json b/apps/angular/3-directive-enhancement/tsconfig.json similarity index 100% rename from apps/angular/ngfor-enhancement/tsconfig.json rename to apps/angular/3-directive-enhancement/tsconfig.json diff --git a/apps/angular/interop-rxjs-signal/.eslintrc.json b/apps/angular/31-module-to-standalone/.eslintrc.json similarity index 100% rename from apps/angular/interop-rxjs-signal/.eslintrc.json rename to apps/angular/31-module-to-standalone/.eslintrc.json diff --git a/apps/angular/31-module-to-standalone/README.md b/apps/angular/31-module-to-standalone/README.md new file mode 100644 index 000000000..bd227b7a2 --- /dev/null +++ b/apps/angular/31-module-to-standalone/README.md @@ -0,0 +1,13 @@ +# Module to Standalone + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-module-to-standalone +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/31-module-to-standalone/). diff --git a/apps/angular/31-module-to-standalone/project.json b/apps/angular/31-module-to-standalone/project.json new file mode 100644 index 000000000..c1a51b5ed --- /dev/null +++ b/apps/angular/31-module-to-standalone/project.json @@ -0,0 +1,71 @@ +{ + "name": "angular-module-to-standalone", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/31-module-to-standalone/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/31-module-to-standalone", + "index": "apps/angular/31-module-to-standalone/src/index.html", + "main": "apps/angular/31-module-to-standalone/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/31-module-to-standalone/tsconfig.app.json", + "assets": [ + "apps/angular/31-module-to-standalone/src/favicon.ico", + "apps/angular/31-module-to-standalone/src/assets" + ], + "styles": ["apps/angular/31-module-to-standalone/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-module-to-standalone:build:production" + }, + "development": { + "buildTarget": "angular-module-to-standalone:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-module-to-standalone:build" + } + } + } +} diff --git a/apps/angular/31-module-to-standalone/src/app/app.component.ts b/apps/angular/31-module-to-standalone/src/app/app.component.ts new file mode 100644 index 000000000..986df84b5 --- /dev/null +++ b/apps/angular/31-module-to-standalone/src/app/app.component.ts @@ -0,0 +1,30 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + template: ` +
+ + + +
+ + `, + host: { + class: 'flex flex-col p-4 gap-3', + }, + standalone: false, +}) +export class AppComponent {} diff --git a/apps/angular/module-to-standalone/src/app/app.module.ts b/apps/angular/31-module-to-standalone/src/app/app.module.ts similarity index 100% rename from apps/angular/module-to-standalone/src/app/app.module.ts rename to apps/angular/31-module-to-standalone/src/app/app.module.ts diff --git a/apps/angular/module-to-standalone/src/assets/.gitkeep b/apps/angular/31-module-to-standalone/src/assets/.gitkeep similarity index 100% rename from apps/angular/module-to-standalone/src/assets/.gitkeep rename to apps/angular/31-module-to-standalone/src/assets/.gitkeep diff --git a/apps/angular/interop-rxjs-signal/src/favicon.ico b/apps/angular/31-module-to-standalone/src/favicon.ico similarity index 100% rename from apps/angular/interop-rxjs-signal/src/favicon.ico rename to apps/angular/31-module-to-standalone/src/favicon.ico diff --git a/apps/angular/31-module-to-standalone/src/index.html b/apps/angular/31-module-to-standalone/src/index.html new file mode 100644 index 000000000..fe0d5b978 --- /dev/null +++ b/apps/angular/31-module-to-standalone/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-module-to-standalone + + + + + + + + diff --git a/apps/angular/module-to-standalone/src/main.ts b/apps/angular/31-module-to-standalone/src/main.ts similarity index 100% rename from apps/angular/module-to-standalone/src/main.ts rename to apps/angular/31-module-to-standalone/src/main.ts diff --git a/apps/angular/bug-cd/src/styles.scss b/apps/angular/31-module-to-standalone/src/styles.scss similarity index 100% rename from apps/angular/bug-cd/src/styles.scss rename to apps/angular/31-module-to-standalone/src/styles.scss diff --git a/apps/angular/module-to-standalone/tailwind.config.js b/apps/angular/31-module-to-standalone/tailwind.config.js similarity index 100% rename from apps/angular/module-to-standalone/tailwind.config.js rename to apps/angular/31-module-to-standalone/tailwind.config.js diff --git a/apps/angular/injection-token/tsconfig.app.json b/apps/angular/31-module-to-standalone/tsconfig.app.json similarity index 100% rename from apps/angular/injection-token/tsconfig.app.json rename to apps/angular/31-module-to-standalone/tsconfig.app.json diff --git a/apps/angular/module-to-standalone/tsconfig.editor.json b/apps/angular/31-module-to-standalone/tsconfig.editor.json similarity index 100% rename from apps/angular/module-to-standalone/tsconfig.editor.json rename to apps/angular/31-module-to-standalone/tsconfig.editor.json diff --git a/apps/angular/router-input/tsconfig.json b/apps/angular/31-module-to-standalone/tsconfig.json similarity index 100% rename from apps/angular/router-input/tsconfig.json rename to apps/angular/31-module-to-standalone/tsconfig.json diff --git a/apps/angular/module-to-standalone/.eslintrc.json b/apps/angular/32-change-detection-bug/.eslintrc.json similarity index 100% rename from apps/angular/module-to-standalone/.eslintrc.json rename to apps/angular/32-change-detection-bug/.eslintrc.json diff --git a/apps/angular/32-change-detection-bug/README.md b/apps/angular/32-change-detection-bug/README.md new file mode 100644 index 000000000..41e533388 --- /dev/null +++ b/apps/angular/32-change-detection-bug/README.md @@ -0,0 +1,13 @@ +# Change Detection Bug + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-change-detection-bug +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/32-bug-cd/). diff --git a/apps/angular/32-change-detection-bug/jest.config.ts b/apps/angular/32-change-detection-bug/jest.config.ts new file mode 100644 index 000000000..d0412f028 --- /dev/null +++ b/apps/angular/32-change-detection-bug/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'angular-change-detection-bug', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/32-change-detection-bug', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/32-change-detection-bug/project.json b/apps/angular/32-change-detection-bug/project.json new file mode 100644 index 000000000..48eb9ef1e --- /dev/null +++ b/apps/angular/32-change-detection-bug/project.json @@ -0,0 +1,82 @@ +{ + "name": "angular-change-detection-bug", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/32-change-detection-bug/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/32-change-detection-bug", + "index": "apps/angular/32-change-detection-bug/src/index.html", + "main": "apps/angular/32-change-detection-bug/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/32-change-detection-bug/tsconfig.app.json", + "assets": [ + "apps/angular/32-change-detection-bug/src/favicon.ico", + "apps/angular/32-change-detection-bug/src/assets" + ], + "styles": ["apps/angular/32-change-detection-bug/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-change-detection-bug:build:production" + }, + "development": { + "buildTarget": "angular-change-detection-bug:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-change-detection-bug:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/32-change-detection-bug/src/app/app.component.ts b/apps/angular/32-change-detection-bug/src/app/app.component.ts new file mode 100644 index 000000000..217999c3a --- /dev/null +++ b/apps/angular/32-change-detection-bug/src/app/app.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet], + selector: 'app-root', + template: ` +

My Application

+
+ +
+ +
+
+ `, + host: { + class: 'flex flex-col gap-2', + }, +}) +export class AppComponent {} diff --git a/apps/angular/bug-cd/src/app/app.config.ts b/apps/angular/32-change-detection-bug/src/app/app.config.ts similarity index 100% rename from apps/angular/bug-cd/src/app/app.config.ts rename to apps/angular/32-change-detection-bug/src/app/app.config.ts diff --git a/apps/angular/bug-cd/src/app/bar.component.ts b/apps/angular/32-change-detection-bug/src/app/bar.component.ts similarity index 78% rename from apps/angular/bug-cd/src/app/bar.component.ts rename to apps/angular/32-change-detection-bug/src/app/bar.component.ts index 26eef1e5e..b7a53924e 100644 --- a/apps/angular/bug-cd/src/app/bar.component.ts +++ b/apps/angular/32-change-detection-bug/src/app/bar.component.ts @@ -2,6 +2,8 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-bar', standalone: true, - template: ` BarComponent `, + template: ` + BarComponent + `, }) export class BarComponent {} diff --git a/apps/angular/bug-cd/src/app/fake.service.ts b/apps/angular/32-change-detection-bug/src/app/fake.service.ts similarity index 100% rename from apps/angular/bug-cd/src/app/fake.service.ts rename to apps/angular/32-change-detection-bug/src/app/fake.service.ts diff --git a/apps/angular/32-change-detection-bug/src/app/foo.component.ts b/apps/angular/32-change-detection-bug/src/app/foo.component.ts new file mode 100644 index 000000000..a5b1207b1 --- /dev/null +++ b/apps/angular/32-change-detection-bug/src/app/foo.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; +@Component({ + selector: 'app-foo', + standalone: true, + template: ` + Foo Component + `, +}) +export class FooComponent {} diff --git a/apps/angular/bug-cd/src/app/main-navigation.component.ts b/apps/angular/32-change-detection-bug/src/app/main-navigation.component.ts similarity index 94% rename from apps/angular/bug-cd/src/app/main-navigation.component.ts rename to apps/angular/32-change-detection-bug/src/app/main-navigation.component.ts index c30281a99..3d5ce20f8 100644 --- a/apps/angular/bug-cd/src/app/main-navigation.component.ts +++ b/apps/angular/32-change-detection-bug/src/app/main-navigation.component.ts @@ -10,12 +10,11 @@ interface MenuItem { @Component({ selector: 'app-nav', - standalone: true, imports: [RouterLink, RouterLinkActive, NgFor], template: ` {{ menu.name }} @@ -38,7 +37,6 @@ export class NavigationComponent { } @Component({ - standalone: true, imports: [NavigationComponent, NgIf, AsyncPipe], template: ` diff --git a/apps/angular/ngfor-enhancement/src/assets/.gitkeep b/apps/angular/32-change-detection-bug/src/assets/.gitkeep similarity index 100% rename from apps/angular/ngfor-enhancement/src/assets/.gitkeep rename to apps/angular/32-change-detection-bug/src/assets/.gitkeep diff --git a/apps/angular/module-to-standalone/src/favicon.ico b/apps/angular/32-change-detection-bug/src/favicon.ico similarity index 100% rename from apps/angular/module-to-standalone/src/favicon.ico rename to apps/angular/32-change-detection-bug/src/favicon.ico diff --git a/apps/angular/32-change-detection-bug/src/index.html b/apps/angular/32-change-detection-bug/src/index.html new file mode 100644 index 000000000..350759387 --- /dev/null +++ b/apps/angular/32-change-detection-bug/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-change-detection-bug + + + + + + + + diff --git a/apps/angular/32-change-detection-bug/src/main.ts b/apps/angular/32-change-detection-bug/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/32-change-detection-bug/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/decoupling/src/styles.scss b/apps/angular/32-change-detection-bug/src/styles.scss similarity index 100% rename from apps/angular/decoupling/src/styles.scss rename to apps/angular/32-change-detection-bug/src/styles.scss diff --git a/apps/angular/bug-cd/src/test-setup.ts b/apps/angular/32-change-detection-bug/src/test-setup.ts similarity index 100% rename from apps/angular/bug-cd/src/test-setup.ts rename to apps/angular/32-change-detection-bug/src/test-setup.ts diff --git a/apps/angular/decoupling/tailwind.config.js b/apps/angular/32-change-detection-bug/tailwind.config.js similarity index 100% rename from apps/angular/decoupling/tailwind.config.js rename to apps/angular/32-change-detection-bug/tailwind.config.js diff --git a/apps/angular/interop-rxjs-signal/tsconfig.app.json b/apps/angular/32-change-detection-bug/tsconfig.app.json similarity index 100% rename from apps/angular/interop-rxjs-signal/tsconfig.app.json rename to apps/angular/32-change-detection-bug/tsconfig.app.json diff --git a/apps/angular/bug-cd/tsconfig.editor.json b/apps/angular/32-change-detection-bug/tsconfig.editor.json similarity index 100% rename from apps/angular/bug-cd/tsconfig.editor.json rename to apps/angular/32-change-detection-bug/tsconfig.editor.json diff --git a/apps/angular/bug-cd/tsconfig.json b/apps/angular/32-change-detection-bug/tsconfig.json similarity index 100% rename from apps/angular/bug-cd/tsconfig.json rename to apps/angular/32-change-detection-bug/tsconfig.json diff --git a/apps/angular/bug-cd/tsconfig.spec.json b/apps/angular/32-change-detection-bug/tsconfig.spec.json similarity index 100% rename from apps/angular/bug-cd/tsconfig.spec.json rename to apps/angular/32-change-detection-bug/tsconfig.spec.json diff --git a/apps/angular/router-input/.eslintrc.json b/apps/angular/33-decoupling-components/.eslintrc.json similarity index 100% rename from apps/angular/router-input/.eslintrc.json rename to apps/angular/33-decoupling-components/.eslintrc.json diff --git a/apps/angular/33-decoupling-components/README.md b/apps/angular/33-decoupling-components/README.md new file mode 100644 index 000000000..4af70458f --- /dev/null +++ b/apps/angular/33-decoupling-components/README.md @@ -0,0 +1,13 @@ +# Decoupling Components + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-decoupling-components +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/33-decoupling/). diff --git a/apps/angular/33-decoupling-components/project.json b/apps/angular/33-decoupling-components/project.json new file mode 100644 index 000000000..762fc01b5 --- /dev/null +++ b/apps/angular/33-decoupling-components/project.json @@ -0,0 +1,71 @@ +{ + "name": "angular-decoupling-components", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/33-decoupling-components/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/33-decoupling-components", + "index": "apps/angular/33-decoupling-components/src/index.html", + "main": "apps/angular/33-decoupling-components/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/33-decoupling-components/tsconfig.app.json", + "assets": [ + "apps/angular/33-decoupling-components/src/favicon.ico", + "apps/angular/33-decoupling-components/src/assets" + ], + "styles": ["apps/angular/33-decoupling-components/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-decoupling-components:build:production" + }, + "development": { + "buildTarget": "angular-decoupling-components:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-decoupling-components:build" + } + } + } +} diff --git a/apps/angular/33-decoupling-components/src/app/app.component.ts b/apps/angular/33-decoupling-components/src/app/app.component.ts new file mode 100644 index 000000000..0d78f4d34 --- /dev/null +++ b/apps/angular/33-decoupling-components/src/app/app.component.ts @@ -0,0 +1,12 @@ +import { BtnDisabledDirective } from '@angular-challenges/decoupling/brain'; +import { BtnHelmetDirective } from '@angular-challenges/decoupling/helmet'; +import { Component } from '@angular/core'; + +@Component({ + imports: [BtnDisabledDirective, BtnHelmetDirective], + selector: 'app-root', + template: ` + + `, +}) +export class AppComponent {} diff --git a/apps/angular/permissions/src/assets/.gitkeep b/apps/angular/33-decoupling-components/src/assets/.gitkeep similarity index 100% rename from apps/angular/permissions/src/assets/.gitkeep rename to apps/angular/33-decoupling-components/src/assets/.gitkeep diff --git a/apps/angular/ngfor-enhancement/src/favicon.ico b/apps/angular/33-decoupling-components/src/favicon.ico similarity index 100% rename from apps/angular/ngfor-enhancement/src/favicon.ico rename to apps/angular/33-decoupling-components/src/favicon.ico diff --git a/apps/angular/33-decoupling-components/src/index.html b/apps/angular/33-decoupling-components/src/index.html new file mode 100644 index 000000000..b946b0cfd --- /dev/null +++ b/apps/angular/33-decoupling-components/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-decoupling-components + + + + + + + + diff --git a/apps/angular/pipe-easy/src/main.ts b/apps/angular/33-decoupling-components/src/main.ts similarity index 100% rename from apps/angular/pipe-easy/src/main.ts rename to apps/angular/33-decoupling-components/src/main.ts diff --git a/apps/angular/injection-token/src/styles.scss b/apps/angular/33-decoupling-components/src/styles.scss similarity index 100% rename from apps/angular/injection-token/src/styles.scss rename to apps/angular/33-decoupling-components/src/styles.scss diff --git a/apps/angular/injection-token/tailwind.config.js b/apps/angular/33-decoupling-components/tailwind.config.js similarity index 100% rename from apps/angular/injection-token/tailwind.config.js rename to apps/angular/33-decoupling-components/tailwind.config.js diff --git a/apps/angular/module-to-standalone/tsconfig.app.json b/apps/angular/33-decoupling-components/tsconfig.app.json similarity index 100% rename from apps/angular/module-to-standalone/tsconfig.app.json rename to apps/angular/33-decoupling-components/tsconfig.app.json diff --git a/apps/angular/decoupling/tsconfig.editor.json b/apps/angular/33-decoupling-components/tsconfig.editor.json similarity index 100% rename from apps/angular/decoupling/tsconfig.editor.json rename to apps/angular/33-decoupling-components/tsconfig.editor.json diff --git a/apps/angular/styling/tsconfig.json b/apps/angular/33-decoupling-components/tsconfig.json similarity index 100% rename from apps/angular/styling/tsconfig.json rename to apps/angular/33-decoupling-components/tsconfig.json diff --git a/apps/angular/injection-token/.eslintrc.json b/apps/angular/39-injection-token/.eslintrc.json similarity index 100% rename from apps/angular/injection-token/.eslintrc.json rename to apps/angular/39-injection-token/.eslintrc.json diff --git a/apps/angular/39-injection-token/README.md b/apps/angular/39-injection-token/README.md new file mode 100644 index 000000000..a96eb9c6e --- /dev/null +++ b/apps/angular/39-injection-token/README.md @@ -0,0 +1,13 @@ +# InjectionToken + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-injection-token +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/39-injection-token/). diff --git a/apps/angular/39-injection-token/jest.config.ts b/apps/angular/39-injection-token/jest.config.ts new file mode 100644 index 000000000..541d663e7 --- /dev/null +++ b/apps/angular/39-injection-token/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'angular-injection-token', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/39-injection-token', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/39-injection-token/project.json b/apps/angular/39-injection-token/project.json new file mode 100644 index 000000000..8dba72d55 --- /dev/null +++ b/apps/angular/39-injection-token/project.json @@ -0,0 +1,82 @@ +{ + "name": "angular-injection-token", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/39-injection-token/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/39-injection-token", + "index": "apps/angular/39-injection-token/src/index.html", + "main": "apps/angular/39-injection-token/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/39-injection-token/tsconfig.app.json", + "assets": [ + "apps/angular/39-injection-token/src/favicon.ico", + "apps/angular/39-injection-token/src/assets" + ], + "styles": ["apps/angular/39-injection-token/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-injection-token:build:production" + }, + "development": { + "buildTarget": "angular-injection-token:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-injection-token:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/39-injection-token/src/app/app.component.ts b/apps/angular/39-injection-token/src/app/app.component.ts new file mode 100644 index 000000000..280dc090a --- /dev/null +++ b/apps/angular/39-injection-token/src/app/app.component.ts @@ -0,0 +1,22 @@ +import { Component } from '@angular/core'; +import { RouterLink, RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet, RouterLink], + selector: 'app-root', + template: ` +
+ + +
+ + `, + host: { + class: 'p-10 flex flex-col', + }, +}) +export class AppComponent {} diff --git a/apps/angular/injection-token/src/app/app.config.ts b/apps/angular/39-injection-token/src/app/app.config.ts similarity index 100% rename from apps/angular/injection-token/src/app/app.config.ts rename to apps/angular/39-injection-token/src/app/app.config.ts diff --git a/apps/angular/injection-token/src/app/data.ts b/apps/angular/39-injection-token/src/app/data.ts similarity index 100% rename from apps/angular/injection-token/src/app/data.ts rename to apps/angular/39-injection-token/src/app/data.ts diff --git a/apps/angular/injection-token/src/app/phone.component.ts b/apps/angular/39-injection-token/src/app/phone.component.ts similarity index 78% rename from apps/angular/injection-token/src/app/phone.component.ts rename to apps/angular/39-injection-token/src/app/phone.component.ts index 73866ca1f..41ee3cfc0 100644 --- a/apps/angular/injection-token/src/app/phone.component.ts +++ b/apps/angular/39-injection-token/src/app/phone.component.ts @@ -3,12 +3,13 @@ import { TimerContainerComponent } from './timer-container.component'; @Component({ selector: 'app-phone', - standalone: true, imports: [TimerContainerComponent], - template: `
+ template: ` +
Phone Call Timer:

(should be 2000s)

- `, + + `, }) export default class PhoneComponent {} diff --git a/apps/angular/injection-token/src/app/timer-container.component.ts b/apps/angular/39-injection-token/src/app/timer-container.component.ts similarity index 96% rename from apps/angular/injection-token/src/app/timer-container.component.ts rename to apps/angular/39-injection-token/src/app/timer-container.component.ts index 30af69354..67db6059a 100644 --- a/apps/angular/injection-token/src/app/timer-container.component.ts +++ b/apps/angular/39-injection-token/src/app/timer-container.component.ts @@ -3,7 +3,6 @@ import { DEFAULT_TIMER } from './data'; import { TimerComponent } from './timer.component'; @Component({ selector: 'timer-container', - standalone: true, imports: [TimerComponent], template: `
diff --git a/apps/angular/injection-token/src/app/timer.component.ts b/apps/angular/39-injection-token/src/app/timer.component.ts similarity index 85% rename from apps/angular/injection-token/src/app/timer.component.ts rename to apps/angular/39-injection-token/src/app/timer.component.ts index db5b96344..95707ec61 100644 --- a/apps/angular/injection-token/src/app/timer.component.ts +++ b/apps/angular/39-injection-token/src/app/timer.component.ts @@ -6,7 +6,9 @@ import { DEFAULT_TIMER } from './data'; @Component({ selector: 'timer', standalone: true, - template: ` Timer running {{ timer() }} `, + template: ` + Timer running {{ timer() }} + `, }) export class TimerComponent { timer = toSignal(interval(DEFAULT_TIMER)); diff --git a/apps/angular/injection-token/src/app/video.component.ts b/apps/angular/39-injection-token/src/app/video.component.ts similarity index 79% rename from apps/angular/injection-token/src/app/video.component.ts rename to apps/angular/39-injection-token/src/app/video.component.ts index 5ea2c2bce..ba0a218b4 100644 --- a/apps/angular/injection-token/src/app/video.component.ts +++ b/apps/angular/39-injection-token/src/app/video.component.ts @@ -3,12 +3,13 @@ import { TimerContainerComponent } from './timer-container.component'; @Component({ selector: 'app-video', - standalone: true, imports: [TimerContainerComponent], - template: `
+ template: ` +
Video Call Timer:

(should be the default 1000s)

- `, + + `, }) export default class VideoComponent {} diff --git a/apps/angular/pipe-easy/src/assets/.gitkeep b/apps/angular/39-injection-token/src/assets/.gitkeep similarity index 100% rename from apps/angular/pipe-easy/src/assets/.gitkeep rename to apps/angular/39-injection-token/src/assets/.gitkeep diff --git a/apps/angular/permissions/src/favicon.ico b/apps/angular/39-injection-token/src/favicon.ico similarity index 100% rename from apps/angular/permissions/src/favicon.ico rename to apps/angular/39-injection-token/src/favicon.ico diff --git a/apps/angular/39-injection-token/src/index.html b/apps/angular/39-injection-token/src/index.html new file mode 100644 index 000000000..3c35787c9 --- /dev/null +++ b/apps/angular/39-injection-token/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-injection-token + + + + + + + + diff --git a/apps/angular/39-injection-token/src/main.ts b/apps/angular/39-injection-token/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/39-injection-token/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/interop-rxjs-signal/src/styles.scss b/apps/angular/39-injection-token/src/styles.scss similarity index 100% rename from apps/angular/interop-rxjs-signal/src/styles.scss rename to apps/angular/39-injection-token/src/styles.scss diff --git a/apps/angular/crud/src/test-setup.ts b/apps/angular/39-injection-token/src/test-setup.ts similarity index 100% rename from apps/angular/crud/src/test-setup.ts rename to apps/angular/39-injection-token/src/test-setup.ts diff --git a/apps/angular/interop-rxjs-signal/tailwind.config.js b/apps/angular/39-injection-token/tailwind.config.js similarity index 100% rename from apps/angular/interop-rxjs-signal/tailwind.config.js rename to apps/angular/39-injection-token/tailwind.config.js diff --git a/apps/angular/router-input/tsconfig.app.json b/apps/angular/39-injection-token/tsconfig.app.json similarity index 100% rename from apps/angular/router-input/tsconfig.app.json rename to apps/angular/39-injection-token/tsconfig.app.json diff --git a/apps/angular/injection-token/tsconfig.editor.json b/apps/angular/39-injection-token/tsconfig.editor.json similarity index 100% rename from apps/angular/injection-token/tsconfig.editor.json rename to apps/angular/39-injection-token/tsconfig.editor.json diff --git a/apps/angular/injection-token/tsconfig.json b/apps/angular/39-injection-token/tsconfig.json similarity index 100% rename from apps/angular/injection-token/tsconfig.json rename to apps/angular/39-injection-token/tsconfig.json diff --git a/apps/angular/injection-token/tsconfig.spec.json b/apps/angular/39-injection-token/tsconfig.spec.json similarity index 100% rename from apps/angular/injection-token/tsconfig.spec.json rename to apps/angular/39-injection-token/tsconfig.spec.json diff --git a/apps/angular/context-outlet-type/.eslintrc.json b/apps/angular/4-typed-context-outlet/.eslintrc.json similarity index 100% rename from apps/angular/context-outlet-type/.eslintrc.json rename to apps/angular/4-typed-context-outlet/.eslintrc.json diff --git a/apps/angular/4-typed-context-outlet/README.md b/apps/angular/4-typed-context-outlet/README.md new file mode 100644 index 000000000..e81915167 --- /dev/null +++ b/apps/angular/4-typed-context-outlet/README.md @@ -0,0 +1,13 @@ +# Typed ContextOutlet + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-typed-context-outlet +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/4-context-outlet-typed/). diff --git a/apps/angular/4-typed-context-outlet/project.json b/apps/angular/4-typed-context-outlet/project.json new file mode 100644 index 000000000..ccebf62c7 --- /dev/null +++ b/apps/angular/4-typed-context-outlet/project.json @@ -0,0 +1,72 @@ +{ + "name": "angular-typed-context-outlet", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/4-typed-context-outlet/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/4-typed-context-outlet", + "index": "apps/angular/4-typed-context-outlet/src/index.html", + "main": "apps/angular/4-typed-context-outlet/src/main.ts", + "polyfills": "apps/angular/4-typed-context-outlet/src/polyfills.ts", + "tsConfig": "apps/angular/4-typed-context-outlet/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/4-typed-context-outlet/src/favicon.ico", + "apps/angular/4-typed-context-outlet/src/assets" + ], + "styles": ["apps/angular/4-typed-context-outlet/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-typed-context-outlet:build:production" + }, + "development": { + "buildTarget": "angular-typed-context-outlet:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-typed-context-outlet:build" + } + } + } +} diff --git a/apps/angular/4-typed-context-outlet/src/app/app.component.ts b/apps/angular/4-typed-context-outlet/src/app/app.component.ts new file mode 100644 index 000000000..23be9dac6 --- /dev/null +++ b/apps/angular/4-typed-context-outlet/src/app/app.component.ts @@ -0,0 +1,45 @@ +import { NgTemplateOutlet } from '@angular/common'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ListComponent } from './list.component'; +import { PersonComponent } from './person.component'; + +@Component({ + imports: [NgTemplateOutlet, PersonComponent, ListComponent], + selector: 'app-root', + template: ` + + + {{ name }}: {{ age }} + + + + + + {{ student.name }}: {{ student.age }} - {{ i }} + + + + + + {{ city.name }}: {{ city.country }} - {{ i }} + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent { + person = { + name: 'toto', + age: 3, + }; + + students = [ + { name: 'toto', age: 3 }, + { name: 'titi', age: 4 }, + ]; + + cities = [ + { name: 'Paris', country: 'France' }, + { name: 'Berlin', country: 'Germany' }, + ]; +} diff --git a/apps/angular/4-typed-context-outlet/src/app/list.component.ts b/apps/angular/4-typed-context-outlet/src/app/list.component.ts new file mode 100644 index 000000000..b9946e428 --- /dev/null +++ b/apps/angular/4-typed-context-outlet/src/app/list.component.ts @@ -0,0 +1,31 @@ +import { CommonModule } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + ContentChild, + Input, + TemplateRef, +} from '@angular/core'; + +@Component({ + selector: 'list', + imports: [CommonModule], + template: ` +
+ +
+ + No Template + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ListComponent { + @Input() list!: TItem[]; + + @ContentChild('listRef', { read: TemplateRef }) + listTemplateRef!: TemplateRef; +} diff --git a/apps/angular/context-outlet-type/src/app/person.component.ts b/apps/angular/4-typed-context-outlet/src/app/person.component.ts similarity index 88% rename from apps/angular/context-outlet-type/src/app/person.component.ts rename to apps/angular/4-typed-context-outlet/src/app/person.component.ts index 4c33ae3a5..59eb00ab1 100644 --- a/apps/angular/context-outlet-type/src/app/person.component.ts +++ b/apps/angular/4-typed-context-outlet/src/app/person.component.ts @@ -7,7 +7,6 @@ interface Person { } @Component({ - standalone: true, imports: [NgTemplateOutlet], selector: 'person', template: ` @@ -17,7 +16,7 @@ interface Person { context: { $implicit: person.name, age: person.age } "> - No Template + No Template `, }) export class PersonComponent { diff --git a/apps/angular/pipe-easy/src/favicon.ico b/apps/angular/4-typed-context-outlet/src/favicon.ico similarity index 100% rename from apps/angular/pipe-easy/src/favicon.ico rename to apps/angular/4-typed-context-outlet/src/favicon.ico diff --git a/apps/angular/4-typed-context-outlet/src/index.html b/apps/angular/4-typed-context-outlet/src/index.html new file mode 100644 index 000000000..a9c0b5484 --- /dev/null +++ b/apps/angular/4-typed-context-outlet/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-typed-context-outlet + + + + + + + + diff --git a/apps/angular/pipe-hard/src/main.ts b/apps/angular/4-typed-context-outlet/src/main.ts similarity index 100% rename from apps/angular/pipe-hard/src/main.ts rename to apps/angular/4-typed-context-outlet/src/main.ts diff --git a/apps/angular/permissions/src/polyfills.ts b/apps/angular/4-typed-context-outlet/src/polyfills.ts similarity index 100% rename from apps/angular/permissions/src/polyfills.ts rename to apps/angular/4-typed-context-outlet/src/polyfills.ts diff --git a/apps/angular/pipe-intermediate/src/styles.scss b/apps/angular/4-typed-context-outlet/src/styles.scss similarity index 100% rename from apps/angular/pipe-intermediate/src/styles.scss rename to apps/angular/4-typed-context-outlet/src/styles.scss diff --git a/apps/angular/permissions/tsconfig.app.json b/apps/angular/4-typed-context-outlet/tsconfig.app.json similarity index 100% rename from apps/angular/permissions/tsconfig.app.json rename to apps/angular/4-typed-context-outlet/tsconfig.app.json diff --git a/apps/angular/ngfor-enhancement/tsconfig.editor.json b/apps/angular/4-typed-context-outlet/tsconfig.editor.json similarity index 100% rename from apps/angular/ngfor-enhancement/tsconfig.editor.json rename to apps/angular/4-typed-context-outlet/tsconfig.editor.json diff --git a/apps/angular/permissions/tsconfig.json b/apps/angular/4-typed-context-outlet/tsconfig.json similarity index 100% rename from apps/angular/permissions/tsconfig.json rename to apps/angular/4-typed-context-outlet/tsconfig.json diff --git a/apps/angular/44-view-transition/.eslintrc.json b/apps/angular/44-view-transition/.eslintrc.json new file mode 100644 index 000000000..3a7370250 --- /dev/null +++ b/apps/angular/44-view-transition/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/angular/44-view-transition/README.md b/apps/angular/44-view-transition/README.md new file mode 100644 index 000000000..02e39b394 --- /dev/null +++ b/apps/angular/44-view-transition/README.md @@ -0,0 +1,13 @@ +# View Transition + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-view-transition +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/44-view-transition/). diff --git a/apps/angular/44-view-transition/project.json b/apps/angular/44-view-transition/project.json new file mode 100644 index 000000000..9f4046607 --- /dev/null +++ b/apps/angular/44-view-transition/project.json @@ -0,0 +1,69 @@ +{ + "name": "angular-view-transition", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/44-view-transition/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/44-view-transition", + "index": "apps/angular/44-view-transition/src/index.html", + "browser": "apps/angular/44-view-transition/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/44-view-transition/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/44-view-transition/src/favicon.ico", + "apps/angular/44-view-transition/src/assets" + ], + "styles": ["apps/angular/44-view-transition/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-view-transition:build:production" + }, + "development": { + "buildTarget": "angular-view-transition:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-view-transition:build" + } + } + } +} diff --git a/apps/angular/44-view-transition/src/app/app.component.ts b/apps/angular/44-view-transition/src/app/app.component.ts new file mode 100644 index 000000000..1fcb0c548 --- /dev/null +++ b/apps/angular/44-view-transition/src/app/app.component.ts @@ -0,0 +1,12 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet], + selector: 'app-root', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent {} diff --git a/apps/angular/44-view-transition/src/app/app.config.ts b/apps/angular/44-view-transition/src/app/app.config.ts new file mode 100644 index 000000000..4c128f040 --- /dev/null +++ b/apps/angular/44-view-transition/src/app/app.config.ts @@ -0,0 +1,17 @@ +import { ApplicationConfig } from '@angular/core'; +import { provideRouter, withComponentInputBinding } from '@angular/router'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter( + [ + { path: '', loadComponent: () => import('./blog/blog.component') }, + { + path: 'post/:id', + loadComponent: () => import('./post/post.component'), + }, + ], + withComponentInputBinding(), + ), + ], +}; diff --git a/apps/angular/44-view-transition/src/app/blog/blog.component.ts b/apps/angular/44-view-transition/src/app/blog/blog.component.ts new file mode 100644 index 000000000..29291d21e --- /dev/null +++ b/apps/angular/44-view-transition/src/app/blog/blog.component.ts @@ -0,0 +1,23 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { posts } from '../data'; +import { ThumbnailComponent } from './thumbnail.component'; + +@Component({ + selector: 'blog', + imports: [ThumbnailComponent], + template: ` +
+ Blog List +
+
+ @for (post of posts; track post.id) { + + } +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export default class BlogComponent { + posts = posts; +} diff --git a/apps/angular/44-view-transition/src/app/blog/thumbnail-header.component.ts b/apps/angular/44-view-transition/src/app/blog/thumbnail-header.component.ts new file mode 100644 index 000000000..18d75aa06 --- /dev/null +++ b/apps/angular/44-view-transition/src/app/blog/thumbnail-header.component.ts @@ -0,0 +1,28 @@ +import { NgOptimizedImage } from '@angular/common'; +import { Component, input } from '@angular/core'; + +@Component({ + selector: 'thumbnail-header', + imports: [NgOptimizedImage], + template: ` +
+ +
+ Thomas Laforge + {{ date() }} +
+
+ + `, + host: { + class: 'flex w-full px-4 py-5 gap-4 justify-between', + }, +}) +export class ThumbnailHeaderComponent { + date = input.required(); +} diff --git a/apps/angular/44-view-transition/src/app/blog/thumbnail.component.ts b/apps/angular/44-view-transition/src/app/blog/thumbnail.component.ts new file mode 100644 index 000000000..dd2e25e26 --- /dev/null +++ b/apps/angular/44-view-transition/src/app/blog/thumbnail.component.ts @@ -0,0 +1,31 @@ +import { NgOptimizedImage } from '@angular/common'; +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { RouterLinkWithHref } from '@angular/router'; +import { Post } from '../post.model'; +import { ThumbnailHeaderComponent } from './thumbnail-header.component'; + +@Component({ + selector: 'blog-thumbnail', + imports: [NgOptimizedImage, ThumbnailHeaderComponent, RouterLinkWithHref], + template: ` +
+ +

{{ post().title }}

+

{{ post().description }}

+ +
+ `, + host: { + class: 'w-full max-w-[600px] rounded-3xl border-none shadow-lg', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ThumbnailComponent { + post = input.required(); +} diff --git a/apps/angular/44-view-transition/src/app/data.ts b/apps/angular/44-view-transition/src/app/data.ts new file mode 100644 index 000000000..52ed38e22 --- /dev/null +++ b/apps/angular/44-view-transition/src/app/data.ts @@ -0,0 +1,38 @@ +import { Post } from './post.model'; + +export const posts: Post[] = [ + { + id: '1', + title: 'Future of Change Detection in Angular with Signals', + description: + 'Learn how change detection is evolving and how signal will improve performance in the future.', + image: '/assets/signal-cd.full.webp', + date: 'May 23, 2023', + readingTime: 5, + }, + { + id: '2', + title: 'Everything you need to know about route Guard in Angular', + description: + 'Routing is a significant aspect of any SPA application, and protecting these routes is often necessary. We’ll learn all build-in guards', + image: '/assets/guard.full.webp', + date: 'Jan 18, 2023', + readingTime: 5, + }, + { + id: '3', + title: 'Create a highly customizable component', + description: 'Learn how to create highly customizable component', + image: '/assets/highly-custom.full.webp', + date: 'Nov 9, 2022', + readingTime: 5, + }, +]; + +export const fakeTextChapters = [ + 'Cyprum itidem insulam procul a continenti discretam et portuosam inter municipia crebra urbes duae faciunt claram Salamis et Paphus, altera Iovis delubris altera Veneris templo insignis. tanta autem tamque multiplici fertilitate abundat rerum omnium eadem Cyprus ut nullius externi indigens adminiculi indigenis viribus a fundamento ipso carinae ad supremos usque carbasos aedificet onerariam navem omnibusque armamentis instructam mari committat', + 'Et quoniam mirari posse quosdam peregrinos existimo haec lecturos forsitan, si contigerit, quamobrem cum oratio ad ea monstranda deflexerit quae Romae gererentur, nihil praeter seditiones narratur et tabernas et vilitates harum similis alias, summatim causas perstringam nusquam a veritate sponte propria digressurus', + 'Utque aegrum corpus quassari etiam levibus solet offensis, ita animus eius angustus et tener, quicquid increpuisset, ad salutis suae dispendium existimans factum aut cogitatum, insontium caedibus fecit victoriam luctuosam', + 'Novo denique perniciosoque exemplo idem Gallus ausus est inire flagitium grave, quod Romae cum ultimo dedecore temptasse aliquando dicitur Gallienus, et adhibitis paucis clam ferro succinctis vesperi per tabernas palabatur et conpita quaeritando Graeco sermone, cuius erat inpendio gnarus, quid de Caesare quisque sentiret. et haec confidenter agebat in urbe ubi pernoctantium luminum claritudo dierum solet imitari fulgorem. postremo agnitus saepe iamque, si prodisset, conspicuum se fore contemplans, non nisi luce palam egrediens ad agenda quae putabat seria cernebatur. et haec quidem medullitus multis gementibus agebantur.', + 'Et quoniam mirari posse quosdam peregrinos existimo haec lecturos forsitan, si contigerit, quamobrem cum oratio ad ea monstranda deflexerit quae Romae gererentur, nihil praeter seditiones narratur et tabernas et vilitates harum similis alias, summatim causas perstringam nusquam a veritate sponte propria digressurus.', +]; diff --git a/apps/angular/44-view-transition/src/app/post.model.ts b/apps/angular/44-view-transition/src/app/post.model.ts new file mode 100644 index 000000000..232e9efe5 --- /dev/null +++ b/apps/angular/44-view-transition/src/app/post.model.ts @@ -0,0 +1,8 @@ +export interface Post { + id: string; + title: string; + description: string; + image: string; + date: string; + readingTime: number; +} diff --git a/apps/angular/44-view-transition/src/app/post/post-header.component.ts b/apps/angular/44-view-transition/src/app/post/post-header.component.ts new file mode 100644 index 000000000..6d5f30e54 --- /dev/null +++ b/apps/angular/44-view-transition/src/app/post/post-header.component.ts @@ -0,0 +1,31 @@ +import { NgOptimizedImage } from '@angular/common'; +import { Component, input } from '@angular/core'; + +@Component({ + selector: 'post-header', + imports: [NgOptimizedImage], + template: ` +
+ + +
+ Thomas Laforge + {{ date() }} + `, + host: { + class: 'flex flex-col justify-center items-center', + }, +}) +export class PostHeaderComponent { + date = input.required(); +} diff --git a/apps/angular/44-view-transition/src/app/post/post.component.ts b/apps/angular/44-view-transition/src/app/post/post.component.ts new file mode 100644 index 000000000..edb87f780 --- /dev/null +++ b/apps/angular/44-view-transition/src/app/post/post.component.ts @@ -0,0 +1,46 @@ +import { NgOptimizedImage } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + computed, + input, +} from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { ThumbnailHeaderComponent } from '../blog/thumbnail-header.component'; +import { fakeTextChapters, posts } from '../data'; +import { PostHeaderComponent } from './post-header.component'; + +@Component({ + selector: 'post', + imports: [ + ThumbnailHeaderComponent, + NgOptimizedImage, + PostHeaderComponent, + RouterLink, + ], + template: ` +
+ + +

{{ post().title }}

+ + @for (chapter of fakeTextChapter; track $index) { +

{{ chapter }}

+ } +
+ `, + host: { + class: 'flex h-full justify-center', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export default class PostComponent { + id = input.required(); + post = computed(() => posts.filter((p) => p.id === this.id())[0]); + + fakeTextChapter = fakeTextChapters; +} diff --git a/apps/angular/pipe-hard/src/assets/.gitkeep b/apps/angular/44-view-transition/src/assets/.gitkeep similarity index 100% rename from apps/angular/pipe-hard/src/assets/.gitkeep rename to apps/angular/44-view-transition/src/assets/.gitkeep diff --git a/apps/angular/44-view-transition/src/assets/angular.webp b/apps/angular/44-view-transition/src/assets/angular.webp new file mode 100644 index 000000000..b20492845 Binary files /dev/null and b/apps/angular/44-view-transition/src/assets/angular.webp differ diff --git a/apps/angular/44-view-transition/src/assets/guard.full.webp b/apps/angular/44-view-transition/src/assets/guard.full.webp new file mode 100644 index 000000000..2f0b4c3d5 Binary files /dev/null and b/apps/angular/44-view-transition/src/assets/guard.full.webp differ diff --git a/apps/angular/44-view-transition/src/assets/highly-custom.full.webp b/apps/angular/44-view-transition/src/assets/highly-custom.full.webp new file mode 100644 index 000000000..74c2df8f8 Binary files /dev/null and b/apps/angular/44-view-transition/src/assets/highly-custom.full.webp differ diff --git a/apps/angular/44-view-transition/src/assets/profil.webp b/apps/angular/44-view-transition/src/assets/profil.webp new file mode 100644 index 000000000..52adde8fd Binary files /dev/null and b/apps/angular/44-view-transition/src/assets/profil.webp differ diff --git a/apps/angular/44-view-transition/src/assets/signal-cd.full.webp b/apps/angular/44-view-transition/src/assets/signal-cd.full.webp new file mode 100644 index 000000000..e483bbfd5 Binary files /dev/null and b/apps/angular/44-view-transition/src/assets/signal-cd.full.webp differ diff --git a/apps/angular/pipe-hard/src/favicon.ico b/apps/angular/44-view-transition/src/favicon.ico similarity index 100% rename from apps/angular/pipe-hard/src/favicon.ico rename to apps/angular/44-view-transition/src/favicon.ico diff --git a/apps/angular/44-view-transition/src/index.html b/apps/angular/44-view-transition/src/index.html new file mode 100644 index 000000000..6050d63e5 --- /dev/null +++ b/apps/angular/44-view-transition/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-view-transition + + + + + + + + diff --git a/apps/angular/44-view-transition/src/main.ts b/apps/angular/44-view-transition/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/44-view-transition/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/44-view-transition/src/styles.scss b/apps/angular/44-view-transition/src/styles.scss new file mode 100644 index 000000000..b5c61c956 --- /dev/null +++ b/apps/angular/44-view-transition/src/styles.scss @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/apps/angular/permissions/tailwind.config.js b/apps/angular/44-view-transition/tailwind.config.js similarity index 100% rename from apps/angular/permissions/tailwind.config.js rename to apps/angular/44-view-transition/tailwind.config.js diff --git a/apps/angular/styling/tsconfig.app.json b/apps/angular/44-view-transition/tsconfig.app.json similarity index 100% rename from apps/angular/styling/tsconfig.app.json rename to apps/angular/44-view-transition/tsconfig.app.json diff --git a/apps/performance/memoized/tsconfig.editor.json b/apps/angular/44-view-transition/tsconfig.editor.json similarity index 100% rename from apps/performance/memoized/tsconfig.editor.json rename to apps/angular/44-view-transition/tsconfig.editor.json diff --git a/apps/angular/44-view-transition/tsconfig.json b/apps/angular/44-view-transition/tsconfig.json new file mode 100644 index 000000000..b94f8837d --- /dev/null +++ b/apps/angular/44-view-transition/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/angular/permissions/.eslintrc.json b/apps/angular/45-react-in-angular/.eslintrc.json similarity index 100% rename from apps/angular/permissions/.eslintrc.json rename to apps/angular/45-react-in-angular/.eslintrc.json diff --git a/apps/angular/45-react-in-angular/README.md b/apps/angular/45-react-in-angular/README.md new file mode 100644 index 000000000..0a8679ac4 --- /dev/null +++ b/apps/angular/45-react-in-angular/README.md @@ -0,0 +1,13 @@ +# React in angular + +> author: wandrille-guesdon + +### Run Application + +```bash +npx nx serve angular-react-in-angular +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/45-react-in-angular/). diff --git a/apps/angular/45-react-in-angular/jest.config.ts b/apps/angular/45-react-in-angular/jest.config.ts new file mode 100644 index 000000000..cda19a635 --- /dev/null +++ b/apps/angular/45-react-in-angular/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'angular-react-in-angular', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/45-react-in-angular', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/45-react-in-angular/project.json b/apps/angular/45-react-in-angular/project.json new file mode 100644 index 000000000..bce6fe70e --- /dev/null +++ b/apps/angular/45-react-in-angular/project.json @@ -0,0 +1,80 @@ +{ + "name": "angular-react-in-angular", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/45-react-in-angular/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/45-react-in-angular", + "index": "apps/angular/45-react-in-angular/src/index.html", + "browser": "apps/angular/45-react-in-angular/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/45-react-in-angular/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/45-react-in-angular/src/favicon.ico", + "apps/angular/45-react-in-angular/src/assets" + ], + "styles": ["apps/angular/45-react-in-angular/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-react-in-angular:build:production" + }, + "development": { + "buildTarget": "angular-react-in-angular:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-react-in-angular:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/45-react-in-angular/src/app/app.component.ts b/apps/angular/45-react-in-angular/src/app/app.component.ts new file mode 100644 index 000000000..87b9675cc --- /dev/null +++ b/apps/angular/45-react-in-angular/src/app/app.component.ts @@ -0,0 +1,61 @@ +import { Component, signal } from '@angular/core'; +import { PostComponent } from './react/post.component'; + +type Post = { title: string; description: string }; + +@Component({ + imports: [PostComponent], + selector: 'app-root', + template: ` +
+
+ @for (post of posts; track post.title) { +
+ +
+ } +
+
+ Selected Post: + + {{ selectedPost()?.title ?? '-' }} + +
+
+ `, + styles: [''], +}) +export class AppComponent { + readonly posts = [ + { + title: 'A Deep Dive into Angular', + description: + "Explore Angular's core features, its evolution, and best practices in development for creating dynamic, efficient web applications in our comprehensive guide.", + pictureLink: + 'https://images.unsplash.com/photo-1471958680802-1345a694ba6d', + }, + { + title: 'The Perfect Combination', + description: + 'Unveil the power of combining Angular & React in web development, maximizing efficiency and flexibility for building scalable, sophisticated applications.', + pictureLink: + 'https://images.unsplash.com/photo-1518717202715-9fa9d099f58a', + }, + { + title: 'Taking Angular to the Next Level', + description: + "Discover how integrating React with Angular elevates web development, blending Angular's structure with React's UI prowess for advanced applications.", + pictureLink: + 'https://images.unsplash.com/photo-1532103050105-860af53bc6aa', + }, + ]; + + readonly selectedPost = signal(null); + + selectPost(post: Post) { + this.selectedPost.set(post); + } +} diff --git a/apps/angular/45-react-in-angular/src/app/app.config.ts b/apps/angular/45-react-in-angular/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/angular/45-react-in-angular/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/angular/45-react-in-angular/src/app/react/ReactPost.tsx b/apps/angular/45-react-in-angular/src/app/react/ReactPost.tsx new file mode 100644 index 000000000..3f6b9e4cd --- /dev/null +++ b/apps/angular/45-react-in-angular/src/app/react/ReactPost.tsx @@ -0,0 +1,29 @@ +// import React from 'react'; + +export default function ReactPost(props: { + title?: string; + description?: string; + pictureLink?: string; + selected?: boolean; + handleClick: () => void; +}) { + return ( +
+
+ {props.title} +
+
{props.title}
+

{props.description}

+ +
+
+
+ ); +} diff --git a/apps/angular/45-react-in-angular/src/app/react/post.component.ts b/apps/angular/45-react-in-angular/src/app/react/post.component.ts new file mode 100644 index 000000000..2a35eaca6 --- /dev/null +++ b/apps/angular/45-react-in-angular/src/app/react/post.component.ts @@ -0,0 +1,17 @@ +import { Component, EventEmitter, input, Output } from '@angular/core'; + +type Post = { title: string; description: string; pictureLink: string }; + +@Component({ + standalone: true, + selector: 'app-post', + template: ` +
+ `, + styles: [''], +}) +export class PostComponent { + post = input(undefined); + isSelected = input(false); + @Output() selectPost = new EventEmitter(); +} diff --git a/apps/angular/pipe-intermediate/src/assets/.gitkeep b/apps/angular/45-react-in-angular/src/assets/.gitkeep similarity index 100% rename from apps/angular/pipe-intermediate/src/assets/.gitkeep rename to apps/angular/45-react-in-angular/src/assets/.gitkeep diff --git a/apps/angular/pipe-intermediate/src/favicon.ico b/apps/angular/45-react-in-angular/src/favicon.ico similarity index 100% rename from apps/angular/pipe-intermediate/src/favicon.ico rename to apps/angular/45-react-in-angular/src/favicon.ico diff --git a/apps/angular/45-react-in-angular/src/index.html b/apps/angular/45-react-in-angular/src/index.html new file mode 100644 index 000000000..9d9dd3923 --- /dev/null +++ b/apps/angular/45-react-in-angular/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-react-in-angular + + + + + + + + diff --git a/apps/angular/45-react-in-angular/src/main.ts b/apps/angular/45-react-in-angular/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/45-react-in-angular/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/module-to-standalone/src/styles.scss b/apps/angular/45-react-in-angular/src/styles.scss similarity index 100% rename from apps/angular/module-to-standalone/src/styles.scss rename to apps/angular/45-react-in-angular/src/styles.scss diff --git a/apps/angular/injection-token/src/test-setup.ts b/apps/angular/45-react-in-angular/src/test-setup.ts similarity index 100% rename from apps/angular/injection-token/src/test-setup.ts rename to apps/angular/45-react-in-angular/src/test-setup.ts diff --git a/apps/angular/projection/tailwind.config.js b/apps/angular/45-react-in-angular/tailwind.config.js similarity index 100% rename from apps/angular/projection/tailwind.config.js rename to apps/angular/45-react-in-angular/tailwind.config.js diff --git a/apps/performance/default-onpush/tsconfig.app.json b/apps/angular/45-react-in-angular/tsconfig.app.json similarity index 100% rename from apps/performance/default-onpush/tsconfig.app.json rename to apps/angular/45-react-in-angular/tsconfig.app.json diff --git a/apps/angular/interop-rxjs-signal/tsconfig.editor.json b/apps/angular/45-react-in-angular/tsconfig.editor.json similarity index 100% rename from apps/angular/interop-rxjs-signal/tsconfig.editor.json rename to apps/angular/45-react-in-angular/tsconfig.editor.json diff --git a/apps/angular/45-react-in-angular/tsconfig.json b/apps/angular/45-react-in-angular/tsconfig.json new file mode 100644 index 000000000..25ca437b4 --- /dev/null +++ b/apps/angular/45-react-in-angular/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/performance/ngfor-optimize/tsconfig.spec.json b/apps/angular/45-react-in-angular/tsconfig.spec.json similarity index 100% rename from apps/performance/ngfor-optimize/tsconfig.spec.json rename to apps/angular/45-react-in-angular/tsconfig.spec.json diff --git a/apps/angular/pipe-easy/.eslintrc.json b/apps/angular/46-simple-animations/.eslintrc.json similarity index 100% rename from apps/angular/pipe-easy/.eslintrc.json rename to apps/angular/46-simple-animations/.eslintrc.json diff --git a/apps/angular/46-simple-animations/README.md b/apps/angular/46-simple-animations/README.md new file mode 100644 index 000000000..87e6c7e7c --- /dev/null +++ b/apps/angular/46-simple-animations/README.md @@ -0,0 +1,13 @@ +# Simple Animations + +> author: sven-brodny + +### Run Application + +```bash +npx nx serve angular-simple-animations +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/46-simple-animations/). diff --git a/apps/angular/46-simple-animations/jest.config.ts b/apps/angular/46-simple-animations/jest.config.ts new file mode 100644 index 000000000..2ad20837f --- /dev/null +++ b/apps/angular/46-simple-animations/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'angular-simple-animations', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/46-simple-animations', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/46-simple-animations/project.json b/apps/angular/46-simple-animations/project.json new file mode 100644 index 000000000..1d00fd246 --- /dev/null +++ b/apps/angular/46-simple-animations/project.json @@ -0,0 +1,80 @@ +{ + "name": "angular-simple-animations", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/46-simple-animations/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/46-simple-animations", + "index": "apps/angular/46-simple-animations/src/index.html", + "browser": "apps/angular/46-simple-animations/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/46-simple-animations/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/46-simple-animations/src/favicon.ico", + "apps/angular/46-simple-animations/src/assets" + ], + "styles": ["apps/angular/46-simple-animations/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-simple-animations:build:production" + }, + "development": { + "buildTarget": "angular-simple-animations:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-simple-animations:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/46-simple-animations/src/app/app.component.ts b/apps/angular/46-simple-animations/src/app/app.component.ts new file mode 100644 index 000000000..ae63db419 --- /dev/null +++ b/apps/angular/46-simple-animations/src/app/app.component.ts @@ -0,0 +1,87 @@ +import { Component } from '@angular/core'; + +@Component({ + imports: [], + selector: 'app-root', + styles: ` + section { + @apply flex flex-1 flex-col gap-5; + } + + .list-item { + @apply flex flex-row border-b px-5 pb-2; + + span { + @apply flex-1; + } + } + `, + template: ` +
+
+
+

2008

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae + mollitia sequi accusantium, distinctio similique laudantium eveniet + quidem sit placeat possimus tempore dolorum inventore corporis atque + quae ad, nobis explicabo delectus. +

+
+ +
+

2010

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae + mollitia sequi accusantium, distinctio similique laudantium eveniet + quidem sit placeat possimus tempore dolorum inventore corporis atque + quae ad, nobis explicabo delectus. +

+
+ +
+

2012

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Vitae + mollitia sequi accusantium, distinctio similique laudantium eveniet + quidem sit placeat possimus tempore dolorum inventore corporis atque + quae ad, nobis explicabo delectus. +

+
+
+ +
+
+ Name: + Samuel +
+ +
+ Age: + 28 +
+ +
+ Birthdate: + 02.11.1995 +
+ +
+ City: + Berlin +
+ +
+ Language: + English +
+ +
+ Like Pizza: + Hell yeah +
+
+
+ `, +}) +export class AppComponent {} diff --git a/apps/angular/46-simple-animations/src/app/app.config.ts b/apps/angular/46-simple-animations/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/angular/46-simple-animations/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/angular/projection/src/assets/.gitkeep b/apps/angular/46-simple-animations/src/assets/.gitkeep similarity index 100% rename from apps/angular/projection/src/assets/.gitkeep rename to apps/angular/46-simple-animations/src/assets/.gitkeep diff --git a/apps/angular/projection/src/favicon.ico b/apps/angular/46-simple-animations/src/favicon.ico similarity index 100% rename from apps/angular/projection/src/favicon.ico rename to apps/angular/46-simple-animations/src/favicon.ico diff --git a/apps/angular/46-simple-animations/src/index.html b/apps/angular/46-simple-animations/src/index.html new file mode 100644 index 000000000..8fbebf9fb --- /dev/null +++ b/apps/angular/46-simple-animations/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-simple-animations + + + + + + + + diff --git a/apps/angular/46-simple-animations/src/main.ts b/apps/angular/46-simple-animations/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/46-simple-animations/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/permissions/src/styles.scss b/apps/angular/46-simple-animations/src/styles.scss similarity index 100% rename from apps/angular/permissions/src/styles.scss rename to apps/angular/46-simple-animations/src/styles.scss diff --git a/apps/angular/interop-rxjs-signal/src/test-setup.ts b/apps/angular/46-simple-animations/src/test-setup.ts similarity index 100% rename from apps/angular/interop-rxjs-signal/src/test-setup.ts rename to apps/angular/46-simple-animations/src/test-setup.ts diff --git a/apps/performance/default-onpush/tailwind.config.js b/apps/angular/46-simple-animations/tailwind.config.js similarity index 100% rename from apps/performance/default-onpush/tailwind.config.js rename to apps/angular/46-simple-animations/tailwind.config.js diff --git a/apps/performance/memoized/tsconfig.app.json b/apps/angular/46-simple-animations/tsconfig.app.json similarity index 100% rename from apps/performance/memoized/tsconfig.app.json rename to apps/angular/46-simple-animations/tsconfig.app.json diff --git a/apps/performance/ngfor-optimize/tsconfig.editor.json b/apps/angular/46-simple-animations/tsconfig.editor.json similarity index 100% rename from apps/performance/ngfor-optimize/tsconfig.editor.json rename to apps/angular/46-simple-animations/tsconfig.editor.json diff --git a/apps/angular/46-simple-animations/tsconfig.json b/apps/angular/46-simple-animations/tsconfig.json new file mode 100644 index 000000000..25ca437b4 --- /dev/null +++ b/apps/angular/46-simple-animations/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/angular/46-simple-animations/tsconfig.spec.json b/apps/angular/46-simple-animations/tsconfig.spec.json new file mode 100644 index 000000000..1a4817a7d --- /dev/null +++ b/apps/angular/46-simple-animations/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "@testing-library/jest-dom"] + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/apps/angular/pipe-hard/.eslintrc.json b/apps/angular/5-crud-application/.eslintrc.json similarity index 100% rename from apps/angular/pipe-hard/.eslintrc.json rename to apps/angular/5-crud-application/.eslintrc.json diff --git a/apps/angular/5-crud-application/README.md b/apps/angular/5-crud-application/README.md new file mode 100644 index 000000000..8992014e3 --- /dev/null +++ b/apps/angular/5-crud-application/README.md @@ -0,0 +1,13 @@ +# Crud application + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-crud-application +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/5-crud/). diff --git a/apps/angular/5-crud-application/jest.config.ts b/apps/angular/5-crud-application/jest.config.ts new file mode 100644 index 000000000..f290dd70a --- /dev/null +++ b/apps/angular/5-crud-application/jest.config.ts @@ -0,0 +1,23 @@ +/* eslint-disable */ +export default { + displayName: 'angular-crud-application', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../../coverage/apps/angular/5-crud-application', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/5-crud-application/project.json b/apps/angular/5-crud-application/project.json new file mode 100644 index 000000000..cdad9374a --- /dev/null +++ b/apps/angular/5-crud-application/project.json @@ -0,0 +1,87 @@ +{ + "name": "angular-crud-application", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/5-crud-application/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/5-crud-application", + "index": "apps/angular/5-crud-application/src/index.html", + "main": "apps/angular/5-crud-application/src/main.ts", + "polyfills": "apps/angular/5-crud-application/src/polyfills.ts", + "tsConfig": "apps/angular/5-crud-application/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/5-crud-application/src/favicon.ico", + "apps/angular/5-crud-application/src/assets" + ], + "styles": [ + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", + "apps/angular/5-crud-application/src/styles.scss" + ], + "scripts": [], + "allowedCommonJsDependencies": ["seedrandom"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-crud-application:build:production" + }, + "development": { + "buildTarget": "angular-crud-application:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-crud-application:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/5-crud-application/src/app/app.component.ts b/apps/angular/5-crud-application/src/app/app.component.ts new file mode 100644 index 000000000..9152ff5e4 --- /dev/null +++ b/apps/angular/5-crud-application/src/app/app.component.ts @@ -0,0 +1,50 @@ +import { CommonModule } from '@angular/common'; +import { HttpClient } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { randText } from '@ngneat/falso'; + +@Component({ + imports: [CommonModule], + selector: 'app-root', + template: ` +
+ {{ todo.title }} + +
+ `, + styles: [], +}) +export class AppComponent implements OnInit { + todos!: any[]; + + constructor(private http: HttpClient) {} + + ngOnInit(): void { + this.http + .get('https://jsonplaceholder.typicode.com/todos') + .subscribe((todos) => { + this.todos = todos; + }); + } + + update(todo: any) { + this.http + .put( + `https://jsonplaceholder.typicode.com/todos/${todo.id}`, + JSON.stringify({ + todo: todo.id, + title: randText(), + body: todo.body, + userId: todo.userId, + }), + { + headers: { + 'Content-type': 'application/json; charset=UTF-8', + }, + }, + ) + .subscribe((todoUpdated: any) => { + this.todos[todoUpdated.id - 1] = todoUpdated; + }); + } +} diff --git a/apps/angular/5-crud-application/src/app/app.config.ts b/apps/angular/5-crud-application/src/app/app.config.ts new file mode 100644 index 000000000..1c0c9422f --- /dev/null +++ b/apps/angular/5-crud-application/src/app/app.config.ts @@ -0,0 +1,6 @@ +import { provideHttpClient } from '@angular/common/http'; +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [provideHttpClient()], +}; diff --git a/apps/angular/router-input/src/assets/.gitkeep b/apps/angular/5-crud-application/src/assets/.gitkeep similarity index 100% rename from apps/angular/router-input/src/assets/.gitkeep rename to apps/angular/5-crud-application/src/assets/.gitkeep diff --git a/apps/angular/router-input/src/favicon.ico b/apps/angular/5-crud-application/src/favicon.ico similarity index 100% rename from apps/angular/router-input/src/favicon.ico rename to apps/angular/5-crud-application/src/favicon.ico diff --git a/apps/angular/5-crud-application/src/index.html b/apps/angular/5-crud-application/src/index.html new file mode 100644 index 000000000..b9ec0b609 --- /dev/null +++ b/apps/angular/5-crud-application/src/index.html @@ -0,0 +1,20 @@ + + + + + angular-crud-application + + + + + + + + + + + diff --git a/apps/angular/5-crud-application/src/main.ts b/apps/angular/5-crud-application/src/main.ts new file mode 100644 index 000000000..9bb5c3023 --- /dev/null +++ b/apps/angular/5-crud-application/src/main.ts @@ -0,0 +1,8 @@ +import { appConfig } from './app/app.config'; + +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/pipe-easy/src/polyfills.ts b/apps/angular/5-crud-application/src/polyfills.ts similarity index 100% rename from apps/angular/pipe-easy/src/polyfills.ts rename to apps/angular/5-crud-application/src/polyfills.ts diff --git a/apps/angular/crud/src/styles.scss b/apps/angular/5-crud-application/src/styles.scss similarity index 100% rename from apps/angular/crud/src/styles.scss rename to apps/angular/5-crud-application/src/styles.scss diff --git a/apps/performance/ngfor-optimize/src/test-setup.ts b/apps/angular/5-crud-application/src/test-setup.ts similarity index 100% rename from apps/performance/ngfor-optimize/src/test-setup.ts rename to apps/angular/5-crud-application/src/test-setup.ts diff --git a/apps/angular/pipe-easy/tsconfig.app.json b/apps/angular/5-crud-application/tsconfig.app.json similarity index 100% rename from apps/angular/pipe-easy/tsconfig.app.json rename to apps/angular/5-crud-application/tsconfig.app.json diff --git a/apps/angular/permissions/tsconfig.editor.json b/apps/angular/5-crud-application/tsconfig.editor.json similarity index 100% rename from apps/angular/permissions/tsconfig.editor.json rename to apps/angular/5-crud-application/tsconfig.editor.json diff --git a/apps/angular/projection/tsconfig.json b/apps/angular/5-crud-application/tsconfig.json similarity index 100% rename from apps/angular/projection/tsconfig.json rename to apps/angular/5-crud-application/tsconfig.json diff --git a/apps/angular/crud/tsconfig.spec.json b/apps/angular/5-crud-application/tsconfig.spec.json similarity index 100% rename from apps/angular/crud/tsconfig.spec.json rename to apps/angular/5-crud-application/tsconfig.spec.json diff --git a/apps/angular/pipe-intermediate/.eslintrc.json b/apps/angular/52-lazy-load-component/.eslintrc.json similarity index 100% rename from apps/angular/pipe-intermediate/.eslintrc.json rename to apps/angular/52-lazy-load-component/.eslintrc.json diff --git a/apps/angular/52-lazy-load-component/README.md b/apps/angular/52-lazy-load-component/README.md new file mode 100644 index 000000000..7da25f89b --- /dev/null +++ b/apps/angular/52-lazy-load-component/README.md @@ -0,0 +1,13 @@ +# lazy-load-component + +> author: lance-finney + +### Run Application + +```bash +npx nx serve angular-lazy-load-component +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/52-lazy-load-component/). diff --git a/apps/angular/52-lazy-load-component/jest.config.ts b/apps/angular/52-lazy-load-component/jest.config.ts new file mode 100644 index 000000000..a0fd1100f --- /dev/null +++ b/apps/angular/52-lazy-load-component/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'angular-lazy-load-component', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/52-lazy-load-component', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/52-lazy-load-component/project.json b/apps/angular/52-lazy-load-component/project.json new file mode 100644 index 000000000..d3b28088a --- /dev/null +++ b/apps/angular/52-lazy-load-component/project.json @@ -0,0 +1,80 @@ +{ + "name": "angular-lazy-load-component", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/52-lazy-load-component/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/52-lazy-load-component", + "index": "apps/angular/52-lazy-load-component/src/index.html", + "browser": "apps/angular/52-lazy-load-component/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/52-lazy-load-component/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/52-lazy-load-component/src/favicon.ico", + "apps/angular/52-lazy-load-component/src/assets" + ], + "styles": ["apps/angular/52-lazy-load-component/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-lazy-load-component:build:production" + }, + "development": { + "buildTarget": "angular-lazy-load-component:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-lazy-load-component:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/52-lazy-load-component/src/app/app.component.ts b/apps/angular/52-lazy-load-component/src/app/app.component.ts new file mode 100644 index 000000000..6d8c03d29 --- /dev/null +++ b/apps/angular/52-lazy-load-component/src/app/app.component.ts @@ -0,0 +1,23 @@ +import { Component, signal } from '@angular/core'; + +@Component({ + selector: 'app-root', + template: ` +
+ @if (topLoaded()) { + + } @else { + + + } +
+ `, + standalone: false, +}) +export class AppComponent { + topLoaded = signal(false); +} diff --git a/apps/angular/52-lazy-load-component/src/app/app.module.ts b/apps/angular/52-lazy-load-component/src/app/app.module.ts new file mode 100644 index 000000000..b5d430e67 --- /dev/null +++ b/apps/angular/52-lazy-load-component/src/app/app.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { AppComponent } from './app.component'; +import { PlaceholderComponent } from './placeholder.component'; +import { TopComponent } from './top.component'; + +@NgModule({ + declarations: [AppComponent, PlaceholderComponent, TopComponent], + imports: [BrowserModule], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/apps/angular/52-lazy-load-component/src/app/placeholder.component.ts b/apps/angular/52-lazy-load-component/src/app/placeholder.component.ts new file mode 100644 index 000000000..cbb2b5fa6 --- /dev/null +++ b/apps/angular/52-lazy-load-component/src/app/placeholder.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-placeholder', + template: ` + I'm a placeholder component. + `, + styles: ` + :host { + display: grid; + padding: 20px; + background-color: #f0f0f0; + height: 50%; + } + `, + standalone: false, +}) +export class PlaceholderComponent {} diff --git a/apps/angular/52-lazy-load-component/src/app/top.component.ts b/apps/angular/52-lazy-load-component/src/app/top.component.ts new file mode 100644 index 000000000..e1ca9012c --- /dev/null +++ b/apps/angular/52-lazy-load-component/src/app/top.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-top', + template: ` + I am a very heavy, expensive component that should be lazy loaded. + `, + styles: ` + :host { + display: grid; + padding: 20px; + background-color: #f0f0f0; + height: 50%; + } + `, + standalone: false, +}) +export class TopComponent {} diff --git a/apps/angular/styling/src/assets/.gitkeep b/apps/angular/52-lazy-load-component/src/assets/.gitkeep similarity index 100% rename from apps/angular/styling/src/assets/.gitkeep rename to apps/angular/52-lazy-load-component/src/assets/.gitkeep diff --git a/apps/angular/styling/src/favicon.ico b/apps/angular/52-lazy-load-component/src/favicon.ico similarity index 100% rename from apps/angular/styling/src/favicon.ico rename to apps/angular/52-lazy-load-component/src/favicon.ico diff --git a/apps/angular/52-lazy-load-component/src/index.html b/apps/angular/52-lazy-load-component/src/index.html new file mode 100644 index 000000000..242ec3e3f --- /dev/null +++ b/apps/angular/52-lazy-load-component/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-lazy-load-component + + + + + + + + diff --git a/apps/angular/52-lazy-load-component/src/main.ts b/apps/angular/52-lazy-load-component/src/main.ts new file mode 100644 index 000000000..16de2365d --- /dev/null +++ b/apps/angular/52-lazy-load-component/src/main.ts @@ -0,0 +1,6 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AppModule } from './app/app.module'; + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); diff --git a/apps/performance/default-onpush/src/styles.scss b/apps/angular/52-lazy-load-component/src/styles.scss similarity index 100% rename from apps/performance/default-onpush/src/styles.scss rename to apps/angular/52-lazy-load-component/src/styles.scss diff --git a/apps/rxjs/catch-error/src/test-setup.ts b/apps/angular/52-lazy-load-component/src/test-setup.ts similarity index 100% rename from apps/rxjs/catch-error/src/test-setup.ts rename to apps/angular/52-lazy-load-component/src/test-setup.ts diff --git a/apps/performance/memoized/tailwind.config.js b/apps/angular/52-lazy-load-component/tailwind.config.js similarity index 100% rename from apps/performance/memoized/tailwind.config.js rename to apps/angular/52-lazy-load-component/tailwind.config.js diff --git a/apps/performance/ngfor-biglist/tsconfig.app.json b/apps/angular/52-lazy-load-component/tsconfig.app.json similarity index 100% rename from apps/performance/ngfor-biglist/tsconfig.app.json rename to apps/angular/52-lazy-load-component/tsconfig.app.json diff --git a/apps/angular/52-lazy-load-component/tsconfig.editor.json b/apps/angular/52-lazy-load-component/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/angular/52-lazy-load-component/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/angular/52-lazy-load-component/tsconfig.json b/apps/angular/52-lazy-load-component/tsconfig.json new file mode 100644 index 000000000..4383e7eb8 --- /dev/null +++ b/apps/angular/52-lazy-load-component/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/angular/52-lazy-load-component/tsconfig.spec.json b/apps/angular/52-lazy-load-component/tsconfig.spec.json new file mode 100644 index 000000000..1a4817a7d --- /dev/null +++ b/apps/angular/52-lazy-load-component/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "@testing-library/jest-dom"] + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/apps/ngrx/effect-selector/.eslintrc.json b/apps/angular/55-back-button-navigation/.eslintrc.json similarity index 100% rename from apps/ngrx/effect-selector/.eslintrc.json rename to apps/angular/55-back-button-navigation/.eslintrc.json diff --git a/apps/angular/55-back-button-navigation/README.md b/apps/angular/55-back-button-navigation/README.md new file mode 100644 index 000000000..2534d270c --- /dev/null +++ b/apps/angular/55-back-button-navigation/README.md @@ -0,0 +1,13 @@ +# Back-Button-Navigation + +> author: ioannis-tsironis + +### Run Application + +```bash +npx nx serve angular-back-button-navigation +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/55-back-button-navigation/). diff --git a/apps/angular/55-back-button-navigation/jest.config.ts b/apps/angular/55-back-button-navigation/jest.config.ts new file mode 100644 index 000000000..845a03a01 --- /dev/null +++ b/apps/angular/55-back-button-navigation/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'angular-back-button-navigation', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/angular/55-back-button-navigation', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/angular/55-back-button-navigation/project.json b/apps/angular/55-back-button-navigation/project.json new file mode 100644 index 000000000..f53d65e27 --- /dev/null +++ b/apps/angular/55-back-button-navigation/project.json @@ -0,0 +1,85 @@ +{ + "name": "angular-back-button-navigation", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/55-back-button-navigation/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/55-back-button-navigation", + "index": "apps/angular/55-back-button-navigation/src/index.html", + "browser": "apps/angular/55-back-button-navigation/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/55-back-button-navigation/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "apps/angular/55-back-button-navigation/public" + } + ], + "styles": [ + "apps/angular/55-back-button-navigation/src/styles.scss", + "node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-back-button-navigation:build:production" + }, + "development": { + "buildTarget": "angular-back-button-navigation:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-back-button-navigation:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/angular/55-back-button-navigation/src/app/app.component.html b/apps/angular/55-back-button-navigation/src/app/app.component.html new file mode 100644 index 000000000..0680b43f9 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/app.component.html @@ -0,0 +1 @@ + diff --git a/apps/angular/55-back-button-navigation/src/app/app.component.ts b/apps/angular/55-back-button-navigation/src/app/app.component.ts new file mode 100644 index 000000000..baffdae25 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/app.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; +import { RouterLink, RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet, RouterLink], + selector: 'app-root', + templateUrl: './app.component.html', +}) +export class AppComponent {} diff --git a/apps/angular/55-back-button-navigation/src/app/app.config.ts b/apps/angular/55-back-button-navigation/src/app/app.config.ts new file mode 100644 index 000000000..440cdf2c3 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/app.config.ts @@ -0,0 +1,10 @@ +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; +import { provideRouter } from '@angular/router'; +import { APP_ROUTES } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(APP_ROUTES), + ], +}; diff --git a/apps/angular/55-back-button-navigation/src/app/app.routes.ts b/apps/angular/55-back-button-navigation/src/app/app.routes.ts new file mode 100644 index 000000000..7deecd57a --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/app.routes.ts @@ -0,0 +1,24 @@ +import { Routes } from '@angular/router'; +import { HomeComponent } from './home/home.component'; +import { SensitiveActionComponent } from './sensitive-action/sensitive-action.component'; +import { SimpleActionComponent } from './simple-action/simple-action.component'; + +export const APP_ROUTES: Routes = [ + { + path: '', + pathMatch: 'full', + redirectTo: 'home', + }, + { + path: 'home', + component: HomeComponent, + }, + { + path: 'simple-action', + component: SimpleActionComponent, + }, + { + path: 'sensitive-action', + component: SensitiveActionComponent, + }, +]; diff --git a/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.html b/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.html new file mode 100644 index 000000000..ff00ea965 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.html @@ -0,0 +1,6 @@ +

Delete file

+Would you like to delete cat.jpeg? + + + + diff --git a/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.ts b/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.ts new file mode 100644 index 000000000..9a9dd0fef --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { + MatDialogActions, + MatDialogClose, + MatDialogContent, + MatDialogRef, + MatDialogTitle, +} from '@angular/material/dialog'; + +@Component({ + selector: 'app-dialog-dialog', + templateUrl: './dialog.component.html', + imports: [ + MatButtonModule, + MatDialogActions, + MatDialogClose, + MatDialogTitle, + MatDialogContent, + ], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DialogComponent { + readonly dialogRef = inject(MatDialogRef); +} diff --git a/apps/angular/55-back-button-navigation/src/app/home/home.component.html b/apps/angular/55-back-button-navigation/src/app/home/home.component.html new file mode 100644 index 000000000..cce9e6d4f --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/home/home.component.html @@ -0,0 +1,7 @@ + + Go to simple dialog action page + + + + Go to sensitive dialog action page + diff --git a/apps/angular/55-back-button-navigation/src/app/home/home.component.ts b/apps/angular/55-back-button-navigation/src/app/home/home.component.ts new file mode 100644 index 000000000..18c4147b1 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/home/home.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { RouterLink } from '@angular/router'; + +@Component({ + imports: [MatButtonModule, RouterLink], + selector: 'app-home', + templateUrl: './home.component.html', +}) +export class HomeComponent {} diff --git a/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.html b/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.html new file mode 100644 index 000000000..bcb7382e9 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.html @@ -0,0 +1,3 @@ + diff --git a/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.ts b/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.ts new file mode 100644 index 000000000..a97282c33 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.ts @@ -0,0 +1,19 @@ +import { Component, inject } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog } from '@angular/material/dialog'; +import { DialogComponent } from '../dialog/dialog.component'; + +@Component({ + imports: [MatButtonModule], + selector: 'app-sensitive-action', + templateUrl: './sensitive-action.component.html', +}) +export class SensitiveActionComponent { + readonly #dialog = inject(MatDialog); + + openDialog(): void { + this.#dialog.open(DialogComponent, { + width: '250px', + }); + } +} diff --git a/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.html b/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.html new file mode 100644 index 000000000..95f63e65e --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.html @@ -0,0 +1 @@ + diff --git a/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.ts b/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.ts new file mode 100644 index 000000000..fe97e7368 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.ts @@ -0,0 +1,19 @@ +import { Component, inject } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog } from '@angular/material/dialog'; +import { DialogComponent } from '../dialog/dialog.component'; + +@Component({ + imports: [MatButtonModule], + selector: 'app-simple-action', + templateUrl: './simple-action.component.html', +}) +export class SimpleActionComponent { + readonly #dialog = inject(MatDialog); + + openDialog(): void { + this.#dialog.open(DialogComponent, { + width: '250px', + }); + } +} diff --git a/apps/angular/55-back-button-navigation/src/index.html b/apps/angular/55-back-button-navigation/src/index.html new file mode 100644 index 000000000..4e657d614 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-back-button-navigation + + + + + + + + diff --git a/apps/angular/55-back-button-navigation/src/main.ts b/apps/angular/55-back-button-navigation/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/55-back-button-navigation/src/styles.scss b/apps/angular/55-back-button-navigation/src/styles.scss new file mode 100644 index 000000000..acd290007 --- /dev/null +++ b/apps/angular/55-back-button-navigation/src/styles.scss @@ -0,0 +1,29 @@ +@use '@angular/material' as mat; + +/* You can add global styles to this file, and also import other style files */ + +@tailwind base; +@tailwind components; +@tailwind utilities; + +@include mat.elevation-classes(); +@include mat.app-background(); + +$theme-primary: mat.m2-define-palette(mat.$m2-indigo-palette); +$theme-accent: mat.m2-define-palette(mat.$m2-pink-palette, A200, A100, A400); + +$theme-warn: mat.m2-define-palette(mat.$m2-red-palette); + +$theme: mat.m2-define-light-theme( + ( + color: ( + primary: $theme-primary, + accent: $theme-accent, + warn: $theme-warn, + ), + typography: mat.m2-define-typography-config(), + ) +); + +@include mat.dialog-theme($theme); +@include mat.button-theme($theme); diff --git a/apps/testing/checkbox/src/test-setup.ts b/apps/angular/55-back-button-navigation/src/test-setup.ts similarity index 100% rename from apps/testing/checkbox/src/test-setup.ts rename to apps/angular/55-back-button-navigation/src/test-setup.ts diff --git a/apps/performance/ngfor-biglist/tailwind.config.js b/apps/angular/55-back-button-navigation/tailwind.config.js similarity index 100% rename from apps/performance/ngfor-biglist/tailwind.config.js rename to apps/angular/55-back-button-navigation/tailwind.config.js diff --git a/apps/performance/ngfor-optimize/tsconfig.app.json b/apps/angular/55-back-button-navigation/tsconfig.app.json similarity index 100% rename from apps/performance/ngfor-optimize/tsconfig.app.json rename to apps/angular/55-back-button-navigation/tsconfig.app.json diff --git a/apps/angular/55-back-button-navigation/tsconfig.editor.json b/apps/angular/55-back-button-navigation/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/angular/55-back-button-navigation/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/angular/55-back-button-navigation/tsconfig.json b/apps/angular/55-back-button-navigation/tsconfig.json new file mode 100644 index 000000000..4383e7eb8 --- /dev/null +++ b/apps/angular/55-back-button-navigation/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/angular/55-back-button-navigation/tsconfig.spec.json b/apps/angular/55-back-button-navigation/tsconfig.spec.json new file mode 100644 index 000000000..1a4817a7d --- /dev/null +++ b/apps/angular/55-back-button-navigation/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "@testing-library/jest-dom"] + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/apps/ngrx/notification/.eslintrc.json b/apps/angular/57-content-projection-default/.eslintrc.json similarity index 100% rename from apps/ngrx/notification/.eslintrc.json rename to apps/angular/57-content-projection-default/.eslintrc.json diff --git a/apps/angular/57-content-projection-default/README.md b/apps/angular/57-content-projection-default/README.md new file mode 100644 index 000000000..fc4579558 --- /dev/null +++ b/apps/angular/57-content-projection-default/README.md @@ -0,0 +1,13 @@ +# Content Projection Default + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-content-projection-default +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/57-content-projection-default/). diff --git a/apps/angular/57-content-projection-default/project.json b/apps/angular/57-content-projection-default/project.json new file mode 100644 index 000000000..a57738bff --- /dev/null +++ b/apps/angular/57-content-projection-default/project.json @@ -0,0 +1,81 @@ +{ + "name": "angular-content-projection-default", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/57-content-projection-default/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/57-content-projection-default", + "index": "apps/angular/57-content-projection-default/src/index.html", + "browser": "apps/angular/57-content-projection-default/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/57-content-projection-default/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "apps/angular/57-content-projection-default/public" + } + ], + "styles": [ + "apps/angular/57-content-projection-default/src/styles.scss" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "4kb", + "maximumError": "8kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-content-projection-default:build:production" + }, + "development": { + "buildTarget": "angular-content-projection-default:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-content-projection-default:build" + } + }, + "serve-static": { + "executor": "@nx/web:file-server", + "options": { + "buildTarget": "angular-content-projection-default:build", + "staticFilePath": "dist/apps/angular/57-content-projection-default/browser", + "spa": true + } + } + } +} diff --git a/apps/ngrx/effect-selector/src/favicon.ico b/apps/angular/57-content-projection-default/public/favicon.ico similarity index 100% rename from apps/ngrx/effect-selector/src/favicon.ico rename to apps/angular/57-content-projection-default/public/favicon.ico diff --git a/apps/angular/57-content-projection-default/src/app/app.component.ts b/apps/angular/57-content-projection-default/src/app/app.component.ts new file mode 100644 index 000000000..b3e370a34 --- /dev/null +++ b/apps/angular/57-content-projection-default/src/app/app.component.ts @@ -0,0 +1,16 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { CardComponent } from './card.component'; + +@Component({ + imports: [CardComponent], + selector: 'app-root', + template: ` + + + `, + host: { + class: 'p-4 block flex flex-col gap-1', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent {} diff --git a/apps/angular/57-content-projection-default/src/app/app.config.ts b/apps/angular/57-content-projection-default/src/app/app.config.ts new file mode 100644 index 000000000..034603cfd --- /dev/null +++ b/apps/angular/57-content-projection-default/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [provideZoneChangeDetection({ eventCoalescing: true })], +}; diff --git a/apps/angular/57-content-projection-default/src/app/card.component.ts b/apps/angular/57-content-projection-default/src/app/card.component.ts new file mode 100644 index 000000000..851a6619d --- /dev/null +++ b/apps/angular/57-content-projection-default/src/app/card.component.ts @@ -0,0 +1,22 @@ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; + +@Component({ + selector: 'app-card', + imports: [], + template: ` +
{{ title() }}
+ @if (message()) { +
{{ message() }}
+ } @else { +
Aucun message
+ } + `, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'p-4 border border-grey rounded-sm flex flex-col w-[200px]', + }, +}) +export class CardComponent { + title = input.required(); + message = input(undefined); +} diff --git a/apps/angular/57-content-projection-default/src/index.html b/apps/angular/57-content-projection-default/src/index.html new file mode 100644 index 000000000..8b3015d4b --- /dev/null +++ b/apps/angular/57-content-projection-default/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-content-projection-default + + + + + + + + diff --git a/apps/angular/57-content-projection-default/src/main.ts b/apps/angular/57-content-projection-default/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/57-content-projection-default/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/performance/memoized/src/styles.scss b/apps/angular/57-content-projection-default/src/styles.scss similarity index 100% rename from apps/performance/memoized/src/styles.scss rename to apps/angular/57-content-projection-default/src/styles.scss diff --git a/apps/performance/ngfor-optimize/tailwind.config.js b/apps/angular/57-content-projection-default/tailwind.config.js similarity index 100% rename from apps/performance/ngfor-optimize/tailwind.config.js rename to apps/angular/57-content-projection-default/tailwind.config.js diff --git a/apps/performance/scroll-cd/tsconfig.app.json b/apps/angular/57-content-projection-default/tsconfig.app.json similarity index 100% rename from apps/performance/scroll-cd/tsconfig.app.json rename to apps/angular/57-content-projection-default/tsconfig.app.json diff --git a/apps/angular/57-content-projection-default/tsconfig.editor.json b/apps/angular/57-content-projection-default/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/angular/57-content-projection-default/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/angular/57-content-projection-default/tsconfig.json b/apps/angular/57-content-projection-default/tsconfig.json new file mode 100644 index 000000000..1b86db04e --- /dev/null +++ b/apps/angular/57-content-projection-default/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "es2022", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/rxjs/pipe-bug/.eslintrc.json b/apps/angular/58-content-projection-condition/.eslintrc.json similarity index 100% rename from apps/rxjs/pipe-bug/.eslintrc.json rename to apps/angular/58-content-projection-condition/.eslintrc.json diff --git a/apps/angular/58-content-projection-condition/README.md b/apps/angular/58-content-projection-condition/README.md new file mode 100644 index 000000000..755bd8854 --- /dev/null +++ b/apps/angular/58-content-projection-condition/README.md @@ -0,0 +1,13 @@ +# Content Projection Condition + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-content-projection-condition +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/58-content-projection-condition/). diff --git a/apps/angular/58-content-projection-condition/project.json b/apps/angular/58-content-projection-condition/project.json new file mode 100644 index 000000000..42869e68b --- /dev/null +++ b/apps/angular/58-content-projection-condition/project.json @@ -0,0 +1,84 @@ +{ + "name": "angular-content-projection-condition", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/58-content-projection-condition/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/58-content-projection-condition", + "index": "apps/angular/58-content-projection-condition/src/index.html", + "browser": "apps/angular/58-content-projection-condition/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/58-content-projection-condition/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "apps/angular/58-content-projection-condition/public" + } + ], + "styles": [ + "apps/angular/58-content-projection-condition/src/styles.scss" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "4kb", + "maximumError": "8kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-content-projection-condition:build:production" + }, + "development": { + "buildTarget": "angular-content-projection-condition:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-content-projection-condition:build" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + }, + "serve-static": { + "executor": "@nx/web:file-server", + "options": { + "buildTarget": "angular-content-projection-condition:build", + "staticFilePath": "dist/apps/angular/58-content-projection-condition/browser", + "spa": true + } + } + } +} diff --git a/apps/ngrx/notification/src/favicon.ico b/apps/angular/58-content-projection-condition/public/favicon.ico similarity index 100% rename from apps/ngrx/notification/src/favicon.ico rename to apps/angular/58-content-projection-condition/public/favicon.ico diff --git a/apps/angular/58-content-projection-condition/src/app/app.component.ts b/apps/angular/58-content-projection-condition/src/app/app.component.ts new file mode 100644 index 000000000..afad56f22 --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/app/app.component.ts @@ -0,0 +1,22 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { CardComponent } from './card.component'; + +@Component({ + imports: [CardComponent], + selector: 'app-root', + template: ` + +
Card 1
+
Message 1
+
+ +
Card 2
+
Message 2
+
+ `, + host: { + class: 'p-4 block flex flex-col gap-1', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent {} diff --git a/apps/angular/58-content-projection-condition/src/app/app.config.ts b/apps/angular/58-content-projection-condition/src/app/app.config.ts new file mode 100644 index 000000000..034603cfd --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [provideZoneChangeDetection({ eventCoalescing: true })], +}; diff --git a/apps/angular/58-content-projection-condition/src/app/card.component.ts b/apps/angular/58-content-projection-condition/src/app/card.component.ts new file mode 100644 index 000000000..46925977c --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/app/card.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; + +@Component({ + selector: 'app-card', + template: ` + @if (small()) { + + + } @else { +
+
+ +
+ +
+ } + `, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'p-4 border border-grey rounded-sm flex flex-col w-[200px]', + }, +}) +export class CardComponent { + small = input(false); +} diff --git a/apps/angular/58-content-projection-condition/src/index.html b/apps/angular/58-content-projection-condition/src/index.html new file mode 100644 index 000000000..f1768ec71 --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-content-projection-condition + + + + + + + + diff --git a/apps/angular/58-content-projection-condition/src/main.ts b/apps/angular/58-content-projection-condition/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/performance/ngfor-biglist/src/styles.scss b/apps/angular/58-content-projection-condition/src/styles.scss similarity index 100% rename from apps/performance/ngfor-biglist/src/styles.scss rename to apps/angular/58-content-projection-condition/src/styles.scss diff --git a/apps/rxjs/catch-error/tailwind.config.js b/apps/angular/58-content-projection-condition/tailwind.config.js similarity index 100% rename from apps/rxjs/catch-error/tailwind.config.js rename to apps/angular/58-content-projection-condition/tailwind.config.js diff --git a/apps/rxjs/catch-error/tsconfig.app.json b/apps/angular/58-content-projection-condition/tsconfig.app.json similarity index 100% rename from apps/rxjs/catch-error/tsconfig.app.json rename to apps/angular/58-content-projection-condition/tsconfig.app.json diff --git a/apps/angular/58-content-projection-condition/tsconfig.editor.json b/apps/angular/58-content-projection-condition/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/angular/58-content-projection-condition/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/angular/58-content-projection-condition/tsconfig.json b/apps/angular/58-content-projection-condition/tsconfig.json new file mode 100644 index 000000000..1b86db04e --- /dev/null +++ b/apps/angular/58-content-projection-condition/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "es2022", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/angular/59-content-projection-defer/.eslintrc.json b/apps/angular/59-content-projection-defer/.eslintrc.json new file mode 100644 index 000000000..995177b5b --- /dev/null +++ b/apps/angular/59-content-projection-defer/.eslintrc.json @@ -0,0 +1,37 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/component-class-suffix": "off", + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/angular/59-content-projection-defer/README.md b/apps/angular/59-content-projection-defer/README.md new file mode 100644 index 000000000..f726842d1 --- /dev/null +++ b/apps/angular/59-content-projection-defer/README.md @@ -0,0 +1,13 @@ +# content-projection-defer + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-content-projection-defer +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/59-content-projection-defer/). diff --git a/apps/angular/59-content-projection-defer/project.json b/apps/angular/59-content-projection-defer/project.json new file mode 100644 index 000000000..5572ab573 --- /dev/null +++ b/apps/angular/59-content-projection-defer/project.json @@ -0,0 +1,82 @@ +{ + "name": "angular-content-projection-defer", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/59-content-projection-defer/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/59-content-projection-defer", + "index": "apps/angular/59-content-projection-defer/src/index.html", + "browser": "apps/angular/59-content-projection-defer/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/59-content-projection-defer/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "apps/angular/59-content-projection-defer/public" + } + ], + "styles": ["apps/angular/59-content-projection-defer/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "4kb", + "maximumError": "8kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-content-projection-defer:build:production" + }, + "development": { + "buildTarget": "angular-content-projection-defer:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-content-projection-defer:build" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + }, + "serve-static": { + "executor": "@nx/web:file-server", + "options": { + "buildTarget": "angular-content-projection-defer:build", + "staticFilePath": "dist/apps/angular/59-content-projection-defer/browser", + "spa": true + } + } + } +} diff --git a/apps/performance/default-onpush/src/favicon.ico b/apps/angular/59-content-projection-defer/public/favicon.ico similarity index 100% rename from apps/performance/default-onpush/src/favicon.ico rename to apps/angular/59-content-projection-defer/public/favicon.ico diff --git a/apps/angular/59-content-projection-defer/src/app/app.component.ts b/apps/angular/59-content-projection-defer/src/app/app.component.ts new file mode 100644 index 000000000..ae40bc880 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/app.component.ts @@ -0,0 +1,23 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { RouterLink, RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet, RouterLink], + selector: 'app-root', + template: ` +
+ + +
+ + `, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'flex flex-col gap-2 ', + }, +}) +export class AppComponent {} diff --git a/apps/angular/59-content-projection-defer/src/app/app.config.ts b/apps/angular/59-content-projection-defer/src/app/app.config.ts new file mode 100644 index 000000000..faf4d099a --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/app.config.ts @@ -0,0 +1,12 @@ +import { provideHttpClient } from '@angular/common/http'; +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; +import { provideRouter } from '@angular/router'; +import { appRoutes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(appRoutes), + provideHttpClient(), + ], +}; diff --git a/apps/angular/59-content-projection-defer/src/app/app.routes.ts b/apps/angular/59-content-projection-defer/src/app/app.routes.ts new file mode 100644 index 000000000..3ca1b67cc --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/app.routes.ts @@ -0,0 +1,13 @@ +import { Route } from '@angular/router'; + +export const appRoutes: Route[] = [ + { + path: 'page-1', + loadComponent: () => import('./page-1').then((m) => m.Page1), + }, + { + path: 'page-2', + loadComponent: () => import('./page-2').then((m) => m.Page2), + }, + { path: '**', redirectTo: 'page-1' }, +]; diff --git a/apps/angular/59-content-projection-defer/src/app/expandable-card.ts b/apps/angular/59-content-projection-defer/src/app/expandable-card.ts new file mode 100644 index 000000000..8f446ed80 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/expandable-card.ts @@ -0,0 +1,54 @@ +import { ChangeDetectionStrategy, Component, signal } from '@angular/core'; + +@Component({ + selector: 'app-expandable-card', + template: ` + + +
+ +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'flex flex-col gap-2 ', + }, +}) +export class ExpandableCard { + public isExpanded = signal(false); +} diff --git a/apps/angular/59-content-projection-defer/src/app/page-1.ts b/apps/angular/59-content-projection-defer/src/app/page-1.ts new file mode 100644 index 000000000..868d76959 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/page-1.ts @@ -0,0 +1,10 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'app-page-1', + template: ` + page1 + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class Page1 {} diff --git a/apps/angular/59-content-projection-defer/src/app/page-2.ts b/apps/angular/59-content-projection-defer/src/app/page-2.ts new file mode 100644 index 000000000..5665466d8 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/page-2.ts @@ -0,0 +1,43 @@ +import { httpResource } from '@angular/common/http'; +import { + ChangeDetectionStrategy, + Component, + ResourceStatus, +} from '@angular/core'; +import { ExpandableCard } from './expandable-card'; + +interface Post { + id: number; + title: string; + body: string; + userId: number; +} + +@Component({ + selector: 'app-page-2', + template: ` + page2 + +
Load Post
+
+ @if (postResource.isLoading()) { + Loading... + } @else if (postResource.status() === ResourceStatus.Error) { + Error... + } @else { + @for (post of postResource.value(); track post.id) { +
{{ post.title }}
+ } + } +
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ExpandableCard], +}) +export class Page2 { + public postResource = httpResource( + 'https://jsonplaceholder.typicode.com/posts', + ); + protected readonly ResourceStatus = ResourceStatus; +} diff --git a/apps/angular/59-content-projection-defer/src/index.html b/apps/angular/59-content-projection-defer/src/index.html new file mode 100644 index 000000000..79f435fa6 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-content-projection-defer + + + + + + + + diff --git a/apps/angular/59-content-projection-defer/src/main.ts b/apps/angular/59-content-projection-defer/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/performance/ngfor-optimize/src/styles.scss b/apps/angular/59-content-projection-defer/src/styles.scss similarity index 100% rename from apps/performance/ngfor-optimize/src/styles.scss rename to apps/angular/59-content-projection-defer/src/styles.scss diff --git a/apps/testing/checkbox/tailwind.config.js b/apps/angular/59-content-projection-defer/tailwind.config.js similarity index 100% rename from apps/testing/checkbox/tailwind.config.js rename to apps/angular/59-content-projection-defer/tailwind.config.js diff --git a/apps/testing/checkbox/tsconfig.app.json b/apps/angular/59-content-projection-defer/tsconfig.app.json similarity index 100% rename from apps/testing/checkbox/tsconfig.app.json rename to apps/angular/59-content-projection-defer/tsconfig.app.json diff --git a/apps/angular/59-content-projection-defer/tsconfig.editor.json b/apps/angular/59-content-projection-defer/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/angular/59-content-projection-defer/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/angular/59-content-projection-defer/tsconfig.json b/apps/angular/59-content-projection-defer/tsconfig.json new file mode 100644 index 000000000..1b86db04e --- /dev/null +++ b/apps/angular/59-content-projection-defer/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "es2022", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/angular/6-structural-directive/.eslintrc.json b/apps/angular/6-structural-directive/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/angular/6-structural-directive/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/angular/6-structural-directive/README.md b/apps/angular/6-structural-directive/README.md new file mode 100644 index 000000000..775b40981 --- /dev/null +++ b/apps/angular/6-structural-directive/README.md @@ -0,0 +1,13 @@ +# Structural Directive + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-structural-directive +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/6-permissions/). diff --git a/apps/angular/6-structural-directive/project.json b/apps/angular/6-structural-directive/project.json new file mode 100644 index 000000000..f803b0cb5 --- /dev/null +++ b/apps/angular/6-structural-directive/project.json @@ -0,0 +1,72 @@ +{ + "name": "angular-structural-directive", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/6-structural-directive/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/6-structural-directive", + "index": "apps/angular/6-structural-directive/src/index.html", + "main": "apps/angular/6-structural-directive/src/main.ts", + "polyfills": "apps/angular/6-structural-directive/src/polyfills.ts", + "tsConfig": "apps/angular/6-structural-directive/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/6-structural-directive/src/favicon.ico", + "apps/angular/6-structural-directive/src/assets" + ], + "styles": ["apps/angular/6-structural-directive/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-structural-directive:build:production" + }, + "development": { + "buildTarget": "angular-structural-directive:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-structural-directive:build" + } + } + } +} diff --git a/apps/angular/6-structural-directive/src/app/app.component.ts b/apps/angular/6-structural-directive/src/app/app.component.ts new file mode 100644 index 000000000..a3d63b374 --- /dev/null +++ b/apps/angular/6-structural-directive/src/app/app.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet], + selector: 'app-root', + template: ` + + `, + styles: [], +}) +export class AppComponent {} diff --git a/apps/angular/permissions/src/app/app.config.ts b/apps/angular/6-structural-directive/src/app/app.config.ts similarity index 100% rename from apps/angular/permissions/src/app/app.config.ts rename to apps/angular/6-structural-directive/src/app/app.config.ts diff --git a/apps/angular/permissions/src/app/button.component.ts b/apps/angular/6-structural-directive/src/app/button.component.ts similarity index 88% rename from apps/angular/permissions/src/app/button.component.ts rename to apps/angular/6-structural-directive/src/app/button.component.ts index b6599e5ef..b1d59e8cc 100644 --- a/apps/angular/permissions/src/app/button.component.ts +++ b/apps/angular/6-structural-directive/src/app/button.component.ts @@ -4,7 +4,9 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ standalone: true, selector: 'button[app-button]', - template: ``, + template: ` + + `, host: { class: 'border border-blue-700 bg-blue-400 p-2 rounded-sm text-white', }, diff --git a/apps/angular/permissions/src/app/dashboard/admin.component.ts b/apps/angular/6-structural-directive/src/app/dashboard/admin.component.ts similarity index 95% rename from apps/angular/permissions/src/app/dashboard/admin.component.ts rename to apps/angular/6-structural-directive/src/app/dashboard/admin.component.ts index 72e4b3bef..26bb23284 100644 --- a/apps/angular/permissions/src/app/dashboard/admin.component.ts +++ b/apps/angular/6-structural-directive/src/app/dashboard/admin.component.ts @@ -4,7 +4,6 @@ import { ButtonComponent } from '../button.component'; @Component({ selector: 'app-dashboard', - standalone: true, imports: [RouterLink, ButtonComponent], template: `

dashboard for Admin works!

diff --git a/apps/angular/permissions/src/app/dashboard/manager.component.ts b/apps/angular/6-structural-directive/src/app/dashboard/manager.component.ts similarity index 100% rename from apps/angular/permissions/src/app/dashboard/manager.component.ts rename to apps/angular/6-structural-directive/src/app/dashboard/manager.component.ts diff --git a/apps/angular/permissions/src/app/information.component.ts b/apps/angular/6-structural-directive/src/app/information.component.ts similarity index 97% rename from apps/angular/permissions/src/app/information.component.ts rename to apps/angular/6-structural-directive/src/app/information.component.ts index e4adeb1b9..81b339520 100644 --- a/apps/angular/permissions/src/app/information.component.ts +++ b/apps/angular/6-structural-directive/src/app/information.component.ts @@ -4,7 +4,6 @@ import { UserStore } from './user.store'; @Component({ selector: 'app-information', - standalone: true, imports: [CommonModule], template: `

Information Panel

diff --git a/apps/angular/permissions/src/app/login.component.ts b/apps/angular/6-structural-directive/src/app/login.component.ts similarity index 88% rename from apps/angular/permissions/src/app/login.component.ts rename to apps/angular/6-structural-directive/src/app/login.component.ts index ab27b11ec..b8644ed38 100644 --- a/apps/angular/permissions/src/app/login.component.ts +++ b/apps/angular/6-structural-directive/src/app/login.component.ts @@ -14,11 +14,10 @@ import { import { UserStore } from './user.store'; @Component({ - standalone: true, imports: [InformationComponent, RouterLink, ButtonComponent], selector: 'app-login', template: ` -
+
Log as : @@ -26,12 +25,12 @@ import { UserStore } from './user.store'; - +
- `, diff --git a/apps/angular/6-structural-directive/src/app/routes.ts b/apps/angular/6-structural-directive/src/app/routes.ts new file mode 100644 index 000000000..4db203f3b --- /dev/null +++ b/apps/angular/6-structural-directive/src/app/routes.ts @@ -0,0 +1,14 @@ +export const APP_ROUTES = [ + { + path: '', + loadComponent: () => + import('./login.component').then((m) => m.LoginComponent), + }, + { + path: 'enter', + loadComponent: () => + import('./dashboard/admin.component').then( + (m) => m.AdminDashboardComponent, + ), + }, +]; diff --git a/apps/angular/permissions/src/app/user.model.ts b/apps/angular/6-structural-directive/src/app/user.model.ts similarity index 100% rename from apps/angular/permissions/src/app/user.model.ts rename to apps/angular/6-structural-directive/src/app/user.model.ts diff --git a/apps/angular/permissions/src/app/user.store.ts b/apps/angular/6-structural-directive/src/app/user.store.ts similarity index 100% rename from apps/angular/permissions/src/app/user.store.ts rename to apps/angular/6-structural-directive/src/app/user.store.ts diff --git a/apps/ngrx/effect-selector/src/assets/.gitkeep b/apps/angular/6-structural-directive/src/assets/.gitkeep similarity index 100% rename from apps/ngrx/effect-selector/src/assets/.gitkeep rename to apps/angular/6-structural-directive/src/assets/.gitkeep diff --git a/apps/performance/memoized/src/favicon.ico b/apps/angular/6-structural-directive/src/favicon.ico similarity index 100% rename from apps/performance/memoized/src/favicon.ico rename to apps/angular/6-structural-directive/src/favicon.ico diff --git a/apps/angular/6-structural-directive/src/index.html b/apps/angular/6-structural-directive/src/index.html new file mode 100644 index 000000000..8a35fb109 --- /dev/null +++ b/apps/angular/6-structural-directive/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-structural-directive + + + + + + + + diff --git a/apps/angular/6-structural-directive/src/main.ts b/apps/angular/6-structural-directive/src/main.ts new file mode 100644 index 000000000..7961924bf --- /dev/null +++ b/apps/angular/6-structural-directive/src/main.ts @@ -0,0 +1,8 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; + +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/pipe-hard/src/polyfills.ts b/apps/angular/6-structural-directive/src/polyfills.ts similarity index 100% rename from apps/angular/pipe-hard/src/polyfills.ts rename to apps/angular/6-structural-directive/src/polyfills.ts diff --git a/apps/rxjs/catch-error/src/styles.scss b/apps/angular/6-structural-directive/src/styles.scss similarity index 100% rename from apps/rxjs/catch-error/src/styles.scss rename to apps/angular/6-structural-directive/src/styles.scss diff --git a/apps/testing/create-harness/tailwind.config.js b/apps/angular/6-structural-directive/tailwind.config.js similarity index 100% rename from apps/testing/create-harness/tailwind.config.js rename to apps/angular/6-structural-directive/tailwind.config.js diff --git a/apps/angular/pipe-hard/tsconfig.app.json b/apps/angular/6-structural-directive/tsconfig.app.json similarity index 100% rename from apps/angular/pipe-hard/tsconfig.app.json rename to apps/angular/6-structural-directive/tsconfig.app.json diff --git a/apps/angular/pipe-easy/tsconfig.editor.json b/apps/angular/6-structural-directive/tsconfig.editor.json similarity index 100% rename from apps/angular/pipe-easy/tsconfig.editor.json rename to apps/angular/6-structural-directive/tsconfig.editor.json diff --git a/apps/angular/pipe-easy/tsconfig.json b/apps/angular/6-structural-directive/tsconfig.json similarity index 100% rename from apps/angular/pipe-easy/tsconfig.json rename to apps/angular/6-structural-directive/tsconfig.json diff --git a/apps/angular/8-pure-pipe/.eslintrc.json b/apps/angular/8-pure-pipe/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/angular/8-pure-pipe/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/angular/8-pure-pipe/README.md b/apps/angular/8-pure-pipe/README.md new file mode 100644 index 000000000..a65a33f85 --- /dev/null +++ b/apps/angular/8-pure-pipe/README.md @@ -0,0 +1,13 @@ +# Pure Pipe + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-pure-pipe +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/8-pipe-pure/). diff --git a/apps/angular/8-pure-pipe/project.json b/apps/angular/8-pure-pipe/project.json new file mode 100644 index 000000000..a684d542f --- /dev/null +++ b/apps/angular/8-pure-pipe/project.json @@ -0,0 +1,72 @@ +{ + "name": "angular-pure-pipe", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/8-pure-pipe/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/8-pure-pipe", + "index": "apps/angular/8-pure-pipe/src/index.html", + "main": "apps/angular/8-pure-pipe/src/main.ts", + "polyfills": "apps/angular/8-pure-pipe/src/polyfills.ts", + "tsConfig": "apps/angular/8-pure-pipe/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/8-pure-pipe/src/favicon.ico", + "apps/angular/8-pure-pipe/src/assets" + ], + "styles": ["apps/angular/8-pure-pipe/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-pure-pipe:build:production" + }, + "development": { + "buildTarget": "angular-pure-pipe:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-pure-pipe:build" + } + } + } +} diff --git a/apps/angular/8-pure-pipe/src/app/app.component.ts b/apps/angular/8-pure-pipe/src/app/app.component.ts new file mode 100644 index 000000000..41dd38e25 --- /dev/null +++ b/apps/angular/8-pure-pipe/src/app/app.component.ts @@ -0,0 +1,20 @@ +import { NgFor } from '@angular/common'; +import { Component } from '@angular/core'; + +@Component({ + imports: [NgFor], + selector: 'app-root', + template: ` +
+ {{ heavyComputation(person, index) }} +
+ `, +}) +export class AppComponent { + persons = ['toto', 'jack']; + + heavyComputation(name: string, index: number) { + // very heavy computation + return `${name} - ${index}`; + } +} diff --git a/apps/ngrx/notification/src/assets/.gitkeep b/apps/angular/8-pure-pipe/src/assets/.gitkeep similarity index 100% rename from apps/ngrx/notification/src/assets/.gitkeep rename to apps/angular/8-pure-pipe/src/assets/.gitkeep diff --git a/apps/performance/ngfor-biglist/src/favicon.ico b/apps/angular/8-pure-pipe/src/favicon.ico similarity index 100% rename from apps/performance/ngfor-biglist/src/favicon.ico rename to apps/angular/8-pure-pipe/src/favicon.ico diff --git a/apps/angular/8-pure-pipe/src/index.html b/apps/angular/8-pure-pipe/src/index.html new file mode 100644 index 000000000..c8ee70b97 --- /dev/null +++ b/apps/angular/8-pure-pipe/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-pure-pipe + + + + + + + + diff --git a/apps/angular/pipe-intermediate/src/main.ts b/apps/angular/8-pure-pipe/src/main.ts similarity index 100% rename from apps/angular/pipe-intermediate/src/main.ts rename to apps/angular/8-pure-pipe/src/main.ts diff --git a/apps/angular/pipe-intermediate/src/polyfills.ts b/apps/angular/8-pure-pipe/src/polyfills.ts similarity index 100% rename from apps/angular/pipe-intermediate/src/polyfills.ts rename to apps/angular/8-pure-pipe/src/polyfills.ts diff --git a/apps/angular/router-input/src/styles.scss b/apps/angular/8-pure-pipe/src/styles.scss similarity index 100% rename from apps/angular/router-input/src/styles.scss rename to apps/angular/8-pure-pipe/src/styles.scss diff --git a/apps/angular/pipe-intermediate/tsconfig.app.json b/apps/angular/8-pure-pipe/tsconfig.app.json similarity index 100% rename from apps/angular/pipe-intermediate/tsconfig.app.json rename to apps/angular/8-pure-pipe/tsconfig.app.json diff --git a/apps/angular/pipe-hard/tsconfig.editor.json b/apps/angular/8-pure-pipe/tsconfig.editor.json similarity index 100% rename from apps/angular/pipe-hard/tsconfig.editor.json rename to apps/angular/8-pure-pipe/tsconfig.editor.json diff --git a/apps/angular/pipe-hard/tsconfig.json b/apps/angular/8-pure-pipe/tsconfig.json similarity index 100% rename from apps/angular/pipe-hard/tsconfig.json rename to apps/angular/8-pure-pipe/tsconfig.json diff --git a/apps/angular/9-wrap-function-pipe/.eslintrc.json b/apps/angular/9-wrap-function-pipe/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/angular/9-wrap-function-pipe/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/angular/9-wrap-function-pipe/README.md b/apps/angular/9-wrap-function-pipe/README.md new file mode 100644 index 000000000..1491e7dda --- /dev/null +++ b/apps/angular/9-wrap-function-pipe/README.md @@ -0,0 +1,13 @@ +# Wrap Function Pipe + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-wrap-function-pipe +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/9-pipe-wrapFn/). diff --git a/apps/angular/9-wrap-function-pipe/project.json b/apps/angular/9-wrap-function-pipe/project.json new file mode 100644 index 000000000..dc5c4ab6e --- /dev/null +++ b/apps/angular/9-wrap-function-pipe/project.json @@ -0,0 +1,72 @@ +{ + "name": "angular-wrap-function-pipe", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/angular/9-wrap-function-pipe/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/9-wrap-function-pipe", + "index": "apps/angular/9-wrap-function-pipe/src/index.html", + "main": "apps/angular/9-wrap-function-pipe/src/main.ts", + "polyfills": "apps/angular/9-wrap-function-pipe/src/polyfills.ts", + "tsConfig": "apps/angular/9-wrap-function-pipe/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/angular/9-wrap-function-pipe/src/favicon.ico", + "apps/angular/9-wrap-function-pipe/src/assets" + ], + "styles": ["apps/angular/9-wrap-function-pipe/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-wrap-function-pipe:build:production" + }, + "development": { + "buildTarget": "angular-wrap-function-pipe:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-wrap-function-pipe:build" + } + } + } +} diff --git a/apps/angular/9-wrap-function-pipe/src/app/app.component.ts b/apps/angular/9-wrap-function-pipe/src/app/app.component.ts new file mode 100644 index 000000000..dd576ae49 --- /dev/null +++ b/apps/angular/9-wrap-function-pipe/src/app/app.component.ts @@ -0,0 +1,33 @@ +import { NgFor } from '@angular/common'; +import { Component } from '@angular/core'; + +@Component({ + imports: [NgFor], + selector: 'app-root', + template: ` +
+ {{ showName(person.name, index) }} + {{ isAllowed(person.age, isFirst) }} +
+ `, +}) +export class AppComponent { + persons = [ + { name: 'Toto', age: 10 }, + { name: 'Jack', age: 15 }, + { name: 'John', age: 30 }, + ]; + + showName(name: string, index: number) { + // very heavy computation + return `${name} - ${index}`; + } + + isAllowed(age: number, isFirst: boolean) { + if (isFirst) { + return 'always allowed'; + } else { + return age > 25 ? 'allowed' : 'declined'; + } + } +} diff --git a/apps/performance/default-onpush/src/assets/.gitkeep b/apps/angular/9-wrap-function-pipe/src/assets/.gitkeep similarity index 100% rename from apps/performance/default-onpush/src/assets/.gitkeep rename to apps/angular/9-wrap-function-pipe/src/assets/.gitkeep diff --git a/apps/performance/ngfor-optimize/src/favicon.ico b/apps/angular/9-wrap-function-pipe/src/favicon.ico similarity index 100% rename from apps/performance/ngfor-optimize/src/favicon.ico rename to apps/angular/9-wrap-function-pipe/src/favicon.ico diff --git a/apps/angular/9-wrap-function-pipe/src/index.html b/apps/angular/9-wrap-function-pipe/src/index.html new file mode 100644 index 000000000..bc8a0ddbd --- /dev/null +++ b/apps/angular/9-wrap-function-pipe/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-wrap-function-pipe + + + + + + + + diff --git a/apps/performance/scroll-cd/src/main.ts b/apps/angular/9-wrap-function-pipe/src/main.ts similarity index 100% rename from apps/performance/scroll-cd/src/main.ts rename to apps/angular/9-wrap-function-pipe/src/main.ts diff --git a/apps/angular/projection/src/polyfills.ts b/apps/angular/9-wrap-function-pipe/src/polyfills.ts similarity index 100% rename from apps/angular/projection/src/polyfills.ts rename to apps/angular/9-wrap-function-pipe/src/polyfills.ts diff --git a/apps/angular/styling/src/styles.scss b/apps/angular/9-wrap-function-pipe/src/styles.scss similarity index 100% rename from apps/angular/styling/src/styles.scss rename to apps/angular/9-wrap-function-pipe/src/styles.scss diff --git a/apps/angular/projection/tsconfig.app.json b/apps/angular/9-wrap-function-pipe/tsconfig.app.json similarity index 100% rename from apps/angular/projection/tsconfig.app.json rename to apps/angular/9-wrap-function-pipe/tsconfig.app.json diff --git a/apps/angular/pipe-intermediate/tsconfig.editor.json b/apps/angular/9-wrap-function-pipe/tsconfig.editor.json similarity index 100% rename from apps/angular/pipe-intermediate/tsconfig.editor.json rename to apps/angular/9-wrap-function-pipe/tsconfig.editor.json diff --git a/apps/angular/pipe-intermediate/tsconfig.json b/apps/angular/9-wrap-function-pipe/tsconfig.json similarity index 100% rename from apps/angular/pipe-intermediate/tsconfig.json rename to apps/angular/9-wrap-function-pipe/tsconfig.json diff --git a/apps/angular/anchor-scrolling/README.md b/apps/angular/anchor-scrolling/README.md deleted file mode 100644 index c6ffb7ff9..000000000 --- a/apps/angular/anchor-scrolling/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Anchor Navigation - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-anchor-scrolling -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/21-achor-scrolling/). diff --git a/apps/angular/anchor-scrolling/jest.config.ts b/apps/angular/anchor-scrolling/jest.config.ts deleted file mode 100644 index 6915111a0..000000000 --- a/apps/angular/anchor-scrolling/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'angular-anchor-scrolling', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - coverageDirectory: '../../../coverage/apps/angular/anchor-scrolling', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/angular/anchor-scrolling/project.json b/apps/angular/anchor-scrolling/project.json deleted file mode 100644 index 7b8f88e2c..000000000 --- a/apps/angular/anchor-scrolling/project.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "name": "angular-anchor-scrolling", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/anchor-scrolling/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/anchor-scrolling", - "index": "apps/angular/anchor-scrolling/src/index.html", - "main": "apps/angular/anchor-scrolling/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/anchor-scrolling/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/anchor-scrolling/src/favicon.ico", - "apps/angular/anchor-scrolling/src/assets" - ], - "styles": ["apps/angular/anchor-scrolling/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-anchor-scrolling:build:production" - }, - "development": { - "browserTarget": "angular-anchor-scrolling:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-anchor-scrolling:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/anchor-scrolling/**/*.ts", - "apps/angular/anchor-scrolling/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/angular/anchor-scrolling/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - } - }, - "tags": [] -} diff --git a/apps/angular/anchor-scrolling/src/app/app.component.ts b/apps/angular/anchor-scrolling/src/app/app.component.ts deleted file mode 100644 index 5a930fb82..000000000 --- a/apps/angular/anchor-scrolling/src/app/app.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; - -@Component({ - standalone: true, - imports: [RouterOutlet], - selector: 'app-root', - template: ` `, -}) -export class AppComponent {} diff --git a/apps/angular/anchor-scrolling/src/app/foo.component.ts b/apps/angular/anchor-scrolling/src/app/foo.component.ts deleted file mode 100644 index a5109a848..000000000 --- a/apps/angular/anchor-scrolling/src/app/foo.component.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Component } from '@angular/core'; -import { NavButtonComponent } from './nav-button.component'; - -@Component({ - standalone: true, - imports: [NavButtonComponent], - selector: 'app-foo', - template: ` - Welcome to foo page - Home Page -
section 1
-
section 2
- `, -}) -export class FooComponent {} diff --git a/apps/angular/anchor-scrolling/src/app/home.component.ts b/apps/angular/anchor-scrolling/src/app/home.component.ts deleted file mode 100644 index 836a19803..000000000 --- a/apps/angular/anchor-scrolling/src/app/home.component.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component } from '@angular/core'; -import { NavButtonComponent } from './nav-button.component'; - -@Component({ - standalone: true, - imports: [NavButtonComponent], - selector: 'app-home', - template: ` - Foo Page -
- Empty - Scroll Bottom -
-
- I want to scroll each - Scroll Top -
- `, -}) -export class HomeComponent {} diff --git a/apps/angular/anchor-scrolling/src/index.html b/apps/angular/anchor-scrolling/src/index.html deleted file mode 100644 index 9a98ab32f..000000000 --- a/apps/angular/anchor-scrolling/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - AnchorScrolling - - - - - - - - diff --git a/apps/angular/anchor-scrolling/src/main.ts b/apps/angular/anchor-scrolling/src/main.ts deleted file mode 100644 index 4ecc5cf6a..000000000 --- a/apps/angular/anchor-scrolling/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { appConfig } from './app/app.config'; -import { bootstrapApplication } from '@angular/platform-browser'; - -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/angular/bug-cd/README.md b/apps/angular/bug-cd/README.md deleted file mode 100644 index 5f0e3b437..000000000 --- a/apps/angular/bug-cd/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Change Detection Bug - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-bug-cd -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/32-bug-cd/). diff --git a/apps/angular/bug-cd/jest.config.ts b/apps/angular/bug-cd/jest.config.ts deleted file mode 100644 index 1f24a7ce5..000000000 --- a/apps/angular/bug-cd/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'angular-bug-cd', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - coverageDirectory: '../../../coverage/apps/angular/bug-cd', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/angular/bug-cd/project.json b/apps/angular/bug-cd/project.json deleted file mode 100644 index 14690cf50..000000000 --- a/apps/angular/bug-cd/project.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "name": "angular-bug-cd", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/angular/bug-cd/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/bug-cd", - "index": "apps/angular/bug-cd/src/index.html", - "main": "apps/angular/bug-cd/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/bug-cd/tsconfig.app.json", - "assets": [ - "apps/angular/bug-cd/src/favicon.ico", - "apps/angular/bug-cd/src/assets" - ], - "styles": ["apps/angular/bug-cd/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-bug-cd:build:production" - }, - "development": { - "browserTarget": "angular-bug-cd:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-bug-cd:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/bug-cd/**/*.ts", - "apps/angular/bug-cd/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/angular/bug-cd/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - } - } -} diff --git a/apps/angular/bug-cd/src/app/app.component.ts b/apps/angular/bug-cd/src/app/app.component.ts deleted file mode 100644 index 3b45baa0f..000000000 --- a/apps/angular/bug-cd/src/app/app.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; - -@Component({ - standalone: true, - imports: [RouterOutlet], - selector: 'app-root', - template: ` -

My Application

-
- -
- -
-
- `, - host: { - class: 'flex flex-col gap-2', - }, -}) -export class AppComponent {} diff --git a/apps/angular/bug-cd/src/app/foo.component.ts b/apps/angular/bug-cd/src/app/foo.component.ts deleted file mode 100644 index 8006ecb17..000000000 --- a/apps/angular/bug-cd/src/app/foo.component.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Component } from '@angular/core'; -@Component({ - selector: 'app-foo', - standalone: true, - template: `Foo Component `, -}) -export class FooComponent {} diff --git a/apps/angular/bug-cd/src/index.html b/apps/angular/bug-cd/src/index.html deleted file mode 100644 index c05f4150d..000000000 --- a/apps/angular/bug-cd/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - test - - - - - - - - diff --git a/apps/angular/bug-cd/src/main.ts b/apps/angular/bug-cd/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/angular/bug-cd/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/angular/context-outlet-type/README.md b/apps/angular/context-outlet-type/README.md deleted file mode 100644 index c7eb23bfc..000000000 --- a/apps/angular/context-outlet-type/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Typed ContextOutlet - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-context-outlet-type -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/4-context-outlet-typed/). diff --git a/apps/angular/context-outlet-type/project.json b/apps/angular/context-outlet-type/project.json deleted file mode 100644 index 76a22cdbb..000000000 --- a/apps/angular/context-outlet-type/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-context-outlet-type", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/context-outlet-type/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/context-outlet-type", - "index": "apps/angular/context-outlet-type/src/index.html", - "main": "apps/angular/context-outlet-type/src/main.ts", - "polyfills": "apps/angular/context-outlet-type/src/polyfills.ts", - "tsConfig": "apps/angular/context-outlet-type/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/context-outlet-type/src/favicon.ico", - "apps/angular/context-outlet-type/src/assets" - ], - "styles": ["apps/angular/context-outlet-type/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-context-outlet-type:build:production" - }, - "development": { - "browserTarget": "angular-context-outlet-type:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-context-outlet-type:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/angular/context-outlet-type/**/*.ts", - "apps/angular/context-outlet-type/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/angular/context-outlet-type/src/app/app.component.ts b/apps/angular/context-outlet-type/src/app/app.component.ts deleted file mode 100644 index 2683ba9d4..000000000 --- a/apps/angular/context-outlet-type/src/app/app.component.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { NgTemplateOutlet } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { ListComponent } from './list.component'; -import { PersonComponent } from './person.component'; - -@Component({ - standalone: true, - imports: [NgTemplateOutlet, PersonComponent, ListComponent], - selector: 'app-root', - template: ` - - - {{ name }}: {{ age }} - - - - - - {{ student.name }}: {{ student.age }} - {{ i }} - - - - - - {{ city.name }}: {{ city.country }} - {{ i }} - - - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AppComponent { - person = { - name: 'toto', - age: 3, - }; - - students = [ - { name: 'toto', age: 3 }, - { name: 'titi', age: 4 }, - ]; - - cities = [ - { name: 'Paris', country: 'France' }, - { name: 'Berlin', country: 'Germany' }, - ]; -} diff --git a/apps/angular/context-outlet-type/src/app/list.component.ts b/apps/angular/context-outlet-type/src/app/list.component.ts deleted file mode 100644 index 4c58a1c1d..000000000 --- a/apps/angular/context-outlet-type/src/app/list.component.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { - ChangeDetectionStrategy, - Component, - ContentChild, - Input, - TemplateRef, -} from '@angular/core'; - -@Component({ - selector: 'list', - standalone: true, - imports: [CommonModule], - template: ` -
- - -
- - No Template - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ListComponent { - @Input() list!: TItem[]; - - @ContentChild('listRef', { read: TemplateRef }) - listTemplateRef!: TemplateRef; -} diff --git a/apps/angular/context-outlet-type/src/index.html b/apps/angular/context-outlet-type/src/index.html deleted file mode 100644 index 0f087d314..000000000 --- a/apps/angular/context-outlet-type/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - ContextOutletType - - - - - - - - diff --git a/apps/angular/crud/README.md b/apps/angular/crud/README.md deleted file mode 100644 index e351dc1ff..000000000 --- a/apps/angular/crud/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Crud application - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-crud -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/5-crud/). diff --git a/apps/angular/crud/jest.config.ts b/apps/angular/crud/jest.config.ts deleted file mode 100644 index 74a17f135..000000000 --- a/apps/angular/crud/jest.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'angular-crud', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../../coverage/apps/angular/crud', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/angular/crud/project.json b/apps/angular/crud/project.json deleted file mode 100644 index 143cfa87f..000000000 --- a/apps/angular/crud/project.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "name": "angular-crud", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/crud/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/crud", - "index": "apps/angular/crud/src/index.html", - "main": "apps/angular/crud/src/main.ts", - "polyfills": "apps/angular/crud/src/polyfills.ts", - "tsConfig": "apps/angular/crud/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/crud/src/favicon.ico", - "apps/angular/crud/src/assets" - ], - "styles": [ - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", - "apps/angular/crud/src/styles.scss" - ], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-crud:build:production" - }, - "development": { - "browserTarget": "angular-crud:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-crud:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/angular/crud/**/*.ts", - "apps/angular/crud/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/angular/crud/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] -} diff --git a/apps/angular/crud/src/app/app.component.ts b/apps/angular/crud/src/app/app.component.ts deleted file mode 100644 index 400d4038a..000000000 --- a/apps/angular/crud/src/app/app.component.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { HttpClient } from '@angular/common/http'; -import { Component, OnInit } from '@angular/core'; -import { randText } from '@ngneat/falso'; - -@Component({ - standalone: true, - imports: [CommonModule], - selector: 'app-root', - template: ` -
- {{ todo.title }} - -
- `, - styles: [], -}) -export class AppComponent implements OnInit { - todos!: any[]; - - constructor(private http: HttpClient) {} - - ngOnInit(): void { - this.http - .get('https://jsonplaceholder.typicode.com/todos') - .subscribe((todos) => { - this.todos = todos; - }); - } - - update(todo: any) { - this.http - .put( - `https://jsonplaceholder.typicode.com/todos/${todo.id}`, - JSON.stringify({ - todo: todo.id, - title: randText(), - body: todo.body, - userId: todo.userId, - }), - { - headers: { - 'Content-type': 'application/json; charset=UTF-8', - }, - } - ) - .subscribe((todoUpdated: any) => { - this.todos[todoUpdated.id - 1] = todoUpdated; - }); - } -} diff --git a/apps/angular/crud/src/app/app.config.ts b/apps/angular/crud/src/app/app.config.ts deleted file mode 100644 index cf4075bfa..000000000 --- a/apps/angular/crud/src/app/app.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ApplicationConfig } from '@angular/core'; -import { enableProdMode, importProvidersFrom } from '@angular/core'; -import { HttpClientModule } from '@angular/common/http'; -export const appConfig: ApplicationConfig = { - providers: [importProvidersFrom(HttpClientModule)], -}; diff --git a/apps/angular/crud/src/index.html b/apps/angular/crud/src/index.html deleted file mode 100644 index 601c3591e..000000000 --- a/apps/angular/crud/src/index.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Http - - - - - - - - - - - diff --git a/apps/angular/crud/src/main.ts b/apps/angular/crud/src/main.ts deleted file mode 100644 index ea9f26cc8..000000000 --- a/apps/angular/crud/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { appConfig } from './app/app.config'; - -import { bootstrapApplication } from '@angular/platform-browser'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/angular/decoupling/README.md b/apps/angular/decoupling/README.md deleted file mode 100644 index faea6043f..000000000 --- a/apps/angular/decoupling/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Decoupling Components - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-decoupling -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/33-decoupling/). diff --git a/apps/angular/decoupling/project.json b/apps/angular/decoupling/project.json deleted file mode 100644 index 4269e89cd..000000000 --- a/apps/angular/decoupling/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-decoupling", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/angular/decoupling/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/decoupling", - "index": "apps/angular/decoupling/src/index.html", - "main": "apps/angular/decoupling/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/decoupling/tsconfig.app.json", - "assets": [ - "apps/angular/decoupling/src/favicon.ico", - "apps/angular/decoupling/src/assets" - ], - "styles": ["apps/angular/decoupling/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-decoupling:build:production" - }, - "development": { - "browserTarget": "angular-decoupling:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-decoupling:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/decoupling/**/*.ts", - "apps/angular/decoupling/**/*.html" - ] - } - } - } -} diff --git a/apps/angular/decoupling/src/app/app.component.ts b/apps/angular/decoupling/src/app/app.component.ts deleted file mode 100644 index e595318b4..000000000 --- a/apps/angular/decoupling/src/app/app.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { BtnDisabledDirective } from '@angular-challenges/decoupling/brain'; -import { BtnHelmetDirective } from '@angular-challenges/decoupling/helmet'; -import { Component } from '@angular/core'; - -@Component({ - standalone: true, - imports: [BtnDisabledDirective, BtnHelmetDirective], - selector: 'app-root', - template: ` `, -}) -export class AppComponent {} diff --git a/apps/angular/decoupling/src/index.html b/apps/angular/decoupling/src/index.html deleted file mode 100644 index c1bf2b795..000000000 --- a/apps/angular/decoupling/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - decoupling - - - - - - - - diff --git a/apps/angular/di/README.md b/apps/angular/di/README.md deleted file mode 100644 index e41c9113c..000000000 --- a/apps/angular/di/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Master Dependancy Injection - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-di -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/16-di/). diff --git a/apps/angular/di/project.json b/apps/angular/di/project.json deleted file mode 100644 index 23f373cba..000000000 --- a/apps/angular/di/project.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "name": "angular-di", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/di/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/di", - "index": "apps/angular/di/src/index.html", - "main": "apps/angular/di/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/di/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/di/src/favicon.ico", - "apps/angular/di/src/assets" - ], - "styles": ["apps/angular/di/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-di:build:production" - }, - "development": { - "browserTarget": "angular-di:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-di:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/di/**/*.ts", - "apps/angular/di/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/angular/di/src/app/app.component.ts b/apps/angular/di/src/app/app.component.ts deleted file mode 100644 index bacff72f6..000000000 --- a/apps/angular/di/src/app/app.component.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { TableComponent } from '@angular-challenges/angular/di'; -import { AsyncPipe, NgFor } from '@angular/common'; -import { Component, Directive } from '@angular/core'; -import { CurrencyPipe } from './currency.pipe'; -import { CurrencyService } from './currency.service'; -import { Product, products } from './product.model'; - -interface ProductContext { - $implicit: Product; -} - -@Directive({ - selector: 'ng-template[product]', - standalone: true, -}) -export class ProductDirective { - static ngTemplateContextGuard( - dir: ProductDirective, - ctx: unknown - ): ctx is ProductContext { - return true; - } -} - -@Component({ - standalone: true, - imports: [TableComponent, CurrencyPipe, AsyncPipe, NgFor, ProductDirective], - providers: [CurrencyService], - selector: 'app-root', - template: ` - - - - - - - - - - - - - - -
- {{ col }} -
{{ product.name }}{{ product.priceA | currency | async }}{{ product.priceB | currency | async }}{{ product.priceC | currency | async }}
- `, -}) -export class AppComponent { - products = products; - displayedColumns = ['name', 'priceA', 'priceB', 'priceC']; -} diff --git a/apps/angular/di/src/app/currency.pipe.ts b/apps/angular/di/src/app/currency.pipe.ts deleted file mode 100644 index 1c8fcc068..000000000 --- a/apps/angular/di/src/app/currency.pipe.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { inject, Pipe, PipeTransform } from '@angular/core'; -import { map } from 'rxjs'; -import { CurrencyService } from './currency.service'; - -@Pipe({ - name: 'currency', - standalone: true, -}) -export class CurrencyPipe implements PipeTransform { - currencyService = inject(CurrencyService); - - transform(price: number) { - return this.currencyService.symbol$.pipe( - map((s) => `${String(price)}${s}`) - ); - } -} diff --git a/apps/angular/di/src/app/currency.service.ts b/apps/angular/di/src/app/currency.service.ts deleted file mode 100644 index 076ffa130..000000000 --- a/apps/angular/di/src/app/currency.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Injectable } from '@angular/core'; -import { ComponentStore } from '@ngrx/component-store'; -import { map } from 'rxjs'; - -export interface Currency { - name: string; - code: string; - symbol: string; -} - -export const currency: Currency[] = [ - { name: 'Euro', code: 'EUR', symbol: '€' }, - { name: 'Dollar US', code: 'USD', symbol: 'US$' }, - { name: 'Dollar Autralien', code: 'AUD', symbol: 'AU$' }, - { name: 'Livre Sterling', code: 'GBP', symbol: '£' }, - { name: 'Dollar Canadien', code: 'CAD', symbol: 'CAD' }, -]; - -@Injectable() -export class CurrencyService extends ComponentStore<{ code: string }> { - readonly code$ = this.select((state) => state.code); - readonly symbol$ = this.code$.pipe( - map((code) => currency.find((c) => c.code === code)?.symbol ?? code) - ); - - constructor() { - super({ code: 'EUR' }); - } -} diff --git a/apps/angular/di/src/index.html b/apps/angular/di/src/index.html deleted file mode 100644 index 98e94c05e..000000000 --- a/apps/angular/di/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Di - - - - - - - - diff --git a/apps/angular/injection-token/README.md b/apps/angular/injection-token/README.md deleted file mode 100644 index 8764b23b2..000000000 --- a/apps/angular/injection-token/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# InjectionToken - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-injection-token -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/39-injection-token/). diff --git a/apps/angular/injection-token/jest.config.ts b/apps/angular/injection-token/jest.config.ts deleted file mode 100644 index d7105f89b..000000000 --- a/apps/angular/injection-token/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'angular-injection-token', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - coverageDirectory: '../../../coverage/apps/angular/injection-token', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/angular/injection-token/project.json b/apps/angular/injection-token/project.json deleted file mode 100644 index 149b5f89e..000000000 --- a/apps/angular/injection-token/project.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "name": "angular-injection-token", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/angular/injection-token/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/injection-token", - "index": "apps/angular/injection-token/src/index.html", - "main": "apps/angular/injection-token/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/injection-token/tsconfig.app.json", - "assets": [ - "apps/angular/injection-token/src/favicon.ico", - "apps/angular/injection-token/src/assets" - ], - "styles": ["apps/angular/injection-token/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-injection-token:build:production" - }, - "development": { - "browserTarget": "angular-injection-token:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-injection-token:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/injection-token/**/*.ts", - "apps/angular/injection-token/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/angular/injection-token/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - } - } -} diff --git a/apps/angular/injection-token/src/app/app.component.ts b/apps/angular/injection-token/src/app/app.component.ts deleted file mode 100644 index 51cf42eac..000000000 --- a/apps/angular/injection-token/src/app/app.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterLink, RouterOutlet } from '@angular/router'; - -@Component({ - standalone: true, - imports: [RouterOutlet, RouterLink], - selector: 'app-root', - template: `
- - -
- `, - host: { - class: 'p-10 flex flex-col', - }, -}) -export class AppComponent {} diff --git a/apps/angular/injection-token/src/index.html b/apps/angular/injection-token/src/index.html deleted file mode 100644 index befe4cfe4..000000000 --- a/apps/angular/injection-token/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - angular-injection-token - - - - - - - - diff --git a/apps/angular/injection-token/src/main.ts b/apps/angular/injection-token/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/angular/injection-token/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/angular/interop-rxjs-signal/README.md b/apps/angular/interop-rxjs-signal/README.md deleted file mode 100644 index d137b0947..000000000 --- a/apps/angular/interop-rxjs-signal/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Interoperability Rxjs/Signal - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-interop-rxjs-signal -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/30-interop-rxjs-signal/). diff --git a/apps/angular/interop-rxjs-signal/jest.config.ts b/apps/angular/interop-rxjs-signal/jest.config.ts deleted file mode 100644 index 23956ebcc..000000000 --- a/apps/angular/interop-rxjs-signal/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'angular-interop-rxjs-signal', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - coverageDirectory: '../../../coverage/apps/angular/interop-rxjs-signal', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/angular/interop-rxjs-signal/project.json b/apps/angular/interop-rxjs-signal/project.json deleted file mode 100644 index b0946b5eb..000000000 --- a/apps/angular/interop-rxjs-signal/project.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "name": "angular-interop-rxjs-signal", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/angular/interop-rxjs-signal/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/interop-rxjs-signal", - "index": "apps/angular/interop-rxjs-signal/src/index.html", - "main": "apps/angular/interop-rxjs-signal/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/interop-rxjs-signal/tsconfig.app.json", - "assets": [ - "apps/angular/interop-rxjs-signal/src/favicon.ico", - "apps/angular/interop-rxjs-signal/src/assets" - ], - "styles": [ - "apps/angular/interop-rxjs-signal/src/styles.scss", - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" - ], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-interop-rxjs-signal:build:production" - }, - "development": { - "browserTarget": "angular-interop-rxjs-signal:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-interop-rxjs-signal:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/interop-rxjs-signal/**/*.ts", - "apps/angular/interop-rxjs-signal/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/angular/interop-rxjs-signal/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - } - } -} diff --git a/apps/angular/interop-rxjs-signal/src/app/app.component.ts b/apps/angular/interop-rxjs-signal/src/app/app.component.ts deleted file mode 100644 index f63192ece..000000000 --- a/apps/angular/interop-rxjs-signal/src/app/app.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; - -@Component({ - standalone: true, - imports: [RouterOutlet], - selector: 'app-root', - template: ``, - styles: [''], -}) -export class AppComponent {} diff --git a/apps/angular/interop-rxjs-signal/src/app/app.config.ts b/apps/angular/interop-rxjs-signal/src/app/app.config.ts deleted file mode 100644 index cd49643a4..000000000 --- a/apps/angular/interop-rxjs-signal/src/app/app.config.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { provideHttpClient } from '@angular/common/http'; -import { ApplicationConfig } from '@angular/core'; -import { provideAnimations } from '@angular/platform-browser/animations'; -import { provideRouter, withComponentInputBinding } from '@angular/router'; - -export const appConfig: ApplicationConfig = { - providers: [ - provideHttpClient(), - provideAnimations(), - provideRouter( - [ - { - path: '', - pathMatch: 'full', - loadComponent: () => import('./list/photos.component'), - }, - { - path: 'detail', - loadComponent: () => import('./detail/detail.component'), - }, - { - path: '**', - redirectTo: '', - }, - ], - withComponentInputBinding() - ), - ], -}; diff --git a/apps/angular/interop-rxjs-signal/src/app/detail/detail.component.ts b/apps/angular/interop-rxjs-signal/src/app/detail/detail.component.ts deleted file mode 100644 index c1493b2fa..000000000 --- a/apps/angular/interop-rxjs-signal/src/app/detail/detail.component.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { DatePipe } from '@angular/common'; -import { Component, Input as RouterInput } from '@angular/core'; -import { RouterLink } from '@angular/router'; -import { Photo } from '../photo.model'; - -@Component({ - selector: 'app-photos', - standalone: true, - imports: [DatePipe, RouterLink], - template: ` - {{ photo.title }} -

Title: {{ photo.title }}

-

Owner: {{ photo.ownername }}

-

Date: {{ photo.datetaken | date }}

-

Tags: {{ photo.tags }}

- - - `, - host: { - class: 'p-5 block', - }, -}) -export default class DetailComponent { - @RouterInput({ - required: true, - transform: (value: string) => JSON.parse(decodeURIComponent(value)), - }) - photo!: Photo; -} diff --git a/apps/angular/interop-rxjs-signal/src/app/photo.model.ts b/apps/angular/interop-rxjs-signal/src/app/photo.model.ts deleted file mode 100644 index 5c78a91b8..000000000 --- a/apps/angular/interop-rxjs-signal/src/app/photo.model.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface Photo { - id: string; - title: string; - tags: string; - owner: string; - ownername: string; - datetaken: string; - url_q: string; - url_m: string; -} diff --git a/apps/angular/interop-rxjs-signal/src/index.html b/apps/angular/interop-rxjs-signal/src/index.html deleted file mode 100644 index b072aa460..000000000 --- a/apps/angular/interop-rxjs-signal/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - rxjs-to-signal - - - - - - - - diff --git a/apps/angular/interop-rxjs-signal/src/main.ts b/apps/angular/interop-rxjs-signal/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/angular/interop-rxjs-signal/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/angular/module-to-standalone/README.md b/apps/angular/module-to-standalone/README.md deleted file mode 100644 index fbbade2c2..000000000 --- a/apps/angular/module-to-standalone/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Module to Standalone - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-module-to-standalone -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/31-module-to-standalone/). diff --git a/apps/angular/module-to-standalone/project.json b/apps/angular/module-to-standalone/project.json deleted file mode 100644 index fc5b08a28..000000000 --- a/apps/angular/module-to-standalone/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-module-to-standalone", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/angular/module-to-standalone/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/module-to-standalone", - "index": "apps/angular/module-to-standalone/src/index.html", - "main": "apps/angular/module-to-standalone/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/module-to-standalone/tsconfig.app.json", - "assets": [ - "apps/angular/module-to-standalone/src/favicon.ico", - "apps/angular/module-to-standalone/src/assets" - ], - "styles": ["apps/angular/module-to-standalone/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-module-to-standalone:build:production" - }, - "development": { - "browserTarget": "angular-module-to-standalone:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-module-to-standalone:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/module-to-standalone/**/*.ts", - "apps/angular/module-to-standalone/**/*.html" - ] - } - } - } -} diff --git a/apps/angular/module-to-standalone/src/app/app.component.ts b/apps/angular/module-to-standalone/src/app/app.component.ts deleted file mode 100644 index 91a72fa4b..000000000 --- a/apps/angular/module-to-standalone/src/app/app.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-root', - template: `
- - - -
- `, - host: { - class: 'flex flex-col p-4 gap-3', - }, -}) -export class AppComponent {} diff --git a/apps/angular/module-to-standalone/src/index.html b/apps/angular/module-to-standalone/src/index.html deleted file mode 100644 index 153133d5c..000000000 --- a/apps/angular/module-to-standalone/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - module-to-standalone - - - - - - - - diff --git a/apps/angular/ngfor-enhancement/README.md b/apps/angular/ngfor-enhancement/README.md deleted file mode 100644 index 0a849c04e..000000000 --- a/apps/angular/ngfor-enhancement/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Directive Enhancement - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-ngfor-enhancement -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/3-directive-enhancement/). diff --git a/apps/angular/ngfor-enhancement/project.json b/apps/angular/ngfor-enhancement/project.json deleted file mode 100644 index 6ab9c34ec..000000000 --- a/apps/angular/ngfor-enhancement/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-ngfor-enhancement", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/ngfor-enhancement/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/ngfor-enhancement", - "index": "apps/angular/ngfor-enhancement/src/index.html", - "main": "apps/angular/ngfor-enhancement/src/main.ts", - "polyfills": "apps/angular/ngfor-enhancement/src/polyfills.ts", - "tsConfig": "apps/angular/ngfor-enhancement/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/ngfor-enhancement/src/favicon.ico", - "apps/angular/ngfor-enhancement/src/assets" - ], - "styles": ["apps/angular/ngfor-enhancement/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-ngfor-enhancement:build:production" - }, - "development": { - "browserTarget": "angular-ngfor-enhancement:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-ngfor-enhancement:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/angular/ngfor-enhancement/**/*.ts", - "apps/angular/ngfor-enhancement/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/angular/ngfor-enhancement/src/app/app.component.ts b/apps/angular/ngfor-enhancement/src/app/app.component.ts deleted file mode 100644 index cd1d5f23c..000000000 --- a/apps/angular/ngfor-enhancement/src/app/app.component.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { NgFor, NgIf } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; - -interface Person { - name: string; -} - -@Component({ - standalone: true, - imports: [NgFor, NgIf], - selector: 'app-root', - template: ` - -
- {{ person.name }} -
-
- The list is empty !! - `, - styles: [], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AppComponent { - persons: Person[] = []; -} diff --git a/apps/angular/ngfor-enhancement/src/index.html b/apps/angular/ngfor-enhancement/src/index.html deleted file mode 100644 index 02e3b691d..000000000 --- a/apps/angular/ngfor-enhancement/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - NgForEnhance - - - - - - - - diff --git a/apps/angular/permissions/README.md b/apps/angular/permissions/README.md deleted file mode 100644 index bf791878f..000000000 --- a/apps/angular/permissions/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Structural Directive - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-permissions -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/6-permissions/). diff --git a/apps/angular/permissions/project.json b/apps/angular/permissions/project.json deleted file mode 100644 index 04a31fa9c..000000000 --- a/apps/angular/permissions/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-permissions", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/permissions/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/permissions", - "index": "apps/angular/permissions/src/index.html", - "main": "apps/angular/permissions/src/main.ts", - "polyfills": "apps/angular/permissions/src/polyfills.ts", - "tsConfig": "apps/angular/permissions/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/permissions/src/favicon.ico", - "apps/angular/permissions/src/assets" - ], - "styles": ["apps/angular/permissions/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-permissions:build:production" - }, - "development": { - "browserTarget": "angular-permissions:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-permissions:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/angular/permissions/**/*.ts", - "apps/angular/permissions/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/angular/permissions/src/app/app.component.ts b/apps/angular/permissions/src/app/app.component.ts deleted file mode 100644 index 5fc4531c1..000000000 --- a/apps/angular/permissions/src/app/app.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; - -@Component({ - standalone: true, - imports: [RouterOutlet], - selector: 'app-root', - template: ` `, - styles: [], -}) -export class AppComponent {} diff --git a/apps/angular/permissions/src/app/routes.ts b/apps/angular/permissions/src/app/routes.ts deleted file mode 100644 index 79a3eccfa..000000000 --- a/apps/angular/permissions/src/app/routes.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const APP_ROUTES = [ - { - path: '', - loadComponent: () => - import('./login.component').then((m) => m.LoginComponent), - }, - { - path: 'enter', - loadComponent: () => - import('./dashboard/admin.component').then( - (m) => m.AdminDashboardComponent - ), - }, -]; diff --git a/apps/angular/permissions/src/index.html b/apps/angular/permissions/src/index.html deleted file mode 100644 index b78cf57c3..000000000 --- a/apps/angular/permissions/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Permissions - - - - - - - - diff --git a/apps/angular/permissions/src/main.ts b/apps/angular/permissions/src/main.ts deleted file mode 100644 index 567931936..000000000 --- a/apps/angular/permissions/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; - -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/angular/pipe-easy/README.md b/apps/angular/pipe-easy/README.md deleted file mode 100644 index 350a0d58f..000000000 --- a/apps/angular/pipe-easy/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Pure Pipe - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-pipe-easy -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/8-pipe-pure/). diff --git a/apps/angular/pipe-easy/project.json b/apps/angular/pipe-easy/project.json deleted file mode 100644 index 5c841686d..000000000 --- a/apps/angular/pipe-easy/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-pipe-easy", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/pipe-easy/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/pipe-easy", - "index": "apps/angular/pipe-easy/src/index.html", - "main": "apps/angular/pipe-easy/src/main.ts", - "polyfills": "apps/angular/pipe-easy/src/polyfills.ts", - "tsConfig": "apps/angular/pipe-easy/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/pipe-easy/src/favicon.ico", - "apps/angular/pipe-easy/src/assets" - ], - "styles": ["apps/angular/pipe-easy/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-pipe-easy:build:production" - }, - "development": { - "browserTarget": "angular-pipe-easy:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-pipe-easy:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/angular/pipe-easy/**/*.ts", - "apps/angular/pipe-easy/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/angular/pipe-easy/src/app/app.component.ts b/apps/angular/pipe-easy/src/app/app.component.ts deleted file mode 100644 index 3c19fa169..000000000 --- a/apps/angular/pipe-easy/src/app/app.component.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NgFor } from '@angular/common'; -import { Component } from '@angular/core'; - -@Component({ - standalone: true, - imports: [NgFor], - selector: 'app-root', - template: ` -
- {{ heavyComputation(person, index) }} -
- `, -}) -export class AppComponent { - persons = ['toto', 'jack']; - - heavyComputation(name: string, index: number) { - // very heavy computation - return `${name} - ${index}`; - } -} diff --git a/apps/angular/pipe-easy/src/index.html b/apps/angular/pipe-easy/src/index.html deleted file mode 100644 index 63b45d4ea..000000000 --- a/apps/angular/pipe-easy/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - PipeEasy - - - - - - - - diff --git a/apps/angular/pipe-hard/README.md b/apps/angular/pipe-hard/README.md deleted file mode 100644 index d86000ed8..000000000 --- a/apps/angular/pipe-hard/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Utility Wrapper Pipe - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-pipe-hard -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/10-pipe-utility/). diff --git a/apps/angular/pipe-hard/project.json b/apps/angular/pipe-hard/project.json deleted file mode 100644 index 0f721fd56..000000000 --- a/apps/angular/pipe-hard/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-pipe-hard", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/pipe-hard/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/pipe-hard", - "index": "apps/angular/pipe-hard/src/index.html", - "main": "apps/angular/pipe-hard/src/main.ts", - "polyfills": "apps/angular/pipe-hard/src/polyfills.ts", - "tsConfig": "apps/angular/pipe-hard/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/pipe-hard/src/favicon.ico", - "apps/angular/pipe-hard/src/assets" - ], - "styles": ["apps/angular/pipe-hard/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-pipe-hard:build:production" - }, - "development": { - "browserTarget": "angular-pipe-hard:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-pipe-hard:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/angular/pipe-hard/**/*.ts", - "apps/angular/pipe-hard/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/angular/pipe-hard/src/app/app.component.ts b/apps/angular/pipe-hard/src/app/app.component.ts deleted file mode 100644 index d91fc7436..000000000 --- a/apps/angular/pipe-hard/src/app/app.component.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { NgFor } from '@angular/common'; -import { Component } from '@angular/core'; -import { PersonUtils } from './person.utils'; - -@Component({ - standalone: true, - imports: [NgFor], - selector: 'app-root', - template: ` -
- {{ activity.name }} : -
- {{ showName(person.name, index) }} - {{ isAllowed(person.age, isFirst, activity.minimumAge) }} -
-
- `, -}) -export class AppComponent { - persons = [ - { name: 'Toto', age: 10 }, - { name: 'Jack', age: 15 }, - { name: 'John', age: 30 }, - ]; - - activities = [ - { name: 'biking', minimumAge: 12 }, - { name: 'hiking', minimumAge: 25 }, - { name: 'dancing', minimumAge: 1 }, - ]; - - showName = PersonUtils.showName; - - isAllowed = PersonUtils.isAllowed; -} diff --git a/apps/angular/pipe-hard/src/index.html b/apps/angular/pipe-hard/src/index.html deleted file mode 100644 index 748c8e6c1..000000000 --- a/apps/angular/pipe-hard/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - PipeHard - - - - - - - - diff --git a/apps/angular/pipe-intermediate/README.md b/apps/angular/pipe-intermediate/README.md deleted file mode 100644 index 78fa327e2..000000000 --- a/apps/angular/pipe-intermediate/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Wrap Function Pipe - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-pipe-intermediate -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/9-pipe-wrapFn/). diff --git a/apps/angular/pipe-intermediate/project.json b/apps/angular/pipe-intermediate/project.json deleted file mode 100644 index dc5e83b65..000000000 --- a/apps/angular/pipe-intermediate/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-pipe-intermediate", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/pipe-intermediate/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/pipe-intermediate", - "index": "apps/angular/pipe-intermediate/src/index.html", - "main": "apps/angular/pipe-intermediate/src/main.ts", - "polyfills": "apps/angular/pipe-intermediate/src/polyfills.ts", - "tsConfig": "apps/angular/pipe-intermediate/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/pipe-intermediate/src/favicon.ico", - "apps/angular/pipe-intermediate/src/assets" - ], - "styles": ["apps/angular/pipe-intermediate/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-pipe-intermediate:build:production" - }, - "development": { - "browserTarget": "angular-pipe-intermediate:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-pipe-intermediate:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/angular/pipe-intermediate/**/*.ts", - "apps/angular/pipe-intermediate/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/angular/pipe-intermediate/src/app/app.component.ts b/apps/angular/pipe-intermediate/src/app/app.component.ts deleted file mode 100644 index d9c163c93..000000000 --- a/apps/angular/pipe-intermediate/src/app/app.component.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NgFor } from '@angular/common'; -import { Component } from '@angular/core'; - -@Component({ - standalone: true, - imports: [NgFor], - selector: 'app-root', - template: ` -
- {{ showName(person.name, index) }} - {{ isAllowed(person.age, isFirst) }} -
- `, -}) -export class AppComponent { - persons = [ - { name: 'Toto', age: 10 }, - { name: 'Jack', age: 15 }, - { name: 'John', age: 30 }, - ]; - - showName(name: string, index: number) { - // very heavy computation - return `${name} - ${index}`; - } - - isAllowed(age: number, isFirst: boolean) { - if (isFirst) { - return 'always allowed'; - } else { - return age > 25 ? 'allowed' : 'declined'; - } - } -} diff --git a/apps/angular/pipe-intermediate/src/index.html b/apps/angular/pipe-intermediate/src/index.html deleted file mode 100644 index 07ccccc2e..000000000 --- a/apps/angular/pipe-intermediate/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - PipeIntermediate - - - - - - - - diff --git a/apps/angular/projection/README.md b/apps/angular/projection/README.md deleted file mode 100644 index 4d89c98ef..000000000 --- a/apps/angular/projection/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Projection - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-projection -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/1-projection/). diff --git a/apps/angular/projection/jest.config.ts b/apps/angular/projection/jest.config.ts deleted file mode 100644 index 289a9b0e3..000000000 --- a/apps/angular/projection/jest.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'angular-projection', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../../coverage/apps/angular/projection', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/angular/projection/project.json b/apps/angular/projection/project.json deleted file mode 100644 index ef4521ed8..000000000 --- a/apps/angular/projection/project.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "name": "angular-projection", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/projection/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/projection", - "index": "apps/angular/projection/src/index.html", - "main": "apps/angular/projection/src/main.ts", - "polyfills": "apps/angular/projection/src/polyfills.ts", - "tsConfig": "apps/angular/projection/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/projection/src/favicon.ico", - "apps/angular/projection/src/assets" - ], - "styles": ["apps/angular/projection/src/styles.scss"], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-projection:build:production" - }, - "development": { - "browserTarget": "angular-projection:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-projection:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/angular/projection/**/*.ts", - "apps/angular/projection/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/angular/projection/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] -} diff --git a/apps/angular/projection/src/app/app.component.ts b/apps/angular/projection/src/app/app.component.ts deleted file mode 100644 index b1d076a9f..000000000 --- a/apps/angular/projection/src/app/app.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Component } from '@angular/core'; -import { CityCardComponent } from './component/city-card/city-card.component'; -import { StudentCardComponent } from './component/student-card/student-card.component'; -import { TeacherCardComponent } from './component/teacher-card/teacher-card.component'; - -@Component({ - selector: 'app-root', - template: ` -
- - - -
- `, - standalone: true, - imports: [TeacherCardComponent, StudentCardComponent, CityCardComponent], -}) -export class AppComponent {} diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts deleted file mode 100644 index 30c8f88ec..000000000 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-city-card', - template: 'TODO City', - standalone: true, - imports: [], -}) -export class CityCardComponent implements OnInit { - constructor() {} - - ngOnInit(): void {} -} diff --git a/apps/angular/projection/src/app/component/student-card/student-card.component.ts b/apps/angular/projection/src/app/component/student-card/student-card.component.ts deleted file mode 100644 index 421630af5..000000000 --- a/apps/angular/projection/src/app/component/student-card/student-card.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { FakeHttpService } from '../../data-access/fake-http.service'; -import { StudentStore } from '../../data-access/student.store'; -import { CardType } from '../../model/card.model'; -import { Student } from '../../model/student.model'; -import { CardComponent } from '../../ui/card/card.component'; - -@Component({ - selector: 'app-student-card', - template: ``, - standalone: true, - styles: [ - ` - ::ng-deep .bg-light-green { - background-color: rgba(0, 250, 0, 0.1); - } - `, - ], - imports: [CardComponent], -}) -export class StudentCardComponent implements OnInit { - students: Student[] = []; - cardType = CardType.STUDENT; - - constructor(private http: FakeHttpService, private store: StudentStore) {} - - ngOnInit(): void { - this.http.fetchStudents$.subscribe((s) => this.store.addAll(s)); - - this.store.students$.subscribe((s) => (this.students = s)); - } -} diff --git a/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts b/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts deleted file mode 100644 index 006b8dbe4..000000000 --- a/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { FakeHttpService } from '../../data-access/fake-http.service'; -import { TeacherStore } from '../../data-access/teacher.store'; -import { CardType } from '../../model/card.model'; -import { Teacher } from '../../model/teacher.model'; -import { CardComponent } from '../../ui/card/card.component'; - -@Component({ - selector: 'app-teacher-card', - template: ``, - styles: [ - ` - ::ng-deep .bg-light-red { - background-color: rgba(250, 0, 0, 0.1); - } - `, - ], - standalone: true, - imports: [CardComponent], -}) -export class TeacherCardComponent implements OnInit { - teachers: Teacher[] = []; - cardType = CardType.TEACHER; - - constructor(private http: FakeHttpService, private store: TeacherStore) {} - - ngOnInit(): void { - this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t)); - - this.store.teachers$.subscribe((t) => (this.teachers = t)); - } -} diff --git a/apps/angular/projection/src/app/data-access/student.store.ts b/apps/angular/projection/src/app/data-access/student.store.ts deleted file mode 100644 index 7918118c3..000000000 --- a/apps/angular/projection/src/app/data-access/student.store.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; -import { Student } from '../model/student.model'; - -@Injectable({ - providedIn: 'root', -}) -export class StudentStore { - private students = new BehaviorSubject([]); - students$ = this.students.asObservable(); - - addAll(students: Student[]) { - this.students.next(students); - } - - addOne(student: Student) { - this.students.next([...this.students.value, student]); - } - - deleteOne(id: number) { - this.students.next(this.students.value.filter((s) => s.id !== id)); - } -} diff --git a/apps/angular/projection/src/app/data-access/teacher.store.ts b/apps/angular/projection/src/app/data-access/teacher.store.ts deleted file mode 100644 index 93f68c4b1..000000000 --- a/apps/angular/projection/src/app/data-access/teacher.store.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; -import { Teacher } from '../model/teacher.model'; - -@Injectable({ - providedIn: 'root', -}) -export class TeacherStore { - private teachers = new BehaviorSubject([]); - teachers$ = this.teachers.asObservable(); - - addAll(teachers: Teacher[]) { - this.teachers.next(teachers); - } - - addOne(teacher: Teacher) { - this.teachers.next([...this.teachers.value, teacher]); - } - - deleteOne(id: number) { - this.teachers.next(this.teachers.value.filter((t) => t.id !== id)); - } -} diff --git a/apps/angular/projection/src/app/model/student.model.ts b/apps/angular/projection/src/app/model/student.model.ts deleted file mode 100644 index 00592d402..000000000 --- a/apps/angular/projection/src/app/model/student.model.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Teacher } from './teacher.model'; - -export interface Student { - id: number; - firstname: string; - lastname: string; - mainTeacher: Teacher; - school: string; -} diff --git a/apps/angular/projection/src/app/model/teacher.model.ts b/apps/angular/projection/src/app/model/teacher.model.ts deleted file mode 100644 index e90438848..000000000 --- a/apps/angular/projection/src/app/model/teacher.model.ts +++ /dev/null @@ -1,15 +0,0 @@ -export const subject = [ - 'Sciences', - 'History', - 'English', - 'Maths', - 'Sport', -] as const; -export type Subject = (typeof subject)[number]; - -export interface Teacher { - id: number; - firstname: string; - lastname: string; - subject: Subject; -} diff --git a/apps/angular/projection/src/app/ui/card/card.component.html b/apps/angular/projection/src/app/ui/card/card.component.html deleted file mode 100644 index 81affa10a..000000000 --- a/apps/angular/projection/src/app/ui/card/card.component.html +++ /dev/null @@ -1,27 +0,0 @@ -
- - - -
- - -
- - -
diff --git a/apps/angular/projection/src/app/ui/card/card.component.ts b/apps/angular/projection/src/app/ui/card/card.component.ts deleted file mode 100644 index 37dd70849..000000000 --- a/apps/angular/projection/src/app/ui/card/card.component.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NgFor, NgIf } from '@angular/common'; -import { Component, Input } from '@angular/core'; -import { randStudent, randTeacher } from '../../data-access/fake-http.service'; -import { StudentStore } from '../../data-access/student.store'; -import { TeacherStore } from '../../data-access/teacher.store'; -import { CardType } from '../../model/card.model'; -import { ListItemComponent } from '../list-item/list-item.component'; - -@Component({ - selector: 'app-card', - templateUrl: './card.component.html', - standalone: true, - imports: [NgIf, NgFor, ListItemComponent], -}) -export class CardComponent { - @Input() list: any[] | null = null; - @Input() type!: CardType; - @Input() customClass = ''; - - CardType = CardType; - - constructor( - private teacherStore: TeacherStore, - private studentStore: StudentStore - ) {} - - addNewItem() { - if (this.type === CardType.TEACHER) { - this.teacherStore.addOne(randTeacher()); - } else if (this.type === CardType.STUDENT) { - this.studentStore.addOne(randStudent()); - } - } -} diff --git a/apps/angular/projection/src/app/ui/list-item/list-item.component.ts b/apps/angular/projection/src/app/ui/list-item/list-item.component.ts deleted file mode 100644 index 225860269..000000000 --- a/apps/angular/projection/src/app/ui/list-item/list-item.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, Input } from '@angular/core'; -import { StudentStore } from '../../data-access/student.store'; -import { TeacherStore } from '../../data-access/teacher.store'; -import { CardType } from '../../model/card.model'; - -@Component({ - selector: 'app-list-item', - template: ` -
- {{ name }} - -
- `, - standalone: true, -}) -export class ListItemComponent { - @Input() id!: number; - @Input() name!: string; - @Input() type!: CardType; - - constructor( - private teacherStore: TeacherStore, - private studentStore: StudentStore - ) {} - - delete(id: number) { - if (this.type === CardType.TEACHER) { - this.teacherStore.deleteOne(id); - } else if (this.type === CardType.STUDENT) { - this.studentStore.deleteOne(id); - } - } -} diff --git a/apps/angular/projection/src/index.html b/apps/angular/projection/src/index.html deleted file mode 100644 index 5083d8a6a..000000000 --- a/apps/angular/projection/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Projection - - - - - - - - diff --git a/apps/angular/projection/src/main.ts b/apps/angular/projection/src/main.ts deleted file mode 100644 index 9cd15da95..000000000 --- a/apps/angular/projection/src/main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent); diff --git a/apps/angular/router-input/README.md b/apps/angular/router-input/README.md deleted file mode 100644 index c213e1068..000000000 --- a/apps/angular/router-input/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# @RouterInput() - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-router-input -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/22-router-input/). diff --git a/apps/angular/router-input/project.json b/apps/angular/router-input/project.json deleted file mode 100644 index d4f2fe8b1..000000000 --- a/apps/angular/router-input/project.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "angular-router-input", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/angular/router-input/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/router-input", - "index": "apps/angular/router-input/src/index.html", - "main": "apps/angular/router-input/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/router-input/tsconfig.app.json", - "assets": [ - "apps/angular/router-input/src/favicon.ico", - "apps/angular/router-input/src/assets" - ], - "styles": ["apps/angular/router-input/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-router-input:build:production" - }, - "development": { - "browserTarget": "angular-router-input:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-router-input:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/router-input/**/*.ts", - "apps/angular/router-input/**/*.html" - ] - } - } - } -} diff --git a/apps/angular/router-input/src/app/app.component.ts b/apps/angular/router-input/src/app/app.component.ts deleted file mode 100644 index 1883309d5..000000000 --- a/apps/angular/router-input/src/app/app.component.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Component } from '@angular/core'; -import { FormControl, ReactiveFormsModule } from '@angular/forms'; -import { RouterLink, RouterModule } from '@angular/router'; - -@Component({ - standalone: true, - imports: [RouterLink, RouterModule, ReactiveFormsModule], - selector: 'app-root', - template: ` - - - - - - `, -}) -export class AppComponent { - userName = new FormControl(); - testId = new FormControl(); -} diff --git a/apps/angular/router-input/src/app/app.routes.ts b/apps/angular/router-input/src/app/app.routes.ts deleted file mode 100644 index 215c016b2..000000000 --- a/apps/angular/router-input/src/app/app.routes.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Route } from '@angular/router'; - -export const appRoutes: Route[] = [ - { - path: '', - loadComponent: () => import('./home.component'), - }, - { - path: 'test/:testId', - loadComponent: () => import('./test.component'), - data: { - permission: 'admin', - }, - }, -]; diff --git a/apps/angular/router-input/src/app/home.component.ts b/apps/angular/router-input/src/app/home.component.ts deleted file mode 100644 index be6a891fa..000000000 --- a/apps/angular/router-input/src/app/home.component.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Component } from '@angular/core'; -@Component({ - selector: 'app-home', - standalone: true, - imports: [], - template: `
Home
`, -}) -export default class HomeComponent {} diff --git a/apps/angular/router-input/src/index.html b/apps/angular/router-input/src/index.html deleted file mode 100644 index 43f4b7999..000000000 --- a/apps/angular/router-input/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - router-input - - - - - - - - diff --git a/apps/angular/router-input/src/main.ts b/apps/angular/router-input/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/angular/router-input/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/angular/styling/README.md b/apps/angular/styling/README.md deleted file mode 100644 index 760a772d1..000000000 --- a/apps/angular/styling/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Highly Customizable CSS - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve angular-styling -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/13-styling/). diff --git a/apps/angular/styling/project.json b/apps/angular/styling/project.json deleted file mode 100644 index 93cc89585..000000000 --- a/apps/angular/styling/project.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "name": "angular-styling", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/angular/styling/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/angular/styling", - "index": "apps/angular/styling/src/index.html", - "main": "apps/angular/styling/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/angular/styling/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/angular/styling/src/favicon.ico", - "apps/angular/styling/src/assets" - ], - "styles": ["apps/angular/styling/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "angular-styling:build:production" - }, - "development": { - "browserTarget": "angular-styling:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "angular-styling:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/angular/styling/**/*.ts", - "apps/angular/styling/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/angular/styling/src/app/page.component.ts b/apps/angular/styling/src/app/page.component.ts deleted file mode 100644 index a37864725..000000000 --- a/apps/angular/styling/src/app/page.component.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* eslint-disable @angular-eslint/component-selector */ -import { Component } from '@angular/core'; -import { TextStaticComponent } from './static-text.component'; -import { TextComponent } from './text.component'; - -@Component({ - selector: 'page', - standalone: true, - imports: [TextStaticComponent, TextComponent], - template: ` - - - - This a a blue text - `, -}) -export class PageComponent {} diff --git a/apps/angular/styling/src/index.html b/apps/angular/styling/src/index.html deleted file mode 100644 index 67d4296bb..000000000 --- a/apps/angular/styling/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Styling - - - - - - - - diff --git a/apps/forms/41-control-value-accessor/.eslintrc.json b/apps/forms/41-control-value-accessor/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/forms/41-control-value-accessor/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/forms/41-control-value-accessor/README.md b/apps/forms/41-control-value-accessor/README.md new file mode 100644 index 000000000..a91920ad2 --- /dev/null +++ b/apps/forms/41-control-value-accessor/README.md @@ -0,0 +1,13 @@ +# Control Value Accessor + +> author: stanislav-gavrilov + +### Run Application + +```bash +npx nx serve forms-control-value-accessor +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/forms/41-control-value-accessor/). diff --git a/apps/forms/41-control-value-accessor/jest.config.ts b/apps/forms/41-control-value-accessor/jest.config.ts new file mode 100644 index 000000000..48769acef --- /dev/null +++ b/apps/forms/41-control-value-accessor/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'forms-control-value-accessor', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/forms/41-control-value-accessor', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/forms/41-control-value-accessor/project.json b/apps/forms/41-control-value-accessor/project.json new file mode 100644 index 000000000..a1ec26bac --- /dev/null +++ b/apps/forms/41-control-value-accessor/project.json @@ -0,0 +1,80 @@ +{ + "name": "forms-control-value-accessor", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/forms/41-control-value-accessor/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/forms/41-control-value-accessor", + "index": "apps/forms/41-control-value-accessor/src/index.html", + "browser": "apps/forms/41-control-value-accessor/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/forms/41-control-value-accessor/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/forms/41-control-value-accessor/src/favicon.ico", + "apps/forms/41-control-value-accessor/src/assets" + ], + "styles": ["apps/forms/41-control-value-accessor/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "forms-control-value-accessor:build:production" + }, + "development": { + "buildTarget": "forms-control-value-accessor:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "forms-control-value-accessor:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/forms/41-control-value-accessor/src/app/app.component.ts b/apps/forms/41-control-value-accessor/src/app/app.component.ts new file mode 100644 index 000000000..69134b864 --- /dev/null +++ b/apps/forms/41-control-value-accessor/src/app/app.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { FeedbackFormComponent } from './feedback-form/feedback-form.component'; + +@Component({ + imports: [FeedbackFormComponent], + selector: 'app-root', + template: ` + + `, +}) +export class AppComponent { + apiCall(event: Record): void { + console.log(event); + } +} diff --git a/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.html b/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.html new file mode 100644 index 000000000..9334b5bc9 --- /dev/null +++ b/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.html @@ -0,0 +1,29 @@ + diff --git a/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.scss b/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.scss new file mode 100644 index 000000000..ac4868a38 --- /dev/null +++ b/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.scss @@ -0,0 +1,50 @@ +* { + box-sizing: border-box; +} + +:host { + display: block; + padding: 20px; +} + +.feedback-form { + display: flex; + flex-direction: column; + width: 500px; + padding: 20px; + border: 1px solid #000000; +} + +.feedback-form-title { + margin-bottom: 20px; + font-size: 24px; +} + +.feedback-form-control { + max-height: 200px; + margin-bottom: 20px; + padding: 12px 12px 12px 20px; + border-radius: 0; + background-color: #fbfbfb; + color: #3c3c3c; + font-size: 18px; + + &:focus { + padding: 10px 10px 10px 18px; + border: 2px solid #054ada; + outline: none; + background: #fff; + } +} + +.feedback-form-submit { + padding: 10px; + background-color: #054ada; + color: #ffffff; + font-size: 18px; + + &[disabled] { + background-color: #cccccc; + color: #ffffff; + } +} diff --git a/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.ts b/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.ts new file mode 100644 index 000000000..4110d6cf7 --- /dev/null +++ b/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.ts @@ -0,0 +1,41 @@ +import { Component, EventEmitter, Output } from '@angular/core'; +import { + FormControl, + FormGroup, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { RatingControlComponent } from '../rating-control/rating-control.component'; + +@Component({ + imports: [RatingControlComponent, ReactiveFormsModule], + selector: 'app-feedback-form', + templateUrl: 'feedback-form.component.html', + styleUrls: ['feedback-form.component.scss'], +}) +export class FeedbackFormComponent { + @Output() + readonly feedBackSubmit: EventEmitter> = + new EventEmitter>(); + + readonly feedbackForm = new FormGroup({ + name: new FormControl('', { + validators: Validators.required, + }), + email: new FormControl('', { + validators: Validators.required, + }), + comment: new FormControl(), + }); + + rating: string | null = null; + + submitForm(): void { + this.feedBackSubmit.emit({ + ...this.feedbackForm.value, + rating: this.rating, + }); + + this.feedbackForm.reset(); + } +} diff --git a/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.html b/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.html new file mode 100644 index 000000000..05b96c138 --- /dev/null +++ b/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.html @@ -0,0 +1,16 @@ + + + + + +
+ @for (item of [].constructor(5); track item) { + + + + } +
diff --git a/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.scss b/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.scss new file mode 100644 index 000000000..1e174f140 --- /dev/null +++ b/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.scss @@ -0,0 +1,26 @@ +.rating { + display: flex; + justify-content: center; + padding: 0 10px; + + &:hover { + .star { + fill: #ffd055; + } + } +} + +.star { + width: 50px; + height: 50px; + fill: #cccccc; + cursor: pointer; + + &:hover ~ .star { + fill: #d8d8d8; + } +} + +.star-active { + fill: #ffd055 !important; +} diff --git a/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.ts b/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.ts new file mode 100644 index 000000000..d6dc31631 --- /dev/null +++ b/apps/forms/41-control-value-accessor/src/app/rating-control/rating-control.component.ts @@ -0,0 +1,23 @@ +import { Component, EventEmitter, Output } from '@angular/core'; + +@Component({ + standalone: true, + selector: 'app-rating-control', + templateUrl: 'rating-control.component.html', + styleUrls: ['rating-control.component.scss'], +}) +export class RatingControlComponent { + @Output() + readonly ratingUpdated: EventEmitter = new EventEmitter(); + + value: number | null = null; + + setRating(index: number): void { + this.value = index + 1; + this.ratingUpdated.emit(`${this.value}`); + } + + isStarActive(index: number, value: number | null): boolean { + return value ? index < value : false; + } +} diff --git a/apps/performance/memoized/src/assets/.gitkeep b/apps/forms/41-control-value-accessor/src/assets/.gitkeep similarity index 100% rename from apps/performance/memoized/src/assets/.gitkeep rename to apps/forms/41-control-value-accessor/src/assets/.gitkeep diff --git a/apps/performance/scroll-cd/src/favicon.ico b/apps/forms/41-control-value-accessor/src/favicon.ico similarity index 100% rename from apps/performance/scroll-cd/src/favicon.ico rename to apps/forms/41-control-value-accessor/src/favicon.ico diff --git a/apps/forms/41-control-value-accessor/src/index.html b/apps/forms/41-control-value-accessor/src/index.html new file mode 100644 index 000000000..957806cf0 --- /dev/null +++ b/apps/forms/41-control-value-accessor/src/index.html @@ -0,0 +1,13 @@ + + + + + forms-control-value-accessor + + + + + + + + diff --git a/apps/rxjs/pipe-bug/src/main.ts b/apps/forms/41-control-value-accessor/src/main.ts similarity index 100% rename from apps/rxjs/pipe-bug/src/main.ts rename to apps/forms/41-control-value-accessor/src/main.ts diff --git a/apps/testing/checkbox/src/styles.scss b/apps/forms/41-control-value-accessor/src/styles.scss similarity index 100% rename from apps/testing/checkbox/src/styles.scss rename to apps/forms/41-control-value-accessor/src/styles.scss diff --git a/apps/testing/create-harness/src/test-setup.ts b/apps/forms/41-control-value-accessor/src/test-setup.ts similarity index 100% rename from apps/testing/create-harness/src/test-setup.ts rename to apps/forms/41-control-value-accessor/src/test-setup.ts diff --git a/apps/testing/harness/tailwind.config.js b/apps/forms/41-control-value-accessor/tailwind.config.js similarity index 100% rename from apps/testing/harness/tailwind.config.js rename to apps/forms/41-control-value-accessor/tailwind.config.js diff --git a/apps/testing/create-harness/tsconfig.app.json b/apps/forms/41-control-value-accessor/tsconfig.app.json similarity index 100% rename from apps/testing/create-harness/tsconfig.app.json rename to apps/forms/41-control-value-accessor/tsconfig.app.json diff --git a/apps/performance/scroll-cd/tsconfig.editor.json b/apps/forms/41-control-value-accessor/tsconfig.editor.json similarity index 100% rename from apps/performance/scroll-cd/tsconfig.editor.json rename to apps/forms/41-control-value-accessor/tsconfig.editor.json diff --git a/apps/forms/41-control-value-accessor/tsconfig.json b/apps/forms/41-control-value-accessor/tsconfig.json new file mode 100644 index 000000000..25ca437b4 --- /dev/null +++ b/apps/forms/41-control-value-accessor/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/forms/41-control-value-accessor/tsconfig.spec.json b/apps/forms/41-control-value-accessor/tsconfig.spec.json new file mode 100644 index 000000000..1a4817a7d --- /dev/null +++ b/apps/forms/41-control-value-accessor/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "@testing-library/jest-dom"] + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/apps/forms/48-avoid-losing-form-data/.eslintrc.json b/apps/forms/48-avoid-losing-form-data/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/forms/48-avoid-losing-form-data/README.md b/apps/forms/48-avoid-losing-form-data/README.md new file mode 100644 index 000000000..1c0e90b35 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/README.md @@ -0,0 +1,11 @@ +# Avoid losing form data + +> author: [Timothy Alcaide](https://github.com/alcaidio) + +### Run Application + +```bash +npx nx serve forms-avoid-losing-form-data +``` + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/forms/48-forms-avoid-losing-form-data/). diff --git a/apps/forms/48-avoid-losing-form-data/project.json b/apps/forms/48-avoid-losing-form-data/project.json new file mode 100644 index 000000000..9517d3123 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/project.json @@ -0,0 +1,72 @@ +{ + "name": "forms-avoid-losing-form-data", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/forms/48-avoid-losing-form-data/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/forms/48-avoid-losing-form-data", + "index": "apps/forms/48-avoid-losing-form-data/src/index.html", + "browser": "apps/forms/48-avoid-losing-form-data/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/forms/48-avoid-losing-form-data/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/forms/48-avoid-losing-form-data/src/favicon.ico", + "apps/forms/48-avoid-losing-form-data/src/assets" + ], + "styles": [ + "apps/forms/48-avoid-losing-form-data/src/styles.scss", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "forms-avoid-losing-form-data:build:production" + }, + "development": { + "buildTarget": "forms-avoid-losing-form-data:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "forms-avoid-losing-form-data:build" + } + } + } +} diff --git a/apps/forms/48-avoid-losing-form-data/src/app/app.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/app.component.ts new file mode 100644 index 000000000..2b5adc443 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/app/app.component.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; +import { NavComponent } from './ui/nav.component'; + +@Component({ + imports: [RouterOutlet, NavComponent], + selector: 'app-root', + template: ` +
+ + +
+ +
+
+ `, +}) +export class AppComponent {} diff --git a/apps/forms/48-avoid-losing-form-data/src/app/app.config.ts b/apps/forms/48-avoid-losing-form-data/src/app/app.config.ts new file mode 100644 index 000000000..a7c1007b9 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/app/app.config.ts @@ -0,0 +1,7 @@ +import { ApplicationConfig } from '@angular/core'; +import { provideRouter, withComponentInputBinding } from '@angular/router'; +import { appRoutes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [provideRouter(appRoutes, withComponentInputBinding())], +}; diff --git a/apps/forms/48-avoid-losing-form-data/src/app/app.routes.ts b/apps/forms/48-avoid-losing-form-data/src/app/app.routes.ts new file mode 100644 index 000000000..84be34b9a --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/app/app.routes.ts @@ -0,0 +1,29 @@ +import { Route } from '@angular/router'; +import { JoinComponent } from './pages/join.component'; +import { PageComponent } from './pages/page.component'; + +export const appRoutes: Route[] = [ + { + path: '', + pathMatch: 'full', + redirectTo: 'form', + }, + { + path: 'form', + loadComponent: () => JoinComponent, + }, + { + path: 'page-1', + data: { + title: 'Page 1', + }, + loadComponent: () => PageComponent, + }, + { + path: 'page-2', + data: { + title: 'Page 2', + }, + loadComponent: () => PageComponent, + }, +]; diff --git a/apps/forms/48-avoid-losing-form-data/src/app/pages/join.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/pages/join.component.ts new file mode 100644 index 000000000..51449a7fb --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/app/pages/join.component.ts @@ -0,0 +1,15 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { FormComponent } from '../ui/form.component'; + +@Component({ + imports: [FormComponent], + template: ` +
+
+ +
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class JoinComponent {} diff --git a/apps/forms/48-avoid-losing-form-data/src/app/pages/page.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/pages/page.component.ts new file mode 100644 index 000000000..13f4e09c2 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/app/pages/page.component.ts @@ -0,0 +1,14 @@ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; + +@Component({ + standalone: true, + template: ` +
+

{{ title() }}

+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class PageComponent { + title = input.required(); +} diff --git a/apps/forms/48-avoid-losing-form-data/src/app/ui/dialog.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/ui/dialog.component.ts new file mode 100644 index 000000000..661da9bcf --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/app/ui/dialog.component.ts @@ -0,0 +1,30 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +// NOTE : this is just the dialog content, you need to implement dialog logic + +@Component({ + standalone: true, + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AlertDialogComponent {} diff --git a/apps/forms/48-avoid-losing-form-data/src/app/ui/form.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/ui/form.component.ts new file mode 100644 index 000000000..f3190d517 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/app/ui/form.component.ts @@ -0,0 +1,77 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; + +@Component({ + selector: 'app-form', + imports: [ReactiveFormsModule], + template: ` +
+
+ + +
+ +
+
+ + +
+ +
+ + +
+
+ +
+ + + +
+ +
+ +
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class FormComponent { + private fb = inject(FormBuilder); + + form = this.fb.nonNullable.group({ + name: ['', { validators: [Validators.required] }], + email: ['', [Validators.required, Validators.email]], // other syntax + phone: '', + message: '', + }); + + onSubmit() { + if (this.form.valid) this.form.reset(); + } +} diff --git a/apps/forms/48-avoid-losing-form-data/src/app/ui/nav.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/ui/nav.component.ts new file mode 100644 index 000000000..269297280 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/app/ui/nav.component.ts @@ -0,0 +1,32 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { RouterLink, RouterLinkActive } from '@angular/router'; + +@Component({ + selector: 'app-nav', + imports: [RouterLink, RouterLinkActive], + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class NavComponent {} diff --git a/apps/performance/ngfor-biglist/src/assets/.gitkeep b/apps/forms/48-avoid-losing-form-data/src/assets/.gitkeep similarity index 100% rename from apps/performance/ngfor-biglist/src/assets/.gitkeep rename to apps/forms/48-avoid-losing-form-data/src/assets/.gitkeep diff --git a/apps/rxjs/catch-error/src/favicon.ico b/apps/forms/48-avoid-losing-form-data/src/favicon.ico similarity index 100% rename from apps/rxjs/catch-error/src/favicon.ico rename to apps/forms/48-avoid-losing-form-data/src/favicon.ico diff --git a/apps/forms/48-avoid-losing-form-data/src/index.html b/apps/forms/48-avoid-losing-form-data/src/index.html new file mode 100644 index 000000000..ed75bb39d --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/index.html @@ -0,0 +1,13 @@ + + + + + form-avoid-losing-form-data + + + + + + + + diff --git a/apps/forms/48-avoid-losing-form-data/src/main.ts b/apps/forms/48-avoid-losing-form-data/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/testing/modal/src/styles.scss b/apps/forms/48-avoid-losing-form-data/src/styles.scss similarity index 100% rename from apps/testing/modal/src/styles.scss rename to apps/forms/48-avoid-losing-form-data/src/styles.scss diff --git a/apps/forms/48-avoid-losing-form-data/tailwind.config.js b/apps/forms/48-avoid-losing-form-data/tailwind.config.js new file mode 100644 index 000000000..16f83c7f4 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [require('@tailwindcss/forms')], +}; diff --git a/apps/testing/harness/tsconfig.app.json b/apps/forms/48-avoid-losing-form-data/tsconfig.app.json similarity index 100% rename from apps/testing/harness/tsconfig.app.json rename to apps/forms/48-avoid-losing-form-data/tsconfig.app.json diff --git a/apps/forms/48-avoid-losing-form-data/tsconfig.editor.json b/apps/forms/48-avoid-losing-form-data/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/forms/48-avoid-losing-form-data/tsconfig.json b/apps/forms/48-avoid-losing-form-data/tsconfig.json new file mode 100644 index 000000000..3df17b921 --- /dev/null +++ b/apps/forms/48-avoid-losing-form-data/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/ngrx/effect-selector/README.md b/apps/ngrx/effect-selector/README.md deleted file mode 100644 index 3f12862c4..000000000 --- a/apps/ngrx/effect-selector/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Effect vs Selector - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve ngrx-effect-selector -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/ngrx/2-effect-selector/). diff --git a/apps/ngrx/effect-selector/jest.config.ts b/apps/ngrx/effect-selector/jest.config.ts deleted file mode 100644 index 86ed38d00..000000000 --- a/apps/ngrx/effect-selector/jest.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'ngrx-effect-selector', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../../coverage/apps/ngrx/effect-selector', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/ngrx/effect-selector/project.json b/apps/ngrx/effect-selector/project.json deleted file mode 100644 index 4488e31d8..000000000 --- a/apps/ngrx/effect-selector/project.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "name": "ngrx-effect-selector", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/ngrx/effect-selector/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/ngrx/effect-selector", - "index": "apps/ngrx/effect-selector/src/index.html", - "main": "apps/ngrx/effect-selector/src/main.ts", - "polyfills": "apps/ngrx/effect-selector/src/polyfills.ts", - "tsConfig": "apps/ngrx/effect-selector/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/ngrx/effect-selector/src/favicon.ico", - "apps/ngrx/effect-selector/src/assets" - ], - "styles": ["apps/ngrx/effect-selector/src/styles.scss"], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "ngrx-effect-selector:build:production" - }, - "development": { - "browserTarget": "ngrx-effect-selector:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "ngrx-effect-selector:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/ngrx/effect-selector/**/*.ts", - "apps/ngrx/effect-selector/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/ngrx/effect-selector/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] -} diff --git a/apps/ngrx/effect-selector/src/app/app.component.ts b/apps/ngrx/effect-selector/src/app/app.component.ts deleted file mode 100644 index 0411abc06..000000000 --- a/apps/ngrx/effect-selector/src/app/app.component.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { AsyncPipe, NgFor } from '@angular/common'; -import { - ChangeDetectionStrategy, - Component, - inject, - OnInit, -} from '@angular/core'; -import { Store } from '@ngrx/store'; -import { loadActivities } from './store/activity/activity.actions'; -import { ActivityType } from './store/activity/activity.model'; -import { selectActivities } from './store/activity/activity.selectors'; -import { loadStatuses } from './store/status/status.actions'; -import { selectAllTeachersByActivityType } from './store/status/status.selectors'; -import { loadUsers } from './store/user/user.actions'; - -@Component({ - selector: 'app-root', - standalone: true, - imports: [NgFor, AsyncPipe], - template: ` -

Activity Board

-
-
-

Activity Name: {{ activity.name }}

-

Main teacher: {{ activity.teacher.name }}

- All teachers available for : {{ activity.type }} are -
    -
  • - {{ teacher.name }} -
  • -
-
-
- `, - styles: [ - ` - section { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 2px; - } - - .card { - display: flex; - flex-direction: column; - border: solid; - border-width: 1px; - border-color: black; - padding: 2px; - } - `, - ], - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AppComponent implements OnInit { - private store = inject(Store); - - activities$ = this.store.select(selectActivities); - - ngOnInit(): void { - this.store.dispatch(loadActivities()); - this.store.dispatch(loadUsers()); - this.store.dispatch(loadStatuses()); - } - - getAllTeachersForActivityType$ = (type: ActivityType) => - this.store.select(selectAllTeachersByActivityType(type)); -} diff --git a/apps/ngrx/effect-selector/src/app/app.config.ts b/apps/ngrx/effect-selector/src/app/app.config.ts deleted file mode 100644 index e18cd3352..000000000 --- a/apps/ngrx/effect-selector/src/app/app.config.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ApplicationConfig } from '@angular/core'; -import { provideStore } from '@ngrx/store'; -import { provideEffects } from '@ngrx/effects'; -import { ActivityEffects } from './store/activity/activity.effects'; -import { UserEffects } from './store/user/user.effects'; -import { StatusEffects } from './store/status/status.effects'; -import { - activityFeatureKey, - activityReducer, -} from './store/activity/activity.reducer'; - -import { statusFeatureKey, statusReducer } from './store/status/status.reducer'; - -import { userFeatureKey, userReducer } from './store/user/user.reducer'; - -const reducers = { - [statusFeatureKey]: statusReducer, - [activityFeatureKey]: activityReducer, - [userFeatureKey]: userReducer, -}; - -export const appConfig: ApplicationConfig = { - providers: [ - provideStore(reducers), - provideEffects([ActivityEffects, UserEffects, StatusEffects]), - ], -}; diff --git a/apps/ngrx/effect-selector/src/app/store/activity/activity.actions.ts b/apps/ngrx/effect-selector/src/app/store/activity/activity.actions.ts deleted file mode 100644 index 214586fef..000000000 --- a/apps/ngrx/effect-selector/src/app/store/activity/activity.actions.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction, props } from '@ngrx/store'; -import { Activity } from './activity.model'; - -export const loadActivities = createAction('[AppComponent] Load Activities'); - -export const loadActivitiesSuccess = createAction( - '[Activity Effect] Load Activitys Success', - props<{ activities: Activity[] }>() -); - -export const loadActivitiesFailure = createAction( - '[Activity Effect] Load Activities Failure', - props<{ error: any }>() -); diff --git a/apps/ngrx/effect-selector/src/app/store/activity/activity.effects.ts b/apps/ngrx/effect-selector/src/app/store/activity/activity.effects.ts deleted file mode 100644 index 63b27e997..000000000 --- a/apps/ngrx/effect-selector/src/app/store/activity/activity.effects.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { of } from 'rxjs'; -import { catchError, concatMap, map } from 'rxjs/operators'; -import * as ActivityActions from './activity.actions'; -import { ActivityService } from './activity.service'; - -@Injectable() -export class ActivityEffects { - loadActivities$ = createEffect(() => { - return this.actions$.pipe( - ofType(ActivityActions.loadActivities), - concatMap(() => - this.ActivityService.fetchActivities().pipe( - map((activities) => - ActivityActions.loadActivitiesSuccess({ activities }) - ), - catchError((error) => - of(ActivityActions.loadActivitiesFailure({ error })) - ) - ) - ) - ); - }); - - constructor( - private actions$: Actions, - private ActivityService: ActivityService - ) {} -} diff --git a/apps/ngrx/effect-selector/src/app/store/activity/activity.model.ts b/apps/ngrx/effect-selector/src/app/store/activity/activity.model.ts deleted file mode 100644 index 75f188132..000000000 --- a/apps/ngrx/effect-selector/src/app/store/activity/activity.model.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { - incrementalNumber, - rand, - randFirstName, - randText, -} from '@ngneat/falso'; - -export const activityType = [ - 'Sport', - 'Sciences', - 'History', - 'Maths', - 'Physics', -] as const; -export type ActivityType = (typeof activityType)[number]; - -export interface Person { - id: number; - name: string; -} - -export interface Activity { - id: number; - name: string; - type: ActivityType; - teacher: Person; -} - -const factoryPerson = incrementalNumber(); - -export const randPerson = () => ({ - id: factoryPerson(), - name: randFirstName(), -}); - -const factoryActivity = incrementalNumber(); - -export const randActivity = (): Activity => ({ - id: factoryActivity(), - name: randText(), - type: rand(activityType), - teacher: randPerson(), -}); - -export const activities: Activity[] = [ - randActivity(), - randActivity(), - randActivity(), - randActivity(), - randActivity(), - randActivity(), - randActivity(), - randActivity(), - randActivity(), -]; diff --git a/apps/ngrx/effect-selector/src/app/store/activity/activity.reducer.ts b/apps/ngrx/effect-selector/src/app/store/activity/activity.reducer.ts deleted file mode 100644 index f370b4b2f..000000000 --- a/apps/ngrx/effect-selector/src/app/store/activity/activity.reducer.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createReducer, on } from '@ngrx/store'; -import * as ActivityActions from './activity.actions'; -import { Activity } from './activity.model'; - -export const activityFeatureKey = 'Activity'; - -export interface ActivityState { - activities: Activity[]; -} - -export const initialState: ActivityState = { - activities: [], -}; - -export const activityReducer = createReducer( - initialState, - on(ActivityActions.loadActivitiesSuccess, (state, { activities }) => ({ - ...state, - activities, - })), - on(ActivityActions.loadActivitiesFailure, (state) => ({ - state, - activities: [], - })) -); diff --git a/apps/ngrx/effect-selector/src/app/store/activity/activity.selectors.ts b/apps/ngrx/effect-selector/src/app/store/activity/activity.selectors.ts deleted file mode 100644 index 7e200de1e..000000000 --- a/apps/ngrx/effect-selector/src/app/store/activity/activity.selectors.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createFeatureSelector, createSelector } from '@ngrx/store'; -import { activityFeatureKey, ActivityState } from './activity.reducer'; - -export const selectActivityState = - createFeatureSelector(activityFeatureKey); - -export const selectActivities = createSelector( - selectActivityState, - (state) => state.activities -); diff --git a/apps/ngrx/effect-selector/src/app/store/activity/activity.service.ts b/apps/ngrx/effect-selector/src/app/store/activity/activity.service.ts deleted file mode 100644 index 07aa8f8ad..000000000 --- a/apps/ngrx/effect-selector/src/app/store/activity/activity.service.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Injectable } from '@angular/core'; -import { map, timer } from 'rxjs'; -import { activities } from './activity.model'; - -@Injectable({ - providedIn: 'root', -}) -export class ActivityService { - fetchActivities = () => timer(500).pipe(map(() => activities)); -} diff --git a/apps/ngrx/effect-selector/src/app/store/status/status.actions.ts b/apps/ngrx/effect-selector/src/app/store/status/status.actions.ts deleted file mode 100644 index c966824f8..000000000 --- a/apps/ngrx/effect-selector/src/app/store/status/status.actions.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createAction, props } from '@ngrx/store'; -import { Status } from './status.model'; - -export const loadStatuses = createAction('[Status] Load Statuses'); - -export const loadStatusesSuccess = createAction( - '[Status] Load Statuses Success', - props<{ statuses: Status[] }>() -); diff --git a/apps/ngrx/effect-selector/src/app/store/status/status.effects.ts b/apps/ngrx/effect-selector/src/app/store/status/status.effects.ts deleted file mode 100644 index 3459a5901..000000000 --- a/apps/ngrx/effect-selector/src/app/store/status/status.effects.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { Store } from '@ngrx/store'; -import { combineLatest, concatMap, map } from 'rxjs'; -import { selectActivities } from '../activity/activity.selectors'; -import { selectUser } from '../user/user.selectors'; -import * as StatusActions from './status.actions'; -import { Status } from './status.model'; - -@Injectable() -export class StatusEffects { - loadStatuses$ = createEffect(() => { - return this.actions$.pipe( - ofType(StatusActions.loadStatuses), - concatMap(() => - combineLatest([ - this.store.select(selectUser), - this.store.select(selectActivities), - ]).pipe( - map(([user, activities]): Status[] => { - if (user?.isAdmin) { - return activities.reduce( - (status: Status[], activity): Status[] => { - const index = status.findIndex( - (s) => s.name === activity.type - ); - if (index === -1) { - return [ - ...status, - { name: activity.type, teachers: [activity.teacher] }, - ]; - } else { - status[index].teachers.push(activity.teacher); - return status; - } - }, - [] - ); - } - return []; - }), - map((statuses) => StatusActions.loadStatusesSuccess({ statuses })) - ) - ) - ); - }); - - constructor(private actions$: Actions, private store: Store) {} -} diff --git a/apps/ngrx/effect-selector/src/app/store/status/status.model.ts b/apps/ngrx/effect-selector/src/app/store/status/status.model.ts deleted file mode 100644 index 07733834a..000000000 --- a/apps/ngrx/effect-selector/src/app/store/status/status.model.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ActivityType, Person } from '../activity/activity.model'; - -export interface Status { - name: ActivityType; - teachers: Person[]; -} diff --git a/apps/ngrx/effect-selector/src/app/store/status/status.reducer.ts b/apps/ngrx/effect-selector/src/app/store/status/status.reducer.ts deleted file mode 100644 index 1dd8ece05..000000000 --- a/apps/ngrx/effect-selector/src/app/store/status/status.reducer.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { createReducer, on } from '@ngrx/store'; -import { ActivityType, Person } from '../activity/activity.model'; -import * as StatusActions from './status.actions'; -import { Status } from './status.model'; - -export const statusFeatureKey = 'status'; - -export interface StatusState { - statuses: Status[]; - teachersMap: Map; -} - -export const initialState: StatusState = { - statuses: [], - teachersMap: new Map(), -}; - -export const statusReducer = createReducer( - initialState, - on(StatusActions.loadStatusesSuccess, (state, { statuses }): StatusState => { - const map = new Map(); - statuses.forEach((s) => map.set(s.name, s.teachers)); - return { - ...state, - statuses, - teachersMap: map, - }; - }) -); diff --git a/apps/ngrx/effect-selector/src/app/store/status/status.selectors.ts b/apps/ngrx/effect-selector/src/app/store/status/status.selectors.ts deleted file mode 100644 index 85b72f885..000000000 --- a/apps/ngrx/effect-selector/src/app/store/status/status.selectors.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createFeatureSelector, createSelector } from '@ngrx/store'; -import { ActivityType } from '../activity/activity.model'; -import { statusFeatureKey, StatusState } from './status.reducer'; - -export const selectStatusState = - createFeatureSelector(statusFeatureKey); - -export const selectStatuses = createSelector( - selectStatusState, - (state) => state.statuses -); - -export const selectAllTeachersByActivityType = (name: ActivityType) => - createSelector( - selectStatusState, - (state) => state.teachersMap.get(name) ?? [] - ); diff --git a/apps/ngrx/effect-selector/src/app/store/user/user.actions.ts b/apps/ngrx/effect-selector/src/app/store/user/user.actions.ts deleted file mode 100644 index dcc8b1daf..000000000 --- a/apps/ngrx/effect-selector/src/app/store/user/user.actions.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createAction, props } from '@ngrx/store'; -import { User } from './user.model'; - -export const loadUsers = createAction('[User] Load User'); - -export const loadUsersSuccess = createAction( - '[User] Load Users Success', - props<{ user: User }>() -); - -export const loadUsersFailure = createAction( - '[User] Load Users Failure', - props<{ error: any }>() -); diff --git a/apps/ngrx/effect-selector/src/app/store/user/user.effects.ts b/apps/ngrx/effect-selector/src/app/store/user/user.effects.ts deleted file mode 100644 index 6f68e5b6d..000000000 --- a/apps/ngrx/effect-selector/src/app/store/user/user.effects.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { of } from 'rxjs'; -import { catchError, concatMap, map } from 'rxjs/operators'; -import * as UserActions from './user.actions'; -import { UserService } from './user.service'; - -@Injectable() -export class UserEffects { - loadUsers$ = createEffect(() => { - return this.actions$.pipe( - ofType(UserActions.loadUsers), - concatMap(() => - this.userService.fetchUser().pipe( - map((user) => UserActions.loadUsersSuccess({ user })), - catchError((error) => of(UserActions.loadUsersFailure({ error }))) - ) - ) - ); - }); - - constructor(private actions$: Actions, private userService: UserService) {} -} diff --git a/apps/ngrx/effect-selector/src/app/store/user/user.model.ts b/apps/ngrx/effect-selector/src/app/store/user/user.model.ts deleted file mode 100644 index d7692041c..000000000 --- a/apps/ngrx/effect-selector/src/app/store/user/user.model.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { randFirstName, randLastName, randText } from '@ngneat/falso'; - -export interface User { - firstname: string; - lastname: string; - isAdmin: boolean; - apiKey: string; -} - -export const user: User = { - firstname: randFirstName(), - lastname: randLastName(), - isAdmin: true, - apiKey: randText(), -}; diff --git a/apps/ngrx/effect-selector/src/app/store/user/user.reducer.ts b/apps/ngrx/effect-selector/src/app/store/user/user.reducer.ts deleted file mode 100644 index 45596afbe..000000000 --- a/apps/ngrx/effect-selector/src/app/store/user/user.reducer.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { createReducer, on } from '@ngrx/store'; -import * as UserActions from './user.actions'; -import { User } from './user.model'; - -export const userFeatureKey = 'user'; - -export interface UserState { - user?: User; -} - -export const initialState: UserState = { - user: undefined, -}; - -export const userReducer = createReducer( - initialState, - on(UserActions.loadUsersSuccess, (state, { user }) => ({ ...state, user })), - on(UserActions.loadUsersFailure, (state) => ({ ...state, user: undefined })) -); diff --git a/apps/ngrx/effect-selector/src/app/store/user/user.selectors.ts b/apps/ngrx/effect-selector/src/app/store/user/user.selectors.ts deleted file mode 100644 index eb6dedae7..000000000 --- a/apps/ngrx/effect-selector/src/app/store/user/user.selectors.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createFeatureSelector, createSelector } from '@ngrx/store'; -import { userFeatureKey, UserState } from './user.reducer'; - -export const selectUserState = createFeatureSelector(userFeatureKey); - -export const selectUser = createSelector( - selectUserState, - (state) => state.user -); diff --git a/apps/ngrx/effect-selector/src/app/store/user/user.service.ts b/apps/ngrx/effect-selector/src/app/store/user/user.service.ts deleted file mode 100644 index a407b020a..000000000 --- a/apps/ngrx/effect-selector/src/app/store/user/user.service.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Injectable } from '@angular/core'; -import { map, timer } from 'rxjs'; -import { user } from './user.model'; - -@Injectable({ - providedIn: 'root', -}) -export class UserService { - fetchUser = () => timer(500).pipe(map(() => user)); -} diff --git a/apps/ngrx/effect-selector/src/index.html b/apps/ngrx/effect-selector/src/index.html deleted file mode 100644 index 5664dcffb..000000000 --- a/apps/ngrx/effect-selector/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Ngrx1 - - - - - - - - diff --git a/apps/ngrx/effect-selector/src/main.ts b/apps/ngrx/effect-selector/src/main.ts deleted file mode 100644 index 31c2a3482..000000000 --- a/apps/ngrx/effect-selector/src/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; - -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig); diff --git a/apps/ngrx/effect-selector/src/polyfills.ts b/apps/ngrx/effect-selector/src/polyfills.ts deleted file mode 100644 index e4555ed11..000000000 --- a/apps/ngrx/effect-selector/src/polyfills.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * This file includes polyfills needed by Angular and is loaded before the app. - * You can add your own extra polyfills to this file. - * - * This file is divided into 2 sections: - * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. - * 2. Application imports. Files imported after ZoneJS that should be loaded before your main - * file. - * - * The current setup is for so-called "evergreen" browsers; the last versions of browsers that - * automatically update themselves. This includes recent versions of Safari, Chrome (including - * Opera), Edge on the desktop, and iOS and Chrome on mobile. - * - * Learn more in https://angular.io/guide/browser-support - */ - -/*************************************************************************************************** - * BROWSER POLYFILLS - */ - -/** - * By default, zone.js will patch all possible macroTask and DomEvents - * user can disable parts of macroTask/DomEvents patch by setting following flags - * because those flags need to be set before `zone.js` being loaded, and webpack - * will put import in the top of bundle, so user need to create a separate file - * in this directory (for example: zone-flags.ts), and put the following flags - * into that file, and then add the following code before importing zone.js. - * import './zone-flags'; - * - * The flags allowed in zone-flags.ts are listed here. - * - * The following flags will work for all browsers. - * - * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame - * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick - * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames - * - * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js - * with the following flag, it will bypass `zone.js` patch for IE/Edge - * - * (window as any).__Zone_enable_cross_context_check = true; - * - */ - -/*************************************************************************************************** - * Zone JS is required by default for Angular itself. - */ -import 'zone.js'; // Included with Angular CLI. - -/*************************************************************************************************** - * APPLICATION IMPORTS - */ diff --git a/apps/ngrx/effect-selector/tsconfig.app.json b/apps/ngrx/effect-selector/tsconfig.app.json deleted file mode 100644 index 7a4dbc47e..000000000 --- a/apps/ngrx/effect-selector/tsconfig.app.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../../dist/out-tsc", - "types": [], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/main.ts", "src/polyfills.ts"], - "include": ["src/**/*.d.ts"], - "exclude": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts"] -} diff --git a/apps/ngrx/effect-selector/tsconfig.editor.json b/apps/ngrx/effect-selector/tsconfig.editor.json deleted file mode 100644 index 20c4afdbf..000000000 --- a/apps/ngrx/effect-selector/tsconfig.editor.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": ["**/*.ts"], - "compilerOptions": { - "types": ["jest", "node"] - } -} diff --git a/apps/ngrx/effect-selector/tsconfig.json b/apps/ngrx/effect-selector/tsconfig.json deleted file mode 100644 index 52eb4f718..000000000 --- a/apps/ngrx/effect-selector/tsconfig.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.editor.json" - } - ], - "compilerOptions": { - "target": "es2020", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/apps/ngrx/effect-selector/tsconfig.spec.json b/apps/ngrx/effect-selector/tsconfig.spec.json deleted file mode 100644 index 7aa46d88c..000000000 --- a/apps/ngrx/effect-selector/tsconfig.spec.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "files": ["src/test-setup.ts"], - "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] -} diff --git a/apps/ngrx/notification/README.md b/apps/ngrx/notification/README.md deleted file mode 100644 index 136a30fbd..000000000 --- a/apps/ngrx/notification/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Power of Effect - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve ngrx-notification -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/ngrx/7-power-effect/). diff --git a/apps/ngrx/notification/project.json b/apps/ngrx/notification/project.json deleted file mode 100644 index 95a0943d2..000000000 --- a/apps/ngrx/notification/project.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "name": "ngrx-notification", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/ngrx/notification/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/ngrx/notification", - "index": "apps/ngrx/notification/src/index.html", - "main": "apps/ngrx/notification/src/main.ts", - "polyfills": "apps/ngrx/notification/src/polyfills.ts", - "tsConfig": "apps/ngrx/notification/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/ngrx/notification/src/favicon.ico", - "apps/ngrx/notification/src/assets" - ], - "styles": ["apps/ngrx/notification/src/styles.scss"], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "ngrx-notification:build:production" - }, - "development": { - "browserTarget": "ngrx-notification:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "ngrx-notification:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/ngrx/notification/**/*.ts", - "apps/ngrx/notification/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/ngrx/notification/src/app/app.actions.ts b/apps/ngrx/notification/src/app/app.actions.ts deleted file mode 100644 index 8292b19f4..000000000 --- a/apps/ngrx/notification/src/app/app.actions.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createActionGroup, emptyProps } from '@ngrx/store'; - -export const appActions = createActionGroup({ - source: 'App Component', - events: { - 'Init App': emptyProps(), - }, -}); diff --git a/apps/ngrx/notification/src/app/app.component.ts b/apps/ngrx/notification/src/app/app.component.ts deleted file mode 100644 index dc14376ac..000000000 --- a/apps/ngrx/notification/src/app/app.component.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Component, inject, OnInit } from '@angular/core'; -import { RouterLink, RouterOutlet } from '@angular/router'; -import { Store } from '@ngrx/store'; -import { appActions } from './app.actions'; - -@Component({ - standalone: true, - imports: [RouterOutlet, RouterLink], - selector: 'app-root', - template: ` - - - - `, - styles: [ - ` - :host { - display: flex; - flex-direction: column; - gap: 20px; - - nav { - display: flex; - gap: 20px; - } - } - `, - ], -}) -export class AppComponent implements OnInit { - private store = inject(Store); - - ngOnInit(): void { - this.store.dispatch(appActions.initApp()); - } -} diff --git a/apps/ngrx/notification/src/app/app.config.ts b/apps/ngrx/notification/src/app/app.config.ts deleted file mode 100644 index 52badc4f3..000000000 --- a/apps/ngrx/notification/src/app/app.config.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { ApplicationConfig } from '@angular/core'; -import { provideStore } from '@ngrx/store'; -import { provideEffects } from '@ngrx/effects'; -import { TeacherEffects } from './teacher/store/teacher.effects'; -import { StudentEffects } from './student/store/student.effects'; -import { provideRouter } from '@angular/router'; -import { ROUTES } from './routes'; -import { APP_INITIALIZER, inject } from '@angular/core'; -import { FakeBackendService } from '@angular-challenges/ngrx-notification/backend'; -import { NotificationService } from './data-access/notification.service'; -import { - teacherReducer, - teachersFeatureKey, -} from './teacher/store/teacher.reducer'; -import { - studentReducer, - studentsFeatureKey, -} from './student/store/student.reducer'; - -const REDUCERS = { - [teachersFeatureKey]: teacherReducer, - [studentsFeatureKey]: studentReducer, -}; - -export const appConfig: ApplicationConfig = { - providers: [ - provideStore(REDUCERS), - provideEffects([TeacherEffects, StudentEffects]), - provideRouter(ROUTES), - { - provide: APP_INITIALIZER, - multi: true, - useFactory: () => { - const service = inject(FakeBackendService); - return () => service.start(); - }, - }, - { - provide: APP_INITIALIZER, - multi: true, - useFactory: () => { - const service = inject(NotificationService); - return () => service.init(); - }, - }, - ], -}; diff --git a/apps/ngrx/notification/src/app/data-access/http.service.ts b/apps/ngrx/notification/src/app/data-access/http.service.ts deleted file mode 100644 index 84aadda07..000000000 --- a/apps/ngrx/notification/src/app/data-access/http.service.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { FakeBackendService } from '@angular-challenges/ngrx-notification/backend'; -import { inject, Injectable } from '@angular/core'; -import { take } from 'rxjs'; - -@Injectable({ providedIn: 'root' }) -export class HttpService { - private fakeBackend = inject(FakeBackendService); - - getAllTeachers = () => this.fakeBackend.getAllTeachers().pipe(take(1)); - - getAllStudents = () => this.fakeBackend.getAllStudents().pipe(take(1)); - - getAllSchools = () => this.fakeBackend.getAllStchools().pipe(take(1)); -} diff --git a/apps/ngrx/notification/src/app/data-access/notification.service.ts b/apps/ngrx/notification/src/app/data-access/notification.service.ts deleted file mode 100644 index 2daca9753..000000000 --- a/apps/ngrx/notification/src/app/data-access/notification.service.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { PushService } from '@angular-challenges/ngrx-notification/backend'; -import { - isSchool, - isStudent, - isTeacher, - Push, -} from '@angular-challenges/ngrx-notification/model'; -import { inject, Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; -import { filter } from 'rxjs'; -import { studentActions } from '../student/store/student.actions'; -import { teacherActions } from '../teacher/store/teacher.actions'; - -@Injectable({ providedIn: 'root' }) -export class NotificationService { - private pushService = inject(PushService); - private store = inject(Store); - - init() { - this.pushService.notification$ - .pipe(filter(Boolean)) - .subscribe((notification: Push) => { - if (isTeacher(notification)) { - this.store.dispatch( - teacherActions.addOneTeacher({ teacher: notification }) - ); - } - if (isStudent(notification)) { - this.store.dispatch( - studentActions.addOneStudent({ student: notification }) - ); - } - if (isSchool(notification)) { - // SchoolStore is not providedin root. thus at initialization, SchoolStore is undefined - // Option 1: set SchoolStore in root, but we don't want this to separate our class. - // Option 2: your turn - } - }); - } -} diff --git a/apps/ngrx/notification/src/app/routes.ts b/apps/ngrx/notification/src/app/routes.ts deleted file mode 100644 index f84b13e28..000000000 --- a/apps/ngrx/notification/src/app/routes.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Route } from '@angular/router'; - -export const ROUTES: Route[] = [ - { path: '', pathMatch: 'full', redirectTo: 'teacher' }, - { - path: 'teacher', - loadComponent: () => - import('./teacher/teacher.component').then((m) => m.TeacherComponent), - }, - { - path: 'student', - loadComponent: () => - import('./student/student.component').then((m) => m.StudentComponent), - }, - { - path: 'school', - loadComponent: () => - import('./school/school.component').then((m) => m.SchoolComponent), - }, -]; diff --git a/apps/ngrx/notification/src/app/school/school.component.ts b/apps/ngrx/notification/src/app/school/school.component.ts deleted file mode 100644 index af58af9c1..000000000 --- a/apps/ngrx/notification/src/app/school/school.component.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* eslint-disable @angular-eslint/component-selector */ -import { AsyncPipe, NgFor } from '@angular/common'; -import { Component, inject } from '@angular/core'; -import { provideComponentStore } from '@ngrx/component-store'; -import { SchoolStore } from './school.store'; - -@Component({ - standalone: true, - imports: [NgFor, AsyncPipe], - providers: [provideComponentStore(SchoolStore)], - selector: 'school', - template: ` -

SCHOOL

-
- {{ school.name }} - {{ school.version }} -
- `, - styles: [ - ` - :host { - display: block; - width: fit-content; - height: fit-content; - border: 1px solid red; - padding: 4px; - } - `, - ], -}) -export class SchoolComponent { - private store = inject(SchoolStore); - school$ = this.store.schools$; -} diff --git a/apps/ngrx/notification/src/app/school/school.store.ts b/apps/ngrx/notification/src/app/school/school.store.ts deleted file mode 100644 index 59899dc6d..000000000 --- a/apps/ngrx/notification/src/app/school/school.store.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { School } from '@angular-challenges/ngrx-notification/model'; -import { Injectable } from '@angular/core'; -import { - ComponentStore, - OnStoreInit, - tapResponse, -} from '@ngrx/component-store'; -import { pipe, switchMap } from 'rxjs'; -import { HttpService } from '../data-access/http.service'; - -@Injectable() -export class SchoolStore - extends ComponentStore<{ schools: School[] }> - implements OnStoreInit -{ - readonly schools$ = this.select((state) => state.schools); - - constructor(private httpService: HttpService) { - super({ schools: [] }); - } - - addSchool = this.updater((state, school: School) => ({ - ...state, - schools: [...state.schools, school], - })); - - updateSchool = this.updater((state, school: School) => ({ - ...state, - schools: state.schools.map((t) => (t.id === school.id ? school : t)), - })); - - private readonly loadSchools = this.effect( - pipe( - switchMap(() => - this.httpService.getAllSchools().pipe( - tapResponse( - (schools) => this.patchState({ schools }), - (_) => _ - ) - ) - ) - ) - ); - - ngrxOnStoreInit() { - this.loadSchools(); - } -} diff --git a/apps/ngrx/notification/src/app/student/store/student.actions.ts b/apps/ngrx/notification/src/app/student/store/student.actions.ts deleted file mode 100644 index 52eda8ee0..000000000 --- a/apps/ngrx/notification/src/app/student/store/student.actions.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Student } from '@angular-challenges/ngrx-notification/model'; -import { createActionGroup, props } from '@ngrx/store'; - -export const studentActions = createActionGroup({ - source: 'Student API', - events: { - 'Add One Student': props<{ student: Student }>(), - 'Add All Students': props<{ students: Student[] }>(), - }, -}); diff --git a/apps/ngrx/notification/src/app/student/store/student.effects.ts b/apps/ngrx/notification/src/app/student/store/student.effects.ts deleted file mode 100644 index 1eef89081..000000000 --- a/apps/ngrx/notification/src/app/student/store/student.effects.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { map, switchMap } from 'rxjs'; -import { appActions } from '../../app.actions'; -import { HttpService } from '../../data-access/http.service'; -import { studentActions } from './student.actions'; - -@Injectable() -export class StudentEffects { - private actions$ = inject(Actions); - private httpService = inject(HttpService); - - loadStudents$ = createEffect(() => - this.actions$.pipe( - ofType(appActions.initApp), - switchMap(() => - this.httpService - .getAllStudents() - .pipe(map((students) => studentActions.addAllStudents({ students }))) - ) - ) - ); -} diff --git a/apps/ngrx/notification/src/app/student/store/student.reducer.ts b/apps/ngrx/notification/src/app/student/store/student.reducer.ts deleted file mode 100644 index 068d890fa..000000000 --- a/apps/ngrx/notification/src/app/student/store/student.reducer.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Student } from '@angular-challenges/ngrx-notification/model'; -import { createEntityAdapter, EntityAdapter, EntityState } from '@ngrx/entity'; -import { createReducer, on } from '@ngrx/store'; -import { studentActions } from './student.actions'; - -export const studentsFeatureKey = 'students'; - -export type StudentState = EntityState; - -export const studentAdapter: EntityAdapter = - createEntityAdapter(); - -export const studentReducer = createReducer( - studentAdapter.getInitialState(), - on(studentActions.addOneStudent, (state, { student }) => - studentAdapter.upsertOne(student, state) - ), - on(studentActions.addAllStudents, (state, { students }) => - studentAdapter.setAll(students, state) - ) -); - -export const { selectIds, selectEntities, selectAll, selectTotal } = - studentAdapter.getSelectors(); diff --git a/apps/ngrx/notification/src/app/student/store/student.selectors.ts b/apps/ngrx/notification/src/app/student/store/student.selectors.ts deleted file mode 100644 index 5c04e2366..000000000 --- a/apps/ngrx/notification/src/app/student/store/student.selectors.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createFeatureSelector, createSelector } from '@ngrx/store'; -import { - studentAdapter, - studentsFeatureKey, - StudentState, -} from './student.reducer'; - -const selectStudentState = - createFeatureSelector(studentsFeatureKey); - -export const { selectAll } = studentAdapter.getSelectors(); - -const selectStudents = createSelector(selectStudentState, selectAll); - -export const StudentSelectors = { - selectStudents, -}; diff --git a/apps/ngrx/notification/src/app/student/student.component.ts b/apps/ngrx/notification/src/app/student/student.component.ts deleted file mode 100644 index bbc45bfd7..000000000 --- a/apps/ngrx/notification/src/app/student/student.component.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* eslint-disable @angular-eslint/component-selector */ -import { AsyncPipe, NgFor } from '@angular/common'; -import { Component, inject } from '@angular/core'; -import { Store } from '@ngrx/store'; -import { StudentSelectors } from './store/student.selectors'; - -@Component({ - standalone: true, - imports: [NgFor, AsyncPipe], - selector: 'student', - template: ` -

STUDENTS

-
- {{ student.firstname }} {{ student.lastname }} - {{ student.version }} -
- `, - styles: [ - ` - :host { - display: block; - width: fit-content; - height: fit-content; - border: 1px solid red; - padding: 4px; - } - `, - ], -}) -export class StudentComponent { - private store = inject(Store); - students$ = this.store.select(StudentSelectors.selectStudents); -} diff --git a/apps/ngrx/notification/src/app/teacher/store/teacher.actions.ts b/apps/ngrx/notification/src/app/teacher/store/teacher.actions.ts deleted file mode 100644 index ff41af34e..000000000 --- a/apps/ngrx/notification/src/app/teacher/store/teacher.actions.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Teacher } from '@angular-challenges/ngrx-notification/model'; -import { createActionGroup, props } from '@ngrx/store'; - -export const teacherActions = createActionGroup({ - source: 'Teacher API', - events: { - 'Add One Teacher': props<{ teacher: Teacher }>(), - 'Add All Teachers': props<{ teachers: Teacher[] }>(), - }, -}); diff --git a/apps/ngrx/notification/src/app/teacher/store/teacher.effects.ts b/apps/ngrx/notification/src/app/teacher/store/teacher.effects.ts deleted file mode 100644 index 9eca53bf8..000000000 --- a/apps/ngrx/notification/src/app/teacher/store/teacher.effects.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { map, switchMap } from 'rxjs'; -import { appActions } from '../../app.actions'; -import { HttpService } from '../../data-access/http.service'; -import { teacherActions } from './teacher.actions'; - -@Injectable() -export class TeacherEffects { - private actions$ = inject(Actions); - private httpService = inject(HttpService); - - loadTeachers$ = createEffect(() => - this.actions$.pipe( - ofType(appActions.initApp), - switchMap(() => - this.httpService - .getAllTeachers() - .pipe(map((teachers) => teacherActions.addAllTeachers({ teachers }))) - ) - ) - ); -} diff --git a/apps/ngrx/notification/src/app/teacher/store/teacher.reducer.ts b/apps/ngrx/notification/src/app/teacher/store/teacher.reducer.ts deleted file mode 100644 index ecc95a043..000000000 --- a/apps/ngrx/notification/src/app/teacher/store/teacher.reducer.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Teacher } from '@angular-challenges/ngrx-notification/model'; -import { createEntityAdapter, EntityAdapter, EntityState } from '@ngrx/entity'; -import { createReducer, on } from '@ngrx/store'; -import { teacherActions } from './teacher.actions'; - -export const teachersFeatureKey = 'teachers'; - -export type TeacherState = EntityState; - -export const teacherAdapter: EntityAdapter = - createEntityAdapter(); - -export const teacherReducer = createReducer( - teacherAdapter.getInitialState(), - on(teacherActions.addOneTeacher, (state, { teacher }) => - teacherAdapter.upsertOne(teacher, state) - ), - on(teacherActions.addAllTeachers, (state, { teachers }) => - teacherAdapter.setAll(teachers, state) - ) -); - -export const { selectIds, selectEntities, selectAll, selectTotal } = - teacherAdapter.getSelectors(); diff --git a/apps/ngrx/notification/src/app/teacher/store/teacher.selectors.ts b/apps/ngrx/notification/src/app/teacher/store/teacher.selectors.ts deleted file mode 100644 index f9fc4f1b6..000000000 --- a/apps/ngrx/notification/src/app/teacher/store/teacher.selectors.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createFeatureSelector, createSelector } from '@ngrx/store'; -import { - teacherAdapter, - teachersFeatureKey, - TeacherState, -} from './teacher.reducer'; - -const selectTeacherState = - createFeatureSelector(teachersFeatureKey); - -export const { selectAll } = teacherAdapter.getSelectors(); - -const selectTeachers = createSelector(selectTeacherState, selectAll); - -export const TeacherSelectors = { - selectTeachers, -}; diff --git a/apps/ngrx/notification/src/app/teacher/teacher.component.ts b/apps/ngrx/notification/src/app/teacher/teacher.component.ts deleted file mode 100644 index 63e812200..000000000 --- a/apps/ngrx/notification/src/app/teacher/teacher.component.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* eslint-disable @angular-eslint/component-selector */ -import { AsyncPipe, NgFor } from '@angular/common'; -import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; -import { TeacherSelectors } from './store/teacher.selectors'; - -@Component({ - standalone: true, - imports: [NgFor, AsyncPipe], - selector: 'teacher', - template: ` -

TEACHERS

-
- {{ teacher.firstname }} {{ teacher.lastname }} - {{ teacher.version }} -
- `, - styles: [ - ` - :host { - display: block; - width: fit-content; - height: fit-content; - border: 1px solid red; - padding: 4px; - } - `, - ], -}) -export class TeacherComponent { - teacher$ = this.store.select(TeacherSelectors.selectTeachers); - - constructor(private store: Store) {} -} diff --git a/apps/ngrx/notification/src/index.html b/apps/ngrx/notification/src/index.html deleted file mode 100644 index a8fe88b9e..000000000 --- a/apps/ngrx/notification/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - NgrxNotification - - - - - - - - diff --git a/apps/ngrx/notification/src/main.ts b/apps/ngrx/notification/src/main.ts deleted file mode 100644 index 444ad6dff..000000000 --- a/apps/ngrx/notification/src/main.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { appConfig } from './app/app.config'; - -import { bootstrapApplication } from '@angular/platform-browser'; - -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/ngrx/notification/src/polyfills.ts b/apps/ngrx/notification/src/polyfills.ts deleted file mode 100644 index e4555ed11..000000000 --- a/apps/ngrx/notification/src/polyfills.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * This file includes polyfills needed by Angular and is loaded before the app. - * You can add your own extra polyfills to this file. - * - * This file is divided into 2 sections: - * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. - * 2. Application imports. Files imported after ZoneJS that should be loaded before your main - * file. - * - * The current setup is for so-called "evergreen" browsers; the last versions of browsers that - * automatically update themselves. This includes recent versions of Safari, Chrome (including - * Opera), Edge on the desktop, and iOS and Chrome on mobile. - * - * Learn more in https://angular.io/guide/browser-support - */ - -/*************************************************************************************************** - * BROWSER POLYFILLS - */ - -/** - * By default, zone.js will patch all possible macroTask and DomEvents - * user can disable parts of macroTask/DomEvents patch by setting following flags - * because those flags need to be set before `zone.js` being loaded, and webpack - * will put import in the top of bundle, so user need to create a separate file - * in this directory (for example: zone-flags.ts), and put the following flags - * into that file, and then add the following code before importing zone.js. - * import './zone-flags'; - * - * The flags allowed in zone-flags.ts are listed here. - * - * The following flags will work for all browsers. - * - * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame - * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick - * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames - * - * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js - * with the following flag, it will bypass `zone.js` patch for IE/Edge - * - * (window as any).__Zone_enable_cross_context_check = true; - * - */ - -/*************************************************************************************************** - * Zone JS is required by default for Angular itself. - */ -import 'zone.js'; // Included with Angular CLI. - -/*************************************************************************************************** - * APPLICATION IMPORTS - */ diff --git a/apps/ngrx/notification/tsconfig.app.json b/apps/ngrx/notification/tsconfig.app.json deleted file mode 100644 index 7a4dbc47e..000000000 --- a/apps/ngrx/notification/tsconfig.app.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../../dist/out-tsc", - "types": [], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/main.ts", "src/polyfills.ts"], - "include": ["src/**/*.d.ts"], - "exclude": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts"] -} diff --git a/apps/ngrx/notification/tsconfig.editor.json b/apps/ngrx/notification/tsconfig.editor.json deleted file mode 100644 index 3d4f1db8b..000000000 --- a/apps/ngrx/notification/tsconfig.editor.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.json", - "include": [ - "**/*.ts", - "../../../libs/ngrx-notification/backend/src/lib/fake-backend.service.ts" - ], - "compilerOptions": { - "types": [] - } -} diff --git a/apps/ngrx/notification/tsconfig.json b/apps/ngrx/notification/tsconfig.json deleted file mode 100644 index b2dbbf22e..000000000 --- a/apps/ngrx/notification/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.editor.json" - } - ], - "compilerOptions": { - "target": "es2020", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/apps/nx/42-static-vs-dynamic-import/.eslintrc.json b/apps/nx/42-static-vs-dynamic-import/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/nx/42-static-vs-dynamic-import/README.md b/apps/nx/42-static-vs-dynamic-import/README.md new file mode 100644 index 000000000..a08abaa82 --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/README.md @@ -0,0 +1,13 @@ +# Static vs Dynamic Import + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve nx-static-vs-dynamic-import +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/nx/42-static-dynamic-import/). diff --git a/apps/nx/42-static-vs-dynamic-import/project.json b/apps/nx/42-static-vs-dynamic-import/project.json new file mode 100644 index 000000000..7f45fb828 --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/project.json @@ -0,0 +1,73 @@ +{ + "name": "nx-static-vs-dynamic-import", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/nx/42-static-vs-dynamic-import/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/nx/42-static-vs-dynamic-import", + "index": "apps/nx/42-static-vs-dynamic-import/src/index.html", + "browser": "apps/nx/42-static-vs-dynamic-import/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/nx/42-static-vs-dynamic-import/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/nx/42-static-vs-dynamic-import/src/favicon.ico", + "apps/nx/42-static-vs-dynamic-import/src/assets" + ], + "styles": [ + "apps/nx/42-static-vs-dynamic-import/src/styles.scss", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all", + "sourceMap": true + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "nx-static-vs-dynamic-import:build:production" + }, + "development": { + "buildTarget": "nx-static-vs-dynamic-import:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "nx-static-vs-dynamic-import:build" + } + } + } +} diff --git a/apps/nx/42-static-vs-dynamic-import/src/app/app.component.ts b/apps/nx/42-static-vs-dynamic-import/src/app/app.component.ts new file mode 100644 index 000000000..59be617e8 --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/src/app/app.component.ts @@ -0,0 +1,26 @@ +import { + UserComponent, + type User, +} from '@angular-challenges/static-dynamic-import/users'; +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + imports: [UserComponent, RouterOutlet], + selector: 'app-root', + template: ` + Author: + + + `, + host: { + class: 'flex flex-col', + }, +}) +export class AppComponent { + author: User = { + name: 'Thomas', + lastName: 'Laforge', + country: 'France', + }; +} diff --git a/apps/nx/42-static-vs-dynamic-import/src/app/app.config.ts b/apps/nx/42-static-vs-dynamic-import/src/app/app.config.ts new file mode 100644 index 000000000..6525263a3 --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/src/app/app.config.ts @@ -0,0 +1,16 @@ +import { ApplicationConfig } from '@angular/core'; +import { provideAnimations } from '@angular/platform-browser/animations'; +import { provideRouter } from '@angular/router'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideAnimations(), + provideRouter([ + { + path: '', + loadComponent: () => + import('@angular-challenges/static-dynamic-import/users'), + }, + ]), + ], +}; diff --git a/apps/performance/ngfor-optimize/src/assets/.gitkeep b/apps/nx/42-static-vs-dynamic-import/src/assets/.gitkeep similarity index 100% rename from apps/performance/ngfor-optimize/src/assets/.gitkeep rename to apps/nx/42-static-vs-dynamic-import/src/assets/.gitkeep diff --git a/apps/rxjs/pipe-bug/src/favicon.ico b/apps/nx/42-static-vs-dynamic-import/src/favicon.ico similarity index 100% rename from apps/rxjs/pipe-bug/src/favicon.ico rename to apps/nx/42-static-vs-dynamic-import/src/favicon.ico diff --git a/apps/nx/42-static-vs-dynamic-import/src/index.html b/apps/nx/42-static-vs-dynamic-import/src/index.html new file mode 100644 index 000000000..1b4f2a84b --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/src/index.html @@ -0,0 +1,16 @@ + + + + + nx-static-vs-dynamic-import + + + + + + + + + diff --git a/apps/nx/42-static-vs-dynamic-import/src/main.ts b/apps/nx/42-static-vs-dynamic-import/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/nx/42-static-vs-dynamic-import/src/styles.scss b/apps/nx/42-static-vs-dynamic-import/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/testing/modal/tailwind.config.js b/apps/nx/42-static-vs-dynamic-import/tailwind.config.js similarity index 100% rename from apps/testing/modal/tailwind.config.js rename to apps/nx/42-static-vs-dynamic-import/tailwind.config.js diff --git a/apps/typescript/overload/tsconfig.app.json b/apps/nx/42-static-vs-dynamic-import/tsconfig.app.json similarity index 100% rename from apps/typescript/overload/tsconfig.app.json rename to apps/nx/42-static-vs-dynamic-import/tsconfig.app.json diff --git a/apps/performance/ngfor-biglist/tsconfig.editor.json b/apps/nx/42-static-vs-dynamic-import/tsconfig.editor.json similarity index 100% rename from apps/performance/ngfor-biglist/tsconfig.editor.json rename to apps/nx/42-static-vs-dynamic-import/tsconfig.editor.json diff --git a/apps/nx/42-static-vs-dynamic-import/tsconfig.json b/apps/nx/42-static-vs-dynamic-import/tsconfig.json new file mode 100644 index 000000000..b94f8837d --- /dev/null +++ b/apps/nx/42-static-vs-dynamic-import/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/angular/styling/.eslintrc.json b/apps/performance/12-optimize-change-detection/.eslintrc.json similarity index 100% rename from apps/angular/styling/.eslintrc.json rename to apps/performance/12-optimize-change-detection/.eslintrc.json diff --git a/apps/performance/12-optimize-change-detection/README.md b/apps/performance/12-optimize-change-detection/README.md new file mode 100644 index 000000000..52fe319d7 --- /dev/null +++ b/apps/performance/12-optimize-change-detection/README.md @@ -0,0 +1,13 @@ +# Optimize Change Detection + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve performance-optimize-change-detection +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/12-performance-optimize-change-detection/). diff --git a/apps/performance/12-optimize-change-detection/jest.config.ts b/apps/performance/12-optimize-change-detection/jest.config.ts new file mode 100644 index 000000000..dc22d99ea --- /dev/null +++ b/apps/performance/12-optimize-change-detection/jest.config.ts @@ -0,0 +1,24 @@ +/* eslint-disable */ +export default { + displayName: 'performance-optimize-change-detection', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + globals: {}, + coverageDirectory: + '../../../coverage/apps/performance/12-optimize-change-detection', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/performance/12-optimize-change-detection/project.json b/apps/performance/12-optimize-change-detection/project.json new file mode 100644 index 000000000..188240700 --- /dev/null +++ b/apps/performance/12-optimize-change-detection/project.json @@ -0,0 +1,85 @@ +{ + "name": "performance-optimize-change-detection", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/performance/12-optimize-change-detection/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/performance/12-optimize-change-detection", + "index": "apps/performance/12-optimize-change-detection/src/index.html", + "main": "apps/performance/12-optimize-change-detection/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/performance/12-optimize-change-detection/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/performance/12-optimize-change-detection/src/favicon.ico", + "apps/performance/12-optimize-change-detection/src/assets" + ], + "styles": [ + "apps/performance/12-optimize-change-detection/src/styles.scss" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "performance-optimize-change-detection:build:production" + }, + "development": { + "buildTarget": "performance-optimize-change-detection:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "performance-optimize-change-detection:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/performance/12-optimize-change-detection/src/app/app.component.ts b/apps/performance/12-optimize-change-detection/src/app/app.component.ts new file mode 100644 index 000000000..dd818cad5 --- /dev/null +++ b/apps/performance/12-optimize-change-detection/src/app/app.component.ts @@ -0,0 +1,52 @@ +import { AsyncPipe, NgIf } from '@angular/common'; +import { Component, HostListener } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; + +@Component({ + imports: [NgIf, AsyncPipe], + selector: 'app-root', + template: ` +
Top
+
Middle
+
Bottom
+ + `, + styles: [ + ` + :host { + height: 1500px; + display: flex; + flex-direction: column; + justify-content: space-between; + + button { + position: fixed; + bottom: 1rem; + left: 1rem; + z-index: 1; + padding: 1rem; + } + } + `, + ], +}) +export class AppComponent { + title = 'scroll-cd'; + + private displayButtonSubject = new BehaviorSubject(false); + displayButton$ = this.displayButtonSubject.asObservable(); + + @HostListener('window:scroll', ['$event']) + onScroll() { + const pos = window.pageYOffset; + this.displayButtonSubject.next(pos > 50); + } + + goToTop() { + window.scroll({ + top: 0, + left: 0, + behavior: 'smooth', + }); + } +} diff --git a/apps/performance/scroll-cd/src/assets/.gitkeep b/apps/performance/12-optimize-change-detection/src/assets/.gitkeep similarity index 100% rename from apps/performance/scroll-cd/src/assets/.gitkeep rename to apps/performance/12-optimize-change-detection/src/assets/.gitkeep diff --git a/apps/rxjs/race-condition/src/favicon.ico b/apps/performance/12-optimize-change-detection/src/favicon.ico similarity index 100% rename from apps/rxjs/race-condition/src/favicon.ico rename to apps/performance/12-optimize-change-detection/src/favicon.ico diff --git a/apps/performance/12-optimize-change-detection/src/index.html b/apps/performance/12-optimize-change-detection/src/index.html new file mode 100644 index 000000000..c1cb61764 --- /dev/null +++ b/apps/performance/12-optimize-change-detection/src/index.html @@ -0,0 +1,13 @@ + + + + + performance-optimize-change-detection + + + + + + + + diff --git a/apps/testing/checkbox/src/main.ts b/apps/performance/12-optimize-change-detection/src/main.ts similarity index 100% rename from apps/testing/checkbox/src/main.ts rename to apps/performance/12-optimize-change-detection/src/main.ts diff --git a/apps/ngrx/notification/src/styles.scss b/apps/performance/12-optimize-change-detection/src/styles.scss similarity index 100% rename from apps/ngrx/notification/src/styles.scss rename to apps/performance/12-optimize-change-detection/src/styles.scss diff --git a/apps/ngrx/effect-selector/src/test-setup.ts b/apps/performance/12-optimize-change-detection/src/test-setup.ts similarity index 100% rename from apps/ngrx/effect-selector/src/test-setup.ts rename to apps/performance/12-optimize-change-detection/src/test-setup.ts diff --git a/apps/performance/12-optimize-change-detection/tsconfig.app.json b/apps/performance/12-optimize-change-detection/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/performance/12-optimize-change-detection/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/rxjs/catch-error/tsconfig.editor.json b/apps/performance/12-optimize-change-detection/tsconfig.editor.json similarity index 100% rename from apps/rxjs/catch-error/tsconfig.editor.json rename to apps/performance/12-optimize-change-detection/tsconfig.editor.json diff --git a/apps/angular/interop-rxjs-signal/tsconfig.json b/apps/performance/12-optimize-change-detection/tsconfig.json similarity index 100% rename from apps/angular/interop-rxjs-signal/tsconfig.json rename to apps/performance/12-optimize-change-detection/tsconfig.json diff --git a/apps/performance/scroll-cd/tsconfig.spec.json b/apps/performance/12-optimize-change-detection/tsconfig.spec.json similarity index 100% rename from apps/performance/scroll-cd/tsconfig.spec.json rename to apps/performance/12-optimize-change-detection/tsconfig.spec.json diff --git a/apps/performance/default-onpush/.eslintrc.json b/apps/performance/34-default-vs-onpush/.eslintrc.json similarity index 100% rename from apps/performance/default-onpush/.eslintrc.json rename to apps/performance/34-default-vs-onpush/.eslintrc.json diff --git a/apps/performance/34-default-vs-onpush/README.md b/apps/performance/34-default-vs-onpush/README.md new file mode 100644 index 000000000..ab82704b5 --- /dev/null +++ b/apps/performance/34-default-vs-onpush/README.md @@ -0,0 +1,13 @@ +# Default vs OnPush + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve performance-default-vs-onpush +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/34-default-onpush/). diff --git a/apps/performance/34-default-vs-onpush/project.json b/apps/performance/34-default-vs-onpush/project.json new file mode 100644 index 000000000..f81cb74a3 --- /dev/null +++ b/apps/performance/34-default-vs-onpush/project.json @@ -0,0 +1,75 @@ +{ + "name": "performance-default-vs-onpush", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/performance/34-default-vs-onpush/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/performance/34-default-vs-onpush", + "index": "apps/performance/34-default-vs-onpush/src/index.html", + "main": "apps/performance/34-default-vs-onpush/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/performance/34-default-vs-onpush/tsconfig.app.json", + "assets": [ + "apps/performance/34-default-vs-onpush/src/favicon.ico", + "apps/performance/34-default-vs-onpush/src/assets" + ], + "styles": [ + "apps/performance/34-default-vs-onpush/src/styles.scss", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [], + "allowedCommonJsDependencies": ["seedrandom"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "performance-default-vs-onpush:build:production" + }, + "development": { + "buildTarget": "performance-default-vs-onpush:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "performance-default-vs-onpush:build" + } + } + } +} diff --git a/apps/performance/34-default-vs-onpush/src/app/app.component.ts b/apps/performance/34-default-vs-onpush/src/app/app.component.ts new file mode 100644 index 000000000..88b0a6571 --- /dev/null +++ b/apps/performance/34-default-vs-onpush/src/app/app.component.ts @@ -0,0 +1,21 @@ +import { Component } from '@angular/core'; +import { randFirstName } from '@ngneat/falso'; +import { PersonListComponent } from './person-list.component'; +import { RandomComponent } from './random.component'; + +@Component({ + imports: [PersonListComponent, RandomComponent], + selector: 'app-root', + template: ` + + +
+ + +
+ `, +}) +export class AppComponent { + girlList = randFirstName({ gender: 'female', length: 10 }); + boyList = randFirstName({ gender: 'male', length: 10 }); +} diff --git a/apps/performance/default-onpush/src/app/app.config.ts b/apps/performance/34-default-vs-onpush/src/app/app.config.ts similarity index 100% rename from apps/performance/default-onpush/src/app/app.config.ts rename to apps/performance/34-default-vs-onpush/src/app/app.config.ts diff --git a/apps/performance/34-default-vs-onpush/src/app/person-list.component.ts b/apps/performance/34-default-vs-onpush/src/app/person-list.component.ts new file mode 100644 index 000000000..4cd92396a --- /dev/null +++ b/apps/performance/34-default-vs-onpush/src/app/person-list.component.ts @@ -0,0 +1,67 @@ +import { Component, Input } from '@angular/core'; + +import { CDFlashingDirective } from '@angular-challenges/shared/directives'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatListModule } from '@angular/material/list'; + +@Component({ + selector: 'app-person-list', + imports: [ + CommonModule, + FormsModule, + MatListModule, + MatFormFieldModule, + MatInputModule, + MatChipsModule, + CDFlashingDirective, + ], + template: ` +

+ {{ title | titlecase }} +

+ + + + + + +
Empty list
+ +
+

+ {{ name }} +

+
+
+ +
+ `, + host: { + class: 'w-full flex flex-col items-center', + }, +}) +export class PersonListComponent { + @Input() names: string[] = []; + @Input() title = ''; + + label = ''; + + handleKey(event: KeyboardEvent) { + if (event.key === 'Enter') { + this.names?.unshift(this.label); + this.label = ''; + } + } +} diff --git a/apps/performance/34-default-vs-onpush/src/app/random.component.ts b/apps/performance/34-default-vs-onpush/src/app/random.component.ts new file mode 100644 index 000000000..71479e28d --- /dev/null +++ b/apps/performance/34-default-vs-onpush/src/app/random.component.ts @@ -0,0 +1,11 @@ +import { CDFlashingDirective } from '@angular-challenges/shared/directives'; +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-random', + template: ` +
I do nothing but I'm here
+ `, + imports: [CDFlashingDirective], +}) +export class RandomComponent {} diff --git a/apps/rxjs/catch-error/src/assets/.gitkeep b/apps/performance/34-default-vs-onpush/src/assets/.gitkeep similarity index 100% rename from apps/rxjs/catch-error/src/assets/.gitkeep rename to apps/performance/34-default-vs-onpush/src/assets/.gitkeep diff --git a/apps/testing/checkbox/src/favicon.ico b/apps/performance/34-default-vs-onpush/src/favicon.ico similarity index 100% rename from apps/testing/checkbox/src/favicon.ico rename to apps/performance/34-default-vs-onpush/src/favicon.ico diff --git a/apps/performance/34-default-vs-onpush/src/index.html b/apps/performance/34-default-vs-onpush/src/index.html new file mode 100644 index 000000000..251489ea3 --- /dev/null +++ b/apps/performance/34-default-vs-onpush/src/index.html @@ -0,0 +1,13 @@ + + + + + performance-default-vs-onpush + + + + + + + + diff --git a/apps/performance/34-default-vs-onpush/src/main.ts b/apps/performance/34-default-vs-onpush/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/performance/34-default-vs-onpush/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/performance/34-default-vs-onpush/src/styles.scss b/apps/performance/34-default-vs-onpush/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/performance/34-default-vs-onpush/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/testing/table/tailwind.config.js b/apps/performance/34-default-vs-onpush/tailwind.config.js similarity index 100% rename from apps/testing/table/tailwind.config.js rename to apps/performance/34-default-vs-onpush/tailwind.config.js diff --git a/apps/performance/34-default-vs-onpush/tsconfig.app.json b/apps/performance/34-default-vs-onpush/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/performance/34-default-vs-onpush/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/performance/default-onpush/tsconfig.editor.json b/apps/performance/34-default-vs-onpush/tsconfig.editor.json similarity index 100% rename from apps/performance/default-onpush/tsconfig.editor.json rename to apps/performance/34-default-vs-onpush/tsconfig.editor.json diff --git a/apps/performance/default-onpush/tsconfig.json b/apps/performance/34-default-vs-onpush/tsconfig.json similarity index 100% rename from apps/performance/default-onpush/tsconfig.json rename to apps/performance/34-default-vs-onpush/tsconfig.json diff --git a/apps/performance/memoized/.eslintrc.json b/apps/performance/35-memoization/.eslintrc.json similarity index 100% rename from apps/performance/memoized/.eslintrc.json rename to apps/performance/35-memoization/.eslintrc.json diff --git a/apps/performance/35-memoization/README.md b/apps/performance/35-memoization/README.md new file mode 100644 index 000000000..a06a0e91d --- /dev/null +++ b/apps/performance/35-memoization/README.md @@ -0,0 +1,13 @@ +# Memoization + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve performance-memoization +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/35-memoize/). diff --git a/apps/performance/35-memoization/project.json b/apps/performance/35-memoization/project.json new file mode 100644 index 000000000..041308626 --- /dev/null +++ b/apps/performance/35-memoization/project.json @@ -0,0 +1,75 @@ +{ + "name": "performance-memoization", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/performance/35-memoization/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/performance/35-memoization", + "index": "apps/performance/35-memoization/src/index.html", + "main": "apps/performance/35-memoization/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/performance/35-memoization/tsconfig.app.json", + "assets": [ + "apps/performance/35-memoization/src/favicon.ico", + "apps/performance/35-memoization/src/assets" + ], + "styles": [ + "apps/performance/35-memoization/src/styles.scss", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [], + "allowedCommonJsDependencies": ["seedrandom"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "performance-memoization:build:production" + }, + "development": { + "buildTarget": "performance-memoization:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "performance-memoization:build" + } + } + } +} diff --git a/apps/performance/35-memoization/src/app/app.component.ts b/apps/performance/35-memoization/src/app/app.component.ts new file mode 100644 index 000000000..04c7758fc --- /dev/null +++ b/apps/performance/35-memoization/src/app/app.component.ts @@ -0,0 +1,27 @@ +import { NgIf } from '@angular/common'; +import { Component } from '@angular/core'; +import { generateList } from './generateList'; +import { PersonListComponent } from './person-list.component'; + +@Component({ + imports: [PersonListComponent, NgIf], + selector: 'app-root', + template: ` +

Performance is key!!

+ + + + `, +}) +export class AppComponent { + persons = generateList(); + loadList = false; +} diff --git a/apps/performance/memoized/src/app/app.config.ts b/apps/performance/35-memoization/src/app/app.config.ts similarity index 100% rename from apps/performance/memoized/src/app/app.config.ts rename to apps/performance/35-memoization/src/app/app.config.ts diff --git a/apps/performance/memoized/src/app/generateList.ts b/apps/performance/35-memoization/src/app/generateList.ts similarity index 100% rename from apps/performance/memoized/src/app/generateList.ts rename to apps/performance/35-memoization/src/app/generateList.ts diff --git a/apps/performance/35-memoization/src/app/person-list.component.ts b/apps/performance/35-memoization/src/app/person-list.component.ts new file mode 100644 index 000000000..28cbac267 --- /dev/null +++ b/apps/performance/35-memoization/src/app/person-list.component.ts @@ -0,0 +1,63 @@ +import { Component, Input } from '@angular/core'; + +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { MatChipsModule } from '@angular/material/chips'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatListModule } from '@angular/material/list'; +import { Person } from './person.model'; + +const fibonacci = (num: number): number => { + if (num === 1 || num === 2) { + return 1; + } + return fibonacci(num - 1) + fibonacci(num - 2); +}; + +@Component({ + selector: 'app-person-list', + imports: [ + CommonModule, + FormsModule, + MatListModule, + MatFormFieldModule, + MatInputModule, + MatChipsModule, + ], + template: ` +

+ {{ title | titlecase }} +

+ + + + + + + +
+

{{ person.name }}

+ {{ calculate(person.fib) }} +
+
+
+ `, + host: { + class: 'w-full flex flex-col items-center', + }, +}) +export class PersonListComponent { + @Input() persons: Person[] = []; + @Input() title = ''; + + label = ''; + + calculate(num: number) { + return fibonacci(num); + } +} diff --git a/apps/performance/memoized/src/app/person.model.ts b/apps/performance/35-memoization/src/app/person.model.ts similarity index 100% rename from apps/performance/memoized/src/app/person.model.ts rename to apps/performance/35-memoization/src/app/person.model.ts diff --git a/apps/rxjs/pipe-bug/src/assets/.gitkeep b/apps/performance/35-memoization/src/assets/.gitkeep similarity index 100% rename from apps/rxjs/pipe-bug/src/assets/.gitkeep rename to apps/performance/35-memoization/src/assets/.gitkeep diff --git a/apps/testing/create-harness/src/favicon.ico b/apps/performance/35-memoization/src/favicon.ico similarity index 100% rename from apps/testing/create-harness/src/favicon.ico rename to apps/performance/35-memoization/src/favicon.ico diff --git a/apps/performance/35-memoization/src/index.html b/apps/performance/35-memoization/src/index.html new file mode 100644 index 000000000..39ddb9045 --- /dev/null +++ b/apps/performance/35-memoization/src/index.html @@ -0,0 +1,13 @@ + + + + + performance-memoization + + + + + + + + diff --git a/apps/performance/35-memoization/src/main.ts b/apps/performance/35-memoization/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/performance/35-memoization/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/performance/35-memoization/src/styles.scss b/apps/performance/35-memoization/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/performance/35-memoization/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/testing/todos-list/tailwind.config.js b/apps/performance/35-memoization/tailwind.config.js similarity index 100% rename from apps/testing/todos-list/tailwind.config.js rename to apps/performance/35-memoization/tailwind.config.js diff --git a/apps/performance/35-memoization/tsconfig.app.json b/apps/performance/35-memoization/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/performance/35-memoization/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/testing/create-harness/tsconfig.editor.json b/apps/performance/35-memoization/tsconfig.editor.json similarity index 100% rename from apps/testing/create-harness/tsconfig.editor.json rename to apps/performance/35-memoization/tsconfig.editor.json diff --git a/apps/performance/memoized/tsconfig.json b/apps/performance/35-memoization/tsconfig.json similarity index 100% rename from apps/performance/memoized/tsconfig.json rename to apps/performance/35-memoization/tsconfig.json diff --git a/apps/performance/ngfor-biglist/.eslintrc.json b/apps/performance/36-ngfor-optimization/.eslintrc.json similarity index 100% rename from apps/performance/ngfor-biglist/.eslintrc.json rename to apps/performance/36-ngfor-optimization/.eslintrc.json diff --git a/apps/performance/36-ngfor-optimization/README.md b/apps/performance/36-ngfor-optimization/README.md new file mode 100644 index 000000000..2ee0bb20e --- /dev/null +++ b/apps/performance/36-ngfor-optimization/README.md @@ -0,0 +1,13 @@ +# NgFor Optimization + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve performance-ngfor-optimization +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/36-ngfor-optimize/). diff --git a/apps/performance/36-ngfor-optimization/jest.config.ts b/apps/performance/36-ngfor-optimization/jest.config.ts new file mode 100644 index 000000000..2e138df90 --- /dev/null +++ b/apps/performance/36-ngfor-optimization/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'performance-ngfor-optimization', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/performance/36-ngfor-optimization', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/performance/36-ngfor-optimization/project.json b/apps/performance/36-ngfor-optimization/project.json new file mode 100644 index 000000000..05dfcd1e2 --- /dev/null +++ b/apps/performance/36-ngfor-optimization/project.json @@ -0,0 +1,86 @@ +{ + "name": "performance-ngfor-optimization", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/performance/36-ngfor-optimization/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/performance/36-ngfor-optimization", + "index": "apps/performance/36-ngfor-optimization/src/index.html", + "main": "apps/performance/36-ngfor-optimization/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/performance/36-ngfor-optimization/tsconfig.app.json", + "assets": [ + "apps/performance/36-ngfor-optimization/src/favicon.ico", + "apps/performance/36-ngfor-optimization/src/assets" + ], + "styles": [ + "apps/performance/36-ngfor-optimization/src/styles.scss", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [], + "allowedCommonJsDependencies": ["seedrandom"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "performance-ngfor-optimization:build:production" + }, + "development": { + "buildTarget": "performance-ngfor-optimization:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "performance-ngfor-optimization:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/performance/36-ngfor-optimization/src/app/app.component.ts b/apps/performance/36-ngfor-optimization/src/app/app.component.ts new file mode 100644 index 000000000..f1aa9f133 --- /dev/null +++ b/apps/performance/36-ngfor-optimization/src/app/app.component.ts @@ -0,0 +1,57 @@ +import { Component, OnInit, inject } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { PersonService } from './list.service'; +import { PersonListComponent } from './person-list.component'; + +@Component({ + imports: [ + PersonListComponent, + FormsModule, + MatFormFieldModule, + MatInputModule, + ], + providers: [PersonService], + selector: 'app-root', + template: ` +

+ List of Persons +

+ + + + + + + `, + host: { + class: 'flex items-center flex-col gap-5', + }, +}) +export class AppComponent implements OnInit { + readonly personService = inject(PersonService); + readonly persons = this.personService.persons; + + label = ''; + + ngOnInit(): void { + this.personService.loadPersons(); + } + + handleKey(event: any) { + if (event.keyCode === 13) { + this.personService.addPerson(this.label); + this.label = ''; + } + } +} diff --git a/apps/performance/ngfor-biglist/src/app/app.config.ts b/apps/performance/36-ngfor-optimization/src/app/app.config.ts similarity index 100% rename from apps/performance/ngfor-biglist/src/app/app.config.ts rename to apps/performance/36-ngfor-optimization/src/app/app.config.ts diff --git a/apps/performance/ngfor-optimize/src/app/generateList.ts b/apps/performance/36-ngfor-optimization/src/app/generateList.ts similarity index 100% rename from apps/performance/ngfor-optimize/src/app/generateList.ts rename to apps/performance/36-ngfor-optimization/src/app/generateList.ts diff --git a/apps/performance/36-ngfor-optimization/src/app/list.service.ts b/apps/performance/36-ngfor-optimization/src/app/list.service.ts new file mode 100644 index 000000000..9a54824d1 --- /dev/null +++ b/apps/performance/36-ngfor-optimization/src/app/list.service.ts @@ -0,0 +1,44 @@ +import { Injectable, inject, signal } from '@angular/core'; +import { randEmail, randFirstName } from '@ngneat/falso'; +import { generateList } from './generateList'; +import { Person } from './person.model'; + +@Injectable() +export class PersonService { + private readonly fakeBackend = inject(FakeBackendService); + readonly persons = signal([]); + + loadPersons() { + this.persons.set(generateList()); + } + + deletePerson(email: string) { + this.persons.set( + this.fakeBackend + .returnNewList(this.persons()) + .filter((p) => p.email !== email), + ); + } + + updatePerson(email: string) { + this.persons.set( + this.fakeBackend + .returnNewList(this.persons()) + .map((p) => (p.email === email ? { email, name: randFirstName() } : p)), + ); + } + + addPerson(name: string) { + this.persons.set([ + { email: randEmail(), name }, + ...this.fakeBackend.returnNewList(this.persons()), + ]); + } +} + +@Injectable({ providedIn: 'root' }) +export class FakeBackendService { + returnNewList = (input: Person[]): Person[] => [ + ...input.map((i) => ({ ...i })), + ]; +} diff --git a/apps/performance/36-ngfor-optimization/src/app/person-list.component.ts b/apps/performance/36-ngfor-optimization/src/app/person-list.component.ts new file mode 100644 index 000000000..6d9b2b4af --- /dev/null +++ b/apps/performance/36-ngfor-optimization/src/app/person-list.component.ts @@ -0,0 +1,36 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; + +import { CommonModule } from '@angular/common'; +import { Person } from './person.model'; + +@Component({ + selector: 'app-person-list', + imports: [CommonModule], + template: ` +
+

{{ person.name }}

+
+ + +
+
+ `, + host: { + class: 'w-full flex flex-col', + }, +}) +export class PersonListComponent { + @Input() persons: Person[] = []; + @Output() delete = new EventEmitter(); + @Output() update = new EventEmitter(); +} diff --git a/apps/performance/ngfor-biglist/src/app/person.model.ts b/apps/performance/36-ngfor-optimization/src/app/person.model.ts similarity index 100% rename from apps/performance/ngfor-biglist/src/app/person.model.ts rename to apps/performance/36-ngfor-optimization/src/app/person.model.ts diff --git a/apps/rxjs/race-condition/src/assets/.gitkeep b/apps/performance/36-ngfor-optimization/src/assets/.gitkeep similarity index 100% rename from apps/rxjs/race-condition/src/assets/.gitkeep rename to apps/performance/36-ngfor-optimization/src/assets/.gitkeep diff --git a/apps/testing/harness/src/favicon.ico b/apps/performance/36-ngfor-optimization/src/favicon.ico similarity index 100% rename from apps/testing/harness/src/favicon.ico rename to apps/performance/36-ngfor-optimization/src/favicon.ico diff --git a/apps/performance/36-ngfor-optimization/src/index.html b/apps/performance/36-ngfor-optimization/src/index.html new file mode 100644 index 000000000..07ec600a8 --- /dev/null +++ b/apps/performance/36-ngfor-optimization/src/index.html @@ -0,0 +1,13 @@ + + + + + performance-ngfor-optimization + + + + + + + + diff --git a/apps/performance/36-ngfor-optimization/src/main.ts b/apps/performance/36-ngfor-optimization/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/performance/36-ngfor-optimization/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/performance/36-ngfor-optimization/src/styles.scss b/apps/performance/36-ngfor-optimization/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/performance/36-ngfor-optimization/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/testing/harness/src/test-setup.ts b/apps/performance/36-ngfor-optimization/src/test-setup.ts similarity index 100% rename from apps/testing/harness/src/test-setup.ts rename to apps/performance/36-ngfor-optimization/src/test-setup.ts diff --git a/apps/performance/36-ngfor-optimization/tailwind.config.js b/apps/performance/36-ngfor-optimization/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/performance/36-ngfor-optimization/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/performance/36-ngfor-optimization/tsconfig.app.json b/apps/performance/36-ngfor-optimization/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/performance/36-ngfor-optimization/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/rxjs/race-condition/tsconfig.editor.json b/apps/performance/36-ngfor-optimization/tsconfig.editor.json similarity index 100% rename from apps/rxjs/race-condition/tsconfig.editor.json rename to apps/performance/36-ngfor-optimization/tsconfig.editor.json diff --git a/apps/performance/ngfor-optimize/tsconfig.json b/apps/performance/36-ngfor-optimization/tsconfig.json similarity index 100% rename from apps/performance/ngfor-optimize/tsconfig.json rename to apps/performance/36-ngfor-optimization/tsconfig.json diff --git a/apps/performance/36-ngfor-optimization/tsconfig.spec.json b/apps/performance/36-ngfor-optimization/tsconfig.spec.json new file mode 100644 index 000000000..1a4817a7d --- /dev/null +++ b/apps/performance/36-ngfor-optimization/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "@testing-library/jest-dom"] + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/apps/performance/ngfor-optimize/.eslintrc.json b/apps/performance/37-optimize-big-list/.eslintrc.json similarity index 100% rename from apps/performance/ngfor-optimize/.eslintrc.json rename to apps/performance/37-optimize-big-list/.eslintrc.json diff --git a/apps/performance/37-optimize-big-list/README.md b/apps/performance/37-optimize-big-list/README.md new file mode 100644 index 000000000..1d8e134c2 --- /dev/null +++ b/apps/performance/37-optimize-big-list/README.md @@ -0,0 +1,13 @@ +# NgFor optimize big list + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve performance-optimize-big-list +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/37-ngfor-biglist/). diff --git a/apps/performance/37-optimize-big-list/project.json b/apps/performance/37-optimize-big-list/project.json new file mode 100644 index 000000000..fbd03771e --- /dev/null +++ b/apps/performance/37-optimize-big-list/project.json @@ -0,0 +1,75 @@ +{ + "name": "performance-optimize-big-list", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/performance/37-optimize-big-list/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/performance/37-optimize-big-list", + "index": "apps/performance/37-optimize-big-list/src/index.html", + "main": "apps/performance/37-optimize-big-list/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/performance/37-optimize-big-list/tsconfig.app.json", + "assets": [ + "apps/performance/37-optimize-big-list/src/favicon.ico", + "apps/performance/37-optimize-big-list/src/assets" + ], + "styles": [ + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", + "apps/performance/37-optimize-big-list/src/styles.scss" + ], + "scripts": [], + "allowedCommonJsDependencies": ["seedrandom"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "performance-optimize-big-list:build:production" + }, + "development": { + "buildTarget": "performance-optimize-big-list:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "performance-optimize-big-list:build" + } + } + } +} diff --git a/apps/performance/37-optimize-big-list/src/app/app.component.ts b/apps/performance/37-optimize-big-list/src/app/app.component.ts new file mode 100644 index 000000000..c441134df --- /dev/null +++ b/apps/performance/37-optimize-big-list/src/app/app.component.ts @@ -0,0 +1,41 @@ +import { NgIf } from '@angular/common'; +import { Component, signal } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { generateList } from './generateList'; +import { PersonService } from './list.service'; +import { PersonListComponent } from './person-list.component'; + +@Component({ + imports: [ + NgIf, + PersonListComponent, + FormsModule, + MatFormFieldModule, + MatInputModule, + ], + providers: [PersonService], + selector: 'app-root', + template: ` + + + + `, + host: { + class: 'flex items-center flex-col gap-5', + }, +}) +export class AppComponent { + readonly persons = signal(generateList()); + readonly loadList = signal(false); + + label = ''; +} diff --git a/apps/performance/ngfor-optimize/src/app/app.config.ts b/apps/performance/37-optimize-big-list/src/app/app.config.ts similarity index 100% rename from apps/performance/ngfor-optimize/src/app/app.config.ts rename to apps/performance/37-optimize-big-list/src/app/app.config.ts diff --git a/apps/performance/ngfor-biglist/src/app/generateList.ts b/apps/performance/37-optimize-big-list/src/app/generateList.ts similarity index 100% rename from apps/performance/ngfor-biglist/src/app/generateList.ts rename to apps/performance/37-optimize-big-list/src/app/generateList.ts diff --git a/apps/performance/37-optimize-big-list/src/app/list.service.ts b/apps/performance/37-optimize-big-list/src/app/list.service.ts new file mode 100644 index 000000000..9a54824d1 --- /dev/null +++ b/apps/performance/37-optimize-big-list/src/app/list.service.ts @@ -0,0 +1,44 @@ +import { Injectable, inject, signal } from '@angular/core'; +import { randEmail, randFirstName } from '@ngneat/falso'; +import { generateList } from './generateList'; +import { Person } from './person.model'; + +@Injectable() +export class PersonService { + private readonly fakeBackend = inject(FakeBackendService); + readonly persons = signal([]); + + loadPersons() { + this.persons.set(generateList()); + } + + deletePerson(email: string) { + this.persons.set( + this.fakeBackend + .returnNewList(this.persons()) + .filter((p) => p.email !== email), + ); + } + + updatePerson(email: string) { + this.persons.set( + this.fakeBackend + .returnNewList(this.persons()) + .map((p) => (p.email === email ? { email, name: randFirstName() } : p)), + ); + } + + addPerson(name: string) { + this.persons.set([ + { email: randEmail(), name }, + ...this.fakeBackend.returnNewList(this.persons()), + ]); + } +} + +@Injectable({ providedIn: 'root' }) +export class FakeBackendService { + returnNewList = (input: Person[]): Person[] => [ + ...input.map((i) => ({ ...i })), + ]; +} diff --git a/apps/performance/37-optimize-big-list/src/app/person-list.component.ts b/apps/performance/37-optimize-big-list/src/app/person-list.component.ts new file mode 100644 index 000000000..6159baaaa --- /dev/null +++ b/apps/performance/37-optimize-big-list/src/app/person-list.component.ts @@ -0,0 +1,29 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; + +import { NgForTrackByModule } from '@angular-challenges/shared/directives'; +import { CommonModule } from '@angular/common'; +import { Person } from './person.model'; + +@Component({ + selector: 'app-person-list', + imports: [CommonModule, NgForTrackByModule], + template: ` +
+
+
+

{{ person.name }}

+

{{ person.email }}

+
+
+
+ `, + host: { + class: 'w-full flex flex-col', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class PersonListComponent { + @Input() persons: Person[] = []; +} diff --git a/apps/performance/ngfor-optimize/src/app/person.model.ts b/apps/performance/37-optimize-big-list/src/app/person.model.ts similarity index 100% rename from apps/performance/ngfor-optimize/src/app/person.model.ts rename to apps/performance/37-optimize-big-list/src/app/person.model.ts diff --git a/apps/testing/checkbox/src/assets/.gitkeep b/apps/performance/37-optimize-big-list/src/assets/.gitkeep similarity index 100% rename from apps/testing/checkbox/src/assets/.gitkeep rename to apps/performance/37-optimize-big-list/src/assets/.gitkeep diff --git a/apps/testing/input-output/src/favicon.ico b/apps/performance/37-optimize-big-list/src/favicon.ico similarity index 100% rename from apps/testing/input-output/src/favicon.ico rename to apps/performance/37-optimize-big-list/src/favicon.ico diff --git a/apps/performance/37-optimize-big-list/src/index.html b/apps/performance/37-optimize-big-list/src/index.html new file mode 100644 index 000000000..f93d2d26f --- /dev/null +++ b/apps/performance/37-optimize-big-list/src/index.html @@ -0,0 +1,13 @@ + + + + + performance-optimize-big-list + + + + + + + + diff --git a/apps/performance/37-optimize-big-list/src/main.ts b/apps/performance/37-optimize-big-list/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/performance/37-optimize-big-list/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/performance/37-optimize-big-list/src/styles.scss b/apps/performance/37-optimize-big-list/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/performance/37-optimize-big-list/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/performance/37-optimize-big-list/tailwind.config.js b/apps/performance/37-optimize-big-list/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/performance/37-optimize-big-list/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/performance/37-optimize-big-list/tsconfig.app.json b/apps/performance/37-optimize-big-list/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/performance/37-optimize-big-list/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/typescript/overload/tsconfig.editor.json b/apps/performance/37-optimize-big-list/tsconfig.editor.json similarity index 100% rename from apps/typescript/overload/tsconfig.editor.json rename to apps/performance/37-optimize-big-list/tsconfig.editor.json diff --git a/apps/performance/ngfor-biglist/tsconfig.json b/apps/performance/37-optimize-big-list/tsconfig.json similarity index 100% rename from apps/performance/ngfor-biglist/tsconfig.json rename to apps/performance/37-optimize-big-list/tsconfig.json diff --git a/apps/performance/40-web-workers/.eslintrc.json b/apps/performance/40-web-workers/.eslintrc.json new file mode 100644 index 000000000..d3cd7997a --- /dev/null +++ b/apps/performance/40-web-workers/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": {} + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/performance/40-web-workers/README.md b/apps/performance/40-web-workers/README.md new file mode 100644 index 000000000..067777a8f --- /dev/null +++ b/apps/performance/40-web-workers/README.md @@ -0,0 +1,13 @@ +# Web workers + +> Author: Thomas Laforge + +### Run Application + +```bash +npx nx serve performance-web-workers +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/40-christmas-web-worker/). diff --git a/apps/performance/40-web-workers/project.json b/apps/performance/40-web-workers/project.json new file mode 100644 index 000000000..843a35c60 --- /dev/null +++ b/apps/performance/40-web-workers/project.json @@ -0,0 +1,69 @@ +{ + "name": "performance-web-workers", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/performance/40-web-workers/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/performance/40-web-workers", + "index": "apps/performance/40-web-workers/src/index.html", + "browser": "apps/performance/40-web-workers/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/performance/40-web-workers/tsconfig.app.json", + "assets": [ + "apps/performance/40-web-workers/src/favicon.ico", + "apps/performance/40-web-workers/src/assets" + ], + "styles": ["apps/performance/40-web-workers/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "performance-web-workers:build:production" + }, + "development": { + "buildTarget": "performance-web-workers:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "performance-web-workers:build" + } + } + } +} diff --git a/apps/performance/40-web-workers/src/app/app.component.ts b/apps/performance/40-web-workers/src/app/app.component.ts new file mode 100644 index 000000000..583572ed2 --- /dev/null +++ b/apps/performance/40-web-workers/src/app/app.component.ts @@ -0,0 +1,31 @@ +import { CommonModule } from '@angular/common'; +import { Component, inject } from '@angular/core'; +import { HeavyCalculationService } from './heavy-calculation.service'; +import { UnknownPersonComponent } from './unknown-person/unknown-person.component'; + +@Component({ + imports: [CommonModule, UnknownPersonComponent], + providers: [HeavyCalculationService], + selector: 'app-root', + template: ` + + +
Progress: {{ loadingPercentage() }}%
+ `, + host: { + class: `flex flex-col h-screen w-screen bg-[#1f75c0]`, + }, +}) +export class AppComponent { + private heavyCalculationService = inject(HeavyCalculationService); + + readonly loadingPercentage = this.heavyCalculationService.loadingPercentage; + + discover() { + this.heavyCalculationService.startLoading(); + } +} diff --git a/apps/performance/40-web-workers/src/app/heavy-calculation.service.ts b/apps/performance/40-web-workers/src/app/heavy-calculation.service.ts new file mode 100644 index 000000000..06dedd1a6 --- /dev/null +++ b/apps/performance/40-web-workers/src/app/heavy-calculation.service.ts @@ -0,0 +1,30 @@ +import { Injectable, computed, signal } from '@angular/core'; + +@Injectable() +export class HeavyCalculationService { + private finalLength = 664579; + private loadingLength = signal(0); + + loadingPercentage = computed( + () => (this.loadingLength() * 100) / this.finalLength, + ); + + startLoading() { + this.randomHeavyCalculationFunction(); + } + + private randomHeavyCalculationFunction() { + for (let num = 2; num <= 10000000; num++) { + let randomFlag = true; + for (let i = 2; i <= Math.sqrt(num); i++) { + if (num % i === 0) { + randomFlag = false; + break; + } + } + if (randomFlag) { + this.loadingLength.update((l) => l + 1); + } + } + } +} diff --git a/apps/performance/40-web-workers/src/app/unknown-person/unknown-person.component.css b/apps/performance/40-web-workers/src/app/unknown-person/unknown-person.component.css new file mode 100644 index 000000000..edc1f75ad --- /dev/null +++ b/apps/performance/40-web-workers/src/app/unknown-person/unknown-person.component.css @@ -0,0 +1,225 @@ +*, +*:before, +*:after { + padding: 0; + margin: 0; + box-sizing: border-box; +} +body { + background-color: #fff2c8; +} +.container { + width: 380px; + height: 500px; + position: absolute; + transform: translate(-50%, -50%); + top: 50%; + left: 50%; +} +.container *:before, +.container *:after { + position: absolute; + content: ''; +} +.santa { + height: 220px; + width: 200px; + background-color: #e84701; + border-radius: 80px; + position: absolute; + left: 115px; + top: 200px; +} +.santa:before, +.santa:after { + width: 40px; + margin: auto; + left: 0; + right: 0; + background-color: #fff2c8; +} +.santa:before { + height: 130px; +} +.santa:after { + height: 40px; + bottom: -15px; +} +.hand-l { + background-color: #e84701; + height: 90px; + width: 105px; + position: absolute; + right: -30px; + top: 20px; + border-radius: 0 80px 0 0; +} +.hand-l:before { + margin: auto; + width: 35px; + height: 15px; + background-color: #ffffff; + top: 85px; + left: 71px; +} +.hand-l:after { + height: 15px; + width: 30px; + background-color: #fad2af; + left: 74px; + top: 101px; + border-radius: 0 0 30px 30px; +} +.hand-r { + height: 150px; + width: 180px; + border: 30px solid transparent; + border-bottom: 40px solid #e84701; + position: absolute; + left: -100px; + bottom: 150px; + border-radius: 50%; + animation: wave 1.5s infinite; + transform-origin: right; +} +@keyframes wave { + 50% { + transform: rotate(15deg); + } +} +.hand-r:before { + width: 35px; + height: 15px; + background-color: #ffffff; + transform: rotate(-50deg); + top: 68px; + left: -22px; +} +.hand-r:after { + width: 30px; + height: 15px; + background-color: #fad2af; + transform: rotate(-50deg); + left: -31px; + top: 58px; + border-radius: 15px 15px 0 0; +} +.face { + position: absolute; + margin: auto; + height: 180px; + width: 180px; + background-color: #fad2af; + border: 25px solid #f2e6da; + border-radius: 50%; + left: 0; + right: 0; + bottom: 140px; +} +.beard { + position: absolute; + height: 90px; + width: 180px; + background-color: #ffffff; + border-radius: 0 0 90px 90px; + right: -25px; + bottom: -25px; +} +.beard:before { + width: 55px; + height: 25px; + background-color: #f2e6da; + border-radius: 20px 0; + left: 34px; +} +.beard:after { + height: 25px; + width: 55px; + background-color: #f2e6da; + border-radius: 0 20px; + right: 34px; +} +.eyes { + height: 12px; + width: 12px; + background-color: #0078ca; + border-radius: 50%; + position: absolute; + top: 40px; + left: 40px; + box-shadow: + 38px 0 #0078ca, + 19px 20px #f69697; +} +.eyes:before { + height: 12px; + width: 25px; + background-color: #ffffff; + border-radius: 10px 0; + left: -10px; + bottom: 20px; +} +.eyes:after { + height: 12px; + width: 25px; + background-color: #ffffff; + border-radius: 0 10px; + left: 32px; + bottom: 20px; +} +.hat { + position: absolute; + height: 60px; + width: 120px; + background-color: #e84701; + top: -98px; + left: 85px; + border-radius: 0 0 60px 60px; +} +.hat:before { + height: 40px; + width: 40px; + background-color: #ffffff; + left: 100px; + top: -15px; + border-radius: 50%; +} +.belt { + position: absolute; + width: 100%; + height: 30px; + background-color: #000000; + top: 100px; +} +.belt:before { + height: 100%; + width: 40px; + border: 7px solid #ffdc2e; + margin: auto; + left: 0; + right: 0; +} +.belt:after { + height: 5px; + width: 15px; + background-color: #ffdc2e; + left: 100px; + top: 12px; +} +.shoe { + height: 20px; + width: 20px; + background-color: #000000; + position: absolute; + top: 220px; + left: 60px; + border-radius: 20px 0 0 0; +} +.shoe:before { + height: 20px; + width: 20px; + background-color: #000000; + top: 0; + left: 60px; + border-radius: 0 20px 0 0; +} diff --git a/apps/performance/40-web-workers/src/app/unknown-person/unknown-person.component.ts b/apps/performance/40-web-workers/src/app/unknown-person/unknown-person.component.ts new file mode 100644 index 000000000..c230a4cec --- /dev/null +++ b/apps/performance/40-web-workers/src/app/unknown-person/unknown-person.component.ts @@ -0,0 +1,35 @@ +import { Component, Input } from '@angular/core'; +@Component({ + selector: 'unknown-person', + standalone: true, + template: ` +
+ @if (step !== 100) { +
+ Who is here? +
+ } +
+
Happy Christmas !!!
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `, + styleUrls: [`unknown-person.component.css`], +}) +export class UnknownPersonComponent { + @Input({ required: true }) step!: number; +} diff --git a/apps/testing/create-harness/src/assets/.gitkeep b/apps/performance/40-web-workers/src/assets/.gitkeep similarity index 100% rename from apps/testing/create-harness/src/assets/.gitkeep rename to apps/performance/40-web-workers/src/assets/.gitkeep diff --git a/apps/testing/modal/src/favicon.ico b/apps/performance/40-web-workers/src/favicon.ico similarity index 100% rename from apps/testing/modal/src/favicon.ico rename to apps/performance/40-web-workers/src/favicon.ico diff --git a/apps/performance/40-web-workers/src/index.html b/apps/performance/40-web-workers/src/index.html new file mode 100644 index 000000000..fa0cf99ae --- /dev/null +++ b/apps/performance/40-web-workers/src/index.html @@ -0,0 +1,13 @@ + + + + + performance-web-worker + + + + + + + + diff --git a/apps/testing/input-output/src/main.ts b/apps/performance/40-web-workers/src/main.ts similarity index 100% rename from apps/testing/input-output/src/main.ts rename to apps/performance/40-web-workers/src/main.ts diff --git a/apps/performance/40-web-workers/src/styles.scss b/apps/performance/40-web-workers/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/performance/40-web-workers/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/performance/40-web-workers/tailwind.config.js b/apps/performance/40-web-workers/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/performance/40-web-workers/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/performance/40-web-workers/tsconfig.app.json b/apps/performance/40-web-workers/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/performance/40-web-workers/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/performance/40-web-workers/tsconfig.editor.json b/apps/performance/40-web-workers/tsconfig.editor.json new file mode 100644 index 000000000..4ee639340 --- /dev/null +++ b/apps/performance/40-web-workers/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": [] + } +} diff --git a/apps/typescript/overload/tsconfig.json b/apps/performance/40-web-workers/tsconfig.json similarity index 100% rename from apps/typescript/overload/tsconfig.json rename to apps/performance/40-web-workers/tsconfig.json diff --git a/apps/performance/default-onpush/README.md b/apps/performance/default-onpush/README.md deleted file mode 100644 index 72b809004..000000000 --- a/apps/performance/default-onpush/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Default vs OnPush - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve performance-default-onpush -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/34-default-onpush/). diff --git a/apps/performance/default-onpush/project.json b/apps/performance/default-onpush/project.json deleted file mode 100644 index 0171a1675..000000000 --- a/apps/performance/default-onpush/project.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "name": "performance-default-onpush", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/performance/default-onpush/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/performance/default-onpush", - "index": "apps/performance/default-onpush/src/index.html", - "main": "apps/performance/default-onpush/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/performance/default-onpush/tsconfig.app.json", - "assets": [ - "apps/performance/default-onpush/src/favicon.ico", - "apps/performance/default-onpush/src/assets" - ], - "styles": [ - "apps/performance/default-onpush/src/styles.scss", - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" - ], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "performance-default-onpush:build:production" - }, - "development": { - "browserTarget": "performance-default-onpush:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "performance-default-onpush:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/performance/default-onpush/**/*.ts", - "apps/performance/default-onpush/**/*.html" - ] - } - } - } -} diff --git a/apps/performance/default-onpush/src/app/app.component.ts b/apps/performance/default-onpush/src/app/app.component.ts deleted file mode 100644 index 1eab3c839..000000000 --- a/apps/performance/default-onpush/src/app/app.component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Component } from '@angular/core'; -import { randFirstName } from '@ngneat/falso'; -import { PersonListComponent } from './person-list.component'; -import { RandomComponent } from './random.component'; - -@Component({ - standalone: true, - imports: [PersonListComponent, RandomComponent], - selector: 'app-root', - template: ` - - -
- - -
- `, -}) -export class AppComponent { - girlList = randFirstName({ gender: 'female', length: 10 }); - boyList = randFirstName({ gender: 'male', length: 10 }); -} diff --git a/apps/performance/default-onpush/src/app/person-list.component.ts b/apps/performance/default-onpush/src/app/person-list.component.ts deleted file mode 100644 index 3c6535edb..000000000 --- a/apps/performance/default-onpush/src/app/person-list.component.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Component, Input } from '@angular/core'; - -import { CDFlashingDirective } from '@angular-challenges/shared/directives'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; -import { MatChipsModule } from '@angular/material/chips'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatListModule } from '@angular/material/list'; - -@Component({ - selector: 'app-person-list', - standalone: true, - imports: [ - CommonModule, - FormsModule, - MatListModule, - MatFormFieldModule, - MatInputModule, - MatChipsModule, - CDFlashingDirective, - ], - template: ` -

- {{ title | titlecase }} -

- - - - - - -
Empty list
- -
-

- {{ name }} -

-
-
- -
- `, - host: { - class: 'w-full flex flex-col items-center', - }, -}) -export class PersonListComponent { - @Input() names: string[] = []; - @Input() title = ''; - - label = ''; - - handleKey(event: any) { - if (event.keyCode === 13) { - this.names?.unshift(this.label); - this.label = ''; - } - } -} diff --git a/apps/performance/default-onpush/src/app/random.component.ts b/apps/performance/default-onpush/src/app/random.component.ts deleted file mode 100644 index 105f7b991..000000000 --- a/apps/performance/default-onpush/src/app/random.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { CDFlashingDirective } from '@angular-challenges/shared/directives'; -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-random', - standalone: true, - template: `
I do nothing but I'm here
`, - imports: [CDFlashingDirective], -}) -export class RandomComponent {} diff --git a/apps/performance/default-onpush/src/index.html b/apps/performance/default-onpush/src/index.html deleted file mode 100644 index dcea38498..000000000 --- a/apps/performance/default-onpush/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Default OnPush - - - - - - - - diff --git a/apps/performance/default-onpush/src/main.ts b/apps/performance/default-onpush/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/performance/default-onpush/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/performance/memoized/README.md b/apps/performance/memoized/README.md deleted file mode 100644 index 94feaddcc..000000000 --- a/apps/performance/memoized/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Memoization - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve performance-memoized -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/35-memoize/). diff --git a/apps/performance/memoized/project.json b/apps/performance/memoized/project.json deleted file mode 100644 index 240e1e626..000000000 --- a/apps/performance/memoized/project.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "name": "performance-memoized", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/performance/memoized/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/performance/memoized", - "index": "apps/performance/memoized/src/index.html", - "main": "apps/performance/memoized/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/performance/memoized/tsconfig.app.json", - "assets": [ - "apps/performance/memoized/src/favicon.ico", - "apps/performance/memoized/src/assets" - ], - "styles": [ - "apps/performance/memoized/src/styles.scss", - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" - ], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "performance-memoized:build:production" - }, - "development": { - "browserTarget": "performance-memoized:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "performance-memoized:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/performance/memoized/**/*.ts", - "apps/performance/memoized/**/*.html" - ] - } - } - } -} diff --git a/apps/performance/memoized/src/app/app.component.ts b/apps/performance/memoized/src/app/app.component.ts deleted file mode 100644 index 01d049309..000000000 --- a/apps/performance/memoized/src/app/app.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { NgIf } from '@angular/common'; -import { Component } from '@angular/core'; -import { generateList } from './generateList'; -import { PersonListComponent } from './person-list.component'; - -@Component({ - standalone: true, - imports: [PersonListComponent, NgIf], - selector: 'app-root', - template: ` -

Performance is key!!

- - - - `, -}) -export class AppComponent { - persons = generateList(); - loadList = false; -} diff --git a/apps/performance/memoized/src/app/person-list.component.ts b/apps/performance/memoized/src/app/person-list.component.ts deleted file mode 100644 index 1f8ae156c..000000000 --- a/apps/performance/memoized/src/app/person-list.component.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Component, Input } from '@angular/core'; - -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; -import { MatChipsModule } from '@angular/material/chips'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatListModule } from '@angular/material/list'; -import { Person } from './person.model'; - -const fibonacci = (num: number): number => { - if (num === 1 || num === 2) { - return 1; - } - return fibonacci(num - 1) + fibonacci(num - 2); -}; - -@Component({ - selector: 'app-person-list', - standalone: true, - imports: [ - CommonModule, - FormsModule, - MatListModule, - MatFormFieldModule, - MatInputModule, - MatChipsModule, - ], - template: ` -

- {{ title | titlecase }} -

- - - - - - - -
-

{{ person.name }}

- {{ calculate(person.fib) }} -
-
-
- `, - host: { - class: 'w-full flex flex-col items-center', - }, -}) -export class PersonListComponent { - @Input() persons: Person[] = []; - @Input() title = ''; - - label = ''; - - calculate(num: number) { - return fibonacci(num); - } -} diff --git a/apps/performance/memoized/src/index.html b/apps/performance/memoized/src/index.html deleted file mode 100644 index 459031f27..000000000 --- a/apps/performance/memoized/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - performance-memoized - - - - - - - - diff --git a/apps/performance/memoized/src/main.ts b/apps/performance/memoized/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/performance/memoized/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/performance/ngfor-biglist/README.md b/apps/performance/ngfor-biglist/README.md deleted file mode 100644 index 828f93eea..000000000 --- a/apps/performance/ngfor-biglist/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# NgFor optimize big list - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve performance-ngfor-biglist -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/37-ngfor-biglist/). diff --git a/apps/performance/ngfor-biglist/project.json b/apps/performance/ngfor-biglist/project.json deleted file mode 100644 index 532181ebc..000000000 --- a/apps/performance/ngfor-biglist/project.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "name": "performance-ngfor-biglist", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/performance/ngfor-biglist/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/performance/ngfor-biglist", - "index": "apps/performance/ngfor-biglist/src/index.html", - "main": "apps/performance/ngfor-biglist/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/performance/ngfor-biglist/tsconfig.app.json", - "assets": [ - "apps/performance/ngfor-biglist/src/favicon.ico", - "apps/performance/ngfor-biglist/src/assets" - ], - "styles": [ - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", - "apps/performance/ngfor-biglist/src/styles.scss" - ], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "performance-ngfor-biglist:build:production" - }, - "development": { - "browserTarget": "performance-ngfor-biglist:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "performance-ngfor-biglist:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/performance/ngfor-biglist/**/*.ts", - "apps/performance/ngfor-biglist/**/*.html" - ] - } - } - } -} diff --git a/apps/performance/ngfor-biglist/src/app/app.component.ts b/apps/performance/ngfor-biglist/src/app/app.component.ts deleted file mode 100644 index 1baa61dab..000000000 --- a/apps/performance/ngfor-biglist/src/app/app.component.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { NgIf } from '@angular/common'; -import { Component, signal } from '@angular/core'; -import { FormsModule } from '@angular/forms'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { generateList } from './generateList'; -import { PersonService } from './list.service'; -import { PersonListComponent } from './person-list.component'; - -@Component({ - standalone: true, - imports: [ - NgIf, - PersonListComponent, - FormsModule, - MatFormFieldModule, - MatInputModule, - ], - providers: [PersonService], - selector: 'app-root', - template: ` - - - - `, - host: { - class: 'flex items-center flex-col gap-5', - }, -}) -export class AppComponent { - readonly persons = signal(generateList()); - readonly loadList = signal(false); - - label = ''; -} diff --git a/apps/performance/ngfor-biglist/src/app/list.service.ts b/apps/performance/ngfor-biglist/src/app/list.service.ts deleted file mode 100644 index e56bddef8..000000000 --- a/apps/performance/ngfor-biglist/src/app/list.service.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Injectable, inject, signal } from '@angular/core'; -import { randEmail, randFirstName } from '@ngneat/falso'; -import { generateList } from './generateList'; -import { Person } from './person.model'; - -@Injectable() -export class PersonService { - private readonly fakeBackend = inject(FakeBackendService); - readonly persons = signal([]); - - loadPersons() { - this.persons.set(generateList()); - } - - deletePerson(email: string) { - this.persons.set( - this.fakeBackend - .returnNewList(this.persons()) - .filter((p) => p.email !== email) - ); - } - - updatePerson(email: string) { - this.persons.set( - this.fakeBackend - .returnNewList(this.persons()) - .map((p) => (p.email === email ? { email, name: randFirstName() } : p)) - ); - } - - addPerson(name: string) { - this.persons.set([ - { email: randEmail(), name }, - ...this.fakeBackend.returnNewList(this.persons()), - ]); - } -} - -@Injectable({ providedIn: 'root' }) -export class FakeBackendService { - returnNewList = (input: Person[]): Person[] => [ - ...input.map((i) => ({ ...i })), - ]; -} diff --git a/apps/performance/ngfor-biglist/src/app/person-list.component.ts b/apps/performance/ngfor-biglist/src/app/person-list.component.ts deleted file mode 100644 index e9bbb1785..000000000 --- a/apps/performance/ngfor-biglist/src/app/person-list.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; - -import { NgForTrackByModule } from '@angular-challenges/shared/directives'; -import { CommonModule } from '@angular/common'; -import { Person } from './person.model'; - -@Component({ - selector: 'app-person-list', - standalone: true, - imports: [CommonModule, NgForTrackByModule], - template: ` -
-
-
-

{{ person.name }}

-

{{ person.email }}

-
-
-
- `, - host: { - class: 'w-full flex flex-col', - }, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class PersonListComponent { - @Input() persons: Person[] = []; -} diff --git a/apps/performance/ngfor-biglist/src/index.html b/apps/performance/ngfor-biglist/src/index.html deleted file mode 100644 index f23a85cca..000000000 --- a/apps/performance/ngfor-biglist/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - performance-ngfor-biglist - - - - - - - - diff --git a/apps/performance/ngfor-biglist/src/main.ts b/apps/performance/ngfor-biglist/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/performance/ngfor-biglist/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/performance/ngfor-optimize/README.md b/apps/performance/ngfor-optimize/README.md deleted file mode 100644 index a26efa57f..000000000 --- a/apps/performance/ngfor-optimize/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# NgFor Optimization - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve performance-ngfor-optimize -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/36-ngfor-optimize/). diff --git a/apps/performance/ngfor-optimize/jest.config.ts b/apps/performance/ngfor-optimize/jest.config.ts deleted file mode 100644 index 5b2ccaee0..000000000 --- a/apps/performance/ngfor-optimize/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'performance-ngfor-optimize', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - coverageDirectory: '../../../coverage/apps/performance/ngfor-optimize', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/performance/ngfor-optimize/project.json b/apps/performance/ngfor-optimize/project.json deleted file mode 100644 index b922dce09..000000000 --- a/apps/performance/ngfor-optimize/project.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "name": "performance-ngfor-optimize", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/performance/ngfor-optimize/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/performance/ngfor-optimize", - "index": "apps/performance/ngfor-optimize/src/index.html", - "main": "apps/performance/ngfor-optimize/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/performance/ngfor-optimize/tsconfig.app.json", - "assets": [ - "apps/performance/ngfor-optimize/src/favicon.ico", - "apps/performance/ngfor-optimize/src/assets" - ], - "styles": [ - "apps/performance/ngfor-optimize/src/styles.scss", - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" - ], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "performance-ngfor-optimize:build:production" - }, - "development": { - "browserTarget": "performance-ngfor-optimize:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "performance-ngfor-optimize:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/performance/ngfor-optimize/**/*.ts", - "apps/performance/ngfor-optimize/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/performance/ngfor-optimize/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - } - } -} diff --git a/apps/performance/ngfor-optimize/src/app/app.component.ts b/apps/performance/ngfor-optimize/src/app/app.component.ts deleted file mode 100644 index 58d89f4f5..000000000 --- a/apps/performance/ngfor-optimize/src/app/app.component.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Component, OnInit, inject } from '@angular/core'; -import { FormsModule } from '@angular/forms'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { PersonService } from './list.service'; -import { PersonListComponent } from './person-list.component'; - -@Component({ - standalone: true, - imports: [ - PersonListComponent, - FormsModule, - MatFormFieldModule, - MatInputModule, - ], - providers: [PersonService], - selector: 'app-root', - template: ` -

- List of Persons -

- - - - - - - `, - host: { - class: 'flex items-center flex-col gap-5', - }, -}) -export class AppComponent implements OnInit { - readonly personService = inject(PersonService); - readonly persons = this.personService.persons; - - label = ''; - - ngOnInit(): void { - this.personService.loadPersons(); - } - - handleKey(event: any) { - if (event.keyCode === 13) { - this.personService.addPerson(this.label); - this.label = ''; - } - } -} diff --git a/apps/performance/ngfor-optimize/src/app/list.service.ts b/apps/performance/ngfor-optimize/src/app/list.service.ts deleted file mode 100644 index e56bddef8..000000000 --- a/apps/performance/ngfor-optimize/src/app/list.service.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Injectable, inject, signal } from '@angular/core'; -import { randEmail, randFirstName } from '@ngneat/falso'; -import { generateList } from './generateList'; -import { Person } from './person.model'; - -@Injectable() -export class PersonService { - private readonly fakeBackend = inject(FakeBackendService); - readonly persons = signal([]); - - loadPersons() { - this.persons.set(generateList()); - } - - deletePerson(email: string) { - this.persons.set( - this.fakeBackend - .returnNewList(this.persons()) - .filter((p) => p.email !== email) - ); - } - - updatePerson(email: string) { - this.persons.set( - this.fakeBackend - .returnNewList(this.persons()) - .map((p) => (p.email === email ? { email, name: randFirstName() } : p)) - ); - } - - addPerson(name: string) { - this.persons.set([ - { email: randEmail(), name }, - ...this.fakeBackend.returnNewList(this.persons()), - ]); - } -} - -@Injectable({ providedIn: 'root' }) -export class FakeBackendService { - returnNewList = (input: Person[]): Person[] => [ - ...input.map((i) => ({ ...i })), - ]; -} diff --git a/apps/performance/ngfor-optimize/src/app/person-list.component.ts b/apps/performance/ngfor-optimize/src/app/person-list.component.ts deleted file mode 100644 index 69aee34d8..000000000 --- a/apps/performance/ngfor-optimize/src/app/person-list.component.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; - -import { CommonModule } from '@angular/common'; -import { Person } from './person.model'; - -@Component({ - selector: 'app-person-list', - standalone: true, - imports: [CommonModule], - template: ` -
-

{{ person.name }}

-
- - -
-
- `, - host: { - class: 'w-full flex flex-col', - }, -}) -export class PersonListComponent { - @Input() persons: Person[] = []; - @Output() delete = new EventEmitter(); - @Output() update = new EventEmitter(); -} diff --git a/apps/performance/ngfor-optimize/src/index.html b/apps/performance/ngfor-optimize/src/index.html deleted file mode 100644 index 63fe2adcd..000000000 --- a/apps/performance/ngfor-optimize/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - performance-ngfor-optimize - - - - - - - - diff --git a/apps/performance/ngfor-optimize/src/main.ts b/apps/performance/ngfor-optimize/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/performance/ngfor-optimize/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/performance/scroll-cd/README.md b/apps/performance/scroll-cd/README.md deleted file mode 100644 index ef30c5c9d..000000000 --- a/apps/performance/scroll-cd/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Optimize Change Detection - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve performance-scroll-cd -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/performance/12-performance-scroll-cd/). diff --git a/apps/performance/scroll-cd/jest.config.ts b/apps/performance/scroll-cd/jest.config.ts deleted file mode 100644 index 4c9105010..000000000 --- a/apps/performance/scroll-cd/jest.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'performance-scroll-cd', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../../coverage/apps/performance/scroll-cd', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/performance/scroll-cd/project.json b/apps/performance/scroll-cd/project.json deleted file mode 100644 index f24ef597c..000000000 --- a/apps/performance/scroll-cd/project.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "name": "performance-scroll-cd", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/performance/scroll-cd/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/performance/scroll-cd", - "index": "apps/performance/scroll-cd/src/index.html", - "main": "apps/performance/scroll-cd/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/performance/scroll-cd/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/performance/scroll-cd/src/favicon.ico", - "apps/performance/scroll-cd/src/assets" - ], - "styles": ["apps/performance/scroll-cd/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "performance-scroll-cd:build:production" - }, - "development": { - "browserTarget": "performance-scroll-cd:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "performance-scroll-cd:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/performance/scroll-cd/**/*.ts", - "apps/performance/scroll-cd/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/performance/scroll-cd/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] -} diff --git a/apps/performance/scroll-cd/src/app/app.component.ts b/apps/performance/scroll-cd/src/app/app.component.ts deleted file mode 100644 index e75ef991e..000000000 --- a/apps/performance/scroll-cd/src/app/app.component.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { AsyncPipe, NgIf } from '@angular/common'; -import { Component, HostListener } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; - -@Component({ - standalone: true, - imports: [NgIf, AsyncPipe], - selector: 'app-root', - template: ` -
Top
-
Middle
-
Bottom
- - `, - styles: [ - ` - :host { - height: 1500px; - display: flex; - flex-direction: column; - justify-content: space-between; - - button { - position: fixed; - bottom: 1rem; - left: 1rem; - z-index: 1; - padding: 1rem; - } - } - `, - ], -}) -export class AppComponent { - title = 'scroll-cd'; - - private displayButtonSubject = new BehaviorSubject(false); - displayButton$ = this.displayButtonSubject.asObservable(); - - @HostListener('window:scroll', ['$event']) - onScroll() { - const pos = window.pageYOffset; - this.displayButtonSubject.next(pos > 50); - } - - goToTop() { - window.scroll({ - top: 0, - left: 0, - behavior: 'smooth', - }); - } -} diff --git a/apps/performance/scroll-cd/src/index.html b/apps/performance/scroll-cd/src/index.html deleted file mode 100644 index 5a2673441..000000000 --- a/apps/performance/scroll-cd/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - ScrollCd - - - - - - - - diff --git a/apps/rxjs/11-high-order-operator-bug/.eslintrc.json b/apps/rxjs/11-high-order-operator-bug/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/rxjs/11-high-order-operator-bug/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/rxjs/11-high-order-operator-bug/README.md b/apps/rxjs/11-high-order-operator-bug/README.md new file mode 100644 index 000000000..5a4fa5512 --- /dev/null +++ b/apps/rxjs/11-high-order-operator-bug/README.md @@ -0,0 +1,13 @@ +# High Order Operator Bug + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve rxjs-high-order-operator-bug +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/rxjs/11-bug-chaining-operator/). diff --git a/apps/rxjs/11-high-order-operator-bug/project.json b/apps/rxjs/11-high-order-operator-bug/project.json new file mode 100644 index 000000000..e8e3f2045 --- /dev/null +++ b/apps/rxjs/11-high-order-operator-bug/project.json @@ -0,0 +1,73 @@ +{ + "name": "rxjs-high-order-operator-bug", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/rxjs/11-high-order-operator-bug/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/rxjs/11-high-order-operator-bug", + "index": "apps/rxjs/11-high-order-operator-bug/src/index.html", + "main": "apps/rxjs/11-high-order-operator-bug/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/rxjs/11-high-order-operator-bug/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/rxjs/11-high-order-operator-bug/src/favicon.ico", + "apps/rxjs/11-high-order-operator-bug/src/assets" + ], + "styles": ["apps/rxjs/11-high-order-operator-bug/src/styles.scss"], + "scripts": [], + "allowedCommonJsDependencies": ["seedrandom"] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "rxjs-high-order-operator-bug:build:production" + }, + "development": { + "buildTarget": "rxjs-high-order-operator-bug:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "rxjs-high-order-operator-bug:build" + } + } + } +} diff --git a/apps/rxjs/11-high-order-operator-bug/src/app/app.component.ts b/apps/rxjs/11-high-order-operator-bug/src/app/app.component.ts new file mode 100644 index 000000000..fb80fb2b6 --- /dev/null +++ b/apps/rxjs/11-high-order-operator-bug/src/app/app.component.ts @@ -0,0 +1,52 @@ +/* eslint-disable @angular-eslint/component-selector */ +import { Component, inject, input, signal } from '@angular/core'; +import { take } from 'rxjs'; +import { AppService } from './app.service'; +import { TopicType } from './localDB.service'; + +@Component({ + selector: 'button-delete-topic', + template: ` + +
{{ message() }}
+ `, +}) +export class ButtonDeleteComponent { + readonly topic = input.required(); + + message = signal(''); + + private service = inject(AppService); + + deleteTopic() { + this.service + .deleteOldTopics(this.topic()) + .pipe(take(1)) + .subscribe((result) => + this.message.set( + result + ? `All ${this.topic()} have been deleted` + : `Error: deletion of some ${this.topic()} failed`, + ), + ); + } +} + +@Component({ + imports: [ButtonDeleteComponent], + selector: 'app-root', + template: ` + @for (info of allInfo(); track info.id) { +
{{ info.id }} - {{ info.topic }}
+ } + + Delete Food + Delete Sport + Delete Book + `, +}) +export class AppComponent { + private service = inject(AppService); + + allInfo = this.service.getAllInfo; +} diff --git a/apps/rxjs/11-high-order-operator-bug/src/app/app.service.ts b/apps/rxjs/11-high-order-operator-bug/src/app/app.service.ts new file mode 100644 index 000000000..df2269a89 --- /dev/null +++ b/apps/rxjs/11-high-order-operator-bug/src/app/app.service.ts @@ -0,0 +1,19 @@ +import { inject, Injectable } from '@angular/core'; +import { merge, Observable, of } from 'rxjs'; +import { LocalDBService, TopicType } from './localDB.service'; + +@Injectable({ providedIn: 'root' }) +export class AppService { + private dbService = inject(LocalDBService); + + getAllInfo = this.dbService.infos; + + deleteOldTopics(type: TopicType): Observable { + const infoByType = this.dbService.searchByType(type); + return infoByType.length > 0 + ? infoByType + .map((t) => this.dbService.deleteOneTopic(t.id)) + .reduce((acc, curr) => merge(acc, curr), of(true)) + : of(true); + } +} diff --git a/apps/rxjs/11-high-order-operator-bug/src/app/localDB.service.ts b/apps/rxjs/11-high-order-operator-bug/src/app/localDB.service.ts new file mode 100644 index 000000000..5a035e087 --- /dev/null +++ b/apps/rxjs/11-high-order-operator-bug/src/app/localDB.service.ts @@ -0,0 +1,53 @@ +/* eslint-disable @typescript-eslint/member-ordering */ +import { randomError } from '@angular-challenges/shared/utils'; +import { computed, Injectable, signal } from '@angular/core'; +import { of } from 'rxjs'; + +export type TopicType = 'food' | 'book' | 'sport'; + +interface Info { + id: number; + topic: TopicType; +} + +interface DBState { + infos: Info[]; +} + +const initialState: DBState = { + infos: [ + { id: 1, topic: 'book' }, + { id: 2, topic: 'book' }, + { id: 3, topic: 'book' }, + { id: 4, topic: 'book' }, + { id: 5, topic: 'food' }, + { id: 6, topic: 'food' }, + { id: 7, topic: 'book' }, + { id: 8, topic: 'book' }, + { id: 9, topic: 'book' }, + { id: 10, topic: 'sport' }, + ], +}; + +@Injectable({ providedIn: 'root' }) +export class LocalDBService { + private state = signal(initialState); + + infos = computed(() => this.state().infos); + + searchByType = (type: TopicType) => + this.infos().filter((i) => i.topic === type); + + deleteOne = (id: number) => { + this.state.set({ infos: this.state().infos.filter((i) => i.id !== id) }); + }; + + deleteOneTopic = (id: number) => + randomError({ + success: () => { + this.deleteOne(id); + return of(true); + }, + error: () => of(false), + }); +} diff --git a/apps/testing/harness/src/assets/.gitkeep b/apps/rxjs/11-high-order-operator-bug/src/assets/.gitkeep similarity index 100% rename from apps/testing/harness/src/assets/.gitkeep rename to apps/rxjs/11-high-order-operator-bug/src/assets/.gitkeep diff --git a/apps/testing/nested/src/favicon.ico b/apps/rxjs/11-high-order-operator-bug/src/favicon.ico similarity index 100% rename from apps/testing/nested/src/favicon.ico rename to apps/rxjs/11-high-order-operator-bug/src/favicon.ico diff --git a/apps/rxjs/11-high-order-operator-bug/src/index.html b/apps/rxjs/11-high-order-operator-bug/src/index.html new file mode 100644 index 000000000..148a16280 --- /dev/null +++ b/apps/rxjs/11-high-order-operator-bug/src/index.html @@ -0,0 +1,13 @@ + + + + + rxjs-high-order-operator-bug + + + + + + + + diff --git a/apps/testing/nested/src/main.ts b/apps/rxjs/11-high-order-operator-bug/src/main.ts similarity index 100% rename from apps/testing/nested/src/main.ts rename to apps/rxjs/11-high-order-operator-bug/src/main.ts diff --git a/apps/performance/scroll-cd/src/styles.scss b/apps/rxjs/11-high-order-operator-bug/src/styles.scss similarity index 100% rename from apps/performance/scroll-cd/src/styles.scss rename to apps/rxjs/11-high-order-operator-bug/src/styles.scss diff --git a/apps/rxjs/pipe-bug/tsconfig.app.json b/apps/rxjs/11-high-order-operator-bug/tsconfig.app.json similarity index 100% rename from apps/rxjs/pipe-bug/tsconfig.app.json rename to apps/rxjs/11-high-order-operator-bug/tsconfig.app.json diff --git a/apps/rxjs/pipe-bug/tsconfig.editor.json b/apps/rxjs/11-high-order-operator-bug/tsconfig.editor.json similarity index 100% rename from apps/rxjs/pipe-bug/tsconfig.editor.json rename to apps/rxjs/11-high-order-operator-bug/tsconfig.editor.json diff --git a/apps/rxjs/pipe-bug/tsconfig.json b/apps/rxjs/11-high-order-operator-bug/tsconfig.json similarity index 100% rename from apps/rxjs/pipe-bug/tsconfig.json rename to apps/rxjs/11-high-order-operator-bug/tsconfig.json diff --git a/apps/performance/scroll-cd/.eslintrc.json b/apps/rxjs/14-race-condition/.eslintrc.json similarity index 100% rename from apps/performance/scroll-cd/.eslintrc.json rename to apps/rxjs/14-race-condition/.eslintrc.json diff --git a/apps/rxjs/14-race-condition/README.md b/apps/rxjs/14-race-condition/README.md new file mode 100644 index 000000000..e9b61106b --- /dev/null +++ b/apps/rxjs/14-race-condition/README.md @@ -0,0 +1,13 @@ +# Race Condition + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve rxjs-race-condition +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/rxjs/14-race-condition/). diff --git a/apps/rxjs/14-race-condition/cypress.config.ts b/apps/rxjs/14-race-condition/cypress.config.ts new file mode 100644 index 000000000..1abef9c0c --- /dev/null +++ b/apps/rxjs/14-race-condition/cypress.config.ts @@ -0,0 +1,6 @@ +import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; +import { defineConfig } from 'cypress'; + +export default defineConfig({ + component: nxComponentTestingPreset(__filename), +}); diff --git a/apps/rxjs/race-condition/cypress/fixtures/example.json b/apps/rxjs/14-race-condition/cypress/fixtures/example.json similarity index 100% rename from apps/rxjs/race-condition/cypress/fixtures/example.json rename to apps/rxjs/14-race-condition/cypress/fixtures/example.json diff --git a/apps/rxjs/race-condition/cypress/support/commands.ts b/apps/rxjs/14-race-condition/cypress/support/commands.ts similarity index 100% rename from apps/rxjs/race-condition/cypress/support/commands.ts rename to apps/rxjs/14-race-condition/cypress/support/commands.ts diff --git a/apps/rxjs/14-race-condition/cypress/support/component-index.html b/apps/rxjs/14-race-condition/cypress/support/component-index.html new file mode 100644 index 000000000..6afcd5780 --- /dev/null +++ b/apps/rxjs/14-race-condition/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + rxjs-race-condition Components App + + +
+ + diff --git a/apps/rxjs/14-race-condition/cypress/support/component.ts b/apps/rxjs/14-race-condition/cypress/support/component.ts new file mode 100644 index 000000000..e7c3e3cbc --- /dev/null +++ b/apps/rxjs/14-race-condition/cypress/support/component.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your subscription files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.ts using ES2015 syntax: +import './commands'; diff --git a/apps/rxjs/race-condition/cypress/tsconfig.json b/apps/rxjs/14-race-condition/cypress/tsconfig.json similarity index 100% rename from apps/rxjs/race-condition/cypress/tsconfig.json rename to apps/rxjs/14-race-condition/cypress/tsconfig.json diff --git a/apps/rxjs/14-race-condition/jest.config.ts b/apps/rxjs/14-race-condition/jest.config.ts new file mode 100644 index 000000000..493fb2452 --- /dev/null +++ b/apps/rxjs/14-race-condition/jest.config.ts @@ -0,0 +1,23 @@ +/* eslint-disable */ +export default { + displayName: 'rxjs-race-condition', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../../coverage/apps/rxjs/14-race-condition', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/rxjs/14-race-condition/project.json b/apps/rxjs/14-race-condition/project.json new file mode 100644 index 000000000..f84ccf155 --- /dev/null +++ b/apps/rxjs/14-race-condition/project.json @@ -0,0 +1,83 @@ +{ + "name": "rxjs-race-condition", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/rxjs/14-race-condition/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/rxjs/14-race-condition", + "index": "apps/rxjs/14-race-condition/src/index.html", + "main": "apps/rxjs/14-race-condition/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/rxjs/14-race-condition/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/rxjs/14-race-condition/src/favicon.ico", + "apps/rxjs/14-race-condition/src/assets" + ], + "styles": ["apps/rxjs/14-race-condition/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "rxjs-race-condition:build:production" + }, + "development": { + "buildTarget": "rxjs-race-condition:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "rxjs-race-condition:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/rxjs/race-condition/src/app/app.component.cy.ts b/apps/rxjs/14-race-condition/src/app/app.component.cy.ts similarity index 100% rename from apps/rxjs/race-condition/src/app/app.component.cy.ts rename to apps/rxjs/14-race-condition/src/app/app.component.cy.ts diff --git a/apps/rxjs/14-race-condition/src/app/app.component.ts b/apps/rxjs/14-race-condition/src/app/app.component.ts new file mode 100644 index 000000000..a7eb77710 --- /dev/null +++ b/apps/rxjs/14-race-condition/src/app/app.component.ts @@ -0,0 +1,40 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + OnInit, +} from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { take } from 'rxjs'; +import { TopicModalComponent } from './topic-dialog.component'; +import { TopicService, TopicType } from './topic.service'; + +@Component({ + standalone: true, + selector: 'app-root', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent implements OnInit { + title = 'rxjs-race-condition'; + dialog = inject(MatDialog); + topicService = inject(TopicService); + topics: TopicType[] = []; + + ngOnInit(): void { + this.topicService + .fakeGetHttpTopic() + .pipe(take(1)) + .subscribe((topics) => (this.topics = topics)); + } + + openTopicModal() { + this.dialog.open(TopicModalComponent, { + data: { + topics: this.topics, + }, + }); + } +} diff --git a/apps/rxjs/14-race-condition/src/app/app.config.ts b/apps/rxjs/14-race-condition/src/app/app.config.ts new file mode 100644 index 000000000..692a8f2e2 --- /dev/null +++ b/apps/rxjs/14-race-condition/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig, importProvidersFrom } from '@angular/core'; +import { MatDialogModule } from '@angular/material/dialog'; +export const appConfig: ApplicationConfig = { + providers: [importProvidersFrom(MatDialogModule)], +}; diff --git a/apps/rxjs/race-condition/src/app/topic-dialog.component.ts b/apps/rxjs/14-race-condition/src/app/topic-dialog.component.ts similarity index 80% rename from apps/rxjs/race-condition/src/app/topic-dialog.component.ts rename to apps/rxjs/14-race-condition/src/app/topic-dialog.component.ts index 31712413a..e01a69a01 100644 --- a/apps/rxjs/race-condition/src/app/topic-dialog.component.ts +++ b/apps/rxjs/14-race-condition/src/app/topic-dialog.component.ts @@ -1,10 +1,11 @@ import { NgFor } from '@angular/common'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; @Component({ - template: `

Show all Topics

+ template: ` +

Show all Topics

  • @@ -14,9 +15,9 @@ import { MatDialogModule, MAT_DIALOG_DATA } from '@angular/material/dialog';
-
`, +
+ `, imports: [MatDialogModule, MatButtonModule, NgFor], - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, }) export class TopicModalComponent { diff --git a/apps/rxjs/race-condition/src/app/topic.service.ts b/apps/rxjs/14-race-condition/src/app/topic.service.ts similarity index 100% rename from apps/rxjs/race-condition/src/app/topic.service.ts rename to apps/rxjs/14-race-condition/src/app/topic.service.ts diff --git a/apps/testing/input-output/src/assets/.gitkeep b/apps/rxjs/14-race-condition/src/assets/.gitkeep similarity index 100% rename from apps/testing/input-output/src/assets/.gitkeep rename to apps/rxjs/14-race-condition/src/assets/.gitkeep diff --git a/apps/testing/router-outlet/src/favicon.ico b/apps/rxjs/14-race-condition/src/favicon.ico similarity index 100% rename from apps/testing/router-outlet/src/favicon.ico rename to apps/rxjs/14-race-condition/src/favicon.ico diff --git a/apps/rxjs/14-race-condition/src/index.html b/apps/rxjs/14-race-condition/src/index.html new file mode 100644 index 000000000..629547b5b --- /dev/null +++ b/apps/rxjs/14-race-condition/src/index.html @@ -0,0 +1,13 @@ + + + + + rxjs-race-condition + + + + + + + + diff --git a/apps/rxjs/14-race-condition/src/main.ts b/apps/rxjs/14-race-condition/src/main.ts new file mode 100644 index 000000000..9bb5c3023 --- /dev/null +++ b/apps/rxjs/14-race-condition/src/main.ts @@ -0,0 +1,8 @@ +import { appConfig } from './app/app.config'; + +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/rxjs/14-race-condition/src/styles.scss b/apps/rxjs/14-race-condition/src/styles.scss new file mode 100644 index 000000000..215c83eb9 --- /dev/null +++ b/apps/rxjs/14-race-condition/src/styles.scss @@ -0,0 +1,25 @@ +/* You can add global styles to this file, and also import other style files */ + +@use '@angular/material' as mat; + +@include mat.elevation-classes(); +@include mat.app-background(); + +$theme-primary: mat.m2-define-palette(mat.$m2-indigo-palette); +$theme-accent: mat.m2-define-palette(mat.$m2-pink-palette, A200, A100, A400); + +$theme-warn: mat.m2-define-palette(mat.$m2-red-palette); + +$theme: mat.m2-define-light-theme( + ( + color: ( + primary: $theme-primary, + accent: $theme-accent, + warn: $theme-warn, + ), + typography: mat.m2-define-typography-config(), + ) +); + +@include mat.dialog-theme($theme); +@include mat.button-theme($theme); diff --git a/apps/performance/scroll-cd/src/test-setup.ts b/apps/rxjs/14-race-condition/src/test-setup.ts similarity index 100% rename from apps/performance/scroll-cd/src/test-setup.ts rename to apps/rxjs/14-race-condition/src/test-setup.ts diff --git a/apps/rxjs/race-condition/tsconfig.app.json b/apps/rxjs/14-race-condition/tsconfig.app.json similarity index 100% rename from apps/rxjs/race-condition/tsconfig.app.json rename to apps/rxjs/14-race-condition/tsconfig.app.json diff --git a/apps/testing/checkbox/tsconfig.editor.json b/apps/rxjs/14-race-condition/tsconfig.editor.json similarity index 100% rename from apps/testing/checkbox/tsconfig.editor.json rename to apps/rxjs/14-race-condition/tsconfig.editor.json diff --git a/apps/rxjs/14-race-condition/tsconfig.json b/apps/rxjs/14-race-condition/tsconfig.json new file mode 100644 index 000000000..8a0cb05fc --- /dev/null +++ b/apps/rxjs/14-race-condition/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + }, + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./cypress/tsconfig.base.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/rxjs/race-condition/tsconfig.spec.json b/apps/rxjs/14-race-condition/tsconfig.spec.json similarity index 100% rename from apps/rxjs/race-condition/tsconfig.spec.json rename to apps/rxjs/14-race-condition/tsconfig.spec.json diff --git a/apps/rxjs/catch-error/.eslintrc.json b/apps/rxjs/38-catch-error/.eslintrc.json similarity index 100% rename from apps/rxjs/catch-error/.eslintrc.json rename to apps/rxjs/38-catch-error/.eslintrc.json diff --git a/apps/rxjs/catch-error/README.md b/apps/rxjs/38-catch-error/README.md similarity index 100% rename from apps/rxjs/catch-error/README.md rename to apps/rxjs/38-catch-error/README.md diff --git a/apps/rxjs/38-catch-error/jest.config.ts b/apps/rxjs/38-catch-error/jest.config.ts new file mode 100644 index 000000000..52f04480f --- /dev/null +++ b/apps/rxjs/38-catch-error/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'rxjs-catch-error', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/rxjs/38-catch-error', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/rxjs/38-catch-error/project.json b/apps/rxjs/38-catch-error/project.json new file mode 100644 index 000000000..a655389f3 --- /dev/null +++ b/apps/rxjs/38-catch-error/project.json @@ -0,0 +1,82 @@ +{ + "name": "rxjs-catch-error", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/rxjs/38-catch-error/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/rxjs/38-catch-error", + "index": "apps/rxjs/38-catch-error/src/index.html", + "main": "apps/rxjs/38-catch-error/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/rxjs/38-catch-error/tsconfig.app.json", + "assets": [ + "apps/rxjs/38-catch-error/src/favicon.ico", + "apps/rxjs/38-catch-error/src/assets" + ], + "styles": ["apps/rxjs/38-catch-error/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "rxjs-catch-error:build:production" + }, + "development": { + "buildTarget": "rxjs-catch-error:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "rxjs-catch-error:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/rxjs/catch-error/src/app/app.component.css b/apps/rxjs/38-catch-error/src/app/app.component.css similarity index 100% rename from apps/rxjs/catch-error/src/app/app.component.css rename to apps/rxjs/38-catch-error/src/app/app.component.css diff --git a/apps/rxjs/catch-error/src/app/app.component.spec.ts b/apps/rxjs/38-catch-error/src/app/app.component.spec.ts similarity index 100% rename from apps/rxjs/catch-error/src/app/app.component.spec.ts rename to apps/rxjs/38-catch-error/src/app/app.component.spec.ts diff --git a/apps/rxjs/38-catch-error/src/app/app.component.ts b/apps/rxjs/38-catch-error/src/app/app.component.ts new file mode 100644 index 000000000..65e177567 --- /dev/null +++ b/apps/rxjs/38-catch-error/src/app/app.component.ts @@ -0,0 +1,60 @@ +import { CommonModule } from '@angular/common'; +import { HttpClient } from '@angular/common/http'; +import { Component, DestroyRef, OnInit, inject } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { FormsModule } from '@angular/forms'; +import { Subject, concatMap, map } from 'rxjs'; + +@Component({ + imports: [CommonModule, FormsModule], + selector: 'app-root', + template: ` +
+ + possible values: posts, comments, albums, photos, todos, users + +
+
+ + +
+
+ {{ response | json }} +
+ `, + styleUrls: ['./app.component.css'], +}) +export class AppComponent implements OnInit { + submit$ = new Subject(); + input = ''; + response: unknown; + + private destroyRef = inject(DestroyRef); + private http = inject(HttpClient); + + ngOnInit() { + this.submit$ + .pipe( + map(() => this.input), + concatMap((value) => + this.http.get(`https://jsonplaceholder.typicode.com/${value}/1`), + ), + takeUntilDestroyed(this.destroyRef), + ) + .subscribe({ + next: (value) => { + console.log(value); + this.response = value; + }, + error: (error) => { + console.log(error); + this.response = error; + }, + complete: () => console.log('done'), + }); + } +} diff --git a/apps/rxjs/38-catch-error/src/app/app.config.ts b/apps/rxjs/38-catch-error/src/app/app.config.ts new file mode 100644 index 000000000..1c0c9422f --- /dev/null +++ b/apps/rxjs/38-catch-error/src/app/app.config.ts @@ -0,0 +1,6 @@ +import { provideHttpClient } from '@angular/common/http'; +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [provideHttpClient()], +}; diff --git a/apps/testing/modal/src/assets/.gitkeep b/apps/rxjs/38-catch-error/src/assets/.gitkeep similarity index 100% rename from apps/testing/modal/src/assets/.gitkeep rename to apps/rxjs/38-catch-error/src/assets/.gitkeep diff --git a/apps/testing/table/src/favicon.ico b/apps/rxjs/38-catch-error/src/favicon.ico similarity index 100% rename from apps/testing/table/src/favicon.ico rename to apps/rxjs/38-catch-error/src/favicon.ico diff --git a/apps/rxjs/38-catch-error/src/index.html b/apps/rxjs/38-catch-error/src/index.html new file mode 100644 index 000000000..7a765faa1 --- /dev/null +++ b/apps/rxjs/38-catch-error/src/index.html @@ -0,0 +1,13 @@ + + + + + rxjs-catch-error + + + + + + + + diff --git a/apps/rxjs/38-catch-error/src/main.ts b/apps/rxjs/38-catch-error/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/rxjs/38-catch-error/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/rxjs/38-catch-error/src/styles.scss b/apps/rxjs/38-catch-error/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/rxjs/38-catch-error/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/testing/input-output/src/test-setup.ts b/apps/rxjs/38-catch-error/src/test-setup.ts similarity index 100% rename from apps/testing/input-output/src/test-setup.ts rename to apps/rxjs/38-catch-error/src/test-setup.ts diff --git a/apps/rxjs/38-catch-error/tailwind.config.js b/apps/rxjs/38-catch-error/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/rxjs/38-catch-error/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/rxjs/38-catch-error/tsconfig.app.json b/apps/rxjs/38-catch-error/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/rxjs/38-catch-error/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/testing/input-output/tsconfig.editor.json b/apps/rxjs/38-catch-error/tsconfig.editor.json similarity index 100% rename from apps/testing/input-output/tsconfig.editor.json rename to apps/rxjs/38-catch-error/tsconfig.editor.json diff --git a/apps/performance/scroll-cd/tsconfig.json b/apps/rxjs/38-catch-error/tsconfig.json similarity index 100% rename from apps/performance/scroll-cd/tsconfig.json rename to apps/rxjs/38-catch-error/tsconfig.json diff --git a/apps/angular/interop-rxjs-signal/tsconfig.spec.json b/apps/rxjs/38-catch-error/tsconfig.spec.json similarity index 100% rename from apps/angular/interop-rxjs-signal/tsconfig.spec.json rename to apps/rxjs/38-catch-error/tsconfig.spec.json diff --git a/apps/rxjs/49-hold-to-save-button/.eslintrc.json b/apps/rxjs/49-hold-to-save-button/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/rxjs/49-hold-to-save-button/README.md b/apps/rxjs/49-hold-to-save-button/README.md new file mode 100644 index 000000000..e0d4c012b --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/README.md @@ -0,0 +1,13 @@ +# Hold to send button + +> author: alcaidio + +### Run Application + +```bash +npx nx serve rxjs-hold-to-save-button +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/rxjs/49-hold-to-save-btn/). diff --git a/apps/rxjs/49-hold-to-save-button/jest.config.ts b/apps/rxjs/49-hold-to-save-button/jest.config.ts new file mode 100644 index 000000000..1071a5815 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'rxjs-hold-to-save-button', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/rxjs/49-hold-to-save-button', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/rxjs/49-hold-to-save-button/project.json b/apps/rxjs/49-hold-to-save-button/project.json new file mode 100644 index 000000000..7b34db2c9 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/project.json @@ -0,0 +1,80 @@ +{ + "name": "rxjs-hold-to-save-button", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/rxjs/49-hold-to-save-button/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/rxjs/49-hold-to-save-button", + "index": "apps/rxjs/49-hold-to-save-button/src/index.html", + "browser": "apps/rxjs/49-hold-to-save-button/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/rxjs/49-hold-to-save-button/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/rxjs/49-hold-to-save-button/src/favicon.ico", + "apps/rxjs/49-hold-to-save-button/src/assets" + ], + "styles": ["apps/rxjs/49-hold-to-save-button/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "rxjs-hold-to-save-button:build:production" + }, + "development": { + "buildTarget": "rxjs-hold-to-save-button:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "rxjs-hold-to-save-button:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/rxjs/49-hold-to-save-button/src/app/app.component.ts b/apps/rxjs/49-hold-to-save-button/src/app/app.component.ts new file mode 100644 index 000000000..8f0dbbc70 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/src/app/app.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + imports: [], + selector: 'app-root', + template: ` +
+
+ + + +
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent { + onSend() { + console.log('Save it!'); + } +} diff --git a/apps/rxjs/49-hold-to-save-button/src/app/app.config.ts b/apps/rxjs/49-hold-to-save-button/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/testing/nested/src/assets/.gitkeep b/apps/rxjs/49-hold-to-save-button/src/assets/.gitkeep similarity index 100% rename from apps/testing/nested/src/assets/.gitkeep rename to apps/rxjs/49-hold-to-save-button/src/assets/.gitkeep diff --git a/apps/testing/todos-list/src/favicon.ico b/apps/rxjs/49-hold-to-save-button/src/favicon.ico similarity index 100% rename from apps/testing/todos-list/src/favicon.ico rename to apps/rxjs/49-hold-to-save-button/src/favicon.ico diff --git a/apps/rxjs/49-hold-to-save-button/src/index.html b/apps/rxjs/49-hold-to-save-button/src/index.html new file mode 100644 index 000000000..3f8e222b1 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/src/index.html @@ -0,0 +1,13 @@ + + + + + rxjs-hold-to-save-button + + + + + + + + diff --git a/apps/rxjs/49-hold-to-save-button/src/main.ts b/apps/rxjs/49-hold-to-save-button/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/rxjs/49-hold-to-save-button/src/styles.scss b/apps/rxjs/49-hold-to-save-button/src/styles.scss new file mode 100644 index 000000000..c98dac907 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/src/styles.scss @@ -0,0 +1,14 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +progress { + @apply h-4 w-full rounded-full bg-gray-200; +} +progress::-webkit-progress-bar { + @apply rounded-full bg-gray-200; +} + +progress::-webkit-progress-value { + @apply rounded-full bg-indigo-600; +} diff --git a/apps/testing/modal/src/test-setup.ts b/apps/rxjs/49-hold-to-save-button/src/test-setup.ts similarity index 100% rename from apps/testing/modal/src/test-setup.ts rename to apps/rxjs/49-hold-to-save-button/src/test-setup.ts diff --git a/apps/rxjs/49-hold-to-save-button/tailwind.config.js b/apps/rxjs/49-hold-to-save-button/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/rxjs/49-hold-to-save-button/tsconfig.app.json b/apps/rxjs/49-hold-to-save-button/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/rxjs/49-hold-to-save-button/tsconfig.editor.json b/apps/rxjs/49-hold-to-save-button/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/rxjs/49-hold-to-save-button/tsconfig.json b/apps/rxjs/49-hold-to-save-button/tsconfig.json new file mode 100644 index 000000000..4383e7eb8 --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/rxjs/49-hold-to-save-button/tsconfig.spec.json b/apps/rxjs/49-hold-to-save-button/tsconfig.spec.json new file mode 100644 index 000000000..1a4817a7d --- /dev/null +++ b/apps/rxjs/49-hold-to-save-button/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node", "@testing-library/jest-dom"] + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/apps/rxjs/catch-error/jest.config.ts b/apps/rxjs/catch-error/jest.config.ts deleted file mode 100644 index f82342048..000000000 --- a/apps/rxjs/catch-error/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'rxjs-catch-error', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - coverageDirectory: '../../../coverage/apps/rxjs/catch-error', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/rxjs/catch-error/project.json b/apps/rxjs/catch-error/project.json deleted file mode 100644 index 491d00710..000000000 --- a/apps/rxjs/catch-error/project.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "name": "rxjs-catch-error", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/rxjs/catch-error/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/rxjs/catch-error", - "index": "apps/rxjs/catch-error/src/index.html", - "main": "apps/rxjs/catch-error/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/rxjs/catch-error/tsconfig.app.json", - "assets": [ - "apps/rxjs/catch-error/src/favicon.ico", - "apps/rxjs/catch-error/src/assets" - ], - "styles": ["apps/rxjs/catch-error/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "rxjs-catch-error:build:production" - }, - "development": { - "browserTarget": "rxjs-catch-error:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "rxjs-catch-error:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/rxjs/catch-error/**/*.ts", - "apps/rxjs/catch-error/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/rxjs/catch-error/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - } - } -} diff --git a/apps/rxjs/catch-error/src/app/app.component.ts b/apps/rxjs/catch-error/src/app/app.component.ts deleted file mode 100644 index 6974c93d8..000000000 --- a/apps/rxjs/catch-error/src/app/app.component.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Component, DestroyRef, inject } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { HttpClient } from '@angular/common/http'; -import { FormsModule } from '@angular/forms'; -import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { Subject, concatMap, map } from 'rxjs'; - -@Component({ - standalone: true, - imports: [CommonModule, FormsModule], - selector: 'app-root', - template: ` -
- possible values: posts, comments, albums, photos, todos, users -
-
- - -
-
- {{ response | json }} -
- `, - styleUrls: ['./app.component.css'], -}) -export class AppComponent { - submit$$ = new Subject(); - input = ''; - response: unknown; - private destroyRef = inject(DestroyRef); - constructor(private http: HttpClient) {} - ngOnInit() { - this.submit$$ - .pipe( - map(() => this.input), - concatMap((value) => - this.http.get(`https://jsonplaceholder.typicode.com/${value}/1`) - ), - takeUntilDestroyed(this.destroyRef) - ) - .subscribe({ - next: (value) => { - console.log(value); - this.response = value; - }, - error: (error) => { - console.log(error); - this.response = error; - }, - complete: () => console.log('done'), - }); - } -} diff --git a/apps/rxjs/catch-error/src/app/app.config.ts b/apps/rxjs/catch-error/src/app/app.config.ts deleted file mode 100644 index 610704b37..000000000 --- a/apps/rxjs/catch-error/src/app/app.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ApplicationConfig, importProvidersFrom } from '@angular/core'; -import { HttpClientModule } from '@angular/common/http'; - -export const appConfig: ApplicationConfig = { - providers: [importProvidersFrom(HttpClientModule)], -}; diff --git a/apps/rxjs/catch-error/src/index.html b/apps/rxjs/catch-error/src/index.html deleted file mode 100644 index 07c9d6692..000000000 --- a/apps/rxjs/catch-error/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - rxjs-catch-error - - - - - - - - diff --git a/apps/rxjs/catch-error/src/main.ts b/apps/rxjs/catch-error/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/rxjs/catch-error/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/rxjs/pipe-bug/README.md b/apps/rxjs/pipe-bug/README.md deleted file mode 100644 index d66511b9d..000000000 --- a/apps/rxjs/pipe-bug/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# High Order Operator Bug - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve rxjs-pipe-bug -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/rxjs/11-bug-chaining-operator/). diff --git a/apps/rxjs/pipe-bug/project.json b/apps/rxjs/pipe-bug/project.json deleted file mode 100644 index 116536506..000000000 --- a/apps/rxjs/pipe-bug/project.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "name": "rxjs-pipe-bug", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/rxjs/pipe-bug/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/rxjs/pipe-bug", - "index": "apps/rxjs/pipe-bug/src/index.html", - "main": "apps/rxjs/pipe-bug/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/rxjs/pipe-bug/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/rxjs/pipe-bug/src/favicon.ico", - "apps/rxjs/pipe-bug/src/assets" - ], - "styles": ["apps/rxjs/pipe-bug/src/styles.scss"], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "rxjs-pipe-bug:build:production" - }, - "development": { - "browserTarget": "rxjs-pipe-bug:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "rxjs-pipe-bug:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/rxjs/pipe-bug/**/*.ts", - "apps/rxjs/pipe-bug/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/rxjs/pipe-bug/src/app/app.component.ts b/apps/rxjs/pipe-bug/src/app/app.component.ts deleted file mode 100644 index b0c695162..000000000 --- a/apps/rxjs/pipe-bug/src/app/app.component.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable @angular-eslint/component-selector */ -import { AsyncPipe, NgFor } from '@angular/common'; -import { Component, inject, Input } from '@angular/core'; -import { BehaviorSubject, take } from 'rxjs'; -import { AppService } from './app.service'; -import { TopicType } from './localDB.service'; - -@Component({ - standalone: true, - selector: 'button-delete-topic', - imports: [AsyncPipe], - template: ` - -
{{ message$$ | async }}
- `, -}) -export class ButtonDeleteComponent { - @Input() topic!: TopicType; - - message$$ = new BehaviorSubject(''); - - private service = inject(AppService); - - deleteTopic() { - this.service - .deleteOldTopics(this.topic) - .pipe(take(1)) - .subscribe((result) => - this.message$$.next( - result - ? `All ${this.topic} have been deleted` - : `Error: deletion of some ${this.topic} failed` - ) - ); - } -} - -@Component({ - standalone: true, - imports: [AsyncPipe, NgFor, ButtonDeleteComponent], - selector: 'app-root', - template: ` -
- {{ item.id }} - {{ item.topic }} -
- - Delete Food - Delete Sport - Delete Book - `, -}) -export class AppComponent { - private service = inject(AppService); - - all$ = this.service.getAll$; -} diff --git a/apps/rxjs/pipe-bug/src/app/app.service.ts b/apps/rxjs/pipe-bug/src/app/app.service.ts deleted file mode 100644 index 09a9ed129..000000000 --- a/apps/rxjs/pipe-bug/src/app/app.service.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { merge, mergeMap, Observable, of, take } from 'rxjs'; -import { LocalDBService, TopicType } from './localDB.service'; - -@Injectable({ providedIn: 'root' }) -export class AppService { - private dbService = inject(LocalDBService); - - getAll$ = this.dbService.infos$; - - deleteOldTopics(type: TopicType): Observable { - return this.dbService.searchByType(type).pipe( - take(1), - mergeMap((topicToDelete) => - topicToDelete.length > 0 - ? topicToDelete - .map((t) => this.dbService.deleteOneTopic(t.id)) - .reduce((acc, curr) => merge(acc, curr), of(true)) - : of(true) - ) - ); - } -} diff --git a/apps/rxjs/pipe-bug/src/app/localDB.service.ts b/apps/rxjs/pipe-bug/src/app/localDB.service.ts deleted file mode 100644 index 88d1e1def..000000000 --- a/apps/rxjs/pipe-bug/src/app/localDB.service.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint-disable @typescript-eslint/member-ordering */ -import { randomError } from '@angular-challenges/shared/utils'; -import { Injectable } from '@angular/core'; -import { ComponentStore } from '@ngrx/component-store'; -import { of } from 'rxjs'; - -export type TopicType = 'food' | 'book' | 'sport'; - -interface Info { - id: number; - topic: TopicType; -} - -interface DBState { - infos: Info[]; -} - -const initialState: DBState = { - infos: [ - { id: 1, topic: 'book' }, - { id: 2, topic: 'book' }, - { id: 3, topic: 'book' }, - { id: 4, topic: 'book' }, - { id: 5, topic: 'food' }, - { id: 6, topic: 'food' }, - { id: 7, topic: 'book' }, - { id: 8, topic: 'book' }, - { id: 9, topic: 'book' }, - { id: 10, topic: 'sport' }, - ], -}; - -@Injectable({ providedIn: 'root' }) -export class LocalDBService extends ComponentStore { - constructor() { - super(initialState); - } - - infos$ = this.select((state) => state.infos); - - searchByType = (type: TopicType) => - this.select((state) => state.infos.filter((i) => i.topic === type)); - - deleteOne = this.updater( - (state, id: number): DBState => ({ - infos: state.infos.filter((i) => i.id !== id), - }) - ); - - deleteOneTopic = (id: number) => - randomError({ - success: () => { - this.deleteOne(id); - return of(true); - }, - error: () => of(false), - }); -} diff --git a/apps/rxjs/pipe-bug/src/index.html b/apps/rxjs/pipe-bug/src/index.html deleted file mode 100644 index caa71f313..000000000 --- a/apps/rxjs/pipe-bug/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - RxjsPipeBug - - - - - - - - diff --git a/apps/rxjs/race-condition/README.md b/apps/rxjs/race-condition/README.md deleted file mode 100644 index 1c6b710d4..000000000 --- a/apps/rxjs/race-condition/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Race Condition - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve rxjs-race-condition -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/rxjs/14-race-condition/). diff --git a/apps/rxjs/race-condition/cypress.config.ts b/apps/rxjs/race-condition/cypress.config.ts deleted file mode 100644 index 7287d91cd..000000000 --- a/apps/rxjs/race-condition/cypress.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'cypress'; -import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; - -export default defineConfig({ - component: nxComponentTestingPreset(__filename), -}); diff --git a/apps/rxjs/race-condition/cypress/support/component-index.html b/apps/rxjs/race-condition/cypress/support/component-index.html deleted file mode 100644 index 5ce08c7d6..000000000 --- a/apps/rxjs/race-condition/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - rxjs-race-condition Components App - - -
- - diff --git a/apps/rxjs/race-condition/cypress/support/component.ts b/apps/rxjs/race-condition/cypress/support/component.ts deleted file mode 100644 index e3684dbdc..000000000 --- a/apps/rxjs/race-condition/cypress/support/component.ts +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.ts using ES2015 syntax: -import './commands'; diff --git a/apps/rxjs/race-condition/jest.config.ts b/apps/rxjs/race-condition/jest.config.ts deleted file mode 100644 index 2e2e8920b..000000000 --- a/apps/rxjs/race-condition/jest.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'rxjs-race-condition', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../../coverage/apps/rxjs/race-condition', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/rxjs/race-condition/project.json b/apps/rxjs/race-condition/project.json deleted file mode 100644 index 24dc6241c..000000000 --- a/apps/rxjs/race-condition/project.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "name": "rxjs-race-condition", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/rxjs/race-condition/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/rxjs/race-condition", - "index": "apps/rxjs/race-condition/src/index.html", - "main": "apps/rxjs/race-condition/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/rxjs/race-condition/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/rxjs/race-condition/src/favicon.ico", - "apps/rxjs/race-condition/src/assets" - ], - "styles": ["apps/rxjs/race-condition/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "rxjs-race-condition:build:production" - }, - "development": { - "browserTarget": "rxjs-race-condition:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "rxjs-race-condition:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/rxjs/race-condition/**/*.ts", - "apps/rxjs/race-condition/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/rxjs/race-condition/jest.config.ts", - "passWithNoTests": true - } - }, - "component-test": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/rxjs/race-condition/cypress.config.ts", - "testingType": "component", - "skipServe": true, - "devServerTarget": "rxjs-race-condition:build" - } - } - }, - "tags": [] -} diff --git a/apps/rxjs/race-condition/src/app/app.component.ts b/apps/rxjs/race-condition/src/app/app.component.ts deleted file mode 100644 index 8b3a04ad5..000000000 --- a/apps/rxjs/race-condition/src/app/app.component.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { - ChangeDetectionStrategy, - Component, - inject, - OnInit, -} from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { take } from 'rxjs'; -import { TopicModalComponent } from './topic-dialog.component'; -import { TopicService, TopicType } from './topic.service'; - -@Component({ - standalone: true, - selector: 'app-root', - template: ` `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class AppComponent implements OnInit { - title = 'rxjs-race-condition'; - dialog = inject(MatDialog); - topicService = inject(TopicService); - topics: TopicType[] = []; - - ngOnInit(): void { - this.topicService - .fakeGetHttpTopic() - .pipe(take(1)) - .subscribe((topics) => (this.topics = topics)); - } - - openTopicModal() { - this.dialog.open(TopicModalComponent, { - data: { - topics: this.topics, - }, - }); - } -} diff --git a/apps/rxjs/race-condition/src/app/app.config.ts b/apps/rxjs/race-condition/src/app/app.config.ts deleted file mode 100644 index d580f0492..000000000 --- a/apps/rxjs/race-condition/src/app/app.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ApplicationConfig } from '@angular/core'; -import { importProvidersFrom } from '@angular/core'; -import { MatDialogModule } from '@angular/material/dialog'; -export const appConfig: ApplicationConfig = { - providers: [importProvidersFrom(MatDialogModule)], -}; diff --git a/apps/rxjs/race-condition/src/index.html b/apps/rxjs/race-condition/src/index.html deleted file mode 100644 index 416065387..000000000 --- a/apps/rxjs/race-condition/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - RxjsRaceCondition - - - - - - - - diff --git a/apps/rxjs/race-condition/src/main.ts b/apps/rxjs/race-condition/src/main.ts deleted file mode 100644 index ea9f26cc8..000000000 --- a/apps/rxjs/race-condition/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { appConfig } from './app/app.config'; - -import { bootstrapApplication } from '@angular/platform-browser'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/rxjs/race-condition/src/styles.scss b/apps/rxjs/race-condition/src/styles.scss deleted file mode 100644 index 5f2e97eb4..000000000 --- a/apps/rxjs/race-condition/src/styles.scss +++ /dev/null @@ -1,24 +0,0 @@ -/* You can add global styles to this file, and also import other style files */ - -@use '@angular/material' as mat; - -@include mat.core(); - -$theme-primary: mat.define-palette(mat.$indigo-palette); -$theme-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400); - -$theme-warn: mat.define-palette(mat.$red-palette); - -$theme: mat.define-light-theme( - ( - color: ( - primary: $theme-primary, - accent: $theme-accent, - warn: $theme-warn, - ), - typography: mat.define-typography-config(), - ) -); - -@include mat.dialog-theme($theme); -@include mat.button-theme($theme); diff --git a/apps/rxjs/race-condition/src/test-setup.ts b/apps/rxjs/race-condition/src/test-setup.ts deleted file mode 100644 index 1100b3e8a..000000000 --- a/apps/rxjs/race-condition/src/test-setup.ts +++ /dev/null @@ -1 +0,0 @@ -import 'jest-preset-angular/setup-jest'; diff --git a/apps/rxjs/race-condition/.eslintrc.json b/apps/signal/30-interop-rxjs-signal/.eslintrc.json similarity index 100% rename from apps/rxjs/race-condition/.eslintrc.json rename to apps/signal/30-interop-rxjs-signal/.eslintrc.json diff --git a/apps/signal/30-interop-rxjs-signal/README.md b/apps/signal/30-interop-rxjs-signal/README.md new file mode 100644 index 000000000..f726d1b0f --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/README.md @@ -0,0 +1,13 @@ +# Interoperability Rxjs/Signal + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve signal-interop-rxjs-signal +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/30-interop-rxjs-signal/). diff --git a/apps/signal/30-interop-rxjs-signal/jest.config.ts b/apps/signal/30-interop-rxjs-signal/jest.config.ts new file mode 100644 index 000000000..9f2001768 --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'signal-interop-rxjs-signal', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/signal/30-interop-rxjs-signal', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/signal/30-interop-rxjs-signal/project.json b/apps/signal/30-interop-rxjs-signal/project.json new file mode 100644 index 000000000..0407655ee --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/project.json @@ -0,0 +1,85 @@ +{ + "name": "signal-interop-rxjs-signal", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/signal/30-interop-rxjs-signal/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/signal/30-interop-rxjs-signal", + "index": "apps/signal/30-interop-rxjs-signal/src/index.html", + "main": "apps/signal/30-interop-rxjs-signal/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/signal/30-interop-rxjs-signal/tsconfig.app.json", + "assets": [ + "apps/signal/30-interop-rxjs-signal/src/favicon.ico", + "apps/signal/30-interop-rxjs-signal/src/assets" + ], + "styles": [ + "apps/signal/30-interop-rxjs-signal/src/styles.scss", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "signal-interop-rxjs-signal:build:production" + }, + "development": { + "buildTarget": "signal-interop-rxjs-signal:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "signal-interop-rxjs-signal:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/signal/30-interop-rxjs-signal/src/app/app.component.ts b/apps/signal/30-interop-rxjs-signal/src/app/app.component.ts new file mode 100644 index 000000000..54fa2b85d --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/src/app/app.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet], + selector: 'app-root', + template: ` + + `, + styles: [''], +}) +export class AppComponent {} diff --git a/apps/signal/30-interop-rxjs-signal/src/app/app.config.ts b/apps/signal/30-interop-rxjs-signal/src/app/app.config.ts new file mode 100644 index 000000000..2885bb0de --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/src/app/app.config.ts @@ -0,0 +1,29 @@ +import { provideHttpClient } from '@angular/common/http'; +import { ApplicationConfig } from '@angular/core'; +import { provideAnimations } from '@angular/platform-browser/animations'; +import { provideRouter, withComponentInputBinding } from '@angular/router'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideHttpClient(), + provideAnimations(), + provideRouter( + [ + { + path: '', + pathMatch: 'full', + loadComponent: () => import('./list/photos.component'), + }, + { + path: 'detail', + loadComponent: () => import('./detail/detail.component'), + }, + { + path: '**', + redirectTo: '', + }, + ], + withComponentInputBinding(), + ), + ], +}; diff --git a/apps/signal/30-interop-rxjs-signal/src/app/detail/detail.component.ts b/apps/signal/30-interop-rxjs-signal/src/app/detail/detail.component.ts new file mode 100644 index 000000000..070bf7d7c --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/src/app/detail/detail.component.ts @@ -0,0 +1,44 @@ +import { DatePipe } from '@angular/common'; +import { Component, Input as RouterInput } from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { Photo } from '../photo.model'; + +@Component({ + selector: 'app-photos', + imports: [DatePipe, RouterLink], + template: ` + {{ photo.title }} +

+ Title: + {{ photo.title }} +

+

+ Owner: + {{ photo.ownername }} +

+

+ Date: + {{ photo.datetaken | date }} +

+

+ Tags: + {{ photo.tags }} +

+ + + `, + host: { + class: 'p-5 block', + }, +}) +export default class DetailComponent { + @RouterInput({ + required: true, + transform: (value: string) => JSON.parse(decodeURIComponent(value)), + }) + photo!: Photo; +} diff --git a/apps/angular/interop-rxjs-signal/src/app/list/photos.component.ts b/apps/signal/30-interop-rxjs-signal/src/app/list/photos.component.ts similarity index 91% rename from apps/angular/interop-rxjs-signal/src/app/list/photos.component.ts rename to apps/signal/30-interop-rxjs-signal/src/app/list/photos.component.ts index b8705e313..f81361957 100644 --- a/apps/angular/interop-rxjs-signal/src/app/list/photos.component.ts +++ b/apps/signal/30-interop-rxjs-signal/src/app/list/photos.component.ts @@ -13,7 +13,6 @@ import { PhotoStore } from './photos.store'; @Component({ selector: 'app-photos', - standalone: true, imports: [ ReactiveFormsModule, MatFormFieldModule, @@ -25,7 +24,7 @@ import { PhotoStore } from './photos.store'; RouterLinkWithHref, ], template: ` -

Photos

+

Photos

Search @@ -33,23 +32,23 @@ import { PhotoStore } from './photos.store'; type="text" matInput [formControl]="search" - placeholder="write an article" /> + placeholder="find a photo" />
-
+
@@ -93,7 +92,7 @@ export default class PhotosComponent implements OnInit { this.search.setValue(search); this.formInit = true; } - }) + }), ); private formInit = false; @@ -104,8 +103,8 @@ export default class PhotosComponent implements OnInit { this.search.valueChanges.pipe( skipWhile(() => !this.formInit), debounceTime(300), - distinctUntilChanged() - ) + distinctUntilChanged(), + ), ); } diff --git a/apps/angular/interop-rxjs-signal/src/app/list/photos.store.ts b/apps/signal/30-interop-rxjs-signal/src/app/list/photos.store.ts similarity index 90% rename from apps/angular/interop-rxjs-signal/src/app/list/photos.store.ts rename to apps/signal/30-interop-rxjs-signal/src/app/list/photos.store.ts index 8f039c4e3..f1315e87e 100644 --- a/apps/angular/interop-rxjs-signal/src/app/list/photos.store.ts +++ b/apps/signal/30-interop-rxjs-signal/src/app/list/photos.store.ts @@ -1,10 +1,10 @@ -import { Injectable, inject } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { ComponentStore, OnStateInit, OnStoreInit, - tapResponse, } from '@ngrx/component-store'; +import { tapResponse } from '@ngrx/operators'; import { pipe } from 'rxjs'; import { filter, mergeMap, tap } from 'rxjs/operators'; import { Photo } from '../photo.model'; @@ -47,7 +47,7 @@ export class PhotoStore private readonly endOfPage$ = this.select( this.page$, this.pages$, - (page, pages) => page === pages + (page, pages) => page === pages, ); readonly vm$ = this.select( @@ -60,7 +60,7 @@ export class PhotoStore loading: this.loading$, error: this.error$, }, - { debounce: true } + { debounce: true }, ); ngrxOnStoreInit() { @@ -82,7 +82,7 @@ export class PhotoStore this.select({ search: this.search$, page: this.page$, - }) + }), ); } @@ -91,21 +91,21 @@ export class PhotoStore ...state, search, page: 1, - }) + }), ); readonly nextPage = this.updater( (state): PhotoState => ({ ...state, page: state.page + 1, - }) + }), ); readonly previousPage = this.updater( (state): PhotoState => ({ ...state, page: state.page - 1, - }) + }), ); readonly searchPhotos = this.effect<{ search: string; page: number }>( @@ -123,13 +123,13 @@ export class PhotoStore }); localStorage.setItem( PHOTO_STATE_KEY, - JSON.stringify({ search, page }) + JSON.stringify({ search, page }), ); }, - (error: unknown) => this.patchState({ error, loading: false }) - ) - ) - ) - ) + (error: unknown) => this.patchState({ error, loading: false }), + ), + ), + ), + ), ); } diff --git a/apps/signal/30-interop-rxjs-signal/src/app/photo.model.ts b/apps/signal/30-interop-rxjs-signal/src/app/photo.model.ts new file mode 100644 index 000000000..c3360fd7a --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/src/app/photo.model.ts @@ -0,0 +1,22 @@ +export interface Photo { + id: string; + owner: string; + secret: string; + server: string; + farm: number; + title: string; + ispublic: number; + isfriend: number; + isfamily: number; + datetaken: string; + datetakengranularity: number; + datetakenunknown: string; + ownername: string; + tags: string; + url_q: string; + height_q: number; + width_q: number; + url_m: string; + height_m: number; + width_m: number; +} diff --git a/apps/angular/interop-rxjs-signal/src/app/photos.service.ts b/apps/signal/30-interop-rxjs-signal/src/app/photos.service.ts similarity index 90% rename from apps/angular/interop-rxjs-signal/src/app/photos.service.ts rename to apps/signal/30-interop-rxjs-signal/src/app/photos.service.ts index a7999e672..c540118f6 100644 --- a/apps/angular/interop-rxjs-signal/src/app/photos.service.ts +++ b/apps/signal/30-interop-rxjs-signal/src/app/photos.service.ts @@ -5,9 +5,13 @@ import { Photo } from './photo.model'; export interface FlickrAPIResponse { photos: { + page: number; pages: number; + perpage: number; + total: number; photo: Photo[]; }; + stat: string; } @Injectable({ providedIn: 'root' }) @@ -16,7 +20,7 @@ export class PhotoService { public searchPublicPhotos( searchTerm: string, - page: number + page: number, ): Observable { return this.http.get( 'https://www.flickr.com/services/rest/', @@ -33,7 +37,7 @@ export class PhotoService { extras: 'tags,date_taken,owner_name,url_q,url_m', api_key: 'c3050d39a5bb308d9921bef0e15c437d', }, - } + }, ); } } diff --git a/apps/testing/router-outlet/src/assets/.gitkeep b/apps/signal/30-interop-rxjs-signal/src/assets/.gitkeep similarity index 100% rename from apps/testing/router-outlet/src/assets/.gitkeep rename to apps/signal/30-interop-rxjs-signal/src/assets/.gitkeep diff --git a/apps/typescript/overload/src/favicon.ico b/apps/signal/30-interop-rxjs-signal/src/favicon.ico similarity index 100% rename from apps/typescript/overload/src/favicon.ico rename to apps/signal/30-interop-rxjs-signal/src/favicon.ico diff --git a/apps/signal/30-interop-rxjs-signal/src/index.html b/apps/signal/30-interop-rxjs-signal/src/index.html new file mode 100644 index 000000000..c8a8e0de5 --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/src/index.html @@ -0,0 +1,13 @@ + + + + + signal-interop-rxjs-signal + + + + + + + + diff --git a/apps/signal/30-interop-rxjs-signal/src/main.ts b/apps/signal/30-interop-rxjs-signal/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/signal/30-interop-rxjs-signal/src/styles.scss b/apps/signal/30-interop-rxjs-signal/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/testing/nested/src/test-setup.ts b/apps/signal/30-interop-rxjs-signal/src/test-setup.ts similarity index 100% rename from apps/testing/nested/src/test-setup.ts rename to apps/signal/30-interop-rxjs-signal/src/test-setup.ts diff --git a/apps/signal/30-interop-rxjs-signal/tailwind.config.js b/apps/signal/30-interop-rxjs-signal/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/signal/30-interop-rxjs-signal/tsconfig.app.json b/apps/signal/30-interop-rxjs-signal/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/signal/30-interop-rxjs-signal/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/testing/modal/tsconfig.editor.json b/apps/signal/30-interop-rxjs-signal/tsconfig.editor.json similarity index 100% rename from apps/testing/modal/tsconfig.editor.json rename to apps/signal/30-interop-rxjs-signal/tsconfig.editor.json diff --git a/apps/rxjs/catch-error/tsconfig.json b/apps/signal/30-interop-rxjs-signal/tsconfig.json similarity index 100% rename from apps/rxjs/catch-error/tsconfig.json rename to apps/signal/30-interop-rxjs-signal/tsconfig.json diff --git a/apps/rxjs/catch-error/tsconfig.spec.json b/apps/signal/30-interop-rxjs-signal/tsconfig.spec.json similarity index 100% rename from apps/rxjs/catch-error/tsconfig.spec.json rename to apps/signal/30-interop-rxjs-signal/tsconfig.spec.json diff --git a/apps/signal/43-signal-input/.eslintrc.json b/apps/signal/43-signal-input/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/signal/43-signal-input/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/signal/43-signal-input/README.md b/apps/signal/43-signal-input/README.md new file mode 100644 index 000000000..d82216bfd --- /dev/null +++ b/apps/signal/43-signal-input/README.md @@ -0,0 +1,13 @@ +# Signal Input + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve signal-signal-input +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/signal/43-signal-input). diff --git a/apps/signal/43-signal-input/project.json b/apps/signal/43-signal-input/project.json new file mode 100644 index 000000000..674aed1a3 --- /dev/null +++ b/apps/signal/43-signal-input/project.json @@ -0,0 +1,69 @@ +{ + "name": "signal-signal-input", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/signal/43-signal-input/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/signal/43-signal-input", + "index": "apps/signal/43-signal-input/src/index.html", + "browser": "apps/signal/43-signal-input/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/signal/43-signal-input/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/signal/43-signal-input/src/favicon.ico", + "apps/signal/43-signal-input/src/assets" + ], + "styles": ["apps/signal/43-signal-input/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "signal-signal-input:build:production" + }, + "development": { + "buildTarget": "signal-signal-input:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "signal-signal-input:build" + } + } + } +} diff --git a/apps/signal/43-signal-input/src/app/app.component.ts b/apps/signal/43-signal-input/src/app/app.component.ts new file mode 100644 index 000000000..5c2deb684 --- /dev/null +++ b/apps/signal/43-signal-input/src/app/app.component.ts @@ -0,0 +1,43 @@ +import { Component } from '@angular/core'; +import { UserComponent } from './user.component'; + +@Component({ + imports: [UserComponent], + selector: 'app-root', + template: ` +
+
+ Name: + + @if (showUser && !name.value) { +
name required
+ } +
+
+ LastName: + +
+
+ Age: + +
+ +
+ @if (showUser && !!name.value) { + + } + `, + host: { + class: 'p-10 block flex flex-col gap-10', + }, +}) +export class AppComponent { + showUser = false; +} diff --git a/apps/signal/43-signal-input/src/app/app.config.ts b/apps/signal/43-signal-input/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/signal/43-signal-input/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/signal/43-signal-input/src/app/user.component.ts b/apps/signal/43-signal-input/src/app/user.component.ts new file mode 100644 index 000000000..908f952c3 --- /dev/null +++ b/apps/signal/43-signal-input/src/app/user.component.ts @@ -0,0 +1,40 @@ +import { TitleCasePipe } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, +} from '@angular/core'; + +type Category = 'Youth' | 'Junior' | 'Open' | 'Senior'; +const ageToCategory = (age: number): Category => { + if (age < 10) return 'Youth'; + else if (age < 18) return 'Junior'; + else if (age < 35) return 'Open'; + return 'Senior'; +}; + +@Component({ + selector: 'app-user', + imports: [TitleCasePipe], + template: ` + {{ fullName | titlecase }} plays tennis in the {{ category }} category!! + `, + host: { + class: 'text-xl text-green-800', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class UserComponent implements OnChanges { + @Input({ required: true }) name!: string; + @Input() lastName?: string; + @Input() age?: string; + + fullName = ''; + category: Category = 'Junior'; + + ngOnChanges(): void { + this.fullName = `${this.name} ${this.lastName ?? ''}`; + this.category = ageToCategory(Number(this.age) ?? 0); + } +} diff --git a/apps/testing/table/src/assets/.gitkeep b/apps/signal/43-signal-input/src/assets/.gitkeep similarity index 100% rename from apps/testing/table/src/assets/.gitkeep rename to apps/signal/43-signal-input/src/assets/.gitkeep diff --git a/apps/signal/43-signal-input/src/favicon.ico b/apps/signal/43-signal-input/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/signal/43-signal-input/src/favicon.ico differ diff --git a/apps/signal/43-signal-input/src/index.html b/apps/signal/43-signal-input/src/index.html new file mode 100644 index 000000000..642a346a4 --- /dev/null +++ b/apps/signal/43-signal-input/src/index.html @@ -0,0 +1,13 @@ + + + + + signal-signal-input + + + + + + + + diff --git a/apps/signal/43-signal-input/src/main.ts b/apps/signal/43-signal-input/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/signal/43-signal-input/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/signal/43-signal-input/src/styles.scss b/apps/signal/43-signal-input/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/signal/43-signal-input/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/signal/43-signal-input/tailwind.config.js b/apps/signal/43-signal-input/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/signal/43-signal-input/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/signal/43-signal-input/tsconfig.app.json b/apps/signal/43-signal-input/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/signal/43-signal-input/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/43-signal-input/tsconfig.editor.json b/apps/signal/43-signal-input/tsconfig.editor.json new file mode 100644 index 000000000..4ee639340 --- /dev/null +++ b/apps/signal/43-signal-input/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": [] + } +} diff --git a/apps/signal/43-signal-input/tsconfig.json b/apps/signal/43-signal-input/tsconfig.json new file mode 100644 index 000000000..b94f8837d --- /dev/null +++ b/apps/signal/43-signal-input/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/signal/50-bug-in-effect/.eslintrc.json b/apps/signal/50-bug-in-effect/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/signal/50-bug-in-effect/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/signal/50-bug-in-effect/README.md b/apps/signal/50-bug-in-effect/README.md new file mode 100644 index 000000000..9e55d151a --- /dev/null +++ b/apps/signal/50-bug-in-effect/README.md @@ -0,0 +1,13 @@ +# Bug in Effect ? + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve signal-bug-in-effect +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/50-bug-effect-signal/). diff --git a/apps/signal/50-bug-in-effect/project.json b/apps/signal/50-bug-in-effect/project.json new file mode 100644 index 000000000..12a9bb47a --- /dev/null +++ b/apps/signal/50-bug-in-effect/project.json @@ -0,0 +1,69 @@ +{ + "name": "signal-bug-in-effect", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/signal/50-bug-in-effect/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/signal/50-bug-in-effect", + "index": "apps/signal/50-bug-in-effect/src/index.html", + "browser": "apps/signal/50-bug-in-effect/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/signal/50-bug-in-effect/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/signal/50-bug-in-effect/src/favicon.ico", + "apps/signal/50-bug-in-effect/src/assets" + ], + "styles": ["apps/signal/50-bug-in-effect/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "signal-bug-in-effect:build:production" + }, + "development": { + "buildTarget": "signal-bug-in-effect:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "signal-bug-in-effect:build" + } + } + } +} diff --git a/apps/signal/50-bug-in-effect/src/app/app.component.ts b/apps/signal/50-bug-in-effect/src/app/app.component.ts new file mode 100644 index 000000000..ec6ba09b0 --- /dev/null +++ b/apps/signal/50-bug-in-effect/src/app/app.component.ts @@ -0,0 +1,52 @@ +import { + ChangeDetectionStrategy, + Component, + effect, + model, +} from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +@Component({ + imports: [FormsModule], + selector: 'app-root', + template: ` +
+

MacBook

+

1999,99 €

+
+ +
+

Extras:

+ +
+ + +500 GB drive-space +
+
+ + +4 GB RAM +
+
+ + Better GPU +
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent { + drive = model(false); + ram = model(false); + gpu = model(false); + + constructor() { + /* + Explain for your junior team mate why this bug occurs ... + */ + effect(() => { + if (this.drive() || this.ram() || this.gpu()) { + alert('Price increased!'); + } + }); + } +} diff --git a/apps/signal/50-bug-in-effect/src/app/app.config.ts b/apps/signal/50-bug-in-effect/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/signal/50-bug-in-effect/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/testing/todos-list/src/assets/.gitkeep b/apps/signal/50-bug-in-effect/src/assets/.gitkeep similarity index 100% rename from apps/testing/todos-list/src/assets/.gitkeep rename to apps/signal/50-bug-in-effect/src/assets/.gitkeep diff --git a/apps/signal/50-bug-in-effect/src/favicon.ico b/apps/signal/50-bug-in-effect/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/signal/50-bug-in-effect/src/favicon.ico differ diff --git a/apps/signal/50-bug-in-effect/src/index.html b/apps/signal/50-bug-in-effect/src/index.html new file mode 100644 index 000000000..e8f5b7364 --- /dev/null +++ b/apps/signal/50-bug-in-effect/src/index.html @@ -0,0 +1,13 @@ + + + + + signal-bug-in-effect + + + + + + + + diff --git a/apps/signal/50-bug-in-effect/src/main.ts b/apps/signal/50-bug-in-effect/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/signal/50-bug-in-effect/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/signal/50-bug-in-effect/src/styles.scss b/apps/signal/50-bug-in-effect/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/signal/50-bug-in-effect/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/signal/50-bug-in-effect/tailwind.config.js b/apps/signal/50-bug-in-effect/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/signal/50-bug-in-effect/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/signal/50-bug-in-effect/tsconfig.app.json b/apps/signal/50-bug-in-effect/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/signal/50-bug-in-effect/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/50-bug-in-effect/tsconfig.editor.json b/apps/signal/50-bug-in-effect/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/signal/50-bug-in-effect/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/50-bug-in-effect/tsconfig.json b/apps/signal/50-bug-in-effect/tsconfig.json new file mode 100644 index 000000000..3df17b921 --- /dev/null +++ b/apps/signal/50-bug-in-effect/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/signal/51-function-call-effect/.eslintrc.json b/apps/signal/51-function-call-effect/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/signal/51-function-call-effect/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/signal/51-function-call-effect/README.md b/apps/signal/51-function-call-effect/README.md new file mode 100644 index 000000000..6d4543361 --- /dev/null +++ b/apps/signal/51-function-call-effect/README.md @@ -0,0 +1,13 @@ +# Function call in effect + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve signal-function-call-effect +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/51-function-call-effect/). diff --git a/apps/signal/51-function-call-effect/project.json b/apps/signal/51-function-call-effect/project.json new file mode 100644 index 000000000..3b3a4f8ae --- /dev/null +++ b/apps/signal/51-function-call-effect/project.json @@ -0,0 +1,69 @@ +{ + "name": "signal-function-call-effect", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/signal/51-function-call-effect/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/signal/51-function-call-effect", + "index": "apps/signal/51-function-call-effect/src/index.html", + "browser": "apps/signal/51-function-call-effect/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/signal/51-function-call-effect/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/signal/51-function-call-effect/src/favicon.ico", + "apps/signal/51-function-call-effect/src/assets" + ], + "styles": ["apps/signal/51-function-call-effect/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "signal-function-call-effect:build:production" + }, + "development": { + "buildTarget": "signal-function-call-effect:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "signal-function-call-effect:build" + } + } + } +} diff --git a/apps/signal/51-function-call-effect/src/app/action.component.ts b/apps/signal/51-function-call-effect/src/app/action.component.ts new file mode 100644 index 000000000..22e0e7a4f --- /dev/null +++ b/apps/signal/51-function-call-effect/src/app/action.component.ts @@ -0,0 +1,44 @@ +import { + ChangeDetectionStrategy, + Component, + effect, + inject, + signal, +} from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { UserService } from './user.service'; + +@Component({ + imports: [FormsModule], + selector: 'app-actions', + template: ` +
+ + +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ActionsComponent { + private userService = inject(UserService); + protected action = signal(undefined); + + protected actions = ['Create', 'Read', 'Update', 'Delete']; + + constructor() { + effect(() => { + this.userService.log(this.action() ?? 'No action selected'); + }); + } +} diff --git a/apps/signal/51-function-call-effect/src/app/app.component.ts b/apps/signal/51-function-call-effect/src/app/app.component.ts new file mode 100644 index 000000000..5f9342eda --- /dev/null +++ b/apps/signal/51-function-call-effect/src/app/app.component.ts @@ -0,0 +1,33 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { ActionsComponent } from './action.component'; +import { UserService } from './user.service'; + +@Component({ + imports: [FormsModule, ActionsComponent], + selector: 'app-root', + template: ` + + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent { + protected userService = inject(UserService); + + protected users = ['Thomas', 'John', 'Alice', 'Bob', 'Charlie', 'David']; +} diff --git a/apps/signal/51-function-call-effect/src/app/app.config.ts b/apps/signal/51-function-call-effect/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/signal/51-function-call-effect/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/signal/51-function-call-effect/src/app/user.service.ts b/apps/signal/51-function-call-effect/src/app/user.service.ts new file mode 100644 index 000000000..b43756b9e --- /dev/null +++ b/apps/signal/51-function-call-effect/src/app/user.service.ts @@ -0,0 +1,10 @@ +import { Injectable, signal } from '@angular/core'; + +@Injectable({ providedIn: 'root' }) +export class UserService { + name = signal('Thomas'); + + log(message: string) { + console.log(`${this.name()}: ${message}`); + } +} diff --git a/apps/typescript/overload/src/assets/.gitkeep b/apps/signal/51-function-call-effect/src/assets/.gitkeep similarity index 100% rename from apps/typescript/overload/src/assets/.gitkeep rename to apps/signal/51-function-call-effect/src/assets/.gitkeep diff --git a/apps/signal/51-function-call-effect/src/favicon.ico b/apps/signal/51-function-call-effect/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/signal/51-function-call-effect/src/favicon.ico differ diff --git a/apps/signal/51-function-call-effect/src/index.html b/apps/signal/51-function-call-effect/src/index.html new file mode 100644 index 000000000..523bcaef2 --- /dev/null +++ b/apps/signal/51-function-call-effect/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-function-call-effect + + + + + + + + diff --git a/apps/signal/51-function-call-effect/src/main.ts b/apps/signal/51-function-call-effect/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/signal/51-function-call-effect/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/signal/51-function-call-effect/src/styles.scss b/apps/signal/51-function-call-effect/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/signal/51-function-call-effect/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/signal/51-function-call-effect/tailwind.config.js b/apps/signal/51-function-call-effect/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/signal/51-function-call-effect/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/signal/51-function-call-effect/tsconfig.app.json b/apps/signal/51-function-call-effect/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/signal/51-function-call-effect/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/51-function-call-effect/tsconfig.editor.json b/apps/signal/51-function-call-effect/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/signal/51-function-call-effect/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/51-function-call-effect/tsconfig.json b/apps/signal/51-function-call-effect/tsconfig.json new file mode 100644 index 000000000..3df17b921 --- /dev/null +++ b/apps/signal/51-function-call-effect/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/signal/53-big-signal-performance/.eslintrc.json b/apps/signal/53-big-signal-performance/.eslintrc.json new file mode 100644 index 000000000..d3cd7997a --- /dev/null +++ b/apps/signal/53-big-signal-performance/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": {} + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/signal/53-big-signal-performance/README.md b/apps/signal/53-big-signal-performance/README.md new file mode 100644 index 000000000..2b1b56672 --- /dev/null +++ b/apps/signal/53-big-signal-performance/README.md @@ -0,0 +1,13 @@ +# Big Signal Performance + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve signal-big-signal-performance +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/signal/52-big-signal-performance/). diff --git a/apps/signal/53-big-signal-performance/project.json b/apps/signal/53-big-signal-performance/project.json new file mode 100644 index 000000000..88363564f --- /dev/null +++ b/apps/signal/53-big-signal-performance/project.json @@ -0,0 +1,69 @@ +{ + "name": "signal-big-signal-performance", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/signal/53-big-signal-performance/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/signal/53-big-signal-performance", + "index": "apps/signal/53-big-signal-performance/src/index.html", + "browser": "apps/signal/53-big-signal-performance/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/signal/53-big-signal-performance/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/signal/53-big-signal-performance/src/favicon.ico", + "apps/signal/53-big-signal-performance/src/assets" + ], + "styles": ["apps/signal/53-big-signal-performance/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "signal-big-signal-performance:build:production" + }, + "development": { + "buildTarget": "signal-big-signal-performance:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "signal-big-signal-performance:build" + } + } + } +} diff --git a/apps/signal/53-big-signal-performance/src/app/address.component.ts b/apps/signal/53-big-signal-performance/src/app/address.component.ts new file mode 100644 index 000000000..f894d697e --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/app/address.component.ts @@ -0,0 +1,20 @@ +import { CDFlashingDirective } from '@angular-challenges/shared/directives'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { UserStore } from './user.service'; + +@Component({ + selector: 'address-user', + template: ` +
+ Address: +
Street: {{ userService.user().address.street }}
+
ZipCode: {{ userService.user().address.zipCode }}
+
City: {{ userService.user().address.city }}
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [CDFlashingDirective], +}) +export class AddressComponent { + userService = inject(UserStore); +} diff --git a/apps/signal/53-big-signal-performance/src/app/app.component.ts b/apps/signal/53-big-signal-performance/src/app/app.component.ts new file mode 100644 index 000000000..bf15a5dc2 --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/app/app.component.ts @@ -0,0 +1,26 @@ +import { Component } from '@angular/core'; +import { AddressComponent } from './address.component'; +import { JobComponent } from './job.component'; +import { NameComponent } from './name.component'; +import { NoteComponent } from './note.component'; +import { UserFormComponent } from './user-form.component'; + +@Component({ + selector: 'app-root', + template: ` + + + + + + `, + styles: [''], + imports: [ + JobComponent, + NameComponent, + AddressComponent, + NoteComponent, + UserFormComponent, + ], +}) +export class AppComponent {} diff --git a/apps/signal/53-big-signal-performance/src/app/app.config.ts b/apps/signal/53-big-signal-performance/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/signal/53-big-signal-performance/src/app/job.component.ts b/apps/signal/53-big-signal-performance/src/app/job.component.ts new file mode 100644 index 000000000..d3186fc9f --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/app/job.component.ts @@ -0,0 +1,19 @@ +import { CDFlashingDirective } from '@angular-challenges/shared/directives'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { UserStore } from './user.service'; + +@Component({ + selector: 'job', + template: ` +
+ Job: +
title: {{ userService.user().title }}
+
salary: {{ userService.user().salary }}
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [CDFlashingDirective], +}) +export class JobComponent { + userService = inject(UserStore); +} diff --git a/apps/signal/53-big-signal-performance/src/app/name.component.ts b/apps/signal/53-big-signal-performance/src/app/name.component.ts new file mode 100644 index 000000000..f93b5675a --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/app/name.component.ts @@ -0,0 +1,17 @@ +import { CDFlashingDirective } from '@angular-challenges/shared/directives'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { UserStore } from './user.service'; + +@Component({ + selector: 'name', + template: ` +
+ Name: {{ userService.user().name }} +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [CDFlashingDirective], +}) +export class NameComponent { + userService = inject(UserStore); +} diff --git a/apps/signal/53-big-signal-performance/src/app/note.component.ts b/apps/signal/53-big-signal-performance/src/app/note.component.ts new file mode 100644 index 000000000..dd0033962 --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/app/note.component.ts @@ -0,0 +1,17 @@ +import { CDFlashingDirective } from '@angular-challenges/shared/directives'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { UserStore } from './user.service'; + +@Component({ + selector: 'note', + template: ` +
+ Note: {{ userService.user().note }} +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [CDFlashingDirective], +}) +export class NoteComponent { + userService = inject(UserStore); +} diff --git a/apps/signal/53-big-signal-performance/src/app/user-form.component.ts b/apps/signal/53-big-signal-performance/src/app/user-form.component.ts new file mode 100644 index 000000000..d0f2164ce --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/app/user-form.component.ts @@ -0,0 +1,99 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { UserStore } from './user.service'; + +@Component({ + selector: 'user-form', + imports: [ReactiveFormsModule], + template: ` +
+
+ Name: + +
+
+ Address: +
+ street: + +
+
+ zipCode: + +
+
+ city: + +
+
+
+ note: + +
+
+ title: + +
+
+ salary: + +
+ +
+ `, + host: { + class: 'block border border-gray-500 p-4 pt-10 m-4', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class UserFormComponent { + userStore = inject(UserStore); + + form = new FormGroup({ + name: new FormControl(this.userStore.user().name, { nonNullable: true }), + street: new FormControl(this.userStore.user().address.street, { + nonNullable: true, + }), + zipCode: new FormControl(this.userStore.user().address.zipCode, { + nonNullable: true, + }), + city: new FormControl(this.userStore.user().address.city, { + nonNullable: true, + }), + note: new FormControl(this.userStore.user().note, { nonNullable: true }), + title: new FormControl(this.userStore.user().title, { nonNullable: true }), + salary: new FormControl(this.userStore.user().salary, { + nonNullable: true, + }), + }); + + submit() { + this.userStore.user.update((u) => ({ + ...u, + name: this.form.getRawValue().name, + address: { + ...u.address, + street: this.form.getRawValue().street, + zipCode: this.form.getRawValue().zipCode, + city: this.form.getRawValue().city, + }, + note: this.form.getRawValue().note, + title: this.form.getRawValue().title, + salary: this.form.getRawValue().salary, + })); + } +} diff --git a/apps/signal/53-big-signal-performance/src/app/user.service.ts b/apps/signal/53-big-signal-performance/src/app/user.service.ts new file mode 100644 index 000000000..4b3b7c512 --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/app/user.service.ts @@ -0,0 +1,16 @@ +import { Injectable, signal } from '@angular/core'; + +@Injectable({ providedIn: 'root' }) +export class UserStore { + user = signal({ + name: 'Bob', + address: { + street: '', + zipCode: '', + city: '', + }, + note: '', + title: '', + salary: 0, + }); +} diff --git a/NX b/apps/signal/53-big-signal-performance/src/assets/.gitkeep similarity index 100% rename from NX rename to apps/signal/53-big-signal-performance/src/assets/.gitkeep diff --git a/apps/signal/53-big-signal-performance/src/favicon.ico b/apps/signal/53-big-signal-performance/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/signal/53-big-signal-performance/src/favicon.ico differ diff --git a/apps/signal/53-big-signal-performance/src/index.html b/apps/signal/53-big-signal-performance/src/index.html new file mode 100644 index 000000000..3f038cc7a --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/index.html @@ -0,0 +1,13 @@ + + + + + signal-big-signal-performance + + + + + + + + diff --git a/apps/signal/53-big-signal-performance/src/main.ts b/apps/signal/53-big-signal-performance/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/signal/53-big-signal-performance/src/styles.scss b/apps/signal/53-big-signal-performance/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/signal/53-big-signal-performance/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/signal/53-big-signal-performance/tailwind.config.js b/apps/signal/53-big-signal-performance/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/signal/53-big-signal-performance/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/signal/53-big-signal-performance/tsconfig.app.json b/apps/signal/53-big-signal-performance/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/signal/53-big-signal-performance/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/53-big-signal-performance/tsconfig.editor.json b/apps/signal/53-big-signal-performance/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/signal/53-big-signal-performance/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/53-big-signal-performance/tsconfig.json b/apps/signal/53-big-signal-performance/tsconfig.json new file mode 100644 index 000000000..3df17b921 --- /dev/null +++ b/apps/signal/53-big-signal-performance/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/signal/54-pipe-observable-to-signal/.eslintrc.json b/apps/signal/54-pipe-observable-to-signal/.eslintrc.json new file mode 100644 index 000000000..d3cd7997a --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": {} + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/signal/54-pipe-observable-to-signal/README.md b/apps/signal/54-pipe-observable-to-signal/README.md new file mode 100644 index 000000000..495cd3aa9 --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/README.md @@ -0,0 +1,13 @@ +# Pipe Observable to Signal + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve signal-pipe-observable-to-signal +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/signal/54-pipe-observable-to-signal/). diff --git a/apps/signal/54-pipe-observable-to-signal/project.json b/apps/signal/54-pipe-observable-to-signal/project.json new file mode 100644 index 000000000..47ab2b9ae --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/project.json @@ -0,0 +1,69 @@ +{ + "name": "signal-pipe-observable-to-signal", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/signal/54-pipe-observable-to-signal/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/signal/54-pipe-observable-to-signal", + "index": "apps/signal/54-pipe-observable-to-signal/src/index.html", + "browser": "apps/signal/54-pipe-observable-to-signal/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/signal/54-pipe-observable-to-signal/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/signal/54-pipe-observable-to-signal/src/favicon.ico", + "apps/signal/54-pipe-observable-to-signal/src/assets" + ], + "styles": ["apps/signal/54-pipe-observable-to-signal/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "signal-pipe-observable-to-signal:build:production" + }, + "development": { + "buildTarget": "signal-pipe-observable-to-signal:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "signal-pipe-observable-to-signal:build" + } + } + } +} diff --git a/apps/signal/54-pipe-observable-to-signal/src/app/app.component.ts b/apps/signal/54-pipe-observable-to-signal/src/app/app.component.ts new file mode 100644 index 000000000..72fe7106e --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/src/app/app.component.ts @@ -0,0 +1,28 @@ +import { TableComponent } from '@angular-challenges/shared/ui'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ProductRowComponent } from './product-row.component'; +import { products } from './product.model'; + +@Component({ + imports: [TableComponent, ProductRowComponent], + selector: 'app-root', + template: ` + + + + @for (col of displayedColumns; track col) { + + } + + + + + +
{{ col }}
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent { + products = products; + displayedColumns = ['name', 'priceA', 'priceB', 'priceC']; +} diff --git a/apps/signal/54-pipe-observable-to-signal/src/app/currency.pipe.ts b/apps/signal/54-pipe-observable-to-signal/src/app/currency.pipe.ts new file mode 100644 index 000000000..e3cc993f4 --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/src/app/currency.pipe.ts @@ -0,0 +1,15 @@ +import { inject, Pipe, PipeTransform } from '@angular/core'; +import { map, Observable } from 'rxjs'; +import { CurrencyService } from './currency.service'; + +@Pipe({ + name: 'currency', + standalone: true, +}) +export class CurrencyPipe implements PipeTransform { + currencyService = inject(CurrencyService); + + transform(price: number): Observable { + return this.currencyService.symbol$.pipe(map((s) => `${price}${s}`)); + } +} diff --git a/apps/signal/54-pipe-observable-to-signal/src/app/currency.service.ts b/apps/signal/54-pipe-observable-to-signal/src/app/currency.service.ts new file mode 100644 index 000000000..8ddf570bf --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/src/app/currency.service.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, map } from 'rxjs'; + +export interface Currency { + name: string; + code: string; + symbol: string; +} + +export const currency: Currency[] = [ + { name: 'Euro', code: 'EUR', symbol: '€' }, + { name: 'Dollar US', code: 'USD', symbol: 'US$' }, + { name: 'Dollar Australian', code: 'AUD', symbol: 'AU$' }, + { name: 'Pound Sterling', code: 'GBP', symbol: '£' }, + { name: 'Dollar Canadian', code: 'CAD', symbol: 'CAD' }, +]; + +@Injectable() +export class CurrencyService { + private code = new BehaviorSubject('EUR'); + + readonly code$ = this.code.asObservable(); + readonly symbol$ = this.code$.pipe( + map((code) => currency.find((c) => c.code === code)?.symbol ?? code), + ); + + public updateCode(code: string) { + this.code.next(code); + } +} diff --git a/apps/signal/54-pipe-observable-to-signal/src/app/product-row.component.ts b/apps/signal/54-pipe-observable-to-signal/src/app/product-row.component.ts new file mode 100644 index 000000000..7cb3d4e03 --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/src/app/product-row.component.ts @@ -0,0 +1,33 @@ +import { AsyncPipe } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + inject, + Input, +} from '@angular/core'; +import { CurrencyPipe } from './currency.pipe'; +import { CurrencyService } from './currency.service'; +import { Product } from './product.model'; + +@Component({ + selector: 'tr[product-row]', + template: ` + {{ productInfo.name }} + {{ productInfo.priceA | currency | async }} + {{ productInfo.priceB | currency | async }} + {{ productInfo.priceC | currency | async }} + `, + imports: [AsyncPipe, CurrencyPipe], + providers: [CurrencyService], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ProductRowComponent { + protected productInfo!: Product; + + @Input({ required: true }) set product(product: Product) { + this.currencyService.updateCode(product.currencyCode); + this.productInfo = product; + } + + currencyService = inject(CurrencyService); +} diff --git a/apps/signal/54-pipe-observable-to-signal/src/app/product.model.ts b/apps/signal/54-pipe-observable-to-signal/src/app/product.model.ts new file mode 100644 index 000000000..174e7dc77 --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/src/app/product.model.ts @@ -0,0 +1,55 @@ +export interface Product { + name: string; + priceA: number; + priceB: number; + priceC: number; + currencyCode: string; +} + +export const products: Product[] = [ + { + name: 'bike', + priceA: 1000, + priceB: 2000, + priceC: 2200, + currencyCode: 'USD', + }, + { name: 'tent', priceA: 112, priceB: 120, priceC: 41, currencyCode: 'EUR' }, + { + name: 'sofa', + priceA: 500, + priceB: 422, + priceC: 5000, + currencyCode: 'EUR', + }, + { + name: 'watch', + priceA: 50, + priceB: 130, + priceC: 150, + currencyCode: 'AUD', + }, + { + name: 'computer', + priceA: 1000, + priceB: 2200, + priceC: 3500, + currencyCode: 'GBP', + }, + { name: 'mug', priceA: 10, priceB: 15, priceC: 20, currencyCode: 'EUR' }, + { + name: 'headset', + priceA: 100, + priceB: 150, + priceC: 220, + currencyCode: 'CAD', + }, + { name: 'cable', priceA: 5, priceB: 10, priceC: 15, currencyCode: 'EUR' }, + { + name: 'table', + priceA: 100, + priceB: 20, + priceC: 500, + currencyCode: 'EUR', + }, +]; diff --git a/apps/ngrx/effect-selector/src/styles.scss b/apps/signal/54-pipe-observable-to-signal/src/assets/.gitkeep similarity index 100% rename from apps/ngrx/effect-selector/src/styles.scss rename to apps/signal/54-pipe-observable-to-signal/src/assets/.gitkeep diff --git a/apps/signal/54-pipe-observable-to-signal/src/favicon.ico b/apps/signal/54-pipe-observable-to-signal/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/signal/54-pipe-observable-to-signal/src/favicon.ico differ diff --git a/apps/signal/54-pipe-observable-to-signal/src/index.html b/apps/signal/54-pipe-observable-to-signal/src/index.html new file mode 100644 index 000000000..997f94663 --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/src/index.html @@ -0,0 +1,13 @@ + + + + + signal-pipe-observable-to-signal + + + + + + + + diff --git a/apps/typescript/overload/src/main.ts b/apps/signal/54-pipe-observable-to-signal/src/main.ts similarity index 100% rename from apps/typescript/overload/src/main.ts rename to apps/signal/54-pipe-observable-to-signal/src/main.ts diff --git a/apps/signal/54-pipe-observable-to-signal/src/styles.scss b/apps/signal/54-pipe-observable-to-signal/src/styles.scss new file mode 100644 index 000000000..552f97df9 --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/src/styles.scss @@ -0,0 +1,26 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ +table { + width: 100%; +} + +table thead > tr > th { + text-align: left; + padding: 1rem 1rem; + border: 1px solid #dee2e6; + border-width: 0 0 1px 0; + font-weight: 700; + color: #343a40; + background: #f8f9fa; + transition: box-shadow 0.2s; +} + +table tbody > tr > td { + text-align: left; + border: 1px solid #dee2e6; + border-width: 0 0 1px 0; + padding: 1rem 1rem; +} diff --git a/apps/signal/54-pipe-observable-to-signal/tailwind.config.js b/apps/signal/54-pipe-observable-to-signal/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/signal/54-pipe-observable-to-signal/tsconfig.app.json b/apps/signal/54-pipe-observable-to-signal/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/54-pipe-observable-to-signal/tsconfig.editor.json b/apps/signal/54-pipe-observable-to-signal/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/54-pipe-observable-to-signal/tsconfig.json b/apps/signal/54-pipe-observable-to-signal/tsconfig.json new file mode 100644 index 000000000..3df17b921 --- /dev/null +++ b/apps/signal/54-pipe-observable-to-signal/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/signal/56-forms-and-signal/.eslintrc.json b/apps/signal/56-forms-and-signal/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/signal/56-forms-and-signal/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/signal/56-forms-and-signal/README.md b/apps/signal/56-forms-and-signal/README.md new file mode 100644 index 000000000..ba5def1f0 --- /dev/null +++ b/apps/signal/56-forms-and-signal/README.md @@ -0,0 +1,13 @@ +# forms and signal + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve signal-forms-and-signal +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/signal/56-forms-and-signal/). diff --git a/apps/signal/56-forms-and-signal/project.json b/apps/signal/56-forms-and-signal/project.json new file mode 100644 index 000000000..d825b063c --- /dev/null +++ b/apps/signal/56-forms-and-signal/project.json @@ -0,0 +1,71 @@ +{ + "name": "signal-forms-and-signal", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/signal/56-forms-and-signal/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/signal/56-forms-and-signal", + "index": "apps/signal/56-forms-and-signal/src/index.html", + "browser": "apps/signal/56-forms-and-signal/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/signal/56-forms-and-signal/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "apps/signal/56-forms-and-signal/public" + } + ], + "styles": ["apps/signal/56-forms-and-signal/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "signal-forms-and-signal:build:production" + }, + "development": { + "buildTarget": "signal-forms-and-signal:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "signal-forms-and-signal:build" + } + } + } +} diff --git a/apps/signal/56-forms-and-signal/public/favicon.ico b/apps/signal/56-forms-and-signal/public/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/signal/56-forms-and-signal/public/favicon.ico differ diff --git a/apps/signal/56-forms-and-signal/src/app/app.component.ts b/apps/signal/56-forms-and-signal/src/app/app.component.ts new file mode 100644 index 000000000..d6690ea9a --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/app/app.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet], + selector: 'app-root', + template: ` +

Shop

+
+ +
+ `, + host: { + class: 'w-full flex justify-center flex-col items-center p-4 gap-10', + }, +}) +export class AppComponent {} diff --git a/apps/signal/56-forms-and-signal/src/app/app.config.ts b/apps/signal/56-forms-and-signal/src/app/app.config.ts new file mode 100644 index 000000000..9cebc385d --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/app/app.config.ts @@ -0,0 +1,10 @@ +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; +import { provideRouter, withComponentInputBinding } from '@angular/router'; +import { routes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(routes, withComponentInputBinding()), + ], +}; diff --git a/apps/signal/56-forms-and-signal/src/app/app.routes.ts b/apps/signal/56-forms-and-signal/src/app/app.routes.ts new file mode 100644 index 000000000..091c56d90 --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/app/app.routes.ts @@ -0,0 +1,29 @@ +import { Routes } from '@angular/router'; + +export const routes: Routes = [ + { + path: '', + redirectTo: 'dashboard', + pathMatch: 'full', + }, + { + path: 'dashboard', + loadComponent: () => import('./dashboard.component'), + }, + { + path: 'order', + loadComponent: () => import('./order.component'), + }, + { + path: 'checkout', + loadComponent: () => import('./checkout.component'), + }, + { + path: 'payment', + loadComponent: () => import('./payment.component'), + }, + { + path: '**', + redirectTo: 'dashboard', + }, +]; diff --git a/apps/signal/56-forms-and-signal/src/app/checkout.component.ts b/apps/signal/56-forms-and-signal/src/app/checkout.component.ts new file mode 100644 index 000000000..f9d831088 --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/app/checkout.component.ts @@ -0,0 +1,55 @@ +import { + ChangeDetectionStrategy, + Component, + computed, + input, +} from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { products } from './products'; + +@Component({ + selector: 'app-dashboard', + imports: [RouterLink], + template: ` +

Checkout

+ +
+
Your order:
+
+ {{ quantity() }} x {{ product()?.name }}: {{ product()?.price }}€ +
+
+ +
Billing Information
+
...
+
...
+
...
+
...
+
...
+ + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export default class DashboardComponent { + quantity = input(1); + productId = input('1'); + + product = computed(() => + products.find((product) => product.id === this.productId()), + ); + totalWithVAT = computed( + () => this.quantity() * (this.product()?.price ?? 0) * 1.21, + ); +} diff --git a/apps/signal/56-forms-and-signal/src/app/dashboard.component.ts b/apps/signal/56-forms-and-signal/src/app/dashboard.component.ts new file mode 100644 index 000000000..d96fedfd7 --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/app/dashboard.component.ts @@ -0,0 +1,30 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { products } from './products'; + +@Component({ + selector: 'app-dashboard', + imports: [RouterLink], + template: ` +

List of Products

+
    + @for (product of products; track product.id) { +
  • +
    + {{ product.name }} ({{ product.price }}€) + +
    +
  • + } +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export default class DashboardComponent { + products = products; +} diff --git a/apps/signal/56-forms-and-signal/src/app/order.component.ts b/apps/signal/56-forms-and-signal/src/app/order.component.ts new file mode 100644 index 000000000..2b03ba814 --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/app/order.component.ts @@ -0,0 +1,71 @@ +import { + ChangeDetectionStrategy, + Component, + computed, + input, +} from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { RouterLink } from '@angular/router'; +import { products } from './products'; + +@Component({ + selector: 'app-order', + imports: [RouterLink, ReactiveFormsModule], + template: ` +

Order

+
+
+ + +
+
+
SubTotal
+
{{ totalWithoutVat() }} €
+
+
+
VAT (21%)
+
{{ vat() }} €
+
+
+
Total
+
{{ total() }} €
+
+ +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export default class OrderComponent { + form = new FormGroup({ + quantity: new FormControl(1, { nonNullable: true }), + }); + + productId = input('1'); + price = computed( + () => products.find((p) => p.id === this.productId())?.price ?? 0, + ); + quantity = toSignal(this.form.controls.quantity.valueChanges, { + initialValue: this.form.getRawValue().quantity, + }); + totalWithoutVat = computed(() => Number(this.price()) * this.quantity()); + vat = computed(() => this.totalWithoutVat() * 0.21); + total = computed(() => this.totalWithoutVat() + this.vat()); +} diff --git a/apps/signal/56-forms-and-signal/src/app/payment.component.ts b/apps/signal/56-forms-and-signal/src/app/payment.component.ts new file mode 100644 index 000000000..800bd6f36 --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/app/payment.component.ts @@ -0,0 +1,18 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { RouterLink } from '@angular/router'; + +@Component({ + selector: 'app-dashboard', + imports: [RouterLink], + template: ` +

Payment Success

+ + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export default class DashboardComponent {} diff --git a/apps/signal/56-forms-and-signal/src/app/products.ts b/apps/signal/56-forms-and-signal/src/app/products.ts new file mode 100644 index 000000000..a893a5b54 --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/app/products.ts @@ -0,0 +1,17 @@ +export const products = [ + { + id: '1', + name: 'Computer', + price: 2000, + }, + { + id: '2', + name: 'Mouse', + price: 40, + }, + { + id: '3', + name: 'Keyboard', + price: 80, + }, +]; diff --git a/apps/signal/56-forms-and-signal/src/index.html b/apps/signal/56-forms-and-signal/src/index.html new file mode 100644 index 000000000..eca231086 --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/index.html @@ -0,0 +1,13 @@ + + + + + signal-forms-and-signal + + + + + + + + diff --git a/apps/signal/56-forms-and-signal/src/main.ts b/apps/signal/56-forms-and-signal/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/signal/56-forms-and-signal/src/styles.scss b/apps/signal/56-forms-and-signal/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/signal/56-forms-and-signal/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/signal/56-forms-and-signal/tailwind.config.js b/apps/signal/56-forms-and-signal/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/signal/56-forms-and-signal/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/signal/56-forms-and-signal/tsconfig.app.json b/apps/signal/56-forms-and-signal/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/signal/56-forms-and-signal/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/56-forms-and-signal/tsconfig.editor.json b/apps/signal/56-forms-and-signal/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/signal/56-forms-and-signal/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/signal/56-forms-and-signal/tsconfig.json b/apps/signal/56-forms-and-signal/tsconfig.json new file mode 100644 index 000000000..3df17b921 --- /dev/null +++ b/apps/signal/56-forms-and-signal/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/testing/checkbox/.eslintrc.json b/apps/testing/17-router/.eslintrc.json similarity index 100% rename from apps/testing/checkbox/.eslintrc.json rename to apps/testing/17-router/.eslintrc.json diff --git a/apps/testing/17-router/README.md b/apps/testing/17-router/README.md new file mode 100644 index 000000000..fe9a75448 --- /dev/null +++ b/apps/testing/17-router/README.md @@ -0,0 +1,13 @@ +# Router + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve testing-router +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/17-router/). diff --git a/apps/testing/17-router/cypress.config.ts b/apps/testing/17-router/cypress.config.ts new file mode 100644 index 000000000..1abef9c0c --- /dev/null +++ b/apps/testing/17-router/cypress.config.ts @@ -0,0 +1,6 @@ +import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; +import { defineConfig } from 'cypress'; + +export default defineConfig({ + component: nxComponentTestingPreset(__filename), +}); diff --git a/apps/testing/input-output/cypress/fixtures/example.json b/apps/testing/17-router/cypress/fixtures/example.json similarity index 100% rename from apps/testing/input-output/cypress/fixtures/example.json rename to apps/testing/17-router/cypress/fixtures/example.json diff --git a/apps/testing/17-router/cypress/support/commands.ts b/apps/testing/17-router/cypress/support/commands.ts new file mode 100644 index 000000000..b5d8a9582 --- /dev/null +++ b/apps/testing/17-router/cypress/support/commands.ts @@ -0,0 +1,25 @@ +/// +import { mount } from 'cypress/angular'; + +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + login(email: string, password: string): void; + mount: typeof mount; + } + } +} + +Cypress.Commands.add('mount', mount); diff --git a/apps/testing/17-router/cypress/support/component-index.html b/apps/testing/17-router/cypress/support/component-index.html new file mode 100644 index 000000000..208ea7126 --- /dev/null +++ b/apps/testing/17-router/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + router-testing Components App + + +
+ + diff --git a/apps/testing/17-router/cypress/support/component.ts b/apps/testing/17-router/cypress/support/component.ts new file mode 100644 index 000000000..e7c3e3cbc --- /dev/null +++ b/apps/testing/17-router/cypress/support/component.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your subscription files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.ts using ES2015 syntax: +import './commands'; diff --git a/apps/testing/input-output/cypress/tsconfig.json b/apps/testing/17-router/cypress/tsconfig.json similarity index 100% rename from apps/testing/input-output/cypress/tsconfig.json rename to apps/testing/17-router/cypress/tsconfig.json diff --git a/apps/testing/17-router/jest.config.ts b/apps/testing/17-router/jest.config.ts new file mode 100644 index 000000000..997c99f0e --- /dev/null +++ b/apps/testing/17-router/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'testing-router', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + globals: {}, + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/testing/17-router/project.json b/apps/testing/17-router/project.json new file mode 100644 index 000000000..44c7a2b18 --- /dev/null +++ b/apps/testing/17-router/project.json @@ -0,0 +1,96 @@ +{ + "name": "testing-router", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/testing/17-router/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/testing/17-router", + "index": "apps/testing/17-router/src/index.html", + "main": "apps/testing/17-router/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/testing/17-router/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/testing/17-router/src/favicon.ico", + "apps/testing/17-router/src/assets" + ], + "styles": ["apps/testing/17-router/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "testing-router:build:production" + }, + "development": { + "buildTarget": "testing-router:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "testing-router:build" + } + }, + "test": { + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}", + "{projectRoot}/coverage" + ], + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + }, + "component-test": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "apps/testing/17-router/cypress.config.ts", + "testingType": "component", + "skipServe": true, + "devServerTarget": "testing-router:build" + } + } + } +} diff --git a/apps/testing/router-outlet/src/app/app.component.cy.ts b/apps/testing/17-router/src/app/app.component.cy.ts similarity index 100% rename from apps/testing/router-outlet/src/app/app.component.cy.ts rename to apps/testing/17-router/src/app/app.component.cy.ts diff --git a/apps/testing/router-outlet/src/app/app.component.spec.ts b/apps/testing/17-router/src/app/app.component.spec.ts similarity index 100% rename from apps/testing/router-outlet/src/app/app.component.spec.ts rename to apps/testing/17-router/src/app/app.component.spec.ts diff --git a/apps/testing/17-router/src/app/app.component.ts b/apps/testing/17-router/src/app/app.component.ts new file mode 100644 index 000000000..cc6298f17 --- /dev/null +++ b/apps/testing/17-router/src/app/app.component.ts @@ -0,0 +1,41 @@ +import { Component } from '@angular/core'; +import { RouterLink, RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet, RouterLink], + selector: 'app-root', + styles: [ + ` + h1 { + margin-bottom: 0; + } + nav a { + padding: 1rem; + text-decoration: none; + margin-top: 10px; + display: inline-block; + background-color: #e8e8e8; + color: #3d3d3d; + border-radius: 4px; + margin-bottom: 10px; + } + nav a:hover { + color: white; + background-color: #42545c; + } + nav a.active { + background-color: black; + } + `, + ], + template: ` +

Library

+ + + + + `, +}) +export class AppComponent {} diff --git a/apps/testing/router-outlet/src/app/app.config.ts b/apps/testing/17-router/src/app/app.config.ts similarity index 100% rename from apps/testing/router-outlet/src/app/app.config.ts rename to apps/testing/17-router/src/app/app.config.ts diff --git a/apps/testing/router-outlet/src/app/app.routes.ts b/apps/testing/17-router/src/app/app.routes.ts similarity index 100% rename from apps/testing/router-outlet/src/app/app.routes.ts rename to apps/testing/17-router/src/app/app.routes.ts diff --git a/apps/testing/router-outlet/src/app/book.guard.ts b/apps/testing/17-router/src/app/book.guard.ts similarity index 86% rename from apps/testing/router-outlet/src/app/book.guard.ts rename to apps/testing/17-router/src/app/book.guard.ts index 3fe568e2a..1419047a2 100644 --- a/apps/testing/router-outlet/src/app/book.guard.ts +++ b/apps/testing/17-router/src/app/book.guard.ts @@ -4,7 +4,7 @@ import { availableBooks } from './book.model'; export const bookGuard = ( route: ActivatedRouteSnapshot, - router = inject(Router) + router = inject(Router), ) => { const searchParam = route.queryParams?.['book'].toLowerCase(); @@ -13,7 +13,7 @@ export const bookGuard = ( availableBooks.some( (b) => b.author.toLowerCase().includes(searchParam) || - b.name.toLowerCase().includes(searchParam) + b.name.toLowerCase().includes(searchParam), ); return isBookAvailable || router.parseUrl('no-result'); diff --git a/apps/testing/router-outlet/src/app/book.model.ts b/apps/testing/17-router/src/app/book.model.ts similarity index 100% rename from apps/testing/router-outlet/src/app/book.model.ts rename to apps/testing/17-router/src/app/book.model.ts diff --git a/apps/testing/router-outlet/src/app/no-book-search.component.ts b/apps/testing/17-router/src/app/no-book-search.component.ts similarity index 75% rename from apps/testing/router-outlet/src/app/no-book-search.component.ts rename to apps/testing/17-router/src/app/no-book-search.component.ts index ed41f5104..17d6b97d7 100644 --- a/apps/testing/router-outlet/src/app/no-book-search.component.ts +++ b/apps/testing/17-router/src/app/no-book-search.component.ts @@ -2,7 +2,9 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ standalone: true, - template: `
No book found for this search
`, + template: ` +
No book found for this search
+ `, changeDetection: ChangeDetectionStrategy.OnPush, }) export default class ShelfComponent {} diff --git a/apps/testing/router-outlet/src/app/search.component.ts b/apps/testing/17-router/src/app/search.component.ts similarity index 98% rename from apps/testing/router-outlet/src/app/search.component.ts rename to apps/testing/17-router/src/app/search.component.ts index b6f8666c3..9027c0cfe 100644 --- a/apps/testing/router-outlet/src/app/search.component.ts +++ b/apps/testing/17-router/src/app/search.component.ts @@ -5,7 +5,6 @@ import { RouterLink } from '@angular/router'; import { availableBooks } from './book.model'; @Component({ - standalone: true, imports: [ReactiveFormsModule, RouterLink, NgFor, NgIf], styles: [ ` diff --git a/apps/testing/router-outlet/src/app/shelf.component.ts b/apps/testing/17-router/src/app/shelf.component.ts similarity index 90% rename from apps/testing/router-outlet/src/app/shelf.component.ts rename to apps/testing/17-router/src/app/shelf.component.ts index bb4fd5dcd..63cddfab6 100644 --- a/apps/testing/router-outlet/src/app/shelf.component.ts +++ b/apps/testing/17-router/src/app/shelf.component.ts @@ -6,7 +6,6 @@ import { availableBooks } from './book.model'; @Component({ selector: 'app-shelf', - standalone: true, imports: [AsyncPipe, JsonPipe, NgFor], template: `
    @@ -25,8 +24,8 @@ export default class ShelfComponent { availableBooks.filter( (b) => b.name.toLowerCase().includes(param) || - b.author.toLowerCase().includes(param) - ) - ) + b.author.toLowerCase().includes(param), + ), + ), ); } diff --git a/apps/testing/17-router/src/assets/.gitkeep b/apps/testing/17-router/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/testing/17-router/src/favicon.ico b/apps/testing/17-router/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/testing/17-router/src/favicon.ico differ diff --git a/apps/testing/17-router/src/index.html b/apps/testing/17-router/src/index.html new file mode 100644 index 000000000..80ec9bf77 --- /dev/null +++ b/apps/testing/17-router/src/index.html @@ -0,0 +1,13 @@ + + + + + testing-router + + + + + + + + diff --git a/apps/testing/17-router/src/main.ts b/apps/testing/17-router/src/main.ts new file mode 100644 index 000000000..7961924bf --- /dev/null +++ b/apps/testing/17-router/src/main.ts @@ -0,0 +1,8 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; + +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/rxjs/pipe-bug/src/styles.scss b/apps/testing/17-router/src/styles.scss similarity index 100% rename from apps/rxjs/pipe-bug/src/styles.scss rename to apps/testing/17-router/src/styles.scss diff --git a/apps/testing/router-outlet/src/test-setup.ts b/apps/testing/17-router/src/test-setup.ts similarity index 100% rename from apps/testing/router-outlet/src/test-setup.ts rename to apps/testing/17-router/src/test-setup.ts diff --git a/apps/testing/input-output/tsconfig.app.json b/apps/testing/17-router/tsconfig.app.json similarity index 100% rename from apps/testing/input-output/tsconfig.app.json rename to apps/testing/17-router/tsconfig.app.json diff --git a/apps/testing/nested/tsconfig.editor.json b/apps/testing/17-router/tsconfig.editor.json similarity index 100% rename from apps/testing/nested/tsconfig.editor.json rename to apps/testing/17-router/tsconfig.editor.json diff --git a/apps/rxjs/race-condition/tsconfig.json b/apps/testing/17-router/tsconfig.json similarity index 100% rename from apps/rxjs/race-condition/tsconfig.json rename to apps/testing/17-router/tsconfig.json diff --git a/apps/testing/checkbox/tsconfig.spec.json b/apps/testing/17-router/tsconfig.spec.json similarity index 100% rename from apps/testing/checkbox/tsconfig.spec.json rename to apps/testing/17-router/tsconfig.spec.json diff --git a/apps/testing/nested/.eslintrc.json b/apps/testing/18-nested-components/.eslintrc.json similarity index 100% rename from apps/testing/nested/.eslintrc.json rename to apps/testing/18-nested-components/.eslintrc.json diff --git a/apps/testing/18-nested-components/README.md b/apps/testing/18-nested-components/README.md new file mode 100644 index 000000000..659b9e365 --- /dev/null +++ b/apps/testing/18-nested-components/README.md @@ -0,0 +1,13 @@ +# Nested Components + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve testing-nested-components +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/18-nested-comp/). diff --git a/apps/testing/18-nested-components/cypress.config.ts b/apps/testing/18-nested-components/cypress.config.ts new file mode 100644 index 000000000..1abef9c0c --- /dev/null +++ b/apps/testing/18-nested-components/cypress.config.ts @@ -0,0 +1,6 @@ +import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; +import { defineConfig } from 'cypress'; + +export default defineConfig({ + component: nxComponentTestingPreset(__filename), +}); diff --git a/apps/testing/modal/cypress/fixtures/example.json b/apps/testing/18-nested-components/cypress/fixtures/example.json similarity index 100% rename from apps/testing/modal/cypress/fixtures/example.json rename to apps/testing/18-nested-components/cypress/fixtures/example.json diff --git a/apps/testing/18-nested-components/cypress/support/commands.ts b/apps/testing/18-nested-components/cypress/support/commands.ts new file mode 100644 index 000000000..b5d8a9582 --- /dev/null +++ b/apps/testing/18-nested-components/cypress/support/commands.ts @@ -0,0 +1,25 @@ +/// +import { mount } from 'cypress/angular'; + +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + login(email: string, password: string): void; + mount: typeof mount; + } + } +} + +Cypress.Commands.add('mount', mount); diff --git a/apps/testing/18-nested-components/cypress/support/component-index.html b/apps/testing/18-nested-components/cypress/support/component-index.html new file mode 100644 index 000000000..f1b19ddbc --- /dev/null +++ b/apps/testing/18-nested-components/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + testing-nested Components App + + +
    + + diff --git a/apps/testing/18-nested-components/cypress/support/component.ts b/apps/testing/18-nested-components/cypress/support/component.ts new file mode 100644 index 000000000..e7c3e3cbc --- /dev/null +++ b/apps/testing/18-nested-components/cypress/support/component.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your subscription files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.ts using ES2015 syntax: +import './commands'; diff --git a/apps/testing/modal/cypress/tsconfig.json b/apps/testing/18-nested-components/cypress/tsconfig.json similarity index 100% rename from apps/testing/modal/cypress/tsconfig.json rename to apps/testing/18-nested-components/cypress/tsconfig.json diff --git a/apps/testing/18-nested-components/jest.config.ts b/apps/testing/18-nested-components/jest.config.ts new file mode 100644 index 000000000..c77df55f9 --- /dev/null +++ b/apps/testing/18-nested-components/jest.config.ts @@ -0,0 +1,21 @@ +/* eslint-disable */ +export default { + displayName: 'testing-nested-components', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/testing/18-nested-components/project.json b/apps/testing/18-nested-components/project.json new file mode 100644 index 000000000..3ea6467a4 --- /dev/null +++ b/apps/testing/18-nested-components/project.json @@ -0,0 +1,96 @@ +{ + "name": "testing-nested-components", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/testing/18-nested-components/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/testing/18-nested-components", + "index": "apps/testing/18-nested-components/src/index.html", + "main": "apps/testing/18-nested-components/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/testing/18-nested-components/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/testing/18-nested-components/src/favicon.ico", + "apps/testing/18-nested-components/src/assets" + ], + "styles": ["apps/testing/18-nested-components/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "testing-nested-components:build:production" + }, + "development": { + "buildTarget": "testing-nested-components:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "testing-nested-components:build" + } + }, + "test": { + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}", + "{projectRoot}/coverage" + ], + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + }, + "component-test": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "apps/testing/18-nested-components/cypress.config.ts", + "testingType": "component", + "skipServe": true, + "devServerTarget": "testing-nested-components:build" + } + } + } +} diff --git a/apps/testing/18-nested-components/src/app/app.component.ts b/apps/testing/18-nested-components/src/app/app.component.ts new file mode 100644 index 000000000..84b0df68a --- /dev/null +++ b/apps/testing/18-nested-components/src/app/app.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { ChildComponent } from './child.component'; + +@Component({ + imports: [ChildComponent], + selector: 'app-root', + template: ` + + `, +}) +export class AppComponent {} diff --git a/apps/testing/nested/src/app/child.component.cy.ts b/apps/testing/18-nested-components/src/app/child.component.cy.ts similarity index 100% rename from apps/testing/nested/src/app/child.component.cy.ts rename to apps/testing/18-nested-components/src/app/child.component.cy.ts diff --git a/apps/testing/nested/src/app/child.component.spec.ts b/apps/testing/18-nested-components/src/app/child.component.spec.ts similarity index 100% rename from apps/testing/nested/src/app/child.component.spec.ts rename to apps/testing/18-nested-components/src/app/child.component.spec.ts diff --git a/apps/testing/18-nested-components/src/app/child.component.ts b/apps/testing/18-nested-components/src/app/child.component.ts new file mode 100644 index 000000000..1aaca5117 --- /dev/null +++ b/apps/testing/18-nested-components/src/app/child.component.ts @@ -0,0 +1,92 @@ +import { NgIf } from '@angular/common'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + Input, + Output, + inject, +} from '@angular/core'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { HttpService } from './http.service'; + +@Component({ + selector: 'app-input', + imports: [ReactiveFormsModule], + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class InputComponent { + title = new FormControl('', { nonNullable: true }); +} + +@Component({ + selector: 'result', + standalone: true, + template: ` +

    Title is {{ title }}

    + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ResultComponent { + @Input() title = ''; +} + +@Component({ + selector: 'app-button', + standalone: true, + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ButtonComponent { + @Output() validate = new EventEmitter(); +} + +@Component({ + selector: 'app-error', + standalone: true, + template: ` +

    Title is required !!!

    + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ErrorComponent { + @Output() validate = new EventEmitter(); +} + +@Component({ + selector: 'app-child', + imports: [ + ResultComponent, + ButtonComponent, + InputComponent, + ErrorComponent, + NgIf, + ], + template: ` + + + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ChildComponent { + http = inject(HttpService); + + showError = false; + + submit(title: string) { + this.showError = false; + if (title === '') { + this.showError = true; + return; + } + + this.http.sendTitle(title); + } +} diff --git a/apps/testing/nested/src/app/http.service.ts b/apps/testing/18-nested-components/src/app/http.service.ts similarity index 100% rename from apps/testing/nested/src/app/http.service.ts rename to apps/testing/18-nested-components/src/app/http.service.ts diff --git a/apps/testing/18-nested-components/src/assets/.gitkeep b/apps/testing/18-nested-components/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/testing/18-nested-components/src/favicon.ico b/apps/testing/18-nested-components/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/testing/18-nested-components/src/favicon.ico differ diff --git a/apps/testing/18-nested-components/src/index.html b/apps/testing/18-nested-components/src/index.html new file mode 100644 index 000000000..5f7055208 --- /dev/null +++ b/apps/testing/18-nested-components/src/index.html @@ -0,0 +1,13 @@ + + + + + testing-nested-components + + + + + + + + diff --git a/apps/testing/18-nested-components/src/main.ts b/apps/testing/18-nested-components/src/main.ts new file mode 100644 index 000000000..31c5da482 --- /dev/null +++ b/apps/testing/18-nested-components/src/main.ts @@ -0,0 +1,4 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent).catch((err) => console.error(err)); diff --git a/apps/testing/input-output/src/styles.scss b/apps/testing/18-nested-components/src/styles.scss similarity index 100% rename from apps/testing/input-output/src/styles.scss rename to apps/testing/18-nested-components/src/styles.scss diff --git a/apps/testing/table/src/test-setup.ts b/apps/testing/18-nested-components/src/test-setup.ts similarity index 100% rename from apps/testing/table/src/test-setup.ts rename to apps/testing/18-nested-components/src/test-setup.ts diff --git a/apps/testing/modal/tsconfig.app.json b/apps/testing/18-nested-components/tsconfig.app.json similarity index 100% rename from apps/testing/modal/tsconfig.app.json rename to apps/testing/18-nested-components/tsconfig.app.json diff --git a/apps/testing/router-outlet/tsconfig.editor.json b/apps/testing/18-nested-components/tsconfig.editor.json similarity index 100% rename from apps/testing/router-outlet/tsconfig.editor.json rename to apps/testing/18-nested-components/tsconfig.editor.json diff --git a/apps/testing/input-output/tsconfig.json b/apps/testing/18-nested-components/tsconfig.json similarity index 100% rename from apps/testing/input-output/tsconfig.json rename to apps/testing/18-nested-components/tsconfig.json diff --git a/apps/testing/input-output/tsconfig.spec.json b/apps/testing/18-nested-components/tsconfig.spec.json similarity index 100% rename from apps/testing/input-output/tsconfig.spec.json rename to apps/testing/18-nested-components/tsconfig.spec.json diff --git a/apps/testing/create-harness/.eslintrc.json b/apps/testing/19-input-output/.eslintrc.json similarity index 100% rename from apps/testing/create-harness/.eslintrc.json rename to apps/testing/19-input-output/.eslintrc.json diff --git a/apps/testing/19-input-output/README.md b/apps/testing/19-input-output/README.md new file mode 100644 index 000000000..59b5fff5d --- /dev/null +++ b/apps/testing/19-input-output/README.md @@ -0,0 +1,13 @@ +# Input Output + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve testing-input-output +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/19-input-output/). diff --git a/apps/testing/19-input-output/cypress.config.ts b/apps/testing/19-input-output/cypress.config.ts new file mode 100644 index 000000000..1abef9c0c --- /dev/null +++ b/apps/testing/19-input-output/cypress.config.ts @@ -0,0 +1,6 @@ +import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; +import { defineConfig } from 'cypress'; + +export default defineConfig({ + component: nxComponentTestingPreset(__filename), +}); diff --git a/apps/testing/nested/cypress/fixtures/example.json b/apps/testing/19-input-output/cypress/fixtures/example.json similarity index 100% rename from apps/testing/nested/cypress/fixtures/example.json rename to apps/testing/19-input-output/cypress/fixtures/example.json diff --git a/apps/testing/19-input-output/cypress/support/commands.ts b/apps/testing/19-input-output/cypress/support/commands.ts new file mode 100644 index 000000000..b5d8a9582 --- /dev/null +++ b/apps/testing/19-input-output/cypress/support/commands.ts @@ -0,0 +1,25 @@ +/// +import { mount } from 'cypress/angular'; + +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + login(email: string, password: string): void; + mount: typeof mount; + } + } +} + +Cypress.Commands.add('mount', mount); diff --git a/apps/testing/19-input-output/cypress/support/component-index.html b/apps/testing/19-input-output/cypress/support/component-index.html new file mode 100644 index 000000000..57debcfad --- /dev/null +++ b/apps/testing/19-input-output/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + testing-input-output Components App + + +
    + + diff --git a/apps/testing/19-input-output/cypress/support/component.ts b/apps/testing/19-input-output/cypress/support/component.ts new file mode 100644 index 000000000..e7c3e3cbc --- /dev/null +++ b/apps/testing/19-input-output/cypress/support/component.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your subscription files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.ts using ES2015 syntax: +import './commands'; diff --git a/apps/testing/nested/cypress/tsconfig.json b/apps/testing/19-input-output/cypress/tsconfig.json similarity index 100% rename from apps/testing/nested/cypress/tsconfig.json rename to apps/testing/19-input-output/cypress/tsconfig.json diff --git a/apps/testing/input-output/jest.config.ts b/apps/testing/19-input-output/jest.config.ts similarity index 100% rename from apps/testing/input-output/jest.config.ts rename to apps/testing/19-input-output/jest.config.ts diff --git a/apps/testing/19-input-output/project.json b/apps/testing/19-input-output/project.json new file mode 100644 index 000000000..e143e2e02 --- /dev/null +++ b/apps/testing/19-input-output/project.json @@ -0,0 +1,96 @@ +{ + "name": "testing-input-output", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/testing/19-input-output/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/testing/19-input-output", + "index": "apps/testing/19-input-output/src/index.html", + "main": "apps/testing/19-input-output/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/testing/19-input-output/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/testing/19-input-output/src/favicon.ico", + "apps/testing/19-input-output/src/assets" + ], + "styles": ["apps/testing/19-input-output/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "testing-input-output:build:production" + }, + "development": { + "buildTarget": "testing-input-output:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "testing-input-output:build" + } + }, + "test": { + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}", + "{projectRoot}/coverage" + ], + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + }, + "component-test": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "apps/testing/19-input-output/cypress.config.ts", + "testingType": "component", + "skipServe": true, + "devServerTarget": "testing-input-output:build" + } + } + } +} diff --git a/apps/testing/19-input-output/src/app/app.component.ts b/apps/testing/19-input-output/src/app/app.component.ts new file mode 100644 index 000000000..7e9e0f78a --- /dev/null +++ b/apps/testing/19-input-output/src/app/app.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { CounterComponent } from './counter.component'; + +@Component({ + imports: [CounterComponent], + selector: 'app-root', + template: ` + + `, +}) +export class AppComponent { + log(counter: number) { + console.log('output log', counter); + } +} diff --git a/apps/testing/input-output/src/app/counter.component.cy.ts b/apps/testing/19-input-output/src/app/counter.component.cy.ts similarity index 100% rename from apps/testing/input-output/src/app/counter.component.cy.ts rename to apps/testing/19-input-output/src/app/counter.component.cy.ts diff --git a/apps/testing/input-output/src/app/counter.component.spec.ts b/apps/testing/19-input-output/src/app/counter.component.spec.ts similarity index 100% rename from apps/testing/input-output/src/app/counter.component.spec.ts rename to apps/testing/19-input-output/src/app/counter.component.spec.ts diff --git a/apps/testing/19-input-output/src/app/counter.component.ts b/apps/testing/19-input-output/src/app/counter.component.ts new file mode 100644 index 000000000..df1eed103 --- /dev/null +++ b/apps/testing/19-input-output/src/app/counter.component.ts @@ -0,0 +1,32 @@ +import { + ChangeDetectionStrategy, + Component, + input, + linkedSignal, + output, +} from '@angular/core'; + +@Component({ + selector: 'app-counter', + template: ` +

    Counter: {{ counter() }}

    + + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class CounterComponent { + initialValue = input.required(); + public counter = linkedSignal(() => this.initialValue()); + + send = output(); + + public increment = () => { + this.counter.set(this.counter() + 1); + }; + + public decrement = () => { + this.counter.set(this.counter() - 1); + }; +} diff --git a/apps/testing/19-input-output/src/assets/.gitkeep b/apps/testing/19-input-output/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/testing/19-input-output/src/favicon.ico b/apps/testing/19-input-output/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/testing/19-input-output/src/favicon.ico differ diff --git a/apps/testing/19-input-output/src/index.html b/apps/testing/19-input-output/src/index.html new file mode 100644 index 000000000..a5cd1c5da --- /dev/null +++ b/apps/testing/19-input-output/src/index.html @@ -0,0 +1,13 @@ + + + + + testing-input-ouput + + + + + + + + diff --git a/apps/testing/19-input-output/src/main.ts b/apps/testing/19-input-output/src/main.ts new file mode 100644 index 000000000..31c5da482 --- /dev/null +++ b/apps/testing/19-input-output/src/main.ts @@ -0,0 +1,4 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent).catch((err) => console.error(err)); diff --git a/apps/testing/nested/src/styles.scss b/apps/testing/19-input-output/src/styles.scss similarity index 100% rename from apps/testing/nested/src/styles.scss rename to apps/testing/19-input-output/src/styles.scss diff --git a/apps/testing/todos-list/src/test-setup.ts b/apps/testing/19-input-output/src/test-setup.ts similarity index 100% rename from apps/testing/todos-list/src/test-setup.ts rename to apps/testing/19-input-output/src/test-setup.ts diff --git a/apps/testing/nested/tsconfig.app.json b/apps/testing/19-input-output/tsconfig.app.json similarity index 100% rename from apps/testing/nested/tsconfig.app.json rename to apps/testing/19-input-output/tsconfig.app.json diff --git a/apps/testing/table/tsconfig.editor.json b/apps/testing/19-input-output/tsconfig.editor.json similarity index 100% rename from apps/testing/table/tsconfig.editor.json rename to apps/testing/19-input-output/tsconfig.editor.json diff --git a/apps/testing/modal/tsconfig.json b/apps/testing/19-input-output/tsconfig.json similarity index 100% rename from apps/testing/modal/tsconfig.json rename to apps/testing/19-input-output/tsconfig.json diff --git a/apps/testing/modal/tsconfig.spec.json b/apps/testing/19-input-output/tsconfig.spec.json similarity index 100% rename from apps/testing/modal/tsconfig.spec.json rename to apps/testing/19-input-output/tsconfig.spec.json diff --git a/apps/testing/harness/.eslintrc.json b/apps/testing/20-modal/.eslintrc.json similarity index 100% rename from apps/testing/harness/.eslintrc.json rename to apps/testing/20-modal/.eslintrc.json diff --git a/apps/testing/20-modal/README.md b/apps/testing/20-modal/README.md new file mode 100644 index 000000000..08737d5a0 --- /dev/null +++ b/apps/testing/20-modal/README.md @@ -0,0 +1,13 @@ +# Modal + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve testing-modal +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/20-modal/). diff --git a/apps/testing/20-modal/cypress.config.ts b/apps/testing/20-modal/cypress.config.ts new file mode 100644 index 000000000..1abef9c0c --- /dev/null +++ b/apps/testing/20-modal/cypress.config.ts @@ -0,0 +1,6 @@ +import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; +import { defineConfig } from 'cypress'; + +export default defineConfig({ + component: nxComponentTestingPreset(__filename), +}); diff --git a/apps/testing/router-outlet/cypress/fixtures/example.json b/apps/testing/20-modal/cypress/fixtures/example.json similarity index 100% rename from apps/testing/router-outlet/cypress/fixtures/example.json rename to apps/testing/20-modal/cypress/fixtures/example.json diff --git a/apps/testing/20-modal/cypress/support/commands.ts b/apps/testing/20-modal/cypress/support/commands.ts new file mode 100644 index 000000000..b5d8a9582 --- /dev/null +++ b/apps/testing/20-modal/cypress/support/commands.ts @@ -0,0 +1,25 @@ +/// +import { mount } from 'cypress/angular'; + +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + login(email: string, password: string): void; + mount: typeof mount; + } + } +} + +Cypress.Commands.add('mount', mount); diff --git a/apps/testing/20-modal/cypress/support/component-index.html b/apps/testing/20-modal/cypress/support/component-index.html new file mode 100644 index 000000000..7af656787 --- /dev/null +++ b/apps/testing/20-modal/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + testing-modal Components App + + +
    + + diff --git a/apps/testing/20-modal/cypress/support/component.ts b/apps/testing/20-modal/cypress/support/component.ts new file mode 100644 index 000000000..e7c3e3cbc --- /dev/null +++ b/apps/testing/20-modal/cypress/support/component.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your subscription files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.ts using ES2015 syntax: +import './commands'; diff --git a/apps/testing/router-outlet/cypress/tsconfig.json b/apps/testing/20-modal/cypress/tsconfig.json similarity index 100% rename from apps/testing/router-outlet/cypress/tsconfig.json rename to apps/testing/20-modal/cypress/tsconfig.json diff --git a/apps/testing/modal/jest.config.ts b/apps/testing/20-modal/jest.config.ts similarity index 100% rename from apps/testing/modal/jest.config.ts rename to apps/testing/20-modal/jest.config.ts diff --git a/apps/testing/20-modal/project.json b/apps/testing/20-modal/project.json new file mode 100644 index 000000000..28134614f --- /dev/null +++ b/apps/testing/20-modal/project.json @@ -0,0 +1,99 @@ +{ + "name": "testing-modal", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/testing/20-modal/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/testing/20-modal", + "index": "apps/testing/20-modal/src/index.html", + "main": "apps/testing/20-modal/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/testing/20-modal/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/testing/20-modal/src/favicon.ico", + "apps/testing/20-modal/src/assets" + ], + "styles": [ + "apps/testing/20-modal/src/styles.scss", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "testing-modal:build:production" + }, + "development": { + "buildTarget": "testing-modal:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "testing-modal:build" + } + }, + "test": { + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}", + "{projectRoot}/coverage" + ], + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + }, + "component-test": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "apps/testing/20-modal/cypress.config.ts", + "testingType": "component", + "skipServe": true, + "devServerTarget": "testing-modal:build" + } + } + } +} diff --git a/apps/testing/modal/src/app/app.component.cy.ts b/apps/testing/20-modal/src/app/app.component.cy.ts similarity index 100% rename from apps/testing/modal/src/app/app.component.cy.ts rename to apps/testing/20-modal/src/app/app.component.cy.ts diff --git a/apps/testing/modal/src/app/app.component.spec.ts b/apps/testing/20-modal/src/app/app.component.spec.ts similarity index 100% rename from apps/testing/modal/src/app/app.component.spec.ts rename to apps/testing/20-modal/src/app/app.component.spec.ts diff --git a/apps/testing/20-modal/src/app/app.component.ts b/apps/testing/20-modal/src/app/app.component.ts new file mode 100644 index 000000000..d5f35b4bf --- /dev/null +++ b/apps/testing/20-modal/src/app/app.component.ts @@ -0,0 +1,64 @@ +import { AsyncPipe } from '@angular/common'; +import { Component, inject } from '@angular/core'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialog, MatDialogModule } from '@angular/material/dialog'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { BehaviorSubject } from 'rxjs'; +import { ErrorDialog } from './error.dialog'; +import { ProfilConfirmationDialog } from './profil-confirmation.dialog'; +@Component({ + imports: [ + ReactiveFormsModule, + MatDialogModule, + MatFormFieldModule, + MatInputModule, + MatButtonModule, + AsyncPipe, + ], + selector: 'app-root', + host: { + class: 'p-4 block flex gap-4 items-center', + }, + template: ` + + Name + + + + +
    {{ result$ | async }}
    + `, +}) +export class AppComponent { + private modal = inject(MatDialog); + private result = new BehaviorSubject(''); + result$ = this.result.asObservable(); + + name = new FormControl('', { nonNullable: true }); + + confirm() { + if (!this.name.value) { + this.modal.open(ErrorDialog); + return; + } + + this.modal + .open(ProfilConfirmationDialog, { + data: { + name: this.name.value, + }, + }) + .afterClosed() + .subscribe((result) => + this.result.next( + result ? 'Name has been submitted' : 'Name is invalid !!', + ), + ); + } +} diff --git a/apps/testing/modal/src/app/app.config.ts b/apps/testing/20-modal/src/app/app.config.ts similarity index 100% rename from apps/testing/modal/src/app/app.config.ts rename to apps/testing/20-modal/src/app/app.config.ts diff --git a/apps/testing/modal/src/app/error.dialog.ts b/apps/testing/20-modal/src/app/error.dialog.ts similarity index 85% rename from apps/testing/modal/src/app/error.dialog.ts rename to apps/testing/20-modal/src/app/error.dialog.ts index 2dd11e1cb..251d5d513 100644 --- a/apps/testing/modal/src/app/error.dialog.ts +++ b/apps/testing/20-modal/src/app/error.dialog.ts @@ -4,12 +4,13 @@ import { MatButtonModule } from '@angular/material/button'; import { MatDialogModule } from '@angular/material/dialog'; @Component({ - standalone: true, imports: [MatButtonModule, MatDialogModule], template: `

    Error

    - You must enter a name first!! + You must enter a + name + first!!
    diff --git a/apps/testing/modal/src/app/profil-confirmation.dialog.ts b/apps/testing/20-modal/src/app/profil-confirmation.dialog.ts similarity index 97% rename from apps/testing/modal/src/app/profil-confirmation.dialog.ts rename to apps/testing/20-modal/src/app/profil-confirmation.dialog.ts index 6af2d41dd..e77211e24 100644 --- a/apps/testing/modal/src/app/profil-confirmation.dialog.ts +++ b/apps/testing/20-modal/src/app/profil-confirmation.dialog.ts @@ -4,7 +4,6 @@ import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; @Component({ - standalone: true, imports: [MatButtonModule, MatDialogModule], template: `

    Profil

    diff --git a/apps/testing/20-modal/src/assets/.gitkeep b/apps/testing/20-modal/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/testing/20-modal/src/favicon.ico b/apps/testing/20-modal/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/testing/20-modal/src/favicon.ico differ diff --git a/apps/testing/20-modal/src/index.html b/apps/testing/20-modal/src/index.html new file mode 100644 index 000000000..362733ce1 --- /dev/null +++ b/apps/testing/20-modal/src/index.html @@ -0,0 +1,13 @@ + + + + + testing-modal + + + + + + + + diff --git a/apps/testing/20-modal/src/main.ts b/apps/testing/20-modal/src/main.ts new file mode 100644 index 000000000..7961924bf --- /dev/null +++ b/apps/testing/20-modal/src/main.ts @@ -0,0 +1,8 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; + +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/testing/20-modal/src/styles.scss b/apps/testing/20-modal/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/testing/20-modal/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/testing/20-modal/src/test-setup.ts b/apps/testing/20-modal/src/test-setup.ts new file mode 100644 index 000000000..15de72a3c --- /dev/null +++ b/apps/testing/20-modal/src/test-setup.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/testing/20-modal/tailwind.config.js b/apps/testing/20-modal/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/testing/20-modal/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/testing/router-outlet/tsconfig.app.json b/apps/testing/20-modal/tsconfig.app.json similarity index 100% rename from apps/testing/router-outlet/tsconfig.app.json rename to apps/testing/20-modal/tsconfig.app.json diff --git a/apps/testing/todos-list/tsconfig.editor.json b/apps/testing/20-modal/tsconfig.editor.json similarity index 100% rename from apps/testing/todos-list/tsconfig.editor.json rename to apps/testing/20-modal/tsconfig.editor.json diff --git a/apps/testing/nested/tsconfig.json b/apps/testing/20-modal/tsconfig.json similarity index 100% rename from apps/testing/nested/tsconfig.json rename to apps/testing/20-modal/tsconfig.json diff --git a/apps/testing/nested/tsconfig.spec.json b/apps/testing/20-modal/tsconfig.spec.json similarity index 100% rename from apps/testing/nested/tsconfig.spec.json rename to apps/testing/20-modal/tsconfig.spec.json diff --git a/apps/testing/input-output/.eslintrc.json b/apps/testing/23-harness/.eslintrc.json similarity index 100% rename from apps/testing/input-output/.eslintrc.json rename to apps/testing/23-harness/.eslintrc.json diff --git a/apps/testing/23-harness/README.md b/apps/testing/23-harness/README.md new file mode 100644 index 000000000..541da1ac8 --- /dev/null +++ b/apps/testing/23-harness/README.md @@ -0,0 +1,13 @@ +# Harness + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve testing-harness +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/23-harness/). diff --git a/apps/testing/harness/jest.config.ts b/apps/testing/23-harness/jest.config.ts similarity index 100% rename from apps/testing/harness/jest.config.ts rename to apps/testing/23-harness/jest.config.ts diff --git a/apps/testing/23-harness/project.json b/apps/testing/23-harness/project.json new file mode 100644 index 000000000..23e5b04f4 --- /dev/null +++ b/apps/testing/23-harness/project.json @@ -0,0 +1,86 @@ +{ + "name": "testing-harness", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/testing/23-harness/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/testing/23-harness", + "index": "apps/testing/23-harness/src/index.html", + "main": "apps/testing/23-harness/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/testing/23-harness/tsconfig.app.json", + "assets": [ + "apps/testing/23-harness/src/favicon.ico", + "apps/testing/23-harness/src/assets" + ], + "styles": ["apps/testing/23-harness/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "testing-harness:build:production" + }, + "development": { + "buildTarget": "testing-harness:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "testing-harness:build" + } + }, + "test": { + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}", + "{projectRoot}/coverage" + ], + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/testing/23-harness/src/app/app.component.ts b/apps/testing/23-harness/src/app/app.component.ts new file mode 100644 index 000000000..7ecf1998d --- /dev/null +++ b/apps/testing/23-harness/src/app/app.component.ts @@ -0,0 +1,12 @@ +import { Component } from '@angular/core'; +import { ChildComponent } from './child.component'; + +@Component({ + imports: [ChildComponent], + selector: 'app-root', + template: ` + + `, + styles: [''], +}) +export class AppComponent {} diff --git a/apps/testing/create-harness/src/app/app.config.ts b/apps/testing/23-harness/src/app/app.config.ts similarity index 100% rename from apps/testing/create-harness/src/app/app.config.ts rename to apps/testing/23-harness/src/app/app.config.ts diff --git a/apps/testing/harness/src/app/child.component.spec.ts b/apps/testing/23-harness/src/app/child.component.spec.ts similarity index 95% rename from apps/testing/harness/src/app/child.component.spec.ts rename to apps/testing/23-harness/src/app/child.component.spec.ts index cb45d2740..1c4b236c8 100644 --- a/apps/testing/harness/src/app/child.component.spec.ts +++ b/apps/testing/23-harness/src/app/child.component.spec.ts @@ -18,7 +18,7 @@ describe('ChildComponent', () => { }); }); - describe('When disabled chebkbox is toggle', () => { + describe('When disabled checkbox is toggled', () => { test('Then slider is disabled', async () => { await render(ChildComponent); }); diff --git a/apps/testing/23-harness/src/app/child.component.ts b/apps/testing/23-harness/src/app/child.component.ts new file mode 100644 index 000000000..935f08f89 --- /dev/null +++ b/apps/testing/23-harness/src/app/child.component.ts @@ -0,0 +1,119 @@ +import { Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { MatCardModule } from '@angular/material/card'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatSliderModule } from '@angular/material/slider'; + +@Component({ + selector: 'app-child', + template: ` + + +

    Slider configuration

    + +
    + + Value + + + + Min value + + + + Max value + + + + Step size + + +
    + +
    + Show ticks +
    + +
    + Show thumb label +
    + +
    + Disabled +
    +
    +
    + + + +
    + + + + + +
    +
    +
    + `, + styles: [ + ` + .mat-mdc-slider { + max-width: 300px; + width: 100%; + } + + .mat-mdc-card + .mat-mdc-card { + margin-top: 8px; + } + `, + ], + imports: [ + MatCardModule, + MatFormFieldModule, + MatInputModule, + FormsModule, + MatCheckboxModule, + MatSliderModule, + MatIconModule, + ], +}) +export class ChildComponent { + disabled = false; + max = 100; + min = 0; + showTicks = false; + step = 1; + thumbLabel = false; + value = 0; + + back() { + if (this.value - this.step >= this.min) { + this.value -= this.step; + } + } + + forward() { + if (this.value + this.step <= this.max) { + this.value += this.step; + } + } +} diff --git a/apps/testing/23-harness/src/assets/.gitkeep b/apps/testing/23-harness/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/testing/23-harness/src/favicon.ico b/apps/testing/23-harness/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/testing/23-harness/src/favicon.ico differ diff --git a/apps/testing/23-harness/src/index.html b/apps/testing/23-harness/src/index.html new file mode 100644 index 000000000..9b55da74f --- /dev/null +++ b/apps/testing/23-harness/src/index.html @@ -0,0 +1,16 @@ + + + + + testing-harness + + + + + + + + + diff --git a/apps/testing/23-harness/src/main.ts b/apps/testing/23-harness/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/testing/23-harness/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/testing/23-harness/src/styles.scss b/apps/testing/23-harness/src/styles.scss new file mode 100644 index 000000000..9a29b71e6 --- /dev/null +++ b/apps/testing/23-harness/src/styles.scss @@ -0,0 +1,29 @@ +@use '@angular/material' as mat; + +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ + +@include mat.elevation-classes(); +@include mat.app-background(); + +$theme-primary: mat.m2-define-palette(mat.$m2-indigo-palette); +$theme-accent: mat.m2-define-palette(mat.$m2-pink-palette, A200, A100, A400); + +$theme-warn: mat.m2-define-palette(mat.$m2-red-palette); + +$theme: mat.m2-define-light-theme( + ( + color: ( + primary: $theme-primary, + accent: $theme-accent, + warn: $theme-warn, + ), + typography: mat.m2-define-typography-config(), + ) +); + +@include mat.dialog-theme($theme); +@include mat.all-component-themes($theme); diff --git a/apps/testing/23-harness/src/test-setup.ts b/apps/testing/23-harness/src/test-setup.ts new file mode 100644 index 000000000..15de72a3c --- /dev/null +++ b/apps/testing/23-harness/src/test-setup.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/testing/23-harness/tailwind.config.js b/apps/testing/23-harness/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/testing/23-harness/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/testing/23-harness/tsconfig.app.json b/apps/testing/23-harness/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/testing/23-harness/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/testing/harness/tsconfig.editor.json b/apps/testing/23-harness/tsconfig.editor.json similarity index 100% rename from apps/testing/harness/tsconfig.editor.json rename to apps/testing/23-harness/tsconfig.editor.json diff --git a/apps/testing/create-harness/tsconfig.json b/apps/testing/23-harness/tsconfig.json similarity index 100% rename from apps/testing/create-harness/tsconfig.json rename to apps/testing/23-harness/tsconfig.json diff --git a/apps/testing/create-harness/tsconfig.spec.json b/apps/testing/23-harness/tsconfig.spec.json similarity index 100% rename from apps/testing/create-harness/tsconfig.spec.json rename to apps/testing/23-harness/tsconfig.spec.json diff --git a/apps/testing/modal/.eslintrc.json b/apps/testing/24-harness-creation/.eslintrc.json similarity index 100% rename from apps/testing/modal/.eslintrc.json rename to apps/testing/24-harness-creation/.eslintrc.json diff --git a/apps/testing/24-harness-creation/README.md b/apps/testing/24-harness-creation/README.md new file mode 100644 index 000000000..928bb1aab --- /dev/null +++ b/apps/testing/24-harness-creation/README.md @@ -0,0 +1,13 @@ +# Harness Creation + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve testing-harness-creation +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/24-harness-creation/). diff --git a/apps/testing/24-harness-creation/jest.config.ts b/apps/testing/24-harness-creation/jest.config.ts new file mode 100644 index 000000000..c4b9f08db --- /dev/null +++ b/apps/testing/24-harness-creation/jest.config.ts @@ -0,0 +1,21 @@ +/* eslint-disable */ +export default { + displayName: 'testing-harness-creation', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/testing/24-harness-creation/project.json b/apps/testing/24-harness-creation/project.json new file mode 100644 index 000000000..f65194122 --- /dev/null +++ b/apps/testing/24-harness-creation/project.json @@ -0,0 +1,86 @@ +{ + "name": "testing-harness-creation", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/testing/24-harness-creation/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/testing/24-harness-creation", + "index": "apps/testing/24-harness-creation/src/index.html", + "main": "apps/testing/24-harness-creation/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/testing/24-harness-creation/tsconfig.app.json", + "assets": [ + "apps/testing/24-harness-creation/src/favicon.ico", + "apps/testing/24-harness-creation/src/assets" + ], + "styles": ["apps/testing/24-harness-creation/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "testing-harness-creation:build:production" + }, + "development": { + "buildTarget": "testing-harness-creation:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "testing-harness-creation:build" + } + }, + "test": { + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}", + "{projectRoot}/coverage" + ], + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/testing/create-harness/src/app/app.component.spec.ts b/apps/testing/24-harness-creation/src/app/app.component.spec.ts similarity index 100% rename from apps/testing/create-harness/src/app/app.component.spec.ts rename to apps/testing/24-harness-creation/src/app/app.component.spec.ts diff --git a/apps/testing/24-harness-creation/src/app/app.component.ts b/apps/testing/24-harness-creation/src/app/app.component.ts new file mode 100644 index 000000000..b1c16240e --- /dev/null +++ b/apps/testing/24-harness-creation/src/app/app.component.ts @@ -0,0 +1,27 @@ +import { Component, signal } from '@angular/core'; +import { SliderComponent } from './slider.component'; + +@Component({ + imports: [SliderComponent], + selector: 'app-root', + template: ` +

    Slider 1: {{ slider1Value() }}

    + +

    Slider 2: {{ slider2Value() }}

    +

    Enabled only if Slider 1 > 20

    + + `, + styles: [''], +}) +export class AppComponent { + slider1Value = signal(10); + slider2Value = signal(0); +} diff --git a/apps/testing/harness/src/app/app.config.ts b/apps/testing/24-harness-creation/src/app/app.config.ts similarity index 100% rename from apps/testing/harness/src/app/app.config.ts rename to apps/testing/24-harness-creation/src/app/app.config.ts diff --git a/apps/testing/create-harness/src/app/slider.component.ts b/apps/testing/24-harness-creation/src/app/slider.component.ts similarity index 96% rename from apps/testing/create-harness/src/app/slider.component.ts rename to apps/testing/24-harness-creation/src/app/slider.component.ts index 1c07c111c..4a3e429bb 100644 --- a/apps/testing/create-harness/src/app/slider.component.ts +++ b/apps/testing/24-harness-creation/src/app/slider.component.ts @@ -11,7 +11,7 @@ import { skip } from 'rxjs'; template: ` -
    +
    @@ -48,7 +48,6 @@ import { skip } from 'rxjs'; } `, ], - standalone: true, imports: [MatCardModule, MatSliderModule, MatIconModule, FormsModule], }) export class SliderComponent implements OnInit { diff --git a/apps/testing/create-harness/src/app/slider.harness.ts b/apps/testing/24-harness-creation/src/app/slider.harness.ts similarity index 100% rename from apps/testing/create-harness/src/app/slider.harness.ts rename to apps/testing/24-harness-creation/src/app/slider.harness.ts diff --git a/apps/testing/24-harness-creation/src/assets/.gitkeep b/apps/testing/24-harness-creation/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/testing/24-harness-creation/src/favicon.ico b/apps/testing/24-harness-creation/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/testing/24-harness-creation/src/favicon.ico differ diff --git a/apps/testing/24-harness-creation/src/index.html b/apps/testing/24-harness-creation/src/index.html new file mode 100644 index 000000000..c66440e5c --- /dev/null +++ b/apps/testing/24-harness-creation/src/index.html @@ -0,0 +1,16 @@ + + + + + testing-harness-creation + + + + + + + + + diff --git a/apps/testing/24-harness-creation/src/main.ts b/apps/testing/24-harness-creation/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/testing/24-harness-creation/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/testing/24-harness-creation/src/styles.scss b/apps/testing/24-harness-creation/src/styles.scss new file mode 100644 index 000000000..1430d2f9b --- /dev/null +++ b/apps/testing/24-harness-creation/src/styles.scss @@ -0,0 +1,30 @@ +/* You can add global styles to this file, and also import other style files */ +@use '@angular/material' as mat; + +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ + +@include mat.elevation-classes(); +@include mat.app-background(); + +$theme-primary: mat.m2-define-palette(mat.$m2-indigo-palette); +$theme-accent: mat.m2-define-palette(mat.$m2-pink-palette, A200, A100, A400); + +$theme-warn: mat.m2-define-palette(mat.$m2-red-palette); + +$theme: mat.m2-define-light-theme( + ( + color: ( + primary: $theme-primary, + accent: $theme-accent, + warn: $theme-warn, + ), + typography: mat.m2-define-typography-config(), + ) +); + +@include mat.dialog-theme($theme); +@include mat.all-component-themes($theme); diff --git a/apps/testing/24-harness-creation/src/test-setup.ts b/apps/testing/24-harness-creation/src/test-setup.ts new file mode 100644 index 000000000..15de72a3c --- /dev/null +++ b/apps/testing/24-harness-creation/src/test-setup.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/testing/24-harness-creation/tailwind.config.js b/apps/testing/24-harness-creation/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/testing/24-harness-creation/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/testing/24-harness-creation/tsconfig.app.json b/apps/testing/24-harness-creation/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/testing/24-harness-creation/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/testing/24-harness-creation/tsconfig.editor.json b/apps/testing/24-harness-creation/tsconfig.editor.json new file mode 100644 index 000000000..4ee639340 --- /dev/null +++ b/apps/testing/24-harness-creation/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": [] + } +} diff --git a/apps/testing/harness/tsconfig.json b/apps/testing/24-harness-creation/tsconfig.json similarity index 100% rename from apps/testing/harness/tsconfig.json rename to apps/testing/24-harness-creation/tsconfig.json diff --git a/apps/testing/harness/tsconfig.spec.json b/apps/testing/24-harness-creation/tsconfig.spec.json similarity index 100% rename from apps/testing/harness/tsconfig.spec.json rename to apps/testing/24-harness-creation/tsconfig.spec.json diff --git a/apps/testing/router-outlet/.eslintrc.json b/apps/testing/28-checkbox/.eslintrc.json similarity index 100% rename from apps/testing/router-outlet/.eslintrc.json rename to apps/testing/28-checkbox/.eslintrc.json diff --git a/apps/testing/28-checkbox/README.md b/apps/testing/28-checkbox/README.md new file mode 100644 index 000000000..905db5f52 --- /dev/null +++ b/apps/testing/28-checkbox/README.md @@ -0,0 +1,13 @@ +# Checkbox + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve testing-checkbox +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/28-checkbox/). diff --git a/apps/testing/28-checkbox/jest.config.ts b/apps/testing/28-checkbox/jest.config.ts new file mode 100644 index 000000000..c27a02c1e --- /dev/null +++ b/apps/testing/28-checkbox/jest.config.ts @@ -0,0 +1,22 @@ +/* eslint-disable */ +export default { + displayName: 'testing-checkbox', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../coverage/apps/testing/28-checkbox', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/testing/28-checkbox/project.json b/apps/testing/28-checkbox/project.json new file mode 100644 index 000000000..982e85c2e --- /dev/null +++ b/apps/testing/28-checkbox/project.json @@ -0,0 +1,82 @@ +{ + "name": "testing-checkbox", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/testing/28-checkbox/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/testing/28-checkbox", + "index": "apps/testing/28-checkbox/src/index.html", + "main": "apps/testing/28-checkbox/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/testing/28-checkbox/tsconfig.app.json", + "assets": [ + "apps/testing/28-checkbox/src/favicon.ico", + "apps/testing/28-checkbox/src/assets" + ], + "styles": ["apps/testing/28-checkbox/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "testing-checkbox:build:production" + }, + "development": { + "buildTarget": "testing-checkbox:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "testing-checkbox:build" + } + }, + "test": { + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + } + } +} diff --git a/apps/testing/checkbox/src/app/app.component.spec.ts b/apps/testing/28-checkbox/src/app/app.component.spec.ts similarity index 100% rename from apps/testing/checkbox/src/app/app.component.spec.ts rename to apps/testing/28-checkbox/src/app/app.component.spec.ts diff --git a/apps/testing/28-checkbox/src/app/app.component.ts b/apps/testing/28-checkbox/src/app/app.component.ts new file mode 100644 index 000000000..936cc781e --- /dev/null +++ b/apps/testing/28-checkbox/src/app/app.component.ts @@ -0,0 +1,29 @@ +import { Component } from '@angular/core'; + +@Component({ + standalone: true, + selector: 'app-root', + template: ` + + + + `, +}) +export class AppComponent { + check = false; + + toggleCheck() { + this.check = !this.check; + } +} diff --git a/apps/testing/28-checkbox/src/assets/.gitkeep b/apps/testing/28-checkbox/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/testing/28-checkbox/src/favicon.ico b/apps/testing/28-checkbox/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/testing/28-checkbox/src/favicon.ico differ diff --git a/apps/testing/28-checkbox/src/index.html b/apps/testing/28-checkbox/src/index.html new file mode 100644 index 000000000..75e95fe9f --- /dev/null +++ b/apps/testing/28-checkbox/src/index.html @@ -0,0 +1,13 @@ + + + + + testing-checkbox + + + + + + + + diff --git a/apps/testing/28-checkbox/src/main.ts b/apps/testing/28-checkbox/src/main.ts new file mode 100644 index 000000000..31c5da482 --- /dev/null +++ b/apps/testing/28-checkbox/src/main.ts @@ -0,0 +1,4 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent).catch((err) => console.error(err)); diff --git a/apps/testing/28-checkbox/src/styles.scss b/apps/testing/28-checkbox/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/testing/28-checkbox/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/testing/28-checkbox/src/test-setup.ts b/apps/testing/28-checkbox/src/test-setup.ts new file mode 100644 index 000000000..15de72a3c --- /dev/null +++ b/apps/testing/28-checkbox/src/test-setup.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/testing/28-checkbox/tailwind.config.js b/apps/testing/28-checkbox/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/testing/28-checkbox/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/testing/28-checkbox/tsconfig.app.json b/apps/testing/28-checkbox/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/testing/28-checkbox/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/testing/28-checkbox/tsconfig.editor.json b/apps/testing/28-checkbox/tsconfig.editor.json new file mode 100644 index 000000000..8ae117d96 --- /dev/null +++ b/apps/testing/28-checkbox/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": ["jest", "node"] + } +} diff --git a/apps/testing/checkbox/tsconfig.json b/apps/testing/28-checkbox/tsconfig.json similarity index 100% rename from apps/testing/checkbox/tsconfig.json rename to apps/testing/28-checkbox/tsconfig.json diff --git a/apps/testing/router-outlet/tsconfig.spec.json b/apps/testing/28-checkbox/tsconfig.spec.json similarity index 100% rename from apps/testing/router-outlet/tsconfig.spec.json rename to apps/testing/28-checkbox/tsconfig.spec.json diff --git a/apps/testing/table/.eslintrc.json b/apps/testing/29-real-life-application/.eslintrc.json similarity index 100% rename from apps/testing/table/.eslintrc.json rename to apps/testing/29-real-life-application/.eslintrc.json diff --git a/apps/testing/29-real-life-application/README.md b/apps/testing/29-real-life-application/README.md new file mode 100644 index 000000000..8dcfe21e6 --- /dev/null +++ b/apps/testing/29-real-life-application/README.md @@ -0,0 +1,13 @@ +# Real-life Application + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve testing-real-life-application +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/29-real-application/). diff --git a/apps/testing/29-real-life-application/cypress.config.ts b/apps/testing/29-real-life-application/cypress.config.ts new file mode 100644 index 000000000..1abef9c0c --- /dev/null +++ b/apps/testing/29-real-life-application/cypress.config.ts @@ -0,0 +1,6 @@ +import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; +import { defineConfig } from 'cypress'; + +export default defineConfig({ + component: nxComponentTestingPreset(__filename), +}); diff --git a/apps/testing/table/cypress/fixtures/example.json b/apps/testing/29-real-life-application/cypress/fixtures/example.json similarity index 100% rename from apps/testing/table/cypress/fixtures/example.json rename to apps/testing/29-real-life-application/cypress/fixtures/example.json diff --git a/apps/testing/29-real-life-application/cypress/support/commands.ts b/apps/testing/29-real-life-application/cypress/support/commands.ts new file mode 100644 index 000000000..b5d8a9582 --- /dev/null +++ b/apps/testing/29-real-life-application/cypress/support/commands.ts @@ -0,0 +1,25 @@ +/// +import { mount } from 'cypress/angular'; + +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + login(email: string, password: string): void; + mount: typeof mount; + } + } +} + +Cypress.Commands.add('mount', mount); diff --git a/apps/testing/29-real-life-application/cypress/support/component-index.html b/apps/testing/29-real-life-application/cypress/support/component-index.html new file mode 100644 index 000000000..57c8a3df4 --- /dev/null +++ b/apps/testing/29-real-life-application/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + testing-todos-list Components App + + +
    + + diff --git a/apps/testing/29-real-life-application/cypress/support/component.ts b/apps/testing/29-real-life-application/cypress/support/component.ts new file mode 100644 index 000000000..e7c3e3cbc --- /dev/null +++ b/apps/testing/29-real-life-application/cypress/support/component.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your subscription files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.ts using ES2015 syntax: +import './commands'; diff --git a/apps/testing/table/cypress/tsconfig.json b/apps/testing/29-real-life-application/cypress/tsconfig.json similarity index 100% rename from apps/testing/table/cypress/tsconfig.json rename to apps/testing/29-real-life-application/cypress/tsconfig.json diff --git a/apps/testing/29-real-life-application/jest.config.ts b/apps/testing/29-real-life-application/jest.config.ts new file mode 100644 index 000000000..b78a06561 --- /dev/null +++ b/apps/testing/29-real-life-application/jest.config.ts @@ -0,0 +1,21 @@ +/* eslint-disable */ +export default { + displayName: 'testing-real-life-application', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/apps/testing/29-real-life-application/project.json b/apps/testing/29-real-life-application/project.json new file mode 100644 index 000000000..c6f1c12d9 --- /dev/null +++ b/apps/testing/29-real-life-application/project.json @@ -0,0 +1,99 @@ +{ + "name": "testing-real-life-application", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/testing/29-real-life-application/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/testing/29-real-life-application", + "index": "apps/testing/29-real-life-application/src/index.html", + "main": "apps/testing/29-real-life-application/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/testing/29-real-life-application/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/testing/29-real-life-application/src/favicon.ico", + "apps/testing/29-real-life-application/src/assets" + ], + "styles": [ + "apps/testing/29-real-life-application/src/styles.scss", + "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "testing-real-life-application:build:production" + }, + "development": { + "buildTarget": "testing-real-life-application:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "testing-real-life-application:build" + } + }, + "test": { + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}", + "{projectRoot}/coverage" + ], + "options": { + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } + } + }, + "component-test": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "apps/testing/29-real-life-application/cypress.config.ts", + "testingType": "component", + "skipServe": true, + "devServerTarget": "testing-real-life-application:build" + } + } + } +} diff --git a/apps/testing/29-real-life-application/src/app/app.component.ts b/apps/testing/29-real-life-application/src/app/app.component.ts new file mode 100644 index 000000000..a4b00aaec --- /dev/null +++ b/apps/testing/29-real-life-application/src/app/app.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + selector: 'app-root', + imports: [RouterOutlet], + template: ` + + `, +}) +export class AppComponent {} diff --git a/apps/testing/todos-list/src/app/app.config.ts b/apps/testing/29-real-life-application/src/app/app.config.ts similarity index 100% rename from apps/testing/todos-list/src/app/app.config.ts rename to apps/testing/29-real-life-application/src/app/app.config.ts diff --git a/apps/testing/todos-list/src/app/app.route.ts b/apps/testing/29-real-life-application/src/app/app.route.ts similarity index 100% rename from apps/testing/todos-list/src/app/app.route.ts rename to apps/testing/29-real-life-application/src/app/app.route.ts diff --git a/apps/testing/todos-list/src/app/backend.service.ts b/apps/testing/29-real-life-application/src/app/backend.service.ts similarity index 98% rename from apps/testing/todos-list/src/app/backend.service.ts rename to apps/testing/29-real-life-application/src/app/backend.service.ts index 2af814b73..08929eda4 100644 --- a/apps/testing/todos-list/src/app/backend.service.ts +++ b/apps/testing/29-real-life-application/src/app/backend.service.ts @@ -101,7 +101,7 @@ export class BackendService { const updatedTicket = { ...foundTicket, ...updates }; this.storedTickets = this.storedTickets.map((t) => - t.id === ticketId ? updatedTicket : t + t.id === ticketId ? updatedTicket : t, ); return of(updatedTicket).pipe(delay(randomDelay())); diff --git a/apps/testing/29-real-life-application/src/app/detail/detail.component.ts b/apps/testing/29-real-life-application/src/app/detail/detail.component.ts new file mode 100644 index 000000000..1afdfb31f --- /dev/null +++ b/apps/testing/29-real-life-application/src/app/detail/detail.component.ts @@ -0,0 +1,63 @@ +import { AsyncPipe, NgIf } from '@angular/common'; +import { Component, inject } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { RouterLink } from '@angular/router'; +import { LetDirective } from '@ngrx/component'; +import { provideComponentStore } from '@ngrx/component-store'; +import { DetailStore } from './detail.store'; + +@Component({ + selector: 'app-detail', + imports: [ + MatButtonModule, + RouterLink, + NgIf, + AsyncPipe, + MatProgressBarModule, + LetDirective, + ], + template: ` +

    Ticket Detail:

    + + +
    +
    + Ticket: + {{ ticket.id }} +
    +
    + Description: + {{ ticket.description }} +
    +
    + AssigneeId: + {{ ticket.assigneeId }} +
    +
    + Is done: + {{ ticket.completed }} +
    +
    +
    + + + `, + providers: [provideComponentStore(DetailStore)], + host: { + class: 'p-5 block', + }, +}) +export class DetailComponent { + vm$ = inject(DetailStore).vm$; +} diff --git a/apps/testing/todos-list/src/app/detail/detail.store.ts b/apps/testing/29-real-life-application/src/app/detail/detail.store.ts similarity index 84% rename from apps/testing/todos-list/src/app/detail/detail.store.ts rename to apps/testing/29-real-life-application/src/app/detail/detail.store.ts index 9d0f421ee..9425b25b2 100644 --- a/apps/testing/todos-list/src/app/detail/detail.store.ts +++ b/apps/testing/29-real-life-application/src/app/detail/detail.store.ts @@ -36,14 +36,17 @@ export class DetailStore loading: this.loading$, }); - constructor(private backend: BackendService, private route: ActivatedRoute) { + constructor( + private backend: BackendService, + private route: ActivatedRoute, + ) { super(initialState); } readonly loadTicket = this.effect( pipe( concatLatestFrom(() => - this.route.params.pipe(map((p) => p[PARAM_TICKET_ID])) + this.route.params.pipe(map((p) => p[PARAM_TICKET_ID])), ), tap(() => this.patchState({ loading: true, error: '' })), mergeMap(([, id]) => @@ -54,11 +57,11 @@ export class DetailStore loading: false, ticket, }), - (error: unknown) => this.patchState({ error }) - ) - ) - ) - ) + (error: unknown) => this.patchState({ error }), + ), + ), + ), + ), ); ngrxOnStateInit() { diff --git a/apps/testing/todos-list/src/app/list/list.component.spec.ts b/apps/testing/29-real-life-application/src/app/list/list.component.spec.ts similarity index 100% rename from apps/testing/todos-list/src/app/list/list.component.spec.ts rename to apps/testing/29-real-life-application/src/app/list/list.component.spec.ts diff --git a/apps/testing/29-real-life-application/src/app/list/list.component.ts b/apps/testing/29-real-life-application/src/app/list/list.component.ts new file mode 100644 index 000000000..64b8f6e63 --- /dev/null +++ b/apps/testing/29-real-life-application/src/app/list/list.component.ts @@ -0,0 +1,74 @@ +import { NgFor, NgIf } from '@angular/common'; +import { Component, OnInit, inject } from '@angular/core'; +import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { LetDirective } from '@ngrx/component'; +import { provideComponentStore } from '@ngrx/component-store'; +import { TicketStore } from './ticket.store'; +import { AddComponent } from './ui/add.component'; +import { RowComponent } from './ui/row.component'; + +@Component({ + selector: 'app-list', + imports: [ + ReactiveFormsModule, + AddComponent, + RowComponent, + MatFormFieldModule, + MatProgressBarModule, + NgIf, + NgFor, + MatInputModule, + LetDirective, + ], + template: ` +

    Tickets

    + + + Search + + + + + + + +
      + +
    +
    + {{ vm.error }} +
    +
    + `, + providers: [provideComponentStore(TicketStore)], + host: { + class: 'p-5 block', + }, +}) +export class ListComponent implements OnInit { + ticketStore = inject(TicketStore); + readonly vm$ = this.ticketStore.vm$; + + search = new FormControl(); + + ngOnInit(): void { + this.ticketStore.search(this.search.valueChanges); + } +} diff --git a/apps/testing/todos-list/src/app/list/ticket.store.spec.ts b/apps/testing/29-real-life-application/src/app/list/ticket.store.spec.ts similarity index 100% rename from apps/testing/todos-list/src/app/list/ticket.store.spec.ts rename to apps/testing/29-real-life-application/src/app/list/ticket.store.spec.ts diff --git a/apps/testing/todos-list/src/app/list/ticket.store.ts b/apps/testing/29-real-life-application/src/app/list/ticket.store.ts similarity index 93% rename from apps/testing/todos-list/src/app/list/ticket.store.ts rename to apps/testing/29-real-life-application/src/app/list/ticket.store.ts index b00d049b4..f8bf979a9 100644 --- a/apps/testing/todos-list/src/app/list/ticket.store.ts +++ b/apps/testing/29-real-life-application/src/app/list/ticket.store.ts @@ -47,7 +47,7 @@ export class TicketStore users.find((user) => user.id === ticket.assigneeId)?.name ?? 'unassigned', })) - : tickets + : tickets, ); readonly tickets$ = this.select( @@ -55,8 +55,8 @@ export class TicketStore this.search$, (tickets, search) => tickets.filter((t) => - t.description.toLowerCase().includes(search.toLowerCase()) - ) + t.description.toLowerCase().includes(search.toLowerCase()), + ), ); readonly vm$ = this.select( @@ -66,7 +66,7 @@ export class TicketStore loading: this.loading$, error: this.error$, }, - { debounce: true } + { debounce: true }, ); readonly updateAssignee = this.updater((state, ticket: Ticket) => { @@ -107,11 +107,11 @@ export class TicketStore loading: false, tickets, }), - (error: unknown) => this.patchState({ error, loading: false }) - ) - ) - ) - ) + (error: unknown) => this.patchState({ error, loading: false }), + ), + ), + ), + ), ); readonly loadUsers = this.effect( @@ -125,11 +125,11 @@ export class TicketStore loading: false, users, }), - (error: unknown) => this.patchState({ error, loading: false }) - ) - ) - ) - ) + (error: unknown) => this.patchState({ error, loading: false }), + ), + ), + ), + ), ); readonly addTicket = this.effect( @@ -143,11 +143,11 @@ export class TicketStore loading: false, tickets: [...state.tickets, newTicket], })), - (error: unknown) => this.patchState({ error, loading: false }) - ) - ) - ) - ) + (error: unknown) => this.patchState({ error, loading: false }), + ), + ), + ), + ), ); readonly assignTicket = this.effect<{ userId: number; ticketId: number }>( @@ -157,11 +157,11 @@ export class TicketStore this.backend.assign(info.ticketId, Number(info.userId)).pipe( tapResponse( (newTicket) => this.updateAssignee(newTicket), - (error: unknown) => this.patchState({ error, loading: false }) - ) - ) - ) - ) + (error: unknown) => this.patchState({ error, loading: false }), + ), + ), + ), + ), ); readonly done = this.effect( @@ -171,10 +171,10 @@ export class TicketStore this.backend.complete(ticketId, true).pipe( tapResponse( (newTicket) => this.updateAssignee(newTicket), - (error: unknown) => this.patchState({ error, loading: false }) - ) - ) - ) - ) + (error: unknown) => this.patchState({ error, loading: false }), + ), + ), + ), + ), ); } diff --git a/apps/testing/29-real-life-application/src/app/list/ui/add.component.ts b/apps/testing/29-real-life-application/src/app/list/ui/add.component.ts new file mode 100644 index 000000000..c48e85a9a --- /dev/null +++ b/apps/testing/29-real-life-application/src/app/list/ui/add.component.ts @@ -0,0 +1,61 @@ +import { NgIf } from '@angular/common'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { + FormControl, + FormGroup, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; + +@Component({ + selector: 'app-add', + imports: [ + ReactiveFormsModule, + MatFormFieldModule, + MatInputModule, + MatButtonModule, + NgIf, + ], + template: ` +
    + + Description + + + Description is + required + + + +
    + `, +}) +export class AddComponent { + @Input() loading = false; + + @Output() addTicket = new EventEmitter(); + + form = new FormGroup({ + description: new FormControl(null, Validators.required), + }); + + submit() { + if (this.form.valid) { + this.addTicket.emit(this.form.value.description ?? ''); + } + } +} diff --git a/apps/testing/todos-list/src/app/list/ui/row.component.spec.ts b/apps/testing/29-real-life-application/src/app/list/ui/row.component.spec.ts similarity index 100% rename from apps/testing/todos-list/src/app/list/ui/row.component.spec.ts rename to apps/testing/29-real-life-application/src/app/list/ui/row.component.spec.ts diff --git a/apps/testing/todos-list/src/app/list/ui/row.component.ts b/apps/testing/29-real-life-application/src/app/list/ui/row.component.ts similarity index 78% rename from apps/testing/todos-list/src/app/list/ui/row.component.ts rename to apps/testing/29-real-life-application/src/app/list/ui/row.component.ts index 1132890bb..12c7d5367 100644 --- a/apps/testing/todos-list/src/app/list/ui/row.component.ts +++ b/apps/testing/29-real-life-application/src/app/list/ui/row.component.ts @@ -10,7 +10,6 @@ import { Ticket, TicketUser, User } from '../../backend.service'; @Component({ selector: 'app-row', - standalone: true, imports: [ RouterLink, ReactiveFormsModule, @@ -22,30 +21,38 @@ import { Ticket, TicketUser, User } from '../../backend.service'; ], template: `
  • + class="flex items-center justify-center gap-4"> Assign to - {{ - user.name - }} + + {{ user.name }} + diff --git a/apps/testing/29-real-life-application/src/assets/.gitkeep b/apps/testing/29-real-life-application/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/testing/29-real-life-application/src/favicon.ico b/apps/testing/29-real-life-application/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/testing/29-real-life-application/src/favicon.ico differ diff --git a/apps/testing/29-real-life-application/src/index.html b/apps/testing/29-real-life-application/src/index.html new file mode 100644 index 000000000..91b0bf44a --- /dev/null +++ b/apps/testing/29-real-life-application/src/index.html @@ -0,0 +1,13 @@ + + + + + testing-real-life-application + + + + + + + + diff --git a/apps/testing/29-real-life-application/src/main.ts b/apps/testing/29-real-life-application/src/main.ts new file mode 100644 index 000000000..7961924bf --- /dev/null +++ b/apps/testing/29-real-life-application/src/main.ts @@ -0,0 +1,8 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; + +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/testing/todos-list/src/styles.scss b/apps/testing/29-real-life-application/src/styles.scss similarity index 100% rename from apps/testing/todos-list/src/styles.scss rename to apps/testing/29-real-life-application/src/styles.scss diff --git a/apps/testing/29-real-life-application/src/test-setup.ts b/apps/testing/29-real-life-application/src/test-setup.ts new file mode 100644 index 000000000..15de72a3c --- /dev/null +++ b/apps/testing/29-real-life-application/src/test-setup.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/testing/29-real-life-application/tailwind.config.js b/apps/testing/29-real-life-application/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/testing/29-real-life-application/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/testing/table/tsconfig.app.json b/apps/testing/29-real-life-application/tsconfig.app.json similarity index 100% rename from apps/testing/table/tsconfig.app.json rename to apps/testing/29-real-life-application/tsconfig.app.json diff --git a/apps/testing/29-real-life-application/tsconfig.editor.json b/apps/testing/29-real-life-application/tsconfig.editor.json new file mode 100644 index 000000000..8ae117d96 --- /dev/null +++ b/apps/testing/29-real-life-application/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": ["jest", "node"] + } +} diff --git a/apps/testing/29-real-life-application/tsconfig.json b/apps/testing/29-real-life-application/tsconfig.json new file mode 100644 index 000000000..c0f4e6dd3 --- /dev/null +++ b/apps/testing/29-real-life-application/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + }, + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./cypress/tsconfig .json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/testing/todos-list/tsconfig.spec.json b/apps/testing/29-real-life-application/tsconfig.spec.json similarity index 100% rename from apps/testing/todos-list/tsconfig.spec.json rename to apps/testing/29-real-life-application/tsconfig.spec.json diff --git a/apps/testing/checkbox/README.md b/apps/testing/checkbox/README.md deleted file mode 100644 index c1c3db787..000000000 --- a/apps/testing/checkbox/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Checkbox - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve testing-checkbox -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/28-checkbox/). diff --git a/apps/testing/checkbox/jest.config.ts b/apps/testing/checkbox/jest.config.ts deleted file mode 100644 index 0c5902908..000000000 --- a/apps/testing/checkbox/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'testing-checkbox', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - coverageDirectory: '../../../coverage/apps/testing/checkbox', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/testing/checkbox/project.json b/apps/testing/checkbox/project.json deleted file mode 100644 index 3046e5914..000000000 --- a/apps/testing/checkbox/project.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "name": "testing-checkbox", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/testing/checkbox/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/checkbox", - "index": "apps/testing/checkbox/src/index.html", - "main": "apps/testing/checkbox/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/checkbox/tsconfig.app.json", - "assets": [ - "apps/testing/checkbox/src/favicon.ico", - "apps/testing/checkbox/src/assets" - ], - "styles": ["apps/testing/checkbox/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-checkbox:build:production" - }, - "development": { - "browserTarget": "testing-checkbox:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-checkbox:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/checkbox/**/*.ts", - "apps/testing/checkbox/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/checkbox/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - } - } -} diff --git a/apps/testing/checkbox/src/app/app.component.ts b/apps/testing/checkbox/src/app/app.component.ts deleted file mode 100644 index 3a2eb367b..000000000 --- a/apps/testing/checkbox/src/app/app.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - standalone: true, - selector: 'app-root', - template: ` - - `, -}) -export class AppComponent { - check = false; - - toggleCheck() { - this.check = !this.check; - } -} diff --git a/apps/testing/checkbox/src/index.html b/apps/testing/checkbox/src/index.html deleted file mode 100644 index c4f112123..000000000 --- a/apps/testing/checkbox/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - testing-checkbox - - - - - - - - diff --git a/apps/testing/create-harness/README.md b/apps/testing/create-harness/README.md deleted file mode 100644 index 47738355a..000000000 --- a/apps/testing/create-harness/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Harness Creation - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve testing-create-harness -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/24-harness-creation/). diff --git a/apps/testing/create-harness/jest.config.ts b/apps/testing/create-harness/jest.config.ts deleted file mode 100644 index 1178b8aaf..000000000 --- a/apps/testing/create-harness/jest.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'testing-create-harness', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/testing/create-harness/project.json b/apps/testing/create-harness/project.json deleted file mode 100644 index bf72aa8e0..000000000 --- a/apps/testing/create-harness/project.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "name": "testing-create-harness", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/testing/create-harness/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/create-harness", - "index": "apps/testing/create-harness/src/index.html", - "main": "apps/testing/create-harness/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/create-harness/tsconfig.app.json", - "assets": [ - "apps/testing/create-harness/src/favicon.ico", - "apps/testing/create-harness/src/assets" - ], - "styles": ["apps/testing/create-harness/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-create-harness:build:production" - }, - "development": { - "browserTarget": "testing-create-harness:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-create-harness:build" - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/create-harness/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/create-harness/**/*.ts", - "apps/testing/create-harness/**/*.html" - ] - } - } - } -} diff --git a/apps/testing/create-harness/src/app/app.component.ts b/apps/testing/create-harness/src/app/app.component.ts deleted file mode 100644 index 06c7eb9af..000000000 --- a/apps/testing/create-harness/src/app/app.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Component, signal } from '@angular/core'; -import { SliderComponent } from './slider.component'; - -@Component({ - standalone: true, - imports: [SliderComponent], - selector: 'app-root', - template: ` -

    Slider 1: {{ slider1Value() }}

    - -

    Slider 2: {{ slider2Value() }}

    -

    Enabled only if Slider 1 > 20

    - - `, - styles: [''], -}) -export class AppComponent { - slider1Value = signal(10); - slider2Value = signal(0); -} diff --git a/apps/testing/create-harness/src/index.html b/apps/testing/create-harness/src/index.html deleted file mode 100644 index 491a1326b..000000000 --- a/apps/testing/create-harness/src/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - create-harness - - - - - - - - - diff --git a/apps/testing/create-harness/src/main.ts b/apps/testing/create-harness/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/testing/create-harness/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/testing/create-harness/src/styles.scss b/apps/testing/create-harness/src/styles.scss deleted file mode 100644 index 94dbf8ff3..000000000 --- a/apps/testing/create-harness/src/styles.scss +++ /dev/null @@ -1,29 +0,0 @@ -/* You can add global styles to this file, and also import other style files */ -@use '@angular/material' as mat; - -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* You can add global styles to this file, and also import other style files */ - -@include mat.core(); - -$theme-primary: mat.define-palette(mat.$indigo-palette); -$theme-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400); - -$theme-warn: mat.define-palette(mat.$red-palette); - -$theme: mat.define-light-theme( - ( - color: ( - primary: $theme-primary, - accent: $theme-accent, - warn: $theme-warn, - ), - typography: mat.define-typography-config(), - ) -); - -@include mat.dialog-theme($theme); -@include mat.all-component-themes($theme); diff --git a/apps/testing/harness/README.md b/apps/testing/harness/README.md deleted file mode 100644 index 15d9b516b..000000000 --- a/apps/testing/harness/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Harness - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve testing-harness -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/23-harness/). diff --git a/apps/testing/harness/project.json b/apps/testing/harness/project.json deleted file mode 100644 index e9521cc01..000000000 --- a/apps/testing/harness/project.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "name": "testing-harness", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "prefix": "app", - "sourceRoot": "apps/testing/harness/src", - "tags": [], - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/harness", - "index": "apps/testing/harness/src/index.html", - "main": "apps/testing/harness/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/harness/tsconfig.app.json", - "assets": [ - "apps/testing/harness/src/favicon.ico", - "apps/testing/harness/src/assets" - ], - "styles": ["apps/testing/harness/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-harness:build:production" - }, - "development": { - "browserTarget": "testing-harness:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-harness:build" - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/harness/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/harness/**/*.ts", - "apps/testing/harness/**/*.html" - ] - } - } - } -} diff --git a/apps/testing/harness/src/app/app.component.ts b/apps/testing/harness/src/app/app.component.ts deleted file mode 100644 index 76ccd4d7e..000000000 --- a/apps/testing/harness/src/app/app.component.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Component } from '@angular/core'; -import { ChildComponent } from './child.component'; - -@Component({ - standalone: true, - imports: [ChildComponent], - selector: 'app-root', - template: ``, - styles: [''], -}) -export class AppComponent {} diff --git a/apps/testing/harness/src/app/child.component.ts b/apps/testing/harness/src/app/child.component.ts deleted file mode 100644 index 178c06cdf..000000000 --- a/apps/testing/harness/src/app/child.component.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { Component } from '@angular/core'; -import { FormsModule } from '@angular/forms'; -import { MatCardModule } from '@angular/material/card'; -import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatIconModule } from '@angular/material/icon'; -import { MatInputModule } from '@angular/material/input'; -import { MatSliderModule } from '@angular/material/slider'; - -@Component({ - selector: 'app-child', - template: ` - - -

    Slider configuration

    - -
    - - Value - - - - Min value - - - - Max value - - - - Step size - - -
    - -
    - Show ticks -
    - -
    - Show thumb label -
    - -
    - Disabled -
    -
    -
    - - - -
    - - - - - -
    -
    -
    - `, - styles: [ - ` - .mat-mdc-slider { - max-width: 300px; - width: 100%; - } - - .mat-mdc-card + .mat-mdc-card { - margin-top: 8px; - } - `, - ], - standalone: true, - imports: [ - MatCardModule, - MatFormFieldModule, - MatInputModule, - FormsModule, - MatCheckboxModule, - MatSliderModule, - MatIconModule, - ], -}) -export class ChildComponent { - disabled = false; - max = 100; - min = 0; - showTicks = false; - step = 1; - thumbLabel = false; - value = 0; - - back() { - if (this.value - this.step >= this.min) { - this.value -= this.step; - } - } - - forward() { - if (this.value + this.step <= this.max) { - this.value += this.step; - } - } -} diff --git a/apps/testing/harness/src/index.html b/apps/testing/harness/src/index.html deleted file mode 100644 index 114170827..000000000 --- a/apps/testing/harness/src/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - harness - - - - - - - - - diff --git a/apps/testing/harness/src/main.ts b/apps/testing/harness/src/main.ts deleted file mode 100644 index 514c89a08..000000000 --- a/apps/testing/harness/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/testing/harness/src/styles.scss b/apps/testing/harness/src/styles.scss deleted file mode 100644 index c9c067e5f..000000000 --- a/apps/testing/harness/src/styles.scss +++ /dev/null @@ -1,28 +0,0 @@ -@use '@angular/material' as mat; - -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* You can add global styles to this file, and also import other style files */ - -@include mat.core(); - -$theme-primary: mat.define-palette(mat.$indigo-palette); -$theme-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400); - -$theme-warn: mat.define-palette(mat.$red-palette); - -$theme: mat.define-light-theme( - ( - color: ( - primary: $theme-primary, - accent: $theme-accent, - warn: $theme-warn, - ), - typography: mat.define-typography-config(), - ) -); - -@include mat.dialog-theme($theme); -@include mat.all-component-themes($theme); diff --git a/apps/testing/input-output/README.md b/apps/testing/input-output/README.md deleted file mode 100644 index 127480a0c..000000000 --- a/apps/testing/input-output/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Input Output - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve testing-input-output -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/19-input-output/). diff --git a/apps/testing/input-output/cypress.config.ts b/apps/testing/input-output/cypress.config.ts deleted file mode 100644 index 7287d91cd..000000000 --- a/apps/testing/input-output/cypress.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'cypress'; -import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; - -export default defineConfig({ - component: nxComponentTestingPreset(__filename), -}); diff --git a/apps/testing/input-output/cypress/support/commands.ts b/apps/testing/input-output/cypress/support/commands.ts deleted file mode 100644 index e6c897603..000000000 --- a/apps/testing/input-output/cypress/support/commands.ts +++ /dev/null @@ -1,42 +0,0 @@ -/// -import { mount } from 'cypress/angular'; - -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface Chainable { - login(email: string, password: string): void; - mount: typeof mount; - } - } -} - -Cypress.Commands.add('mount', mount); - -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/apps/testing/input-output/cypress/support/component-index.html b/apps/testing/input-output/cypress/support/component-index.html deleted file mode 100644 index c04f2f6d9..000000000 --- a/apps/testing/input-output/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - testing-input-output Components App - - -
    - - diff --git a/apps/testing/input-output/cypress/support/component.ts b/apps/testing/input-output/cypress/support/component.ts deleted file mode 100644 index e3684dbdc..000000000 --- a/apps/testing/input-output/cypress/support/component.ts +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.ts using ES2015 syntax: -import './commands'; diff --git a/apps/testing/input-output/project.json b/apps/testing/input-output/project.json deleted file mode 100644 index ada57e6de..000000000 --- a/apps/testing/input-output/project.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "name": "testing-input-output", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/testing/input-output/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/input-output", - "index": "apps/testing/input-output/src/index.html", - "main": "apps/testing/input-output/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/input-output/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/testing/input-output/src/favicon.ico", - "apps/testing/input-output/src/assets" - ], - "styles": ["apps/testing/input-output/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-input-output:build:production" - }, - "development": { - "browserTarget": "testing-input-output:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-input-output:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/input-output/**/*.ts", - "apps/testing/input-output/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/input-output/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - }, - "component-test": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/testing/input-output/cypress.config.ts", - "testingType": "component", - "skipServe": true, - "devServerTarget": "testing-input-output:build" - } - } - }, - "tags": [] -} diff --git a/apps/testing/input-output/src/app/app.component.ts b/apps/testing/input-output/src/app/app.component.ts deleted file mode 100644 index 6a6392a4b..000000000 --- a/apps/testing/input-output/src/app/app.component.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Component } from '@angular/core'; -import { CounterComponent } from './counter.component'; - -@Component({ - standalone: true, - imports: [CounterComponent], - selector: 'app-root', - template: ` - - `, -}) -export class AppComponent { - log(counter: number) { - console.log('output log', counter); - } -} diff --git a/apps/testing/input-output/src/app/counter.component.ts b/apps/testing/input-output/src/app/counter.component.ts deleted file mode 100644 index 1ca95430d..000000000 --- a/apps/testing/input-output/src/app/counter.component.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { AsyncPipe } from '@angular/common'; -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - Input, - Output, -} from '@angular/core'; -import { LetDirective } from '@ngrx/component'; -import { ComponentStore } from '@ngrx/component-store'; - -@Component({ - selector: 'app-counter', - standalone: true, - imports: [AsyncPipe, LetDirective], - template: ` - -

    Counter: {{ counter }}

    - - - -
    - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class CounterComponent extends ComponentStore<{ counter: number }> { - @Input() set initialValue(initialValue: number) { - this.patchState({ counter: initialValue }); - } - - @Output() send = new EventEmitter(); - - readonly counter$ = this.select((state) => state.counter); - - readonly increment = this.updater((state) => ({ - counter: state.counter + 1, - })); - readonly decrement = this.updater((state) => ({ - counter: state.counter - 1, - })); - - constructor() { - super({ counter: 0 }); - } -} diff --git a/apps/testing/input-output/src/index.html b/apps/testing/input-output/src/index.html deleted file mode 100644 index 435d4bb65..000000000 --- a/apps/testing/input-output/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - TestingInputOutput - - - - - - - - diff --git a/apps/testing/modal/README.md b/apps/testing/modal/README.md deleted file mode 100644 index 01cc15919..000000000 --- a/apps/testing/modal/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Modal - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve testing-modal -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/20-modal/). diff --git a/apps/testing/modal/cypress.config.ts b/apps/testing/modal/cypress.config.ts deleted file mode 100644 index 7287d91cd..000000000 --- a/apps/testing/modal/cypress.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'cypress'; -import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; - -export default defineConfig({ - component: nxComponentTestingPreset(__filename), -}); diff --git a/apps/testing/modal/cypress/support/commands.ts b/apps/testing/modal/cypress/support/commands.ts deleted file mode 100644 index e6c897603..000000000 --- a/apps/testing/modal/cypress/support/commands.ts +++ /dev/null @@ -1,42 +0,0 @@ -/// -import { mount } from 'cypress/angular'; - -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface Chainable { - login(email: string, password: string): void; - mount: typeof mount; - } - } -} - -Cypress.Commands.add('mount', mount); - -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/apps/testing/modal/cypress/support/component-index.html b/apps/testing/modal/cypress/support/component-index.html deleted file mode 100644 index 539b1d24f..000000000 --- a/apps/testing/modal/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - testing-modal Components App - - -
    - - diff --git a/apps/testing/modal/cypress/support/component.ts b/apps/testing/modal/cypress/support/component.ts deleted file mode 100644 index e3684dbdc..000000000 --- a/apps/testing/modal/cypress/support/component.ts +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.ts using ES2015 syntax: -import './commands'; diff --git a/apps/testing/modal/project.json b/apps/testing/modal/project.json deleted file mode 100644 index 61a5094b0..000000000 --- a/apps/testing/modal/project.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "name": "testing-modal", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/testing/modal/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/modal", - "index": "apps/testing/modal/src/index.html", - "main": "apps/testing/modal/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/modal/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/testing/modal/src/favicon.ico", - "apps/testing/modal/src/assets" - ], - "styles": [ - "apps/testing/modal/src/styles.scss", - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" - ], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-modal:build:production" - }, - "development": { - "browserTarget": "testing-modal:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-modal:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/modal/**/*.ts", - "apps/testing/modal/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/modal/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - }, - "component-test": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/testing/modal/cypress.config.ts", - "testingType": "component", - "skipServe": true, - "devServerTarget": "testing-modal:build" - } - } - }, - "tags": [] -} diff --git a/apps/testing/modal/src/app/app.component.ts b/apps/testing/modal/src/app/app.component.ts deleted file mode 100644 index 8c0fd8d84..000000000 --- a/apps/testing/modal/src/app/app.component.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { AsyncPipe } from '@angular/common'; -import { Component, inject } from '@angular/core'; -import { FormControl, ReactiveFormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialog, MatDialogModule } from '@angular/material/dialog'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { BehaviorSubject } from 'rxjs'; -import { ErrorDialog } from './error.dialog'; -import { ProfilConfirmationDialog } from './profil-confirmation.dialog'; -@Component({ - standalone: true, - imports: [ - ReactiveFormsModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - MatButtonModule, - AsyncPipe, - ], - selector: 'app-root', - host: { - class: 'p-4 block flex gap-4 items-center', - }, - template: ` - - Name - - - - -
    {{ result$ | async }}
    - `, -}) -export class AppComponent { - private modal = inject(MatDialog); - private result = new BehaviorSubject(''); - result$ = this.result.asObservable(); - - name = new FormControl('', { nonNullable: true }); - - confirm() { - if (!this.name.value) { - this.modal.open(ErrorDialog); - return; - } - - this.modal - .open(ProfilConfirmationDialog, { - data: { - name: this.name.value, - }, - }) - .afterClosed() - .subscribe((result) => - this.result.next( - result ? 'Name has been submitted' : 'Name is invalid !!' - ) - ); - } -} diff --git a/apps/testing/modal/src/index.html b/apps/testing/modal/src/index.html deleted file mode 100644 index ce6d8d49b..000000000 --- a/apps/testing/modal/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - TestingModal - - - - - - - - diff --git a/apps/testing/modal/src/main.ts b/apps/testing/modal/src/main.ts deleted file mode 100644 index 4ecc5cf6a..000000000 --- a/apps/testing/modal/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { appConfig } from './app/app.config'; -import { bootstrapApplication } from '@angular/platform-browser'; - -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/testing/nested/README.md b/apps/testing/nested/README.md deleted file mode 100644 index 1b7fea6ab..000000000 --- a/apps/testing/nested/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Nested Components - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve testing-nested -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/18-nested-comp/). diff --git a/apps/testing/nested/cypress.config.ts b/apps/testing/nested/cypress.config.ts deleted file mode 100644 index 7287d91cd..000000000 --- a/apps/testing/nested/cypress.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'cypress'; -import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; - -export default defineConfig({ - component: nxComponentTestingPreset(__filename), -}); diff --git a/apps/testing/nested/cypress/support/commands.ts b/apps/testing/nested/cypress/support/commands.ts deleted file mode 100644 index e6c897603..000000000 --- a/apps/testing/nested/cypress/support/commands.ts +++ /dev/null @@ -1,42 +0,0 @@ -/// -import { mount } from 'cypress/angular'; - -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface Chainable { - login(email: string, password: string): void; - mount: typeof mount; - } - } -} - -Cypress.Commands.add('mount', mount); - -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/apps/testing/nested/cypress/support/component-index.html b/apps/testing/nested/cypress/support/component-index.html deleted file mode 100644 index ee5b07370..000000000 --- a/apps/testing/nested/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - testing-nested Components App - - -
    - - diff --git a/apps/testing/nested/cypress/support/component.ts b/apps/testing/nested/cypress/support/component.ts deleted file mode 100644 index e3684dbdc..000000000 --- a/apps/testing/nested/cypress/support/component.ts +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.ts using ES2015 syntax: -import './commands'; diff --git a/apps/testing/nested/jest.config.ts b/apps/testing/nested/jest.config.ts deleted file mode 100644 index a89947bd9..000000000 --- a/apps/testing/nested/jest.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'testing-nested', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/testing/nested/project.json b/apps/testing/nested/project.json deleted file mode 100644 index fdb0f64be..000000000 --- a/apps/testing/nested/project.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "name": "testing-nested", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/testing/nested/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/nested", - "index": "apps/testing/nested/src/index.html", - "main": "apps/testing/nested/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/nested/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/testing/nested/src/favicon.ico", - "apps/testing/nested/src/assets" - ], - "styles": ["apps/testing/nested/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-nested:build:production" - }, - "development": { - "browserTarget": "testing-nested:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-nested:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/nested/**/*.ts", - "apps/testing/nested/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/nested/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - }, - "component-test": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/testing/nested/cypress.config.ts", - "testingType": "component", - "skipServe": true, - "devServerTarget": "testing-nested:build" - } - } - }, - "tags": [] -} diff --git a/apps/testing/nested/src/app/app.component.ts b/apps/testing/nested/src/app/app.component.ts deleted file mode 100644 index 8877b8c89..000000000 --- a/apps/testing/nested/src/app/app.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { ChildComponent } from './child.component'; - -@Component({ - standalone: true, - imports: [ChildComponent], - selector: 'app-root', - template: ` `, -}) -export class AppComponent {} diff --git a/apps/testing/nested/src/app/child.component.ts b/apps/testing/nested/src/app/child.component.ts deleted file mode 100644 index e148cca7f..000000000 --- a/apps/testing/nested/src/app/child.component.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { NgIf } from '@angular/common'; -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - Input, - Output, - inject, -} from '@angular/core'; -import { FormControl, ReactiveFormsModule } from '@angular/forms'; -import { HttpService } from './http.service'; - -@Component({ - selector: 'app-input', - standalone: true, - imports: [ReactiveFormsModule], - template: ` `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class InputComponent { - title = new FormControl('', { nonNullable: true }); -} - -@Component({ - selector: 'result', - standalone: true, - template: `

    Title is {{ title }}

    `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ResultComponent { - @Input() title = ''; -} - -@Component({ - selector: 'app-button', - standalone: true, - template: ``, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ButtonComponent { - @Output() validate = new EventEmitter(); -} - -@Component({ - selector: 'app-error', - standalone: true, - template: `

    Title is required !!!

    `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ErrorComponent { - @Output() validate = new EventEmitter(); -} - -@Component({ - selector: 'app-child', - standalone: true, - imports: [ - ResultComponent, - ButtonComponent, - InputComponent, - ErrorComponent, - NgIf, - ], - template: ` - - - - - `, - changeDetection: ChangeDetectionStrategy.OnPush, -}) -export class ChildComponent { - http = inject(HttpService); - - showError = false; - - submit(title: string) { - this.showError = false; - if (title === '') { - this.showError = true; - return; - } - - this.http.sendTitle(title); - } -} diff --git a/apps/testing/nested/src/index.html b/apps/testing/nested/src/index.html deleted file mode 100644 index 93eefa731..000000000 --- a/apps/testing/nested/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - TestingNested - - - - - - - - diff --git a/apps/testing/router-outlet/README.md b/apps/testing/router-outlet/README.md deleted file mode 100644 index 71208a4fc..000000000 --- a/apps/testing/router-outlet/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Router - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve testing-router-outlet -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/17-router/). diff --git a/apps/testing/router-outlet/cypress.config.ts b/apps/testing/router-outlet/cypress.config.ts deleted file mode 100644 index 7287d91cd..000000000 --- a/apps/testing/router-outlet/cypress.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'cypress'; -import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; - -export default defineConfig({ - component: nxComponentTestingPreset(__filename), -}); diff --git a/apps/testing/router-outlet/cypress/support/commands.ts b/apps/testing/router-outlet/cypress/support/commands.ts deleted file mode 100644 index e6c897603..000000000 --- a/apps/testing/router-outlet/cypress/support/commands.ts +++ /dev/null @@ -1,42 +0,0 @@ -/// -import { mount } from 'cypress/angular'; - -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface Chainable { - login(email: string, password: string): void; - mount: typeof mount; - } - } -} - -Cypress.Commands.add('mount', mount); - -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/apps/testing/router-outlet/cypress/support/component-index.html b/apps/testing/router-outlet/cypress/support/component-index.html deleted file mode 100644 index 4d7f518eb..000000000 --- a/apps/testing/router-outlet/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - router-testing Components App - - -
    - - diff --git a/apps/testing/router-outlet/cypress/support/component.ts b/apps/testing/router-outlet/cypress/support/component.ts deleted file mode 100644 index e3684dbdc..000000000 --- a/apps/testing/router-outlet/cypress/support/component.ts +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.ts using ES2015 syntax: -import './commands'; diff --git a/apps/testing/router-outlet/jest.config.ts b/apps/testing/router-outlet/jest.config.ts deleted file mode 100644 index 0bca8aebb..000000000 --- a/apps/testing/router-outlet/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'testing-router-outlet', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - globals: {}, - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/testing/router-outlet/project.json b/apps/testing/router-outlet/project.json deleted file mode 100644 index 59fafa118..000000000 --- a/apps/testing/router-outlet/project.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "name": "testing-router-outlet", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/testing/router-outlet/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/router-outlet", - "index": "apps/testing/router-outlet/src/index.html", - "main": "apps/testing/router-outlet/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/router-outlet/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/testing/router-outlet/src/favicon.ico", - "apps/testing/router-outlet/src/assets" - ], - "styles": ["apps/testing/router-outlet/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-router-outlet:build:production" - }, - "development": { - "browserTarget": "testing-router-outlet:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-router-outlet:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/router-outlet/**/*.ts", - "apps/testing/router-outlet/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/router-outlet/jest.config.ts", - "passWithNoTests": true - } - }, - "component-test": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/testing/router-outlet/cypress.config.ts", - "testingType": "component", - "skipServe": true, - "devServerTarget": "testing-router-outlet:build" - } - } - }, - "tags": [] -} diff --git a/apps/testing/router-outlet/src/app/app.component.ts b/apps/testing/router-outlet/src/app/app.component.ts deleted file mode 100644 index 3b420a867..000000000 --- a/apps/testing/router-outlet/src/app/app.component.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterLink, RouterOutlet } from '@angular/router'; - -@Component({ - standalone: true, - imports: [RouterOutlet, RouterLink], - selector: 'app-root', - styles: [ - ` - h1 { - margin-bottom: 0; - } - nav a { - padding: 1rem; - text-decoration: none; - margin-top: 10px; - display: inline-block; - background-color: #e8e8e8; - color: #3d3d3d; - border-radius: 4px; - margin-bottom: 10px; - } - nav a:hover { - color: white; - background-color: #42545c; - } - nav a.active { - background-color: black; - } - `, - ], - template: ` -

    Library

    - - - - - `, -}) -export class AppComponent {} diff --git a/apps/testing/router-outlet/src/index.html b/apps/testing/router-outlet/src/index.html deleted file mode 100644 index dc98015dc..000000000 --- a/apps/testing/router-outlet/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - RouterTesting - - - - - - - - diff --git a/apps/testing/router-outlet/src/main.ts b/apps/testing/router-outlet/src/main.ts deleted file mode 100644 index 4ecc5cf6a..000000000 --- a/apps/testing/router-outlet/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { appConfig } from './app/app.config'; -import { bootstrapApplication } from '@angular/platform-browser'; - -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/testing/router-outlet/tsconfig.json b/apps/testing/router-outlet/tsconfig.json deleted file mode 100644 index 3879b94cd..000000000 --- a/apps/testing/router-outlet/tsconfig.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "compilerOptions": { - "target": "es2022", - "useDefineForClassFields": false, - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.editor.json" - }, - { - "path": "./cypress/tsconfig.json" - } - ], - "extends": "../../../tsconfig.base.json", - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/apps/testing/table/README.md b/apps/testing/table/README.md deleted file mode 100644 index f5e232e98..000000000 --- a/apps/testing/table/README.md +++ /dev/null @@ -1,38 +0,0 @@ -

    Table testing

    - -> Author: Thomas Laforge - -## Statement: - -NOT IMPLEMENTED YET - - - -### Submitting your work - -1. Fork the project -2. clone it -3. npm ci -4. `npx nx serve testing-table` to play with the application -5. `npx nx test testing-table` to test your application with Testing Library -6. `npx nx component-test testing-table --watch` to test your application with Cypress -7. _...work on it_ -8. Commit your work -9. Submit a PR with a title beginning with **Answer:22** that I will review and other dev can review. - -nested testing -nested testing solution author - - - -_You can ask any question on_ twitter diff --git a/apps/testing/table/cypress.config.ts b/apps/testing/table/cypress.config.ts deleted file mode 100644 index 7287d91cd..000000000 --- a/apps/testing/table/cypress.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'cypress'; -import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; - -export default defineConfig({ - component: nxComponentTestingPreset(__filename), -}); diff --git a/apps/testing/table/cypress/support/commands.ts b/apps/testing/table/cypress/support/commands.ts deleted file mode 100644 index e6c897603..000000000 --- a/apps/testing/table/cypress/support/commands.ts +++ /dev/null @@ -1,42 +0,0 @@ -/// -import { mount } from 'cypress/angular'; - -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface Chainable { - login(email: string, password: string): void; - mount: typeof mount; - } - } -} - -Cypress.Commands.add('mount', mount); - -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/apps/testing/table/cypress/support/component-index.html b/apps/testing/table/cypress/support/component-index.html deleted file mode 100644 index a749e54f5..000000000 --- a/apps/testing/table/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - testing-table Components App - - -
    - - diff --git a/apps/testing/table/cypress/support/component.ts b/apps/testing/table/cypress/support/component.ts deleted file mode 100644 index e3684dbdc..000000000 --- a/apps/testing/table/cypress/support/component.ts +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.ts using ES2015 syntax: -import './commands'; diff --git a/apps/testing/table/jest.config.ts b/apps/testing/table/jest.config.ts deleted file mode 100644 index 56b0e7df7..000000000 --- a/apps/testing/table/jest.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'testing-table', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/testing/table/project.json b/apps/testing/table/project.json deleted file mode 100644 index b675e3e75..000000000 --- a/apps/testing/table/project.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "name": "testing-table", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/testing/table/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/table", - "index": "apps/testing/table/src/index.html", - "main": "apps/testing/table/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/table/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/testing/table/src/favicon.ico", - "apps/testing/table/src/assets" - ], - "styles": ["apps/testing/table/src/styles.scss"], - "scripts": [], - "allowedCommonJsDependencies": ["seedrandom"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-table:build:production" - }, - "development": { - "browserTarget": "testing-table:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-table:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/table/**/*.ts", - "apps/testing/table/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/table/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - }, - "component-test": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/testing/table/cypress.config.ts", - "testingType": "component", - "skipServe": true, - "devServerTarget": "testing-table:build" - } - } - }, - "tags": [] -} diff --git a/apps/testing/table/src/app/app.component.ts b/apps/testing/table/src/app/app.component.ts deleted file mode 100644 index 534b44976..000000000 --- a/apps/testing/table/src/app/app.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { TableComponent } from './table.component'; - -@Component({ - standalone: true, - imports: [TableComponent], - selector: 'app-root', - template: ` `, -}) -export class AppComponent {} diff --git a/apps/testing/table/src/app/table.component.spec.ts b/apps/testing/table/src/app/table.component.spec.ts deleted file mode 100644 index 2b71f26cc..000000000 --- a/apps/testing/table/src/app/table.component.spec.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; -import { MatTableHarness } from '@angular/material/table/testing'; -import { render } from '@testing-library/angular'; -import userEvent from '@testing-library/user-event'; -import { TableComponent } from './table.component'; - -describe('AppComponent', () => { - // let loader: HarnessLoader; - // let fixture: ComponentFixture; - // let loader: HarnessLoader; - - // beforeEach(async () => { - // const view = await render(TableComponent); - // fixture = view.fixture; - // loader = TestbedHarnessEnvironment.loader(fixture); - // }); - it('error modal is displayed if you click on "Confirm" without inputing a name', async () => { - userEvent.setup(); - const { fixture } = await render(TableComponent); - const loader = TestbedHarnessEnvironment.loader(fixture); - - const tables = await loader.getAllHarnesses(MatTableHarness); - expect(tables.length).toBe(1); - - // const confirmButton = await screen.findByRole('button', { - // name: /confirm/i, - // }); - // await userEvent.click(confirmButton); - - // const dialogControl = await screen.findByRole('dialog'); - // expect(dialogControl).toBeInTheDocument(); - // const errorTitle = await screen.findByRole('heading', { - // name: /error/i, - // }); - // expect(errorTitle).toBeInTheDocument(); - - // const okButton = await screen.findByRole('button', { - // name: /ok/i, - // }); - // await userEvent.click(okButton); - }); - - // test('error message is shown if you click "Cancel" in the confirmation modal after submitting a name', async () => { - // userEvent.setup(); - // await render(AppComponent); - - // const inputControl = await screen.getByRole('textbox'); - // await userEvent.type(inputControl, 'toto'); - - // const confirmButton = await screen.findByRole('button', { - // name: /confirm/i, - // }); - // await userEvent.click(confirmButton); - - // const dialogControl = await screen.findByRole('dialog'); - // expect(dialogControl).toBeInTheDocument(); - // const profilTitle = await screen.findByRole('heading', { - // name: /profil/i, - // }); - // expect(profilTitle).toBeInTheDocument(); - - // const cancelButton = await screen.findByRole('button', { - // name: /cancel/i, - // }); - // await userEvent.click(cancelButton); - - // const errorText = await screen.getByText('Name is invalid !!'); - // expect(errorText).toBeInTheDocument(); - // }); - - // test('confirm message is shown if you click "Confirm" in the confirmation modal after submitting a name', async () => { - // userEvent.setup(); - // await render(AppComponent); - - // const inputControl = await screen.getByRole('textbox'); - // await userEvent.type(inputControl, 'toto'); - - // const confirmButton = await screen.findByRole('button', { - // name: /confirm/i, - // }); - // await userEvent.click(confirmButton); - - // const dialogControl = await screen.findByRole('dialog'); - // expect(dialogControl).toBeInTheDocument(); - // const profilTitle = await screen.findByRole('heading', { - // name: /profil/i, - // }); - // expect(profilTitle).toBeInTheDocument(); - - // const confirmDialogButton = await screen.findByRole('button', { - // name: /confirm/i, - // }); - // await userEvent.click(confirmDialogButton); - - // const confirmText = await screen.getByText('Name has been submitted'); - // expect(confirmText).toBeInTheDocument(); - // }); -}); diff --git a/apps/testing/table/src/app/table.component.ts b/apps/testing/table/src/app/table.component.ts deleted file mode 100644 index a2c6d4ce3..000000000 --- a/apps/testing/table/src/app/table.component.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { FakeBackendService } from '@angular-challenges/testing-table/backend'; -import { AsyncPipe, DatePipe, NgIf } from '@angular/common'; -import { AfterViewInit, Component, ViewChild, inject } from '@angular/core'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; -import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { MatSort, MatSortModule, SortDirection } from '@angular/material/sort'; -import { MatTableModule } from '@angular/material/table'; -import { User } from '@ngneat/falso'; -import { LetDirective } from '@ngrx/component'; -import { ComponentStore, tapResponse } from '@ngrx/component-store'; -import { map, pipe, startWith, switchMap, tap } from 'rxjs'; - -interface TableState { - loading: boolean; - error?: string; - users: User[]; -} - -@Component({ - selector: 'app-table', - standalone: true, - imports: [ - MatFormFieldModule, - MatInputModule, - MatTableModule, - MatSortModule, - MatPaginatorModule, - MatProgressSpinnerModule, - LetDirective, - NgIf, - AsyncPipe, - DatePipe, - ], - template: ` -
    -
    - - -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    FirstName{{ row.firstName }}LastName{{ row.lastName }}Email{{ row.email }}
    -
    - - -
    - `, -}) -export class TableComponent - extends ComponentStore - implements AfterViewInit -{ - readonly displayedColumns = ['firstName', 'lastName', 'email']; - - private api = inject(FakeBackendService); - - readonly issues$ = this.select((s) => s.users).pipe( - tap((t) => console.log('UserNEw ', t)) - ); - readonly loading$ = this.select((s) => s.loading); - readonly error$ = this.select((s) => s.error); - readonly resultsLength$ = this.select((s) => 100); - - // resultsLength = 0; - // isLoadingResults = true; - // isRateLimitReached = false; - - @ViewChild(MatPaginator) paginator!: MatPaginator; - @ViewChild(MatSort) sort!: MatSort; - - constructor() { - super({ loading: false, users: [] }); - } - - readonly loadData = this.effect<{ - sortActive: keyof User; - sortDir: SortDirection; - pageIndex: number; - }>( - pipe( - tap((t) => console.log('cocou', t)), - tap(() => this.patchState({ loading: true, users: [] })), - switchMap(({ sortActive, sortDir, pageIndex }) => - this.api.getUsers(sortActive, sortDir, pageIndex).pipe( - tap((t) => console.log('user', t)), - tapResponse( - (data) => this.patchState({ users: data, loading: false }), - (err) => this.patchState({ error: err as string, loading: false }) - ) - ) - ) - ) - ); - - ngAfterViewInit(): void { - // due to ExpressionChangedAfterItHasBeenCheckedError - console.log('cocuo', this.sort, this.paginator); - this.loadData( - this.select({ - sortActive: this.sort.sortChange.pipe( - map((s) => s.active as keyof User) - ), - sortDir: this.sort.sortChange.pipe(map((s) => s.direction)), - pageIndex: this.paginator.page.pipe(map((p) => p.pageIndex)), - }).pipe( - startWith({ - sortActive: this.sort.active as keyof User, - sortDir: this.sort.direction, - pageIndex: 1, - }) - ) - ); - } - - // applyFilter(event: Event) { - // const filterValue = (event.target as HTMLInputElement).value; - // this.dataSource.filter = filterValue.trim().toLowerCase(); - - // if (this.dataSource.paginator) { - // this.dataSource.paginator.firstPage(); - // } - // } -} diff --git a/apps/testing/table/src/index.html b/apps/testing/table/src/index.html deleted file mode 100644 index 2eadaaa7d..000000000 --- a/apps/testing/table/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - TestingTable - - - - - - - - diff --git a/apps/testing/table/src/main.ts b/apps/testing/table/src/main.ts deleted file mode 100644 index b0ca80b94..000000000 --- a/apps/testing/table/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { provideHttpClient } from '@angular/common/http'; -import { bootstrapApplication } from '@angular/platform-browser'; -import { provideAnimations } from '@angular/platform-browser/animations'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, { - providers: [provideAnimations(), provideHttpClient()], -}).catch((err) => console.error(err)); diff --git a/apps/testing/table/src/styles.scss b/apps/testing/table/src/styles.scss deleted file mode 100644 index ce5105b51..000000000 --- a/apps/testing/table/src/styles.scss +++ /dev/null @@ -1,31 +0,0 @@ -@use '@angular/material' as mat; - -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* You can add global styles to this file, and also import other style files */ - -@include mat.core(); - -$theme-primary: mat.define-palette(mat.$indigo-palette); -$theme-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400); - -$theme-warn: mat.define-palette(mat.$red-palette); - -$theme: mat.define-light-theme( - ( - color: ( - primary: $theme-primary, - accent: $theme-accent, - warn: $theme-warn, - ), - typography: mat.define-typography-config(), - ) -); - -@include mat.core-theme($theme); -@include mat.all-component-themes($theme); -// @include mat.form-field-theme($theme); -// @include mat.input-theme($theme); -// @include mat.paginator-theme($theme); diff --git a/apps/testing/table/tsconfig.json b/apps/testing/table/tsconfig.json deleted file mode 100644 index 3879b94cd..000000000 --- a/apps/testing/table/tsconfig.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "compilerOptions": { - "target": "es2022", - "useDefineForClassFields": false, - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.editor.json" - }, - { - "path": "./cypress/tsconfig.json" - } - ], - "extends": "../../../tsconfig.base.json", - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/apps/testing/table/tsconfig.spec.json b/apps/testing/table/tsconfig.spec.json deleted file mode 100644 index a578b4624..000000000 --- a/apps/testing/table/tsconfig.spec.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node", "@testing-library/jest-dom"], - "target": "ES2016" - }, - "files": ["src/test-setup.ts"], - "include": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] -} diff --git a/apps/testing/todos-list/README.md b/apps/testing/todos-list/README.md deleted file mode 100644 index 2adce88a0..000000000 --- a/apps/testing/todos-list/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Real-life Application - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve testing-todos-list -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/testing/29-real-application/). diff --git a/apps/testing/todos-list/cypress.config.ts b/apps/testing/todos-list/cypress.config.ts deleted file mode 100644 index 7287d91cd..000000000 --- a/apps/testing/todos-list/cypress.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'cypress'; -import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing'; - -export default defineConfig({ - component: nxComponentTestingPreset(__filename), -}); diff --git a/apps/testing/todos-list/cypress/fixtures/example.json b/apps/testing/todos-list/cypress/fixtures/example.json deleted file mode 100644 index 02e425437..000000000 --- a/apps/testing/todos-list/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} diff --git a/apps/testing/todos-list/cypress/support/commands.ts b/apps/testing/todos-list/cypress/support/commands.ts deleted file mode 100644 index e6c897603..000000000 --- a/apps/testing/todos-list/cypress/support/commands.ts +++ /dev/null @@ -1,42 +0,0 @@ -/// -import { mount } from 'cypress/angular'; - -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** - -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface Chainable { - login(email: string, password: string): void; - mount: typeof mount; - } - } -} - -Cypress.Commands.add('mount', mount); - -// -// -- This is a parent command -- -Cypress.Commands.add('login', (email, password) => { - console.log('Custom command example: Login', email, password); -}); -// -// -- This is a child command -- -// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/apps/testing/todos-list/cypress/support/component-index.html b/apps/testing/todos-list/cypress/support/component-index.html deleted file mode 100644 index 8b1d58770..000000000 --- a/apps/testing/todos-list/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - testing-todos-list Components App - - -
    - - diff --git a/apps/testing/todos-list/cypress/support/component.ts b/apps/testing/todos-list/cypress/support/component.ts deleted file mode 100644 index e3684dbdc..000000000 --- a/apps/testing/todos-list/cypress/support/component.ts +++ /dev/null @@ -1,17 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.ts using ES2015 syntax: -import './commands'; diff --git a/apps/testing/todos-list/cypress/tsconfig.json b/apps/testing/todos-list/cypress/tsconfig.json deleted file mode 100644 index 918d96378..000000000 --- a/apps/testing/todos-list/cypress/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "outDir": "../../../dist/out-tsc", - "module": "commonjs", - "types": ["cypress", "node"], - "sourceMap": false - }, - "include": [ - "support/**/*.ts", - "../cypress.config.ts", - "../**/*.cy.ts", - "../**/*.cy.tsx", - "../**/*.cy.js", - "../**/*.cy.jsx", - "../**/*.d.ts" - ] -} diff --git a/apps/testing/todos-list/jest.config.ts b/apps/testing/todos-list/jest.config.ts deleted file mode 100644 index eb61074e5..000000000 --- a/apps/testing/todos-list/jest.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'testing-todos-list', - preset: '../../../jest.preset.js', - setupFilesAfterEnv: ['/src/test-setup.ts'], - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], -}; diff --git a/apps/testing/todos-list/project.json b/apps/testing/todos-list/project.json deleted file mode 100644 index c0ed6e5e1..000000000 --- a/apps/testing/todos-list/project.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "name": "testing-todos-list", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/testing/todos-list/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/testing/todos-list", - "index": "apps/testing/todos-list/src/index.html", - "main": "apps/testing/todos-list/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/testing/todos-list/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/testing/todos-list/src/favicon.ico", - "apps/testing/todos-list/src/assets" - ], - "styles": [ - "apps/testing/todos-list/src/styles.scss", - "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css" - ], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "testing-todos-list:build:production" - }, - "development": { - "browserTarget": "testing-todos-list:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "testing-todos-list:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/testing/todos-list/**/*.ts", - "apps/testing/todos-list/**/*.html" - ] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "apps/testing/todos-list/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - }, - "component-test": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/testing/todos-list/cypress.config.ts", - "testingType": "component", - "skipServe": true, - "devServerTarget": "testing-todos-list:build" - } - } - }, - "tags": [] -} diff --git a/apps/testing/todos-list/src/app/app.component.ts b/apps/testing/todos-list/src/app/app.component.ts deleted file mode 100644 index a3de393be..000000000 --- a/apps/testing/todos-list/src/app/app.component.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; - -@Component({ - selector: 'app-root', - standalone: true, - imports: [RouterOutlet], - template: ``, -}) -export class AppComponent {} diff --git a/apps/testing/todos-list/src/app/detail/detail.component.ts b/apps/testing/todos-list/src/app/detail/detail.component.ts deleted file mode 100644 index 5b5214c48..000000000 --- a/apps/testing/todos-list/src/app/detail/detail.component.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { AsyncPipe, NgIf } from '@angular/common'; -import { Component, inject } from '@angular/core'; -import { MatButtonModule } from '@angular/material/button'; -import { MatProgressBarModule } from '@angular/material/progress-bar'; -import { RouterLink } from '@angular/router'; -import { LetDirective } from '@ngrx/component'; -import { provideComponentStore } from '@ngrx/component-store'; -import { DetailStore } from './detail.store'; - -@Component({ - selector: 'app-detail', - standalone: true, - imports: [ - MatButtonModule, - RouterLink, - NgIf, - AsyncPipe, - MatProgressBarModule, - LetDirective, - ], - template: ` -

    Ticket Detail:

    - - -
    -
    Ticket: {{ ticket.id }}
    -
    - Description: {{ ticket.description }} -
    -
    - AssigneeId: {{ ticket.assigneeId }} -
    -
    - Is done: {{ ticket.completed }} -
    -
    -
    - - - `, - providers: [provideComponentStore(DetailStore)], - host: { - class: 'p-5 block', - }, -}) -export class DetailComponent { - vm$ = inject(DetailStore).vm$; -} diff --git a/apps/testing/todos-list/src/app/list/list.component.ts b/apps/testing/todos-list/src/app/list/list.component.ts deleted file mode 100644 index bc244859c..000000000 --- a/apps/testing/todos-list/src/app/list/list.component.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { NgFor, NgIf } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, ReactiveFormsModule } from '@angular/forms'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatProgressBarModule } from '@angular/material/progress-bar'; -import { LetDirective } from '@ngrx/component'; -import { provideComponentStore } from '@ngrx/component-store'; -import { TicketStore } from './ticket.store'; -import { AddComponent } from './ui/add.component'; -import { RowComponent } from './ui/row.component'; - -@Component({ - selector: 'app-list', - standalone: true, - imports: [ - ReactiveFormsModule, - AddComponent, - RowComponent, - MatFormFieldModule, - MatProgressBarModule, - NgIf, - NgFor, - MatInputModule, - LetDirective, - ], - template: ` -

    Tickets

    - - - Search - - - - - - - -
      - - -
    -
    - {{ vm.error }} -
    -
    - `, - providers: [provideComponentStore(TicketStore)], - host: { - class: 'p-5 block', - }, -}) -export class ListComponent implements OnInit { - ticketStore = inject(TicketStore); - readonly vm$ = this.ticketStore.vm$; - - search = new FormControl(); - - ngOnInit(): void { - this.ticketStore.search(this.search.valueChanges); - } -} diff --git a/apps/testing/todos-list/src/app/list/ui/add.component.ts b/apps/testing/todos-list/src/app/list/ui/add.component.ts deleted file mode 100644 index dabb008c0..000000000 --- a/apps/testing/todos-list/src/app/list/ui/add.component.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { NgIf } from '@angular/common'; -import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { - FormControl, - FormGroup, - ReactiveFormsModule, - Validators, -} from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; - -@Component({ - selector: 'app-add', - standalone: true, - imports: [ - ReactiveFormsModule, - MatFormFieldModule, - MatInputModule, - MatButtonModule, - NgIf, - ], - template: ` - - Description - - - Description is required - - - - `, -}) -export class AddComponent { - @Input() loading = false; - - @Output() addTicket = new EventEmitter(); - - form = new FormGroup({ - description: new FormControl(null, Validators.required), - }); - - submit() { - if (this.form.valid) { - this.addTicket.emit(this.form.value.description ?? ''); - } - } -} diff --git a/apps/testing/todos-list/src/index.html b/apps/testing/todos-list/src/index.html deleted file mode 100644 index 269ff341e..000000000 --- a/apps/testing/todos-list/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - TestingTodosList - - - - - - - - diff --git a/apps/testing/todos-list/src/main.ts b/apps/testing/todos-list/src/main.ts deleted file mode 100644 index 4ecc5cf6a..000000000 --- a/apps/testing/todos-list/src/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { appConfig } from './app/app.config'; -import { bootstrapApplication } from '@angular/platform-browser'; - -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); diff --git a/apps/testing/todos-list/tsconfig.app.json b/apps/testing/todos-list/tsconfig.app.json deleted file mode 100644 index 01a02ed77..000000000 --- a/apps/testing/todos-list/tsconfig.app.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../../dist/out-tsc", - "types": [] - }, - "files": ["src/main.ts"], - "include": ["src/**/*.d.ts"], - "exclude": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "cypress/**/*", - "cypress.config.ts", - "**/*.cy.ts", - "**/*.cy.js", - "**/*.cy.tsx", - "**/*.cy.jsx" - ] -} diff --git a/apps/testing/todos-list/tsconfig.json b/apps/testing/todos-list/tsconfig.json deleted file mode 100644 index 3879b94cd..000000000 --- a/apps/testing/todos-list/tsconfig.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "compilerOptions": { - "target": "es2022", - "useDefineForClassFields": false, - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.editor.json" - }, - { - "path": "./cypress/tsconfig.json" - } - ], - "extends": "../../../tsconfig.base.json", - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/apps/testing/todos-list/.eslintrc.json b/apps/typescript/15-function-overload/.eslintrc.json similarity index 100% rename from apps/testing/todos-list/.eslintrc.json rename to apps/typescript/15-function-overload/.eslintrc.json diff --git a/apps/typescript/15-function-overload/README.md b/apps/typescript/15-function-overload/README.md new file mode 100644 index 000000000..96ce65e9d --- /dev/null +++ b/apps/typescript/15-function-overload/README.md @@ -0,0 +1,13 @@ +# Function Overload + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve typescript-function-overload` +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/typescript/15-typescript-function-overload-fn/). diff --git a/apps/typescript/15-function-overload/project.json b/apps/typescript/15-function-overload/project.json new file mode 100644 index 000000000..95e554c3d --- /dev/null +++ b/apps/typescript/15-function-overload/project.json @@ -0,0 +1,72 @@ +{ + "name": "typescript-function-overload", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/typescript/15-function-overload/src", + "prefix": "app", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/typescript/15-function-overload", + "index": "apps/typescript/15-function-overload/src/index.html", + "main": "apps/typescript/15-function-overload/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/typescript/15-function-overload/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/typescript/15-function-overload/src/favicon.ico", + "apps/typescript/15-function-overload/src/assets" + ], + "styles": ["apps/typescript/15-function-overload/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "typescript-function-overload:build:production" + }, + "development": { + "buildTarget": "typescript-function-overload:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "typescript-function-overload:build" + } + } + } +} diff --git a/apps/typescript/overload/src/app/app.component.ts b/apps/typescript/15-function-overload/src/app/app.component.ts similarity index 100% rename from apps/typescript/overload/src/app/app.component.ts rename to apps/typescript/15-function-overload/src/app/app.component.ts diff --git a/apps/typescript/overload/src/app/vehicle.utils.ts b/apps/typescript/15-function-overload/src/app/vehicle.utils.ts similarity index 97% rename from apps/typescript/overload/src/app/vehicle.utils.ts rename to apps/typescript/15-function-overload/src/app/vehicle.utils.ts index ce5538650..bec95c08d 100644 --- a/apps/typescript/overload/src/app/vehicle.utils.ts +++ b/apps/typescript/15-function-overload/src/app/vehicle.utils.ts @@ -32,7 +32,7 @@ export function createVehicle( type: VehicleType, fuel?: Fuel, capacity?: number, - isPublicTransport?: boolean + isPublicTransport?: boolean, ): Vehicle { switch (type) { case 'bicycle': diff --git a/apps/typescript/15-function-overload/src/assets/.gitkeep b/apps/typescript/15-function-overload/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/typescript/15-function-overload/src/favicon.ico b/apps/typescript/15-function-overload/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/typescript/15-function-overload/src/favicon.ico differ diff --git a/apps/typescript/15-function-overload/src/index.html b/apps/typescript/15-function-overload/src/index.html new file mode 100644 index 000000000..37dd3a978 --- /dev/null +++ b/apps/typescript/15-function-overload/src/index.html @@ -0,0 +1,13 @@ + + + + + typescript-function-overload + + + + + + + + diff --git a/apps/typescript/15-function-overload/src/main.ts b/apps/typescript/15-function-overload/src/main.ts new file mode 100644 index 000000000..31c5da482 --- /dev/null +++ b/apps/typescript/15-function-overload/src/main.ts @@ -0,0 +1,4 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; + +bootstrapApplication(AppComponent).catch((err) => console.error(err)); diff --git a/apps/testing/router-outlet/src/styles.scss b/apps/typescript/15-function-overload/src/styles.scss similarity index 100% rename from apps/testing/router-outlet/src/styles.scss rename to apps/typescript/15-function-overload/src/styles.scss diff --git a/apps/typescript/15-function-overload/tsconfig.app.json b/apps/typescript/15-function-overload/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/typescript/15-function-overload/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/typescript/15-function-overload/tsconfig.editor.json b/apps/typescript/15-function-overload/tsconfig.editor.json new file mode 100644 index 000000000..4ee639340 --- /dev/null +++ b/apps/typescript/15-function-overload/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": [] + } +} diff --git a/apps/typescript/15-function-overload/tsconfig.json b/apps/typescript/15-function-overload/tsconfig.json new file mode 100644 index 000000000..51c7908c5 --- /dev/null +++ b/apps/typescript/15-function-overload/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/typescript/47-enums-vs-union-types/.eslintrc.json b/apps/typescript/47-enums-vs-union-types/.eslintrc.json new file mode 100644 index 000000000..8ebcbfd59 --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/typescript/47-enums-vs-union-types/README.md b/apps/typescript/47-enums-vs-union-types/README.md new file mode 100644 index 000000000..99aa0acf2 --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/README.md @@ -0,0 +1,13 @@ +# Enums vs Union Types + +> author: sven-brodny + +### Run Application + +```bash +npx nx serve typescript-enums-vs-union-types +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/typescript/47-enums-vs-union-types/). diff --git a/apps/typescript/47-enums-vs-union-types/project.json b/apps/typescript/47-enums-vs-union-types/project.json new file mode 100644 index 000000000..964750ac6 --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/project.json @@ -0,0 +1,69 @@ +{ + "name": "typescript-enums-vs-union-types", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/typescript/47-enums-vs-union-types/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/typescript/47-enums-vs-union-types", + "index": "apps/typescript/47-enums-vs-union-types/src/index.html", + "browser": "apps/typescript/47-enums-vs-union-types/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/typescript/47-enums-vs-union-types/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "apps/typescript/47-enums-vs-union-types/src/favicon.ico", + "apps/typescript/47-enums-vs-union-types/src/assets" + ], + "styles": ["apps/typescript/47-enums-vs-union-types/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "typescript-enums-vs-union-types:build:production" + }, + "development": { + "buildTarget": "typescript-enums-vs-union-types:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "typescript-enums-vs-union-types:build" + } + } + } +} diff --git a/apps/typescript/47-enums-vs-union-types/src/app/app.component.ts b/apps/typescript/47-enums-vs-union-types/src/app/app.component.ts new file mode 100644 index 000000000..05886724f --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/src/app/app.component.ts @@ -0,0 +1,82 @@ +import { Component, computed, signal } from '@angular/core'; + +enum Difficulty { + EASY = 'easy', + NORMAL = 'normal', +} + +enum Direction { + LEFT = 'left', + RIGHT = 'right', +} + +@Component({ + imports: [], + selector: 'app-root', + template: ` +
    +
    + + +
    +

    Selected Difficulty: {{ difficultyLabel() }}

    +
    + +
    +
    + + +
    +

    {{ directionLabel() }}

    +
    + `, + styles: ` + section { + @apply mx-auto my-5 flex w-fit flex-col items-center gap-2; + + > div { + @apply flex w-fit gap-5; + } + } + + button { + @apply rounded-md border px-4 py-2; + } + `, +}) +export class AppComponent { + readonly Difficulty = Difficulty; + readonly difficulty = signal(Difficulty.EASY); + + readonly Direction = Direction; + readonly direction = signal(undefined); + + readonly difficultyLabel = computed(() => { + switch (this.difficulty()) { + case Difficulty.EASY: + return Difficulty.EASY; + case Difficulty.NORMAL: + return Difficulty.NORMAL; + } + }); + + readonly directionLabel = computed(() => { + const prefix = 'You chose to go'; + switch (this.direction()) { + case Direction.LEFT: + return `${prefix} ${Direction.LEFT}`; + case Direction.RIGHT: + return `${prefix} ${Direction.RIGHT}`; + default: + return 'Choose a direction!'; + } + }); +} diff --git a/apps/typescript/47-enums-vs-union-types/src/app/app.config.ts b/apps/typescript/47-enums-vs-union-types/src/app/app.config.ts new file mode 100644 index 000000000..81a6edde4 --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [], +}; diff --git a/apps/typescript/47-enums-vs-union-types/src/assets/.gitkeep b/apps/typescript/47-enums-vs-union-types/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/typescript/47-enums-vs-union-types/src/favicon.ico b/apps/typescript/47-enums-vs-union-types/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/typescript/47-enums-vs-union-types/src/favicon.ico differ diff --git a/apps/typescript/47-enums-vs-union-types/src/index.html b/apps/typescript/47-enums-vs-union-types/src/index.html new file mode 100644 index 000000000..1b677a046 --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/src/index.html @@ -0,0 +1,13 @@ + + + + + typescript-enums-vs-union-types + + + + + + + + diff --git a/apps/typescript/47-enums-vs-union-types/src/main.ts b/apps/typescript/47-enums-vs-union-types/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/typescript/47-enums-vs-union-types/src/styles.scss b/apps/typescript/47-enums-vs-union-types/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/typescript/47-enums-vs-union-types/tailwind.config.js b/apps/typescript/47-enums-vs-union-types/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/typescript/47-enums-vs-union-types/tsconfig.app.json b/apps/typescript/47-enums-vs-union-types/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/typescript/47-enums-vs-union-types/tsconfig.editor.json b/apps/typescript/47-enums-vs-union-types/tsconfig.editor.json new file mode 100644 index 000000000..4ee639340 --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": { + "types": [] + } +} diff --git a/apps/typescript/47-enums-vs-union-types/tsconfig.json b/apps/typescript/47-enums-vs-union-types/tsconfig.json new file mode 100644 index 000000000..b94f8837d --- /dev/null +++ b/apps/typescript/47-enums-vs-union-types/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/apps/typescript/overload/.eslintrc.json b/apps/typescript/overload/.eslintrc.json deleted file mode 100644 index bf8df1428..000000000 --- a/apps/typescript/overload/.eslintrc.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "extends": ["../../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "app", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "app", - "style": "kebab-case" - } - ] - }, - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] -} diff --git a/apps/typescript/overload/README.md b/apps/typescript/overload/README.md deleted file mode 100644 index d181c0d52..000000000 --- a/apps/typescript/overload/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Function Overload - -> Author: Thomas Laforge - -### Run Application - -```bash -npx nx serve typescript-overload` -``` - -### Documentation and Instruction - -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/typescript/15-typescript-overload-fn/). diff --git a/apps/typescript/overload/project.json b/apps/typescript/overload/project.json deleted file mode 100644 index 1ac3f2703..000000000 --- a/apps/typescript/overload/project.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "name": "typescript-overload", - "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "sourceRoot": "apps/typescript/overload/src", - "prefix": "app", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/typescript/overload", - "index": "apps/typescript/overload/src/index.html", - "main": "apps/typescript/overload/src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "apps/typescript/overload/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/typescript/overload/src/favicon.ico", - "apps/typescript/overload/src/assets" - ], - "styles": ["apps/typescript/overload/src/styles.scss"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": false, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "typescript-overload:build:production" - }, - "development": { - "browserTarget": "typescript-overload:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "typescript-overload:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "apps/typescript/overload/**/*.ts", - "apps/typescript/overload/**/*.html" - ] - } - } - }, - "tags": [] -} diff --git a/apps/typescript/overload/src/index.html b/apps/typescript/overload/src/index.html deleted file mode 100644 index e501c90a4..000000000 --- a/apps/typescript/overload/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Overload - - - - - - - - diff --git a/apps/typescript/overload/src/styles.scss b/apps/typescript/overload/src/styles.scss deleted file mode 100644 index 90d4ee007..000000000 --- a/apps/typescript/overload/src/styles.scss +++ /dev/null @@ -1 +0,0 @@ -/* You can add global styles to this file, and also import other style files */ diff --git a/challenge-number.json b/challenge-number.json index 6e455d37f..9504fd39d 100644 --- a/challenge-number.json +++ b/challenge-number.json @@ -1,6 +1,6 @@ { - "total": 39, - "🟢": 14, - "🟠": 118, - "🔴": 207 + "total": 59, + "🟢": 22, + "🟠": 124, + "🔴": 212 } diff --git a/commitlint.config.js b/commitlint.config.js index 3347cb961..422b19445 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1 +1 @@ -module.exports = {extends: ['@commitlint/config-conventional']}; +module.exports = { extends: ['@commitlint/config-conventional'] }; diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index b14ac6c08..953462156 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -1,57 +1,124 @@ import starlight from '@astrojs/starlight'; import { defineConfig } from 'astro/config'; +import svelte from '@astrojs/svelte'; +import vercel from '@astrojs/vercel/serverless'; + +export const locales = { + root: { + label: 'English', + lang: 'en' + }, + es: { + label: 'Español', + lang: 'es' + }, + fr: { + label: 'Français', + lang: 'fr' + }, + pt: { + label: 'Português', + lang: 'pt' + }, + ru: { + label: 'Русский', + lang: 'ru' + }, + 'zh-cn': { + label: '简体中文', + lang: 'zh-CN' + } +}; + // https://astro.build/config export default defineConfig({ - integrations: [ - starlight({ - title: 'Angular Challenges', - logo: { - src: './public/angular-challenge.webp', - alt: 'angular challenges logo', + integrations: [starlight({ + title: 'Angular Challenges', + logo: { + src: './public/angular-challenge.webp', + alt: 'angular challenges logo' + }, + favicon: './angular-challenge.ico', + social: { + github: 'https://github.com/tomalaforge/angular-challenges', + linkedin: 'https://www.linkedin.com/in/thomas-laforge-2b05a945/', + twitter: 'https://twitter.com/laforge_toma' + }, + customCss: ['./src/styles/custom-css.css'], + sidebar: [{ + label: 'Guides', + autogenerate: { + directory: 'guides' }, - favicon: './angular-challenge.ico', - social: { - github: 'https://github.com/tomalaforge/angular-challenges', - linkedin: 'https://www.linkedin.com/in/thomas-laforge-2b05a945/', - twitter: 'https://twitter.com/laforge_toma', + translations: { + es: 'Guías', + fr: 'Guides', + pt: 'Guias', + ru: 'Руководство', + 'zh-CN': '指南' + } + }, + { + label: 'Leaderboard', + autogenerate: { + directory: 'leaderboard', + collapsed: true }, - customCss: ['./src/styles/custom-css.css'], - sidebar: [ - { - label: 'Guides', - autogenerate: { directory: 'guides' }, - }, - { - label: 'Challenges', - autogenerate: { directory: 'challenges' }, - }, - ], - head: [ - { - tag: 'script', - attrs: { - src: 'https://www.googletagmanager.com/gtag/js?id=G-6BXJ62W6G5', - async: true, - }, - }, - { - tag: 'script', - content: ` + translations: { + es: 'Leaderboard', + fr: 'Leaderboard', + pt: 'Tabela de Classificação', + ru: 'Leaderboard', + 'zh-CN': '排行榜' + } + }, + { + label: 'Challenges', + autogenerate: { + directory: 'challenges' + }, + translations: { + es: 'Desafíos', + fr: 'Challenges', + pt: 'Desafios', + ru: 'Задачи', + 'zh-CN': '挑战' + } + }], + head: [{ + tag: 'script', + attrs: { + src: 'https://www.googletagmanager.com/gtag/js?id=G-6BXJ62W6G5', + async: true + } + }, { + tag: 'script', + content: ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-6BXJ62W6G5'); - `, - }, - ], - components: { - MarkdownContent: './src/components/Content.astro', - TableOfContents: './src/components/TableOfContents.astro', - PageTitle: './src/components/PageTitle.astro', - MobileMenuFooter: './src/components/MobileMenuFooter.astro', - }, - }), - ], + ` + }, { + tag: 'script', + attrs: { + src: 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2438923752868254', + async: true + } + }], + components: { + MarkdownContent: './src/components/Content.astro', + TableOfContents: './src/components/TableOfContents.astro', + PageTitle: './src/components/PageTitle.astro', + MobileMenuFooter: './src/components/MobileMenuFooter.astro', + SiteTitle: './src/components/SiteTitle.astro', + Hero: './src/components/Hero.astro' + }, + defaultLocale: 'root', + locales + }), svelte()], + output: "hybrid", + adapter: vercel() }); diff --git a/docs/package-lock.json b/docs/package-lock.json index 84ed29bae..626127ffe 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8,10 +8,14 @@ "name": "angular-challenges-docs", "version": "0.0.1", "dependencies": { - "@astrojs/starlight": "^0.11.1", + "@astrojs/starlight": "^0.15.1", + "@astrojs/svelte": "^5.2.0", + "@astrojs/vercel": "^7.5.0", "@fontsource/ibm-plex-serif": "^5.0.8", - "astro": "^3.0.6", - "sharp": "^0.32.5" + "astro": "^4.0.0", + "sharp": "^0.32.5", + "svelte": "^4.2.12", + "typescript": "^5.4.3" } }, "node_modules/@ampproject/remapping": { @@ -27,467 +31,434 @@ } }, "node_modules/@astrojs/compiler": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.2.0.tgz", - "integrity": "sha512-JvmckEJgg8uXUw8Rs6VZDvN7LcweCHOdcxsCXpC+4KMDC9FaB5t9EH/NooSE+hu/rnACEhsXA3FKmf9wnhb7hA==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.7.0.tgz", + "integrity": "sha512-XpC8MAaWjD1ff6/IfkRq/5k1EFj6zhCNqXRd5J43SVJEBj/Bsmizkm8N0xOYscGcDFQkRgEw6/eKnI5x/1l6aA==" }, "node_modules/@astrojs/internal-helpers": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.2.1.tgz", - "integrity": "sha512-06DD2ZnItMwUnH81LBLco3tWjcZ1lGU9rLCCBaeUCGYe9cI0wKyY2W3kDyoW1I6GmcWgt1fu+D1CTvz+FIKf8A==" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.4.0.tgz", + "integrity": "sha512-6B13lz5n6BrbTqCTwhXjJXuR1sqiX/H6rTxzlXx+lN1NnV4jgnq/KJldCQaUWJzPL5SiWahQyinxAbxQtwgPHA==" }, "node_modules/@astrojs/markdown-remark": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-3.3.0.tgz", - "integrity": "sha512-ezFzEiZygc/ASe2Eul9v1yrTbNGqSbR348UGNXQ4Dtkx8MYRwfiBfmPm6VnEdfIGkW+bi5qIUReKfc7mPVUkIg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-4.0.1.tgz", + "integrity": "sha512-RU4ESnqvyLpj8WZs0n5elS6idaDdtIIm7mIpMaRNPCebpxMjfcfdwcmBwz83ktAj5d2eO5bC3z92TcGdli+lRw==", "dependencies": { "@astrojs/prism": "^3.0.0", "github-slugger": "^2.0.0", - "import-meta-resolve": "^3.0.0", + "import-meta-resolve": "^4.0.0", "mdast-util-definitions": "^6.0.0", - "rehype-raw": "^6.1.1", - "rehype-stringify": "^9.0.4", - "remark-gfm": "^3.0.1", - "remark-parse": "^10.0.2", - "remark-rehype": "^10.1.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.0", + "remark-gfm": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", "remark-smartypants": "^2.0.0", - "shikiji": "^0.6.8", - "unified": "^10.1.2", - "unist-util-visit": "^4.1.2", - "vfile": "^5.3.7" - }, - "peerDependencies": { - "astro": "^3.3.0" + "shikiji": "^0.6.13", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.1" } }, - "node_modules/@astrojs/mdx": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-1.1.2.tgz", - "integrity": "sha512-W+CXjdrfbIAUEDUedNOeZvpxyg+6Coji5NaOvF4e3jNhcOMtCWXpTKZTuzkFe25/uIzV2huuUl3ICJnp7qdWFA==", + "node_modules/@astrojs/markdown-remark/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/@astrojs/markdown-remark/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", "dependencies": { - "@astrojs/markdown-remark": "3.3.0", - "@mdx-js/mdx": "^2.3.0", - "acorn": "^8.10.0", - "es-module-lexer": "^1.3.0", - "estree-util-visit": "^1.2.1", - "github-slugger": "^2.0.0", - "gray-matter": "^4.0.3", - "hast-util-to-html": "^8.0.4", - "kleur": "^4.1.4", - "rehype-raw": "^6.1.1", - "remark-gfm": "^3.0.1", - "remark-smartypants": "^2.0.0", - "source-map": "^0.7.4", - "unist-util-visit": "^4.1.2", - "vfile": "^5.3.7" - }, - "engines": { - "node": ">=18.14.1" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "peerDependencies": { - "astro": "^3.3.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@astrojs/prism": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.0.0.tgz", - "integrity": "sha512-g61lZupWq1bYbcBnYZqdjndShr/J3l/oFobBKPA3+qMat146zce3nz2kdO4giGbhYDt4gYdhmoBz0vZJ4sIurQ==", + "node_modules/@astrojs/markdown-remark/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dependencies": { - "prismjs": "^1.29.0" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=18.14.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@astrojs/sitemap": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.0.1.tgz", - "integrity": "sha512-ErCthOQF0Yt6KkvaS+v/7CM6TxztOPHJjla4cbM3fBAFsDQbCS3tvoWSMqPJtmTFiy7veQ1eC5gH58FhPe85zg==", + "node_modules/@astrojs/markdown-remark/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "sitemap": "^7.1.1", - "zod": "3.21.1" + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@astrojs/starlight": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.11.1.tgz", - "integrity": "sha512-R1kBYnAOqPznsXCPLpSrbFQlKAy7jl7VIw+IY0s4tLfK5A9X6/nuX3Asm/kay6GJ035e9PHTljM5qFcAdJnPDw==", + "node_modules/@astrojs/markdown-remark/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "dependencies": { - "@astrojs/mdx": "^1.1.0", - "@astrojs/sitemap": "^3.0.0", - "@pagefind/default-ui": "^1.0.3", - "@types/mdast": "^3.0.11", - "bcp-47": "^2.1.0", - "execa": "^8.0.1", - "hast-util-select": "^5.0.5", - "hastscript": "^7.2.0", - "pagefind": "^1.0.3", - "rehype": "^12.0.1", - "remark-directive": "^2.0.1", - "unified": "^10.1.2", - "unist-util-remove": "^3.1.1", - "unist-util-visit": "^4.1.2", - "vfile": "^5.3.7" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, - "peerDependencies": { - "astro": "^3.2.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@astrojs/telemetry": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.0.3.tgz", - "integrity": "sha512-j19Cf5mfyLt9hxgJ9W/FMdAA5Lovfp7/CINNB/7V71GqvygnL7KXhRC3TzfB+PsVQcBtgWZzCXhUWRbmJ64Raw==", + "node_modules/@astrojs/markdown-remark/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "dependencies": { - "ci-info": "^3.8.0", - "debug": "^4.3.4", - "dlv": "^1.1.3", - "dset": "^3.1.2", - "is-docker": "^3.0.0", - "is-wsl": "^3.0.0", - "which-pm-runs": "^1.1.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, - "engines": { - "node": ">=18.14.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "node_modules/@astrojs/markdown-remark/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "node_modules/@astrojs/markdown-remark/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "node_modules/@astrojs/mdx": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-2.0.1.tgz", + "integrity": "sha512-lWbiNoVV/6DO8hAf6eZmcN28hY/herif9eglw2PXZ5lEPoRu175BvBtuNTt9rH9YA/Ldm5mkNXhvMWNEnMqJkw==", + "dependencies": { + "@astrojs/markdown-remark": "4.0.1", + "@mdx-js/mdx": "^3.0.0", + "acorn": "^8.11.2", + "es-module-lexer": "^1.4.1", + "estree-util-visit": "^2.0.0", + "github-slugger": "^2.0.0", + "gray-matter": "^4.0.3", + "hast-util-to-html": "^9.0.0", + "kleur": "^4.1.4", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.0", + "remark-smartypants": "^2.0.0", + "source-map": "^0.7.4", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.14.1" + }, + "peerDependencies": { + "astro": "^4.0.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "node_modules/@astrojs/mdx/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/@astrojs/mdx/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dependencies": { - "@babel/types": "^7.22.5" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "node_modules/@astrojs/mdx/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "node_modules/@astrojs/mdx/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "engines": { - "node": ">=6.9.0" + "node_modules/@astrojs/mdx/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@astrojs/mdx/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@astrojs/mdx/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "@babel/types": "^7.22.5" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "node_modules/@astrojs/prism": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.0.0.tgz", + "integrity": "sha512-g61lZupWq1bYbcBnYZqdjndShr/J3l/oFobBKPA3+qMat146zce3nz2kdO4giGbhYDt4gYdhmoBz0vZJ4sIurQ==", "dependencies": { - "@babel/types": "^7.22.15" + "prismjs": "^1.29.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.14.1" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "node_modules/@astrojs/sitemap": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.0.3.tgz", + "integrity": "sha512-+GRKp1yho9dpHBcMcU6JpbL41k0yYZghOkNsMRb8QIRflbGHvd787tdv9oIZ5NJj0SqAuOlqp2UpqLkJXuAe2A==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "engines": { - "node": ">=6.9.0" + "sitemap": "^7.1.1", + "zod": "^3.22.4" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "node_modules/@astrojs/starlight": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.15.1.tgz", + "integrity": "sha512-5AdySPQOG/+r1vHSNotQAGqhQIfF68hS8PfV+z4M2ewnrWoeCsHI3yYRFYgSRsVofcOEGTHiIryTRG/uRIvDkQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@astrojs/mdx": "^2.0.0", + "@astrojs/sitemap": "^3.0.3", + "@pagefind/default-ui": "^1.0.3", + "@types/hast": "^3.0.3", + "@types/mdast": "^4.0.3", + "astro-expressive-code": "^0.30.1", + "bcp-47": "^2.1.0", + "execa": "^8.0.1", + "hast-util-select": "^6.0.2", + "hastscript": "^8.0.0", + "mdast-util-directive": "^3.0.0", + "pagefind": "^1.0.3", + "rehype": "^13.0.1", + "remark-directive": "^3.0.0", + "unified": "^11.0.4", + "unist-util-remove": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.1" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "astro": "^4.0.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "node_modules/@astrojs/starlight/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/@astrojs/starlight/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "node_modules/@astrojs/starlight/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "node_modules/@astrojs/starlight/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "bin": { - "parser": "bin/babel-parser.js" + "node_modules/@astrojs/starlight/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, - "engines": { - "node": ">=6.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "node_modules/@astrojs/starlight/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz", - "integrity": "sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==", + "node_modules/@astrojs/starlight/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "node_modules/@astrojs/starlight/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "node_modules/@astrojs/svelte": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@astrojs/svelte/-/svelte-5.2.0.tgz", + "integrity": "sha512-GmwbXks2WMkmAfl0rlPM/2gA1RtmZzjGV2mOceV3g7QNyjIsSYBPKrlEnSFnuR+YMvlAtWdbMFBsb3gtGxnTTg==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" + "@sveltejs/vite-plugin-svelte": "^3.0.0", + "svelte2tsx": "^0.6.27" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.14.1" + }, + "peerDependencies": { + "astro": "^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.56", + "typescript": "^5.3.3" } }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, + "node_modules/@astrojs/svelte/node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "peer": true, "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", - "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -495,14 +466,15 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", - "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -510,14 +482,15 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", - "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -525,14 +498,15 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", - "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -540,14 +514,15 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", - "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -555,14 +530,15 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", - "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -570,14 +546,15 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", - "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -585,14 +562,15 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", - "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -600,14 +578,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", - "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -615,14 +594,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", - "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -630,14 +610,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", - "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -645,14 +626,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", - "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -660,14 +642,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", - "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -675,14 +658,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", - "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -690,14 +674,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", - "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -705,14 +690,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", - "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -720,14 +706,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", - "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -735,14 +722,15 @@ "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", - "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -750,14 +738,15 @@ "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", - "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -765,14 +754,15 @@ "os": [ "sunos" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", - "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -780,14 +770,15 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", - "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -795,14 +786,15 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", - "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "node_modules/@astrojs/svelte/node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -810,507 +802,2966 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } }, - "node_modules/@fontsource/ibm-plex-serif": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@fontsource/ibm-plex-serif/-/ibm-plex-serif-5.0.8.tgz", - "integrity": "sha512-KUp1E9Wzf2Umhr2SbpcF9HwgFJmuxvKAARmpl7GDDkIG30R1PMFJWxfSfQ7oX/oVBtomGq5RUTaMMUeE0ngEgw==" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "engines": { - "node": ">=6.0.0" - } + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.1.tgz", + "integrity": "sha512-4C4UERETjXpC4WpBXDbkgNVgHyWfG3B/NKY46e7w5H134UDOFqUJKpsLm0UYmuupW+aJmRgeScrDNfvZ5WV80A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "peer": true }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "engines": { - "node": ">=6.0.0" - } + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-android-arm64": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.1.tgz", + "integrity": "sha512-TrTaFJ9pXgfXEiJKQ3yQRelpQFqgRzVR9it8DbeRzG0RX7mKUy0bqhCFsgevwXLJepQKTnLl95TnPGf9T9AMOA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "peer": true }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.1.tgz", + "integrity": "sha512-fz7jN6ahTI3cKzDO2otQuybts5cyu0feymg0bjvYCBrZQ8tSgE8pc0sSNEuGvifrQJWiwx9F05BowihmLxeQKw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.1.tgz", + "integrity": "sha512-WTvdz7SLMlJpektdrnWRUN9C0N2qNHwNbWpNo0a3Tod3gb9leX+yrYdCeB7VV36OtoyiPAivl7/xZ3G1z5h20g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.1.tgz", + "integrity": "sha512-dBHQl+7wZzBYcIF6o4k2XkAfwP2ks1mYW2q/Gzv9n39uDcDiAGDqEyml08OdY0BIct0yLSPkDTqn4i6czpBLLw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.1.tgz", + "integrity": "sha512-bur4JOxvYxfrAmocRJIW0SADs3QdEYK6TQ7dTNz6Z4/lySeu3Z1H/+tl0a4qDYv0bCdBpUYM0sYa/X+9ZqgfSQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.1.tgz", + "integrity": "sha512-ssp77SjcDIUSoUyj7DU7/5iwM4ZEluY+N8umtCT9nBRs3u045t0KkW02LTyHouHDomnMXaXSZcCSr2bdMK63kA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.1.tgz", + "integrity": "sha512-Jv1DkIvwEPAb+v25/Unrnnq9BO3F5cbFPT821n3S5litkz+O5NuXuNhqtPx5KtcwOTtaqkTsO+IVzJOsxd11aQ==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.1.tgz", + "integrity": "sha512-zGRDulLTeDemR8DFYyFIQ8kMP02xpUsX4IBikc7lwL9PrwR3gWmX2NopqiGlI2ZVWMl15qZeUjumTwpv18N7sQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.1.tgz", + "integrity": "sha512-VTk/MveyPdMFkYJJPCkYBw07KcTkGU2hLEyqYMsU4NjiOfzoaDTW9PWGRsNwiOA3qI0k/JQPjkl/4FCK1smskQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.1.tgz", + "integrity": "sha512-L+hX8Dtibb02r/OYCsp4sQQIi3ldZkFI0EUkMTDwRfFykXBPptoz/tuuGqEd3bThBSLRWPR6wsixDSgOx/U3Zw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.1.tgz", + "integrity": "sha512-+dI2jVPfM5A8zme8riEoNC7UKk0Lzc7jCj/U89cQIrOjrZTCWZl/+IXUeRT2rEZ5j25lnSA9G9H1Ob9azaF/KQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.1.tgz", + "integrity": "sha512-YY1Exxo2viZ/O2dMHuwQvimJ0SqvL+OAWQLLY6rvXavgQKjhQUzn7nc1Dd29gjB5Fqi00nrBWctJBOyfVMIVxw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@astrojs/svelte/node_modules/@sveltejs/vite-plugin-svelte": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-3.0.2.tgz", + "integrity": "sha512-MpmF/cju2HqUls50WyTHQBZUV3ovV/Uk8k66AN2gwHogNAG8wnW8xtZDhzNBsFJJuvmq1qnzA5kE7YfMJNFv2Q==", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@sveltejs/vite-plugin-svelte-inspector": "^2.0.0", + "debug": "^4.3.4", + "deepmerge": "^4.3.1", + "kleur": "^4.1.5", + "magic-string": "^0.30.5", + "svelte-hmr": "^0.15.3", + "vitefu": "^0.2.5" + }, + "engines": { + "node": "^18.0.0 || >=20" + }, + "peerDependencies": { + "svelte": "^4.0.0 || ^5.0.0-next.0", + "vite": "^5.0.0" } }, - "node_modules/@mdx-js/mdx": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz", - "integrity": "sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==", + "node_modules/@astrojs/svelte/node_modules/@sveltejs/vite-plugin-svelte-inspector": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-2.0.0.tgz", + "integrity": "sha512-gjr9ZFg1BSlIpfZ4PRewigrvYmHWbDrq2uvvPB1AmTWKuM+dI1JXQSUu2pIrYLb/QncyiIGkFDFKTwJ0XqQZZg==", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/mdx": "^2.0.0", - "estree-util-build-jsx": "^2.0.0", - "estree-util-is-identifier-name": "^2.0.0", - "estree-util-to-js": "^1.1.0", - "estree-walker": "^3.0.0", - "hast-util-to-estree": "^2.0.0", - "markdown-extensions": "^1.0.0", - "periscopic": "^3.0.0", - "remark-mdx": "^2.0.0", - "remark-parse": "^10.0.0", - "remark-rehype": "^10.0.0", - "unified": "^10.0.0", - "unist-util-position-from-estree": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "unist-util-visit": "^4.0.0", - "vfile": "^5.0.0" + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.0.0 || >=20" + }, + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^3.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.0", + "vite": "^5.0.0" + } + }, + "node_modules/@astrojs/svelte/node_modules/@types/node": { + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@astrojs/svelte/node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "hasInstallScript": true, + "peer": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/@astrojs/svelte/node_modules/rollup": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.1.tgz", + "integrity": "sha512-hFi+fU132IvJ2ZuihN56dwgpltpmLZHZWsx27rMCTZ2sYwrqlgL5sECGy1eeV2lAihD8EzChBVVhsXci0wD4Tg==", + "peer": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.13.1", + "@rollup/rollup-android-arm64": "4.13.1", + "@rollup/rollup-darwin-arm64": "4.13.1", + "@rollup/rollup-darwin-x64": "4.13.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.1", + "@rollup/rollup-linux-arm64-gnu": "4.13.1", + "@rollup/rollup-linux-arm64-musl": "4.13.1", + "@rollup/rollup-linux-riscv64-gnu": "4.13.1", + "@rollup/rollup-linux-s390x-gnu": "4.13.1", + "@rollup/rollup-linux-x64-gnu": "4.13.1", + "@rollup/rollup-linux-x64-musl": "4.13.1", + "@rollup/rollup-win32-arm64-msvc": "4.13.1", + "@rollup/rollup-win32-ia32-msvc": "4.13.1", + "@rollup/rollup-win32-x64-msvc": "4.13.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/@astrojs/svelte/node_modules/vite": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.6.tgz", + "integrity": "sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA==", + "peer": true, + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.36", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@astrojs/telemetry": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.0.4.tgz", + "integrity": "sha512-A+0c7k/Xy293xx6odsYZuXiaHO0PL+bnDoXOc47sGDF5ffIKdKQGRPFl2NMlCF4L0NqN4Ynbgnaip+pPF0s7pQ==", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "ci-info": "^3.8.0", + "debug": "^4.3.4", + "dlv": "^1.1.3", + "dset": "^3.1.2", + "is-docker": "^3.0.0", + "is-wsl": "^3.0.0", + "which-pm-runs": "^1.1.0" }, "engines": { - "node": ">= 8" + "node": ">=18.14.1" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@astrojs/telemetry/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@astrojs/vercel": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@astrojs/vercel/-/vercel-7.5.0.tgz", + "integrity": "sha512-RYFZNHkfNgFNb41nblG26ubw5924hAjLYs+Bpp4kttcsYJAX/wavIfDbfZQ/XesDTKwIH+Gi/+3c5bldZePFDA==", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@astrojs/internal-helpers": "0.4.0", + "@vercel/analytics": "^1.0.2", + "@vercel/edge": "^1.1.1", + "@vercel/nft": "^0.26.4", + "esbuild": "^0.19.6", + "fast-glob": "^3.3.2", + "set-cookie-parser": "^2.6.0", + "web-vitals": "^3.4.0" + }, + "peerDependencies": { + "astro": "^4.2.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/@pagefind/darwin-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.0.3.tgz", - "integrity": "sha512-vsHDtvao3W4iFCxVc4S0BVhpj3E2MAoIVM7RmuQfGp1Ng22nGLRaMP6FguLO8TMabRJdvp4SVr227hL4WGKOHA==", - "cpu": [ - "arm64" + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "dependencies": { + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz", + "integrity": "sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dependencies": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz", + "integrity": "sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.10.tgz", + "integrity": "sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz", + "integrity": "sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.10.tgz", + "integrity": "sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz", + "integrity": "sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz", + "integrity": "sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz", + "integrity": "sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz", + "integrity": "sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz", + "integrity": "sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz", + "integrity": "sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz", + "integrity": "sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz", + "integrity": "sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz", + "integrity": "sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz", + "integrity": "sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz", + "integrity": "sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz", + "integrity": "sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz", + "integrity": "sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz", + "integrity": "sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz", + "integrity": "sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz", + "integrity": "sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz", + "integrity": "sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz", + "integrity": "sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz", + "integrity": "sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@expressive-code/core": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.30.1.tgz", + "integrity": "sha512-z11G1lfzzuTJ63C4dGPUIEKxJse5eKrVxqxQJRiuCDH8hPqfIQs/+by04UceSWB0dt5SIFsL5J+7HvCycbc1iA==", + "dependencies": { + "@ctrl/tinycolor": "^3.6.0", + "hast-util-to-html": "^8.0.4", + "hastscript": "^7.2.0", + "postcss": "^8.4.21", + "postcss-nested": "^6.0.1" + } + }, + "node_modules/@expressive-code/core/node_modules/@types/hast": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.8.tgz", + "integrity": "sha512-aMIqAlFd2wTIDZuvLbhUT+TGvMxrNC8ECUIVtH6xxy0sQLs3iu6NO8Kp/VT5je7i5ufnebXzdV1dNDMnvaH6IQ==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@expressive-code/core/node_modules/hast-util-from-parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", + "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "hastscript": "^7.0.0", + "property-information": "^6.0.0", + "vfile": "^5.0.0", + "vfile-location": "^4.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/core/node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "dependencies": { + "@types/hast": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/core/node_modules/hast-util-raw": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz", + "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/parse5": "^6.0.0", + "hast-util-from-parse5": "^7.0.0", + "hast-util-to-parse5": "^7.0.0", + "html-void-elements": "^2.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile": "^5.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/core/node_modules/hast-util-to-html": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-8.0.4.tgz", + "integrity": "sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-raw": "^7.0.0", + "hast-util-whitespace": "^2.0.0", + "html-void-elements": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/core/node_modules/hast-util-to-parse5": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz", + "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/core/node_modules/hast-util-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/core/node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/core/node_modules/html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@expressive-code/core/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/@expressive-code/core/node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/core/node_modules/vfile-location": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", + "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", + "dependencies": { + "@types/unist": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/plugin-frames": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.30.1.tgz", + "integrity": "sha512-fBqd+NWcmlP63q8kNi73b6EuwWZwb+8OIhqWEsEQ/lsoOmT8FVYqsnH+M+TRC9or+U0PNd7Po/ojcFNnS0TAIQ==", + "dependencies": { + "@expressive-code/core": "^0.30.1", + "hastscript": "^7.2.0" + } + }, + "node_modules/@expressive-code/plugin-frames/node_modules/@types/hast": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.8.tgz", + "integrity": "sha512-aMIqAlFd2wTIDZuvLbhUT+TGvMxrNC8ECUIVtH6xxy0sQLs3iu6NO8Kp/VT5je7i5ufnebXzdV1dNDMnvaH6IQ==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@expressive-code/plugin-frames/node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "dependencies": { + "@types/hast": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/plugin-frames/node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/plugin-shiki": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.30.1.tgz", + "integrity": "sha512-VoJZWZ1wjW/I+CsHg4/RwurrHdtnF5C5fbXESQCQlnXWOhWBfJnOX1ilx5B11gsH5kEWNoD5WRAt8t0L0V/VJA==", + "dependencies": { + "@expressive-code/core": "^0.30.1", + "shikiji": "^0.8.0" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/shikiji": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.8.7.tgz", + "integrity": "sha512-j5usxwI0yHkDTHOuhuSJl9+wT5CNYeYO82dJMSJBlJ/NYT5SIebGcPoL6y9QOyH15wGrJC4LOP2nz5k8mUDGRQ==", + "dependencies": { + "hast-util-to-html": "^9.0.0" + } + }, + "node_modules/@expressive-code/plugin-text-markers": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.30.1.tgz", + "integrity": "sha512-Dtw2lIsAfcfWy/qUhrEW1NwZdgMsI+qeHQ/7Do+W9fMBIoIIHh2GLwmhwkBitoOvLgOJQWsNoBvT42LUp2+16g==", + "dependencies": { + "@expressive-code/core": "^0.30.1", + "hastscript": "^7.2.0", + "unist-util-visit-parents": "^5.1.3" + } + }, + "node_modules/@expressive-code/plugin-text-markers/node_modules/@types/hast": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.8.tgz", + "integrity": "sha512-aMIqAlFd2wTIDZuvLbhUT+TGvMxrNC8ECUIVtH6xxy0sQLs3iu6NO8Kp/VT5je7i5ufnebXzdV1dNDMnvaH6IQ==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@expressive-code/plugin-text-markers/node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "dependencies": { + "@types/hast": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@expressive-code/plugin-text-markers/node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@fontsource/ibm-plex-serif": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@fontsource/ibm-plex-serif/-/ibm-plex-serif-5.0.8.tgz", + "integrity": "sha512-KUp1E9Wzf2Umhr2SbpcF9HwgFJmuxvKAARmpl7GDDkIG30R1PMFJWxfSfQ7oX/oVBtomGq5RUTaMMUeE0ngEgw==" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mdx-js/mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.0.tgz", + "integrity": "sha512-Icm0TBKBLYqroYbNW3BPnzMGn+7mwpQOK310aZ7+fkCtiU3aqv2cdcX+nd0Ydo3wI5Rx8bX2Z2QmGb/XcAClCw==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-to-js": "^2.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/@mdx-js/mdx/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pagefind/darwin-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.0.3.tgz", + "integrity": "sha512-vsHDtvao3W4iFCxVc4S0BVhpj3E2MAoIVM7RmuQfGp1Ng22nGLRaMP6FguLO8TMabRJdvp4SVr227hL4WGKOHA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/darwin-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.0.3.tgz", + "integrity": "sha512-NhEXHHYmB/hT6lx5rCcmnVTxH+uIkMAd43bzEqMwHQosqTZEIQfwihmV39H+m8yo7jFvz3zRbJNzhAh7G4PiwA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/default-ui": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.0.3.tgz", + "integrity": "sha512-WieFJXvezyvjZh49I8j7a7Kz3LsXYY2Uep3IWvG5NG05mmiurURXjXc+KyrpIp/iAycSnjrC1TDJ8CdES/ee3A==" + }, + "node_modules/@pagefind/linux-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.0.3.tgz", + "integrity": "sha512-RGsMt4AmGT8WxCSeP09arU7Za6Vf/We4TWHVSbY7vDMuwWql9Ngoib/q1cP9dIAIMdkXh9ePG/S3mGnJYsdzuQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/linux-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.0.3.tgz", + "integrity": "sha512-o+VCKaqImL42scSH1n5gUfppYSNyu3BuGTvtKKgWHmycbL+A3fkFH+ZOFbaLeN7LVTvJqJIOYbk4j2yaq9784Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/windows-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.0.3.tgz", + "integrity": "sha512-S+Yq4FyvXJm4F+iN/wRiLvEEF8Xs9lTKGtQGaRHXJslQyl65dytDDPIULXJXIadrDbnMrnTt4C2YHmEUIyUIHg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.2.tgz", + "integrity": "sha512-3XFIDKWMFZrMnao1mJhnOT1h2g0169Os848NhhmGweEcfJ4rCi+3yMCOLG4zA61rbJdkcrM/DjVZm9Hg5p5w7g==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.2.tgz", + "integrity": "sha512-GdxxXbAuM7Y/YQM9/TwwP+L0omeE/lJAR1J+olu36c3LqqZEBdsIWeQ91KBe6nxwOnb06Xh7JS2U5ooWU5/LgQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.2.tgz", + "integrity": "sha512-mCMlpzlBgOTdaFs83I4XRr8wNPveJiJX1RLfv4hggyIVhfB5mJfN4P8Z6yKh+oE4Luz+qq1P3kVdWrCKcMYrrA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.2.tgz", + "integrity": "sha512-yUoEvnH0FBef/NbB1u6d3HNGyruAKnN74LrPAfDQL3O32e3k3OSfLrPgSJmgb3PJrBZWfPyt6m4ZhAFa2nZp2A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.2.tgz", + "integrity": "sha512-GYbLs5ErswU/Xs7aGXqzc3RrdEjKdmoCrgzhJWyFL0r5fL3qd1NPcDKDowDnmcoSiGJeU68/Vy+OMUluRxPiLQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.2.tgz", + "integrity": "sha512-L1+D8/wqGnKQIlh4Zre9i4R4b4noxzH5DDciyahX4oOz62CphY7WDWqJoQ66zNR4oScLNOqQJfNSIAe/6TPUmQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.2.tgz", + "integrity": "sha512-tK5eoKFkXdz6vjfkSTCupUzCo40xueTOiOO6PeEIadlNBkadH1wNOH8ILCPIl8by/Gmb5AGAeQOFeLev7iZDOA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.13.2.tgz", + "integrity": "sha512-zvXvAUGGEYi6tYhcDmb9wlOckVbuD+7z3mzInCSTACJ4DQrdSLPNUeDIcAQW39M3q6PDquqLWu7pnO39uSMRzQ==", + "cpu": [ + "ppc64le" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.2.tgz", + "integrity": "sha512-C3GSKvMtdudHCN5HdmAMSRYR2kkhgdOfye4w0xzyii7lebVr4riCgmM6lRiSCnJn2w1Xz7ZZzHKuLrjx5620kw==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.13.1.tgz", + "integrity": "sha512-U564BrhEfaNChdATQaEODtquCC7Ez+8Hxz1h5MAdMYj0AqD0GA9rHCpElajb/sQcaFL6NXmHc5O+7FXpWMa73Q==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.2.tgz", + "integrity": "sha512-xXMLUAMzrtsvh3cZ448vbXqlUa7ZL8z0MwHp63K2IIID2+DeP5iWIT6g1SN7hg1VxPzqx0xZdiDM9l4n9LRU1A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.2.tgz", + "integrity": "sha512-M/JYAWickafUijWPai4ehrjzVPKRCyDb1SLuO+ZyPfoXgeCEAlgPkNXewFZx0zcnoIe3ay4UjXIMdXQXOZXWqA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.2.tgz", + "integrity": "sha512-2YWwoVg9KRkIKaXSh0mz3NmfurpmYoBBTAXA9qt7VXk0Xy12PoOP40EFuau+ajgALbbhi4uTj3tSG3tVseCjuA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.2.tgz", + "integrity": "sha512-2FSsE9aQ6OWD20E498NYKEQLneShWes0NGMPQwxWOdws35qQXH+FplabOSP5zEe1pVjurSDOGEVCE2agFwSEsw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.2.tgz", + "integrity": "sha512-7h7J2nokcdPePdKykd8wtc8QqqkqxIrUz7MHj6aNr8waBRU//NLDVnNjQnqQO6fqtjrtCdftpbTuOKAyrAQETQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.2.1.tgz", + "integrity": "sha512-KaIS0H4EQ3KI2d++TjYqRNgwp8E3M/68e9veR4QtInzA7kKFgcjeiJqb80fuXW+blDy5fmd11PN9g9soz/3ANQ==" + }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.3.tgz", + "integrity": "sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.3.tgz", + "integrity": "sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz", + "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.10.tgz", + "integrity": "sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg==" + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/nlcst": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-1.0.2.tgz", + "integrity": "sha512-ykxL/GDDUhqikjU0LIywZvEwb1NTYXTEWf+XgMSS2o6IXIakafPccxZmxgZcvJPZ3yFl2kdL1gJZz3U3iZF3QA==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + }, + "node_modules/@types/parse5": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", + "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.8.tgz", + "integrity": "sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/@vercel/analytics": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.2.2.tgz", + "integrity": "sha512-X0rctVWkQV1e5Y300ehVNqpOfSOufo7ieA5PIdna8yX/U7Vjz0GFsGf4qvAhxV02uQ2CVt7GYcrFfddXXK2Y4A==", + "dependencies": { + "server-only": "^0.0.1" + }, + "peerDependencies": { + "next": ">= 13", + "react": "^18 || ^19" + }, + "peerDependenciesMeta": { + "next": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/@vercel/edge": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@vercel/edge/-/edge-1.1.1.tgz", + "integrity": "sha512-NtKiIbn9Cq6HWGy+qRudz28mz5nxfOJWls5Pnckjw1yCfSX8rhXdvY/il3Sy3Zd5n/sKCM2h7VSCCpJF/oaDrQ==" + }, + "node_modules/@vercel/nft": { + "version": "0.26.4", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.26.4.tgz", + "integrity": "sha512-j4jCOOXke2t8cHZCIxu1dzKLHLcFmYzC3yqAK6MfZznOL1QIJKd0xcFsXK3zcqzU7ScsE2zWkiMMNHGMHgp+FA==", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.5", + "@rollup/pluginutils": "^4.0.0", + "acorn": "^8.6.0", + "acorn-import-attributes": "^1.9.2", + "async-sema": "^3.1.1", + "bindings": "^1.4.0", + "estree-walker": "2.0.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.2", + "node-gyp-build": "^4.2.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "nft": "out/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vercel/nft/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.4.tgz", + "integrity": "sha512-dNIX/5UEnZvVL94dV2scl4VIooK36D8AteP4xiz7cPKhDbhLhSuWkzG580g+Q7TXJklp+Z21SiaK7/HpLO84Qg==", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/astring": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", + "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/astro": { + "version": "4.5.12", + "resolved": "https://registry.npmjs.org/astro/-/astro-4.5.12.tgz", + "integrity": "sha512-xIJcFI2hbyV8+h5pWjL7SKD1jIP0K01fYVAH+gdAt0mJaXy+u8Mj+goD0cPlK6sEaykR+7zxQLYGKJ44U4qarg==", + "dependencies": { + "@astrojs/compiler": "^2.7.0", + "@astrojs/internal-helpers": "0.4.0", + "@astrojs/markdown-remark": "4.3.2", + "@astrojs/telemetry": "3.0.4", + "@babel/core": "^7.24.3", + "@babel/generator": "^7.23.3", + "@babel/parser": "^7.23.3", + "@babel/plugin-transform-react-jsx": "^7.22.5", + "@babel/traverse": "^7.23.3", + "@babel/types": "^7.23.3", + "@types/babel__core": "^7.20.4", + "acorn": "^8.11.2", + "aria-query": "^5.3.0", + "axobject-query": "^4.0.0", + "boxen": "^7.1.1", + "chokidar": "^3.5.3", + "ci-info": "^4.0.0", + "clsx": "^2.0.0", + "common-ancestor-path": "^1.0.1", + "cookie": "^0.6.0", + "cssesc": "^3.0.0", + "debug": "^4.3.4", + "deterministic-object-hash": "^2.0.1", + "devalue": "^4.3.2", + "diff": "^5.1.0", + "dlv": "^1.1.3", + "dset": "^3.1.3", + "es-module-lexer": "^1.4.1", + "esbuild": "^0.19.6", + "estree-walker": "^3.0.3", + "execa": "^8.0.1", + "fast-glob": "^3.3.2", + "flattie": "^1.1.0", + "github-slugger": "^2.0.0", + "gray-matter": "^4.0.3", + "html-escaper": "^3.0.3", + "http-cache-semantics": "^4.1.1", + "js-yaml": "^4.1.0", + "kleur": "^4.1.4", + "magic-string": "^0.30.3", + "mime": "^3.0.0", + "ora": "^7.0.1", + "p-limit": "^5.0.0", + "p-queue": "^8.0.1", + "path-to-regexp": "^6.2.1", + "preferred-pm": "^3.1.2", + "prompts": "^2.4.2", + "rehype": "^13.0.1", + "resolve": "^1.22.4", + "semver": "^7.5.4", + "shiki": "^1.1.2", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0", + "tsconfck": "^3.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.1", + "vite": "^5.1.4", + "vitefu": "^0.2.5", + "which-pm": "^2.1.1", + "yargs-parser": "^21.1.1", + "zod": "^3.22.4", + "zod-to-json-schema": "^3.22.4" + }, + "bin": { + "astro": "astro.js" + }, + "engines": { + "node": ">=18.14.1", + "npm": ">=6.14.0" + }, + "optionalDependencies": { + "sharp": "^0.32.6" + } + }, + "node_modules/astro-expressive-code": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.30.1.tgz", + "integrity": "sha512-Dr3VbK4HvIXTT8rsvd8PuRW4uZOpfRz9J8noVSSxmx7/M7o73SBtqauBYvxXpGHnagTJPGzYOa9BQS7jDHNUVw==", + "dependencies": { + "remark-expressive-code": "^0.30.1" + }, + "peerDependencies": { + "astro": "^3.3.0 || ^4.0.0-beta" + } + }, + "node_modules/astro/node_modules/@astrojs/markdown-remark": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-4.3.2.tgz", + "integrity": "sha512-4Oa4VaYiBd0MatB+rWIU/0A8pZH/sK3c2QkRYb+OO2lPl+qzevJtWaZY8hAQc4qurIOlRdn6B6ofDAGhWw+DSg==", + "dependencies": { + "@astrojs/prism": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.0", + "hast-util-to-text": "^4.0.0", + "import-meta-resolve": "^4.0.0", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.0", + "remark-gfm": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "remark-smartypants": "^2.0.0", + "shiki": "^1.1.2", + "unified": "^11.0.4", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.0", + "vfile": "^6.0.1" + } + }, + "node_modules/astro/node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/astro/node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" ], "optional": true, "os": [ - "darwin" - ] + "openbsd" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@pagefind/darwin-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.0.3.tgz", - "integrity": "sha512-NhEXHHYmB/hT6lx5rCcmnVTxH+uIkMAd43bzEqMwHQosqTZEIQfwihmV39H+m8yo7jFvz3zRbJNzhAh7G4PiwA==", + "node_modules/astro/node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], "optional": true, "os": [ - "darwin" - ] - }, - "node_modules/@pagefind/default-ui": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.0.3.tgz", - "integrity": "sha512-WieFJXvezyvjZh49I8j7a7Kz3LsXYY2Uep3IWvG5NG05mmiurURXjXc+KyrpIp/iAycSnjrC1TDJ8CdES/ee3A==" + "sunos" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@pagefind/linux-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.0.3.tgz", - "integrity": "sha512-RGsMt4AmGT8WxCSeP09arU7Za6Vf/We4TWHVSbY7vDMuwWql9Ngoib/q1cP9dIAIMdkXh9ePG/S3mGnJYsdzuQ==", + "node_modules/astro/node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], "optional": true, "os": [ - "linux" - ] + "win32" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@pagefind/linux-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.0.3.tgz", - "integrity": "sha512-o+VCKaqImL42scSH1n5gUfppYSNyu3BuGTvtKKgWHmycbL+A3fkFH+ZOFbaLeN7LVTvJqJIOYbk4j2yaq9784Q==", + "node_modules/astro/node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ - "x64" + "ia32" ], "optional": true, "os": [ - "linux" - ] + "win32" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@pagefind/windows-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.0.3.tgz", - "integrity": "sha512-S+Yq4FyvXJm4F+iN/wRiLvEEF8Xs9lTKGtQGaRHXJslQyl65dytDDPIULXJXIadrDbnMrnTt4C2YHmEUIyUIHg==", + "node_modules/astro/node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], "optional": true, "os": [ "win32" - ] - }, - "node_modules/@types/acorn": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", - "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", - "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", - "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", - "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", - "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/debug": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", - "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", - "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.1.tgz", - "integrity": "sha512-sHyakZlAezNFxmYRo0fopDZW+XvK6ipeZkkp5EAOLjdPfZp8VjZBJ67vSRI99RSCAoqXVmXOHS4fnWoxpuGQtQ==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/hast": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.6.tgz", - "integrity": "sha512-47rJE80oqPmFdVDCD7IheXBrVdwuBgsYwoczFvKmwfo2Mzsnt+V9OONsYauFmICb6lQPpCuXYJWejBNs4pDJRg==", - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/@types/mdast": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.13.tgz", - "integrity": "sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==", - "dependencies": { - "@types/unist": "^2" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/mdx": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.8.tgz", - "integrity": "sha512-r7/zWe+f9x+zjXqGxf821qz++ld8tp6Z4jUS6qmPZUXH6tfh4riXOhAqb12tWGWAevCFtMt1goLWkQMqIJKpsA==" - }, - "node_modules/@types/ms": { - "version": "0.7.32", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz", - "integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==" + "node_modules/astro/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.13.2.tgz", + "integrity": "sha512-l4U0KDFwzD36j7HdfJ5/TveEQ1fUTjFFQP5qIt9gBqBgu1G8/kCaq5Ok05kd5TG9F8Lltf3MoYsUMw3rNlJ0Yg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/nlcst": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-1.0.2.tgz", - "integrity": "sha512-ykxL/GDDUhqikjU0LIywZvEwb1NTYXTEWf+XgMSS2o6IXIakafPccxZmxgZcvJPZ3yFl2kdL1gJZz3U3iZF3QA==", + "node_modules/astro/node_modules/@types/node": { + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "optional": true, + "peer": true, "dependencies": { - "@types/unist": "^2" + "undici-types": "~5.26.4" } }, - "node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" - }, - "node_modules/@types/parse5": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", - "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" + "node_modules/astro/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" }, - "node_modules/@types/sax": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.5.tgz", - "integrity": "sha512-9jWta97bBVC027/MShr3gLab8gPhKy4l6qpb+UJLF5pDm3501NvA7uvqVCW+REFtx00oTi6Cq9JzLwgq6evVgw==", + "node_modules/astro/node_modules/rollup": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.2.tgz", + "integrity": "sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g==", "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/unist": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.8.tgz", - "integrity": "sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==" - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" - }, - "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "@types/estree": "1.0.5" + }, "bin": { - "acorn": "bin/acorn" + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.13.2", + "@rollup/rollup-android-arm64": "4.13.2", + "@rollup/rollup-darwin-arm64": "4.13.2", + "@rollup/rollup-darwin-x64": "4.13.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.2", + "@rollup/rollup-linux-arm64-gnu": "4.13.2", + "@rollup/rollup-linux-arm64-musl": "4.13.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.13.2", + "@rollup/rollup-linux-riscv64-gnu": "4.13.2", + "@rollup/rollup-linux-s390x-gnu": "4.13.2", + "@rollup/rollup-linux-x64-gnu": "4.13.2", + "@rollup/rollup-linux-x64-musl": "4.13.2", + "@rollup/rollup-win32-arm64-msvc": "4.13.2", + "@rollup/rollup-win32-ia32-msvc": "4.13.2", + "@rollup/rollup-win32-x64-msvc": "4.13.2", + "fsevents": "~2.3.2" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "node_modules/astro/node_modules/string-width": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", + "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/astro/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/astro/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/astro/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "ansi-regex": "^5.0.1" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" + "node_modules/astro/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/astro/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "dependencies": { - "color-convert": "^1.9.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, - "engines": { - "node": ">=4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/astro/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": ">= 8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/array-iterate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", - "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "node_modules/astro/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/astring": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", - "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", + "node_modules/astro/node_modules/vite": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.6.tgz", + "integrity": "sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA==", + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.36", + "rollup": "^4.13.0" + }, "bin": { - "astring": "bin/astring" + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/astro": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/astro/-/astro-3.3.1.tgz", - "integrity": "sha512-PzXJN8IIjQrxf+D39utnBtxscdqizwslOKoXXGtVFCA66IPh37HzGts0VLtB/kSf8ouTojk5JBQWbevDiW53VQ==", - "dependencies": { - "@astrojs/compiler": "^2.1.0", - "@astrojs/internal-helpers": "0.2.1", - "@astrojs/markdown-remark": "3.3.0", - "@astrojs/telemetry": "3.0.3", - "@babel/core": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/parser": "^7.22.10", - "@babel/plugin-transform-react-jsx": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10", - "@types/babel__core": "^7.20.1", - "acorn": "^8.10.0", - "boxen": "^7.1.1", - "chokidar": "^3.5.3", - "ci-info": "^3.8.0", - "clsx": "^2.0.0", - "common-ancestor-path": "^1.0.1", - "cookie": "^0.5.0", - "debug": "^4.3.4", - "deterministic-object-hash": "^1.3.1", - "devalue": "^4.3.2", - "diff": "^5.1.0", - "es-module-lexer": "^1.3.0", - "esbuild": "^0.19.2", - "estree-walker": "^3.0.3", - "execa": "^8.0.1", - "fast-glob": "^3.3.1", - "github-slugger": "^2.0.0", - "gray-matter": "^4.0.3", - "html-escaper": "^3.0.3", - "http-cache-semantics": "^4.1.1", - "js-yaml": "^4.1.0", - "kleur": "^4.1.4", - "magic-string": "^0.30.3", - "mime": "^3.0.0", - "ora": "^7.0.1", - "p-limit": "^4.0.0", - "path-to-regexp": "^6.2.1", - "preferred-pm": "^3.1.2", - "probe-image-size": "^7.2.3", - "prompts": "^2.4.2", - "rehype": "^12.0.1", - "resolve": "^1.22.4", - "semver": "^7.5.4", - "server-destroy": "^1.0.1", - "shikiji": "^0.6.8", - "string-width": "^6.1.0", - "strip-ansi": "^7.1.0", - "tsconfck": "^3.0.0", - "unist-util-visit": "^4.1.2", - "vfile": "^5.3.7", - "vite": "^4.4.9", - "vitefu": "^0.2.4", - "which-pm": "^2.1.1", - "yargs-parser": "^21.1.1", - "zod": "3.21.1" - }, + "node_modules/astro/node_modules/vite/node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "hasInstallScript": true, "bin": { - "astro": "astro.js" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=18.14.1", - "npm": ">=6.14.0" + "node": ">=12" }, "optionalDependencies": { - "sharp": "^0.32.5" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/async-sema": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", + "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==" + }, + "node_modules/axobject-query": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", + "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==", + "dependencies": { + "dequal": "^2.0.3" } }, "node_modules/b4a": { @@ -1327,6 +3778,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base-64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1377,6 +3838,14 @@ "node": ">=8" } }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, "node_modules/bl": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", @@ -1445,6 +3914,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -1457,9 +3935,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "funding": [ { "type": "opencollective", @@ -1475,9 +3953,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -1522,9 +4000,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001549", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz", - "integrity": "sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "funding": [ { "type": "opencollective", @@ -1630,9 +4108,9 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", "funding": [ { "type": "github", @@ -1687,6 +4165,27 @@ "node": ">=6" } }, + "node_modules/code-red": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", + "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@types/estree": "^1.0.1", + "acorn": "^8.10.0", + "estree-walker": "^3.0.3", + "periscopic": "^3.1.0" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -1721,6 +4220,14 @@ "simple-swizzle": "^0.2.2" } }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/color/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1751,15 +4258,25 @@ "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==" }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -1778,9 +4295,42 @@ } }, "node_modules/css-selector-parser": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz", - "integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g==" + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.0.4.tgz", + "integrity": "sha512-pnmS1dbKsz6KA4EW4BznyPL2xxkNDRg62hcD0v8g6DEw2W7hxOln5M953jsp9hmw5Dg57S6o/A8GOn37mbAgcQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } }, "node_modules/debug": { "version": "4.3.4", @@ -1824,6 +4374,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dedent-js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz", + "integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==" + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -1832,6 +4387,19 @@ "node": ">=4.0.0" } }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -1849,9 +4417,15 @@ } }, "node_modules/deterministic-object-hash": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-1.3.1.tgz", - "integrity": "sha512-kQDIieBUreEgY+akq0N7o4FzZCr27dPG1xr3wq267vPwDlSXQ3UMcBXHqTGUBaM/5WDS1jwTYjxRhUzHeuiAvw==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", + "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", + "dependencies": { + "base-64": "^1.0.0" + }, + "engines": { + "node": ">=18" + } }, "node_modules/devalue": { "version": "4.3.2", @@ -1896,9 +4470,9 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "node_modules/dset": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", - "integrity": "sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", + "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", "engines": { "node": ">=4" } @@ -1909,9 +4483,9 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.4.556", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.556.tgz", - "integrity": "sha512-6RPN0hHfzDU8D56E72YkDvnLw5Cj2NMXZGg3UkgyoHxjVhG99KZpsKgBWMmTy0Ei89xwan+rbRsVB9yzATmYzQ==" + "version": "1.4.615", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", + "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==" }, "node_modules/emoji-regex": { "version": "10.3.0", @@ -1938,14 +4512,14 @@ } }, "node_modules/es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "node_modules/esbuild": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", - "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.10.tgz", + "integrity": "sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -1954,28 +4528,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.5", - "@esbuild/android-arm64": "0.19.5", - "@esbuild/android-x64": "0.19.5", - "@esbuild/darwin-arm64": "0.19.5", - "@esbuild/darwin-x64": "0.19.5", - "@esbuild/freebsd-arm64": "0.19.5", - "@esbuild/freebsd-x64": "0.19.5", - "@esbuild/linux-arm": "0.19.5", - "@esbuild/linux-arm64": "0.19.5", - "@esbuild/linux-ia32": "0.19.5", - "@esbuild/linux-loong64": "0.19.5", - "@esbuild/linux-mips64el": "0.19.5", - "@esbuild/linux-ppc64": "0.19.5", - "@esbuild/linux-riscv64": "0.19.5", - "@esbuild/linux-s390x": "0.19.5", - "@esbuild/linux-x64": "0.19.5", - "@esbuild/netbsd-x64": "0.19.5", - "@esbuild/openbsd-x64": "0.19.5", - "@esbuild/sunos-x64": "0.19.5", - "@esbuild/win32-arm64": "0.19.5", - "@esbuild/win32-ia32": "0.19.5", - "@esbuild/win32-x64": "0.19.5" + "@esbuild/aix-ppc64": "0.19.10", + "@esbuild/android-arm": "0.19.10", + "@esbuild/android-arm64": "0.19.10", + "@esbuild/android-x64": "0.19.10", + "@esbuild/darwin-arm64": "0.19.10", + "@esbuild/darwin-x64": "0.19.10", + "@esbuild/freebsd-arm64": "0.19.10", + "@esbuild/freebsd-x64": "0.19.10", + "@esbuild/linux-arm": "0.19.10", + "@esbuild/linux-arm64": "0.19.10", + "@esbuild/linux-ia32": "0.19.10", + "@esbuild/linux-loong64": "0.19.10", + "@esbuild/linux-mips64el": "0.19.10", + "@esbuild/linux-ppc64": "0.19.10", + "@esbuild/linux-riscv64": "0.19.10", + "@esbuild/linux-s390x": "0.19.10", + "@esbuild/linux-x64": "0.19.10", + "@esbuild/netbsd-x64": "0.19.10", + "@esbuild/openbsd-x64": "0.19.10", + "@esbuild/sunos-x64": "0.19.10", + "@esbuild/win32-arm64": "0.19.10", + "@esbuild/win32-ia32": "0.19.10", + "@esbuild/win32-x64": "0.19.10" } }, "node_modules/escalade": { @@ -2007,9 +4582,9 @@ } }, "node_modules/estree-util-attach-comments": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz", - "integrity": "sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", "dependencies": { "@types/estree": "^1.0.0" }, @@ -2019,12 +4594,13 @@ } }, "node_modules/estree-util-build-jsx": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-2.2.2.tgz", - "integrity": "sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", "dependencies": { "@types/estree-jsx": "^1.0.0", - "estree-util-is-identifier-name": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", "estree-walker": "^3.0.0" }, "funding": { @@ -2033,18 +4609,18 @@ } }, "node_modules/estree-util-is-identifier-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz", - "integrity": "sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/estree-util-to-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz", - "integrity": "sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", "dependencies": { "@types/estree-jsx": "^1.0.0", "astring": "^1.8.0", @@ -2056,18 +4632,23 @@ } }, "node_modules/estree-util-visit": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz", - "integrity": "sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", "dependencies": { "@types/estree-jsx": "^1.0.0", - "@types/unist": "^2.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, + "node_modules/estree-util-visit/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -2076,6 +4657,11 @@ "@types/estree": "^1.0.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, "node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -2106,6 +4692,17 @@ "node": ">=6" } }, + "node_modules/expressive-code": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.30.1.tgz", + "integrity": "sha512-iD8xtfN8X29jfk0B2U4/ws1pV/8GgRVIGOIDm9f6U9Zcnse1OnD/i+cYkcaOr5MLpVe8eLEr8GvVtZDOBxekrg==", + "dependencies": { + "@expressive-code/core": "^0.30.1", + "@expressive-code/plugin-frames": "^0.30.1", + "@expressive-code/plugin-shiki": "^0.30.1", + "@expressive-code/plugin-text-markers": "^0.30.1" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2128,9 +4725,9 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -2143,13 +4740,18 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2185,10 +4787,50 @@ "pkg-dir": "^4.2.0" } }, - "node_modules/fs-constants": { + "node_modules/flattie": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.0.tgz", + "integrity": "sha512-xU99gDEnciIwJdGcBmNHnzTJ/w5AT+VFJOu6sTB6WM8diOYNA3Sa+K1DiEBQ7XH4QikQq3iFW1U+jRVcotQnBw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.3", @@ -2203,6 +4845,67 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2211,6 +4914,17 @@ "node": ">=6.9.0" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", @@ -2232,6 +4946,25 @@ "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -2298,69 +5031,280 @@ "node": ">= 0.4.0" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "node_modules/hast-util-from-html": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.1.tgz", + "integrity": "sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/hast-util-from-html/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", + "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^8.0.0", + "property-information": "^6.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/hast-util-from-parse5/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.1.tgz", + "integrity": "sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/hast-util-raw/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-from-parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", - "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", + "node_modules/hast-util-raw/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", - "hastscript": "^7.0.0", - "property-information": "^6.0.0", - "vfile": "^5.0.0", - "vfile-location": "^4.0.0", - "web-namespaces": "^2.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-has-property": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.1.tgz", - "integrity": "sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==", + "node_modules/hast-util-raw/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-parse-selector": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", - "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "node_modules/hast-util-raw/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "@types/hast": "^2.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-raw": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz", - "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==", + "node_modules/hast-util-raw/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "@types/hast": "^2.0.0", - "@types/parse5": "^6.0.0", - "hast-util-from-parse5": "^7.0.0", - "hast-util-to-parse5": "^7.0.0", - "html-void-elements": "^2.0.0", - "parse5": "^6.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0", - "vfile": "^5.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", @@ -2368,24 +5312,25 @@ } }, "node_modules/hast-util-select": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-5.0.5.tgz", - "integrity": "sha512-QQhWMhgTFRhCaQdgTKzZ5g31GLQ9qRb1hZtDPMqQaOhpLBziWcshUS0uCR5IJ0U1jrK/mxg35fmcq+Dp/Cy2Aw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.2.tgz", + "integrity": "sha512-hT/SD/d/Meu+iobvgkffo1QecV8WeKWxwsNMzcTJsKw1cKTQKSR/7ArJeURLNJF9HDjp9nVoORyNNJxrvBye8Q==", "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", "bcp-47-match": "^2.0.0", "comma-separated-tokens": "^2.0.0", - "css-selector-parser": "^1.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.0.0", "direction": "^2.0.0", - "hast-util-has-property": "^2.0.0", - "hast-util-to-string": "^2.0.0", - "hast-util-whitespace": "^2.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "hast-util-whitespace": "^3.0.0", "not": "^0.1.0", "nth-check": "^2.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", - "unist-util-visit": "^4.0.0", + "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" }, "funding": { @@ -2393,25 +5338,70 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-select/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/hast-util-select/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-select/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-select/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-estree": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz", - "integrity": "sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", + "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", + "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", - "estree-util-attach-comments": "^2.0.0", - "estree-util-is-identifier-name": "^2.0.0", - "hast-util-whitespace": "^2.0.0", - "mdast-util-mdx-expression": "^1.0.0", - "mdast-util-mdxjs-esm": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", - "style-to-object": "^0.4.1", - "unist-util-position": "^4.0.0", + "style-to-object": "^0.4.0", + "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" }, "funding": { @@ -2420,17 +5410,18 @@ } }, "node_modules/hast-util-to-html": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-8.0.4.tgz", - "integrity": "sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.0.tgz", + "integrity": "sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==", "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", - "hast-util-raw": "^7.0.0", - "hast-util-whitespace": "^2.0.0", - "html-void-elements": "^2.0.0", + "hast-util-raw": "^9.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", @@ -2441,13 +5432,88 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-html/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.2.tgz", + "integrity": "sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==" + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.5.tgz", + "integrity": "sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==", + "dependencies": { + "inline-style-parser": "0.2.2" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-parse5": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz", - "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", "dependencies": { - "@types/hast": "^2.0.0", + "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", @@ -2459,34 +5525,57 @@ } }, "node_modules/hast-util-to-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-2.0.0.tgz", - "integrity": "sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", "dependencies": { - "@types/hast": "^2.0.0" + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.0.tgz", + "integrity": "sha512-EWiE1FSArNBPUo1cKWtzqgnuRQwEeQbQtnFJRYV1hb1BWDgrAlBU0ExptvZMM/KSA82cDpm2sFGf3Dmc5Mza3w==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-text/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, "node_modules/hast-util-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", - "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/hastscript": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", - "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", "dependencies": { - "@types/hast": "^2.0.0", + "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^3.0.0", + "hast-util-parse-selector": "^4.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0" }, @@ -2501,9 +5590,9 @@ "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==" }, "node_modules/html-void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", - "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -2514,6 +5603,18 @@ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", @@ -2522,17 +5623,6 @@ "node": ">=16.17.0" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2553,14 +5643,23 @@ ] }, "node_modules/import-meta-resolve": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.0.0.tgz", - "integrity": "sha512-4IwhLhNNA8yy445rPjD/lWh++7hMDOml2eHtd58eG7h+qK3EryMuuRbsHGPikCoAgIkkDnckKfWSk2iDla/ejg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", + "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -2898,6 +5997,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2912,11 +6016,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, "node_modules/log-symbols": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", @@ -2952,6 +6051,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -2971,12 +6078,37 @@ "node": ">=12" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/markdown-extensions": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", - "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", "engines": { - "node": ">=0.10.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/markdown-table": { @@ -3002,18 +6134,10 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-definitions/node_modules/@types/mdast": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.1.tgz", - "integrity": "sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==", - "dependencies": { - "@types/unist": "*" - } - }, "node_modules/mdast-util-definitions/node_modules/@types/unist": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.0.tgz", - "integrity": "sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" }, "node_modules/mdast-util-definitions/node_modules/unist-util-is": { "version": "6.0.0", @@ -3055,17 +6179,48 @@ } }, "node_modules/mdast-util-directive": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-2.2.4.tgz", - "integrity": "sha512-sK3ojFP+jpj1n7Zo5ZKvoxP1MvLyzVG63+gm40Z/qI00avzdPCYxt7RBMgofwAva9gBjbDBWVRB/i+UD+fUCzQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", + "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "mdast-util-from-markdown": "^1.3.0", - "mdast-util-to-markdown": "^1.5.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", - "unist-util-visit-parents": "^5.1.3" + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-directive/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/mdast-util-directive/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-directive/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, "funding": { "type": "opencollective", @@ -3073,20 +6228,25 @@ } }, "node_modules/mdast-util-find-and-replace": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.2.tgz", - "integrity": "sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", "dependencies": { - "@types/mdast": "^3.0.0", + "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.0.0" + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-find-and-replace/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", @@ -3098,23 +6258,65 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mdast-util-find-and-replace/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-from-markdown": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", - "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", + "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", - "mdast-util-to-string": "^3.1.0", - "micromark": "^3.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-decode-string": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/mdast-util-from-markdown/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", @@ -3122,17 +6324,17 @@ } }, "node_modules/mdast-util-gfm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz", - "integrity": "sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", "dependencies": { - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-gfm-autolink-literal": "^1.0.0", - "mdast-util-gfm-footnote": "^1.0.0", - "mdast-util-gfm-strikethrough": "^1.0.0", - "mdast-util-gfm-table": "^1.0.0", - "mdast-util-gfm-task-list-item": "^1.0.0", - "mdast-util-to-markdown": "^1.0.0" + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3140,14 +6342,15 @@ } }, "node_modules/mdast-util-gfm-autolink-literal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.3.tgz", - "integrity": "sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.0.tgz", + "integrity": "sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==", "dependencies": { - "@types/mdast": "^3.0.0", + "@types/mdast": "^4.0.0", "ccount": "^2.0.0", - "mdast-util-find-and-replace": "^2.0.0", - "micromark-util-character": "^1.0.0" + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3155,13 +6358,15 @@ } }, "node_modules/mdast-util-gfm-footnote": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.2.tgz", - "integrity": "sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0", - "micromark-util-normalize-identifier": "^1.0.0" + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3169,12 +6374,13 @@ } }, "node_modules/mdast-util-gfm-strikethrough": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.3.tgz", - "integrity": "sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0" + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3182,14 +6388,15 @@ } }, "node_modules/mdast-util-gfm-table": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.7.tgz", - "integrity": "sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", "dependencies": { - "@types/mdast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-to-markdown": "^1.3.0" + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3197,12 +6404,14 @@ } }, "node_modules/mdast-util-gfm-task-list-item": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.2.tgz", - "integrity": "sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0" + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3210,135 +6419,259 @@ } }, "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.0.0.tgz", + "integrity": "sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/mdast-util-mdx-jsx/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz", - "integrity": "sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.0.0.tgz", + "integrity": "sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/mdast-util-phrasing/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.0.2.tgz", + "integrity": "sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==", "dependencies": { - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-mdx-expression": "^1.0.0", - "mdast-util-mdx-jsx": "^2.0.0", - "mdast-util-mdxjs-esm": "^1.0.0", - "mdast-util-to-markdown": "^1.0.0" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-expression": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz", - "integrity": "sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==", + "node_modules/mdast-util-to-hast/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/mdast-util-to-hast/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-to-markdown": "^1.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdx-jsx": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz", - "integrity": "sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==", + "node_modules/mdast-util-to-hast/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "ccount": "^2.0.0", - "mdast-util-from-markdown": "^1.1.0", - "mdast-util-to-markdown": "^1.3.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-remove-position": "^4.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz", - "integrity": "sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==", + "node_modules/mdast-util-to-hast/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-to-markdown": "^1.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-phrasing": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", - "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", "dependencies": { - "@types/mdast": "^3.0.0", - "unist-util-is": "^5.0.0" + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-hast": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", - "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==", + "node_modules/mdast-util-to-markdown/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/mdast-util-to-markdown/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dependencies": { - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "mdast-util-definitions": "^5.0.0", - "micromark-util-sanitize-uri": "^1.1.0", - "trim-lines": "^3.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-hast/node_modules/mdast-util-definitions": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", - "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==", + "node_modules/mdast-util-to-markdown/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "unist-util-visit": "^4.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-to-markdown": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", - "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", + "node_modules/mdast-util-to-markdown/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^3.0.0", - "mdast-util-to-string": "^3.0.0", - "micromark-util-decode-string": "^1.0.0", - "unist-util-visit": "^4.0.0", - "zwitch": "^2.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, "funding": { "type": "opencollective", @@ -3346,17 +6679,22 @@ } }, "node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", "dependencies": { - "@types/mdast": "^3.0.0" + "@types/mdast": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -3371,9 +6709,9 @@ } }, "node_modules/micromark": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", "funding": [ { "type": "GitHub Sponsors", @@ -3388,26 +6726,26 @@ "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", - "micromark-core-commonmark": "^1.0.1", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-core-commonmark": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", - "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz", + "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==", "funding": [ { "type": "GitHub Sponsors", @@ -3420,35 +6758,35 @@ ], "dependencies": { "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-extension-directive": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-2.2.1.tgz", - "integrity": "sha512-ZFKZkNaEqAP86IghX1X7sE8NNnx6kFNq9mSBRvEHjArutTCJZ3LYg6VH151lXVb1JHpmIcW/7rX25oMoIHuSug==", - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "parse-entities": "^4.0.0", - "uvu": "^0.5.0" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.0.tgz", + "integrity": "sha512-61OI07qpQrERc+0wEysLHMvoiO3s2R56x5u7glHq2Yqq6EHbH4dW25G9GfDdGCDYqA21KE6DWgNSzxSwHc2hSg==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" }, "funding": { "type": "opencollective", @@ -3456,18 +6794,18 @@ } }, "node_modules/micromark-extension-gfm": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz", - "integrity": "sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^1.0.0", - "micromark-extension-gfm-footnote": "^1.0.0", - "micromark-extension-gfm-strikethrough": "^1.0.0", - "micromark-extension-gfm-table": "^1.0.0", - "micromark-extension-gfm-tagfilter": "^1.0.0", - "micromark-extension-gfm-task-list-item": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-types": "^1.0.0" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3475,14 +6813,14 @@ } }, "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz", - "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.0.0.tgz", + "integrity": "sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3490,18 +6828,18 @@ } }, "node_modules/micromark-extension-gfm-footnote": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz", - "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==", "dependencies": { - "micromark-core-commonmark": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3509,16 +6847,16 @@ } }, "node_modules/micromark-extension-gfm-strikethrough": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz", - "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==", "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3526,15 +6864,15 @@ } }, "node_modules/micromark-extension-gfm-table": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz", - "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz", + "integrity": "sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==", "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3542,11 +6880,11 @@ } }, "node_modules/micromark-extension-gfm-tagfilter": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz", - "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", "dependencies": { - "micromark-util-types": "^1.0.0" + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3554,15 +6892,15 @@ } }, "node_modules/micromark-extension-gfm-task-list-item": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz", - "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.0.1.tgz", + "integrity": "sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==", "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3570,9 +6908,9 @@ } }, "node_modules/micromark-extension-mdx-expression": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz", - "integrity": "sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", + "integrity": "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==", "funding": [ { "type": "GitHub Sponsors", @@ -3585,30 +6923,60 @@ ], "dependencies": { "@types/estree": "^1.0.0", - "micromark-factory-mdx-expression": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-events-to-acorn": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-extension-mdx-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz", - "integrity": "sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.0.tgz", + "integrity": "sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w==", "dependencies": { "@types/acorn": "^4.0.0", "@types/estree": "^1.0.0", - "estree-util-is-identifier-name": "^2.0.0", - "micromark-factory-mdx-expression": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0", - "vfile-message": "^3.0.0" + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", @@ -3616,11 +6984,11 @@ } }, "node_modules/micromark-extension-mdx-md": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz", - "integrity": "sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", "dependencies": { - "micromark-util-types": "^1.0.0" + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3628,18 +6996,18 @@ } }, "node_modules/micromark-extension-mdxjs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz", - "integrity": "sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", "dependencies": { "acorn": "^8.0.0", "acorn-jsx": "^5.0.0", - "micromark-extension-mdx-expression": "^1.0.0", - "micromark-extension-mdx-jsx": "^1.0.0", - "micromark-extension-mdx-md": "^1.0.0", - "micromark-extension-mdxjs-esm": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -3647,19 +7015,49 @@ } }, "node_modules/micromark-extension-mdxjs-esm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz", - "integrity": "sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", "dependencies": { "@types/estree": "^1.0.0", - "micromark-core-commonmark": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-events-to-acorn": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-position-from-estree": "^1.1.0", - "uvu": "^0.5.0", - "vfile-message": "^3.0.0" + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", @@ -3667,9 +7065,9 @@ } }, "node_modules/micromark-factory-destination": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", - "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", "funding": [ { "type": "GitHub Sponsors", @@ -3681,15 +7079,15 @@ } ], "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-factory-label": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", - "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", "funding": [ { "type": "GitHub Sponsors", @@ -3701,16 +7099,16 @@ } ], "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-factory-mdx-expression": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz", - "integrity": "sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.1.tgz", + "integrity": "sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==", "funding": [ { "type": "GitHub Sponsors", @@ -3723,19 +7121,49 @@ ], "dependencies": { "@types/estree": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-events-to-acorn": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-position-from-estree": "^1.0.0", - "uvu": "^0.5.0", - "vfile-message": "^3.0.0" + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/micromark-factory-mdx-expression/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/micromark-factory-space": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", "funding": [ { "type": "GitHub Sponsors", @@ -3747,14 +7175,14 @@ } ], "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-factory-title": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", - "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", "funding": [ { "type": "GitHub Sponsors", @@ -3766,16 +7194,16 @@ } ], "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-factory-whitespace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", - "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", "funding": [ { "type": "GitHub Sponsors", @@ -3787,16 +7215,16 @@ } ], "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", + "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", "funding": [ { "type": "GitHub Sponsors", @@ -3808,14 +7236,14 @@ } ], "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-util-chunked": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", "funding": [ { "type": "GitHub Sponsors", @@ -3827,13 +7255,13 @@ } ], "dependencies": { - "micromark-util-symbol": "^1.0.0" + "micromark-util-symbol": "^2.0.0" } }, "node_modules/micromark-util-classify-character": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", "funding": [ { "type": "GitHub Sponsors", @@ -3845,15 +7273,15 @@ } ], "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-util-combine-extensions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", - "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", "funding": [ { "type": "GitHub Sponsors", @@ -3865,14 +7293,14 @@ } ], "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", - "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", "funding": [ { "type": "GitHub Sponsors", @@ -3884,13 +7312,13 @@ } ], "dependencies": { - "micromark-util-symbol": "^1.0.0" + "micromark-util-symbol": "^2.0.0" } }, "node_modules/micromark-util-decode-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", - "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", "funding": [ { "type": "GitHub Sponsors", @@ -3903,15 +7331,15 @@ ], "dependencies": { "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-symbol": "^1.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, "node_modules/micromark-util-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", "funding": [ { "type": "GitHub Sponsors", @@ -3924,9 +7352,9 @@ ] }, "node_modules/micromark-util-events-to-acorn": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz", - "integrity": "sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz", + "integrity": "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==", "funding": [ { "type": "GitHub Sponsors", @@ -3940,18 +7368,48 @@ "dependencies": { "@types/acorn": "^4.0.0", "@types/estree": "^1.0.0", - "@types/unist": "^2.0.0", - "estree-util-visit": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0", - "vfile-message": "^3.0.0" + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/micromark-util-events-to-acorn/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/micromark-util-html-tag-name": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", - "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", "funding": [ { "type": "GitHub Sponsors", @@ -3964,9 +7422,9 @@ ] }, "node_modules/micromark-util-normalize-identifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", "funding": [ { "type": "GitHub Sponsors", @@ -3978,13 +7436,13 @@ } ], "dependencies": { - "micromark-util-symbol": "^1.0.0" + "micromark-util-symbol": "^2.0.0" } }, "node_modules/micromark-util-resolve-all": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", "funding": [ { "type": "GitHub Sponsors", @@ -3996,13 +7454,13 @@ } ], "dependencies": { - "micromark-util-types": "^1.0.0" + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", "funding": [ { "type": "GitHub Sponsors", @@ -4014,15 +7472,15 @@ } ], "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, "node_modules/micromark-util-subtokenize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", - "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz", + "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==", "funding": [ { "type": "GitHub Sponsors", @@ -4034,16 +7492,16 @@ } ], "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", "funding": [ { "type": "GitHub Sponsors", @@ -4056,9 +7514,9 @@ ] }, "node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", "funding": [ { "type": "GitHub Sponsors", @@ -4115,6 +7573,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -4123,28 +7592,67 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "engines": { - "node": ">=4" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -4163,30 +7671,6 @@ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, - "node_modules/needle": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", - "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/nlcst-to-string": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-3.1.1.tgz", @@ -4199,6 +7683,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-abi": { "version": "3.51.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.51.0.tgz", @@ -4215,10 +7708,53 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } }, "node_modules/normalize-path": { "version": "3.0.0", @@ -4258,6 +7794,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -4269,6 +7816,14 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4325,14 +7880,14 @@ } }, "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "dependencies": { "yocto-queue": "^1.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4377,6 +7932,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-queue": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.0.1.tgz", + "integrity": "sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.2.tgz", + "integrity": "sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -4434,9 +8015,24 @@ } }, "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } }, "node_modules/path-exists": { "version": "4.0.0", @@ -4446,6 +8042,14 @@ "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4558,9 +8162,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "funding": [ { "type": "opencollective", @@ -4576,12 +8180,42 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=4" } }, "node_modules/prebuild-install": { @@ -4702,16 +8336,6 @@ "node": ">=6" } }, - "node_modules/probe-image-size": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-7.2.3.tgz", - "integrity": "sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==", - "dependencies": { - "lodash.merge": "^4.6.2", - "needle": "^2.5.2", - "stream-parser": "~0.3.1" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -4769,860 +8393,1245 @@ } ] }, - "node_modules/queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rehype": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.1.tgz", + "integrity": "sha512-AcSLS2mItY+0fYu9xKxOu1LhUZeBZZBx8//5HKzF+0XP+eP8+6a5MXn2+DW2kfXR6Dtp1FEXMVrjyKAcvcU8vg==", + "dependencies": { + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.0.tgz", + "integrity": "sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/rehype-parse/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/rehype-raw/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.0.tgz", + "integrity": "sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/rehype-stringify/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/rehype/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "node_modules/rehype/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, - "bin": { - "rc": "cli.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/remark-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.0.tgz", + "integrity": "sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" }, - "engines": { - "node": ">= 6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/remark-directive/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/remark-directive/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", "dependencies": { - "picomatch": "^2.2.1" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">=8.10.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/rehype": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/rehype/-/rehype-12.0.1.tgz", - "integrity": "sha512-ey6kAqwLM3X6QnMDILJthGvG1m1ULROS9NT4uG9IDCuv08SFyLlreSuvOa//DgEvbXx62DS6elGVqusWhRUbgw==", + "node_modules/remark-directive/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "@types/hast": "^2.0.0", - "rehype-parse": "^8.0.0", - "rehype-stringify": "^9.0.0", - "unified": "^10.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/rehype-parse": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.5.tgz", - "integrity": "sha512-Ds3RglaY/+clEX2U2mHflt7NlMA72KspZ0JLUJgBBLpRddBcEw3H8uYZQliQriku22NZpYMfjDdSgHcjxue24A==", + "node_modules/remark-directive/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "@types/hast": "^2.0.0", - "hast-util-from-parse5": "^7.0.0", - "parse5": "^6.0.0", - "unified": "^10.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/rehype-raw": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz", - "integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==", + "node_modules/remark-directive/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "@types/hast": "^2.0.0", - "hast-util-raw": "^7.2.0", - "unified": "^10.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/rehype-stringify": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-9.0.4.tgz", - "integrity": "sha512-Uk5xu1YKdqobe5XpSskwPvo1XeHUUucWEQSl8hTrXt5selvca1e8K1EZ37E6YoZ4BT8BCqCdVfQW7OfHfthtVQ==", + "node_modules/remark-expressive-code": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/remark-expressive-code/-/remark-expressive-code-0.30.1.tgz", + "integrity": "sha512-1cxsvXn1FyZsgaZXvkV+uoJLkg0rcS/k9Yemw211oD8Fblhh67Gb6ThxbuQdPf346kgg5D4R/iVyR49oAS5kbg==", + "dependencies": { + "expressive-code": "^0.30.1", + "hast-util-to-html": "^8.0.4", + "unist-util-visit": "^4.1.2" + } + }, + "node_modules/remark-expressive-code/node_modules/@types/hast": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.8.tgz", + "integrity": "sha512-aMIqAlFd2wTIDZuvLbhUT+TGvMxrNC8ECUIVtH6xxy0sQLs3iu6NO8Kp/VT5je7i5ufnebXzdV1dNDMnvaH6IQ==", + "dependencies": { + "@types/unist": "^2" + } + }, + "node_modules/remark-expressive-code/node_modules/hast-util-from-parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", + "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", "dependencies": { "@types/hast": "^2.0.0", - "hast-util-to-html": "^8.0.0", - "unified": "^10.0.0" + "@types/unist": "^2.0.0", + "hastscript": "^7.0.0", + "property-information": "^6.0.0", + "vfile": "^5.0.0", + "vfile-location": "^4.0.0", + "web-namespaces": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-directive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-2.0.1.tgz", - "integrity": "sha512-oosbsUAkU/qmUE78anLaJePnPis4ihsE7Agp0T/oqTzvTea8pOiaYEtfInU/+xMOVTS9PN5AhGOiaIVe4GD8gw==", + "node_modules/remark-expressive-code/node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-directive": "^2.0.0", - "micromark-extension-directive": "^2.0.0", - "unified": "^10.0.0" + "@types/hast": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-gfm": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", - "integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==", + "node_modules/remark-expressive-code/node_modules/hast-util-raw": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz", + "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==", "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-gfm": "^2.0.0", - "micromark-extension-gfm": "^2.0.0", - "unified": "^10.0.0" + "@types/hast": "^2.0.0", + "@types/parse5": "^6.0.0", + "hast-util-from-parse5": "^7.0.0", + "hast-util-to-parse5": "^7.0.0", + "html-void-elements": "^2.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile": "^5.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-mdx": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz", - "integrity": "sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==", + "node_modules/remark-expressive-code/node_modules/hast-util-to-html": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-8.0.4.tgz", + "integrity": "sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==", "dependencies": { - "mdast-util-mdx": "^2.0.0", - "micromark-extension-mdxjs": "^1.0.0" + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-raw": "^7.0.0", + "hast-util-whitespace": "^2.0.0", + "html-void-elements": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-parse": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", - "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", + "node_modules/remark-expressive-code/node_modules/hast-util-to-parse5": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz", + "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==", "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "unified": "^10.0.0" + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-rehype": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz", - "integrity": "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==", + "node_modules/remark-expressive-code/node_modules/hast-util-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-expressive-code/node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", "dependencies": { "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "mdast-util-to-hast": "^12.1.0", - "unified": "^10.0.0" + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/remark-smartypants": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-2.0.0.tgz", - "integrity": "sha512-Rc0VDmr/yhnMQIz8n2ACYXlfw/P/XZev884QU1I5u+5DgJls32o97Vc1RbK3pfumLsJomS2yy8eT4Fxj/2MDVA==", + "node_modules/remark-expressive-code/node_modules/html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/remark-expressive-code/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/remark-expressive-code/node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", "dependencies": { - "retext": "^8.1.0", - "retext-smartypants": "^5.1.0", - "unist-util-visit": "^4.1.0" + "@types/unist": "^2.0.0" }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/remark-expressive-code/node_modules/vfile-location": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", + "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "@types/unist": "^2.0.0", + "vfile": "^5.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/restore-cursor": { + "node_modules/remark-gfm": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" + "node_modules/remark-gfm/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/remark-gfm/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/remark-gfm/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/retext": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/retext/-/retext-8.1.0.tgz", - "integrity": "sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==", + "node_modules/remark-gfm/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "@types/nlcst": "^1.0.0", - "retext-latin": "^3.0.0", - "retext-stringify": "^3.0.0", - "unified": "^10.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/retext-latin": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-3.1.0.tgz", - "integrity": "sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==", + "node_modules/remark-gfm/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "@types/nlcst": "^1.0.0", - "parse-latin": "^5.0.0", - "unherit": "^3.0.0", - "unified": "^10.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/retext-smartypants": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-5.2.0.tgz", - "integrity": "sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==", + "node_modules/remark-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.0.tgz", + "integrity": "sha512-O7yfjuC6ra3NHPbRVxfflafAj3LTwx3b73aBvkEFU5z4PsD6FD4vrqJAkE5iNGLz71GdjXfgRqm3SQ0h0VuE7g==", "dependencies": { - "@types/nlcst": "^1.0.0", - "nlcst-to-string": "^3.0.0", - "unified": "^10.0.0", - "unist-util-visit": "^4.0.0" + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/retext-stringify": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-3.1.0.tgz", - "integrity": "sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==", + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "dependencies": { - "@types/nlcst": "^1.0.0", - "nlcst-to-string": "^3.0.0", - "unified": "^10.0.0" + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } + "node_modules/remark-parse/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" }, - "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" + "node_modules/remark-parse/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/remark-parse/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "queue-microtask": "^1.2.2" + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "node_modules/remark-parse/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "mri": "^1.1.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": ">=6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" - }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "node_modules/remark-parse/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, - "engines": { - "node": ">=4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/remark-rehype": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.0.0.tgz", + "integrity": "sha512-vx8x2MDMcxuE4lBmQ46zYUDfcFMmvg80WYX+UNLeG6ixjdCCLcw1lrgAukwBTuOFsS78eoAedHGn9sNM0w7TPw==", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">=10" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/remark-rehype/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/remark-rehype/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", "dependencies": { - "yallist": "^4.0.0" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">=10" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/semver/node_modules/yallist": { + "node_modules/remark-rehype/node_modules/unist-util-stringify-position": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/server-destroy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", - "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" - }, - "node_modules/sharp": { - "version": "0.32.6", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", - "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", - "hasInstallScript": true, + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.2", - "node-addon-api": "^6.1.0", - "prebuild-install": "^7.1.1", - "semver": "^7.5.4", - "simple-get": "^4.0.1", - "tar-fs": "^3.0.4", - "tunnel-agent": "^0.6.0" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=14.15.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, "funding": { - "url": "https://opencollective.com/libvips" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/remark-rehype/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "shebang-regex": "^3.0.0" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/shikiji": { - "version": "0.6.10", - "resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.10.tgz", - "integrity": "sha512-WE+A5Y2ntM5hL3iJQujk97qr5Uj7PSIRXpQfrZ6h+JWPXZ8KBEDhFXc4lqNriaRq1WGOVPUT83XMOzmHiH3W8A==", - "dependencies": { - "hast-util-to-html": "^9.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/@types/hast": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.1.tgz", - "integrity": "sha512-hs/iBJx2aydugBQx5ETV3ZgeSS0oIreQrFJ4bjBl0XvM4wAmDjFEALY7p0rTSLt2eL+ibjRAAs9dTPiCLtmbqQ==", + "node_modules/remark-smartypants": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-2.0.0.tgz", + "integrity": "sha512-Rc0VDmr/yhnMQIz8n2ACYXlfw/P/XZev884QU1I5u+5DgJls32o97Vc1RbK3pfumLsJomS2yy8eT4Fxj/2MDVA==", "dependencies": { - "@types/unist": "*" + "retext": "^8.1.0", + "retext-smartypants": "^5.1.0", + "unist-util-visit": "^4.1.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/shikiji/node_modules/@types/mdast": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.1.tgz", - "integrity": "sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==", + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", "dependencies": { - "@types/unist": "*" + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/@types/unist": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.0.tgz", - "integrity": "sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==" + "node_modules/remark-stringify/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" }, - "node_modules/shikiji/node_modules/hast-util-from-parse5": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", - "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "node_modules/remark-stringify/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", "dependencies": { - "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", + "bail": "^2.0.0", "devlop": "^1.0.0", - "hastscript": "^8.0.0", - "property-information": "^6.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/hast-util-parse-selector": { + "node_modules/remark-stringify/node_modules/unist-util-stringify-position": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "@types/hast": "^3.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/hast-util-raw": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.1.tgz", - "integrity": "sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==", + "node_modules/remark-stringify/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-from-parse5": "^8.0.0", - "hast-util-to-parse5": "^8.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "parse5": "^7.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/hast-util-to-html": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.0.tgz", - "integrity": "sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==", + "node_modules/remark-stringify/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { - "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-raw": "^9.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/retext": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-8.1.0.tgz", + "integrity": "sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==", + "dependencies": { + "@types/nlcst": "^1.0.0", + "retext-latin": "^3.0.0", + "retext-stringify": "^3.0.0", + "unified": "^10.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "node_modules/retext-latin": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-3.1.0.tgz", + "integrity": "sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==", "dependencies": { - "@types/hast": "^3.0.0" + "@types/nlcst": "^1.0.0", + "parse-latin": "^5.0.0", + "unherit": "^3.0.0", + "unified": "^10.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "node_modules/retext-smartypants": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-5.2.0.tgz", + "integrity": "sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==", "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" + "@types/nlcst": "^1.0.0", + "nlcst-to-string": "^3.0.0", + "unified": "^10.0.0", + "unist-util-visit": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "node_modules/retext-stringify": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-3.1.0.tgz", + "integrity": "sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==", + "dependencies": { + "@types/nlcst": "^1.0.0", + "nlcst-to-string": "^3.0.0", + "unified": "^10.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/shikiji/node_modules/mdast-util-to-hast": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.0.2.tgz", - "integrity": "sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0" + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/shikiji/node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "node_modules/rollup": { + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "optional": true, + "peer": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/shikiji/node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "funding": [ { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/shikiji/node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" + "type": "consulting", + "url": "https://feross.org/support" } ], "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" + "queue-microtask": "^1.2.2" } }, - "node_modules/shikiji/node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/shikiji/node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" + "type": "consulting", + "url": "https://feross.org/support" } ] }, - "node_modules/shikiji/node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", "dependencies": { - "entities": "^4.4.0" + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">=4" } }, - "node_modules/shikiji/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { - "@types/unist": "^3.0.0" + "lru-cache": "^6.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/shikiji/node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { - "@types/unist": "^3.0.0" + "yallist": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=10" } }, - "node_modules/shikiji/node_modules/unist-util-stringify-position": { + "node_modules/semver/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/shikiji/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "node_modules/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" + }, + "node_modules/sharp": { + "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", + "hasInstallScript": true, "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "color": "^4.2.3", + "detect-libc": "^2.0.2", + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.1", + "semver": "^7.5.4", + "simple-get": "^4.0.1", + "tar-fs": "^3.0.4", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=14.15.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/libvips" } }, - "node_modules/shikiji/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "shebang-regex": "^3.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/shikiji/node_modules/vfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", - "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" } }, - "node_modules/shikiji/node_modules/vfile-location": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.2.tgz", - "integrity": "sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==", + "node_modules/shiki": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.2.1.tgz", + "integrity": "sha512-u+XW6o0vCkUNlneZb914dLO+AayEIwK5tI62WeS//R5HIXBFiYaj/Hc5xcq27Yh83Grr4JbNtUBV8W6zyK4hWg==", "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "@shikijs/core": "1.2.1" } }, - "node_modules/shikiji/node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "node_modules/shikiji": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.13.tgz", + "integrity": "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "hast-util-to-html": "^9.0.0" } }, "node_modules/signal-exit": { @@ -5719,9 +9728,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -5752,28 +9761,7 @@ }, "funding": { "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stream-parser": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", - "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==", - "dependencies": { - "debug": "2" - } - }, - "node_modules/stream-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/stream-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } }, "node_modules/streamx": { "version": "2.15.1", @@ -5900,6 +9888,70 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svelte": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz", + "integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==", + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@jridgewell/sourcemap-codec": "^1.4.15", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/estree": "^1.0.1", + "acorn": "^8.9.0", + "aria-query": "^5.3.0", + "axobject-query": "^4.0.0", + "code-red": "^1.0.3", + "css-tree": "^2.3.1", + "estree-walker": "^3.0.3", + "is-reference": "^3.0.1", + "locate-character": "^3.0.0", + "magic-string": "^0.30.4", + "periscopic": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/svelte-hmr": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz", + "integrity": "sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==", + "engines": { + "node": "^12.20 || ^14.13.1 || >= 16" + }, + "peerDependencies": { + "svelte": "^3.19.0 || ^4.0.0" + } + }, + "node_modules/svelte2tsx": { + "version": "0.6.27", + "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.6.27.tgz", + "integrity": "sha512-E1uPW1o6VsbRz+nUk3fznZ2lSmCITAJoNu8AYefWSvIwE2pSB01i5sId4RMbWNzfcwCQl1DcgGShCPcldl4rvg==", + "dependencies": { + "dedent-js": "^1.0.1", + "pascal-case": "^3.1.1" + }, + "peerDependencies": { + "svelte": "^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0", + "typescript": "^4.9.4 || ^5.0.0" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-fs": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", @@ -5920,6 +9972,19 @@ "streamx": "^2.15.0" } }, + "node_modules/tar/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -5939,6 +10004,11 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -5976,6 +10046,11 @@ } } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -5998,6 +10073,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typescript": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "optional": true, + "peer": true + }, "node_modules/unherit": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-3.0.1.tgz", @@ -6025,10 +10119,31 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-generated": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", - "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-find-after/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/unist-util-find-after/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" @@ -6060,11 +10175,11 @@ } }, "node_modules/unist-util-position": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", - "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "dependencies": { - "@types/unist": "^2.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", @@ -6072,25 +10187,35 @@ } }, "node_modules/unist-util-position-from-estree": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz", - "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", "dependencies": { - "@types/unist": "^2.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-position-from-estree/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/unist-util-position/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, "node_modules/unist-util-remove": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-3.1.1.tgz", - "integrity": "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz", + "integrity": "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", @@ -6098,12 +10223,86 @@ } }, "node_modules/unist-util-remove-position": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz", - "integrity": "sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-visit": "^4.0.0" + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/unist-util-remove-position/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/unist-util-remove/node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove/node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, "funding": { "type": "opencollective", @@ -6195,23 +10394,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/uvu": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", - "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/vfile": { "version": "5.3.7", "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", @@ -6228,12 +10410,56 @@ } }, "node_modules/vfile-location": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", - "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.2.tgz", + "integrity": "sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==", "dependencies": { - "@types/unist": "^2.0.0", - "vfile": "^5.0.0" + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/vfile-location/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location/node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", @@ -6257,6 +10483,8 @@ "version": "4.4.11", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz", "integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==", + "optional": true, + "peer": true, "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", @@ -6318,6 +10546,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } @@ -6333,6 +10562,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } @@ -6348,6 +10578,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } @@ -6363,6 +10594,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=12" } @@ -6378,6 +10610,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=12" } @@ -6393,6 +10626,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=12" } @@ -6408,6 +10642,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=12" } @@ -6423,6 +10658,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6438,6 +10674,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6453,6 +10690,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6468,6 +10706,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6483,6 +10722,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6498,6 +10738,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6513,6 +10754,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6528,6 +10770,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6543,6 +10786,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -6558,6 +10802,7 @@ "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=12" } @@ -6573,6 +10818,7 @@ "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=12" } @@ -6588,6 +10834,7 @@ "os": [ "sunos" ], + "peer": true, "engines": { "node": ">=12" } @@ -6603,6 +10850,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } @@ -6618,6 +10866,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } @@ -6633,6 +10882,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } @@ -6642,6 +10892,8 @@ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", "hasInstallScript": true, + "optional": true, + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -6695,6 +10947,25 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/web-vitals": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.5.2.tgz", + "integrity": "sha512-c0rhqNcHXRkY/ogGDJQxZ9Im9D19hDihbzSQJrsioex+KnFgmMzBiy57Z1EjkhX/+OjyBpclDCzz2ITtjokFmg==" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6729,6 +11000,51 @@ "node": ">=4" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", @@ -6842,13 +11158,21 @@ } }, "node_modules/zod": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.1.tgz", - "integrity": "sha512-+dTu2m6gmCbO9Ahm4ZBDapx2O6ZY9QSPXst2WXjcznPMwf2YNpn3RevLx4KkZp1OPW/ouFcoBtBzFz/LeY69oA==", + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zod-to-json-schema": { + "version": "3.22.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.22.5.tgz", + "integrity": "sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==", + "peerDependencies": { + "zod": "^3.22.4" + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/docs/package.json b/docs/package.json index 644b8f486..520d3f94b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -10,9 +10,13 @@ "astro": "astro" }, "dependencies": { - "@astrojs/starlight": "^0.11.1", + "@astrojs/starlight": "^0.15.1", + "@astrojs/svelte": "^5.2.0", + "@astrojs/vercel": "^7.5.0", "@fontsource/ibm-plex-serif": "^5.0.8", - "astro": "^3.0.6", - "sharp": "^0.32.5" + "astro": "^4.0.0", + "sharp": "^0.32.5", + "svelte": "^4.2.12", + "typescript": "^5.4.3" } } diff --git a/docs/src/assets/codespaces.png b/docs/src/assets/codespaces.png new file mode 100644 index 000000000..2b8e8a43c Binary files /dev/null and b/docs/src/assets/codespaces.png differ diff --git a/docs/src/assets/rxjs/49/prototype.gif b/docs/src/assets/rxjs/49/prototype.gif new file mode 100644 index 000000000..32c33528c Binary files /dev/null and b/docs/src/assets/rxjs/49/prototype.gif differ diff --git a/docs/src/components/ActionButtonFooter.astro b/docs/src/components/ActionButtonFooter.astro index 3110f89d8..ccc03c221 100644 --- a/docs/src/components/ActionButtonFooter.astro +++ b/docs/src/components/ActionButtonFooter.astro @@ -1,48 +1,56 @@ --- import { Icon } from '@astrojs/starlight/components'; import MyIcon from './MyIcon.astro'; +import type { Props } from '@astrojs/starlight/props'; +import { getEntry } from 'astro:content'; + +const { lang } = Astro.props; +const { data } = await getEntry('i18n', lang); --- -