mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 21:03:03 -05:00
Merge branch 'main' into answer29-links
This commit is contained in:
@@ -1,15 +1,8 @@
|
||||
import starlight from '@astrojs/starlight';
|
||||
import vercel from '@astrojs/vercel/static';
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
output: 'static',
|
||||
adapter: vercel({
|
||||
webAnalytics: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
integrations: [
|
||||
starlight({
|
||||
title: 'Angular Challenges',
|
||||
@@ -19,7 +12,7 @@ export default defineConfig({
|
||||
},
|
||||
favicon: './angular-challenge.ico',
|
||||
social: {
|
||||
github: 'https://github.com/withastro/starlight',
|
||||
github: 'https://github.com/tomalaforge/angular-challenges',
|
||||
linkedin: 'https://www.linkedin.com/in/thomas-laforge-2b05a945/',
|
||||
twitter: 'https://twitter.com/laforge_toma',
|
||||
},
|
||||
|
||||
589
docs/package-lock.json
generated
589
docs/package-lock.json
generated
@@ -9,7 +9,6 @@
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@astrojs/starlight": "^0.10.0",
|
||||
"@astrojs/vercel": "^5.0.1",
|
||||
"@fontsource/ibm-plex-serif": "^5.0.8",
|
||||
"astro": "^3.0.6",
|
||||
"sharp": "^0.32.5"
|
||||
@@ -152,23 +151,6 @@
|
||||
"node": ">=18.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@astrojs/vercel": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@astrojs/vercel/-/vercel-5.0.1.tgz",
|
||||
"integrity": "sha512-qDXTBSRSzTRourx90QcB/uARUcABDRLfrDggNtyiyyh6WoJPK7BuhKDYh0Bd372Mrt2mm15ZSGaxHJLmbpv2wg==",
|
||||
"dependencies": {
|
||||
"@astrojs/internal-helpers": "0.2.0",
|
||||
"@vercel/analytics": "^1.0.2",
|
||||
"@vercel/nft": "^0.23.1",
|
||||
"esbuild": "^0.19.2",
|
||||
"fast-glob": "^3.3.1",
|
||||
"set-cookie-parser": "^2.6.0",
|
||||
"web-vitals": "^3.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.22.13",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
||||
@@ -881,25 +863,6 @@
|
||||
"@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": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz",
|
||||
@@ -1025,23 +988,6 @@
|
||||
"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/@types/acorn": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
|
||||
@@ -1175,45 +1121,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.8.tgz",
|
||||
"integrity": "sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw=="
|
||||
},
|
||||
"node_modules/@vercel/analytics": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.0.2.tgz",
|
||||
"integrity": "sha512-BZFxVrv24VbNNl5xMxqUojQIegEeXMI6rX3rg1uVLYUEXsuKNBSAEQf4BWEcjQDp/8aYJOj6m8V4PUA3x/cxgg=="
|
||||
},
|
||||
"node_modules/@vercel/nft": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.23.1.tgz",
|
||||
"integrity": "sha512-NE0xSmGWVhgHF1OIoir71XAd0W0C1UE3nzFyhpFiMr3rVhetww7NvM1kc41trBsPG37Bh+dE5FYCTMzM/gBu0w==",
|
||||
"dependencies": {
|
||||
"@mapbox/node-pre-gyp": "^1.0.5",
|
||||
"@rollup/pluginutils": "^4.0.0",
|
||||
"acorn": "^8.6.0",
|
||||
"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": ">=14"
|
||||
}
|
||||
},
|
||||
"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.10.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
||||
@@ -1233,17 +1140,6 @@
|
||||
"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",
|
||||
@@ -1328,23 +1224,6 @@
|
||||
"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",
|
||||
@@ -1497,11 +1376,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"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/b4a": {
|
||||
"version": "1.6.4",
|
||||
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz",
|
||||
@@ -1516,11 +1390,6 @@
|
||||
"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/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
@@ -1571,14 +1440,6 @@
|
||||
"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",
|
||||
@@ -1647,15 +1508,6 @@
|
||||
"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",
|
||||
@@ -1943,14 +1795,6 @@
|
||||
"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",
|
||||
@@ -1981,16 +1825,6 @@
|
||||
"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": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
@@ -2072,11 +1906,6 @@
|
||||
"node": ">=4.0.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",
|
||||
@@ -2367,11 +2196,6 @@
|
||||
"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",
|
||||
@@ -2412,38 +2236,6 @@
|
||||
"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.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
@@ -2462,62 +2254,6 @@
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"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/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",
|
||||
@@ -2547,25 +2283,6 @@
|
||||
"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",
|
||||
@@ -2643,11 +2360,6 @@
|
||||
"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-parse5": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
|
||||
@@ -2856,18 +2568,6 @@
|
||||
"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": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
|
||||
@@ -2915,15 +2615,6 @@
|
||||
"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",
|
||||
@@ -3347,28 +3038,6 @@
|
||||
"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",
|
||||
@@ -4513,17 +4182,6 @@
|
||||
"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",
|
||||
@@ -4532,53 +4190,6 @@
|
||||
"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",
|
||||
@@ -4671,54 +4282,11 @@
|
||||
"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.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz",
|
||||
"integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==",
|
||||
"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=="
|
||||
},
|
||||
"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",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@@ -4757,17 +4325,6 @@
|
||||
"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",
|
||||
@@ -4779,14 +4336,6 @@
|
||||
"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",
|
||||
@@ -4964,14 +4513,6 @@
|
||||
"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",
|
||||
@@ -5497,14 +5038,6 @@
|
||||
"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",
|
||||
@@ -5610,20 +5143,6 @@
|
||||
"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": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "3.29.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.2.tgz",
|
||||
@@ -5748,16 +5267,6 @@
|
||||
"resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
|
||||
"integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ=="
|
||||
},
|
||||
"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.5",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.5.tgz",
|
||||
@@ -6087,22 +5596,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
|
||||
"integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
|
||||
"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",
|
||||
@@ -6123,19 +5616,6 @@
|
||||
"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",
|
||||
@@ -6155,11 +5635,6 @@
|
||||
"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",
|
||||
@@ -6945,25 +6420,6 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/web-vitals": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.4.0.tgz",
|
||||
"integrity": "sha512-n9fZ5/bG1oeDkyxLWyep0eahrNcPDF6bFqoyispt7xkW0xhDzpUBTgyDKqWDi1twT0MgH4HvvqzpUyh0ZxZV4A=="
|
||||
},
|
||||
"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",
|
||||
@@ -6998,51 +6454,6 @@
|
||||
"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",
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/starlight": "^0.10.0",
|
||||
"@astrojs/vercel": "^5.0.1",
|
||||
"@fontsource/ibm-plex-serif": "^5.0.8",
|
||||
"astro": "^3.0.6",
|
||||
"sharp": "^0.32.5"
|
||||
|
||||
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
BIN
docs/src/assets/angular-performance/35/memoize-profiler.png
Normal file
BIN
docs/src/assets/angular-performance/35/memoize-profiler.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
@@ -2,35 +2,39 @@
|
||||
title: 🟠 Optimize Change Detection
|
||||
description: Challenge 12 about optimizing the number of change detection cycle while scrolling
|
||||
sidebar:
|
||||
order: 12
|
||||
order: 107
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
||||
:::
|
||||
|
||||
<div class="chip">Challenge #12</div>
|
||||
|
||||
## Information
|
||||
|
||||
In this challenge, you will need to optimize the change detection cycles run by Angular.
|
||||
In Angular, there is a library called <b>Zone.js</b> that performs a lot of magic to simplify a developer's life. Zone.js monkey patches all DOM events so that it will recheck and rerender the view when something has changed inside the application. The developer doesn't have to manually trigger change detection.
|
||||
|
||||
Zone.js triggers a change detection cycle each time a scroll event is dispatched. However we only want to show or hide a button at a specific scroll position. Therefore, we only want to refresh our application once.
|
||||
However, sometimes Zone.js triggers a lot more change detection than needed. For example, when you are listening to a scroll event, each scroll event will dispatch a new change detection cycle.
|
||||
|
||||
> You can vizualise how many times CD is triggered by installing the [Angular chrome devTool](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) and starting a new recording on the profiler tab.
|
||||
In this challenge, we only need to refresh the view at a specific scroll position to display or hide a button. All other cycles are unnecessary.
|
||||
|
||||
The following video will explain what is the goal of this challenge.
|
||||
To have a better visualization of the problem, profile your application with Angular Dev Tools.
|
||||
|
||||
:::note
|
||||
If you don't know how to use it, read [the performance introduction page](/challenges/angular-performance/) first and come back after.
|
||||
:::
|
||||
|
||||
You can learn more details about zone pollution and how to resolve it [here](https://angular.io/guide/change-detection-zone-pollution).
|
||||
|
||||
The following video will explain more in-depth the issue of this application.
|
||||
|
||||
<video controls src="https://user-images.githubusercontent.com/30832608/209819211-58d9ddcf-e1ad-4a78-8a7a-2be9d729e3f1.mov">
|
||||
</video>
|
||||
|
||||
## Statement
|
||||
|
||||
Your goal for this challenge is to avoid all unnecessary change detection cycles and trigger a CD only when needed.
|
||||
Your goal for this challenge is to avoid all unnecessary change detection cycles and trigger a change detection only when needed.
|
||||
|
||||
## Constraint:
|
||||
|
||||
You cannot opt-out of zone.js. If this code is part of a large project and you opt out of zone.js, you will break many things within your application.
|
||||
You cannot opt-out of Zone.js globally. If this code is part of a large project and you opt out of Zone.js, you will break your application without any doubt.
|
||||
|
||||
---
|
||||
|
||||
@@ -49,7 +53,7 @@ Your PR title must start with <b>Answer:12</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A{challenge number}+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A{challenge number}+label%3A"answer+author"'
|
||||
alt="Optimize Change Detection solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,36 +2,40 @@
|
||||
title: 🟢 Default vs OnPush
|
||||
description: Challenge 34 is about learning the difference between Default and OnPush Change Detection Strategy.
|
||||
sidebar:
|
||||
order: 34
|
||||
order: 7
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
||||
:::
|
||||
|
||||
<div class="chip">Challenge #34</div>
|
||||
|
||||
## Information
|
||||
|
||||
In this series of challenges, you will learn how to optimize and enhance the performance of your Angular Application.
|
||||
In this challenge, we will explore the differences and impacts of using `ChangeDetectionStrategy.Default` versus `ChangeDetectionStrategy.OnPush`.
|
||||
|
||||
The first step is to download the [Angular DevTools Chrome extention](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) if you haven't already done so. This extension allows you to profile your application and detect performance issues.
|
||||
You can read the [Angular documentation](https://angular.io/guide/change-detection-skipping-subtrees) to learn more about the differences between these strategies.
|
||||
|
||||
In this challenge, we will explore the differences and impacts of using `ChangeDetectionStrategy.Default` versus `ChangeDetectionStrategy.OnPush`. To provide a clearer demonstration, I have added color enlightment to each component and each row in our application. However, in real-world scenarios, you will not have such visualization. This is where the Angular DevTool profiler comes to the rescue.
|
||||
In this challenge, all components start with the `Default` strategy. When you type letters inside the input field, you will notice that all components are highlighted in orange.
|
||||
|
||||
Start by serving this application by running: `npx nx serve performance-default-onpush` inside your terminal. Then open Chrome DevTool by pressing **F12** and switch to the Angular Tab. From there you can select the Profiler tab as shown below.
|
||||
:::note
|
||||
I added color highlighting to each component and each row to provide a better visualization of when a component is rerendered.
|
||||
:::
|
||||
|
||||

|
||||
As you can see, each letter triggers a new change detection cycle, and all components are rerendered, causing performance issues.
|
||||
|
||||
Start profiling your application and type some letters inside the input field. You will notice that each element of your application will flash at each change detection cycle and the profiler will show you a bar for each change detection cycle.
|
||||
Let's use the <b>Angular DevTool</b> to profile our application and understand how this tool can help us understand what is happening inside our application.
|
||||
|
||||
If you click on one of the bars (indicated by the yellow arrow on the picture below), you can see that `PersonListComponent`, `RandomComponent` and all the `MatListItem` are impacted by the change detection cycle, even when we only interact with the input field.
|
||||
:::note
|
||||
If you don't know how to use it, read [the performance introduction page](/challenges/angular-performance/) first and come back after.
|
||||
:::
|
||||
|
||||

|
||||
Now, start profiling your application and type some letters inside the input field to trigger some change detection cycles.
|
||||
|
||||
If you click on one of the bars (indicated by the yellow arrow in the picture below), you can see that `PersonListComponent`, `RandomComponent`, and all the `MatListItem` are impacted by the change detection cycle, even when we only interact with the input field.
|
||||
|
||||

|
||||
|
||||
## Statement
|
||||
|
||||
The goal of this challenge is to improve the clustering of change detection within the application.
|
||||
The goal of this challenge is to improve the clustering of change detection within the application using the `OnPush` change detection strategy, but not only...
|
||||
|
||||
## Hints:
|
||||
|
||||
@@ -66,7 +70,7 @@ Your PR title must start with <b>Answer:34</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A34+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A34+label%3A"answer+author"'
|
||||
alt="Default vs OnPush solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: 🟢 Memoization
|
||||
description: Challenge 35 is about learning
|
||||
sidebar:
|
||||
order: 8
|
||||
---
|
||||
|
||||
<div class="chip">Challenge #35</div>
|
||||
|
||||
## Information
|
||||
|
||||
In Angular, <b>pure Pipes</b> are very powerful because the value is memoized, which means if the input value doesn't change, the `transform` function of the pipe is not recomputed, and the cached value is outputted.
|
||||
|
||||
You can learn more about pipes in the [Angular documentation](https://angular.io/guide/pipes) and inside this [deep dive article](https://medium.com/ngconf/deep-dive-into-angular-pipes-c040588cd15d).
|
||||
|
||||
In this challenge, we start with a button to load a list of people. Each person is associated with a number, and we will use the Fibonacci calculation to create a heavy computation that will slow down the application.
|
||||
|
||||
Once the list is loaded, try typing some letters inside the input field. You will notice that the application is very slow, even though you are only performing very basic typing.
|
||||
|
||||
:::note
|
||||
We will not focus on the initial loading of the list in this challenge.
|
||||
:::
|
||||
|
||||
Let's use the <b>Angular DevTool</b> to profile our application and understand how this tool can help us understand what is happening inside our application.
|
||||
|
||||
:::note
|
||||
If you don't know how to use it, read [the performance introduction page](/challenges/angular-performance/) first and come back after.
|
||||
:::
|
||||
|
||||
Now, start profiling your application and type some letters inside the input field. You will see some red bars showing up inside the profiler panel.
|
||||
|
||||
If you click on one of the bars (indicated by the yellow arrow in the picture below), you will see that the change detection cycle is taking more than 3s in `PersonListComponent`.
|
||||
|
||||

|
||||
|
||||
## Statement
|
||||
|
||||
The goal of this challenge is to understand what is causing this latency and to improve it.
|
||||
|
||||
## Hints:
|
||||
|
||||
<details>
|
||||
<summary>Hint 1</summary>
|
||||
|
||||
Use `Pipes` to memoize the Fibonnaci computation.
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
:::note
|
||||
Start the project by running: `npx nx serve performance-memoized`.
|
||||
:::
|
||||
|
||||
:::tip[Reminder]
|
||||
Your PR title must start with <b>Answer:35</b>.
|
||||
:::
|
||||
|
||||
<div class="article-footer">
|
||||
<a
|
||||
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A35+label%3Aanswer"
|
||||
alt="Memoization community solutions">
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A35+label%3A"answer+author"'
|
||||
alt="Memoization solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
</div>
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: 🟢 NgFor Optimization
|
||||
description: Challenge 36 is about ...
|
||||
sidebar:
|
||||
order: 13
|
||||
badge: New
|
||||
---
|
||||
|
||||
<div class="chip">Challenge #36</div>
|
||||
|
||||
## Information
|
||||
|
||||
In this application, we have a list of individuals that we can add, delete or update. If you open the developer Chrome panel by pressing **F12**, go to he <b>source</b> tab, and expand the element to see the list, you will notice that each time, you add, delete or update a list item, the entire DOM elements are destroyed and initialized again. (See video below).
|
||||
|
||||
<video controls src="https://github.com/tomalaforge/angular-challenges/assets/30832608/71b90307-3ee3-42c0-a532-b67ce4f20bf6">
|
||||
</video>
|
||||
|
||||
We can also use the <b>Angular DevTool</b> to profile our application and understand what is happening inside our application. I will show you how to do it inside the following video.
|
||||
|
||||
<video controls src="https://github.com/tomalaforge/angular-challenges/assets/30832608/dd8108c6-1d89-4b05-9aa5-e760bd6f7f11">
|
||||
</video>
|
||||
|
||||
:::note
|
||||
If you don't know how to use it, read [the performance introduction page](/challenges/angular-performance/) first and come back after.
|
||||
:::
|
||||
|
||||
If you need more information about `NgFor`, I invite you to read the [documentation](https://angular.io/api/common/NgFor) first.
|
||||
|
||||
## Statement
|
||||
|
||||
The goal of this challenge is to understand what is causing this DOM refresh and to solve it.
|
||||
|
||||
---
|
||||
|
||||
:::note
|
||||
Start the project by running: `npx nx serve ngfor-optimize`.
|
||||
:::
|
||||
|
||||
:::tip[Reminder]
|
||||
Your PR title must start with <b>Answer:36</b>.
|
||||
:::
|
||||
|
||||
<div class="article-footer">
|
||||
<a
|
||||
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A36+label%3Aanswer"
|
||||
alt="NgFor Optimization community solutions">
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A36+label%3A"answer+author"'
|
||||
alt="NgFor Optimization solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
</div>
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: Angular Performance
|
||||
prev: false
|
||||
next: false
|
||||
description: Learn how to use the Angular Devtool chrome extension.
|
||||
sidebar:
|
||||
order: 1
|
||||
---
|
||||
|
||||
import { LinkCard } from '@astrojs/starlight/components';
|
||||
|
||||
In this series of challenges about performance, you will learn how to optimize and enhance the performance of your Angular application.
|
||||
|
||||
Before starting to resolve any challenge, I invite you to download the [Angular DevTools Chrome extention](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) if you haven't already done so.
|
||||
|
||||
This extension allows you to profile your application and detect performance issues, which is very useful for understanding where performance issues can occur.
|
||||
|
||||
## How to use it
|
||||
|
||||
When you serve an Angular application, you can inspect a page by pressing <b>F12</b>, which will open the <b>Chrome developer tools</b>. Then navigate to the <b>Angular tab</b>. From there, you can select the <b>Profiler tab</b> as shown below.
|
||||
|
||||

|
||||
|
||||
You can now profile your application by clicking on the record button. You can play with your application and see when change detection is triggered and which components are rerendered.
|
||||
|
||||
:::tip[Learn more]
|
||||
You can learn more on the [documentation page](https://angular.io/guide/devtools).
|
||||
:::
|
||||
|
||||
Now that you know how to use the <b>Angular DevTool</b>, you can choose a challenge, profile it, and resolve it.
|
||||
|
||||
<LinkCard
|
||||
title="🟠 Optimize Change Detection"
|
||||
description="Learn how to remove zone pollution."
|
||||
href="/challenges/angular-performance/12-scroll-cd/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🟢 Default vs OnPush"
|
||||
description="Learn the difference between Default and OnPush change detection strategies."
|
||||
href="/challenges/angular-performance/34-default-onpush/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🟢 Memoization"
|
||||
description="Learn the power of pure pipes."
|
||||
href="/challenges/angular-performance/35-memoize/"
|
||||
/>
|
||||
@@ -56,7 +56,16 @@ Your PR title must start with <b>Answer:1</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Projection blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
<a
|
||||
href="https://www.youtube.com/watch?v=npyEyUZxoIw&ab_channel=ArthurLannelucq"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Projection video by Arthur Lannelucq">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M23.5 6.2A3 3 0 0 0 21.4 4c-1.9-.5-9.4-.5-9.4-.5s-7.5 0-9.4.5A3 3 0 0 0 .5 6.3C0 8 0 12 0 12s0 4 .5 5.8A3 3 0 0 0 2.6 20c1.9.6 9.4.6 9.4.6s7.5 0 9.4-.6a3 3 0 0 0 2.1-2c.5-2 .5-5.9.5-5.9s0-4-.5-5.8zm-14 9.4V8.4l6.3 3.6-6.3 3.6z"></path></svg>
|
||||
Video
|
||||
<span class="flag">🇫🇷<span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🔴 Utility Wrapper Pipe
|
||||
description: Challenge 10 is about creating a pipe to wrap utilities
|
||||
sidebar:
|
||||
order: 10
|
||||
order: 202
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -40,7 +40,7 @@ Your PR title must start with <b>Answer:10</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A10+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A10+label%3A"answer+author"'
|
||||
alt="Utility Wrapper Pipe solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Highly Customizable CSS
|
||||
description: Challenge 13 is about creating highly customizable CSS styles
|
||||
sidebar:
|
||||
order: 13
|
||||
order: 104
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -42,7 +42,7 @@ Your PR title must start with <b>Answer:13</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A13+label%3A"answer+author"'
|
||||
alt="Highly Customizable CSS solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🔴 Master Dependancy Injection
|
||||
description: Challenge 16 is about masjering how dependancy injection works
|
||||
sidebar:
|
||||
order: 16
|
||||
order: 203
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -45,7 +45,7 @@ Your PR title must start with <b>Answer:16</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A16+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A16+label%3A"answer+author"'
|
||||
alt="Master Dependancy Injection solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟢 Anchor Navigation
|
||||
description: Challenge 21 is about navigating inside the page with anchor
|
||||
sidebar:
|
||||
order: 21
|
||||
order: 4
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -37,7 +37,7 @@ Your PR title must start with <b>Answer:21</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A21+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A21+label%3A"answer+author"'
|
||||
alt="Anchor Navigation solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟢 @RouterInput()
|
||||
description: Challenge 22 is about using the @Input decorator to retreive router params.
|
||||
sidebar:
|
||||
order: 22
|
||||
order: 5
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -32,7 +32,7 @@ Your PR title must start with <b>Answer:22</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A22+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A22+label%3A"answer+author"'
|
||||
alt="@RouterInput() solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -41,7 +41,7 @@ Your PR title must start with <b>Answer:22</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="@RouterInput() blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Directive Enhancement
|
||||
description: Challenge 3 is about enhancing a built-in directive
|
||||
sidebar:
|
||||
order: 3
|
||||
order: 101
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -60,7 +60,7 @@ Your PR title must start with <b>Answer:3</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A3+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A3+label%3A"answer+author"'
|
||||
alt="Directive Enhancement solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -69,7 +69,7 @@ Your PR title must start with <b>Answer:3</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Directive Enhancement blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🔴 Interoperability Rxjs/Signal
|
||||
description: Challenge 30 is about learning how to mix signal with Rxjs
|
||||
sidebar:
|
||||
order: 30
|
||||
order: 204
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -34,7 +34,7 @@ Your PR title must start with <b>Answer:30</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A30+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A30+label%3A"answer+author"'
|
||||
alt="Interoperability Rxjs/Signal solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟢 Module to Standalone
|
||||
description: Challenge 31 is about migrating a module based application to a standalone application.
|
||||
sidebar:
|
||||
order: 31
|
||||
order: 6
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -42,7 +42,7 @@ Your PR title must start with <b>Answer:31</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A31+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A31+label%3A"answer+author"'
|
||||
alt="Module to Standalone solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Change Detection Bug
|
||||
description: Challenge 32 is about debugging an application that has issue when change detection is triggered
|
||||
sidebar:
|
||||
order: 32
|
||||
order: 105
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -11,11 +11,13 @@ WIP: The following documentation will be reviewed and improved. However, you can
|
||||
|
||||
<div class="chip">Challenge #32</div>
|
||||
|
||||
:::note
|
||||
This challenge is inspired by a real-life example that I simplified to create this nice challenge.
|
||||
:::
|
||||
|
||||
## Information
|
||||
|
||||
In this small application, we have a navigation menu to route our application to either `barComponent` or `FooComponent`. However our application is not loading and no errors are displayed inside the console.
|
||||
In this small application, we have a navigation menu to route our application to either `BarComponent` or `FooComponent`. However our application is not loading and no errors are displayed inside the console.
|
||||
|
||||
## Statement
|
||||
|
||||
@@ -53,7 +55,7 @@ Your PR title must start with <b>Answer:32</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A32+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A32+label%3A"answer+author"'
|
||||
alt="Change Detection Bug solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Decoupling Components
|
||||
description: Challenge 33 is about decoupling two strongly coupled components using Injection Token
|
||||
sidebar:
|
||||
order: 33
|
||||
order: 106
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -50,7 +50,7 @@ Your PR title must start with <b>Answer:33</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A33+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A33+label%3A"answer+author"'
|
||||
alt="Decoupling Components solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🔴 Typed ContextOutlet
|
||||
description: Challenge 4 is about strongly typing ngContextOutlet directives
|
||||
sidebar:
|
||||
order: 4
|
||||
order: 201
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -58,7 +58,7 @@ Your PR title must start with <b>Answer:4</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A4+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A4+label%3A"answer+author"'
|
||||
alt="Typed ContextOutlet solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -67,7 +67,7 @@ Your PR title must start with <b>Answer:4</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Typed ContextOutlet blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟢 Crud application
|
||||
description: Challenge 5 is about refactoring a crud application
|
||||
sidebar:
|
||||
order: 5
|
||||
order: 2
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -67,12 +67,12 @@ Your PR title must start with <b>Answer:5</b>.
|
||||
|
||||
<div class="article-footer">
|
||||
<a
|
||||
href="https://jsonplaceholder.typicode.com/"
|
||||
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A5+label%3Aanswer"
|
||||
alt="Crud application community solutions">
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A5+label%3Aanswer'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A5+label%3A"answer+author"'
|
||||
alt="Crud application solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Structural Directive
|
||||
description: Challenge 6 is about creating a structural directive to handle permissions
|
||||
sidebar:
|
||||
order: 6
|
||||
order: 102
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -73,7 +73,7 @@ Your PR title must start with <b>Answer:6</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A6+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A6+label%3A"answer+author"'
|
||||
alt="Structural Directive solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -82,7 +82,7 @@ Your PR title must start with <b>Answer:6</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Structural Directive blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟢 Pure Pipe
|
||||
description: Challenge 8 is about creating a pure pipe
|
||||
sidebar:
|
||||
order: 8
|
||||
order: 3
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -40,7 +40,7 @@ Your PR title must start with <b>Answer:8</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A8+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A8+label%3A"answer+author"'
|
||||
alt="Pure Pipe solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -49,7 +49,7 @@ Your PR title must start with <b>Answer:8</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Pure Pipe blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Wrap Function Pipe
|
||||
description: Challenge 9 is about creating a pipe to wrap component fonctions
|
||||
sidebar:
|
||||
order: 9
|
||||
order: 103
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -41,7 +41,7 @@ Your PR title must start with <b>Answer:9</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A9+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A9+label%3A"answer+author"'
|
||||
alt="Wrap Function Pipe solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -50,7 +50,7 @@ Your PR title must start with <b>Answer:9</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Wrap Function Pipe blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Effect vs Selector
|
||||
description: Challenge 2 is about learning the difference between effects and selectors in NgRx
|
||||
sidebar:
|
||||
order: 2
|
||||
order: 113
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -48,7 +48,7 @@ Your PR title must start with <b>Answer:2</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A2+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A2+label%3A"answer+author"'
|
||||
alt="Effect vs Selector solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -57,7 +57,7 @@ Your PR title must start with <b>Answer:2</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Effect vs Selector blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🔴 Power of Effect
|
||||
description: Challenge 7 is about creating an Ngrx effect with another Rxjs Hot observable
|
||||
sidebar:
|
||||
order: 7
|
||||
order: 206
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -51,7 +51,7 @@ Your PR title must start with <b>Answer:7</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A7+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A7+label%3A"answer+author"'
|
||||
alt="Power of Effect solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🔴 Extend Lib Generator
|
||||
description: Challenge 25 is about creating a Nx generator to extend the built-in Library Generator
|
||||
sidebar:
|
||||
order: 25
|
||||
order: 207
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -67,7 +67,7 @@ Your PR title must start with <b>Answer:25</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A25+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A25+label%3A"answer+author"'
|
||||
alt="Extend Lib Generator solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Component Generator
|
||||
description: Challenge 26 is about creating a Nx generator to create a custom component
|
||||
sidebar:
|
||||
order: 26
|
||||
order: 116
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -155,7 +155,7 @@ Your PR title must start with <b>Answer:26</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A26+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A26+label%3A"answer+author"'
|
||||
alt="Component Generator solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟢 Custom Eslint Rule
|
||||
description: Challenge 27 is about creating a custom Eslint Rule to forbid enums
|
||||
sidebar:
|
||||
order: 27
|
||||
order: 12
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -36,7 +36,7 @@ Your PR title must start with <b>Answer:27</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A27+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A27+label%3A"answer+author"'
|
||||
alt="Custom Eslint Rule solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 High Order Operator Bug
|
||||
description: Challenge 11 is about resolving a Rxjs bug because of high order operators
|
||||
sidebar:
|
||||
order: 11
|
||||
order: 114
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -48,7 +48,7 @@ Your PR title must start with <b>Answer:11</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A11+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A11+label%3A"answer+author"'
|
||||
alt="High Order Operator Bug solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟢 Race Condition
|
||||
description: Challenge 14 is about race condition in Rxjs
|
||||
sidebar:
|
||||
order: 14
|
||||
order: 11
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -46,7 +46,7 @@ Your PR title must start with <b>Answer:14</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A14+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A14+label%3A"answer+author"'
|
||||
alt="Race Condition solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,34 +2,26 @@
|
||||
title: 🟠 Router
|
||||
description: Challenge 17 is about testing the router
|
||||
sidebar:
|
||||
order: 17
|
||||
order: 108
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
||||
:::
|
||||
|
||||
<div class="chip">Challenge #17</div>
|
||||
|
||||
## Information
|
||||
|
||||
Testing is a crucial step in building scalable, maintainable, and trustworthy applications.
|
||||
Testing should never be avoided, even in the face of short deadlines or strong pressure from the product team.
|
||||
Nowadays, there are numerous awesome tools available that make it easy to test your code and provide a great developer experience.
|
||||
We have a functional application that lists available books for borrowing inside a library. If the book you searched for is available, you will be directed to the corresponding book(s), otherwise, you will end up on an error page.
|
||||
|
||||
In this series of testing exercises, we will learn and master [Testing Library](https://testing-library.com/docs/) and [Cypress Component Testing](https://docs.cypress.io/guides/component-testing/angular/overview) that simplifies DOM manipulation for testing any Angular component.
|
||||
|
||||
## Statement:
|
||||
|
||||
We have a functional application that lists available books for borrowing inside a library. If the book you searched is available, you will be directed to the corresponding book(s), otherwise, you will end up on an error page.
|
||||
|
||||
The goal is to test this behavior with Testing library and Cypress
|
||||
|
||||
The file named `app.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-router-outlet`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
|
||||
The file named `app.component.spec.ts` will let you test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-router-outlet`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
|
||||
|
||||
For testing cypress, you will execute your test inside the `app.component.cy.ts` and run `npx nx component-test testing-router-outlet` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
|
||||
|
||||
I created some `it` blocks but feel free to add more test if you like to.
|
||||
# Statement
|
||||
|
||||
The goal is to test multiple behaviors of the application described in each test file using Testing library and Cypress Component Testing.
|
||||
|
||||
:::note
|
||||
I have created some `it` blocks but feel free to add more tests if you want.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
@@ -48,7 +40,7 @@ Your PR title must start with <b>Answer:17</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A17+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A17+label%3A"answer+author"'
|
||||
alt="Router solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,28 +2,30 @@
|
||||
title: 🟠 Nested Components
|
||||
description: Challenge 18 is about testing nested components
|
||||
sidebar:
|
||||
order: 18
|
||||
order: 109
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
||||
:::
|
||||
|
||||
<div class="chip">Challenge #18</div>
|
||||
|
||||
## Statement:
|
||||
## Information
|
||||
|
||||
We have a small application that sends a title, typed into an input to a fake backend.
|
||||
If the title is correctly typed, you can send the request otherwise you receive an error and the request is not sent.
|
||||
The application is created with <b>nested components</b>. `ChildComponent` is the container that includes four components: `ResultComponent`, `ButtonComponent`, `InputComponent` and `ErrorComponent`. However since we are testing our component as a black box, the architecture of our components doesn't change anything. You can create your test, change how the components are structured, and your tests should still pass. That's the goal of integration tests. <b>Never test internal implementation details!!!</b>.
|
||||
|
||||
We have a small application that send a title to a fake backend that you type inside a input.
|
||||
If the title is correctly typed, you can send the request otherwise you get a nice error and the request is not sent.
|
||||
You can play with it by running : `npx nx serve testing-nested`.
|
||||
|
||||
The goal is to test this behavior with Testing library and Cypress
|
||||
|
||||
The file named `child.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-nested`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
|
||||
|
||||
For testing cypress, you will execute your test inside the `child.component.cy.ts` and run `npx nx component-test testing-nested` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
|
||||
|
||||
I created some `it` blocks but feel free to add more test if you like to.
|
||||
# Statement
|
||||
|
||||
The goal is to test multiple behaviors of the application describe inside each test files using Testing library and Cypress Component Testing.
|
||||
|
||||
:::note
|
||||
I have created some `it` blocks but feel free to add more tests if you want.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
@@ -42,7 +44,7 @@ Your PR title must start with <b>Answer:18</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A18+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A18+label%3A"answer+author"'
|
||||
alt="Nested Components solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,27 +2,28 @@
|
||||
title: 🟠 Input Output
|
||||
description: Challenge 19 is about testing inputs and ouputs
|
||||
sidebar:
|
||||
order: 19
|
||||
order: 110
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
||||
:::
|
||||
|
||||
<div class="chip">Challenge #19</div>
|
||||
|
||||
## Statement:
|
||||
## Information:
|
||||
|
||||
We have a small counter application that increments or decrements a number. The `CounterComponent` takes an initial value as an `@Input` and emits the result of the counter as an `@Output` when we click on the **Send** button. Since we are testing our component as a black box, we only have access to our inputs and listen to the output values. <b>We should not rely on any internal implementation details!!!</b>
|
||||
|
||||
We have a small counter application that increment or decrement a number.
|
||||
You can play with it by running : `npx nx serve testing-input-output`.
|
||||
|
||||
The goal is to test `CounterComponent` with Testing library and Cypress
|
||||
The file named `counter.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-input-output`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
|
||||
|
||||
The file named `counter.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-nested`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
|
||||
For testing cypress, you will execute your test inside the `child.component.cy.ts` and run `npx nx component-test testing-input-output` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
|
||||
|
||||
For testing cypress, you will execute your test inside the `counter.component.cy.ts` and run `npx nx component-test testing-nested` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
|
||||
# Statement
|
||||
|
||||
I created some `it` blocks but feel free to add more test if you like to.
|
||||
The goal is to test multiple behaviors of the application describe inside each test files using Testing library and Cypress Component Testing.
|
||||
|
||||
:::note
|
||||
I have created some `it` blocks but feel free to add more tests if you want.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
@@ -41,7 +42,7 @@ Your PR title must start with <b>Answer:19</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A19+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A19+label%3A"answer+author"'
|
||||
alt="Input Output solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,30 +2,32 @@
|
||||
title: 🟠 Modal
|
||||
description: Challenge 20 is about testing modals
|
||||
sidebar:
|
||||
order: 20
|
||||
order: 111
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
||||
:::
|
||||
|
||||
<div class="chip">Challenge #20</div>
|
||||
|
||||
## Statement:
|
||||
## Information:
|
||||
|
||||
The goal of this challenge is to test dialogs inside your application.
|
||||
Within this program, you will get an error modal if the user doesn't input a name, while a confirmation modal will appear in all other cases.
|
||||
In the confirmation modal, if you click the "confirm" button, a message confirming the submission of the form will appear. Otherwise, if the user clicks on "Cancel", an error message will be displayed.
|
||||
In this small application, you have an input prompting you to enter a name, and a **Confirm** button to submit your form.
|
||||
If you enter a name, a confirmation modal will appear; otherwise an error modal will be displayed.
|
||||
In the confirmation modal, if you click the **Confirm** button, a message confirming the submission of the form will appear. If the user clicks on **Cancel**, an error message will be displayed.
|
||||
|
||||
The goal of this challenge is to test the dialogs inside your application. To do so, we will test the full application like an end-to-end test will do. This means, we will test the `AppComponent` as a black box and react to events on the page. <b>No internal details should be tested</b>. The difference between an e2e test and integration test is that we will mock all API calls. _(All http requests are faked inside this application, but this would not be the case in a real entreprice application.)_
|
||||
|
||||
You can play with it by running : `npx nx serve testing-modal`.
|
||||
|
||||
The goal is to test this behavior with Testing library and Cypress
|
||||
|
||||
The file named `app.component.spec.ts` will let test your application using Testing Library. To run the test suits, you need to run `npx nx test testing-modal`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
|
||||
|
||||
For testing cypress, you will execute your test inside the `app.component.cy.ts` and run `npx nx component-test testing-modal` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
|
||||
|
||||
I created some `it` blocks but feel free to add more test if you like to.
|
||||
# Statement
|
||||
|
||||
The goal is to test multiple behaviors of the application describe inside each test files using Testing library and Cypress Component Testing.
|
||||
|
||||
:::note
|
||||
I have created some `it` blocks but feel free to add more tests if you want.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
@@ -44,7 +46,7 @@ Your PR title must start with <b>Answer:20</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A20+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A20+label%3A"answer+author"'
|
||||
alt="Modal solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟢 Harness
|
||||
description: Challenge 23 is about testing with component harnesses
|
||||
sidebar:
|
||||
order: 23
|
||||
order: 9
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -39,7 +39,7 @@ Your PR title must start with <b>Answer:23</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A23+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A23+label%3A"answer+author"'
|
||||
alt="Harness solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Harness Creation
|
||||
description: Challenge 24 is about creating a component harness.
|
||||
sidebar:
|
||||
order: 24
|
||||
order: 112
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -63,7 +63,7 @@ Your PR title must start with <b>Answer:24</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A24+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A24+label%3A"answer+author"'
|
||||
alt="Harness Creation solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,26 +2,26 @@
|
||||
title: 🟢 Checkbox
|
||||
description: Challenge 28 is about testing a simple checkbox
|
||||
sidebar:
|
||||
order: 28
|
||||
order: 10
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
||||
:::
|
||||
|
||||
<div class="chip">Challenge #28</div>
|
||||
|
||||
## Information
|
||||
|
||||
This is the perfect example to get started with `Testing Library`.
|
||||
This application is very simple. It consists of a checkbox that enables or disables a button. The primary goal of this application is to become familiar with the debug API of Testing Library. Knowing how to debug your tests is a crucial tool you need to have in your toolkit.
|
||||
|
||||
You will need to only check if the button gets enabled when clicking on the checkbox
|
||||
You can find the documentation about debugging in Testing Library [here](https://testing-library.com/docs/dom-testing-library/api-debugging#screenlogtestingplaygroundurl).
|
||||
|
||||
You can look into debug function to get full power of `Testing Library` like:
|
||||
The main functions to remember are as follows:
|
||||
|
||||
- logRoles(...);
|
||||
- screen.debug(); // you can pass a element as input
|
||||
- screen.logTestingPlaygroundURL(); // you can pass a element as input
|
||||
- `logRoles(myDOMElement)`: prints out all ARIA roles within the tree of the given DOM element. ARIA roles are the primary selectors you should reach for in the first place.
|
||||
- `screen.debug()` or `screen.debug(myDOMElement)`: prints the DOM inside the console.
|
||||
- `screen.logTestingPlaygroundURL()` or `screen.logTestingPlaygroundURL(myDOMElement)`: this function is very powerful. It will create a playground to expose all elements, and you can interact with it to see the selectors you should choose for a DOM element.
|
||||
|
||||
## Statement
|
||||
|
||||
The goal of this challenge is not to submit an answer, but you can if you want. It's more about using the debugging API to play around. These tools will be of great help for the upcoming testing challenges.
|
||||
|
||||
---
|
||||
|
||||
@@ -40,7 +40,7 @@ Your PR title must start with <b>Answer:28</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A28+label%3A"answer+author"'
|
||||
alt="Checkbox solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
@@ -2,25 +2,34 @@
|
||||
title: 🔴 Real-life Application
|
||||
description: Challenge 29 is about testing a real-life application
|
||||
sidebar:
|
||||
order: 29
|
||||
order: 205
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
||||
:::
|
||||
|
||||
<div class="chip">Challenge #29</div>
|
||||
|
||||
## Statement:
|
||||
## Information:
|
||||
|
||||
I built this more real life application to create more real life test cases.
|
||||
In this application, you can search for tickets, you can assign or finish them. You can also create new tickets.
|
||||
This application presents a greater challenge because it closely resembles a real-life application that you might encounter in your day-to-day activities as an Angular developer. What makes it more difficult is the need to handle asynchronous tasks and create appropriate mocks.
|
||||
|
||||
This is a very simple application, but it will let you deal with asynchronous task and mocks
|
||||
The application is a typical todo list application. You can filter tickets, create new ones, assign each ticket, close others, and navigate to the details of each ticket.
|
||||
|
||||
The goal of this challenge is to write all test cases of `ticket.store` , `list.component` and `row.component` with Testing Library.
|
||||
In this challenge, you will write tests for the `ListComponent`, which represents the global view, and the `RowComponent`, which represents a specific ticket. Additionally, you will need to write unit tests for the `TicketStoreService` using Testing Library. _This library allows you to test services effectively._
|
||||
|
||||
You can also do it with cypress.
|
||||
Handling asynchronous tasks will be particularly challenging. It's important not to introduce any explicit <b>waits</b> in your tests, as this would introduce unnecessary delays. Instead, it's better to look for an element that needs to appear or disappear from the DOM. In this case, the test will naturally wait for the correct period of time, as the waits are already implemented within both libraries. Take advantage of these built-in functionalities to create efficient and reliable tests.
|
||||
|
||||
You can play with it by running : `npx nx serve testing-todos-list`.
|
||||
|
||||
To run Testing Library test suits, you need to run `npx nx test testing-input-output`. You can also install [Jest Runner](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner) to execute your test by clicking on the `Run` button above each `describe` or `it` blocks.
|
||||
|
||||
For testing cypress, you will execute your test inside the `child.component.cy.ts` and run `npx nx component-test testing-input-output` to execute your test suits. You can add the `--watch` flag to execute your test in watch mode.
|
||||
|
||||
# Statement
|
||||
|
||||
The goal is to test multiple behaviors of the application describe inside each test files using Testing library and Cypress Component Testing.
|
||||
|
||||
:::note
|
||||
I have created some `it` blocks but feel free to add more tests if you want.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
@@ -39,7 +48,7 @@ Your PR title must start with <b>Answer:29</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A29+label%3A%22answer+author%22'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A29+label%3A"answer+author"'
|
||||
alt="Real-life Application solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
|
||||
70
docs/src/content/docs/challenges/testing/index.mdx
Normal file
70
docs/src/content/docs/challenges/testing/index.mdx
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: Testing
|
||||
prev: false
|
||||
next: false
|
||||
description: Introduction to testing challenges.
|
||||
sidebar:
|
||||
order: 1
|
||||
---
|
||||
|
||||
import { LinkCard } from '@astrojs/starlight/components';
|
||||
|
||||
Testing is a crucial step in building scalable, maintainable, and trustworthy applications.
|
||||
Testing should never be avoided, even in the face of short deadlines or strong pressure from the product team.
|
||||
Nowadays, there are numerous awesome tools available that make it easy to test your code and provide a great developer experience.
|
||||
|
||||
In this series of testing exercises, we will learn and master [Testing Library](https://testing-library.com/docs/) and [Cypress Component Testing](https://docs.cypress.io/guides/component-testing/angular/overview) that simplifies DOM manipulation for testing any Angular component.
|
||||
|
||||
The benefits of using <b>Testing Library</b> or <b>Cypress Component Testing</b> are to test your component as a black box. You will only interact with what the user can do on the UI. However, the difference with end-to-end tests is that the backend is mocked, which makes the tests faster and more maintainable.
|
||||
The goal is to mock as little as possible to test your component at a higher level than unit testing, which will make refactoring easier.
|
||||
Within a real application, integration tests are the tests you will write the most. Learning how to write them will make your application more robust and more maintainable.
|
||||
|
||||
Here is a series of 8 challenges that you can take in any order.
|
||||
|
||||
<LinkCard
|
||||
title="🟢 Harness"
|
||||
description="Learn how to test using Angular CDK Component harnesses"
|
||||
href="/challenges/testing/23-harness/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🟢 Checkbox"
|
||||
description="Learn how to debug your tests using Testing Library on a simple checkbox application"
|
||||
href="/challenges/testing/28-checkbox/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🟠 Router"
|
||||
description="Learn how to test the routed components"
|
||||
href="/challenges/testing/17-router/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🟠 Nested Components"
|
||||
description="Learn how to test nested components"
|
||||
href="/challenges/testing/18-nested-comp/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🟠 Input Output"
|
||||
description="Learn how to test inputs and outputs"
|
||||
href="/challenges/testing/19-input-output/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🟠 Modal"
|
||||
description="Learn how to test a modal component"
|
||||
href="/challenges/testing/20-modal/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🟠 Harness Creation"
|
||||
description="Learn how to create harness on your own components"
|
||||
href="/challenges/testing/24-harness-creation/"
|
||||
/>
|
||||
|
||||
<LinkCard
|
||||
title="🔴 Real-life Application"
|
||||
description="Learn how to write a series of test for a real-life applications"
|
||||
href="/challenges/testing/29-real-application/"
|
||||
/>
|
||||
@@ -2,7 +2,7 @@
|
||||
title: 🟠 Function Overload
|
||||
description: Challenge 15 is about creating overload functions
|
||||
sidebar:
|
||||
order: 15
|
||||
order: 115
|
||||
---
|
||||
|
||||
:::note
|
||||
@@ -42,7 +42,7 @@ Your PR title must start with <b>Answer:15</b>.
|
||||
❖ Community Answers
|
||||
</a>
|
||||
<a
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A15+label%3A'
|
||||
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A15+label%3A"answer+author"'
|
||||
alt="Function Overload solution author">
|
||||
▶︎ Author Answer
|
||||
</a>
|
||||
@@ -51,7 +51,7 @@ Your PR title must start with <b>Answer:15</b>.
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
alt="Function Overload blog article">
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
<svg aria-hidden="true" class="astro-yzt5nm4y astro-lq7oo3uf" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="--sl-icon-size: 1.5rem;"><path d="M9 10h1a1 1 0 1 0 0-2H9a1 1 0 0 0 0 2Zm0 2a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2H9Zm11-3.06a1.3 1.3 0 0 0-.06-.27v-.09c-.05-.1-.11-.2-.19-.28l-6-6a1.07 1.07 0 0 0-.28-.19h-.09a.88.88 0 0 0-.33-.11H7a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V8.94Zm-6-3.53L16.59 8H15a1 1 0 0 1-1-1V5.41ZM18 19a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5v3a3 3 0 0 0 3 3h3v9Zm-3-3H9a1 1 0 0 0 0 2h6a1 1 0 0 0 0-2Z"></path></svg>
|
||||
Blog Post
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,16 @@ sidebar:
|
||||
order: 4
|
||||
---
|
||||
|
||||
:::note
|
||||
WIP:
|
||||
:::
|
||||
You can contribute to this repository in many ways:
|
||||
|
||||
🔥 Create a new challenge by following the intructions [here](/guides/create-challenge).
|
||||
|
||||
🔥 Answer challenges and submit the results. (guide [here](/guides/resolve-challenge)).
|
||||
|
||||
🔥 Comment on other's solutions by providing constructive and caring feedback.
|
||||
|
||||
🔥 Correct typos or English mistakes within the documentation.
|
||||
|
||||
🔥 File an issue to suggest new challenge ideas or report a bug.
|
||||
|
||||
🔥 Sponsor the project [here](https://github.com/sponsors/tomalaforge)
|
||||
|
||||
@@ -23,8 +23,8 @@ hero:
|
||||
import { Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
<CardGrid>
|
||||
<Card title="35 Challenges">
|
||||
This repository gathers 35 Challenges related to <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> and <b>Typescript</b>.
|
||||
<Card title="36 Challenges">
|
||||
This repository gathers 36 Challenges related to <b>Angular</b>, <b>Nx</b>, <b>RxJS</b>, <b>Ngrx</b> and <b>Typescript</b>.
|
||||
These challenges resolve around real-life issues or specific features to elevate your skills.
|
||||
</Card>
|
||||
|
||||
@@ -56,7 +56,10 @@ import { Card, CardGrid } from '@astrojs/starlight/components';
|
||||
---
|
||||
|
||||
<div class="article-footer">
|
||||
<a href="https://github.com/sponsors/tomalaforge" alt="Sponsor link">
|
||||
<a
|
||||
href="https://github.com/sponsors/tomalaforge"
|
||||
alt="Sponsor link"
|
||||
class="primary action astro-yjy4zhro">
|
||||
🤍 Sponsor the Project
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,18 +2,30 @@
|
||||
--sl-color-black: #1b1b1d;
|
||||
--sl-color-gray-6: #242526;
|
||||
--sl-color-accent-high: #f10023;
|
||||
/* --sl-color-black: white; */
|
||||
--sl-icon-color: #fff;
|
||||
--sl-color-text-invert: #fff;
|
||||
--primary-color: var(--sl-color-bg-nav) !important;
|
||||
/* --sl-color-text-invert: #212121; */
|
||||
--cardBgColor: #242526;
|
||||
/* --sl-font: 'IBM Plex Serif', serif; */
|
||||
|
||||
--sl-hue-purple: 41;
|
||||
--sl-color-purple-low: hsl(var(--sl-hue-orange), 39%, 22%);
|
||||
--sl-color-purple: hsl(var(--sl-hue-orange), 82%, 63%);
|
||||
--sl-color-purple-high: hsl(var(--sl-hue-orange), 82%, 87%);
|
||||
|
||||
--color-btn: var(--sl-color-white);
|
||||
--color-chip: rgb(35, 38, 47);
|
||||
--color-chip-border: rgba(240, 246, 252, 0.1);
|
||||
}
|
||||
|
||||
:root[data-theme='light'],
|
||||
[data-theme='light'] {
|
||||
--sl-color-accent: #f10023;
|
||||
--sl-color-accent-high: #f10023;
|
||||
--sl-icon-color: rgb(35, 38, 47);
|
||||
|
||||
--color-btn: white;
|
||||
--color-chip: white;
|
||||
--color-chip-border: rgb(33, 38, 45);
|
||||
}
|
||||
|
||||
.github-success-btn {
|
||||
@@ -21,7 +33,7 @@
|
||||
border-radius: 6px;
|
||||
padding: 2px 8px;
|
||||
background-color: rgb(35, 134, 54);
|
||||
color: var(--sl-color-white);
|
||||
color: var(-color-btn);
|
||||
}
|
||||
|
||||
.github-neutral-btn {
|
||||
@@ -38,12 +50,13 @@
|
||||
}
|
||||
|
||||
.chip {
|
||||
border: 1px solid rgba(240, 246, 252, 0.1);
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--color-chip-border);
|
||||
border-radius: 6px;
|
||||
padding: 2px 8px;
|
||||
background-color: rgb(33, 38, 45);
|
||||
color: rgb(201, 209, 217);
|
||||
fill: rgb(201, 209, 217);
|
||||
background-color: var(--color-chip);
|
||||
color: var(--sl-color-text);
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
@@ -54,14 +67,14 @@
|
||||
flex-wrap: wrap;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.article-footer > a {
|
||||
border: 1px solid var(--sl-color-accent-high);
|
||||
border-radius: 999rem;
|
||||
padding: 1rem;
|
||||
text-decoration: none;
|
||||
color: var(--sl-color-gray-2);
|
||||
color: var(--color-btn);
|
||||
box-shadow: var(--sl-shadow-md);
|
||||
color: var(--sl-color-white);
|
||||
font-size: var(--sl-text-lg);
|
||||
line-height: var(--sl-line-height-headings);
|
||||
display: flex;
|
||||
@@ -72,14 +85,19 @@
|
||||
background-color: var(--sl-color-accent-high);
|
||||
}
|
||||
|
||||
a.primary {
|
||||
color: var(--sl-color-white) !important;
|
||||
a.primary,
|
||||
a.primary > svg {
|
||||
color: var(--color-btn) !important;
|
||||
}
|
||||
|
||||
b {
|
||||
color: var(--sl-color-accent-high);
|
||||
}
|
||||
|
||||
.starlight-aside--tip b {
|
||||
color: var(--sl-color-asides-text-accent);
|
||||
}
|
||||
|
||||
.main-page-footer {
|
||||
margin-top: 2rem !important;
|
||||
font-size: var(--sl-text-sm);
|
||||
@@ -96,3 +114,9 @@ b {
|
||||
starlight-menu-button svg {
|
||||
color: #1c1a1d;
|
||||
}
|
||||
|
||||
.flag {
|
||||
background-color: white;
|
||||
padding: 1px 2px;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user