diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000000000..652e5dc35e0cd6 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,30 @@ +ARG VARIANT=20.04 +FROM mcr.microsoft.com/devcontainers/base:ubuntu-${VARIANT} + +ARG NODE_VERSION=18 +ARG MONGODB_VERSION=6.0.4 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y sudo && \ + curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | sudo -E bash - && \ + sudo apt-get install -y nodejs && \ + sudo apt-get install -y libcurl4 openssl liblzma5 && \ + mkdir -p /tmp/mongodb && \ + cd /tmp/mongodb && \ + wget -qOmongodb.tgz https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-${MONGODB_VERSION}.tgz && \ + tar -zxvf mongodb.tgz && \ + cd mongodb-* && \ + sudo cp bin/* /usr/local/bin/ && \ + rm -rf /tmp/mongodb && \ + sudo mkdir -p /data/db && \ + sudo chown vscode:vscode -R /data/db + +# Setup ENV +ENV COOKIE_DOMAIN=github.dev +ENV HOME_LOCATION=https://$CODESPACE_NAME-8000.$GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN +ENV API_LOCATION=https://$CODESPACE_NAME-3000.$GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN +ENV CYPRESS_BASE_URL=https://$CODESPACE_NAME-8000.$GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN +ENV REACT_APP_CHALLENGE_EDITOR_API_LOCATION=https://$CODESPACE_NAME-3200.$GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN +ENV CHALLENGE_EDITOR_CLIENT_LOCATION=https://$CODESPACE_NAME-3300.$GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN + diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000000000..3208a7fcb7c303 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,24 @@ +{ + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "freeCodeCamp.freecodecamp-dark-vscode-theme" + ] + } + }, + "dockerFile": "Dockerfile", + "forwardPorts": [3000, 8000, 27017], + "portsAttributes": { + "8000": { + "label": "Learn", + "onAutoForward": "openPreview" + } + }, + "postCreateCommand": "cp sample.env .env && npm ci", + // It is more reliable to start these processes oneself + // "postStartCommand": "mongod &", + // "postAttachCommand": "npm run develop", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}" +} diff --git a/.devcontainer/docs/Dockerfile b/.devcontainer/docs/Dockerfile new file mode 100644 index 00000000000000..678e47248012f5 --- /dev/null +++ b/.devcontainer/docs/Dockerfile @@ -0,0 +1,6 @@ +FROM node:18-alpine + +# Install git +RUN apk add --no-cache git + +RUN npm install -g docsify-cli prettier eslint diff --git a/.devcontainer/docs/devcontainer.json b/.devcontainer/docs/devcontainer.json new file mode 100644 index 00000000000000..646851488890da --- /dev/null +++ b/.devcontainer/docs/devcontainer.json @@ -0,0 +1,24 @@ +{ + "context": "../..", + "customizations": { + "codespaces": { + "openFiles": ["docs/how-to-work-on-the-docs-theme.md"] + }, + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "freeCodeCamp.freecodecamp-dark-vscode-theme" + ] + } + }, + "dockerFile": "Dockerfile", + "forwardPorts": [3400], + "portsAttributes": { + "3400": { + "label": "Docs", + "onAutoForward": "openPreview" + } + }, + "postAttachCommand": "npm run docs:serve" +} diff --git a/.eslintignore b/.eslintignore index b69c5e33fcdce0..f73fb4cf88be8d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,6 +5,7 @@ api-server/src/public/** api-server/lib/** config/i18n.js config/certification-settings.js +config/donation-settings.js config/superblock-order.js web/** docs/**/*.md diff --git a/.eslintrc.json b/.eslintrc.json index d0bd51611849c8..c1349259d4ce32 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -55,12 +55,15 @@ "parser": "@typescript-eslint/parser", "parserOptions": { "project": [ + "./client/tsconfig.json", "./tsconfig.json", + "./api/tsconfig.json", "./config/tsconfig.json", "./tools/ui-components/tsconfig.json", "./utils/tsconfig.json", "./web/tsconfig.json", - "./curriculum-server/tsconfig.json" + "./curriculum-server/tsconfig.json", + "./cypress/tsconfig.json" ] }, "extends": [ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fb4b2175b69b82..6418cf05b658b8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -17,7 +17,7 @@ *.md package.json -package-lock.json +pnpm-lock.yaml # ------------------------------------------------- # All files in the root are owned by dev team @@ -28,7 +28,7 @@ package-lock.json # --- Owned by none (negate rule above) --- /package.json -/package-lock.json +/pnpm-lock.yaml # ------------------------------------------------- # Files that need attention from Staff diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 24f617ec82b415..d95ff61a37ec67 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,10 +2,10 @@ Checklist: -- [] I have read [freeCodeCamp's contribution guidelines](https://contribute.freecodecamp.org). -- [] My pull request has a descriptive title (not a vague title like `Update index.md`) -- [] My pull request targets the `main` branch of freeCodeCamp. -- [] I have tested these changes either locally on my machine, or GitPod. +- [ ] I have read and followed the [contribution guidelines](https://contribute.freecodecamp.org). +- [ ] I have read and followed the [how to open a pull request guide](https://contribute.freecodecamp.org/#/how-to-open-a-pull-request). +- [ ] My pull request targets the `main` branch of freeCodeCamp. +- [ ] I have tested these changes either locally on my machine, or GitPod. diff --git a/.github/labeler.yml b/.github/labeler.yml index cae5f5099b469a..1581cb23b3db00 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -23,4 +23,3 @@ - client/i18n/**/* - config/crowdin/**/* - config/i18n/**/* - - tools/crowdin/**/* diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 122a159d1b2df3..b031dbdb42a726 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,13 +1,15 @@ name: CI - Run CodeQL Analysis on: push: - branches: [main] paths-ignore: - 'docs/**' + branches: + - 'main' pull_request: - branches: [main] paths-ignore: - 'docs/**' + branches: + - 'main' permissions: contents: read @@ -30,10 +32,10 @@ jobs: language: ['javascript'] steps: - name: Checkout repository - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - name: Setup CodeQL - uses: github/codeql-action/init@b2a92eb56d8cb930006a1c6ed86b0782dd8a4297 # v2 + uses: github/codeql-action/init@32dc499307d133bb5085bae78498c0ac2cf762d5 # v2 with: languages: ${{ matrix.language }} - name: Perform Analysis - uses: github/codeql-action/analyze@b2a92eb56d8cb930006a1c6ed86b0782dd8a4297 # v2 + uses: github/codeql-action/analyze@32dc499307d133bb5085bae78498c0ac2cf762d5 # v2 diff --git a/.github/workflows/codesee-diagram.yml b/.github/workflows/codesee-diagram.yml index 007153cbd5aa81..5f03fb8b8bba12 100644 --- a/.github/workflows/codesee-diagram.yml +++ b/.github/workflows/codesee-diagram.yml @@ -9,76 +9,15 @@ on: - 'docs/**' types: [opened, synchronize, reopened] +permissions: read-all + jobs: - test_map_action: + codesee: runs-on: ubuntu-20.04 if: ${{ github.actor != 'renovate[bot]' && github.actor != 'camperbot' }} continue-on-error: true - name: Run CodeSee Map Analysis + name: Analyze the repo with CodeSee steps: - - name: checkout - id: checkout - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 - with: - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.ref }} - fetch-depth: 0 - - # codesee-detect-languages has an output with id languages. - - name: Detect Languages - id: detect-languages - uses: Codesee-io/codesee-detect-languages-action@latest - - - name: Configure JDK 16 - uses: actions/setup-java@19eeec562b37d29a1ad055b7de9c280bd0906d8d # v3 - if: ${{ fromJSON(steps.detect-languages.outputs.languages).java }} - with: - java-version: '16' - distribution: 'zulu' - - # CodeSee Maps Go support uses a static binary so there's no setup step required. - - - name: Configure Node.js 16 - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 - if: ${{ fromJSON(steps.detect-languages.outputs.languages).javascript }} - with: - node-version: '16' - - - name: Configure Python 3.x - uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 # tag=v4 - if: ${{ fromJSON(steps.detect-languages.outputs.languages).python }} - with: - python-version: '3.x' - architecture: 'x64' - - - name: Configure Ruby '3.x' - uses: ruby/setup-ruby@v1 - if: ${{ fromJSON(steps.detect-languages.outputs.languages).ruby }} - with: - ruby-version: '3.0' - - # CodeSee Maps Rust support uses a static binary so there's no setup step required. - - - name: Generate Map - id: generate-map - uses: Codesee-io/codesee-map-action@latest - with: - step: map - github_ref: ${{ github.ref }} - languages: ${{ steps.detect-languages.outputs.languages }} - - - name: Upload Map - id: upload-map - uses: Codesee-io/codesee-map-action@latest - with: - step: mapUpload - api_token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} - github_ref: ${{ github.ref }} - - - name: Insights - id: insights - uses: Codesee-io/codesee-map-action@latest + - uses: Codesee-io/codesee-action@ab0fd0985bb57b40f5c80661430b8184f5bad31e # v2 with: - step: insights - api_token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} - github_ref: ${{ github.ref }} + codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} diff --git a/.github/workflows/crowdin-download.client-ui.yml b/.github/workflows/crowdin-download.client-ui.yml index 6a03a3f108f5dd..eb9348bb6966b0 100644 --- a/.github/workflows/crowdin-download.client-ui.yml +++ b/.github/workflows/crowdin-download.client-ui.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 with: token: ${{ secrets.CROWDIN_CAMPERBOT_PAT }} diff --git a/.github/workflows/crowdin-download.curriculum.yml b/.github/workflows/crowdin-download.curriculum.yml index 5d82cbc62b3eba..d72cda53b62419 100644 --- a/.github/workflows/crowdin-download.curriculum.yml +++ b/.github/workflows/crowdin-download.curriculum.yml @@ -17,12 +17,12 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - node-version: [16.x] + node-version: [18.x] fail-fast: true steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 with: token: ${{ secrets.CROWDIN_CAMPERBOT_PAT }} @@ -276,9 +276,13 @@ jobs: # Validate the Download # # All languages should go ABOVE this. # + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -290,15 +294,15 @@ jobs: - name: Build Source Files run: | - echo npm version $(npm -v) - npm ci - npm run create:config - npm run build:curriculum - npm run build:server + echo pnpm version $(pnpm -v) + pnpm install + pnpm run create:config + pnpm run build:curriculum + pnpm run build:server - name: Lint and Format Files run: | - npm run format:curriculum + pnpm run format:curriculum # We do not need to run tests because they are run after the PR is created. diff --git a/.github/workflows/crowdin-download.docs.yml b/.github/workflows/crowdin-download.docs.yml index c1cbdce22cea7d..5008a30123d9ee 100644 --- a/.github/workflows/crowdin-download.docs.yml +++ b/.github/workflows/crowdin-download.docs.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 with: token: ${{ secrets.CROWDIN_CAMPERBOT_PAT }} diff --git a/.github/workflows/crowdin-upload.client-ui.yml b/.github/workflows/crowdin-upload.client-ui.yml index fdf22f6bb26b6c..c1157d3243355c 100644 --- a/.github/workflows/crowdin-upload.client-ui.yml +++ b/.github/workflows/crowdin-upload.client-ui.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - name: Generate Crowdin Config uses: freecodecamp/crowdin-action@main diff --git a/.github/workflows/crowdin-upload.curriculum.yml b/.github/workflows/crowdin-upload.curriculum.yml index 0453108db912c8..3f1cd1c3eabc0f 100644 --- a/.github/workflows/crowdin-upload.curriculum.yml +++ b/.github/workflows/crowdin-upload.curriculum.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - name: Generate Crowdin Config uses: freecodecamp/crowdin-action@main diff --git a/.github/workflows/crowdin-upload.docs.yml b/.github/workflows/crowdin-upload.docs.yml index ead433d6439e06..c7eaf0ff98b5da 100644 --- a/.github/workflows/crowdin-upload.docs.yml +++ b/.github/workflows/crowdin-upload.docs.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - name: Generate Crowdin Config uses: freecodecamp/crowdin-action@main diff --git a/.github/workflows/e2e-mobile.yml b/.github/workflows/e2e-mobile.yml index 8e911c44f5528f..5a558be91c3d62 100644 --- a/.github/workflows/e2e-mobile.yml +++ b/.github/workflows/e2e-mobile.yml @@ -4,31 +4,42 @@ on: # push: # paths-ignore: # - 'docs/**' - # branches-ignore: - # - 'renovate/**' + # branches: + # - 'main' # pull_request: # paths-ignore: # - 'docs/**' + # branches: + # - 'main' + # - 'next-**' jobs: mobile-test: name: Test curriculum for mobile app runs-on: ubuntu-20.04 + strategy: + matrix: + node-version: [18.x] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - name: Checkout mobile - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 with: repository: freeCodeCamp/mobile path: mobile - - name: Use Node.js 16.x - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 with: - node-version: 16.x + version: 7 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 + with: + node-version: ${{ matrix.node-version }} - name: Setup Flutter 3.3.x uses: subosito/flutter-action@dbf1fa04f4d2e52c33185153d06cdb5443aa189d # tag=v2 @@ -44,9 +55,9 @@ jobs: - name: Install and Build run: | - npm ci - npm run create:config - npm run build:curriculum + pnpm install + pnpm run create:config + pnpm run build:curriculum - name: Generate mobile test files run: | diff --git a/.github/workflows/e2e-third-party.yml b/.github/workflows/e2e-third-party.yml index 96fce5c650faac..edeb766e6ca227 100644 --- a/.github/workflows/e2e-third-party.yml +++ b/.github/workflows/e2e-third-party.yml @@ -5,7 +5,7 @@ name: CI - E2E - 3rd party donation tests on: push: branches: - - 'prod-*' + - 'prod-**' paths-ignore: - 'docs/**' @@ -13,6 +13,9 @@ jobs: do-everything: name: Build & Test runs-on: ubuntu-20.04 + strategy: + matrix: + node-version: [18.x] services: mongodb: image: mongo:4.4 @@ -26,18 +29,23 @@ jobs: steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - name: Checkout client-config - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 with: repository: freeCodeCamp/client-config path: client-config - - name: Use Node.js 16.x - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 with: - node-version: 16.x + version: 7 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 + with: + node-version: ${{ matrix.node-version }} - name: Set freeCodeCamp Environment Variables run: | @@ -49,10 +57,10 @@ jobs: - name: Install and Build run: | - npm ci - npm run build + pnpm install + pnpm run build - name: Seed Database - run: npm run seed + run: pnpm run seed - name: Move serve.json to Public Folder run: cp client-config/serve.json client/public/serve.json @@ -60,10 +68,10 @@ jobs: uses: cypress-io/github-action@v4 with: record: ${{ env.CYPRESS_RECORD_KEY != 0 }} - start: npm run start-ci + start: pnpm run start-ci wait-on: http://localhost:8000 wait-on-timeout: 1200 config: baseUrl=http://localhost:8000 browser: chrome - spec: cypress/e2e/third-party/*.js + spec: cypress/e2e/third-party/*.{js,ts} diff --git a/.github/workflows/e2e-web.yml b/.github/workflows/e2e-web.yml index c014b5e96e2375..750e439d3bf8fa 100644 --- a/.github/workflows/e2e-web.yml +++ b/.github/workflows/e2e-web.yml @@ -3,42 +3,50 @@ on: push: paths-ignore: - 'docs/**' - branches-ignore: - - 'renovate/**' - - 'next-api' + branches: + - 'main' pull_request: paths-ignore: - 'docs/**' - branches-ignore: - - 'next-api' + branches: + - 'main' + - 'next-**' jobs: build-client: name: Build runs-on: ubuntu-20.04 + strategy: + matrix: + node-version: [18.x] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - name: Checkout client-config - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 with: repository: freeCodeCamp/client-config path: client-config - - name: Use Node.js 16.x - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: - node-version: 16.x + node-version: ${{ matrix.node-version }} - name: Set freeCodeCamp Environment Variables run: cp sample.env .env - name: Install and Build run: | - npm ci - npm run build + pnpm install + pnpm run build - name: Move serve.json to Public Folder run: cp client-config/serve.json client/public/serve.json @@ -48,13 +56,13 @@ jobs: run: tar -cf client-artifact.tar client/public - name: Upload Client Artifact - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3 with: name: client-artifact path: client-artifact.tar - name: Upload Webpack Stats - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3 + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3 with: name: webpack-stats path: client/public/stats.json @@ -67,14 +75,14 @@ jobs: fail-fast: false matrix: browsers: [chrome, firefox, electron] - node-version: [16.x] + node-version: [18.x] include: - browsers: electron spec: cypress/e2e/default/learn/challenges/projects.js - browsers: chrome - spec: cypress/e2e/default/**/*.js + spec: cypress/e2e/default/**/*.{js,ts} - browsers: firefox - spec: cypress/e2e/default/**/*.js + spec: cypress/e2e/default/**/*.{js,ts} services: mongodb: image: mongo:4.4 @@ -93,9 +101,9 @@ jobs: echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - - uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # tag=v3 + - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3 with: name: client-artifact @@ -112,8 +120,13 @@ jobs: sudo mv /usr/bin/firefox /usr/bin/firefox_old sudo ln -s /opt/firefox/firefox /usr/bin/firefox + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 + - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -122,19 +135,19 @@ jobs: - name: Install and Build run: | - npm ci - npm run create:config - npm run build:curriculum - npm run build:server + pnpm install + pnpm run create:config + pnpm run build:curriculum + pnpm run build:server - name: Seed Database - run: npm run seed + run: pnpm run seed - name: Cypress run uses: cypress-io/github-action@v4 with: record: ${{ env.CYPRESS_RECORD_KEY != 0 }} - start: npm run start-ci + start: pnpm run start-ci wait-on: http://localhost:8000 wait-on-timeout: 1200 config: baseUrl=http://localhost:8000 diff --git a/.github/workflows/github-autoclose.yml b/.github/workflows/github-autoclose.yml index 1f3bf8a804b2f2..152055a3223725 100644 --- a/.github/workflows/github-autoclose.yml +++ b/.github/workflows/github-autoclose.yml @@ -10,7 +10,7 @@ jobs: autoclose: runs-on: ubuntu-20.04 steps: - - uses: actions/github-script@d556feaca394842dc55e4734bf3bb9f685482fa0 # tag=v6 + - uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 # v6 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | diff --git a/.github/workflows/github-no-i18n-via-prs.yml b/.github/workflows/github-no-i18n-via-prs.yml index ba47629262e884..e50b5f7d2937ae 100644 --- a/.github/workflows/github-no-i18n-via-prs.yml +++ b/.github/workflows/github-no-i18n-via-prs.yml @@ -15,7 +15,7 @@ jobs: has-translation: runs-on: ubuntu-20.04 steps: - - uses: actions/github-script@d556feaca394842dc55e4734bf3bb9f685482fa0 # tag=v6 + - uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 # v6 with: github-token: ${{secrets.CAMPERBOT_NO_TRANSLATE}} script: | diff --git a/.github/workflows/github-spam.yml b/.github/workflows/github-spam.yml index ccfe1ee42491d4..b086d0458834dd 100644 --- a/.github/workflows/github-spam.yml +++ b/.github/workflows/github-spam.yml @@ -8,7 +8,7 @@ jobs: is-spam: runs-on: ubuntu-20.04 steps: - - uses: actions/github-script@d556feaca394842dc55e4734bf3bb9f685482fa0 # tag=v6 + - uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 # v6 with: github-token: ${{secrets.CAMPERBOT_NO_TRANSLATE}} script: | diff --git a/.github/workflows/i18n-validate-builds.yml b/.github/workflows/i18n-validate-builds.yml index 73dd3d33b84512..c97761262103ad 100644 --- a/.github/workflows/i18n-validate-builds.yml +++ b/.github/workflows/i18n-validate-builds.yml @@ -7,18 +7,20 @@ on: jobs: ci: name: Validate i18n Builds - runs-on: ubuntu-latest - + runs-on: ubuntu-20.04 strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 - - - name: Use Node.js v${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -26,7 +28,7 @@ jobs: run: cp sample.env .env - name: Install Dependencies - run: npm ci + run: pnpm install - name: Validate Challenge Files - run: npm run audit-challenges + run: pnpm run audit-challenges diff --git a/.github/workflows/i18n-validate-prs.yml b/.github/workflows/i18n-validate-prs.yml index f1068db0f1af55..c858003d5f69c5 100644 --- a/.github/workflows/i18n-validate-prs.yml +++ b/.github/workflows/i18n-validate-prs.yml @@ -7,19 +7,22 @@ on: jobs: ci: name: Validate i18n Builds - runs-on: ubuntu-latest # run only on PRs that camperbot opens with title that matches the curriculum sync if: ${{ github.event.pull_request.user.login == 'camperbot' && contains(github.event.pull_request.title, 'chore(i18n,learn)') }} + runs-on: ubuntu-20.04 strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 - - - name: Use Node.js v${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -27,16 +30,16 @@ jobs: run: cp sample.env .env - name: Install Dependencies - run: npm ci + run: pnpm install - name: Validate Challenge Files id: validate - run: npm run audit-challenges + run: pnpm run audit-challenges - name: Create Comment # Run if the validate challenge files step fails, specifically. Note that we need the failure() call for this step to trigger if the action fails. if: ${{ failure() && steps.validate.conclusion == 'failure' }} - uses: actions/github-script@d556feaca394842dc55e4734bf3bb9f685482fa0 # tag=v6 + uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 # v6 with: github-token: ${{secrets.CAMPERBOT_NO_TRANSLATE}} script: | diff --git a/.github/workflows/node.js-find-unused.yml b/.github/workflows/node.js-find-unused.yml index 3a70da8646461d..4817ee3adfa6aa 100644 --- a/.github/workflows/node.js-find-unused.yml +++ b/.github/workflows/node.js-find-unused.yml @@ -17,14 +17,17 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 - + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -35,6 +38,6 @@ jobs: - name: Run Checks run: | - echo npm version $(npm -v) - npm ci - npm run knip + echo pnpm version $(pnpm -v) + pnpm install + pnpm run knip diff --git a/.github/workflows/node.js-tests-upcoming.yml b/.github/workflows/node.js-tests-upcoming.yml index 8baa16f7ad37c0..7f9a1869c28765 100644 --- a/.github/workflows/node.js-tests-upcoming.yml +++ b/.github/workflows/node.js-tests-upcoming.yml @@ -2,14 +2,20 @@ name: CI - Node.js Test Upcoming env: NODE_OPTIONS: '--max_old_space_size=6144' on: + # Run on push events, but only for the below branches push: branches: - # Treat the below branches as special case for working on workflows - - actions-** - - upcoming-** + - 'main' + - 'prod-**' + # Run on pull requests, but only for the below targets + pull_request: + branches: + - 'main' + - 'next-**' schedule: # run this Action every 14 days - cron: '0 * */14 * *' + # Run on demand workflow_dispatch: permissions: @@ -19,18 +25,20 @@ jobs: lint: name: Lint runs-on: ubuntu-20.04 - strategy: - fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] + fail-fast: false steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 - + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -43,12 +51,12 @@ jobs: - name: Lint Source Files run: | - npm ci - npm run create:config + pnpm install + pnpm run create:config npm i --prefix=curriculum-server npm i --prefix=web - npm run build:curriculum - npm run lint + pnpm run build:curriculum + pnpm run lint test: name: Test @@ -58,14 +66,17 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 - + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -78,9 +89,9 @@ jobs: - name: Install Dependencies run: | - npm ci - npm run create:config - npm run build:curriculum + pnpm install + pnpm run create:config + pnpm run build:curriculum - name: Run Tests - run: npm test + run: pnpm test diff --git a/.github/workflows/node.js-tests.yml b/.github/workflows/node.js-tests.yml index f6d59c6ec7e439..21b8c0e498a324 100644 --- a/.github/workflows/node.js-tests.yml +++ b/.github/workflows/node.js-tests.yml @@ -1,14 +1,21 @@ name: CI - Node.js Test Current env: NODE_OPTIONS: '--max_old_space_size=6144' + on: + # Run on push events, but only for the below branches push: - branches-ignore: - - 'renovate/**' - - 'next-api' + branches: + - 'main' + - 'prod-**' + # Run on pull requests, but only for the below targets pull_request: - branches-ignore: - - 'next-api' + branches: + - 'main' + - 'next-**' + # Run on Merge Queue + merge_group: + types: [checks_requested] permissions: contents: read @@ -17,26 +24,30 @@ jobs: lint: name: Lint runs-on: ubuntu-20.04 - strategy: - fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] + fail-fast: false steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 - name: Check number of lockfiles run: | - if [ $(find . -name 'package-lock.json' | grep -vc -e 'node_modules') -gt 1 ] + if [ $(find . -name 'package-lock.json' | grep -vc -e 'node_modules') -gt 0 ] then - echo 'Error: found too many lockfiles in the repository' + echo -e 'Error: found package-lock files in the repository.\nWe use pnpm workspaces to manage packages so all dependencies should be added via pnpm add' exit 1 fi + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 + - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -50,13 +61,13 @@ jobs: # currently, built as workspaces. - name: Lint Source Files run: | - echo npm version $(npm -v) - npm ci - npm run create:config + echo pnpm version $(pnpm -v) + pnpm install + pnpm run create:config npm i --prefix=curriculum-server npm i --prefix=web - npm run build:curriculum - npm run lint + pnpm run build:curriculum + pnpm run lint test: name: Test @@ -66,14 +77,19 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -84,13 +100,13 @@ jobs: - name: Install Dependencies run: | - echo npm version $(npm -v) - npm ci - npm run create:config - npm run build:curriculum + echo pnpm version $(pnpm -v) + pnpm install + pnpm run create:config + pnpm run build:curriculum - name: Run Tests - run: npm test + run: pnpm test test-upcoming: name: Test Upcoming Changes @@ -100,14 +116,19 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -119,13 +140,13 @@ jobs: - name: Install Dependencies run: | - echo npm version $(npm -v) - npm ci - npm run create:config - npm run build:curriculum + echo pnpm version $(pnpm -v) + pnpm install + pnpm run create:config + pnpm run build:curriculum - name: Run Tests - run: npm test + run: pnpm test test-localization: name: Localize @@ -135,15 +156,20 @@ jobs: strategy: fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] locale: [chinese, espanol] steps: - name: Checkout Source Files - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3 + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 7 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # tag=v3 + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: node-version: ${{ matrix.node-version }} @@ -157,13 +183,13 @@ jobs: CURRICULUM_LOCALE: ${{ matrix.locale }} CLIENT_LOCALE: ${{ matrix.locale }} run: | - echo npm version $(npm -v) - npm ci - npm run create:config - npm run build:curriculum + echo pnpm version $(pnpm -v) + pnpm install + pnpm run create:config + pnpm run build:curriculum - name: Run Tests env: CURRICULUM_LOCALE: ${{ matrix.locale }} CLIENT_LOCALE: ${{ matrix.locale }} - run: npm test + run: pnpm test diff --git a/.github/workflows/update-license.yaml b/.github/workflows/update-license.yaml new file mode 100644 index 00000000000000..0c59424e025213 --- /dev/null +++ b/.github/workflows/update-license.yaml @@ -0,0 +1,24 @@ +name: Update copyright year(s) in license file + +on: + workflow_dispatch: + schedule: + - cron: '0 3 1 1 *' + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3 + with: + fetch-depth: 0 + - uses: FantasticFiasco/action-update-license-year@26ffac173f956c25f7467aa8e6f750eed24a1b7a # v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + path: | + README.md + LICENSE + commitTitle: 'docs: update copyright years' + prTitle: 'docs: update copyright years' + prBody: It's that time of the year, let's update the license + labels: 'status: waiting review' diff --git a/.gitignore b/.gitignore index 4c468c511bb9ce..60a4aafe9c9f09 100644 --- a/.gitignore +++ b/.gitignore @@ -165,6 +165,7 @@ config/client/test-evaluator.json config/curriculum.json config/i18n.js config/certification-settings.js +config/donation-settings.js config/superblock-order.js config/superblock-order.test.js @@ -174,6 +175,10 @@ utils/block-nameify.test.js utils/slugs.js utils/slugs.test.js utils/index.js +utils/get-lines.js +utils/get-lines.test.js +utils/validate.js +utils/validate.test.js ### vim ### # Swap @@ -213,6 +218,10 @@ client/static/_redirects client/static/mobile client/static/curriculum-data client/i18n/locales/**/trending.json +client/src/components/Donation/types.js ### UI Components ### tools/ui-components/dist + +### API ### +api/**/*.js diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile new file mode 100644 index 00000000000000..54b67b14d533c1 --- /dev/null +++ b/.gitpod.Dockerfile @@ -0,0 +1,8 @@ +FROM gitpod/workspace-mongodb:latest + +# from https://www.gitpod.io/docs/introduction/languages/javascript#node-versions +RUN bash -c 'VERSION="lts/*" \ + && source $HOME/.nvm/nvm.sh && nvm install $VERSION \ + && nvm use $VERSION && nvm alias default $VERSION' + +RUN echo "nvm use default &>/dev/null" >> ~/.bashrc.d/51-nvm-fix diff --git a/.gitpod.yml b/.gitpod.yml index d69ba77091ed03..4d8161af73e58e 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,4 +1,5 @@ -image: gitpod/workspace-mongodb +image: + file: .gitpod.Dockerfile ports: - port: 27017 # mongodb onOpen: ignore @@ -43,28 +44,28 @@ tasks: # so we should put all the heavy initialization here init: > cp sample.env .env && - npm ci && - gp sync-done npm-ci && + pnpm install && + gp sync-done pnpm-install && gp ports await 27017 && - npm run seed && + pnpm run seed && mongo --eval "db.fsyncLock(); db.fsyncUnlock()" command: > - npm run create:config && - npm run build:curriculum && + pnpm run create:config && + pnpm run build:curriculum && gp ports await 27017 && - npm run develop:server + pnpm run develop:server - name: client before: export HOME_LOCATION=$(gp url 8000) && export API_LOCATION=$(gp url 3000) && export CYPRESS_BASE_URL=$(gp url 8000) init: > cd ./client && - gp sync-await npm-ci && - npm run predevelop && + gp sync-await pnpm-install && + pnpm run predevelop && cd .. command: > gp ports await 3000 && cd ./client && - npm run develop -- -H '0.0.0.0' + pnpm run develop -- -H '0.0.0.0' openMode: split-right github: diff --git a/.lintstagedrc.js b/.lintstagedrc.js index 9e057a416e9f1b..c32ba6ed2127d8 100644 --- a/.lintstagedrc.js +++ b/.lintstagedrc.js @@ -43,7 +43,7 @@ module.exports = { if (files.length > 10) { completedStages.add('markdown'); - return 'npm run lint:challenges'; + return 'pnpm run lint:challenges'; } else { return files.map( filename => `node ./tools/scripts/lint/index.js '${filename}'` diff --git a/.npmrc b/.npmrc index 9ce0b728d94416..9483f4e6f49d15 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,5 @@ -CYPRESS_INSTALL_BINARY=0 +auto-install-peers=true +strict-peer-dependencies=true +# TODO: consider reworking the scripts to avoid usage of pre/post scripts +enable-pre-post-scripts=true +use-node-version=18.14.2 diff --git a/.prettierignore b/.prettierignore index 2d392969792346..4ba5da92add66d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -8,6 +8,7 @@ curriculum/challenges/**/* config/**/*.json config/i18n.js config/certification-settings.js +config/donation-settings.js config/superblock-order.js config/superblock-order.test.js utils/block-nameify.js @@ -15,7 +16,12 @@ utils/block-nameify.test.js utils/slugs.js utils/slugs.test.js utils/index.js -**/package-lock.json +utils/get-lines.js +utils/get-lines.test.js +utils/validate.js +utils/validate.test.js +pnpm-lock.yaml web/.next curriculum-server/data/curriculum.json docs/**/*.md +client/src/components/Donation/types.js diff --git a/LICENSE.md b/LICENSE.md index 12e9c3b39b3ed5..6eadad76438d3d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2022, freeCodeCamp. +Copyright (c) 2023, freeCodeCamp. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index 773490dac9ba12..c71509e222edcb 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## freeCodeCamp.org's open-source codebase and curriculum -[freeCodeCamp.org](https://www.freecodecamp.org) is a friendly community where you can learn to code for free. It is run by a [donor-supported 501(c)(3) nonprofit](https://www.freecodecamp.org/donate) to help millions of busy adults transition into tech. Our community has already helped more than 40,000 people get their first developer job. +[freeCodeCamp.org](https://www.freecodecamp.org) is a friendly community where you can learn to code for free. It is run by a [donor-supported 501(c)(3) charity](https://www.freecodecamp.org/donate) to help millions of busy adults transition into tech. Our community has already helped more than 40,000 people get their first developer job. Our full-stack web development and machine learning curriculum is completely free and self-paced. We have thousands of interactive coding challenges to help you expand your skills. @@ -190,7 +190,7 @@ The general platform status for all our applications is available at [`status.fr ### License -Copyright © 2022 freeCodeCamp.org +Copyright © 2023 freeCodeCamp.org The content of this repository is bound by the following licenses: diff --git a/api-server/ecosystem.config.js b/api-server/ecosystem.config.js index 42c4ff402d148e..d5f8d082bfd07a 100644 --- a/api-server/ecosystem.config.js +++ b/api-server/ecosystem.config.js @@ -3,13 +3,14 @@ const path = require('path'); const dotenv = require('dotenv'); -const filePath = path.resolve('..', '.env'); +const filePath = path.resolve(__dirname, '..', '.env'); const env = dotenv.parse(fs.readFileSync(filePath)); module.exports = { apps: [ { script: `./lib/production-start.js`, + cwd: __dirname, env, max_memory_restart: '600M', instances: 'max', diff --git a/api-server/package.json b/api-server/package.json index 7be433231a72d9..060280b2c282f4 100644 --- a/api-server/package.json +++ b/api-server/package.json @@ -6,7 +6,7 @@ "private": true, "engines": { "node": ">=16", - "npm": ">=8" + "pnpm": "7" }, "repository": { "type": "git", @@ -29,7 +29,8 @@ }, "dependencies": { "@freecodecamp/loopback-component-passport": "1.2.0", - "@sentry/node": "6.19.7", + "@sentry/node": "7.37.1", + "@sentry/tracing": "7.37.1", "accepts": "1.3.8", "axios": "0.23.0", "bad-words": "3.0.4", @@ -45,6 +46,7 @@ "dedent": "0.7.0", "dotenv": "6.2.0", "express-flash": "0.0.2", + "express-rate-limit": "^6.7.0", "express-session": "1.17.3", "express-validator": "6.14.1", "helmet": "3.23.3", @@ -60,12 +62,14 @@ "mongodb": "3.6.9", "morgan": "1.10.0", "nanoid": "3.3.4", + "node-fetch": "^2.6.7", "nodemailer-ses-transport": "1.5.1", "passport": "0.4.1", "passport-auth0": "1.4.2", "passport-local": "1.0.0", "passport-mock-strategy": "2.0.0", "query-string": "6.14.0", + "rate-limit-mongo": "^2.3.2", "rx": "4.1.0", "stripe": "8.205.0", "uuid": "3.4.0", diff --git a/api-server/src/common/models/user.js b/api-server/src/common/models/user.js index 31efb6a04d5fc3..028ffcc7dc96ee 100644 --- a/api-server/src/common/models/user.js +++ b/api-server/src/common/models/user.js @@ -162,6 +162,8 @@ export default function initializeUser(User) { User.definition.properties.rand.default = getRandomNumber; // increase user accessToken ttl to 900 days User.settings.ttl = 900 * 24 * 60 * 60 * 1000; + // Sets ttl to 900 days for mobile login created access tokens + User.settings.maxTTL = 900 * 24 * 60 * 60 * 1000; // username should not be in blocklist User.validatesExclusionOf('username', { @@ -341,6 +343,21 @@ export default function initializeUser(User) { ); }; + User.prototype.mobileLoginByRequest = function mobileLoginByRequest( + req, + res + ) { + return new Promise((resolve, reject) => + this.createAccessToken({}, (err, accessToken) => { + if (err) { + return reject(err); + } + setAccessTokenToResponse({ accessToken }, req, res); + return resolve(accessToken); + }) + ); + }; + User.afterRemote('logout', function ({ req, res }, result, next) { removeCookies(req, res); next(); diff --git a/api-server/src/development-start.js b/api-server/src/development-start.js index 356650780918a9..4b11c906447dfb 100644 --- a/api-server/src/development-start.js +++ b/api-server/src/development-start.js @@ -30,7 +30,7 @@ if (process.env.WEBHOOK_PROXY_URL) { nodemon({ ext: 'js json', // --silent squashes an ELIFECYCLE error when the server exits - exec: 'npm run --silent babel-dev-server', + exec: 'pnpm run --silent babel-dev-server', watch: path.resolve(__dirname, './server'), spawn: true, env: { diff --git a/api-server/src/server/boot/authentication.js b/api-server/src/server/boot/authentication.js index b55a90cdc49340..c7589da53cefc5 100644 --- a/api-server/src/server/boot/authentication.js +++ b/api-server/src/server/boot/authentication.js @@ -2,10 +2,9 @@ import dedent from 'dedent'; import { check } from 'express-validator'; import jwt from 'jsonwebtoken'; import passport from 'passport'; +import fetch from 'node-fetch'; import { isEmail } from 'validator'; - import { jwtSecret } from '../../../../config/secrets'; - import { decodeEmail } from '../../common/utils'; import { createPassportCallbackAuthenticator, @@ -14,7 +13,11 @@ import { } from '../component-passport'; import { wrapHandledError } from '../utils/create-handled-error.js'; import { removeCookies } from '../utils/getSetAccessToken'; -import { ifUserRedirectTo, ifNoUserRedirectHome } from '../utils/middleware'; +import { + ifUserRedirectTo, + ifNoUserRedirectHome, + ifNotMobileRedirect +} from '../utils/middleware'; import { getRedirectParams } from '../utils/redirection'; import { createDeleteUserToken } from '../middlewares/user-token'; @@ -34,6 +37,7 @@ module.exports = function enableAuthentication(app) { // enable loopback access control authentication. see: // loopback.io/doc/en/lb2/Authentication-authorization-and-permissions.html app.enableAuth(); + const ifNotMobile = ifNotMobileRedirect(); const ifUserRedirect = ifUserRedirectTo(); const ifNoUserRedirect = ifNoUserRedirectHome(); const devSaveAuthCookies = devSaveResponseAuthCookies(); @@ -87,6 +91,8 @@ module.exports = function enableAuthentication(app) { createGetPasswordlessAuth(app) ); + api.get('/mobile-login', ifNotMobile, ifUserRedirect, mobileLogin(app)); + app.use(api); }; @@ -188,3 +194,53 @@ function createGetPasswordlessAuth(app) { ); }; } + +function mobileLogin(app) { + const { + models: { User } + } = app; + return async function getPasswordlessAuth(req, res, next) { + try { + const auth0Res = await fetch( + `https://${process.env.AUTH0_DOMAIN}/userinfo`, + { + headers: { Authorization: req.headers.authorization } + } + ); + + if (!auth0Res.ok) { + return next( + wrapHandledError(new Error('Invalid Auth0 token'), { + type: 'danger', + message: 'We could not log you in, please try again in a moment.', + status: auth0Res.status + }) + ); + } + + const { email } = await auth0Res.json(); + + if (!isEmail(email)) { + return next( + wrapHandledError(new TypeError('decoded email is invalid'), { + type: 'danger', + message: 'The email is incorrectly formatted', + status: 400 + }) + ); + } + + User.findOne$({ where: { email } }) + .do(async user => { + if (!user) { + user = await User.create({ email }); + } + await user.mobileLoginByRequest(req, res); + res.end(); + }) + .subscribe(() => {}, next); + } catch (err) { + next(err); + } + }; +} diff --git a/api-server/src/server/boot/explorer.js b/api-server/src/server/boot/explorer.js index a78447e3475ef6..8de921c416ed7c 100644 --- a/api-server/src/server/boot/explorer.js +++ b/api-server/src/server/boot/explorer.js @@ -14,7 +14,7 @@ module.exports = function mountLoopBackExplorer(app) { // Do not print any message when the project is used as a component. app.once('started', function () { log( - 'Run `npm install loopback-component-explorer` to enable ' + + 'Run `pnpm add loopback-component-explorer` to enable ' + 'the LoopBack explorer' ); }); diff --git a/api-server/src/server/boot/settings.js b/api-server/src/server/boot/settings.js index d1a4b4006cf6e1..e93f32dff8327b 100644 --- a/api-server/src/server/boot/settings.js +++ b/api-server/src/server/boot/settings.js @@ -281,12 +281,6 @@ function handleInvalidUpdate(res) { function updateUserFlag(req, res, next) { const { user, body: update } = req; const allowedKeys = [ - 'theme', - 'sound', - 'keyboardShortcuts', - 'isHonest', - 'portfolio', - 'sendQuincyEmail', 'isGithub', 'isLinkedIn', 'isTwitter', diff --git a/api-server/src/server/boot/user.js b/api-server/src/server/boot/user.js index 9d11ea2459fa06..339dd258e28cfc 100644 --- a/api-server/src/server/boot/user.js +++ b/api-server/src/server/boot/user.js @@ -93,22 +93,21 @@ function deleteUserTokenResponse(req, res) { } function createReadSessionUser(app) { - const { Donation } = app.models; + const { Donation, UserToken } = app.models; return async function getSessionUser(req, res, next) { const queryUser = req.user; - const userTokenArr = await queryUser.userTokens({ - userId: queryUser.id - }); - - const userToken = userTokenArr[0]?.id; - let encodedUserToken; + const userId = queryUser?.id; + const userToken = userId + ? await UserToken.findOne({ + where: { userId } + }) + : null; - // only encode if a userToken was found - if (userToken) { - encodedUserToken = encodeUserToken(userToken); - } + const encodedUserToken = userToken + ? encodeUserToken(userToken.id) + : undefined; const source = queryUser && diff --git a/api-server/src/server/index.js b/api-server/src/server/index.js index 6c350cf2cfbedb..f696000d86c192 100644 --- a/api-server/src/server/index.js +++ b/api-server/src/server/index.js @@ -2,6 +2,7 @@ const path = require('path'); require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') }); const Sentry = require('@sentry/node'); +// const Tracing = require('@sentry/tracing'); const createDebugger = require('debug'); const _ = require('lodash'); const loopback = require('loopback'); @@ -14,15 +15,6 @@ const { setupPassport } = require('./component-passport'); const log = createDebugger('fcc:server'); const reqLogFormat = ':date[iso] :status :method :response-time ms - :url'; -if (sentry.dsn === 'dsn_from_sentry_dashboard') { - log('Sentry reporting disabled unless DSN is provided.'); -} else { - Sentry.init({ - dsn: sentry.dsn - }); - log('Sentry initialized'); -} - const app = loopback(); app.set('state namespace', '__fcc__'); @@ -62,6 +54,7 @@ db.on( 'connected', _.once(() => log('db connected')) ); + app.start = _.once(function () { const server = app.listen(app.get('port'), function () { app.emit('started'); @@ -89,6 +82,25 @@ app.start = _.once(function () { }); }); +if (sentry.dsn === 'dsn_from_sentry_dashboard') { + log('Sentry reporting disabled unless DSN is provided.'); +} else { + Sentry.init({ + dsn: sentry.dsn + // integrations: [ + // new Sentry.Integrations.Http({ tracing: true }), + // new Tracing.Integrations.Express({ + // app + // }) + // ], + // // Capture 20% of transactions to avoid + // // overwhelming Sentry and remain within + // // the usage quota + // tracesSampleRate: 0.2 + }); + log('Sentry initialized'); +} + module.exports = app; if (require.main === module) { diff --git a/api-server/src/server/middleware.json b/api-server/src/server/middleware.json index 69a47f44021f0c..df8d4ae9ff8b91 100644 --- a/api-server/src/server/middleware.json +++ b/api-server/src/server/middleware.json @@ -39,7 +39,10 @@ "./middlewares/constant-headers": {}, "./middlewares/csp": {}, "./middlewares/flash-cheaters": {}, - "./middlewares/passport-login": {} + "./middlewares/passport-login": {}, + "./middlewares/rate-limit": { + "paths": ["/mobile-login"] + } }, "files": {}, "final:after": { diff --git a/api-server/src/server/middlewares/rate-limit.js b/api-server/src/server/middlewares/rate-limit.js new file mode 100644 index 00000000000000..b461039a12c58b --- /dev/null +++ b/api-server/src/server/middlewares/rate-limit.js @@ -0,0 +1,23 @@ +import rateLimit from 'express-rate-limit'; +import MongoStore from 'rate-limit-mongo'; + +const url = process.env.MONGODB || process.env.MONGOHQ_URL; + +// Rate limit for mobile login +// 10 requests per 15 minute windows +export default function rateLimitMiddleware() { + return rateLimit({ + windowMs: 15 * 60 * 1000, + max: 10, + standardHeaders: true, + legacyHeaders: false, + keyGenerator: req => { + return req.headers['x-forwarded-for'] || 'localhost'; + }, + store: new MongoStore({ + collectionName: 'UserRateLimit', + uri: url, + expireTimeMs: 15 * 60 * 1000 + }) + }); +} diff --git a/api-server/src/server/middlewares/request-authorization.js b/api-server/src/server/middlewares/request-authorization.js index 93d27911884657..f8907c3c9324ae 100644 --- a/api-server/src/server/middlewares/request-authorization.js +++ b/api-server/src/server/middlewares/request-authorization.js @@ -35,6 +35,7 @@ const updateHooksRE = /^\/hooks\/update-paypal$/; // note: this would be replaced by webhooks later const donateRE = /^\/donate\/charge-stripe$/; const submitCoderoadChallengeRE = /^\/coderoad-challenge-completed$/; +const mobileLoginRE = /^\/mobile-login\/?$/; const _pathsAllowedREs = [ authRE, @@ -50,7 +51,8 @@ const _pathsAllowedREs = [ unsubscribeRE, updateHooksRE, donateRE, - submitCoderoadChallengeRE + submitCoderoadChallengeRE, + mobileLoginRE ]; export function isAllowedPath(path, pathsAllowedREs = _pathsAllowedREs) { diff --git a/api-server/src/server/middlewares/sentry-tracing-handler.js b/api-server/src/server/middlewares/sentry-tracing-handler.js new file mode 100644 index 00000000000000..41a04e306a9e6c --- /dev/null +++ b/api-server/src/server/middlewares/sentry-tracing-handler.js @@ -0,0 +1,8 @@ +import { Handlers } from '@sentry/node'; +import { sentry } from '../../../../config/secrets'; + +export default function sentryRequestHandler() { + return sentry.dsn === 'dsn_from_sentry_dashboard' + ? (req, res, next) => next() + : Handlers.tracingHandler(); +} diff --git a/api-server/src/server/utils/donation.js b/api-server/src/server/utils/donation.js index a47d1889429355..d3d9f86b1118b2 100644 --- a/api-server/src/server/utils/donation.js +++ b/api-server/src/server/utils/donation.js @@ -217,7 +217,7 @@ export async function createStripeCardDonation(req, res, stripe) { * if user is already donating and the donation isn't one time only, * throw error */ - if (user.isDonating && duration !== 'onetime') { + if (user.isDonating && duration !== 'one-time') { throw { message: `User already has active recurring donation(s).`, type: 'AlreadyDonatingError' diff --git a/api-server/src/server/utils/middleware.js b/api-server/src/server/utils/middleware.js index 52f5551fc85fb3..61144fae64b2be 100644 --- a/api-server/src/server/utils/middleware.js +++ b/api-server/src/server/utils/middleware.js @@ -77,6 +77,20 @@ export function ifUserRedirectTo(status) { }; } +export function ifNotMobileRedirect() { + return (req, res, next) => { + // + // Todo: Use the below check once we have done more research on usage + // + // const isMobile = /(iPhone|iPad|Android)/.test(req.headers['user-agent']); + // if (!isMobile) { + // res.json({ error: 'not from mobile' }); + // } else { + // next(); + // } + next(); + }; +} // for use with express-validator error formatter export const createValidatorErrorHandler = (...args) => diff --git a/api-server/src/server/utils/stripeHelpers.js b/api-server/src/server/utils/stripeHelpers.js index c64e44ce618b2b..ae0938d4145732 100644 --- a/api-server/src/server/utils/stripeHelpers.js +++ b/api-server/src/server/utils/stripeHelpers.js @@ -9,7 +9,7 @@ export function validStripeForm(amount, duration, email) { return isEmail('' + email) && isNumeric('' + amount) && durationKeysConfig.includes(duration) && - duration === 'onetime' + duration === 'one-time' ? donationOneTimeConfig.includes(amount) : donationSubscriptionConfig.plans[duration]; } diff --git a/api/db/index.ts b/api/db/index.ts new file mode 100644 index 00000000000000..cfc364a88fb412 --- /dev/null +++ b/api/db/index.ts @@ -0,0 +1,14 @@ +import fastifyPlugin from 'fastify-plugin'; +import fastifyMongo from '@fastify/mongodb'; +import { FastifyInstance } from 'fastify'; + +import { MONGOHQ_URL } from '../utils/env'; + +async function connect(fastify: FastifyInstance) { + fastify.log.info(`Connecting to Mongodb`); + await fastify.register(fastifyMongo, { + url: MONGOHQ_URL + }); +} + +export const dbConnector = fastifyPlugin(connect); diff --git a/api/index.ts b/api/index.ts new file mode 100644 index 00000000000000..b80cc69849018b --- /dev/null +++ b/api/index.ts @@ -0,0 +1,48 @@ +import fastifyAuth0 from 'fastify-auth0-verify'; +import Fastify from 'fastify'; +import middie from '@fastify/middie'; + +import jwtAuthz from './plugins/fastify-jwt-authz'; +import { testRoutes } from './routes/test'; +import { dbConnector } from './db'; +import { auth0Verify, testMiddleware } from './middleware'; +import { AUTH0_AUDIENCE, AUTH0_DOMAIN, NODE_ENV, PORT } from './utils/env'; + +const fastify = Fastify({ + logger: { level: NODE_ENV === 'development' ? 'debug' : 'fatal' } +}); + +fastify.get('/', async (_request, _reply) => { + return { hello: 'world' }; +}); + +const start = async () => { + // NOTE: Awaited to ensure `.use` is registered on `fastify` + await fastify.register(middie); + + // Auth0 plugin + void fastify.register(fastifyAuth0, { + domain: AUTH0_DOMAIN, + audience: AUTH0_AUDIENCE + }); + void fastify.register(jwtAuthz); + + void fastify.use('/test', testMiddleware); + + // Hooks + void fastify.addHook('preValidation', auth0Verify); + + void fastify.register(dbConnector); + void fastify.register(testRoutes); + + try { + const port = Number(PORT); + fastify.log.info(`Starting server on port ${port}`); + await fastify.listen({ port }); + } catch (err) { + fastify.log.error(err); + process.exit(1); + } +}; + +void start(); diff --git a/api/middleware/index.ts b/api/middleware/index.ts new file mode 100644 index 00000000000000..59fb5108041612 --- /dev/null +++ b/api/middleware/index.ts @@ -0,0 +1,25 @@ +import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'; +import type { NextFunction, NextHandleFunction } from '@fastify/middie'; + +export async function auth0Verify( + this: FastifyInstance, + request: FastifyRequest, + reply: FastifyReply +): Promise { + await this.authenticate(request, reply); +} + +type MiddieRequest = Parameters[0]; +type MiddieResponse = Parameters[1]; + +export function testMiddleware( + req: MiddieRequest, + res: MiddieResponse, + next: NextFunction +): void { + console.log('Test middleware running'); + console.log(req.headers); + console.log(req.query); + res.setHeader('X-Test-Header', 'test'); + next(); +} diff --git a/api/package.json b/api/package.json new file mode 100644 index 00000000000000..9505aea973c2b5 --- /dev/null +++ b/api/package.json @@ -0,0 +1,43 @@ +{ + "author": "freeCodeCamp ", + "bugs": { + "url": "https://github.com/freeCodeCamp/freeCodeCamp/issues" + }, + "dependencies": { + "@fastify/middie": "8.1", + "@fastify/mongodb": "6.2.0", + "fastify": "4.14.0", + "fastify-auth0-verify": "^1.0.0", + "fastify-plugin": "^4.3.0", + "nodemon": "2.0.21" + }, + "description": "The freeCodeCamp.org open-source codebase and curriculum", + "engines": { + "node": ">=18", + "npm": ">=8" + }, + "homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme", + "license": "BSD-3-Clause", + "main": "none", + "name": "@freecodecamp/api", + "nodemonConfig": { + "env": { + "NODE_ENV": "development" + }, + "ignore": [ + "**/*.js" + ] + }, + "private": true, + "repository": { + "type": "git", + "url": "git+https://github.com/freeCodeCamp/freeCodeCamp.git" + }, + "scripts": { + "build": "tsc", + "develop": "nodemon index.ts", + "start": "NODE_ENV=production node index.js", + "test": "node --test -r ts-node/register **/*.test.ts" + }, + "version": "0.0.1" +} diff --git a/api/plugins/fastify-jwt-authz.test.ts b/api/plugins/fastify-jwt-authz.test.ts new file mode 100644 index 00000000000000..9067266ae928c1 --- /dev/null +++ b/api/plugins/fastify-jwt-authz.test.ts @@ -0,0 +1,292 @@ +/* +MIT License + +Copyright (c) 2018 Ethan Arrowood + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import assert from 'node:assert'; +// eslint-disable-next-line import/no-unresolved +import { describe, it } from 'node:test'; +import Fastify from 'fastify'; +import jwtAuthz from './fastify-jwt-authz'; + +interface ErrorResponse { + statusCode: number; + error: string; + message: string; +} + +describe('fastify-jwt-authz', { only: true }, () => { + it('should decorate request instance with jwtAuthz method', async () => { + const fastify = Fastify(); + await fastify.register(jwtAuthz); + + fastify.get('/test', function (request) { + assert(request.jwtAuthz); + return { foo: 'bar' }; + }); + + fastify.listen({ port: 0 }, function () { + fastify.server.unref(); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test' + }); + + assert.strictEqual(res.statusCode, 200); + }); + + it('should throw an error "Scopes cannot be empty" with an empty scopes parameter', async () => { + const fastify = Fastify(); + await fastify.register(jwtAuthz); + + fastify.get( + '/test2', + { + preHandler: function (request, _reply, done) { + void request.jwtAuthz([], done); + } + }, + function () { + return { foo: 'bar' }; + } + ); + + fastify.listen({ port: 0 }, function () { + fastify.server.unref(); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test2' + }); + const resData: ErrorResponse = res.json(); + + assert.strictEqual(res.statusCode, 500); + assert.strictEqual(resData.message, 'Scopes cannot be empty'); + }); + + it('should throw an error "request.user does not exist" non existing request.user', async () => { + const fastify = Fastify(); + await fastify.register(jwtAuthz); + + fastify.get( + '/test3', + { + preHandler: function (request, _reply, done) { + void request.jwtAuthz(['baz'], done); + } + }, + function () { + return { foo: 'bar' }; + } + ); + + fastify.listen({ port: 0 }, function () { + fastify.server.unref(); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test3' + }); + const resData: ErrorResponse = res.json(); + + assert.strictEqual(res.statusCode, 500); + assert.strictEqual(resData.message, 'request.user does not exist'); + }); + + it('should throw an error "request.user.scope must be a string"', async () => { + const fastify = Fastify(); + await fastify.register(jwtAuthz); + + fastify.get( + '/test4', + { + preHandler: function (request, _reply, done) { + request.user = { + name: 'sample', + scope: 123 + }; + void request.jwtAuthz(['baz'], done); + } + }, + function () { + return { foo: 'bar' }; + } + ); + + fastify.listen({ port: 0 }, function () { + fastify.server.unref(); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test4' + }); + const resData: ErrorResponse = res.json(); + + assert.strictEqual(res.statusCode, 500); + assert.strictEqual(resData.message, 'request.user.scope must be a string'); + }); + + it('should throw an error "Insufficient scope"', async () => { + const fastify = Fastify(); + await fastify.register(jwtAuthz); + + fastify.get( + '/test5', + { + preHandler: function (request, _reply, done) { + request.user = { + name: 'sample', + scope: 'baz' + }; + void request.jwtAuthz(['foo'], done); + } + }, + function () { + return { foo: 'bar' }; + } + ); + + fastify.listen({ port: 0 }, function () { + fastify.server.unref(); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test5' + }); + const resData: ErrorResponse = res.json(); + + assert.strictEqual(res.statusCode, 500); + assert.strictEqual(resData.message, 'Insufficient scope'); + }); + + it('should verify user scope', async () => { + const fastify = Fastify(); + await fastify.register(jwtAuthz); + + fastify.get( + '/test6', + { + preHandler: function (request, _reply, done) { + request.user = { + name: 'sample', + scope: 'user manager' + }; + void request.jwtAuthz(['user'], done); + } + }, + function () { + return { foo: 'bar' }; + } + ); + + fastify.listen({ port: 0 }, function () { + fastify.server.unref(); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test6' + }); + + const resData: { foo: string } = res.json(); + + assert.strictEqual(res.statusCode, 200); + assert.strictEqual(resData.foo, 'bar'); + }); + + it('should throw an error when there is no callback', async () => { + const fastify = Fastify(); + await fastify.register(jwtAuthz); + + fastify.get( + '/test7', + { + preHandler: function (request, _reply, done) { + request.user = { + name: 'sample', + scope: 123 + }; + + request.jwtAuthz(['baz']); + done(); + } + }, + function () { + return { foo: 'bar' }; + } + ); + + fastify.listen({ port: 0 }, function () { + fastify.server.unref(); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test7' + }); + const resData: ErrorResponse = res.json(); + + assert.strictEqual(res.statusCode, 500); + assert.strictEqual(resData.message, 'request.user.scope must be a string'); + }); + + it('should verify user scope when there is no callback', async () => { + const fastify = Fastify(); + await fastify.register(jwtAuthz); + + fastify.get( + '/test8', + { + preHandler: function (request, _reply, done) { + request.user = { + name: 'sample', + scope: 'user manager' + }; + request.jwtAuthz(['user']); + done(); + } + }, + function () { + return { foo: 'bar' }; + } + ); + + fastify.listen({ port: 0 }, function () { + fastify.server.unref(); + }); + + const res = await fastify.inject({ + method: 'GET', + url: '/test8' + }); + const resData: { foo: string } = res.json(); + + assert.strictEqual(res.statusCode, 200); + assert.strictEqual(resData.foo, 'bar'); + }); +}); diff --git a/api/plugins/fastify-jwt-authz.ts b/api/plugins/fastify-jwt-authz.ts new file mode 100644 index 00000000000000..388d42bfb25729 --- /dev/null +++ b/api/plugins/fastify-jwt-authz.ts @@ -0,0 +1,72 @@ +/* +MIT License + +Copyright (c) 2018 Ethan Arrowood + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import { FastifyPluginCallback, FastifyRequest } from 'fastify'; +import fp from 'fastify-plugin'; + +interface UserObject { + scope?: string; +} + +interface JwtAuthz { + (scopes: string[], callback?: (err?: Error) => void): void; +} + +const fastifyJwtAuthz: FastifyPluginCallback = (fastify, _opts, done) => { + fastify.decorateRequest('jwtAuthz', jwtAuthz); + + function checkScopes(user: UserObject, scopes: string[]) { + if (scopes.length === 0) return Error('Scopes cannot be empty'); + + if (!user) return Error('request.user does not exist'); + + if (typeof user.scope !== 'string') + return Error('request.user.scope must be a string'); + + const userScopes = user.scope.split(' '); + const sufficientScope = scopes.some(scope => userScopes.includes(scope)); + + if (!sufficientScope) return Error('Insufficient scope'); + } + + function jwtAuthz( + this: FastifyRequest, + scopes: string[], + callback?: (err?: Error) => void + ) { + const err = checkScopes(this.user as UserObject, scopes); + if (callback) return callback(err); + if (err) throw err; + } + + done(); +}; + +declare module 'fastify' { + interface FastifyRequest { + jwtAuthz: JwtAuthz; + } +} + +export default fp(fastifyJwtAuthz); diff --git a/api/routes/test.ts b/api/routes/test.ts new file mode 100644 index 00000000000000..73b313d764c545 --- /dev/null +++ b/api/routes/test.ts @@ -0,0 +1,57 @@ +import { FastifyPluginCallback, FastifyRequest } from 'fastify'; + +export const testRoutes: FastifyPluginCallback = (fastify, _options, done) => { + const collection = fastify.mongo.db?.collection('user'); + + fastify.get('/test', async (_request, _reply) => { + if (!collection) { + return { error: 'No collection' }; + } + const user = await collection?.findOne({ email: 'bar@bar.com' }); + return { user }; + }); + + fastify.put( + '/update-privacy-terms', + { + preHandler: [ + function ( + req: FastifyRequest<{ Body: { quincyEmails: boolean } }>, + _res, + done + ) { + void req.jwtAuthz(['write:user'], done); + } + ], + schema: { + body: { + required: ['quincyEmails'], + properties: { + quincyEmails: { type: 'boolean' } + } + } + } + }, + (req, res) => { + const { + body: { quincyEmails } + } = req; + + const update = { + acceptedPrivacyTerms: true, + sendQuincyEmail: !!quincyEmails + }; + + return collection + ?.updateOne({ email: 'bar@bar.com' }, { $set: update }) + .then(() => { + void res.code(200).send({ msg: 'Successfully updated' }); + }) + .catch(err => { + fastify.log.error(err); + void res.code(500).send({ msg: 'Something went wrong' }); + }); + } + ); + done(); +}; diff --git a/api/tsconfig.json b/api/tsconfig.json new file mode 100644 index 00000000000000..adfcc0f8660776 --- /dev/null +++ b/api/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "CommonJS", + "allowJs": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "typeRoots": ["../node_modules/@types", "../node_modules/@fastify"] + } +} diff --git a/api/utils/env.ts b/api/utils/env.ts new file mode 100644 index 00000000000000..a54e35c9c8174a --- /dev/null +++ b/api/utils/env.ts @@ -0,0 +1,35 @@ +import assert from 'node:assert'; +import path from 'node:path'; +import { config } from 'dotenv'; + +const envPath = path.resolve(__dirname, '../../.env'); +const { error } = config({ path: envPath }); + +if (error) { + console.warn(` + ---------------------------------------------------- + Warning: .env file not found. + ---------------------------------------------------- + Please copy sample.env to .env + + You can ignore this warning if using a different way + to setup this environment. + ---------------------------------------------------- + `); +} + +assert.ok(process.env.NODE_ENV); +assert.ok(process.env.AUTH0_DOMAIN); +assert.ok(process.env.AUTH0_AUDIENCE); + +if (process.env.NODE_ENV !== 'development') { + assert.ok(process.env.PORT); + assert.ok(process.env.MONGOHQ_URL); +} + +export const MONGOHQ_URL = + process.env.MONGOHQ_URL || 'mongodb://localhost:27017/freecodecamp'; +export const NODE_ENV = process.env.NODE_ENV; +export const AUTH0_DOMAIN = process.env.AUTH0_DOMAIN; +export const AUTH0_AUDIENCE = process.env.AUTH0_AUDIENCE; +export const PORT = process.env.PORT || '3000'; diff --git a/api/utils/index.test.ts b/api/utils/index.test.ts new file mode 100644 index 00000000000000..6b6eb6bff5240c --- /dev/null +++ b/api/utils/index.test.ts @@ -0,0 +1,18 @@ +import assert from 'node:assert'; +// eslint-disable-next-line import/no-unresolved +import { describe, it } from 'node:test'; +import { base64URLEncode, challenge, verifier } from '.'; + +describe('utils', { only: true }, () => { + it('base64URLEncode', () => { + assert.strictEqual(base64URLEncode(Buffer.from('test')), 'dGVzdA'); + }); + it('verifier', () => { + const v = verifier; + assert.strictEqual(v.length, 43); + }); + it('challenge', () => { + const c = challenge; + assert.strictEqual(c.length, 43); + }); +}); diff --git a/api/utils/index.ts b/api/utils/index.ts new file mode 100644 index 00000000000000..fbe8447a59cf95 --- /dev/null +++ b/api/utils/index.ts @@ -0,0 +1,15 @@ +import { randomBytes, createHash } from 'crypto'; + +export function base64URLEncode(buf: Buffer): string { + return buf + .toString('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=/g, ''); +} +export const verifier = base64URLEncode(randomBytes(32)); + +function sha256(buf: Buffer) { + return createHash('sha256').update(buf).digest(); +} +export const challenge = base64URLEncode(sha256(Buffer.from(verifier))); diff --git a/client/gatsby-browser.js b/client/gatsby-browser.js index 513cc8d8a55d9f..f93c9c10a26755 100644 --- a/client/gatsby-browser.js +++ b/client/gatsby-browser.js @@ -6,7 +6,7 @@ import { Provider } from 'react-redux'; import i18n from './i18n/config'; import AppMountNotifier from './src/components/app-mount-notifier'; -import { createStore } from './src/redux/createStore'; +import { createStore } from './src/redux/create-store'; import layoutSelector from './utils/gatsby/layout-selector'; import GrowthBookProvider from './src/components/growth-book/growth-book-wrapper'; diff --git a/client/gatsby-config.js b/client/gatsby-config.js index acc2d255106291..4a9e48b6619b87 100644 --- a/client/gatsby-config.js +++ b/client/gatsby-config.js @@ -22,6 +22,7 @@ module.exports = { }, pathPrefix: pathPrefix, plugins: [ + 'gatsby-plugin-pnpm', { resolve: '@sentry/gatsby', options: { diff --git a/client/gatsby-node.js b/client/gatsby-node.js index 736fa2ff580f8c..9e5b6d157723a0 100644 --- a/client/gatsby-node.js +++ b/client/gatsby-node.js @@ -270,6 +270,8 @@ exports.onCreatePage = async ({ page, actions }) => { } }; +// Take care to QA the challenges when modifying this. It has broken certain +// types of challenge in the past. exports.createSchemaCustomization = ({ actions }) => { const { createTypes } = actions; const typeDefs = ` @@ -280,6 +282,7 @@ exports.createSchemaCustomization = ({ actions }) => { challengeFiles: [FileContents] notes: String url: String + assignments: [String] } type FileContents { fileKey: String @@ -293,44 +296,3 @@ exports.createSchemaCustomization = ({ actions }) => { `; createTypes(typeDefs); }; - -// TODO: this broke the React challenges, not sure why, but I'll investigate -// further and reimplement if it's possible and necessary (Oliver) -// I'm still not sure why, but the above schema seems to work. -// Typically the schema can be inferred, but not when some challenges are -// skipped (at time of writing the Chinese only has responsive web design), so -// this makes the missing fields explicit. -// exports.createSchemaCustomization = ({ actions }) => { -// const { createTypes } = actions; -// const typeDefs = ` -// type ChallengeNode implements Node { -// question: Question -// videoId: String -// required: ExternalFile -// files: ChallengeFile -// } -// type Question { -// text: String -// answers: [String] -// solution: Int -// } -// type ChallengeFile { -// indexhtml: FileContents -// indexjs: FileContents -// indexjsx: FileContents -// } -// type ExternalFile { -// link: String -// src: String -// } -// type FileContents { -// key: String -// ext: String -// name: String -// contents: String -// head: String -// tail: String -// } -// `; -// createTypes(typeDefs); -// }; diff --git a/client/gatsby-ssr.js b/client/gatsby-ssr.js index e7995a365d0cae..c0f6e4237c6604 100644 --- a/client/gatsby-ssr.js +++ b/client/gatsby-ssr.js @@ -4,7 +4,7 @@ import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import i18n from './i18n/config'; -import { createStore } from './src/redux/createStore'; +import { createStore } from './src/redux/create-store'; import layoutSelector from './utils/gatsby/layout-selector'; import { getheadTagComponents, getPostBodyComponents } from './utils/tags'; import GrowthBookProvider from './src/components/growth-book/growth-book-wrapper'; diff --git a/client/i18n/locales/arabic/intro.json b/client/i18n/locales/arabic/intro.json index fddcb6cdd83aa2..26f9fd200aa1fa 100644 --- a/client/i18n/locales/arabic/intro.json +++ b/client/i18n/locales/arabic/intro.json @@ -3,23 +3,23 @@ "title": "تراث تصميم مواقع الويب المتجاوبة", "intro": [ "في شهادة تصميم الويب المستجيب هذه، ستتعلم اللغات التي يستخدمها المطورين لبناء صفحات الويب: HTML (Hypertext Markup Language) للمحتوى، و CSS (Cascading Style Sheets) للتصميم.", - "أولاً، سوف تقوم ببناء تطبيق صورة القطة لتعلم أساسيات HTML و CSS. لاحقاً، سوف تتعلم التقنيات الحديثة مثل متغيرات CSS عن طريق بناء بطريق، وأفضل الممارسات في اتاحة الوصول (accessibility) عن طريق بناء نموذج ويب.", - "أخيراً، سوف تتعلم كيف تنشئ صفحات ويب تستجيب لأحجام الشاشات المختلفة من خلال بناء بطاقة تويتر باستخدام Flexbox، وتخطيط معقد لمدونة باستخدام CSS Grid." + "أولاً، سوف تبني تطبيق صورة قطة لتتعلم أساسيات HTML و CSS. لاحقاً، سوف تتعلم التقنيات الحديثة مثل متغيرات CSS عن طريق بناء بِطْرِيق، وأفضل الممارسات في إتاحة الوصول (accessibility) عن طريق بناء نموذج ويب.", + "أخيراً، سوف تتعلم كيف تنشئ صفحات ويب تستجيب لأحجام الشاشات المختلفة عندما تبني بطاقة تويتر باستخدام Flexbox، وتخطيط معقد لمدونة باستخدام CSS Grid." ], - "note": "ملاحظة: بعض إضافات المتصفح, مثل Ad-blockers وإضافات الوضع الليلي قد تتصادم مع نتائج الاختبارات, إذا واجهت مشاكل, ننصحك بتعطيل الإضافات التي قد تؤثر أو تعدل على مخطط الصفحات, أثناء حضورك للدورة.", + "note": "ملاحظة: بعض إضافات المتصفح, مثل Ad-blockers وإضافات الوضع الليلي قد تتصادم مع نتائج الاختبارات, إذا واجهت مشكلات, ننصحك بتعطيل الإضافات التي قد تؤثر أو تعدل على مخطط الصفحات في أثناء حضورك للدورة.", "blocks": { "basic-html-and-html5": { "title": "أساسيات HTML و HTML5", "intro": [ - "HTML هي لغة ترميز تستخدم سياق خاص أو رموز لوصف الهيكل الخاص بصفحة الويب للمتصفح، عناصر HTML عادة لديها وسم فتح واغلاق تحيط المحتوى وتضيف معنى له. على سبيل المثال، عناصر مختلفة بامكانها وصف النص كعنوان أو فقرة أو عنصر من قائمة.", - "في هذه الدورة، ستبني تطبيق صورة القطة لتعلم بعض من أكثر عناصر الـ HTML شيوعاً، كتل البناء لأي صفحة على الويب." + "HTML هي لغة ترميز تستخدم سياق خاص أو رموز لوصف الهيكل الخاص بصفحة الويب للمتصفح، عناصر HTML عادة لديها علامة فتح وإغلاق تحيط المحتوى وتضيف معنى له. على سبيل المثال، عناصر مختلفة بإمكانها وصف النص كعنوان أو فَقَرة أو عنصر من قائمة.", + "في هذه الدورة، ستبني تطبيق صورة القطة لتتعلم بعض من أكثر عناصر لغة HTML شيوعاً، وهي كتل البناء لأي صفحة على الويب." ] }, "basic-css": { "title": "أساسيات CSS", "intro": [ - "CSS أو Cascading Style Sheets تخبر المتصفح كيف يعرض النص والعناصر الأخرى التي قمت بكتابتها في ملف الـ HTML، مع CSS تستطيع التحكم باللون والخط والحجم والمسافة والكثير من الأوجه المختلفة لعناصر HTML.", - "الآن بعد أن وصفت بنية تطبيق صورة القطة الخاص بك، أضف له بعض التصاميم باستخدام CSS." + "CSS أو Cascading Style Sheets تخبر المتصفح كيف يعرض النص والعناصر الأخرى الذي قمت بكتابتها في مِلَفّ HTML. و بواسطة CSS تستطيع التحكم باللون والخط والحجم والمسافة والكثير من الأوجه المختلفة لعناصر HTML.", + "الآن بعد أن وصفت بنية تطبيق صورة القطة الخاصة بك، أضف له بعض التصاميم باستخدام CSS." ] }, "applied-visual-design": { @@ -32,7 +32,7 @@ "applied-accessibility": { "title": "امكانية الوصول المطبقة", "intro": [ - "في تطوير المواقع، اماكنية الوصول تشير إلى محتوى ويب وواجهة مستخدم يمكن فهمها والتنقل بها والتفاعل معها من قبل جمهور عريض. هذا يتضمن أشخاص مصابين بإعاقات بصرية أو سمعية أو حركية أو ادراكية.", + "في تطوير المواقع، إماكنية الوصول تشير إلى محتوى ويب وواجهة مستخدم (UI - User Interface) يمكن فهمها والتنقل بها والتفاعل معها من قبل جَمهور عريض. هذا يتضمن أشخاص مصابين بإعاقات بصرية أو سمعية أو حركية أو إدراكية.", "في هذه الدورة، ستتعلم أفضل الممارسات لبناء صفحات الويب التي يمكن للجميع الوصول إليها وفهمها." ] }, @@ -76,80 +76,80 @@ "note": "ملاحظة: بعض إضافات المتصفح, مثل Ad-blockers وإضافات الوضع الليلي قد تتصادم مع نتائج الاختبارات, إذا واجهت مشاكل, ننصحك بتعطيل الإضافات التي قد تؤثر أو تعدل على مخطط الصفحات, أثناء حضورك للدورة.", "blocks": { "build-a-tribute-page-project": { - "title": "صفحة الإشادة", + "title": "صفحة الثناء", "intro": [ "هذا هو أحد المشاريع المطلوبة للحصول على شهادتك.", - "في هذا المشروع، سوف تقوم ببناء صفحة ثناء لموضوع من اختيارك سواء كان الموضوع من وحي خيالك أو حقيقي." + "في هذا المشروع، سوف تنشئ صفحة إثناء لموضوع من اختيارك سواء كان الموضوع من وحي خيالك أو حقيقي." ] }, "build-a-personal-portfolio-webpage-project": { - "title": "صفحه الويب لعرض نموذجات الأعمال الشخصية", + "title": "معرضا لأعمالك الخاصة", "intro": [ - "هذا هو أحد المشاريع المطلوبة للحصول على شهادتك.", - "في هذا المشروع، سوف تقوم ببناء صفحة ويب لعرض نماذج الاعمال الشخصية الخاصة بك." + "هذا هو أحد المشروعات المطلوبة للحصول على شهادتك.", + "في هذا المشروع، سوف تتشئ صفحة ويب معرضا لأعمالك الخاصة." ] }, "build-a-product-landing-page-project": { - "title": "صفحة الهبوط للمنتج", + "title": "صفحة لعرض المنتج", "intro": [ - "هذا هو أحد المشاريع المطلوبة للحصول على شهادتك.", - "في هذا المشروع، سوف تقوم ببناء صفحة هبوط لمنتج من اختيارك للتسويق له." + "هذا هو أحد المشروعات المطلوبة للحصول على شهادتك.", + "في هذا المشروع، ستنشئ صفحة لعرض المنتج من اختيارك للتسويق له." ] }, "build-a-survey-form-project": { "title": "نموذج استطلاع رأي", "intro": [ - "هذا هو أحد المشاريع المطلوبة للحصول على شهادتك.", - "في هذا المشروع، سوف تقوم ببناء نموذج الدراسة الاستقصائية لجمع بيانات من المستخدمين." + "هذا هو أحد المشروعات المطلوبة للحصول على شهادتك.", + "في هذا المشروع، سوف تنشئ نموذج استطلاع رأي لجمع بيانات من مستخدميك." ] }, "build-a-technical-documentation-page-project": { - "title": "صفحة الوثائق التقنية", + "title": "صفحة التوثيق التقنية", "intro": [ - "هذا هو أحد المشاريع المطلوبة للحصول على شهادتك.", - "في هذا المشروع، ستنشئ صفحة التوثيق التقني لتكون بمثابة تعليمات أو مرجع لموضوع ما." + "هذا هو أحد المشروعات المطلوبة للحصول على شهادتك.", + "في هذا المشروع، ستنشئ صفحة نموذج استطلاع رأي لتقوم مقام التعليمات أو المرجع لموضوع ما." ] }, "learn-html-by-building-a-cat-photo-app": { "title": "تعلم HTML عن طريق بناء تطبيق صورة القطة", "intro": [ "تعطي وسوم HTML صفحة الويب هيكلها. يمكنك استخدام وسوم HTML لإضافة الصور والأزرار والعناصر الأخرى إلى صفحة الويب الخاصة بك.", - "في هذه الدورة، ستتعلم وسوم HTML الأكثر شيوعاً عن طريق بناء تطبيقك لصورة القطة." + "في هذه الدورة، ستتعلم وسوم HTML الأكثر شيوعاً عن طريق بناء تطبيقك صورة القطة." ] }, "learn-basic-css-by-building-a-cafe-menu": { "title": "تعلم اساسيات CSS عن طريق بناء قائمة مقهى", "intro": [ - "CSS يخبر المتصفح كيفية عرض صفحة الويب الخاصة بك. يمكنك استخدام CSS لتعيين اللون والخطوط والحجم والجوانب الأخرى لعناصر HTML.", - "في هذه الدورة، سوف تتعلم CSS عن طريق تصميم صفحة قائمة لصفحة ويب لمقهي." + "يخبر CSS المتصفح كيف تعرض صفحتك الويب. يمكنك استخدام CSS لتعيين اللون والخطوط والحجم والجوانب الأخرى لعناصر HTML.", + "في هذه الدورة، سوف تتعلم CSS عن طريق تصميم صفحة قائمة لصفحة ويب لمقهى." ] }, "learn-the-css-box-model-by-building-a-rothko-painting": { "title": "تعلم CSS Box Model عن طريق بناء رسم لـRothko", "intro": [ - "كل عنصر من عناصر HTML هو صندوق خاص به - مع مساحته الخاصة وحدوده. وهذا يسمى نموذج Box Model.", - "في هذه الدورة، ستستخدم CSS و Box Model لإنشاء قطع فنية مستطيلة على نمط Rothko-الخاص بك." + "كل عنصر من عناصر HTML هو صندوقه - مع مساحته الخاصة وحدوده. وهذا يسمى نموذج الصندوق Box Model.", + "في هذه الدورة، ستستخدم CSS و Box Model لإنشاء قطع فنية مستطيلة على تصممك لوحة روثكو." ] }, "learn-css-variables-by-building-a-city-skyline": { - "title": "تعلم متغيرات CSS عن طريق بناء خط افق المدينة", + "title": "تعلم متغيرات CSS عن طريق أنشئ ناطحة السحاب بالمدينة", "intro": [ - "تساعدك متغيرات CSS على تنظيم الأنماط الخاصة بك وإعادة استخدامها.", - "في هذه الدورة، ستبني خط افق المدينة. ستتعلم كيفية تهيئة متغيرات CSS حتى تتمكن من إعادة استخدامها كلما أردت." + "تساعدك متغيرات CSS على تنظيم تصميماتك وإعادة استخدامها.", + "في هذه الدورة، ستبني ناطحة سحب بالمدينة. ستتعلم كيفية إعداد متغيرات CSS حتى تتمكن من إعادة استخدامها كلما أردت." ] }, "learn-html-forms-by-building-a-registration-form": { - "title": "تعلم نماذج HTML عن طريق بناء نموذج تسجيل", + "title": "تعلم نموذجات HTML عن طريق بناء نموذج تسجيل", "intro": [ - "يمكنك استخدام نماذج HTML لجمع المعلومات من الأشخاص الذين يزورون صفحة الويب الخاصة بك.", + "يمكنك استخدام نموذجات HTML لجمع المعلومات من الأشخاص الذين يزورون صفحتك الويب.", "في هذه الدورة، ستتعلم نماذج HTML عن طريق بناء صفحة التسجيل. ستتعلم كيفية التحكم في أنواع البيانات التي يمكن للناس كتابتها في النموذج، وبعض أدوات CSS الجديدة لتصميم صفحتك." ] }, "learn-accessibility-by-building-a-quiz": { - "title": "تعلم إمكانية الوصول Accessibility عن طريق بناء اختبار", + "title": "تعلم تسهيل المنال Accessibility عن طريق بناء اختبار", "intro": [ - "إمكانية الوصول تجعل صفحة الويب الخاصة بك سهلة الاستخدام لجميع الناس - حتى الأشخاص ذوي الإعاقة.", - "في هذه الدورة، ستبني صفحة ويب لاختبار. ستتعلم أدوات الوصول مثل اختصارات لوحة المفاتيح، سمات ARIA وأفضل الممارسات في التصميم." + "الاهتمام بتسهيل المنال إلى صفحتك الويب سهلة الاستخدام لجميع الناس - حتى الأشخاص ذوي الإعاقة.", + "في هذه الدورة، ستبني صفحة ويب لاختبار. ستتعلم أدوات تسهل المنال مثل اختصارات لوحة المفاتيح، سمات ARIA وأفضل الممارسات في التصميم." ] }, "learn-intermediate-css-by-building-a-picasso-painting": { @@ -159,31 +159,31 @@ ] }, "learn-responsive-web-design-by-building-a-piano": { - "title": "تعلم تصميم الويب المتجاوب Responsive Web Design عن طريق بناء بيانو", + "title": "تعلم تصميم الويب المستجيب Responsive Web Design عن طريق بناء بيانو", "intro": [ - "التصميم المستجيب يخبر صفحة الويب الخاصة بك كيف ينبغي أن تبدو على شاشات مختلفة الحجم.", + "يخبر التصميم المستجيب صفحتك الويب كيف ينبغي أن تبدو على شاشات مختلفة الحجم.", "في هذه الدورة، ستستخدم CSS والتصميم المستجيب لبرمجة وبناء بيانو. كما ستتعلم المزيد عن media queries و pseudo selectors." ] }, "learn-css-flexbox-by-building-a-photo-gallery": { "title": "تعلم CSS Flexbox من خلال بناء معرض للصور", "intro": [ - "يساعدك Flexbox في تصميم صفحة الويب الخاصة بك بحيث تبدو جيدة على أي حجم شاشة.", + "يساعدك Flexbox في تصميم صفحتك الويب بحيث تبدو جيدة على أي حجم شاشة.", "في هذه الدورة، ستستخدم Flexbox لإنشاء موقع ويب مستجيب Responsive لمعرض صور." ] }, "learn-css-grid-by-building-a-magazine": { "title": "تعلم CSS Grid عن طريق بناء مجلة", "intro": [ - "تمنحك CSS Grid التحكم في صفوف وأعمدة تصميم صفحة الويب الخاصة بك.", + "تمنحك CSS Grid التحكم في صفوف وأعمدة تصميم صفحتك الويب.", "في هذه الدورة، ستقوم ببناء مقال في مجلة. ستتعلم كيفية استخدام CSS Grid، بما في ذلك مفاهيم مثل صفوف الشبكة Grid rows وأعمدة الشبكة Grid columns." ] }, "learn-typography-by-building-a-nutrition-label": { "title": "تعلم الطباعة Typography عن طريق بناء علامة التغذية", "intro": [ - "التيبوغرافي هو فن تصميم النص الخاص بك ليكون سهل القراءة ويناسب الغرض منه.", - "في هذه الدورة، ستستخدم typography لإنشاء صفحة ويب لتسمية التغذية. ستتعلم كيفية تغيير نمط النص، وتعديل ارتفاع الخط line-height، و تغيير وضع position نصك باستخدام CSS." + "إن تشكيل الخط فن لتصميم نصك ليسهل قراءة ويلائم غرضه.", + "في هذه الدورة، ستستخدم typography لإنشاء صفحة ويب لتسمية التغذية. ستتعلم كيفية تغيير تشكيل النص، وتعديل ارتفاع الخط line-height، و تغيير وضع position نصك باستخدام CSS." ] }, "learn-css-transforms-by-building-a-penguin": { @@ -204,7 +204,7 @@ "title": "تعلم المزيد عن Selectors Pseudo في CSS عن طريق بناء كشف ميزانية", "intro": [ "يمكنك استخدام CSS pseudo selectors لتغيير عناصر HTML محددة.", - "في هذه الدورة ، ستبني ميزانية عامة باستخدام pseudo selectors. سوف تتعلم كيفية تغيير نمط عنصر ما عندما تحوم فوقه بالماوس الخاص بك، وتفعيل أحداث أخرى على صفحة الويب الخاصة بك." + "في هذه الدورة، ستبني ميزانية عامة باستخدام المنتقات الزائفة pseudo selectors. سوف تتعلم كيفية تغيير تصميم عنصر ما عندما تحوم فوقه بماوسك، وتفعيل أحداث أخرى على صفحتك الويب." ] }, "learn-css-colors-by-building-a-set-of-colored-markers": { @@ -219,7 +219,7 @@ "javascript-algorithms-and-data-structures": { "title": "الخوارزميات وهياكل البيانات في JavaScript", "intro": [ - "في حين أن HTML و CSS يتحكمان في محتوى الصفحة ونمط الصفحة، يتم استخدام Javascript لجعلها تفاعلية. في شهادة الخوارزميات وهياكل البيانات في JavaScript، ستتعلم أساسيات JavaScript بما في ذلك المتغيرات والمصفوفات Arrays والكائنات Objects والحلقات Loops والدوال.", + "في حين أن HTML و CSS يتحكمان في محتوى الصفحة وتصميم الصفحة، يستخدم Javascript لجعلها تفاعلية. في شهادة الخوارزميات وهياكل البيانات في JavaScript، ستتعلم أساسيات JavaScript بما في ذلك المتغيرات variables, والقوائم arrays, والكائنات objects والحلقات loops, والوظائف functions.", "بمجرد أن يكون لديك الأساسيات، ستطبق تلك المعرفة عن طريق إنشاء خوارزميات للتلاعب بالسلاسل strings، تحديد الأعداد، بل وحساب مدار محطة الفضاء الدولية.", "في هذا المشوار ستتعلم أيضًا أسلوبين أو نموذجين مهمين للبرمجة: البرمجة كائنية التوجه (OOP) ، والبرمجة الوظيفية (FP)." ], @@ -228,8 +228,8 @@ "basic-javascript": { "title": "أساسيات JavaScript", "intro": [ - "JavaScript هي لغة برمجة يمكنك استخدامها لجعل صفحات الويب تفاعلية. إنها إحدى التكنولوجيات الأساسية للويب، إلى جانب HTML و CSS، وهي مدعومة بجميع المتصفحات الحديثة.", - "في هذه الدورة ، ستتعلم مفاهيم البرمجة الأساسية في Javascript. ستبدأ بهياكل البيانات الأساسية مثل الأرقام والنصوص. ثم سوف تتعلم العمل مع المصفوفات والكائنات والدوال والحلقات والشروط وأكثر من ذلك." + "إن JavaScript لغة برمجة يمكنك استخدامها لجعل صفحات الويب تفاعلية. إنها إحدى التكنولوجيات الأساسية للويب، إلى جانب HTML و CSS، وهي مدعومة بجميع المتصفحات الحديثة.", + "في هذه الدورة، ستتعلم مفاهيم البرمجة الأساسية في Javascript. ستبدأ بهياكل البيانات الأساسية مثل الأرقام والنصوص. ثم سوف تتعلم العمل مع الكائنات والقوائم والوظائف والحلقات والشروط وتعبيرات if/else وأكثر من ذلك." ] }, "es6": { @@ -241,9 +241,9 @@ ] }, "regular-expressions": { - "title": "التعبيرات العادية Regular Expressions", + "title": "العبارات العادية Regular Expressions", "intro": [ - "التعبيرات العادية Regular expressions، غالباً ما تسمي \"regex\" أو \"regexp\"، هي أنماط تساعد المبرمجين على المطابقة والبحث واستبدال النص. التعابير العادية قوية جداً، ولكن يمكن أن يكون من الصعب قراءتها لأنها تستخدم رموز خاصة لعمل مطابقات أكثر تعقيداً ومرونة.", + "العبارات العادية Regular expressions، غالباً ما تسمي \"regex\" أو \"regexp\"، هي أنماط تساعد المبرمجين على المطابقة والبحث واستبدال النص. التعابير العادية قوية جداً، ولكن يمكن أن يكون من الصعب قراءتها لأنها تستخدم رموز خاصة لعمل مطابقات أكثر تعقيداً ومرونة.", "في هذه الدورة، ستتعلم كيفية استخدام الرموز الخاصة، التقاط المجموعات، النظرات الإيجابية والسلبية، وتقنيات أخرى لمطابقة أي نص تريده." ] }, @@ -258,8 +258,8 @@ "basic-data-structures": { "title": "هياكل البيانات الأساسية", "intro": [ - "يمكن تخزين البيانات والوصول إليها بعدة طرق. أنت تعرف بالفعل بعض هياكل بيانات javascript الشائعة - المصفوفات والكائنات.", - "في هذه الدورة لهياكل البيانات الأساسية، ستتعلم المزيد عن الاختلافات بين المصفوفات والكائنات، وعن كيفية استخدامها في أوضاع مختلفة. سوف تتعلم أيضاً كيفية استخدام أساليب Javascript المفيدة مثل splice() و Object.keys() للوصول إلى البيانات والتلاعب بها." + "يمكن تخزين البيانات والوصول إليها بعدة طرق. أنت تعرف بالفعل بعض هياكل بيانات javascript الشائعة - القوائم والكائنات.", + "في هذه الدورة لهياكل البيانات الأساسية، ستتعلم المزيد عن الاختلافات بين القوائم والكائنات، وعن كيفية استخدامها في أوضاع مختلفة. سوف تتعلم أيضاً كيفية استخدام أساليب Javascript المفيدة مثل splice() و Object.keys() للوصول إلى البيانات والتلاعب بها." ] }, "basic-algorithm-scripting": { @@ -267,7 +267,7 @@ "intro": [ "الخوارزمية هي سلسلة من التعليمات خطوة بخطوة تصف كيفية القيام بشيء ما.", "يساعدك تفكيك المشكلة إلى أجزاء أصغر والتفكير بعناية حول كيفية حل كل جزء علي حدي بواسطة الكود البرمجي على كتابة خوارزميات اكثر فاعلية.", - "في هذه الدورة، ستتعلم أساسيات التفكير الخوارزمي عن طريق كتابة الخوارزميات التي تفعل كل شيء من تحويل درجات الحرارة إلى التعامل مع المصفوفات ثنائية الأبعاد 2D arrays المعقدة." + "في هذه الدورة، ستتعلم أساسيات التفكير الخوارزمي عن طريق كتابة خوارزميات تفعل كل شيء من تحويل درجات الحرارة إلى التعامل مع القوائم ثنائية الأبعاد 2D arrays المعقدة." ] }, "object-oriented-programming": { @@ -280,8 +280,8 @@ "functional-programming": { "title": "البرمجة الوظيفية Functional Programming", "intro": [ - "البرمجة الوظيفية هي نهج شائع آخر لتطوير البرمجيات. في البرمجة الوظيفية، يتم تنظيم الكود في وظائف أصغر وأساسية يمكن الجمع بينها لبناء برامج معقدة.", - "في هذه الدورة، ستتعلم المفاهيم الأساسية للبرمجة الوظيفية بما في ذلك الدوال العادية، كيفية تجنب الطفرات وكيفية كتابة كود أنظف مع أساليب مثل .map() و .filter()." + "إن البرمجة الوظيفية نهج شائع آخر لتطوير البرمجيات. في البرمجة الوظيفية، ينظم الكود في وظائف أصغر وأساسية يمكن الجمع بينها لبناء برامج معقدة.", + "في هذه الدورة، ستتعلم المفاهيم الأساسية للبرمجة الوظيفية بما في تلك الوظيفة العادية، كيفية تجنب الطفرات وكيفية كتابة كود أنظف مع أساليب مثل .map() و .filter()." ] }, "intermediate-algorithm-scripting": { @@ -305,23 +305,23 @@ "note": "", "blocks": { "build-a-caesars-cipher-project": { - "title": "بناء مشروع Caesars Cipher", + "title": "بناء مشروع شفرة قيصر", "intro": ["", ""] }, "build-a-cash-register-project": { - "title": "بناء مشروع Cash Register", + "title": "بناء مشروع مكنة لتسجيل النقود", "intro": ["", ""] }, "build-a-palindrome-checker-project": { - "title": "بناء مشروع Palindrome Checker", + "title": "أنشئ مشروع مدقق لمعاكس المقطع النصي", "intro": ["", ""] }, "build-a-roman-numeral-converter-project": { - "title": "بناء مشروع Roman Numeral Converter", + "title": "أنشئ مشروع محول للأرقام الرومانية", "intro": ["", ""] }, "build-a-telephone-number-validator-project": { - "title": "بناء مشروع Telephone Number Validator", + "title": "بناء مشروع مدقق الأرقام الهواتف", "intro": ["", ""] }, "learn-basic-javascript-by-building-a-role-playing-game": { @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "تعلم البرمجة الوظيفية عن طريق بناء Spreadsheet", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Learn Advanced Array Methods by Building a Statistics Calculator", + "intro": ["", ""] } } }, @@ -372,7 +376,7 @@ "react": { "title": "React", "intro": [ - "React هي مكتبة شائعة من مكتبات JavaScript لبناء واجهة مستخدم قابلة لإعادة البناء اعتماداً على المكون لصفحات الويب أو التطبيقات.", + "إن React مكتبة شائعة من مكتبات JavaScript لبناء واجهة مستخدم قابلة لإعادة البناء اعتماداً على المكون لصفحات الويب أو التطبيقات.", "يجمع React بين الـ HTML ووظائف الـ JavaScript في لغة ترميز خاصة به تدعى JSX. كما أن React يجعل من السهل إدارة تدفق البيانات في التطبيق.", "في هذه الدورة ، ستتعلم كيفية إنشاء مكونات مختلفة من React وإدارة البيانات في شكل State و Props و استخدام أساليب دورة الحياة المختلفة مثل componentDidMount، وأكثر من ذلك بكثير." ] @@ -389,13 +393,13 @@ "title": "React and Redux", "intro": [ "كثيرا ما يُشار إلى React و Redux معاً، ولسبب وجيه. المطور الذي أنشأ Redux كان مطور لـ React و اراد أن يسهل مشاركة البيانات عبر المكونات المختلفة.", - "الآن بعد أن عرفت كيفية إدارة تدفق البيانات المشتركة مع Redux، حان الوقت للجمع بين تلك المعرفة و React. في دورات React و Redux، ستبني مكون React وتتعلم كيفية إدارة الحالة state محلياً على مستوى المكون. وعبر التطبيق باكمله مع Redux." + "الآن بعد أن عرفت كيفية إدارة تدفق البيانات المشتركة مع Redux، حان الوقت للجمع بين تلك المعرفة و React. في دورات React و Redux، ستبني مكون React وتتعلم كيفية إدارة الحالة state محلياً على مستوى المكون. وعبر التطبيق برمته مع Redux." ] }, "front-end-development-libraries-projects": { "title": "مشاريع مكتبات تطوير واجهة المستخدم", "intro": [ - "حان الوقت لوضع مهاراتك في مكتبات تطوير واجهات المستخدم للاختبار، استخدم Bootstrap, jQuery, Sass, React و Redux لبناء 5 مشاريع لتختبر كل ما تعلمته حتى هذه النقطة.", + "حان الوقت لوضع مهاراتك في مكتبات تطوير واجهات المستخدم للاختبار. استخدم Bootstrap, و jQuery, و Sass, و React, و Redux لبناء 5 مشروعات لتختبر ما تعلمته حتى هذه النقطة.", "أكمل جميع المشاريع الخمسة، وستحصل على شهادة في مكتبات تطوير واجهة المستخدم." ] } @@ -551,9 +555,9 @@ "back-end-development-and-apis": { "title": "تطوير الواجهات الخلفية للمواقع و واجهات برمجة التطبيقات - Back End Development and APIs", "intro": [ - "حتى هذه النقطة، لقد استخدمت JavaScript فقط في الواجهة الأمامية لإضافة تفاعل إلى صفحة، أو حل تحديات الخوارزميات، أو بناء SPA. ولكن يمكن أيضاً استخدام JavaScript في الواجهة الخلفية back end، أو الخادم، لبناء تطبيقات ويب بأكملها.", + "حتى هذه النقطة، لقد استخدمت JavaScript فقط في الواجهة الأمامية لإضافة تفاعل إلى صفحة، أو حل تحديات الخوارزميات، أو بناء SPA. ولكن يمكن أيضاً استخدام JavaScript في الواجهة الخلفية back end، أو السيرفر، لبناء تطبيقات ويب برمتها.", "واليوم، فإن إحدى الطرق الشائعة لبناء التطبيقات هي من خلال الخدمات المصّغرة microservices، وهي تطبيقات صغيرة ومحددة تعمل معاً لتشًكل وحدة اكبر.", - "في شهادة واجهة برمجة التطبيقات والـAPIs، ستتعلم كيفية انشاء تطبيقات back end جاهزة باستخدام Node.js و npm. سوف تقوم أيضا ببناء تطبيقات ويب باستخدام إطار Express وبناء microservice لـ People Finder باستخدام MongoDB ومكتبة Mongoose." + "في شهادة تطوير واجهات الBack End و الAPIs، سوف تتعلم كيف تنشئ تطبيقات back end باستخدام Node.js و npm. سوف تقوم أيضا ببناء تطبيقات الويب باستخدام إطار العمل Express، و بناء microservice لإيجاد الأفراد باستخدام MongoDB ومكتبة Mongoose." ], "note": "", "blocks": { @@ -584,7 +588,7 @@ "back-end-development-and-apis-projects": { "title": "مشاريع تطوير الواجهات الخلفية للمواقع و واجهات برمجة التطبيقات APIs", "intro": [ - "لقد عملت مع واجهة برمجة التطبيقات APIs من قبل، ولكن الآن بعد أن عرفت npm، وNode, Express، وMongoDB وMongoose، حان الوقت لبناء API بنفسك، بالاعتماد على كل ما تعلمته حتى هذه النقطة لإنشاء 5 خدمات مصغّرة microservices مختلفة، وهي تطبيقات أصغر محدودة النطاق.", + "لقد عملت مع واجهة برمجة التطبيقات APIs من قبل، ولكن الآن بعد أن عرفت npm، و Node, و Express، و MongoDB، و Mongoose، حان الوقت لبناء API بنفسك، بالاعتماد على ما تعلمته حتى هذه النقطة لإنشاء 5 خدمات مصغّرة microservices مختلفة، وهي تطبيقات أصغر محدودة النطاق.", "بعد إنشاء هذه البرمجيات، سيكون لديك 5 APIs رائعة للخدمات الصغرى يمكنك عرضها للأصدقاء والعائلة وأصحاب العمل المحتملين، وستحصل أيضًا على شهادة تطوير الواجهة الخلفية وواجهات برمجة التطبيقات." ] } @@ -628,7 +632,7 @@ "title": "الحوسبة العلمية باستخدام Python", "intro": [ "Python هي واحدة من لغات البرمجة الأكثر شعبية ومرونة اليوم. يمكنك استخدامها لكل شيء من البرمجة النصية الأساسية إلى تعلم الآلة.", - "في شهادة الحوسبة العلمية باستخدام Python، ستتعلم أساسيات Python مثل المتغيرات والحلقات والشروط والدوال. ثم ستصل بسرعة إلى هياكل البيانات المعقدة، والربط الشبكي Networking، وقواعد البيانات العلائقية، وتصوّر البيانات." + "في شهادة الحوسبة العلمية باستخدام Python، ستتعلم أساسيات Python مثل المتغيرات والحلقات والشروط والوظيفة. ثم ستصل بسرعة إلى هياكل البيانات المعقدة، والربط الشبكي Networking، وقواعد البيانات العلائقية، وتصوّر البيانات." ], "note": "", "blocks": { @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "مشروع أودين", + "intro": [ + "The Odin Project is one of those \"What I wish I had when I was learning\" resources. ", + "Not everyone has access to a computer science education or the funds to attend an intensive coding school and neither of those is right for everyone anyway.", + "This project is designed to fill in the gap for people who are trying to hack it on their own but still want a high quality education." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Learn HTML Foundations", + "intro": ["A description is to be determined"] + }, + "top-build-a-recipe-project": { + "title": "Learn HTML Foundations by Building a Recipe Page", + "intro": ["A description is to be determined"] + } + } + }, "misc-text": { "certification": "شهادة {{cert}}", "browse-other": "تصفح الشهادات المجانية الأخرى\n(نوصي بالقيام بها بالترتيب)", diff --git a/client/i18n/locales/arabic/links.json b/client/i18n/locales/arabic/links.json index d1b675b924c2e4..c86b1892e839e5 100644 --- a/client/i18n/locales/arabic/links.json +++ b/client/i18n/locales/arabic/links.json @@ -2,7 +2,7 @@ "help-translate-link-url": "https://contribute.freecodecamp.org/#/how-to-translate-files", "top-contributors": "https://www.freecodecamp.org/news/freecodecamp-top-contributors/", "footer": { - "about-url": "https://www.freecodecamp.org/news/about/", + "about-url": "https://www.freecodecamp.org/arabic/news/about/", "shop-url": "https://www.freecodecamp.org/shop/", "support-url": "https://www.freecodecamp.org/arabic/news/support/", "sponsors-url": "https://www.freecodecamp.org/news/sponsors/", diff --git a/client/i18n/locales/arabic/motivation.json b/client/i18n/locales/arabic/motivation.json index ef2f8304ce8f70..ec5ed1d86e6e6f 100644 --- a/client/i18n/locales/arabic/motivation.json +++ b/client/i18n/locales/arabic/motivation.json @@ -1,864 +1,142 @@ { "compliments": [ - "Over the top!", - "Down the rabbit hole we go!", - "Bring that rain!", - "Target acquired.", - "Feel that need for speed!", - "You've got guts!", - "We have liftoff!", - "To infinity and beyond!", - "Encore!", - "Onward!", - "Challenge destroyed!", - "It's on like Donkey Kong!", - "Power level? It's over 9000!", - "Coding spree!", - "Code long and prosper.", - "The crowd goes wild!", - "One for the Guinness book!", - "Flawless victory!", - "Most efficient!", - "You've got the touch!", - "You're on fire!", - "The town is now red!", - "To the nines!", - "To the Batmobile!", - "Pull out all the stops!", - "You're a wizard, Harry!", - "You're an all star!", - "Way to go!", - "Outta sight!", - "You're crushing it!", - "What sorcery is this?", - "The world rejoices!", - "That's the way it's done!", - "You rock!", - "Woo-hoo!", - "We knew you could do it!", - "Hyper Combo Finish!", - "Nothing but net!", - "Boom-shakalaka!", - "You're a shooting star!", - "You're unstoppable!", - "Way cool!", - "Walk on that sunshine!", - "Keep on trucking!", - "Off the charts!", - "There is no spoon!", - "Cranked it up to 11!", - "Escape velocity reached!", - "You make this look easy!", - "Passed with flying colors!", - "You've got this!", - "Happy, happy, joy, joy!", - "Tomorrow, the world!", - "Your powers combined!", - "It's alive. It's alive!", - "Sonic Boom!", - "Here's looking at you, Code!", - "Ride like the wind!", - "Legen - wait for it - dary!", - "Ludicrous Speed! Go!", - "Most triumphant!", - "One loop to rule them all!", - "By the power of Grayskull!", - "You did it!", - "Storm that castle!", - "Face-melting guitar solo!", - "Checkmate!", - "Bodacious!", - "Tubular!", - "You're outta sight!", - "Keep calm and code on!", - "Even sad panda smiles!", - "Even grumpy cat approves!", - "Kool Aid Man says oh yeah!", - "Bullseye!", - "Far out!", - "You're heating up!", - "Standing ovation!", - "Nice one!", - "All right!", - "Hasta la vista, challenge!", - "Terminated.", - "Off the hook!", - "Thundercats, Hooo!", - "Shiver me timbers!", - "Raise the roof!", - "Bingo!", - "Even Honey Badger cares!", - "Helm, Warp Nine. Engage!", - "Gotta code 'em all!", - "Spool up the FTL drive!", - "Cool beans!", - "They're in another castle.", - "Power UP!", - "Pikachu chooses you!", - "I gotta have more cowbell.", - "Gotta go fast!", - "Yippee!", - "Cowabunga!", - "Moon Prism Power!", - "Plus Ultra!", - "Everything's coming up Milhouse!" + "ياي! روعة!", + "!جزاك الله خير", + "!فعلا أحسنت", + "!ربنا يسعد قلبك", + "!صبرت ونلت", + "!عبقري ياناس", + "!برافو", + "!ما شاء الله", + "!ياواد ياشاطر", + "!إيه الشطارة دي ياناس", + "!مقطع السمكة وديلها", + "!مبروك التفوق", + "!تحية كبيرة", + "!عشت يا باشا", + "!مفيش زيك بجد", + "!هو حلم ولا علم", + "!قمة الروعة", + "!طلعت برا المريخ", + "!أدي الكلام ولا بلاش", + "!مفيش حد أدك" ], "motivationalQuotes": [ { - "quote": "Whatever you are, be a good one.", - "author": "Abraham Lincoln" + "quote": "ليست السعادة في أن تعمل دائمًا ما تريد بل في أن تريد ما تعمله.", + "author": "جان-بول سارتر" }, { - "quote": "A change in perspective is worth 80 IQ points.", - "author": "Alan Kay" + "quote": "لا يوجد رجل فاشل ولكن يوجد رجل بدأ من القاع وبقي فيه.", + "author": "فولتير" }, { - "quote": "The best way to predict the future is to invent it.", - "author": "Alan Kay" + "quote": "الرجل القوي يعمل والضعيف يتمنى.", + "author": "جورج برنارد شو" }, { - "quote": "The future is not laid out on a track. It is something that we can decide, and to the extent that we do not violate any known laws of the universe, we can probably make it work the way that we want to.", - "author": "Alan Kay" + "quote": "قليل من العلم مع العمل به أنفع من كثير من العلم مع قلة العمل به.", + "author": "أفلاطون" }, { - "quote": "We can only see a short distance ahead, but we can see plenty there that needs to be done.", - "author": "Alan Turing" + "quote": "العمل المتواصل هو الأساس للنجاح.", + "author": "فادي عزام" }, { - "quote": "In the depth of winter, I finally learned that within me there lay an invincible summer.", - "author": "Albert Camus" + "quote": "التعلم أفضل من النجاح، فالنجاح يأتي بعد التعلم.", + "author": "الحسن البصري" }, { - "quote": "A person who never made a mistake never tried anything new.", - "author": "Albert Einstein" + "quote": "لا تخاف من الإختبار، لأن الإختبار هو الطريق الوحيد للإكتشاف.", + "author": "علي أحمد سعيد إسبر" }, { - "quote": "Creativity is intelligence having fun.", - "author": "Albert Einstein" + "quote": "كل من يعمل بجد يحصل على ما يريد.", + "author": "عبد الرحمن الأبنودي" }, { - "quote": "I have no special talents. I am only passionately curious.", - "author": "Albert Einstein" + "quote": "خذ من اليوم عبرة، وخذ من الأمس خبرة.", + "author": "سلمان العودة" }, { - "quote": "Life is like riding a bicycle. To keep your balance, you must keep moving.", - "author": "Albert Einstein" + "quote": "الفارق بين المستحيل و الممكن يتوقف على عزيمة المرء و اصراره.", + "author": "محمد علي كلاي" }, { - "quote": "Make everything as simple as possible, but not simpler.", - "author": "Albert Einstein" + "quote": "اعطني اذنك اعطك صوتاً .. اعطني عقلك اعطك فكرة.", + "author": "أبو جعفر المنصور" }, { - "quote": "Never memorize something that you can look up.", - "author": "Albert Einstein" + "quote": "أينما ركزت الانتباه تدفقت الطاقة و ظهرت النتيجة.", + "author": "إبراهيم الفقي" }, { - "quote": "Once we accept our limits, we go beyond them.", - "author": "Albert Einstein" + "quote": "تضعك المعرفة في صفوف الحكماء .. و يضعك العمل في صفوف الناجحين .. و يضعك التفاهم في صفوف السعداء.", + "author": "إبراهيم الفقي" }, { - "quote": "Play is the highest form of research.", - "author": "Albert Einstein" + "quote": "الذكي يعرف من اجاباته ، والحكيم يعرف من اسئلته.", + "author": "نجيب محفوظ" }, { - "quote": "We cannot solve our problems with the same thinking we used when we created them.", - "author": "Albert Einstein" + "quote": "أكتبوا أحسن ما تسمعون، و احفـظوا أحسن ما تكتبون، و تحدثوا بأحسن ما تسمعون.", + "author": "عبد الله بن المقفع" }, { - "quote": "Wisdom is not a product of schooling but of the lifelong attempt to acquire it.", - "author": "Albert Einstein" + "quote": "الإنسان في كل مرحلة من مراحل حياته .. مازال يولد.", + "author": "مصطفى السباعي" }, { - "quote": "Your imagination is your preview of life's coming attractions.", - "author": "Albert Einstein" + "quote": "من لم يحتمل ذل التعلم ساعة ، بقي في ذل الجهل أبداً .", + "author": "الاصمعي" }, { - "quote": "There is only one corner of the universe you can be certain of improving, and that's your own self.", - "author": "Aldous Huxley" + "quote": "طوبى لمن جمع بين همة الشباب وحكمة الشيوخ.", + "author": "طه حسين" }, { - "quote": "I am thankful for my struggle because, without it, I wouldn't have stumbled across my strength.", - "author": "Alex Elle" + "quote": "إياك والرضى عن نفسك فإنه يضطرك إلى الخمول، وإياك والعجب فإنه يورطك في الحمق، وإياك والغرور فإنه يظهر للناس نقائصك كلها ولا يخفيها.", + "author": "طه حسين" }, { - "quote": "The most common way people give up their power is by thinking they don't have any.", - "author": "Alice Walker" + "quote": "السعادة هي ذلك الإحساس الغريب الذي يراودنا حينما تشغلنا ظروف الحياة عن أن نكون أشقياء.", + "author": "طه حسين" }, { - "quote": "Follow your inner moonlight. Don't hide the madness.", - "author": "Allen Ginsberg" + "quote": "يقول لك المرشدون : اقرأ ما ينفعك ، و لكني أقول : بل انتفع بما تقرأ.", + "author": "عباس محمود العقاد" }, { - "quote": "The most difficult thing is the decision to act. The rest is merely tenacity.", - "author": "Amelia Earhart" + "quote": "من غير تحديد الأهداف بوضوح يصعب الحديث عن قرارات جيدة.", + "author": "خولة القزويني" }, { - "quote": "Life shrinks or expands in proportion with one's courage.", - "author": "Anaïs Nin" + "quote": "لتكن أعمالك مصغية دائماً إلى صوت هدفك الأسمى.", + "author": "خولة القزويني" }, { - "quote": "Weeks of programming can save you hours of planning.", - "author": "Unknown" + "quote": "الضعيف هو الغبى الذى لا يعرف سر قوته.", + "author": "نجيب محفوظ" }, { - "quote": "Quality is not an act, it is a habit.", - "author": "Aristotle" + "quote": "على المرء أن يختار أفكاره كما يختار ملابسه و كتبه و أصدقاءه و مسكنه.", + "author": "كفاح فياض" }, { - "quote": "Start where you are. Use what you have. Do what you can.", - "author": "Arthur Ashe" + "quote": "قد تكون أفضل الطرق أصعبها و لكن عليك دائما اتباعها ، إذ أن الاعتياد عليها سيجعل الامور تبدو سهلة.", + "author": "أبو الطيب المتنبي" }, { - "quote": "Nothing is impossible, the word itself says \"I'm possible\"!", - "author": "Audrey Hepburn" + "quote": "من المحتمل ألا تستطيع التحكم في الظروف ، و لكنك تستـطيع التحكم في أفكارك ، فالتفكير الايجابي يؤدي الى الفعل الايجابي و النتائج الايجابية.", + "author": "إبراهيم الفقي" }, { - "quote": "Every strike brings me closer to the next home run.", - "author": "Babe Ruth" + "quote": "الفكرة باختصار : ضع هدفاً ، و لا تتخل عنه حتى تحققه.", + "author": "خولة القزويني" }, { - "quote": "By failing to prepare, you are preparing to fail.", - "author": "Benjamin Franklin" - }, - { - "quote": "Tell me and I forget. Teach me and I remember. Involve me and I learn.", - "author": "Benjamin Franklin" - }, - { - "quote": "Well done is better than well said.", - "author": "Benjamin Franklin" - }, - { - "quote": "There are no short cuts to any place worth going.", - "author": "Beverly Sills" - }, - { - "quote": "Controlling complexity is the essence of computer programming.", - "author": "Brian Kernighan" - }, - { - "quote": "I fear not the man who has practiced 10,000 kicks once, but I fear the man who has practiced one kick 10,000 times.", - "author": "Bruce Lee" - }, - { - "quote": "There are far, far better things ahead than any we leave behind.", - "author": "C.S. Lewis" - }, - { - "quote": "We are what we believe we are.", - "author": "C.S. Lewis" - }, - { - "quote": "With the possible exception of the equator, everything begins somewhere.", - "author": "C.S. Lewis" - }, - { - "quote": "You are never too old to set another goal, or to dream a new dream.", - "author": "C.S. Lewis" - }, - { - "quote": "Somewhere, something incredible is waiting to be known.", - "author": "Carl Sagan" - }, - { - "quote": "When you have a dream, you've got to grab it and never let go.", - "author": "Carol Burnett" - }, - { - "quote": "If you're not making mistakes, then you're not making decisions.", - "author": "Catherine Cook" - }, - { - "quote": "Find what you love and let it kill you.", - "author": "Charles Bukowski" - }, - { - "quote": "What matters most is how well you walk through the fire.", - "author": "Charles Bukowski" - }, - { - "quote": "It is not the strongest of the species that survive, nor the most intelligent, but the one most responsive to change.", - "author": "Charles Darwin" - }, - { - "quote": "The details are not the details. They make the design.", - "author": "Charles Eames" - }, - { - "quote": "Creativity is more than just being different. Anybody can plan weird. That's easy. What's hard is to be as simple as Bach. Making the simple, awesomely simple, that's creativity.", - "author": "Charles Mingus" - }, - { - "quote": "Life is 10% what happens to you and 90% how you react to it.", - "author": "Charles R. Swindoll" - }, - { - "quote": "You will do foolish things, but do them with enthusiasm.", - "author": "Colette" - }, - { - "quote": "It does not matter how slowly you go as long as you do not stop.", - "author": "Confucius" - }, - { - "quote": "Real knowledge is to know the extent of one's ignorance.", - "author": "Confucius" - }, - { - "quote": "The past cannot be changed. The future is yet in your power.", - "author": "Confucius" - }, - { - "quote": "Looking at code you wrote more than two weeks ago is like looking at code you are seeing for the first time.", - "author": "Dan Hurvitz" - }, - { - "quote": "Someday is not a day of the week.", - "author": "Denise Brennan-Nelson" - }, - { - "quote": "UNIX is simple. It just takes a genius to understand its simplicity.", - "author": "Dennis Ritchie" - }, - { - "quote": "The way I see it, if you want the rainbow, you gotta put up with the rain!", - "author": "Dolly Parton" - }, - { - "quote": "Computers are good at following instructions, but not at reading your mind.", - "author": "Donald Knuth" - }, - { - "quote": "A good programmer is someone who always looks both ways before crossing a one-way street.", - "author": "Doug Linder" - }, - { - "quote": "Creativity is a wild mind and a disciplined eye.", - "author": "Dorothy Parker" - }, - { - "quote": "Tough times never last, but tough people do.", - "author": "Dr. Robert Schuller" - }, - { - "quote": "If things start happening, don't worry, don't stew, just go right along and you'll start happening too.", - "author": "Dr. Seuss" - }, - { - "quote": "Do not go gentle into that good night. Rage, rage against the dying of the light.", - "author": "Dylan Thomas" - }, - { - "quote": "The question of whether computers can think is like the question of whether submarines can swim.", - "author": "E.W. Dijkstra" - }, - { - "quote": "Any code of your own that you haven't looked at for six or more months might as well have been written by someone else.", - "author": "Eagleson's Law" - }, - { - "quote": "Do one thing every day that scares you.", - "author": "Eleanor Roosevelt" - }, - { - "quote": "With the new day comes new strength and new thoughts.", - "author": "Eleanor Roosevelt" - }, - { - "quote": "You must do the things you think you cannot do.", - "author": "Eleanor Roosevelt" - }, - { - "quote": "Light tomorrow with today.", - "author": "Elizabeth Barrett Browning" - }, - { - "quote": "If your dreams do not scare you, they are not big enough.", - "author": "Ellen Johnson Sirleaf" - }, - { - "quote": "Forever is composed of nows.", - "author": "Emily Dickinson" - }, - { - "quote": "Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter.", - "author": "Eric Raymond" - }, - { - "quote": "If you don't risk anything, you risk even more.", - "author": "Erica Jong" - }, - { - "quote": "The world breaks everyone, and afterward, many are strong at the broken places.", - "author": "Ernest Hemingway" - }, - { - "quote": "There is nothing noble in being superior to your fellow man; true nobility is being superior to your former self.", - "author": "Ernest Hemingway" - }, - { - "quote": "Never confuse a single defeat with a final defeat.", - "author": "F. Scott Fitzgerald" - }, - { - "quote": "I attribute my success to this - I never gave or took any excuse.", - "author": "Florence Nightingale" - }, - { - "quote": "The best revenge is massive success.", - "author": "Frank Sinatra" - }, - { - "quote": "The only limit to our realization of tomorrow, will be our doubts of today.", - "author": "Franklin D. Roosevelt" - }, - { - "quote": "Right or wrong, it's very pleasant to break something from time to time.", - "author": "Fyodor Dostoevsky" - }, - { - "quote": "The harder I work, the luckier I get.", - "author": "Gary Player" - }, - { - "quote": "Giving up is the only sure way to fail.", - "author": "Gena Showalter" - }, - { - "quote": "The only truly secure system is one that is powered off, cast in a block of concrete and sealed in a lead-lined room with armed guards.", - "author": "Gene Spafford" - }, - { - "quote": "A life spent making mistakes is not only more honorable, but more useful than a life spent doing nothing.", - "author": "George Bernard Shaw" - }, - { - "quote": "First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack.", - "author": "George Carrette" - }, - { - "quote": "Discovering the unexpected is more important than confirming the known.", - "author": "George Box" - }, - { - "quote": "We only see what we know.", - "author": "Goethe" - }, - { - "quote": "Without hard work, nothing grows but weeds.", - "author": "Gordon B. Hinckley" - }, - { - "quote": "The function of good software is to make the complex appear to be simple.", - "author": "Grady Booch" - }, - { - "quote": "When you know that you're capable of dealing with whatever comes, you have the only security the world has to offer.", - "author": "Harry Browne" - }, - { - "quote": "Pain is inevitable. Suffering is optional.", - "author": "Haruki Murakami" - }, - { - "quote": "Optimism is the faith that leads to achievement. Nothing can be done without hope and confidence.", - "author": "Helen Keller" - }, - { - "quote": "The price of anything is the amount of life you exchange for it.", - "author": "Henry David Thoreau" - }, - { - "quote": "Whether you think you can or think you can't, you're right.", - "author": "Henry Ford" - }, - { - "quote": "The most exciting phrase to hear in science, the one that heralds discoveries, is not 'Eureka!' but 'Now that's funny…'", - "author": "Isaac Asimov" - }, - { - "quote": "What you do makes a difference. And you have to decide what kind of difference you want to make.", - "author": "Jane Goodall" - }, - { - "quote": "We are all failures. At least the best of us are.", - "author": "J.M. Barrie" - }, - { - "quote": "You can't wait for inspiration. You have to go after it with a club.", - "author": "Jack London" - }, - { - "quote": "Don't wish it were easier, wish you were better.", - "author": "Jim Rohn" - }, - { - "quote": "By seeking and blundering we learn.", - "author": "Johann Wolfgang von Goethe" - }, - { - "quote": "Knowing is not enough; we must apply. Wishing is not enough; we must do.", - "author": "Johann Wolfgang von Goethe" - }, - { - "quote": "We first make our habits, then our habits make us.", - "author": "John Dryden" - }, - { - "quote": "The power of imagination makes us infinite.", - "author": "John Muir" - }, - { - "quote": "May you live every day of your life.", - "author": "Jonathan Swift" - }, - { - "quote": "Perseverance is failing 19 times and succeeding the 20th.", - "author": "Julie Andrews" - }, - { - "quote": "The work of today is the history of tomorrow, and we are its makers.", - "author": "Juliette Gordon Low" - }, - { - "quote": "If you reveal your secrets to the wind, you should not blame the wind for revealing them to the trees.", - "author": "Kahlil Gibran" - }, - { - "quote": "Optimism is an occupational hazard of programming; feedback is the treatment.", - "author": "Kent Beck" - }, - { - "quote": "Opportunity does not knock, it presents itself when you beat down the door.", - "author": "Kyle Chandler" - }, - { - "quote": "To iterate is human, to recurse divine.", - "author": "Peter Deutsch" - }, - { - "quote": "A good traveler has no fixed plans and is not intent on arriving.", - "author": "Lao Tzu" - }, - { - "quote": "An ant on the move does more than a dozing ox.", - "author": "Lao Tzu" - }, - { - "quote": "Do the difficult things while they are easy and do the great things while they are small. A journey of a thousand miles must begin with a single step.", - "author": "Lao Tzu" - }, - { - "quote": "That's the thing about people who think they hate computers. What they really hate is lousy programmers.", - "author": "Larry Niven" - }, - { - "quote": "It had long since come to my attention that people of accomplishment rarely sat back and let things happen to them. They went out and happened to things.", - "author": "Leonardo da Vinci" - }, - { - "quote": "If you're any good at all, you know you can be better.", - "author": "Lindsay Buckingham" - }, - { - "quote": "If people never did silly things, nothing intelligent would ever get done.", - "author": "Ludwig Wittgenstein" - }, - { - "quote": "You only live once, but if you do it right, once is enough.", - "author": "Mae West" - }, - { - "quote": "Live as if you were to die tomorrow. Learn as if you were to live forever.", - "author": "Mahatma Gandhi" - }, - { - "quote": "Strength does not come from physical capacity. It comes from an indomitable will.", - "author": "Mahatma Gandhi" - }, - { - "quote": "One person's 'paranoia' is another person's 'engineering redundancy'.", - "author": "Marcus J. Ranum" - }, - { - "quote": "Nothing in life is to be feared, it is only to be understood. Now is the time to understand more, so that we may fear less.", - "author": "Marie Curie" - }, - { - "quote": "If you have everything under control, you're not moving fast enough.", - "author": "Mario Andretti" - }, - { - "quote": "Education: the path from cocky ignorance to miserable uncertainty.", - "author": "Mark Twain" - }, - { - "quote": "It ain't what you don't know that gets you into trouble. It's what you know for sure that just ain't so.", - "author": "Mark Twain" - }, - { - "quote": "The secret of getting ahead is getting started.", - "author": "Mark Twain" - }, - { - "quote": "The two most important days in your life are the day you are born and the day you find out why.", - "author": "Mark Twain" - }, - { - "quote": "Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails.", - "author": "Mark Twain" - }, - { - "quote": "Any fool can write code that a computer can understand. Good programmers write code that humans can understand.", - "author": "Martin Fowler" - }, - { - "quote": "I know, somehow, that only when it is dark enough can you see the stars.", - "author": "Martin Luther King Jr." - }, - { - "quote": "It is never too late to be what you might have been.", - "author": "Mary Anne Evans" - }, - { - "quote": "Nothing will work unless you do.", - "author": "Maya Angelou" - }, - { - "quote": "You can't use up creativity. The more you use, the more you have.", - "author": "Maya Angelou" - }, - { - "quote": "We delight in the beauty of the butterfly, but rarely admit the changes it has gone through to achieve that beauty.", - "author": "Maya Angelou" - }, - { - "quote": "We may encounter many defeats, but we must not be defeated.", - "author": "Maya Angelou" - }, - { - "quote": "Everybody has talent, but ability takes hard work.", - "author": "Michael Jordan" - }, - { - "quote": "I've missed more than 9,000 shots during my career. I've lost almost 300 games. 26 times, I've been trusted to take the game winning shot and missed. I've failed over and over and over again in my life. And that is why I succeed.", - "author": "Michael Jordan" - }, - { - "quote": "Impossible is just a big word thrown around by small men who find it easier to live in the world they've been given than to explore the power they have to change it. Impossible is not a fact. It's an opinion. Impossible is not a declaration. It's a dare. Impossible is potential. Impossible is temporary. Impossible is nothing.", - "author": "Muhammad Ali" - }, - { - "quote": "A winner is a dreamer who never gives up.", - "author": "Nelson Mandela" - }, - { - "quote": "It always seems impossible until it's done.", - "author": "Nelson Mandela" - }, - { - "quote": "Failure will never overtake me if my determination to succeed is strong enough.", - "author": "Og Mandino" - }, - { - "quote": "I am not young enough to know everything.", - "author": "Oscar Wilde" - }, - { - "quote": "There is only one thing that makes a dream impossible to achieve: the fear of failure.", - "author": "Paulo Coelho" - }, - { - "quote": "Never go to bed mad. Stay up and fight.", - "author": "Phyllis Diller" - }, - { - "quote": "You can't cross the sea merely by standing and staring at the water.", - "author": "Rabindranath Tagore" - }, - { - "quote": "The only person you are destined to become is the person you decide to be.", - "author": "Ralph Waldo Emerson" - }, - { - "quote": "What you do speaks so loudly that I cannot hear what you say.", - "author": "Ralph Waldo Emerson" - }, - { - "quote": "People who are crazy enough to think they can change the world, are the ones who do.", - "author": "Rob Siltanen" - }, - { - "quote": "The best way out is always through.", - "author": "Robert Frost" - }, - { - "quote": "Today's accomplishments were yesterday's impossibilities.", - "author": "Robert H. Schuller" - }, - { - "quote": "Don't be satisfied with stories, how things have gone with others. Unfold your own myth.", - "author": "Rumi" - }, - { - "quote": "Forget safety. Live where you fear to live. Destroy your reputation. Be notorious.", - "author": "Rumi" - }, - { - "quote": "Sell your cleverness and buy bewilderment.", - "author": "Rumi" - }, - { - "quote": "The cure for pain is in the pain.", - "author": "Rumi" - }, - { - "quote": "Have no fear of perfection - you'll never reach it.", - "author": "Salvador Dalí" - }, - { - "quote": "Don't watch the clock. Do what it does. Keep going.", - "author": "Sam Levenson" - }, - { - "quote": "Ever Tried. Ever failed. No matter. Try again. Fail again. Fail better.", - "author": "Samuel Beckett" - }, - { - "quote": "The more you know, the more you realize you know nothing.", - "author": "Socrates" - }, - { - "quote": "The greatest enemy of knowledge is not ignorance, it is the illusion of knowledge.", - "author": "Stephen Hawking" - }, - { - "quote": "The universe doesn't allow perfection.", - "author": "Stephen Hawking" - }, - { - "quote": "Whether you want to uncover the secrets of the universe, or you want to pursue a career in the 21st century, basic computer programming is an essential skill to learn.", - "author": "Stephen Hawking" - }, - { - "quote": "The scariest moment is always just before you start.", - "author": "Stephen King" - }, - { - "quote": "You can, you should, and if you're brave enough to start, you will.", - "author": "Stephen King" - }, - { - "quote": "Arise, Awake and Stop not until the goal is reached.", - "author": "Swami Vivekananda" - }, - { - "quote": "It is said that your life flashes before your eyes just before you die. That is true, it's called Life.", - "author": "Terry Pratchett" - }, - { - "quote": "Believe you can and you're halfway there.", - "author": "Theodore Roosevelt" - }, - { - "quote": "I have not failed. I've just found 10,000 ways that won't work.", - "author": "Thomas A. Edison" - }, - { - "quote": "Our greatest weakness lies in giving up. The most certain way to succeed is always to try just one more time.", - "author": "Thomas A. Edison" - }, - { - "quote": "The harder the conflict, the more glorious the triumph.", - "author": "Thomas Paine" - }, - { - "quote": "The Web as I envisaged it, we have not seen it yet. The future is still so much bigger than the past.", - "author": "Tim Berners-Lee" - }, - { - "quote": "Failure is the condiment that gives success its flavor.", - "author": "Truman Capote" - }, - { - "quote": "Those who says it cannot be done should not interrupt the person doing it.", - "author": "Unknown" - }, - { - "quote": "Look at usual things with unusual eyes.", - "author": "Vico Magistetti" - }, - { - "quote": "Even if you fall on your face, you're still moving forward.", - "author": "Victor Kiam" - }, - { - "quote": "It's not whether you get knocked down, it's whether you get up.", - "author": "Vince Lombardi" - }, - { - "quote": "I dream my painting and I paint my dream.", - "author": "Vincent van Gogh" - }, - { - "quote": "Great things are done by a series of small things brought together.", - "author": "Vincent van Gogh" - }, - { - "quote": "Let us cultivate our garden.", - "author": "Voltaire" - }, - { - "quote": "Aim for the moon. If you miss, you may hit a star.", - "author": "W. Clement Stone" - }, - { - "quote": "The way to get started is to quit talking and begin doing.", - "author": "Walt Disney" - }, - { - "quote": "You miss 100% of the shots you don't take.", - "author": "Wayne Gretzky" - }, - { - "quote": "Don't let yesterday take up too much of today.", - "author": "Will Rogers" - }, - { - "quote": "Even if you're on the right track, you'll get run over if you just sit there.", - "author": "Will Rogers" - }, - { - "quote": "Do not wait to strike till the iron is hot; but make it hot by striking.", - "author": "William Butler Yeats" - }, - { - "quote": "You cannot swim for new horizons until you have courage to lose sight of the shore.", - "author": "William Faulkner" - }, - { - "quote": "Be not afraid of greatness. Some are born great, some achieve greatness, and others have greatness thrust upon them.", - "author": "William Shakespeare" - }, - { - "quote": "We know what we are, but not what we may be.", - "author": "William Shakespeare" - }, - { - "quote": "In theory there is no difference between theory and practice. In practice there is.", - "author": "Yogi Berra" - }, - { - "quote": "You can see a lot by just looking.", - "author": "Yogi Berra" - }, - { - "quote": "There is no elevator to success, you have to take the stairs.", - "author": "Zig Ziglar" - }, - { - "quote": "You don't have to be great to start, but you have to start to be great.", - "author": "Zig Ziglar" + "quote": "سر النجاح في الحياة أن تواجه مصاعبها بثبات الطير في ثورة العاصفة.", + "author": "مصطفى السباعي" } ] } diff --git a/client/i18n/locales/arabic/translations.json b/client/i18n/locales/arabic/translations.json index 8ef010ee660f6c..a0bba047beb9c2 100644 --- a/client/i18n/locales/arabic/translations.json +++ b/client/i18n/locales/arabic/translations.json @@ -1,7 +1,7 @@ { "buttons": { - "logged-in-cta-btn": "ابدأ (مجاني)", - "logged-out-cta-btn": "قم بتسجيل الدخول لحفظ تقدّمك (مجاني)", + "logged-in-cta-btn": "ابدأ (بالمجان)", + "logged-out-cta-btn": "سجل الدخول لحفظ تقدّمك (بالمجان)", "view-curriculum": "عرض المنهج الدراسي", "first-lesson": "انتقل إلى الدرس الأول", "close": "أغلق", @@ -11,11 +11,12 @@ "view": "عرض", "view-code": "أظهار الكود", "view-project": "إظهار المشروع", + "view-cert-title": "عرض {{certTitle}}", "show-cert": "عرض الشهادة", "claim-cert": "المطالبة بالشهادة", "save-progress": "حفظ التقدم", - "accepted-honesty": "لقد قبلت سياسة الصدق الأكاديمي الخاصة بنا.", - "agree": "موافق", + "accepted-honesty": "لقد وافقت على سياستنا للصدق الأكاديمي.", + "agree-honesty": "أوافق على سياسة freeCodeCamp للصدق الأكاديمي.", "save-portfolio": "حفظ عنصر الحافظة هذا", "remove-portfolio": "إزالة عنصر الحافظة هذا", "add-portfolio": "إضافة عنصر حافظة جديد", @@ -34,7 +35,7 @@ "news": "الأخبار", "donate": "تبرّع", "update-settings": "تحديث إعدادات حسابي", - "sign-me-out": "قم بتسجيل خروجي من freeCodeCamp", + "sign-me-out": "سجل خروجي من freeCodeCamp", "flag-user": "الإبلاغ عن حساب هذا المستخدم لسوء الاستخدام", "current-challenge": "انتقل إلى التحدي الحالي", "try-again": "حاول مرة أخرى", @@ -46,13 +47,13 @@ "ask-for-help": "طلب المساعدة", "create-post": "إنشاء منشور مساعدة في المنتدى", "cancel": "إلغاء", - "reset-lesson": "إعادة تعيين هذا الدرس", + "reset-lesson": "أعد الدرس ألى حالته الأولية", "run": "تشغيل", "run-test": "تشغيل الاختبارات (Ctrl + Enter)", "check-code": "تيقن من كودك (Ctrl + Enter)", "check-code-2": "تيقن من كودك", "reset": "إعادة ضبط", - "reset-code": "إعادة تعيين كل الكود", + "reset-step": "إعادة الخطوة إلى حالتها الأولية", "help": "مساعدة", "get-help": "الحصول على المساعدة", "watch-video": "شاهد الفيديو", @@ -88,24 +89,24 @@ "shawn": { "location": "شون وانغ في سنغافورة", "occupation": "مهندس برمجيات في أمازون", - "testimony": "\"من المخيف تغيير الحياة المهنية. لقد اكتسبت الثقة فقط بأنني أستطيع البرمجة من خلال العمل على مئات الساعات من الدروس المجانية على freeCodeCamp. في غضون عام كان لدي وظيفة من ستة أرقام كمهندس برمجيات. freeCodeCampغيّر حياتي.\"" + "testimony": "\"من المخيف تغيير الحياة المهنية. لقد اكتسبت الثقة بأنني أستطيع البرمجة بممارسة مئات الساعات من الدروس المجانية في freeCodeCamp فقط. في غضون عام كان لدي وظيفة بمرتب ذات ست أرقام كمهندس برمجيات. freeCodeCampغيّر حياتي.\"" }, "sarah": { "location": "سارة شيما في نيجيريا", "occupation": "مهندس برمجيات في ChatDesk", - "testimony": "freeCodeCampكان المدخل إلى مهنتي كمطور برمجيات. المنهج الدراسي الجيد والتنظيم أخذ معرفتي البرمجية من مستوى مبتدئ إلى مستوى واثق جداً. كان كل ما أحتاجه للحصول على أول وظيفة لي في شركة مدهشة.\"" + "testimony": "\"كان freeCodeCamp المدخل إلى مهنتي كمطور برمجيات. المنهج الدراسي الجيد والتنظيم أخذ معرفتي البرمجية من مستوى مبتدئ إلى مستوى واثق جداً. كان كل ما احتاجه للحصول على أول وظيفة لي في شركة مدهشة.\"" }, "emma": { "location": "إيما بوستيان في السويد", "occupation": "مهندس برمجيات في Spotify", - "testimony": "\"لقد ناضلت دائمًا لتعلم JavaScript. لقد أخذت العديد من الدورات ولكن دورة freeCodeCamp's كانت تلك العالقة. إن دراسة JavaScript وكذلك هياكل البيانات والخوارزميات على freeCodeCamp أعطتني المهارات والثقة التي كنت بحاجة إليها لإبراز عملي كمهندس برمجيات في Spotify.\"" + "testimony": "\"لقد ناضلت دائمًا لتعلم JavaScript. لقد أخذت العديد من الدورات ولكن دورة freeCodeCamp التي دامت. إن دراسة JavaScript وكذلك هياكل البيانات والخوارزميات على freeCodeCamp أعطتني المهارات والثقة التي كنت بحاجة إليها لإبراز عملي كمهندس برمجيات في Spotify.\"" } }, "certification-heading": "احصل على شهادات معتمدة مجانية في:" }, "settings": { "share-projects": "شارك مشاريعك غير التي بـ freeCodeCamp أو مقالاتك أو الـ pull requests الخاصه بك.", - "privacy": "الإعدادات في هذا القسم تمكنك من التحكم في ما يظهر في حافظة حسابك العامة على freeCodeCamp. أضغت على زر أحفظ لحفظ تغيراتك.", + "privacy": "الإعدادات في هذا القسم تمكنك من التحكم في ما يظهر في portfolio العامة على freeCodeCamp. أضغت على زر أحفظ لحفظ تغيراتك.", "data": "لمعرفة البيانات التي نحتفظ بها على حسابك، انقر فوق الزر \"تحميل بياناتك\" أدناه", "disabled": "سيتم إخفاء شهاداتك، إذا تم تعيينها إلى خاصّة.", "private-name": "اسمك لن يظهر على شهاداتك، إذا تم التعيين إلى شخصي.", @@ -142,7 +143,7 @@ "my-location": "موقعي", "my-about": "عني", "my-points": "نقاطي", - "my-heatmap": "خريطتي الحرارية", + "my-heatmap": "أوقات نشاطي", "my-certs": "شهاداتي", "my-portfolio": "حافظتي", "my-timeline": "خطي الزمني", @@ -157,12 +158,13 @@ "honesty": "سياسة الصدق الأكاديمي", "internet": "حضورك على الإنترنت", "portfolio": "إعدادات المحفظة", - "privacy": "إعدادات الخصوصية" + "privacy": "إعدادات الخصوصية", + "personal-info": "البيانات الشخصية" }, "danger": { "heading": "منطقة الخطر", "be-careful": "يرجى توخي الحذر. التغييرات في هذا القسم دائمة.", - "reset": "إعادة تعيين كل تقدمي", + "reset": "أعد تقدمي ألى حالته الأولية", "delete": "حذف حسابي", "delete-title": "حذف حسابي", "delete-p1": "سيؤدي هذا حقًا إلى حذف جميع بياناتك، بما في ذلك جميع معلومات تقدمك وحسابك.", @@ -170,11 +172,11 @@ "delete-p3": "إذا كان هناك شيء يمكننا فعله بشكل أفضل، ارسل لنا رسالة بريد إلكتروني بدلاً من ذلك وسنقوم بأفضل ما لدينا: <0>{{email}}", "nevermind": "لا أريد حذف حسابي", "certain": "أنا متأكد 100٪. احذف كل ما يتعلق بهذا الحساب", - "reset-heading": "إعادة تعيين تقدمي", + "reset-heading": "أعد تقدمي ألى حالته الأولية", "reset-p1": "سيؤدي هذا بالفعل إلى حذف كل تقدمك، نقاطك، التحديات المكتملة، سجلاتنا لمشاريعك، أي شهادات لديك، كل شيء.", "reset-p2": "لن نكون قادرين على استرجاع أي منها لك في وقت لاحق، حتى لو غيّرت رأيك.", "nevermind-2": "لا داعي للقلق ، لا أريد حذف كل تقدمي", - "reset-confirm": "إعادة تعيين كل شيء. أريد أن أبدأ من البداية" + "reset-confirm": "أعد كل شيء ألى حالته الأولية. أريد أن أبدأ من البداية" }, "email": { "missing": "ليس لديك بريد إلكتروني مرتبط بهذا الحساب.", @@ -222,7 +224,6 @@ "total-points_plural": "مُجمل النقاط {{count}}", "points": "{{count}} نقطة في {{date}}", "points_plural": "{{count}} نقاط في {{date}}", - "screen-shot": "لقطة شاشة لـ{{title}}", "page-number": "{{pageNumber}} من {{totalPages}}" }, "footer": { @@ -231,7 +232,7 @@ "donation-initiatives": "التبرعات لـ freeCodeCamp تذهب لمبادراتنا التعليمية، وتساعد في دفع تكاليف الخوادم، والخدمات، والموظفين.", "donate-text": "يمكنك <1>تقديم تبرع قابل للخصم الضريبي هنا .", "trending-guides": "أدلة إرشادية", - "our-nonprofit": "منظمتنا الخيرية", + "our-nonprofit": "مؤسستنا الخيرية", "links": { "about": "حول", "alumni": "شبكة الخريجين", @@ -249,6 +250,7 @@ }, "learn": { "heading": "مرحباً بكم في منهج freeCodeCamp.", + "skip-to-content": "Skip to content", "welcome-1": "مرحباً بعودتك، {{name}}.", "welcome-2": "مرحباً بك في freeCodeCamp.org", "start-at-beginning": "إذا كنت جديداً على البرمجة، ننصحك على <0>البدء من البداية.", @@ -272,6 +274,9 @@ "add-subtitles": "المساعدة في تحسين أو إضافة ترجمات", "wrong-answer": "عذراً، هذه ليست الإجابة الصحيحة. قم بالمحاولة مرة أخرى؟", "check-answer": "انقر على الزر أدناه للتحقق من إجابتك.", + "assignment-not-complete": "يرجى إنهاء المهام", + "assignments": "Assignments", + "question": "Question", "solution-link": "رابط الحل", "github-link": "رابط Github", "submit-and-go": "أرسل وانتقل إلى التحدي التالي", @@ -288,8 +293,8 @@ "tried-rsa": "إذا كنت قد جربت طريقة <0>اقرأ-ابحث-اسأل، فيمكنك طلب المساعدة في منتدى freeCodeCamp.", "rsa": "اقرأ ، ابحث ، اسأل", "rsa-forum": "قبل إجراء موضوع جديدة يرجى الاطلاع على ما إذا كان سؤالك <0> قد تم الإجابة عليه فعلًا في المنتدى .", - "reset": "إعادة تعيين هذا الدرس؟", - "reset-warn": "هل أنت متأكد من رغبتك في إعادة تعيين هذا الدرس؟ سيتم إعادة تعيين المحرر والاختبارات.", + "reset": "أعد الدرس ألى حالته الأولية؟", + "reset-warn": "هل أنت متأكد من رغبتك في إعادة الدرس ألى حالته الأولية؟ سيتم إعادة المحرر والاختبارات إلى حالتهما الأولية.", "reset-warn-2": "لا يمكن التراجع عن هذا", "scrimba-tip": "نصيحة: إذا كان المتصفح المصغر يغطي الكود البرمجي ، انقر واسحب لتحريكه. كذلك لا تتردد في إيقاف وتعديل التعليمات البرمجية في الفيديو في أي وقت.", "chal-preview": "معاينة التحدي", @@ -297,7 +302,6 @@ "certs": "شهادة {{title}}" }, "editor-tabs": { - "info": "معلومات", "code": "الكود", "tests": "الاختبارات", "restart": "أعد التشغيل", @@ -307,6 +311,10 @@ "notes": "ملاحظات", "preview": "معاينة" }, + "editor-alerts": { + "tab-trapped": "الضغط على زر tab سيدرج الآن رمز التباعد", + "tab-free": "الضغط على زر tab سينقل تركيز على عنصر إلى العنصر التالي الذي يمكن التركيز عليه الآن" + }, "help-translate": "ما زلنا نترجم الشهادات التالية.", "help-translate-link": "ساعدنا على الترجمة.", "project-preview-title": "إليك معاينة لما ستقوم ببناؤه", @@ -332,7 +340,7 @@ "if-help-university": "لقد حققنا قدرا كبيرا من التقدم بالفعل. أدعم منظمتنا الخيرية بالطريق الطويل الذي أمامنا." }, "donate": { - "title": "ادعم منظمتنا الخيرية", + "title": "ادعم مؤسستنا الخيرية", "processing": "نحن نقوم بمعالجة تبرعك.", "redirecting": "جارٍ إعادة توجيهك...", "thanks": "شكرا على التبرع", @@ -357,7 +365,6 @@ "become-supporter": "أصبح داعماً", "duration": "كن داعماً لمرة واحدة لمنظمتنا الخيرية.", "duration-2": "كن داعماً شهريا لمنظمتنا الخيرية.", - "duration-3": "كن داعماً سنويا لمنظمتنا الخيرية", "duration-4": "كن داعماً لمنظمتنا الخيرية", "nicely-done": "ممتاز، لقد انتهيت لتوك من {{block}}.", "credit-card": "بطاقة ائتمان", @@ -372,8 +379,8 @@ "email-receipt": "البريد الإلكتروني (سوف نرسل لك إيصال تبرع قابل للخصم من الضرائب):", "need-help": "بحاجة إلى مساعدة مع تبرعاتك الحالية أو السابقة؟", "forward-receipt": "إعادة توجيه نسخة من إيصال التبرع الخاص بك إلى donors@freecodecamp.org وإخبارنا كيف يمكننا المساعدة.", - "efficiency": "freeCodeCamp هي مؤسسة تعليمية خيرية عالية الكفاءة.", - "why-donate-1": "عندما تتبرع لـ freeCodeCamp ، فإنك تساعد الناس على تعلم مهارات جديدة وإعالة عائلاتهم.", + "efficiency": "إن freeCodeCamp مؤسسة تعليمية خيرية عالية الكفاءة.", + "why-donate-1": "عندما تتبرع إلى freeCodeCamp، فإنك تساعد الناس على تعلم مهارات جديدة وإعالة عائلاتهم.", "why-donate-2": "كما تساعدنا ايضا على إنشاء موارد جديدة لك لاستخدامها لتوسيع مهاراتك التكنولوجية الخاصة.", "bigger-donation": "هل ترغب في تقديم تبرع أكبر لمرة واحدة، أو إرسال شيكًا بالبريد الإلكتروني، أو التبرع بطرق أخرى؟", "other-ways": "فيما يلي العديد من <0>الطرق الأخرى الذي يمكنك بها دعم مهمتنا الخيرية.", @@ -383,14 +390,14 @@ "expiration": "تاريخ انتهاء الصلاحية:", "secure-donation": "التبرع الآمن", "faq": "الأسئلة الشائعة", - "only-you": "أنت فقط من يمكنه رؤية هذه الرسالة. تهانينا لحصولك على هذه الشهادة. إنها ليست مهمة سهلة. أدارة freeCodeCamp ليس سهلاً أيضًا. وهي إلى ذلك ليست بمهمة رخيصة الثمن. ساعدنا على مساعدتك أنت والعديد من الأشخاص الآخرين حول العالم. قدم تبرع دعمي معفى من الضرائب لمنظمتنا الخيرية اليوم.", + "only-you": "أنت فقط من يمكنه رؤية هذه الرسالة. تهانينا لحصولك على هذه الشهادة. إنه ليس بالأمر اليسير. أدارة freeCodeCamp ليس بالأمر اليسير أيضًا. وإلى ذلك ليست بالأمر زهيد. ساعدنا على مساعدتك والعديد من الأشخاص الآخرين حول العالم. قدم تبرع دعمي معفى من الضرائب لمؤسستنا الخيرية اليوم.", "get-help": "كيف يمكنني الحصول على المساعدة في تبرعاتي؟", "how-transparent": "ما مدى شفافية freeCodeCamp.org؟", "very-transparent": "نحن نملك تصنيف بلاتينيوم للشفافية من GuideStar.org.", "download-irs": "يمكنك <0>تنزيل رسالة تحديد الـ IRS الخاصة بنا هنا .", "download-990": "يمكنك <0>تنزيل أحدث 990 (التقرير الضريبي السنوي) هنا .", "how-efficient": "ما مدى كفاءة freeCodeCamp؟", - "fcc-budget": "ميزانية freeCodeCamp أصغر بكثير من معظم المنظمات خيرية المماثلة. نحن لم نجلب جامعي أموال محترفين. بدلاً من ذلك، Quincy يفعل كل شيء بنفسه.", + "fcc-budget": "ميزانية freeCodeCamp أصغر بكثير من معظم المؤسسات خيرية المماثلة. نحن لم نجلب جامعي أموال محترفين. بدلاً من ذلك، Quincy يفعل كل شيء بنفسه.", "help-millions": "ومع ذلك، وبميزانية لا تتجاوز بضع مئات الآلاف من الدولارات سنويا، تمكنا من مساعدة ملايين الناس.", "how-one-time": "كيف يمكنني تقديم تبرع لمرة واحدة؟", "one-time": "إذا كنت تفضل تقديم تبرعات لمرة واحدة، يمكنك دعم مهمة freeCodeCamp كلما كان لديك lمقدار من المال لا تحتاجه. يمكنك استخدام <0>هذا الرابط للتبرع بأي مبلغ ترغب به من خلال PayPal.", @@ -400,23 +407,23 @@ "can-check": "هل يمكنني إرسال شيك مادي؟", "yes-check": "نعم، نحن نقبل بالشيكات. يمكنك إرساله إلينا على:", "how-matching-gift": "كيف يمكنني إعداد الهدايا المطابقة من رب العمل لدي، أو خصم الرواتب؟", - "employers-vary": "هذا يختلف من صاحب عمل إلى صاحب عمل، ومنظمتنا الخيرية مدرجة فعلًا في العديد من قواعد البيانات الكبيرة المطابقة للتبرعات.", + "employers-vary": "هذا يختلف من صاحب عمل إلى صاحب عمل، ومؤسستنا الخيرية مدرجة فعلًا في العديد من قواعد البيانات الكبيرة والمتطابقة للتبرعات.", "some-volunteer": "بعض الناس قادرون على التطوع في freeCodeCamp وأرباب عملهم يتطابقون من خلال التبرع بمبلغ ثابت في الساعة يعادل وقت التطوع. أما أرباب العمل الآخرون فسيضاهون أي تبرعات يقدمها المتبرعون لحد معين", "help-matching-gift": "إذا كنت بحاجة إلى مساعدة في ذلك، يرجى إرسال بريد إلكتروني مباشر: Quincy@freecodecamp.org", - "how-endowment": "كيف يمكنني اعداد هدية منح لـ freeCodeCamp.org؟", + "how-endowment": "كيف يمكنني إعداد هدية منح إلى freeCodeCamp.org؟", "endowment": "هذه ستكون مساعدة هائلة. بما أن هذه عملية يدوية أكثر، يمكن لـ Quincy أن يساعدك فيها شخصيا. يرجى مراسلته مباشرة على Quincy@freecodecamp.org.", - "how-legacy": "كيف يمكنني اعداد هدية مستقبلية لـ freeCodeCamp.org؟", + "how-legacy": "كيف يمكنني إعداد هدية مستقبلية إلى freeCodeCamp.org؟", "we-honored": "سيشرفنا أن نضع مثل هذه الهدية في الاستخدام الجيد لمساعدة الناس في جميع أنحاء العالم على تعلم البرمجة. وتبعا لمكان سكنك، قد يكون هذا معفيا من الضرائب.", "legacy-gift-message": "أعطي وأوريث [مبلغ _____ دولار أمريكي (أو عملة أخرى) أو _____ في المائة من الباقي وبقايا تركتي] إلى freeCodeCamp.org (رقم التعريف الضريبي لشركة Free Code Camp، Inc. 82-0779546) ، وهي مؤسسة خيرية بموجب قوانين ولاية ديلاوير، الولايات المتحدة، وتقع حاليًا في 3905 Hedgcoxe Rd، PO Box 250352، Plano، Texas، 75025 United States، لاستخدامها في أغراضها الخيرية العامة وفقًا لتقديرها.", "thank-wikimedia": "ونود أن نشكر مؤسسة ويكيميديا على توفير هذه اللغة الرسمية لنا لكي نستخدمها.", "legacy-gift-questions": "إذا كان لديك أي أسئلة حول هذه العملية، يرجى إرسال بريد الإلكتروني إلى Quincy@freecodecamp.org.", - "how-stock": "كيف يمكنني التبرع بالاسهم لـ freeCodeCamp.org؟", + "how-stock": "كيف يمكنني التبرع بالأسهم إلى freeCodeCamp.org؟", "welcome-stock": "نحن نرحب بتبرعاتك للأسهم. يرجى إرسال بريد إلكتروني مباشر إلى Quincy ويمكنه مساعدتك في ذلك، ومشاركة تفاصيل حساب الوساطة الخاص بالمؤسسة الخيرية: Quincy@freecodecamp.org.", "how-receipt": "هل يمكنني الحصول على إيصال تبرع حتى يمكنني خصم تبرعي من ضرائبي؟", "just-forward": "بالتأكيد. فقط أرسل الإيصال من معاملتك إلى donors@freecodecamp.org، أخبرنا بأنك تريد إيصال وأي تعليمات خاصة قد تكون لديك، وسنرد مع إيصال لك.", "how-update": "لقد قمت بإعداد تبرع شهري، ولكن أحتاج إلى تحديث أو إيقاف تكرار ذلك شهريا. كيف يمكنني القيام بذلك؟", "take-care-of-this": "فقط قم بإرسال واحد من إيصالاتك الشهرية للتبرع إلى donors@freecodecamp.org و أخبرنا بما تريد منا أن نفعل. سنعتني بهذا من أجلك ونرسل لك تأكيدات.", - "anything-else": "هل هناك أي شيء آخر يمكنني معرفته حول التبرع لـ freeCodeCamp.org؟", + "anything-else": "هل هناك أي شيء آخر يمكنني معرفته حول التبرع إلى freeCodeCamp.org؟", "other-support": "إذا كانت هناك طريقة أخرى غير مدرجة هنا ترغب بها في دعم منظمتنا الخيرية ومهمتها، أو إذا كان لديك أي أسئلة على الإطلاق، فيرجى إرسال بريد إلكتروني إلى Quincy على العنوان quincy@freecodecamp.org." }, "report": { @@ -460,7 +467,8 @@ "iframe-preview": "معاينة {{title}}", "iframe-alert": "عادة هذا الرابط من شأنه أن يجلبك إلى موقع آخر! إنه يعمل. هذا رابط: {{externalLink}}", "iframe-form-submit-alert": "عادة سيتم تقديم هذا النموذج! إنه يعمل. سيتم إرسال هذا إلى: {{externalLink}}", - "document-notfound": "لم يوجد المستند" + "document-notfound": "لم يوجد المستند", + "slow-load-msg": "يبدو أن هذا يستغرق وقتاً أطول من المعتاد، الرجاء محاولة تحديث الصفحة." }, "icons": { "gold-cup": "كأس الذهب", @@ -475,10 +483,11 @@ "hint": "تلميح", "heart": "Heart", "initial": "مبدئي", + "input-reset": "حذف مصطلحات البحث", "info": "معلومات المقدمة", "spacer": "فاصل", "toggle": "تبديل علامة التحقق", - "magnifier": "عدسه مكبرة" + "magnifier": "إرسال مصطلحات البحث" }, "aria": { "fcc-curriculum": "منهج freeCodeCamp", @@ -504,15 +513,16 @@ "step": "الخطوة", "steps": "الخطوات", "steps-for": "خطوات {{blockTitle}}", - "code-example": "{{codeName}} code example" + "code-example": "{{codeName}} مثال على الكود", + "opens-new-window": "فتح في نافذة جديدة" }, "flash": { - "honest-first": "للمطالبة بشهادة ، يجب عليك أولاً قبول سياسة الصدق الأكاديمي الخاصة بنا", + "honest-first": "للمطالبة بشهادة، يجب عليك أولاً الموافقة على سياسة للصدق الأكاديمي", "really-weird": "حدث شيء غريب حقاً، إذا حدث مرة أخرى، يرجى النظر في الإبلاغ عنها على https://github.com/freeCodeCamp/freeCodeCamp/issues/new", "not-right": "يبدو ان هناك خطأ ما. لقد تم إنشاء تقرير وتم إخطار فريق freeCodeCamp.org", "went-wrong": "حدث خطأ ما، الرجاء التحقق والمحاولة مرة أخرى", "account-deleted": "تم حذف حسابك بنجاح", - "progress-reset": "تم إعادة تعيين تقدمك", + "progress-reset": "تم إعادة تقدمك ألى حالته الأولية", "not-authorized": "غير مصرح لك بالمتابعة على هذا المسار", "could-not-find": "لم نتمكن من العثور على ما كنت تبحث عنه. الرجاء التحقق والمحاولة مرة أخرى", "wrong-updating": "حدث خطأ ما في تحديث حسابك. الرجاء التحقق والمحاولة مرة أخرى", @@ -586,7 +596,8 @@ "editor-url": "تذكر أن تقدم رابط التطبيق المباشر.", "http-url": "لا يمكن استخدام عنوان URL غير آمن (http).", "own-work-url": "تذكر أن تقدم عملك الخاص.", - "publicly-visible-url": "تذكر أن ترسل عنوان URL للتطبيق متاح للجميع." + "publicly-visible-url": "تذكر أن ترسل عنوان URL للتطبيق متاح للجميع.", + "path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path" }, "certification": { "executive": "المدير التنفيذي، freeCodeCamp.org", @@ -601,10 +612,10 @@ "source": "المصدر", "footnote": "إذا كنت تشك في أن أيا من هذه المشاريع ينتهك <2>سياسة الأمانة الأكاديمية، يرجى <5>إبلاغ فريقنا بهذا .", "title": { - "Build a Personal Portfolio Webpage": "قم ببناء مشروع صفحة ويب لعرض نماذج الاعمال الشخصية", + "Build a Personal Portfolio Webpage": "أنشئ معرضا لأعمالك الخاصة", "Build a Random Quote Machine": "بناء آلة عرض اقتباسات عشوائية", "Build a 25 + 5 Clock": "بناء ساعة 25 + 5", - "Build a JavaScript Calculator": "بناء حاسبة بإستخدام JavaScript", + "Build a JavaScript Calculator": "بناء آلة حاسبة باستخدام JavaScript", "Show the Local Weather": "إظهار الطقس المحلي", "Use the TwitchTV JSON API": "استخدام TwitchTV JSON API", "Stylize Stories on Camper News": "نسق قصص على أخبار Camper", @@ -638,14 +649,14 @@ "Anonymous Message Board": "لوحة الرسائل المجهولة", "Build a Tribute Page": "بناء مشروع صفحة الثناء", "Build a Survey Form": "بناء مشروع نموذج الدراسة الاستقصائية", - "Build a Product Landing Page": "بناء صفحة هبوط لمنتج", + "Build a Product Landing Page": "أنشئ صفحة لعرض المنتج", "Build a Technical Documentation Page": "بناء مشروع صفحة التوثيق التقني", "Palindrome Checker": "مدقق باليندروم", "Roman Numeral Converter": "تحويل الأرقام الرومانية", "Caesars Cipher": "Caesars Cipher", "Telephone Number Validator": "مدقق رقم الهاتف", "Cash Register": "سجل النقدية", - "Build a Drum Machine": "بناء آلة الدرامز", + "Build a Drum Machine": "أنشئ آلة الطبول", "Visualize Data with a Choropleth Map": "التصوير المرئي للبيانات باستخدام خريطة التمثيل اللوني", "Visualize Data with a Treemap Diagram": "التصوير المرئي للبيانات باستخدام الخريطة الشجرية", "Exercise Tracker": "متعقب التمارين", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "مصنف صور القطط والكلاب", "Book Recommendation Engine using KNN": "محرك توصية للكتب باستخدام KNN", "Linear Regression Health Costs Calculator": "حاسبة التكاليف الصحية بالانحدار الخطي", - "Neural Network SMS Text Classifier": "مصنف الرسائل SMS بالشبكة العصبية" + "Neural Network SMS Text Classifier": "مصنف الرسائل SMS بالشبكة العصبية", + "Celestial Bodies Database": "قاعدة بيانات الأحجام الهائلة", + "World Cup Database": "قاعدة بيانات كأس العالم", + "Salon Appointment Scheduler": "جدولة مواعيد الصالون", + "Periodic Table Database": "قاعدة بيانات قائمة العناصر الكيميائية", + "Number Guessing Game": "لُعْبَة تخمين العدد", + "Build a freeCodeCamp Forum Homepage": "بناء صفحة لمنتدى freeCodeCamp" } + }, + "title": { + "Responsive Web Design": "تصميم مواقع الويب المتجاوبة", + "responsive-web-design": "شهادة تصميم مواقع الويب المتجاوبة", + "JavaScript Algorithms and Data Structures": "الخوارزميات وهياكل البيانات في JavaScript", + "javascript-algorithms-and-data-structures": "شهادة الخوارزميات وهياكل البيانات في JavaScript", + "Front End Development Libraries": "مكتبات تطوير واجهة المستخدم", + "front-end-development-libraries": "شهادة مكتبات تطوير واجهة المستخدم", + "Data Visualization": "التصوير المرئي للبيانات", + "data-visualization": "شهادة التصوير المرئي للبيانات", + "Relational Database": "قاعدة البيانات ذات علاقات", + "relational-database-v8": "شهادة قاعدة البيانات ذات علاقات", + "Back End Development and APIs": "تطوير الواجهات الخلفية للمواقع و APIs", + "back-end-development-and-apis": "شهادة تطوير الواجهات الخلفية للمواقع و APIs", + "Quality Assurance": "ضمان الجودة", + "quality-assurance-v7": "شهادة ضمان الجودة", + "Scientific Computing with Python": "الحساب العلمي باستخدام Python", + "scientific-computing-with-python-v7": "شهادة الحساب العلمي مع Python", + "Data Analysis with Python": "تحليل البيانات باستخدام Python", + "data-analysis-with-python-v7": "شهادة تحليل البيانات باستخدام Python", + "Information Security": "أمن المعلومات", + "information-security-v7": "شهادة امن المعلومات", + "Machine Learning with Python": "تعلم الآلة باستخدام Python", + "machine-learning-with-python-v7": "مشاريع تعلم الآله باستخدام Python", + "Legacy Front End": "الواجهة الأمامية التراثية", + "legacy-front-end": "شهادة الواجهة الأمامية التراثية", + "Legacy Back End": "الواجهة الخلفية التراثية", + "legacy-back-end": "شهادة الواجهة الخلفية التراثية", + "Legacy Data Visualization": "التصوير المرئي للبيانات التراثي", + "legacy-data-visualization": "شهادة التصوير المرئي للبيانات", + "Legacy Information Security and Quality Assurance": "أمن المعلومات وشهادة ضمان الجودة التراثية", + "information-security-and-quality-assurance": "شهادة أمن المعلومات وشهادة ضمان الجودة", + "Legacy Full Stack Certification": "شهادة الشامل الخلفية التراثية", + "Legacy Full Stack": "الشامل الخلفية التراثية", + "full-stack": "شهادة الشامل الخلفية" } }, "certification-card": { diff --git a/client/i18n/locales/chinese-traditional/intro.json b/client/i18n/locales/chinese-traditional/intro.json index cf1d7d845108e4..cec79b3a46b3db 100644 --- a/client/i18n/locales/chinese-traditional/intro.json +++ b/client/i18n/locales/chinese-traditional/intro.json @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "通過構建電子表格學習函數式編程", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Learn Advanced Array Methods by Building a Statistics Calculator", + "intro": ["", ""] } } }, @@ -553,7 +557,7 @@ "intro": [ "在這之前,你只是在前端使用 JavaScript 來給頁面添加交互、解決算法挑戰,或構建一個 SPA(單頁應用程序)。但 JavaScript 也可以用於後端或者服務器來構建整個 web 應用程序。", "今天,構建應用軟件的廣受歡迎的方法之一是微服務,這些微服務是一種小型模塊化的應用,能夠共同形成一個更大的整體。", - "在後端開發和 APIs 認證中,你將學習如何使用 Node.js 和 npm(Node 包管理工具)來寫後端。你還將使用 Express 框架構建 web 應用程序,並使用 MongoDB 和 Mongoose 庫構建一個 People Finder 微服務。" + "In the Back End Development and APIs Certification, you'll learn how to write back end apps with Node.js and npm. You'll also build web applications with the Express framework, and build a People Finder microservice with MongoDB and the Mongoose library." ], "note": "", "blocks": { @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "The Odin Project", + "intro": [ + "The Odin Project is one of those \"What I wish I had when I was learning\" resources. ", + "Not everyone has access to a computer science education or the funds to attend an intensive coding school and neither of those is right for everyone anyway.", + "This project is designed to fill in the gap for people who are trying to hack it on their own but still want a high quality education." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Learn HTML Foundations", + "intro": ["A description is to be determined"] + }, + "top-build-a-recipe-project": { + "title": "Learn HTML Foundations by Building a Recipe Page", + "intro": ["A description is to be determined"] + } + } + }, "misc-text": { "certification": "{{cert}} 認證", "browse-other": "瀏覽我們的其他免費認證\n(我們建議你按順序學習)", diff --git a/client/i18n/locales/chinese-traditional/motivation.json b/client/i18n/locales/chinese-traditional/motivation.json index d65a69bb268698..12eb62efeed4a5 100644 --- a/client/i18n/locales/chinese-traditional/motivation.json +++ b/client/i18n/locales/chinese-traditional/motivation.json @@ -1,819 +1,856 @@ { "compliments": [ - "Over the top!", - "Down the rabbit hole we go!", - "Bring that rain!", - "Target acquired.", - "Feel that need for speed!", - "You've got guts!", - "We have liftoff!", - "To infinity and beyond!", - "Encore!", - "Onward!", - "Challenge destroyed!", - "It's on like Donkey Kong!", - "Power level? It's over 9000!", - "Coding spree!", - "Code long and prosper.", - "The crowd goes wild!", - "One for the Guinness book!", - "Flawless victory!", - "Most efficient!", - "You've got the touch!", - "You're on fire!", - "The town is now red!", - "To the nines!", - "To the Batmobile!", - "Pull out all the stops!", - "You're a wizard, Harry!", - "You're an all-star!", - "Way to go!", - "Outta sight!", - "You're crushing it!", - "What sorcery is this?", - "The world rejoices!", - "That's the way it's done!", - "You rock!", - "Woo-hoo!", - "We knew you could do it!", - "Hyper Combo Finish!", - "Nothing but net!", - "Boom-shakalaka!", - "You're a shooting star!", - "You're unstoppable!", - "Way cool!", - "Walk on that sunshine!", - "Keep on trucking!", - "Off the charts!", - "There is no spoon!", - "Cranked it up to 11!", - "Escape velocity reached!", - "You make this look easy!", - "Passed with flying colors!", - "You've got this!", - "Happy, happy, joy, joy!", - "Tomorrow, the world!", - "Your powers combined!", - "It's alive. It's alive!", - "Sonic Boom!", - "Here's looking at you, Code!", - "Ride like the wind!", - "Legen - wait for it - dary!", - "Ludicrous Speed! Go!", - "Most triumphant!", - "One loop to rule them all!", - "By the power of Grayskull!", - "You did it!", - "Storm that castle!", - "Face-melting guitar solo!", - "Checkmate!", - "Bodacious!", - "Tubular!", - "You're outta sight!", - "Keep calm and code on!", - "Even sad panda smiles!", - "Even grumpy cat approves!", - "Kool Aid Man says oh yeah!", - "Bullseye!", - "Far out!", - "You're heating up!", - "Standing ovation!", - "Nice one!", - "All right!", - "Hasta la vista, challenge!", - "Terminated.", - "Off the hook!", - "Thundercats, Hooo!", - "Shiver me timbers!", - "Raise the roof!", - "Bingo!", - "Even Honey Badger cares!", - "Helm, Warp Nine. Engage!", - "Gotta code 'em all!", - "Spool up the FTL drive!", - "Cool beans!", - "They're in another castle.", - "Power UP!", - "Pikachu chooses you!", - "I gotta have more cowbell.", - "Gotta go fast!", - "Yippee!", - "Cowabunga!", - "Moon Prism Power!", - "Plus Ultra!" + "太棒了!", + "我們跳進兔子洞!", + "雨下吧!", + "獲取目標。", + "體驗極速快感!", + "你有膽量!", + "我們升空了!", + "飛向無限!", + "再來一次!", + "向前進!", + "挑戰被摧毀!", + "重磅如同大金剛!", + "戰鬥力?超過 9000!", + "編碼狂潮!", + "編碼不息,繁榮昌盛。", + "人羣變得瘋狂!", + "一個吉尼斯世界紀錄!", + "完勝!", + "最高效率!", + "你有手感了!", + "你正在燃燒!", + "滿城春色!", + "完美!", + "上蝙蝠車!", + "全力以赴!", + "你是個巫師,哈利!", + "你是全明星隊員!", + "幹得好!", + "棒極了!", + "你太出色了!", + "這是什麼魔法?", + "世界歡欣鼓舞!", + "難題就是這樣搞定的!", + "你真棒!", + "嗚呼!", + "我們就知道你能行!", + "超級組合終結!", + "空心球!", + "炸彈-沙卡拉卡!", + "你是一顆流星!", + "你勢不可擋!", + "太酷了!", + "走在那陽光下!", + "堅持下去!", + "水平爆表!", + "勺子並不存在!", + "調到最大音量!", + "達到逃逸速度!", + "你讓這看起來很簡單!", + "以優異的成績通過!", + "你能行!", + "開心,開心,快樂,快樂!", + "明天,征服世界!", + "你的全部力量!", + "它活了。它活了!", + "索尼克音爆!", + "看着你呢,代碼!", + "疾馳如風!", + "傳——奇!", + "離譜的速度!出發!", + "高奏凱歌!", + "用一個循環來統治它們!", + "憑藉灰殼堡的神力!", + "你做到了!", + "衝進城堡!", + "蕩人心魄的吉他獨奏!", + "完全擊敗!", + "大有膽識!", + "厲害!", + "你真強啊!", + "保持冷靜,繼續編碼!", + "即使是悲傷的熊貓也會微笑!", + "即使脾氣暴躁的貓也同意!", + "如此感覺無以倫比。", + "正中靶心!", + "前衛!", + "燃燒吧,小宇宙!", + "起立鼓掌!", + "不錯!", + "好啊!", + "回見,挑戰!", + "終結了。", + "脫身!", + "霹靂貓顯神威!", + "讓我五體投地!", + "大顯身手!", + "答對了!", + "連蜜獾都在乎!", + "掌舵,第九曲速。啓動!", + "必須全部編碼!", + "發動超光速引擎!", + "酷豆子!", + "她們在另一個城堡裏。", + "加電!", + "皮卡丘選擇了你!", + "我要再多點牛鈴。", + "得快點!", + "了不起!", + "卡瓦邦嘎!", + "月亮棱鏡能量!", + "超越極致!", + "米爾豪斯一切都會好起來的!" ], "motivationalQuotes": [ { - "quote": "Whatever you are, be a good one.", - "author": "Abraham Lincoln" + "quote": "不管你是誰,做個好人。", + "author": "亞伯拉罕·林肯" }, { - "quote": "A change in perspective is worth 80 IQ points.", - "author": "Alan Kay" + "quote": "換一個角度看問題值80點智商。", + "author": "艾倫·凱" }, { - "quote": "The best way to predict the future is to invent it.", - "author": "Alan Kay" + "quote": "預測未來的最好方法是創造未來。", + "author": "艾倫·凱" }, { - "quote": "The future is not laid out on a track. It is something that we can decide, and to the extent that we do not violate any known laws of the universe, we can probably make it work the way that we want to.", - "author": "Alan Kay" + "quote": "未來不是在軌道上規劃的。這是我們可以決定的事情,只要我們不違反任何已知的宇宙法則,我們就可以讓它按我們想要的方式運行。", + "author": "艾倫·凱" }, { - "quote": "We can only see a short distance ahead, but we can see plenty there that needs to be done.", - "author": "Alan Turing" + "quote": "我們只能看到前面很短的距離,但我們可以看到有很多事情需要做。", + "author": "艾倫·圖靈" }, { - "quote": "In the depth of winter, I finally learned that within me there lay an invincible summer.", - "author": "Albert Camus" + "quote": "隆冬時節,我終於明白,我的內心深處有一個不可戰勝的夏天。", + "author": "阿爾伯特·加繆" }, { - "quote": "A person who never made a mistake never tried anything new.", - "author": "Albert Einstein" + "quote": "從不犯錯的人從不嘗試新事物。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "Creativity is intelligence having fun.", - "author": "Albert Einstein" + "quote": "創造力是智力的樂趣。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "I have no special talents. I am only passionately curious.", - "author": "Albert Einstein" + "quote": "我沒有什麼特別的才能。我只是非常好奇。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "Life is like riding a bicycle. To keep your balance, you must keep moving.", - "author": "Albert Einstein" + "quote": "生活就像騎自行車。爲了保持平衡,你必須繼續前進。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "Make everything as simple as possible, but not simpler.", - "author": "Albert Einstein" + "quote": "事情應該力求簡單,但不能過於簡單。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "Never memorize something that you can look up.", - "author": "Albert Einstein" + "quote": "絕不要去記那些你能夠查得到的東西。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "Once we accept our limits, we go beyond them.", - "author": "Albert Einstein" + "quote": "一旦我們接受了自己的極限,我們就超越了它們。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "Play is the highest form of research.", - "author": "Albert Einstein" + "quote": "玩耍是研究的最高形式。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "We cannot solve our problems with the same thinking we used when we created them.", - "author": "Albert Einstein" + "quote": "我們不能用我們創造問題時的思維來解決問題。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "Wisdom is not a product of schooling but of the lifelong attempt to acquire it.", - "author": "Albert Einstein" + "quote": "智慧不是學校教育的產物,而是終身學習的產物。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "Your imagination is your preview of life's coming attractions.", - "author": "Albert Einstein" + "quote": "你的想像是你人生的預覽。", + "author": "阿爾伯特·愛因斯坦" }, { - "quote": "There is only one corner of the universe you can be certain of improving, and that's your own self.", - "author": "Aldous Huxley" + "quote": "宇宙中只有一個角落是你可以切實改進的,那就是你自己。", + "author": "奧爾德斯·赫胥黎" }, { - "quote": "The most common way people give up their power is by thinking they don't have any.", - "author": "Alice Walker" + "quote": "我感謝我的奮鬥,因爲沒有它,我就不會偶然發現自己的力量。", + "author": "亞歷克斯·艾爾" }, { - "quote": "Follow your inner moonlight. Don't hide the madness.", - "author": "Allen Ginsberg" + "quote": "人們放棄權力最常見的方式是認爲自己沒有權力。", + "author": "艾麗絲·沃克" }, { - "quote": "The most difficult thing is the decision to act. The rest is merely tenacity.", - "author": "Amelia Earhart" + "quote": "跟隨你內心的月光。別掩飾自己的瘋狂。", + "author": "艾倫·金斯伯格" }, { - "quote": "Life shrinks or expands in proportion with one's courage.", - "author": "Anaïs Nin" + "quote": "最困難的是決定採取行動。剩下的只是堅韌。", + "author": "阿梅莉亞·埃爾哈特" }, { - "quote": "Weeks of programming can save you hours of planning.", - "author": "Unknown" + "quote": "生命的縮小或擴大與一個人的勇氣成正比。", + "author": "阿奈斯·寧" }, { - "quote": "Quality is not an act, it is a habit.", - "author": "Aristotle" + "quote": "數週的編程可以節省你數小時的計劃。", + "author": "佚名" }, { - "quote": "Start where you are. Use what you have. Do what you can.", - "author": "Arthur Ashe" + "quote": "質量不是一種行爲,而是一種習慣。", + "author": "亞里士多德" }, { - "quote": "Nothing is impossible, the word itself says \"I'm possible\"!", - "author": "Audrey Hepburn" + "quote": "從現在開始。利用你所擁有的。盡你所能。", + "author": "亞瑟·阿什" }, { - "quote": "Every strike brings me closer to the next home run.", - "author": "Babe Ruth" + "quote": "沒有什麼是不可能的,連這個詞本身都說“不,可能”!", + "author": "奧黛麗·赫本" }, { - "quote": "By failing to prepare, you are preparing to fail.", - "author": "Benjamin Franklin" + "quote": "每一擊都讓我離下一個本壘打越來越近。", + "author": "貝比·魯斯" }, { - "quote": "Tell me and I forget. Teach me and I remember. Involve me and I learn.", - "author": "Benjamin Franklin" + "quote": "如果你沒有做好準備,你就是在準備失敗。", + "author": "本傑明·富蘭克林" }, { - "quote": "Well done is better than well said.", - "author": "Benjamin Franklin" + "quote": "告訴我,我會忘記。教我,我會記住。讓我參與,我會學習。", + "author": "本傑明·富蘭克林" }, { - "quote": "There are no short cuts to any place worth going.", - "author": "Beverly Sills" + "quote": "說得好不如做得好。", + "author": "本傑明·富蘭克林" }, { - "quote": "Controlling complexity is the essence of computer programming.", - "author": "Brian Kernighan" + "quote": "任何值得去的地方都沒有捷徑。", + "author": "貝弗利·希爾斯" }, { - "quote": "I fear not the man who has practiced 10,000 kicks once, but I fear the man who has practiced one kick 10,000 times.", - "author": "Bruce Lee" + "quote": "控制複雜性是計算機編程的本質。", + "author": "布萊恩·科尼漢" }, { - "quote": "There are far, far better things ahead than any we leave behind.", - "author": "C.S. Lewis" + "quote": "我不怕遇到練習過一萬種腿法的對手,但害怕遇到只將一種腿法練習一萬次的強敵。", + "author": "李小龍" }, { - "quote": "We are what we believe we are.", - "author": "C.S. Lewis" + "quote": "比起遺落在過去的,未來還有更加美好的在等待着我們。", + "author": "C.S. 路易斯" }, { - "quote": "With the possible exception of the equator, everything begins somewhere.", - "author": "C.S. Lewis" + "quote": "我們就是我們所相信的自己。", + "author": "C.S. 路易斯" }, { - "quote": "You are never too old to set another goal, or to dream a new dream.", - "author": "C.S. Lewis" + "quote": "可能除了赤道以外,一切都從某處開始。", + "author": "C.S. 路易斯" }, { - "quote": "Somewhere, something incredible is waiting to be known.", - "author": "Carl Sagan" + "quote": "無論年紀多大,你都可以設立新目標或擁有新夢想。", + "author": "C.S. 路易斯" }, { - "quote": "If you're not making mistakes, then you're not making decisions.", - "author": "Catherine Cook" + "quote": "在某個地方,一些不可思議的事物正在等你去發現。", + "author": "卡爾·薩根" }, { - "quote": "Find what you love and let it kill you.", - "author": "Charles Bukowski" + "quote": "當你有夢想時,你必須抓住它,永不放棄。", + "author": "卡羅爾·伯內特" }, { - "quote": "What matters most is how well you walk through the fire.", - "author": "Charles Bukowski" + "quote": "如果你沒有犯錯誤,那麼你就沒有做決定。", + "author": "凱瑟琳·庫克" }, { - "quote": "It is not the strongest of the species that survive, nor the most intelligent, but the one most responsive to change.", - "author": "Charles Darwin" + "quote": "愛我所愛,至死方休。", + "author": "查爾斯·布考斯基" }, { - "quote": "Life is 10% what happens to you and 90% how you react to it.", - "author": "Charles R. Swindoll" + "quote": "最重要的是你能否赴湯蹈火。", + "author": "查爾斯·布考斯基" }, { - "quote": "You will do foolish things, but do them with enthusiasm.", - "author": "Colette" + "quote": "生存下來的不是最強壯的物種,也不是最聰明的物種,而是最能適應變化的物種。", + "author": "查爾斯·達爾文" }, { - "quote": "It does not matter how slowly you go as long as you do not stop.", - "author": "Confucius" + "quote": "細節不僅是細節,而且決定了設計。", + "author": "查爾斯·伊姆斯" }, { - "quote": "Real knowledge is to know the extent of one's ignorance.", - "author": "Confucius" + "quote": "創造力不僅僅是與衆不同。任何人都可以做到怪誕不經,這很簡單。難的是像巴赫那樣簡單。使簡單的,非常簡單,這就是創造力。", + "author": "查爾斯·明格斯" }, { - "quote": "The past cannot be changed. The future is yet in your power.", - "author": "Confucius" + "quote": "生活的 10% 是發生在你身上的事,90% 是你對它的反應。", + "author": "查爾斯·R·斯溫多爾" }, { - "quote": "Looking at code you wrote more than two weeks ago is like looking at code you are seeing for the first time.", - "author": "Dan Hurvitz" + "quote": "你不免會做傻事,但熱烈地、衷心地投入做吧。", + "author": "科萊特" }, { - "quote": "Someday is not a day of the week.", - "author": "Denise Brennan-Nelson" + "quote": "譬如爲山,未成一簣,止,吾止也。譬如平地,雖覆一簣,進,吾往也。", + "author": "孔子" }, { - "quote": "UNIX is simple. It just takes a genius to understand its simplicity.", - "author": "Dennis Ritchie" + "quote": "知之爲知之,不知爲不知,是知也。", + "author": "孔子" }, { - "quote": "Computers are good at following instructions, but not at reading your mind.", - "author": "Donald Knuth" + "quote": "往昔不可諫,來者猶可追。", + "author": "孔子" }, { - "quote": "A good programmer is someone who always looks both ways before crossing a one-way street.", - "author": "Doug Linder" + "quote": "看着自己兩個多星期前編寫的代碼就像第一次看到這代碼一樣。", + "author": "丹·赫維茨" }, { - "quote": "Tough times never last, but tough people do.", - "author": "Dr. Robert Schuller" + "quote": "“總有一天”不是一週中的一天。", + "author": "丹尼斯·布倫南-納爾遜" }, { - "quote": "If things start happening, don't worry, don't stew, just go right along and you'll start happening too.", - "author": "Dr. Seuss" + "quote": "UNIX很簡單。不過只有天才才能理解它的簡單性。", + "author": "丹尼斯·裏奇" }, { - "quote": "Do not go gentle into that good night. Rage, rage against the dying of the light.", - "author": "Dylan Thomas" + "quote": "在我看來,要想見彩虹,就得忍受風雨!", + "author": "多莉·帕頓" }, { - "quote": "The question of whether computers can think is like the question of whether submarines can swim.", - "author": "E.W. Dijkstra" + "quote": "計算機善於遵循指令,但不善於理解你的思維。", + "author": "唐納德·克努特" }, { - "quote": "Any code of your own that you haven't looked at for six or more months might as well have been written by someone else.", - "author": "Eagleson's Law" + "quote": "優秀的程序員總是在過單行道之前兩邊都看一下。", + "author": "道格·林德" }, { - "quote": "Do one thing every day that scares you.", - "author": "Eleanor Roosevelt" + "quote": "創造力是狂野的頭腦和訓練有素的眼睛。", + "author": "多蘿西·帕克" }, { - "quote": "With the new day comes new strength and new thoughts.", - "author": "Eleanor Roosevelt" + "quote": "艱苦的時光終將過去,堅強的人們必將苦盡甘來。", + "author": "羅伯特·舒勒博士" }, { - "quote": "You must do the things you think you cannot do.", - "author": "Eleanor Roosevelt" + "quote": "如果事情開始發生,不要發愁,不要擔憂,只要一直走下去,你也會開始發生的。", + "author": "蘇斯博士" }, { - "quote": "Light tomorrow with today.", - "author": "Elizabeth Barrett Browning" + "quote": "不要溫和地走進那良夜。怒斥,怒斥光明的消逝。", + "author": "狄蘭·托馬斯" }, { - "quote": "Forever is composed of nows.", - "author": "Emily Dickinson" + "quote": "計算機能否思考的問題就像潛艇能否游泳的問題一樣。", + "author": "E·W·迪科斯徹" }, { - "quote": "Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter.", - "author": "Eric Raymond" + "quote": "自己寫的代碼,只要有六個月沒有看過,就像是別人寫的一樣。", + "author": "伊格爾森定律" }, { - "quote": "If you don't risk anything, you risk even more.", - "author": "Erica Jong" + "quote": "每天做一件讓你害怕的事。", + "author": "埃莉諾·羅斯福" }, { - "quote": "The world breaks everyone, and afterward, many are strong at the broken places.", - "author": "Ernest Hemingway" + "quote": "新的一天帶來了新的力量和新的思想。", + "author": "埃莉諾·羅斯福" }, { - "quote": "There is nothing noble in being superior to your fellow man; true nobility is being superior to your former self.", - "author": "Ernest Hemingway" + "quote": "你必須做你自己認爲做不到的事。", + "author": "埃莉諾·羅斯福" }, { - "quote": "Never confuse a single defeat with a final defeat.", - "author": "F. Scott Fitzgerald" + "quote": "用今天照亮明天。", + "author": "伊麗莎白·巴雷特·布朗寧" }, { - "quote": "I attribute my success to this - I never gave or took any excuse.", - "author": "Florence Nightingale" + "quote": "如果你的夢想沒有嚇到你,那是因爲你夢想得還不夠大。", + "author": "愛倫·約翰森·希爾麗夫" }, { - "quote": "The best revenge is massive success.", - "author": "Frank Sinatra" + "quote": "永遠是由現在組成的。", + "author": "艾米莉·狄金森" }, { - "quote": "The only limit to our realization of tomorrow, will be our doubts of today.", - "author": "Franklin D. Roosevelt" + "quote": "計算機科學教育不能使任何人成爲專家程序員,正如學習畫筆和顏料無法讓人成爲繪畫專家一樣。", + "author": "埃裏克·雷蒙德" }, { - "quote": "Right or wrong, it's very pleasant to break something from time to time.", - "author": "Fyodor Dostoevsky" + "quote": "如果你不冒任何風險,你的風險就更大。", + "author": "艾瑞卡·瓊" }, { - "quote": "The harder I work, the luckier I get.", - "author": "Gary Player" + "quote": "生活總是讓我們遍體鱗傷,但到後來,那些受傷的地方會變得更堅強。", + "author": "厄內斯特·海明威" }, { - "quote": "Giving up is the only sure way to fail.", - "author": "Gena Showalter" + "quote": "優於別人,並不高貴,真正的高貴應該是優於過去的自己。", + "author": "厄內斯特·海明威" }, { - "quote": "The only truly secure system is one that is powered off, cast in a block of concrete and sealed in a lead-lined room with armed guards.", - "author": "Gene Spafford" + "quote": "永遠不要將一次失敗與最終失敗混淆。", + "author": "F. 斯科特·菲茨傑拉德" }, { - "quote": "A life spent making mistakes is not only more honorable, but more useful than a life spent doing nothing.", - "author": "George Bernard Shaw" + "quote": "我將我的成功歸功於此——我從不找,也不接受任何藉口。", + "author": "弗洛倫斯·南丁格爾" }, { - "quote": "First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack.", - "author": "George Carrette" + "quote": "最好的報復是巨大的成功。", + "author": "弗蘭克·西納特拉" }, { - "quote": "Discovering the unexpected is more important than confirming the known.", - "author": "George Box" + "quote": "我們實現明天的唯一限制是我們對今天的懷疑。", + "author": "富蘭克林·羅斯福" }, { - "quote": "We only see what we know.", - "author": "Goethe" + "quote": "不管是對是錯,時不時弄壞點東西是一件非常愉快的事情。", + "author": "陀思妥耶夫斯基" }, { - "quote": "Without hard work, nothing grows but weeds.", - "author": "Gordon B. Hinckley" + "quote": "我越努力,就越幸運。", + "author": "蓋瑞·普萊爾" }, { - "quote": "The function of good software is to make the complex appear to be simple.", - "author": "Grady Booch" + "quote": "放棄是失敗的唯一可靠途徑。", + "author": "吉娜·肖沃爾特" }, { - "quote": "When you know that you're capable of dealing with whatever comes, you have the only security the world has to offer.", - "author": "Harry Browne" + "quote": "唯一真正安全的系統是斷了電、澆鑄在混凝土塊中、並密封在有武裝警衛的鉛襯房間內的系統。", + "author": "金·斯帕福德" }, { - "quote": "Pain is inevitable. Suffering is optional.", - "author": "Haruki Murakami" + "quote": "一生犯錯誤不僅比一生無所事事更光榮,而且更有用。", + "author": "蕭伯納" }, { - "quote": "Optimism is the faith that leads to achievement. Nothing can be done without hope and confidence.", - "author": "Helen Keller" + "quote": "首先學會計算機科學和所有的理論。 然後發展出一個編程風格。之後便要忘掉所有這些,自由地編碼。", + "author": "喬治·卡雷特" }, { - "quote": "The price of anything is the amount of life you exchange for it.", - "author": "Henry David Thoreau" + "quote": "發現意想不到的比確認已知的更重要。", + "author": "喬治·博克斯" }, { - "quote": "Whether you think you can or think you can't, you're right.", - "author": "Henry Ford" + "quote": "我們只能看到自己所知的。", + "author": "歌德" }, { - "quote": "The most exciting phrase to hear in science, the one that heralds discoveries, is not 'Eureka!' but 'Now that's funny…'", - "author": "Isaac Asimov" + "quote": "不努力耕耘,只會長出雜草。", + "author": "戈登·B·欣克利" }, { - "quote": "We are all failures. At least the best of us are.", - "author": "J.M. Barrie" + "quote": "好的軟件的功能就是化繁爲簡。", + "author": "格雷迪·布奇" }, { - "quote": "You can't wait for inspiration. You have to go after it with a club.", - "author": "Jack London" + "quote": "當你知道自己有能力應對任何事情時,你就擁有了世界所能提供的唯一安全感。", + "author": "哈利·布朗" }, { - "quote": "Don't wish it were easier, wish you were better.", - "author": "Jim Rohn" + "quote": "痛苦不可避免,但可以選擇是否受苦。", + "author": "村上春樹" }, { - "quote": "By seeking and blundering we learn.", - "author": "Johann Wolfgang von Goethe" + "quote": "樂觀是導致成就的信念。沒有希望和信心,就什麼都做不了。", + "author": "海倫·凱勒" }, { - "quote": "Knowing is not enough; we must apply. Wishing is not enough; we must do.", - "author": "Johann Wolfgang von Goethe" + "quote": "任何東西的價格都等於你用多少生命去換取它。", + "author": "亨利·大衛·梭羅" }, { - "quote": "We first make our habits, then our habits make us.", - "author": "John Dryden" + "quote": "不管你認爲你能還是不能,你都是對的。", + "author": "亨利·福特" }, { - "quote": "The power of imagination makes us infinite.", - "author": "John Muir" + "quote": "在科學中聽到的最令人興奮的短語,即預示着發現的短語,不是“找到了!” 而是“這很有趣……”", + "author": "艾薩克·阿西莫夫" }, { - "quote": "May you live every day of your life.", - "author": "Jonathan Swift" + "quote": "你所做的會有影響。你必須決定你想要做出什麼樣的改變。", + "author": "簡·古道爾" }, { - "quote": "Perseverance is failing 19 times and succeeding the 20th.", - "author": "Julie Andrews" + "quote": "我們都是失敗者。至少我們中最好的人是。", + "author": "J.M.巴里" }, { - "quote": "The work of today is the history of tomorrow, and we are its makers.", - "author": "Juliette Gordon Low" + "quote": "你不能等待靈感。你必須提着木棒去追求它。", + "author": "傑克·倫敦" }, { - "quote": "If you reveal your secrets to the wind, you should not blame the wind for revealing them to the trees.", - "author": "Kahlil Gibran" + "quote": "不要希望事情更容易,希望你更有能力。", + "author": "吉姆·羅恩" }, { - "quote": "Optimism is an occupational hazard of programming; feedback is the treatment.", - "author": "Kent Beck" + "quote": "我們通過尋找和犯錯誤來學習。", + "author": "約翰·沃爾夫岡·馮·歌德" }, { - "quote": "Opportunity does not knock, it presents itself when you beat down the door.", - "author": "Kyle Chandler" + "quote": "知道是不夠的;我們必須應用。希望是不夠的;我們必須行動。", + "author": "約翰·沃爾夫岡·馮·歌德" }, { - "quote": "To iterate is human, to recurse divine.", - "author": "Peter Deutsch" + "quote": "我們先養成習慣,然後習慣造就我們。", + "author": "約翰·德萊登" }, { - "quote": "A good traveler has no fixed plans and is not intent on arriving.", - "author": "Lao Tzu" + "quote": "想象力使我們無限。", + "author": "約翰·繆爾" }, { - "quote": "An ant on the move does more than a dozing ox.", - "author": "Lao Tzu" + "quote": "願你過好每一天。", + "author": "喬納森·斯威夫特" }, { - "quote": "Do the difficult things while they are easy and do the great things while they are small. A journey of a thousand miles must begin with a single step.", - "author": "Lao Tzu" + "quote": "堅持就是前 19 次失敗,第 20 次成功。", + "author": "朱莉·安德魯斯" }, { - "quote": "That's the thing about people who think they hate computers. What they really hate is lousy programmers.", - "author": "Larry Niven" + "quote": "今天的工作就是明天的歷史,我們是它的創造者。", + "author": "朱麗葉·戈登·洛" }, { - "quote": "It had long since come to my attention that people of accomplishment rarely sat back and let things happen to them. They went out and happened to things.", - "author": "Leonardo da Vinci" + "quote": "如果你向風泄露了你的祕密,你不應該責怪風將它們泄露給樹木。", + "author": "紀伯倫" }, { - "quote": "If you're any good at all, you know you can be better.", - "author": "Lindsay Buckingham" + "quote": "樂觀是編程的職業病;反饋就是治療。", + "author": "肯特·貝克" }, { - "quote": "If people never did silly things, nothing intelligent would ever get done.", - "author": "Ludwig Wittgenstein" + "quote": "機會不會敲門,它會在你敲門的時候出現。", + "author": "凱爾·錢德勒" }, { - "quote": "You only live once, but if you do it right, once is enough.", - "author": "Mae West" + "quote": "迭代的是人,遞歸的是神。", + "author": "彼得·多伊奇" }, { - "quote": "Live as if you were to die tomorrow. Learn as if you were to live forever.", - "author": "Mahatma Gandhi" + "quote": "善行無轍跡,善言無瑕謫。", + "author": "老子" }, { - "quote": "Strength does not come from physical capacity. It comes from an indomitable will.", - "author": "Mahatma Gandhi" + "quote": "合抱之木,生於毫末;九層之臺,起於累土;千里之行,始於足下。", + "author": "老子" }, { - "quote": "One person's 'paranoia' is another person's 'engineering redundancy'.", - "author": "Marcus J. Ranum" + "quote": "那些認爲自己討厭電腦的人就是這樣。他們真正討厭的是糟糕的程序員。", + "author": "拉里·尼文" }, { - "quote": "Nothing in life is to be feared, it is only to be understood. Now is the time to understand more, so that we may fear less.", - "author": "Marie Curie" + "quote": "我早就發現,成功的人很少坐以待斃,讓事情發生在他們身上。他們出去主動去做事。", + "author": "達芬奇" }, { - "quote": "If you have everything under control, you're not moving fast enough.", - "author": "Mario Andretti" + "quote": "如果你有一點才能,你就會知道你還可以做得更好。", + "author": "林賽·白金漢" }, { - "quote": "Education: the path from cocky ignorance to miserable uncertainty.", - "author": "Mark Twain" + "quote": "如果人們從不做傻事,就什麼都不會做得聰明。", + "author": "路德維希·維特根斯坦" }, { - "quote": "It ain't what you don't know that gets you into trouble. It's what you know for sure that just ain't so.", - "author": "Mark Twain" + "quote": "人只活一次,但若活得其所一次已足夠。", + "author": "梅·韋斯特" }, { - "quote": "The secret of getting ahead is getting started.", - "author": "Mark Twain" + "quote": "像明天就要死一樣生活,像永遠活着一樣學習。", + "author": "聖雄甘地" }, { - "quote": "The two most important days in your life are the day you are born and the day you find out why.", - "author": "Mark Twain" + "quote": "力量不是來自身體能力。它來自不屈不撓的意志。", + "author": "聖雄甘地" }, { - "quote": "Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails.", - "author": "Mark Twain" + "quote": "一個人的“偏執狂”是另一個人的“工程冗餘”。", + "author": "馬庫斯·拉納姆" }, { - "quote": "Any fool can write code that a computer can understand. Good programmers write code that humans can understand.", - "author": "Martin Fowler" + "quote": "生活中沒有什麼可怕的,只有需要理解的。現在是時候多去理解,這樣我們就會少一些恐懼。", + "author": "瑪麗·居里" }, { - "quote": "I know, somehow, that only when it is dark enough can you see the stars.", - "author": "Martin Luther King Jr." + "quote": "如果一切都在你的掌控之中,那麼你的行動還不夠快。", + "author": "馬里奧·安德雷蒂" }, { - "quote": "It is never too late to be what you might have been.", - "author": "Mary Anne Evans" + "quote": "教育:從自大的無知到悲慘的不確定性的道路。", + "author": "馬克·吐溫" }, { - "quote": "Nothing will work unless you do.", - "author": "Maya Angelou" + "quote": "讓你陷入麻煩的不是你不知道的東西,而是你確信的、其實並不是真的東西。", + "author": "馬克·吐溫" }, { - "quote": "We delight in the beauty of the butterfly, but rarely admit the changes it has gone through to achieve that beauty.", - "author": "Maya Angelou" + "quote": "取得成功的祕訣就是開始。", + "author": "馬克·吐溫" }, { - "quote": "We may encounter many defeats, but we must not be defeated.", - "author": "Maya Angelou" + "quote": "你生命中最重要的兩天是你出生的那一天和你找到意義的那一天。", + "author": "馬克·吐溫" }, { - "quote": "Everybody has talent, but ability takes hard work.", - "author": "Michael Jordan" + "quote": "二十年後,你會因自己沒做的事情而更加失望,而不是做過的事情。所以,請解開繩索,駛離安全的港灣,揚帆起航吧。", + "author": "馬克·吐溫" }, { - "quote": "I've missed more than 9,000 shots during my career. I've lost almost 300 games. 26 times, I've been trusted to take the game winning shot and missed. I've failed over and over and over again in my life. And that is why I succeed.", - "author": "Michael Jordan" + "quote": "任何傻瓜都可以編寫計算機可以理解的代碼。優秀的程序員編寫人類可以理解的代碼。", + "author": "馬丁·福勒" }, { - "quote": "Impossible is just a big word thrown around by small men who find it easier to live in the world they've been given than to explore the power they have to change it. Impossible is not a fact. It's an opinion. Impossible is not a declaration. It's a dare. Impossible is potential. Impossible is temporary. Impossible is nothing.", - "author": "Muhammad Ali" + "quote": "我知道,不知何故,只有當天足夠黑時,你才能看到星星。", + "author": "馬丁·路德·金" }, { - "quote": "A winner is a dreamer who never gives up.", - "author": "Nelson Mandela" + "quote": "永遠不會太晚去成爲你可能成爲的人。", + "author": "瑪麗·安妮·埃文斯" }, { - "quote": "It always seems impossible until it's done.", - "author": "Nelson Mandela" + "quote": "除非你行動起來,否則什麼都不會改變。", + "author": "瑪雅·安傑洛" }, { - "quote": "Failure will never overtake me if my determination to succeed is strong enough.", - "author": "Og Mandino" + "quote": "你無法用盡創造力。使用得越多,就會有越多。", + "author": "瑪雅·安傑洛" }, { - "quote": "I am not young enough to know everything.", - "author": "Oscar Wilde" + "quote": "我們喜歡蝴蝶的美麗,但很少承認它爲實現這種美麗所經歷的變化。", + "author": "瑪雅·安傑洛" }, { - "quote": "There is only one thing that makes a dream impossible to achieve: the fear of failure.", - "author": "Paulo Coelho" + "quote": "我們可能會遇到很多失敗,但我們絕不能被擊敗。", + "author": "瑪雅·安傑洛" }, { - "quote": "Never go to bed mad. Stay up and fight.", - "author": "Phyllis Diller" + "quote": "每個人都有天賦,但能力需要努力。", + "author": "邁克爾·喬丹" }, { - "quote": "You can't cross the sea merely by standing and staring at the water.", - "author": "Rabindranath Tagore" + "quote": "在我的職業生涯中,我錯過了 9000 多次投籃。我輸掉了近 300 場比賽。26 次,我被信任去投決勝一投,但都沒有命中。我一次又一次地失敗。但正因如此,我才獲得了成功。", + "author": "邁克爾·喬丹" }, { - "quote": "The only person you are destined to become is the person you decide to be.", - "author": "Ralph Waldo Emerson" + "quote": "“不可能”只是小人物們輕易拋出的大詞,他們寧願留在自己被賦予的世界裏,也不願探索自己改變它的力量。“不可能”不是事實,而是意見。“不可能”不是宣言,而是挑戰。“不可能”是潛力。“不可能”是暫時的。“不可能”什麼也不是。", + "author": "穆罕默德·阿里" }, { - "quote": "What you do speaks so loudly that I cannot hear what you say.", - "author": "Ralph Waldo Emerson" + "quote": "勝利者是永不放棄的夢想家。", + "author": "納爾遜·曼德拉" }, { - "quote": "People who are crazy enough to think they can change the world, are the ones who do.", - "author": "Rob Siltanen" + "quote": "看起來總是不可能,直到它被做到。", + "author": "納爾遜·曼德拉" }, { - "quote": "The best way out is always through.", - "author": "Robert Frost" + "quote": "如果我成功的決心足夠堅定,失敗永遠不會壓倒我。", + "author": "奧格·曼狄諾" }, { - "quote": "Today's accomplishments were yesterday's impossibilities.", - "author": "Robert H. Schuller" + "quote": "我還不夠年輕,不可能瞭解所有的事情。", + "author": "奧斯卡·王爾德" }, { - "quote": "Don't be satisfied with stories, how things have gone with others. Unfold your own myth.", - "author": "Rumi" + "quote": "只有一件事使夢想無法實現:對失敗的恐懼。", + "author": "保羅·柯艾略" }, { - "quote": "Forget safety. Live where you fear to live. Destroy your reputation. Be notorious.", - "author": "Rumi" + "quote": "光是站着看水是無法渡海的。", + "author": "羅賓德拉納特·泰戈爾" }, { - "quote": "Sell your cleverness and buy bewilderment.", - "author": "Rumi" + "quote": "你註定要成爲的唯一的人,就是你決定成爲的人。", + "author": "拉爾夫·沃爾多·愛默生" }, { - "quote": "The cure for pain is in the pain.", - "author": "Rumi" + "quote": "你的所作所爲聲音很大,我聽不見你在說什麼。", + "author": "拉爾夫·沃爾多·愛默生" }, { - "quote": "Have no fear of perfection - you'll never reach it.", - "author": "Salvador Dalí" + "quote": "那些足夠瘋狂以爲自己可以改變世界的人,纔是真正改變世界的人。", + "author": "羅伯·西塔寧" }, { - "quote": "Don't watch the clock. Do what it does. Keep going.", - "author": "Sam Levenson" + "quote": "最好的出路是有始有終。", + "author": "羅伯特·弗羅斯特" }, { - "quote": "Ever Tried. Ever failed. No matter. Try again. Fail again. Fail better.", - "author": "Samuel Beckett" + "quote": "今天的成就是昨天的不可能。", + "author": "羅伯特·舒樂" }, { - "quote": "The more you know, the more you realize you know nothing.", - "author": "Socrates" + "quote": "不要滿足於故事,不要滿足於別人的經歷。揭開你自己的神話。", + "author": "魯米" }, { - "quote": "The greatest enemy of knowledge is not ignorance, it is the illusion of knowledge.", - "author": "Stephen Hawking" + "quote": "忘掉安全感,到你所害怕的地方去生活。摧毀你的名聲,做一個聲名狼藉的人。", + "author": "魯米" }, { - "quote": "The universe doesn't allow perfection.", - "author": "Stephen Hawking" + "quote": "賣掉你的聰明,買下困惑。", + "author": "魯米" }, { - "quote": "Whether you want to uncover the secrets of the universe, or you want to pursue a career in the 21st century, basic computer programming is an essential skill to learn.", - "author": "Stephen Hawking" + "quote": "治療疼痛的方法是在疼痛中。", + "author": "魯米" }, { - "quote": "The scariest moment is always just before you start.", - "author": "Stephen King" + "quote": "不要害怕完美——你永遠達不到完美。", + "author": "薩爾瓦多·達利" }, { - "quote": "You can, you should, and if you're brave enough to start, you will.", - "author": "Stephen King" + "quote": "不要看時鐘。做它做的事情。繼續前進。", + "author": "山姆·李文生" }, { - "quote": "Arise, Awake and Stop not until the goal is reached.", - "author": "Swami Vivekananda" + "quote": "曾經嘗試過。曾經失敗過。沒關係。再嘗試一次。再失敗一次。做得更好。", + "author": "塞繆爾·貝克特" }, { - "quote": "It is said that your life flashes before your eyes just before you die. That is true, it's called Life.", - "author": "Terry Pratchett" + "quote": "你知道的越多,你就越發現你什麼都不知道。", + "author": "蘇格拉底" }, { - "quote": "Believe you can and you're halfway there.", - "author": "Theodore Roosevelt" + "quote": "知識最大的敵人不是無知,而是知識的幻覺。", + "author": "史蒂芬·霍金" }, { - "quote": "I have not failed. I've just found 10,000 ways that won't work.", - "author": "Thomas A. Edison" + "quote": "宇宙不允許完美。", + "author": "史蒂芬·霍金" }, { - "quote": "Our greatest weakness lies in giving up. The most certain way to succeed is always to try just one more time.", - "author": "Thomas A. Edison" + "quote": "無論你是想揭開宇宙的祕密,還是想在 21 世紀謀求職業,基礎計算機編程是必學的技能。", + "author": "史蒂芬·霍金" }, { - "quote": "The harder the conflict, the more glorious the triumph.", - "author": "Thomas Paine" + "quote": "最可怕的時刻總是在你開始之前。", + "author": "史蒂芬.金" }, { - "quote": "The Web as I envisaged it, we have not seen it yet. The future is still so much bigger than the past.", - "author": "Tim Berners-Lee" + "quote": "你可以,你應該,如果你有足夠的勇氣開始,你會的。", + "author": "史蒂芬.金" }, { - "quote": "Failure is the condiment that gives success its flavor.", - "author": "Truman Capote" + "quote": "起牀,醒來,直到達到目標才停下來。", + "author": "斯瓦米·維韋卡南達" }, { - "quote": "Those who says it cannot be done should not interrupt the person doing it.", - "author": "Unknown" + "quote": "據說,就在你死之前,你的生命在你眼前閃過。沒錯,這就是所謂的生活。", + "author": "泰瑞·普萊契" }, { - "quote": "Even if you fall on your face, you're still moving forward.", - "author": "Victor Kiam" + "quote": "相信你可以,你就成功了一半。", + "author": "西奧多·羅斯福" }, { - "quote": "It's not whether you get knocked down, it's whether you get up.", - "author": "Vince Lombardi" + "quote": "我沒有失敗。我只是找到了一萬種行不通的方法。", + "author": "愛迪生" }, { - "quote": "I dream my painting and I paint my dream.", - "author": "Vincent van Gogh" + "quote": "我們最大的弱點在於放棄。最確定的成功方法永遠是再試一次。", + "author": "愛迪生" }, { - "quote": "Let us cultivate our garden.", - "author": "Voltaire" + "quote": "衝突越激烈,勝利就越光榮。", + "author": "托馬斯·潘恩" }, { - "quote": "Aim for the moon. If you miss, you may hit a star.", - "author": "W. Clement Stone" + "quote": "我所設想的網絡,我們還沒有看到。未來仍然比過去要大得多。", + "author": "蒂姆·伯納斯-李" }, { - "quote": "The way to get started is to quit talking and begin doing.", - "author": "Walt Disney" + "quote": "失敗是給成功增添風味的調味品。", + "author": "杜魯門·卡波特" }, { - "quote": "You miss 100% of the shots you don't take.", - "author": "Wayne Gretzky" + "quote": "那些說這是不可能的人,不應該打斷正在做這件事的人。", + "author": "佚名" }, { - "quote": "Don't let yesterday take up too much of today.", - "author": "Will Rogers" + "quote": "用不同的眼光看待平常的事物。", + "author": "維科·馬吉斯泰蒂" }, { - "quote": "Even if you're on the right track, you'll get run over if you just sit there.", - "author": "Will Rogers" + "quote": "即使你摔倒在地,你仍然在前進。", + "author": "維克托·基亞姆" }, { - "quote": "Do not wait to strike till the iron is hot; but make it hot by striking.", - "author": "William Butler Yeats" + "quote": "重要的不是你是否被擊倒,而是你是否爬起來。", + "author": "文斯·隆巴迪" }, { - "quote": "You cannot swim for new horizons until you have courage to lose sight of the shore.", - "author": "William Faulkner" + "quote": "我夢想我的畫,我畫我的夢。", + "author": "文森特·梵高" }, { - "quote": "Be not afraid of greatness. Some are born great, some achieve greatness, and others have greatness thrust upon them.", - "author": "William Shakespeare" + "quote": "偉大的事情是由一系列小事情匯聚而成的。", + "author": "文森特·梵高" }, { - "quote": "We know what we are, but not what we may be.", - "author": "William Shakespeare" + "quote": "讓我們耕種我們的花園。", + "author": "伏爾泰" }, { - "quote": "In theory there is no difference between theory and practice. In practice there is.", - "author": "Yogi Berra" + "quote": "瞄準月亮。如果你錯失目標,你可能會擊中一顆恆星。", + "author": "克萊門特·斯通" }, { - "quote": "You can see a lot by just looking.", - "author": "Yogi Berra" + "quote": "開始的方法是停止說話,開始行動。", + "author": "沃爾特·迪斯尼" }, { - "quote": "There is no elevator to success, you have to take the stairs.", - "author": "Zig Ziglar" + "quote": "你不嘗試的話,就有 100% 的機會失敗。", + "author": "韋恩·格雷茨基" }, { - "quote": "You don't have to be great to start, but you have to start to be great.", - "author": "Zig Ziglar" + "quote": "不要讓昨天佔據太多的今天。", + "author": "威爾·羅傑斯" + }, + { + "quote": "即使你是在正確的路上,如果你只是坐在那裏,你也會被撞倒。", + "author": "威爾·羅傑斯" + }, + { + "quote": "不要等鐵熱了再打;要用敲打使它變熱。", + "author": "威廉·巴特勒·葉芝" + }, + { + "quote": "除非你有勇氣離開海岸,否則你無法遊向新的地平線。", + "author": "威廉·福克納" + }, + { + "quote": "不要害怕偉大。 有些人天生偉大,有些人成就偉大,而另一些人則被推向偉大。", + "author": "威廉·莎士比亞" + }, + { + "quote": "我們知道我們是什麼,但不知道我們可能成爲什麼。", + "author": "威廉·莎士比亞" + }, + { + "quote": "從理論上講,理論和實踐之間沒有區別。在實踐中是有的。", + "author": "約吉·貝拉" + }, + { + "quote": "通過看,你就可以覺察到很多東西。", + "author": "約吉·貝拉" + }, + { + "quote": "成功沒有電梯,你必須走樓梯。", + "author": "齊格·齊格勒" + }, + { + "quote": "你不一定要很偉大才能開始,但你必須開始才能變得偉大。", + "author": "齊格·齊格勒" } ] } diff --git a/client/i18n/locales/chinese-traditional/translations.json b/client/i18n/locales/chinese-traditional/translations.json index ae3ed605d182b7..ea2808a2c9bbda 100644 --- a/client/i18n/locales/chinese-traditional/translations.json +++ b/client/i18n/locales/chinese-traditional/translations.json @@ -11,11 +11,12 @@ "view": "查看", "view-code": "查看代碼", "view-project": "查看項目", + "view-cert-title": "View {{certTitle}}", "show-cert": "顯示認證", "claim-cert": "申請認證", "save-progress": "保存進度", - "accepted-honesty": "你已接受我們的《學術誠信條例》", - "agree": "同意", + "accepted-honesty": "You have agreed to our Academic Honesty Policy.", + "agree-honesty": "I agree to freeCodeCamp's Academic Honesty Policy.", "save-portfolio": "保存這個作品集項目", "remove-portfolio": "移除這個作品集項目", "add-portfolio": "增加一個新的作品集項目", @@ -52,7 +53,7 @@ "check-code": "檢查您的代碼 (Ctrl + Enter)", "check-code-2": "檢查你的代碼", "reset": "重置", - "reset-code": "重置所有代碼", + "reset-step": "Reset This Step", "help": "幫助", "get-help": "獲得幫助", "watch-video": "觀看視頻", @@ -157,7 +158,8 @@ "honesty": "學術誠信條例", "internet": "你在各平臺的賬號", "portfolio": "作品集設置", - "privacy": "隱私設置" + "privacy": "隱私設置", + "personal-info": "Personal Information" }, "danger": { "heading": "危險區域", @@ -222,16 +224,15 @@ "total-points_plural": "{{count}} 總分", "points": "{{date}} 獲得 {{count}} 分", "points_plural": "{{date}} 獲得 {{count}} 分", - "screen-shot": "{{title}} 截圖", "page-number": "第 {{pageNumber}} 頁,共 {{totalPages}} 頁" }, "footer": { - "tax-exempt-status": "freeCodeCamp 是捐助者支持的 501(c)(3) 條款下具有免稅資格的非營利性組織(稅號:82-0779546)。", + "tax-exempt-status": "freeCodeCamp 是捐助者支持的 501(c)(3) 條款下具有免稅資格的慈善組織(稅號:82-0779546)。", "mission-statement": "我們的使命:幫助人們免費學習編程。我們通過創建成千上萬的視頻、文章和交互式編程課程——所有內容向公衆免費開放——來實現這一目標。學員在世界各地自發成立數千個 freeCodeCamp 學習小組。", "donation-initiatives": "所有給 freeCodeCamp 的捐款都將用於我們的教育項目,購買服務器和其他服務,以及聘用員工。", "donate-text": "你可以<1>在此處進行免稅捐贈。", "trending-guides": "精選文章", - "our-nonprofit": "關於我們", + "our-nonprofit": "我們的慈善組織", "links": { "about": "簡介", "alumni": "校友網絡", @@ -249,6 +250,7 @@ }, "learn": { "heading": "歡迎學習 freeCodeCamp 的課程。", + "skip-to-content": "Skip to content", "welcome-1": "歡迎回來,{{name}}。", "welcome-2": "歡迎來到 freeCodeCamp.org", "start-at-beginning": "如果你剛開始學習編程,我們建議你<0>從頭開始。", @@ -264,7 +266,7 @@ "p8": "這套課程需要你進行數千個小時的編程練習。", "p9": "如果你想學習更多數學和計算機科學理論,<0>freeCodeCamp 的 \n YouTube channel 還有數千個小時的視頻課程。", "p10": "如果你想獲得開發者工作或者成爲自由職業開發者找到客戶,那麼除了編程技能,你還需要搭建自己的社交網絡,打造自己作爲開發者的影響力。", - "p11": "You can do this on LinkedIn and GitHub, and also on <0>the freeCodeCamp forum.", + "p11": "你還可以在 LinkedIn、Twitter、GitHub 和 <0>freeCodeCamp 論壇 上做到這一點。", "p12": "編程愉快!" }, "upcoming-lessons": "即將上線的課程", @@ -272,6 +274,9 @@ "add-subtitles": "幫助我們完善或添加字幕", "wrong-answer": "抱歉,這個答案不正確。再試一次?", "check-answer": "點擊下方按鈕,查看你的答案。", + "assignment-not-complete": "Please finish the assignments", + "assignments": "Assignments", + "question": "Question", "solution-link": "解決方案鏈接", "github-link": "GitHub 鏈接", "submit-and-go": "提交併訪問下一個挑戰", @@ -284,7 +289,7 @@ "sign-in-save": "登錄以保存你的學習進度", "download-solution": "下載我的解決方案", "percent-complete": "完成 {{percent}}%", - "project-complete": "Completed {{completedChallengesInBlock}} of {{totalChallengesInBlock}} certification projects", + "project-complete": "已完成 {{totalChallengesInBlock}} 認證項目中的 {{completedChallengesInBlock}}", "tried-rsa": "如果你已經嘗試了 <0>Read-Search-Ask(閱讀-搜索-提問)方法,那麼你可以在 freeCodeCamp 論壇請求幫助。", "rsa": "閱讀,搜索,提問", "rsa-forum": "在發佈新帖子之前 ,請確認你的問題是否<0>已經在論壇上被回答過。", @@ -297,7 +302,6 @@ "certs": "{{title}} 認證" }, "editor-tabs": { - "info": "信息", "code": "編程", "tests": "測試", "restart": "重啓", @@ -307,6 +311,10 @@ "notes": "注意", "preview": "預覽" }, + "editor-alerts": { + "tab-trapped": "按下選項卡將插入選項卡字符", + "tab-free": "按下選項卡將焦點移動到下一個焦點元素" + }, "help-translate": "我們仍然在翻譯以下證書。", "help-translate-link": "幫助我們翻譯。", "project-preview-title": "下面是你將構建的項目的預覽", @@ -326,16 +334,16 @@ "sorry-hang-in-there": "抱歉,你的代碼未通過,堅持一下。", "sorry-dont-giveup": "抱歉,你的代碼未通過,不要放棄。", "challenges-completed": "已完成 {{completedCount}}/{{totalChallenges}}", - "season-greetings-fcc": "Season's Greetings from the freeCodeCamp community 🎉", - "if-getting-value": "If you're getting a lot out of freeCodeCamp, now is a great time to donate to support our nonprofit's mission.", - "building-a-university": "We're Building a Free Computer Science University Degree Program", - "if-help-university": "We've already made a ton of progress. Support our charity with the long road ahead." + "season-greetings-fcc": "來自 freeCodeCamp 社區的季節問候 🎉", + "if-getting-value": "如果你從 freeCodeCamp 中獲益良多,可以捐款支持我們的慈善組織的使命。", + "building-a-university": "我們正在創建一個免費計算機科學大學學位課程", + "if-help-university": "我們已取得了重大進展。請支持我們的慈善組織完成這項長期事業。" }, "donate": { - "title": "支持我們的非營利組織", + "title": "支持我們的慈善組織", "processing": "我們正在處理你的捐款。", "redirecting": "重新引導中...", - "thanks": "謝謝捐款", + "thanks": "Thanks for donating", "thank-you": "謝謝你成爲我們的支持者。", "additional": "你可以使用這個鏈接 <0>{{url}} 額外進行一次性捐款:", "help-more": "幫助我們做更多", @@ -354,11 +362,10 @@ "your-donation": "你的 ${{usd}} 捐款將幫助世界各地的人們學習 {{hours}} 小時。", "your-donation-2": "你的 ${{usd}} 捐款每月將幫助世界各地的人們學習 {{hours}} 小時。", "your-donation-3": "你的 ${{usd}} 捐款每年將幫助世界各地的人們學習 {{hours}} 小時。", - "become-supporter": "Become a Supporter", - "duration": "成爲我們非營利組織的一次性支持者", - "duration-2": "成爲我們非營利組織的每月定期支持者", - "duration-3": "成爲我們非營利組織的每年定期支持者", - "duration-4": "成爲我們非營利組織的支持者", + "become-supporter": "成爲支持者", + "duration": "成爲我們的慈善組織的一次性支持者", + "duration-2": "成爲我們的慈善組織的每月定期支持者", + "duration-4": "成爲我們的慈善組織的支持者", "nicely-done": "很棒,你已完成 {{block}}。", "credit-card": "信用卡", "credit-card-2": "或者使用信用卡捐款:", @@ -372,25 +379,25 @@ "email-receipt": "郵箱(我們將把捐款稅務收據發送給你):", "need-help": "需要我們幫助處理你的當前或之前的捐款?", "forward-receipt": "將你的捐款收據副本發送至 donors@freecodecamp.org,告訴我們你需要什麼幫助。", - "efficiency": "freeCodeCamp 是一個高效率的專注教育的非營利組織。", + "efficiency": "freeCodeCamp 是一個高效率的教育慈善組織。", "why-donate-1": "通過給 freeCodeCamp 捐款,你幫助人們學習新技能以供養家庭。", "why-donate-2": "你也幫助我們創建新的學習資源,你可以利用這些資源拓展自己的技術能力。", "bigger-donation": "給我們額度更大的一次性捐款,或寄一張支票,或通過其他方式給我們捐款?", - "other-ways": "有許多<0>其他方式可以支持我們的非營利組織踐行使命.", + "other-ways": "有許多<0>其他方式可以支持我們的慈善組織踐行使命.", "failed-pay": "呃,你的轉賬似乎沒有成功,再試一次好嗎?", "try-again": "請重試。", "card-number": "你的卡號:", "expiration": "到期日:", "secure-donation": "安全捐款", "faq": "常見問題", - "only-you": "只有你可以看到此消息。祝賀你獲得這項認證。獲得認證不是一件容易的事情,運營 freeCodeCamp 也不容易,而且需要花費很多。請幫助我們更好地幫助你和世界各地的許多其他人。今天就爲我們的非營利組織提供免稅捐款,支持我們。", + "only-you": "只有你可以看到此消息。祝賀你獲得這項認證。獲得認證不是一件容易的事情,運營 freeCodeCamp 也不容易,而且需要花費很多。請幫助我們更好地幫助你和世界各地的許多其他人。今天就爲我們的慈善組織提供免稅捐款,支持我們。", "get-help": "我如何利用我的捐款得到幫助?", "how-transparent": "freeCodeCamp.org 的透明度如何?", "very-transparent": "我們甚至有一個來自 GuideStar.org 的白金透明度評級。", "download-irs": "你可以<0>在此處下載我們的國稅局認定函。", "download-990": "你可以<0>在此處下載我們最新的 990 (年度稅務報告)。", "how-efficient": "freeCodeCamp 的效率如何?", - "fcc-budget": "freeCodeCamp 的預算比大多數非營利組織少得多。我們還沒有引入專業募捐者,而是 Quincy 自己處理一切相關事務。", + "fcc-budget": "freeCodeCamp 的預算比大多數慈善組織少得多。我們還沒有引入專業募捐者,而是 Quincy 自己處理一切相關事務。", "help-millions": "然而,在每年僅有 10 萬美元的預算中,我們能夠幫助數百萬人。", "how-one-time": "我如何進行一次性捐款?", "one-time": "如果你喜歡一次性捐款,你可以在有閒錢時支持 freeCodeCamp 的事業。你可以使用<0>此鏈接,通過 PayPal 捐你認爲合適的金額。", @@ -400,7 +407,7 @@ "can-check": "我可以郵寄實物支票嗎?", "yes-check": "是的,我們歡迎支票。你可以將其郵寄給我們:", "how-matching-gift": "我如何從我的僱主那裏設置匹配的禮物,或者工資扣除?", - "employers-vary": "這因僱主而異,而我們的非營利組織已經被列入許多大型捐贈匹配數據庫。", + "employers-vary": "這因僱主而異,而我們的慈善組織已經被列入許多大型捐贈匹配數據庫。", "some-volunteer": "有些人能夠爲 freeCodeCamp 提供志願服務,他們的僱主通過每小時志願服務捐贈一個固定的金額進行匹配。其他僱主會對捐贈者的任何捐贈進行匹配,最高可達某一數額。", "help-matching-gift": "如你需要幫助,請直接給 Quincy 發送電子郵件:quincy@freecodecamp.org", "how-endowment": "如何爲 freeCodeCamp.org 設置捐贈禮物?", @@ -411,13 +418,13 @@ "thank-wikimedia": "我們要感謝維基百科基金會爲我們提供這種正式文書。", "legacy-gift-questions": "如果你對此過程有任何疑問,請給 Quincy 發送電子郵件到 Quincy@freecodecamp.org。", "how-stock": "如何將股票捐贈給 freeCodeCamp.org?", - "welcome-stock": "我們歡迎你的股票捐贈。請直接爲 Quincy 發送電子郵件到 quincy@freecodecamp.org,他可以幫助你做到這一點,並分享我們的非營利經紀業務賬戶的詳細信息。", + "welcome-stock": "我們歡迎你的股票捐贈。請直接給 Quincy 發送電子郵件到 quincy@freecodecamp.org,他可以幫助你,並分享我們的慈善組織的經紀賬戶的詳細信息。", "how-receipt": "我能夠收到捐贈收據以從我的稅款中扣除我的捐贈嗎?", "just-forward": "可以,只需將你交易的收據轉發到 donors@freecodecamp.org,告訴我們你想要一個收據以及你的使用場景,我們將發給你一個收據。", "how-update": "我設置了每月捐款,但我需要更新或暫停每月的重複。我如何做?", "take-care-of-this": "只需轉發你的每月捐款記錄中的一個記錄給 donors@freecodecamp.org, 並告訴我們你要做什麼。我們會爲你處理這個問題,並向你發送確認。", "anything-else": "還有什麼關於爲 freeCodeCamp.org 捐贈可以瞭解的嗎?", - "other-support": "如果你想要以其他方式支持我們的非營利工作並且它的渠道沒有在此列出, 或者如果你有任何問題,請給 Quincy 發送電子郵件到 quincy@freecodecamp.org。" + "other-support": "如果你想要通過此處未列出的其他方式支持我們的慈善組織和它的使命,或者如果你有任何問題,請給 Quincy 發送電子郵件到 quincy@freecodecamp.org。" }, "report": { "sign-in": "你需要先登錄才能舉報用戶", @@ -460,7 +467,8 @@ "iframe-preview": "{{title}} 預覽", "iframe-alert": "通常,此鏈接會將你帶到另一個網站!一切正常,這個鏈接指向:{{externalLink}}。", "iframe-form-submit-alert": "通常這個表單將被提交!工作正常,這將被提交到:{{externalLink}}", - "document-notfound": "找不到文件" + "document-notfound": "找不到文件", + "slow-load-msg": "Looks like this is taking longer than usual, please try refreshing the page." }, "icons": { "gold-cup": "金獎盃", @@ -475,10 +483,11 @@ "hint": "提示", "heart": "愛心", "initial": "初始", + "input-reset": "Clear search terms", "info": "介紹信息", "spacer": "間隔", "toggle": "切換選中標記", - "magnifier": "放大鏡" + "magnifier": "Submit search terms" }, "aria": { "fcc-curriculum": "freeCodeCamp 課程", @@ -504,10 +513,11 @@ "step": "步驟", "steps": "步驟", "steps-for": "{{blockTitle}} 的步驟", - "code-example": "{{codeName}} code example" + "code-example": "{{codeName}} 代碼示例", + "opens-new-window": "Opens in new window" }, "flash": { - "honest-first": "申請認證之前,你必須先接受我們的《學術誠信條例》", + "honest-first": "To claim a certification, you must first agree to our academic honesty policy", "really-weird": "出現了一些奇怪的情況。如果再出現這種情況,請考慮在 https://github.com/freeCodeCamp/freeCodeCamp/issues/new 提交 issue。", "not-right": "有些不對勁。已生成報告,通知 freeCodeCamp.org 團隊。", "went-wrong": "出了點問題,請檢查並重試。", @@ -586,7 +596,8 @@ "editor-url": "記得要提交Live App的URL", "http-url": "不能使用不安全的(http)URL。", "own-work-url": "記住要提交你自己的作業", - "publicly-visible-url": "記得要提交一個公開可見的app URL" + "publicly-visible-url": "記得要提交一個公開可見的app URL", + "path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path" }, "certification": { "executive": "執行董事,freeCodeCamp.org", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "貓和狗圖像分類器", "Book Recommendation Engine using KNN": "基於 KNN 的圖書推薦引擎", "Linear Regression Health Costs Calculator": "線性迴歸健康成本計算器", - "Neural Network SMS Text Classifier": "神經網絡短信分類器" + "Neural Network SMS Text Classifier": "神經網絡短信分類器", + "Celestial Bodies Database": "Celestial Bodies Database", + "World Cup Database": "World Cup Database", + "Salon Appointment Scheduler": "Salon Appointment Scheduler", + "Periodic Table Database": "Periodic Table Database", + "Number Guessing Game": "Number Guessing Game", + "Build a freeCodeCamp Forum Homepage": "Build a freeCodeCamp Forum Homepage" } + }, + "title": { + "Responsive Web Design": "Responsive Web Design", + "responsive-web-design": "Responsive Web Design Certification", + "JavaScript Algorithms and Data Structures": "JavaScript Algorithms and Data Structures", + "javascript-algorithms-and-data-structures": "JavaScript Algorithms and Data Structures Certification", + "Front End Development Libraries": "Front End Development Libraries", + "front-end-development-libraries": "Front End Development Libraries Certification", + "Data Visualization": "Data Visualization", + "data-visualization": "Data Visualization Certification", + "Relational Database": "Relational Database", + "relational-database-v8": "Relational Database Certification", + "Back End Development and APIs": "Back End Development and APIs", + "back-end-development-and-apis": "Back End Development and APIs Certification", + "Quality Assurance": "Quality Assurance", + "quality-assurance-v7": "Quality Assurance Certification", + "Scientific Computing with Python": "Scientific Computing with Python", + "scientific-computing-with-python-v7": "Scientific Computing with Python Certification", + "Data Analysis with Python": "Data Analysis with Python", + "data-analysis-with-python-v7": "Data Analysis with Python Certification", + "Information Security": "Information Security", + "information-security-v7": "Information Security Certification", + "Machine Learning with Python": "Machine Learning with Python", + "machine-learning-with-python-v7": "Machine Learning with Python Certification", + "Legacy Front End": "Legacy Front End", + "legacy-front-end": "Front End Certification", + "Legacy Back End": "Legacy Back End", + "legacy-back-end": "Back End Certification", + "Legacy Data Visualization": "Legacy Data Visualization", + "legacy-data-visualization": "Data Visualization Certification", + "Legacy Information Security and Quality Assurance": "Legacy Information Security and Quality Assurance", + "information-security-and-quality-assurance": "Information Security and Quality Assurance Certification", + "Legacy Full Stack Certification": "Legacy Full Stack Certification", + "Legacy Full Stack": "Legacy Full Stack", + "full-stack": "Full Stack Certification" } }, "certification-card": { @@ -724,10 +776,10 @@ "navigate-next": "跳轉至下一個練習" }, "signout": { - "heading": "Sign out of your account", - "p1": "Warning: If you continue, your progress will no longer be saved.", - "p2": "This action will sign you out of your account on this device and browser session only. Please confirm if you would like to proceed.", - "certain": "Yes, sign out of my account", - "nevermind": "Nevermind, I don't want to sign out" + "heading": "註銷你的賬戶", + "p1": "警告:如果你繼續,你的當前進度將不再被保存。", + "p2": "此操作只會將你在此設備和瀏覽器會話上的賬號註銷。請確認你是否要繼續。", + "certain": "是的,請註銷我的賬戶", + "nevermind": "算了,我不想註銷賬戶" } } diff --git a/client/i18n/locales/chinese/intro.json b/client/i18n/locales/chinese/intro.json index bf8b57ea863a39..5d0179ab507947 100644 --- a/client/i18n/locales/chinese/intro.json +++ b/client/i18n/locales/chinese/intro.json @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "通过构建电子表格学习函数式编程", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Learn Advanced Array Methods by Building a Statistics Calculator", + "intro": ["", ""] } } }, @@ -553,7 +557,7 @@ "intro": [ "在这之前,你只是在前端使用 JavaScript 来给页面添加交互、解决算法挑战,或构建一个 SPA(单页应用程序)。但 JavaScript 也可以用于后端或者服务器来构建整个 web 应用程序。", "今天,构建应用软件的广受欢迎的方法之一是微服务,这些微服务是一种小型模块化的应用,能够共同形成一个更大的整体。", - "在后端开发和 APIs 认证中,你将学习如何使用 Node.js 和 npm(Node 包管理工具)来写后端。你还将使用 Express 框架构建 web 应用程序,并使用 MongoDB 和 Mongoose 库构建一个 People Finder 微服务。" + "In the Back End Development and APIs Certification, you'll learn how to write back end apps with Node.js and npm. You'll also build web applications with the Express framework, and build a People Finder microservice with MongoDB and the Mongoose library." ], "note": "", "blocks": { @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "The Odin Project", + "intro": [ + "The Odin Project is one of those \"What I wish I had when I was learning\" resources. ", + "Not everyone has access to a computer science education or the funds to attend an intensive coding school and neither of those is right for everyone anyway.", + "This project is designed to fill in the gap for people who are trying to hack it on their own but still want a high quality education." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Learn HTML Foundations", + "intro": ["A description is to be determined"] + }, + "top-build-a-recipe-project": { + "title": "Learn HTML Foundations by Building a Recipe Page", + "intro": ["A description is to be determined"] + } + } + }, "misc-text": { "certification": "{{cert}} 认证", "browse-other": "浏览我们的其他免费认证\n(我们建议你按顺序学习)", diff --git a/client/i18n/locales/chinese/motivation.json b/client/i18n/locales/chinese/motivation.json index d65a69bb268698..43aba58e9b9d34 100644 --- a/client/i18n/locales/chinese/motivation.json +++ b/client/i18n/locales/chinese/motivation.json @@ -1,819 +1,856 @@ { "compliments": [ - "Over the top!", - "Down the rabbit hole we go!", - "Bring that rain!", - "Target acquired.", - "Feel that need for speed!", - "You've got guts!", - "We have liftoff!", - "To infinity and beyond!", - "Encore!", - "Onward!", - "Challenge destroyed!", - "It's on like Donkey Kong!", - "Power level? It's over 9000!", - "Coding spree!", - "Code long and prosper.", - "The crowd goes wild!", - "One for the Guinness book!", - "Flawless victory!", - "Most efficient!", - "You've got the touch!", - "You're on fire!", - "The town is now red!", - "To the nines!", - "To the Batmobile!", - "Pull out all the stops!", - "You're a wizard, Harry!", - "You're an all-star!", - "Way to go!", - "Outta sight!", - "You're crushing it!", - "What sorcery is this?", - "The world rejoices!", - "That's the way it's done!", - "You rock!", - "Woo-hoo!", - "We knew you could do it!", - "Hyper Combo Finish!", - "Nothing but net!", - "Boom-shakalaka!", - "You're a shooting star!", - "You're unstoppable!", - "Way cool!", - "Walk on that sunshine!", - "Keep on trucking!", - "Off the charts!", - "There is no spoon!", - "Cranked it up to 11!", - "Escape velocity reached!", - "You make this look easy!", - "Passed with flying colors!", - "You've got this!", - "Happy, happy, joy, joy!", - "Tomorrow, the world!", - "Your powers combined!", - "It's alive. It's alive!", - "Sonic Boom!", - "Here's looking at you, Code!", - "Ride like the wind!", - "Legen - wait for it - dary!", - "Ludicrous Speed! Go!", - "Most triumphant!", - "One loop to rule them all!", - "By the power of Grayskull!", - "You did it!", - "Storm that castle!", - "Face-melting guitar solo!", - "Checkmate!", - "Bodacious!", - "Tubular!", - "You're outta sight!", - "Keep calm and code on!", - "Even sad panda smiles!", - "Even grumpy cat approves!", - "Kool Aid Man says oh yeah!", - "Bullseye!", - "Far out!", - "You're heating up!", - "Standing ovation!", - "Nice one!", - "All right!", - "Hasta la vista, challenge!", - "Terminated.", - "Off the hook!", - "Thundercats, Hooo!", - "Shiver me timbers!", - "Raise the roof!", - "Bingo!", - "Even Honey Badger cares!", - "Helm, Warp Nine. Engage!", - "Gotta code 'em all!", - "Spool up the FTL drive!", - "Cool beans!", - "They're in another castle.", - "Power UP!", - "Pikachu chooses you!", - "I gotta have more cowbell.", - "Gotta go fast!", - "Yippee!", - "Cowabunga!", - "Moon Prism Power!", - "Plus Ultra!" + "太棒了!", + "我们跳进兔子洞!", + "雨下吧!", + "获取目标。", + "体验极速快感!", + "你有胆量!", + "我们升空了!", + "飞向无限!", + "再来一次!", + "向前进!", + "挑战被摧毁!", + "重磅如同大金刚!", + "战斗力?超过 9000!", + "编码狂潮!", + "编码不息,繁荣昌盛。", + "人群变得疯狂!", + "一个吉尼斯世界纪录!", + "完胜!", + "最高效率!", + "你有手感了!", + "你正在燃烧!", + "满城春色!", + "完美!", + "上蝙蝠车!", + "全力以赴!", + "你是个巫师,哈利!", + "你是全明星队员!", + "干得好!", + "棒极了!", + "你太出色了!", + "这是什么魔法?", + "世界欢欣鼓舞!", + "难题就是这样搞定的!", + "你真棒!", + "呜呼!", + "我们就知道你能行!", + "超级组合终结!", + "空心球!", + "炸弹-沙卡拉卡!", + "你是一颗流星!", + "你势不可挡!", + "太酷了!", + "走在那阳光下!", + "坚持下去!", + "水平爆表!", + "勺子并不存在!", + "调到最大音量!", + "达到逃逸速度!", + "你让这看起来很简单!", + "以优异的成绩通过!", + "你能行!", + "开心,开心,快乐,快乐!", + "明天,征服世界!", + "你的全部力量!", + "它活了。它活了!", + "索尼克音爆!", + "看着你呢,代码!", + "疾驰如风!", + "传——奇!", + "离谱的速度!出发!", + "高奏凯歌!", + "用一个循环来统治它们!", + "凭借灰壳堡的神力!", + "你做到了!", + "冲进城堡!", + "荡人心魄的吉他独奏!", + "完全击败!", + "大有胆识!", + "厉害!", + "你真强啊!", + "保持冷静,继续编码!", + "即使是悲伤的熊猫也会微笑!", + "即使脾气暴躁的猫也同意!", + "如此感觉无以伦比。", + "正中靶心!", + "前卫!", + "燃烧吧,小宇宙!", + "起立鼓掌!", + "不错!", + "好啊!", + "回见,挑战!", + "终结了。", + "脱身!", + "霹雳猫显神威!", + "让我五体投地!", + "大显身手!", + "答对了!", + "连蜜獾都在乎!", + "掌舵,第九曲速。启动!", + "必须全部编码!", + "发动超光速引擎!", + "酷豆子!", + "她们在另一个城堡里。", + "加电!", + "皮卡丘选择了你!", + "我要再多点牛铃。", + "得快点!", + "了不起!", + "卡瓦邦嘎!", + "月亮棱镜能量!", + "超越极致!", + "米尔豪斯一切都会好起来的!" ], "motivationalQuotes": [ { - "quote": "Whatever you are, be a good one.", - "author": "Abraham Lincoln" + "quote": "不管你是谁,做个好人。", + "author": "亚伯拉罕·林肯" }, { - "quote": "A change in perspective is worth 80 IQ points.", - "author": "Alan Kay" + "quote": "换一个角度看问题值80点智商。", + "author": "艾伦·凯" }, { - "quote": "The best way to predict the future is to invent it.", - "author": "Alan Kay" + "quote": "预测未来的最好方法是创造未来。", + "author": "艾伦·凯" }, { - "quote": "The future is not laid out on a track. It is something that we can decide, and to the extent that we do not violate any known laws of the universe, we can probably make it work the way that we want to.", - "author": "Alan Kay" + "quote": "未来不是在轨道上规划的。这是我们可以决定的事情,只要我们不违反任何已知的宇宙法则,我们就可以让它按我们想要的方式运行。", + "author": "艾伦·凯" }, { - "quote": "We can only see a short distance ahead, but we can see plenty there that needs to be done.", - "author": "Alan Turing" + "quote": "我们只能看到前面很短的距离,但我们可以看到有很多事情需要做。", + "author": "艾伦·图灵" }, { - "quote": "In the depth of winter, I finally learned that within me there lay an invincible summer.", - "author": "Albert Camus" + "quote": "隆冬时节,我终于明白,我的内心深处有一个不可战胜的夏天。", + "author": "阿尔伯特·加缪" }, { - "quote": "A person who never made a mistake never tried anything new.", - "author": "Albert Einstein" + "quote": "从不犯错的人从不尝试新事物。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "Creativity is intelligence having fun.", - "author": "Albert Einstein" + "quote": "创造力是智力的乐趣。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "I have no special talents. I am only passionately curious.", - "author": "Albert Einstein" + "quote": "我没有什么特别的才能。我只是非常好奇。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "Life is like riding a bicycle. To keep your balance, you must keep moving.", - "author": "Albert Einstein" + "quote": "生活就像骑自行车。为了保持平衡,你必须继续前进。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "Make everything as simple as possible, but not simpler.", - "author": "Albert Einstein" + "quote": "事情应该力求简单,但不能过于简单。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "Never memorize something that you can look up.", - "author": "Albert Einstein" + "quote": "绝不要去记那些你能够查得到的东西。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "Once we accept our limits, we go beyond them.", - "author": "Albert Einstein" + "quote": "一旦我们接受了自己的极限,我们就超越了它们。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "Play is the highest form of research.", - "author": "Albert Einstein" + "quote": "玩耍是研究的最高形式。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "We cannot solve our problems with the same thinking we used when we created them.", - "author": "Albert Einstein" + "quote": "我们不能用我们创造问题时的思维来解决问题。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "Wisdom is not a product of schooling but of the lifelong attempt to acquire it.", - "author": "Albert Einstein" + "quote": "智慧不是学校教育的产物,而是终身学习的产物。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "Your imagination is your preview of life's coming attractions.", - "author": "Albert Einstein" + "quote": "你的想像是你人生的预览。", + "author": "阿尔伯特·爱因斯坦" }, { - "quote": "There is only one corner of the universe you can be certain of improving, and that's your own self.", - "author": "Aldous Huxley" + "quote": "宇宙中只有一个角落是你可以切实改进的,那就是你自己。", + "author": "奥尔德斯·赫胥黎" }, { - "quote": "The most common way people give up their power is by thinking they don't have any.", - "author": "Alice Walker" + "quote": "我感谢我的奋斗,因为没有它,我就不会偶然发现自己的力量。", + "author": "亚历克斯·艾尔" }, { - "quote": "Follow your inner moonlight. Don't hide the madness.", - "author": "Allen Ginsberg" + "quote": "人们放弃权力最常见的方式是认为自己没有权力。", + "author": "艾丽丝·沃克" }, { - "quote": "The most difficult thing is the decision to act. The rest is merely tenacity.", - "author": "Amelia Earhart" + "quote": "跟随你内心的月光。别掩饰自己的疯狂。", + "author": "艾伦·金斯伯格" }, { - "quote": "Life shrinks or expands in proportion with one's courage.", - "author": "Anaïs Nin" + "quote": "最困难的是决定采取行动。剩下的只是坚韧。", + "author": "阿梅莉亚·埃尔哈特" }, { - "quote": "Weeks of programming can save you hours of planning.", - "author": "Unknown" + "quote": "生命的缩小或扩大与一个人的勇气成正比。", + "author": "阿奈斯·宁" }, { - "quote": "Quality is not an act, it is a habit.", - "author": "Aristotle" + "quote": "数周的编程可以节省你数小时的计划。", + "author": "佚名" }, { - "quote": "Start where you are. Use what you have. Do what you can.", - "author": "Arthur Ashe" + "quote": "质量不是一种行为,而是一种习惯。", + "author": "亚里士多德" }, { - "quote": "Nothing is impossible, the word itself says \"I'm possible\"!", - "author": "Audrey Hepburn" + "quote": "从现在开始。利用你所拥有的。尽你所能。", + "author": "亚瑟·阿什" }, { - "quote": "Every strike brings me closer to the next home run.", - "author": "Babe Ruth" + "quote": "没有什么是不可能的,连这个词本身都说“不,可能”!", + "author": "奥黛丽·赫本" }, { - "quote": "By failing to prepare, you are preparing to fail.", - "author": "Benjamin Franklin" + "quote": "每一击都让我离下一个本垒打越来越近。", + "author": "贝比·鲁斯" }, { - "quote": "Tell me and I forget. Teach me and I remember. Involve me and I learn.", - "author": "Benjamin Franklin" + "quote": "如果你没有做好准备,你就是在准备失败。", + "author": "本杰明·富兰克林" }, { - "quote": "Well done is better than well said.", - "author": "Benjamin Franklin" + "quote": "告诉我,我会忘记。教我,我会记住。让我参与,我会学习。", + "author": "本杰明·富兰克林" }, { - "quote": "There are no short cuts to any place worth going.", - "author": "Beverly Sills" + "quote": "说得好不如做得好。", + "author": "本杰明·富兰克林" }, { - "quote": "Controlling complexity is the essence of computer programming.", - "author": "Brian Kernighan" + "quote": "任何值得去的地方都没有捷径。", + "author": "贝弗利·希尔斯" }, { - "quote": "I fear not the man who has practiced 10,000 kicks once, but I fear the man who has practiced one kick 10,000 times.", - "author": "Bruce Lee" + "quote": "控制复杂性是计算机编程的本质。", + "author": "布莱恩·科尼汉" }, { - "quote": "There are far, far better things ahead than any we leave behind.", - "author": "C.S. Lewis" + "quote": "我不怕遇到练习过一万种腿法的对手,但害怕遇到只将一种腿法练习一万次的强敌。", + "author": "李小龙" }, { - "quote": "We are what we believe we are.", - "author": "C.S. Lewis" + "quote": "比起遗落在过去的,未来还有更加美好的在等待着我们。", + "author": "C.S. 路易斯" }, { - "quote": "With the possible exception of the equator, everything begins somewhere.", - "author": "C.S. Lewis" + "quote": "我们就是我们所相信的自己。", + "author": "C.S. 路易斯" }, { - "quote": "You are never too old to set another goal, or to dream a new dream.", - "author": "C.S. Lewis" + "quote": "可能除了赤道以外,一切都从某处开始。", + "author": "C.S. 路易斯" }, { - "quote": "Somewhere, something incredible is waiting to be known.", - "author": "Carl Sagan" + "quote": "无论年纪多大,你都可以设立新目标或拥有新梦想。", + "author": "C.S. 路易斯" }, { - "quote": "If you're not making mistakes, then you're not making decisions.", - "author": "Catherine Cook" + "quote": "在某个地方,一些不可思议的事物正在等你去发现。", + "author": "卡尔·萨根" }, { - "quote": "Find what you love and let it kill you.", - "author": "Charles Bukowski" + "quote": "当你有梦想时,你必须抓住它,永不放弃。", + "author": "卡罗尔·伯内特" }, { - "quote": "What matters most is how well you walk through the fire.", - "author": "Charles Bukowski" + "quote": "如果你没有犯错误,那么你就没有做决定。", + "author": "凯瑟琳·库克" }, { - "quote": "It is not the strongest of the species that survive, nor the most intelligent, but the one most responsive to change.", - "author": "Charles Darwin" + "quote": "爱我所爱,至死方休。", + "author": "查尔斯·布考斯基" }, { - "quote": "Life is 10% what happens to you and 90% how you react to it.", - "author": "Charles R. Swindoll" + "quote": "最重要的是你能否赴汤蹈火。", + "author": "查尔斯·布考斯基" }, { - "quote": "You will do foolish things, but do them with enthusiasm.", - "author": "Colette" + "quote": "生存下来的不是最强壮的物种,也不是最聪明的物种,而是最能适应变化的物种。", + "author": "查尔斯·达尔文" }, { - "quote": "It does not matter how slowly you go as long as you do not stop.", - "author": "Confucius" + "quote": "细节不仅是细节,而且决定了设计。", + "author": "查尔斯·伊姆斯" }, { - "quote": "Real knowledge is to know the extent of one's ignorance.", - "author": "Confucius" + "quote": "创造力不仅仅是与众不同。任何人都可以做到怪诞不经,这很简单。难的是像巴赫那样简单。使简单的,非常简单,这就是创造力。", + "author": "查尔斯·明格斯" }, { - "quote": "The past cannot be changed. The future is yet in your power.", - "author": "Confucius" + "quote": "生活的 10% 是发生在你身上的事,90% 是你对它的反应。", + "author": "查尔斯·R·斯温多尔" }, { - "quote": "Looking at code you wrote more than two weeks ago is like looking at code you are seeing for the first time.", - "author": "Dan Hurvitz" + "quote": "你不免会做傻事,但热烈地、衷心地投入做吧。", + "author": "科莱特" }, { - "quote": "Someday is not a day of the week.", - "author": "Denise Brennan-Nelson" + "quote": "譬如为山,未成一篑,止,吾止也。譬如平地,虽覆一篑,进,吾往也。", + "author": "孔子" }, { - "quote": "UNIX is simple. It just takes a genius to understand its simplicity.", - "author": "Dennis Ritchie" + "quote": "知之为知之,不知为不知,是知也。", + "author": "孔子" }, { - "quote": "Computers are good at following instructions, but not at reading your mind.", - "author": "Donald Knuth" + "quote": "往昔不可谏,来者犹可追。", + "author": "孔子" }, { - "quote": "A good programmer is someone who always looks both ways before crossing a one-way street.", - "author": "Doug Linder" + "quote": "看着自己两个多星期前编写的代码就像第一次看到这代码一样。", + "author": "丹·赫维茨" }, { - "quote": "Tough times never last, but tough people do.", - "author": "Dr. Robert Schuller" + "quote": "“总有一天”不是一周中的一天。", + "author": "丹尼斯·布伦南-纳尔逊" }, { - "quote": "If things start happening, don't worry, don't stew, just go right along and you'll start happening too.", - "author": "Dr. Seuss" + "quote": "UNIX很简单。不过只有天才才能理解它的简单性。", + "author": "丹尼斯·里奇" }, { - "quote": "Do not go gentle into that good night. Rage, rage against the dying of the light.", - "author": "Dylan Thomas" + "quote": "在我看来,要想见彩虹,就得忍受风雨!", + "author": "多莉·帕顿" }, { - "quote": "The question of whether computers can think is like the question of whether submarines can swim.", - "author": "E.W. Dijkstra" + "quote": "计算机善于遵循指令,但不善于理解你的思维。", + "author": "唐纳德·克努特" }, { - "quote": "Any code of your own that you haven't looked at for six or more months might as well have been written by someone else.", - "author": "Eagleson's Law" + "quote": "优秀的程序员总是在过单行道之前两边都看一下。", + "author": "道格·林德" }, { - "quote": "Do one thing every day that scares you.", - "author": "Eleanor Roosevelt" + "quote": "创造力是狂野的头脑和训练有素的眼睛。", + "author": "多萝西·帕克" }, { - "quote": "With the new day comes new strength and new thoughts.", - "author": "Eleanor Roosevelt" + "quote": "艰苦的时光终将过去,坚强的人们必将苦尽甘来。", + "author": "罗伯特·舒勒博士" }, { - "quote": "You must do the things you think you cannot do.", - "author": "Eleanor Roosevelt" + "quote": "如果事情开始发生,不要发愁,不要担忧,只要一直走下去,你也会开始发生的。", + "author": "苏斯博士" }, { - "quote": "Light tomorrow with today.", - "author": "Elizabeth Barrett Browning" + "quote": "不要温和地走进那良夜。怒斥,怒斥光明的消逝。", + "author": "狄兰·托马斯" }, { - "quote": "Forever is composed of nows.", - "author": "Emily Dickinson" + "quote": "计算机能否思考的问题就像潜艇能否游泳的问题一样。", + "author": "E·W·迪科斯彻" }, { - "quote": "Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter.", - "author": "Eric Raymond" + "quote": "自己写的代码,只要有六个月没有看过,就像是别人写的一样。", + "author": "伊格尔森定律" }, { - "quote": "If you don't risk anything, you risk even more.", - "author": "Erica Jong" + "quote": "每天做一件让你害怕的事。", + "author": "埃莉诺·罗斯福" }, { - "quote": "The world breaks everyone, and afterward, many are strong at the broken places.", - "author": "Ernest Hemingway" + "quote": "新的一天带来了新的力量和新的思想。", + "author": "埃莉诺·罗斯福" }, { - "quote": "There is nothing noble in being superior to your fellow man; true nobility is being superior to your former self.", - "author": "Ernest Hemingway" + "quote": "你必须做你自己认为做不到的事。", + "author": "埃莉诺·罗斯福" }, { - "quote": "Never confuse a single defeat with a final defeat.", - "author": "F. Scott Fitzgerald" + "quote": "用今天照亮明天。", + "author": "伊丽莎白·巴雷特·布朗宁" }, { - "quote": "I attribute my success to this - I never gave or took any excuse.", - "author": "Florence Nightingale" + "quote": "如果你的梦想没有吓到你,那是因为你梦想得还不够大。", + "author": "爱伦·约翰森·希尔丽夫" }, { - "quote": "The best revenge is massive success.", - "author": "Frank Sinatra" + "quote": "永远是由现在组成的。", + "author": "艾米莉·狄金森" }, { - "quote": "The only limit to our realization of tomorrow, will be our doubts of today.", - "author": "Franklin D. Roosevelt" + "quote": "计算机科学教育不能使任何人成为专家程序员,正如学习画笔和颜料无法让人成为绘画专家一样。", + "author": "埃里克·雷蒙德" }, { - "quote": "Right or wrong, it's very pleasant to break something from time to time.", - "author": "Fyodor Dostoevsky" + "quote": "如果你不冒任何风险,你的风险就更大。", + "author": "艾瑞卡·琼" }, { - "quote": "The harder I work, the luckier I get.", - "author": "Gary Player" + "quote": "生活总是让我们遍体鳞伤,但到后来,那些受伤的地方会变得更坚强。", + "author": "厄内斯特·海明威" }, { - "quote": "Giving up is the only sure way to fail.", - "author": "Gena Showalter" + "quote": "优于别人,并不高贵,真正的高贵应该是优于过去的自己。", + "author": "厄内斯特·海明威" }, { - "quote": "The only truly secure system is one that is powered off, cast in a block of concrete and sealed in a lead-lined room with armed guards.", - "author": "Gene Spafford" + "quote": "永远不要将一次失败与最终失败混淆。", + "author": "F. 斯科特·菲茨杰拉德" }, { - "quote": "A life spent making mistakes is not only more honorable, but more useful than a life spent doing nothing.", - "author": "George Bernard Shaw" + "quote": "我将我的成功归功于此——我从不找,也不接受任何借口。", + "author": "弗洛伦斯·南丁格尔" }, { - "quote": "First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack.", - "author": "George Carrette" + "quote": "最好的报复是巨大的成功。", + "author": "弗兰克·西纳特拉" }, { - "quote": "Discovering the unexpected is more important than confirming the known.", - "author": "George Box" + "quote": "我们实现明天的唯一限制是我们对今天的怀疑。", + "author": "富兰克林·罗斯福" }, { - "quote": "We only see what we know.", - "author": "Goethe" + "quote": "不管是对是错,时不时弄坏点东西是一件非常愉快的事情。", + "author": "陀思妥耶夫斯基" }, { - "quote": "Without hard work, nothing grows but weeds.", - "author": "Gordon B. Hinckley" + "quote": "我越努力,就越幸运。", + "author": "盖瑞·普莱尔" }, { - "quote": "The function of good software is to make the complex appear to be simple.", - "author": "Grady Booch" + "quote": "放弃是失败的唯一可靠途径。", + "author": "吉娜·肖沃尔特" }, { - "quote": "When you know that you're capable of dealing with whatever comes, you have the only security the world has to offer.", - "author": "Harry Browne" + "quote": "唯一真正安全的系统是断了电、浇铸在混凝土块中、并密封在有武装警卫的铅衬房间内的系统。", + "author": "金·斯帕福德" }, { - "quote": "Pain is inevitable. Suffering is optional.", - "author": "Haruki Murakami" + "quote": "一生犯错误不仅比一生无所事事更光荣,而且更有用。", + "author": "萧伯纳" }, { - "quote": "Optimism is the faith that leads to achievement. Nothing can be done without hope and confidence.", - "author": "Helen Keller" + "quote": "首先学会计算机科学和所有的理论。 然后发展出一个编程风格。之后便要忘掉所有这些,自由地编码。", + "author": "乔治·卡雷特" }, { - "quote": "The price of anything is the amount of life you exchange for it.", - "author": "Henry David Thoreau" + "quote": "发现意想不到的比确认已知的更重要。", + "author": "乔治·博克斯" }, { - "quote": "Whether you think you can or think you can't, you're right.", - "author": "Henry Ford" + "quote": "我们只能看到自己所知的。", + "author": "歌德" }, { - "quote": "The most exciting phrase to hear in science, the one that heralds discoveries, is not 'Eureka!' but 'Now that's funny…'", - "author": "Isaac Asimov" + "quote": "不努力耕耘,只会长出杂草。", + "author": "戈登·B·欣克利" }, { - "quote": "We are all failures. At least the best of us are.", - "author": "J.M. Barrie" + "quote": "好的软件的功能就是化繁为简。", + "author": "格雷迪·布奇" }, { - "quote": "You can't wait for inspiration. You have to go after it with a club.", - "author": "Jack London" + "quote": "当你知道自己有能力应对任何事情时,你就拥有了世界所能提供的唯一安全感。", + "author": "哈利·布朗" }, { - "quote": "Don't wish it were easier, wish you were better.", - "author": "Jim Rohn" + "quote": "痛苦不可避免,但可以选择是否受苦。", + "author": "村上春树" }, { - "quote": "By seeking and blundering we learn.", - "author": "Johann Wolfgang von Goethe" + "quote": "乐观是导致成就的信念。没有希望和信心,就什么都做不了。", + "author": "海伦·凯勒" }, { - "quote": "Knowing is not enough; we must apply. Wishing is not enough; we must do.", - "author": "Johann Wolfgang von Goethe" + "quote": "任何东西的价格都等于你用多少生命去换取它。", + "author": "亨利·大卫·梭罗" }, { - "quote": "We first make our habits, then our habits make us.", - "author": "John Dryden" + "quote": "不管你认为你能还是不能,你都是对的。", + "author": "亨利·福特" }, { - "quote": "The power of imagination makes us infinite.", - "author": "John Muir" + "quote": "在科学中听到的最令人兴奋的短语,即预示着发现的短语,不是“找到了!” 而是“这很有趣……”", + "author": "艾萨克·阿西莫夫" }, { - "quote": "May you live every day of your life.", - "author": "Jonathan Swift" + "quote": "你所做的会有影响。你必须决定你想要做出什么样的改变。", + "author": "简·古道尔" }, { - "quote": "Perseverance is failing 19 times and succeeding the 20th.", - "author": "Julie Andrews" + "quote": "我们都是失败者。至少我们中最好的人是。", + "author": "J.M.巴里" }, { - "quote": "The work of today is the history of tomorrow, and we are its makers.", - "author": "Juliette Gordon Low" + "quote": "你不能等待灵感。你必须提着木棒去追求它。", + "author": "杰克·伦敦" }, { - "quote": "If you reveal your secrets to the wind, you should not blame the wind for revealing them to the trees.", - "author": "Kahlil Gibran" + "quote": "不要希望事情更容易,希望你更有能力。", + "author": "吉姆·罗恩" }, { - "quote": "Optimism is an occupational hazard of programming; feedback is the treatment.", - "author": "Kent Beck" + "quote": "我们通过寻找和犯错误来学习。", + "author": "约翰·沃尔夫冈·冯·歌德" }, { - "quote": "Opportunity does not knock, it presents itself when you beat down the door.", - "author": "Kyle Chandler" + "quote": "知道是不够的;我们必须应用。希望是不够的;我们必须行动。", + "author": "约翰·沃尔夫冈·冯·歌德" }, { - "quote": "To iterate is human, to recurse divine.", - "author": "Peter Deutsch" + "quote": "我们先养成习惯,然后习惯造就我们。", + "author": "约翰·德莱登" }, { - "quote": "A good traveler has no fixed plans and is not intent on arriving.", - "author": "Lao Tzu" + "quote": "想象力使我们无限。", + "author": "约翰·缪尔" }, { - "quote": "An ant on the move does more than a dozing ox.", - "author": "Lao Tzu" + "quote": "愿你过好每一天。", + "author": "乔纳森·斯威夫特" }, { - "quote": "Do the difficult things while they are easy and do the great things while they are small. A journey of a thousand miles must begin with a single step.", - "author": "Lao Tzu" + "quote": "坚持就是前 19 次失败,第 20 次成功。", + "author": "朱莉·安德鲁斯" }, { - "quote": "That's the thing about people who think they hate computers. What they really hate is lousy programmers.", - "author": "Larry Niven" + "quote": "今天的工作就是明天的历史,我们是它的创造者。", + "author": "朱丽叶·戈登·洛" }, { - "quote": "It had long since come to my attention that people of accomplishment rarely sat back and let things happen to them. They went out and happened to things.", - "author": "Leonardo da Vinci" + "quote": "如果你向风泄露了你的秘密,你不应该责怪风将它们泄露给树木。", + "author": "纪伯伦" }, { - "quote": "If you're any good at all, you know you can be better.", - "author": "Lindsay Buckingham" + "quote": "乐观是编程的职业病;反馈就是治疗。", + "author": "肯特·贝克" }, { - "quote": "If people never did silly things, nothing intelligent would ever get done.", - "author": "Ludwig Wittgenstein" + "quote": "机会不会敲门,它会在你敲门的时候出现。", + "author": "凯尔·钱德勒" }, { - "quote": "You only live once, but if you do it right, once is enough.", - "author": "Mae West" + "quote": "迭代的是人,递归的是神。", + "author": "彼得·多伊奇" }, { - "quote": "Live as if you were to die tomorrow. Learn as if you were to live forever.", - "author": "Mahatma Gandhi" + "quote": "善行无辙迹,善言无瑕谪。", + "author": "老子" }, { - "quote": "Strength does not come from physical capacity. It comes from an indomitable will.", - "author": "Mahatma Gandhi" + "quote": "合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。", + "author": "老子" }, { - "quote": "One person's 'paranoia' is another person's 'engineering redundancy'.", - "author": "Marcus J. Ranum" + "quote": "那些认为自己讨厌电脑的人就是这样。他们真正讨厌的是糟糕的程序员。", + "author": "拉里·尼文" }, { - "quote": "Nothing in life is to be feared, it is only to be understood. Now is the time to understand more, so that we may fear less.", - "author": "Marie Curie" + "quote": "我早就发现,成功的人很少坐以待毙,让事情发生在他们身上。他们出去主动去做事。", + "author": "达芬奇" }, { - "quote": "If you have everything under control, you're not moving fast enough.", - "author": "Mario Andretti" + "quote": "如果你有一点才能,你就会知道你还可以做得更好。", + "author": "林赛·白金汉" }, { - "quote": "Education: the path from cocky ignorance to miserable uncertainty.", - "author": "Mark Twain" + "quote": "如果人们从不做傻事,就什么都不会做得聪明。", + "author": "路德维希·维特根斯坦" }, { - "quote": "It ain't what you don't know that gets you into trouble. It's what you know for sure that just ain't so.", - "author": "Mark Twain" + "quote": "人只活一次,但若活得其所一次已足够。", + "author": "梅·韦斯特" }, { - "quote": "The secret of getting ahead is getting started.", - "author": "Mark Twain" + "quote": "像明天就要死一样生活,像永远活着一样学习。", + "author": "圣雄甘地" }, { - "quote": "The two most important days in your life are the day you are born and the day you find out why.", - "author": "Mark Twain" + "quote": "力量不是来自身体能力。它来自不屈不挠的意志。", + "author": "圣雄甘地" }, { - "quote": "Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails.", - "author": "Mark Twain" + "quote": "一个人的“偏执狂”是另一个人的“工程冗余”。", + "author": "马库斯·拉纳姆" }, { - "quote": "Any fool can write code that a computer can understand. Good programmers write code that humans can understand.", - "author": "Martin Fowler" + "quote": "生活中没有什么可怕的,只有需要理解的。现在是时候多去理解,这样我们就会少一些恐惧。", + "author": "玛丽·居里" }, { - "quote": "I know, somehow, that only when it is dark enough can you see the stars.", - "author": "Martin Luther King Jr." + "quote": "如果一切都在你的掌控之中,那么你的行动还不够快。", + "author": "马里奥·安德雷蒂" }, { - "quote": "It is never too late to be what you might have been.", - "author": "Mary Anne Evans" + "quote": "教育:从自大的无知到悲惨的不确定性的道路。", + "author": "马克·吐温" }, { - "quote": "Nothing will work unless you do.", - "author": "Maya Angelou" + "quote": "让你陷入麻烦的不是你不知道的东西,而是你确信的、其实并不是真的东西。", + "author": "马克·吐温" }, { - "quote": "We delight in the beauty of the butterfly, but rarely admit the changes it has gone through to achieve that beauty.", - "author": "Maya Angelou" + "quote": "取得成功的秘诀就是开始。", + "author": "马克·吐温" }, { - "quote": "We may encounter many defeats, but we must not be defeated.", - "author": "Maya Angelou" + "quote": "你生命中最重要的两天是你出生的那一天和你找到意义的那一天。", + "author": "马克·吐温" }, { - "quote": "Everybody has talent, but ability takes hard work.", - "author": "Michael Jordan" + "quote": "二十年后,你会因自己没做的事情而更加失望,而不是做过的事情。所以,请解开绳索,驶离安全的港湾,扬帆起航吧。", + "author": "马克·吐温" }, { - "quote": "I've missed more than 9,000 shots during my career. I've lost almost 300 games. 26 times, I've been trusted to take the game winning shot and missed. I've failed over and over and over again in my life. And that is why I succeed.", - "author": "Michael Jordan" + "quote": "任何傻瓜都可以编写计算机可以理解的代码。优秀的程序员编写人类可以理解的代码。", + "author": "马丁·福勒" }, { - "quote": "Impossible is just a big word thrown around by small men who find it easier to live in the world they've been given than to explore the power they have to change it. Impossible is not a fact. It's an opinion. Impossible is not a declaration. It's a dare. Impossible is potential. Impossible is temporary. Impossible is nothing.", - "author": "Muhammad Ali" + "quote": "我知道,不知何故,只有当天足够黑时,你才能看到星星。", + "author": "马丁·路德·金" }, { - "quote": "A winner is a dreamer who never gives up.", - "author": "Nelson Mandela" + "quote": "永远不会太晚去成为你可能成为的人。", + "author": "玛丽·安妮·埃文斯" }, { - "quote": "It always seems impossible until it's done.", - "author": "Nelson Mandela" + "quote": "除非你行动起来,否则什么都不会改变。", + "author": "玛雅·安杰洛" }, { - "quote": "Failure will never overtake me if my determination to succeed is strong enough.", - "author": "Og Mandino" + "quote": "你无法用尽创造力。使用得越多,就会有越多。", + "author": "玛雅·安杰洛" }, { - "quote": "I am not young enough to know everything.", - "author": "Oscar Wilde" + "quote": "我们喜欢蝴蝶的美丽,但很少承认它为实现这种美丽所经历的变化。", + "author": "玛雅·安杰洛" }, { - "quote": "There is only one thing that makes a dream impossible to achieve: the fear of failure.", - "author": "Paulo Coelho" + "quote": "我们可能会遇到很多失败,但我们绝不能被击败。", + "author": "玛雅·安杰洛" }, { - "quote": "Never go to bed mad. Stay up and fight.", - "author": "Phyllis Diller" + "quote": "每个人都有天赋,但能力需要努力。", + "author": "迈克尔·乔丹" }, { - "quote": "You can't cross the sea merely by standing and staring at the water.", - "author": "Rabindranath Tagore" + "quote": "在我的职业生涯中,我错过了 9000 多次投篮。我输掉了近 300 场比赛。26 次,我被信任去投决胜一投,但都没有命中。我一次又一次地失败。但正因如此,我才获得了成功。", + "author": "迈克尔·乔丹" }, { - "quote": "The only person you are destined to become is the person you decide to be.", - "author": "Ralph Waldo Emerson" + "quote": "“不可能”只是小人物们轻易抛出的大词,他们宁愿留在自己被赋予的世界里,也不愿探索自己改变它的力量。“不可能”不是事实,而是意见。“不可能”不是宣言,而是挑战。“不可能”是潜力。“不可能”是暂时的。“不可能”什么也不是。", + "author": "穆罕默德·阿里" }, { - "quote": "What you do speaks so loudly that I cannot hear what you say.", - "author": "Ralph Waldo Emerson" + "quote": "胜利者是永不放弃的梦想家。", + "author": "纳尔逊·曼德拉" }, { - "quote": "People who are crazy enough to think they can change the world, are the ones who do.", - "author": "Rob Siltanen" + "quote": "看起来总是不可能,直到它被做到。", + "author": "纳尔逊·曼德拉" }, { - "quote": "The best way out is always through.", - "author": "Robert Frost" + "quote": "如果我成功的决心足够坚定,失败永远不会压倒我。", + "author": "奥格·曼狄诺" }, { - "quote": "Today's accomplishments were yesterday's impossibilities.", - "author": "Robert H. Schuller" + "quote": "我还不够年轻,不可能了解所有的事情。", + "author": "奥斯卡·王尔德" }, { - "quote": "Don't be satisfied with stories, how things have gone with others. Unfold your own myth.", - "author": "Rumi" + "quote": "只有一件事使梦想无法实现:对失败的恐惧。", + "author": "保罗·柯艾略" }, { - "quote": "Forget safety. Live where you fear to live. Destroy your reputation. Be notorious.", - "author": "Rumi" + "quote": "光是站着看水是无法渡海的。", + "author": "罗宾德拉纳特·泰戈尔" }, { - "quote": "Sell your cleverness and buy bewilderment.", - "author": "Rumi" + "quote": "你注定要成为的唯一的人,就是你决定成为的人。", + "author": "拉尔夫·沃尔多·爱默生" }, { - "quote": "The cure for pain is in the pain.", - "author": "Rumi" + "quote": "你的所作所为声音很大,我听不见你在说什么。", + "author": "拉尔夫·沃尔多·爱默生" }, { - "quote": "Have no fear of perfection - you'll never reach it.", - "author": "Salvador Dalí" + "quote": "那些足够疯狂以为自己可以改变世界的人,才是真正改变世界的人。", + "author": "罗伯·西塔宁" }, { - "quote": "Don't watch the clock. Do what it does. Keep going.", - "author": "Sam Levenson" + "quote": "最好的出路是有始有终。", + "author": "罗伯特·弗罗斯特" }, { - "quote": "Ever Tried. Ever failed. No matter. Try again. Fail again. Fail better.", - "author": "Samuel Beckett" + "quote": "今天的成就是昨天的不可能。", + "author": "罗伯特·舒乐" }, { - "quote": "The more you know, the more you realize you know nothing.", - "author": "Socrates" + "quote": "不要满足于故事,不要满足于别人的经历。揭开你自己的神话。", + "author": "鲁米" }, { - "quote": "The greatest enemy of knowledge is not ignorance, it is the illusion of knowledge.", - "author": "Stephen Hawking" + "quote": "忘掉安全感,到你所害怕的地方去生活。摧毁你的名声,做一个声名狼藉的人。", + "author": "鲁米" }, { - "quote": "The universe doesn't allow perfection.", - "author": "Stephen Hawking" + "quote": "卖掉你的聪明,买下困惑。", + "author": "鲁米" }, { - "quote": "Whether you want to uncover the secrets of the universe, or you want to pursue a career in the 21st century, basic computer programming is an essential skill to learn.", - "author": "Stephen Hawking" + "quote": "治疗疼痛的方法是在疼痛中。", + "author": "鲁米" }, { - "quote": "The scariest moment is always just before you start.", - "author": "Stephen King" + "quote": "不要害怕完美——你永远达不到完美。", + "author": "萨尔瓦多·达利" }, { - "quote": "You can, you should, and if you're brave enough to start, you will.", - "author": "Stephen King" + "quote": "不要看时钟。做它做的事情。继续前进。", + "author": "山姆·李文生" }, { - "quote": "Arise, Awake and Stop not until the goal is reached.", - "author": "Swami Vivekananda" + "quote": "曾经尝试过。曾经失败过。没关系。再尝试一次。再失败一次。做得更好。", + "author": "塞缪尔·贝克特" }, { - "quote": "It is said that your life flashes before your eyes just before you die. That is true, it's called Life.", - "author": "Terry Pratchett" + "quote": "你知道的越多,你就越发现你什么都不知道。", + "author": "苏格拉底" }, { - "quote": "Believe you can and you're halfway there.", - "author": "Theodore Roosevelt" + "quote": "知识最大的敌人不是无知,而是知识的幻觉。", + "author": "史蒂芬·霍金" }, { - "quote": "I have not failed. I've just found 10,000 ways that won't work.", - "author": "Thomas A. Edison" + "quote": "宇宙不允许完美。", + "author": "史蒂芬·霍金" }, { - "quote": "Our greatest weakness lies in giving up. The most certain way to succeed is always to try just one more time.", - "author": "Thomas A. Edison" + "quote": "无论你是想揭开宇宙的秘密,还是想在 21 世纪谋求职业,基础计算机编程是必学的技能。", + "author": "史蒂芬·霍金" }, { - "quote": "The harder the conflict, the more glorious the triumph.", - "author": "Thomas Paine" + "quote": "最可怕的时刻总是在你开始之前。", + "author": "史蒂芬.金" }, { - "quote": "The Web as I envisaged it, we have not seen it yet. The future is still so much bigger than the past.", - "author": "Tim Berners-Lee" + "quote": "你可以,你应该,如果你有足够的勇气开始,你会的。", + "author": "史蒂芬.金" }, { - "quote": "Failure is the condiment that gives success its flavor.", - "author": "Truman Capote" + "quote": "起床,醒来,直到达到目标才停下来。", + "author": "斯瓦米·维韦卡南达" }, { - "quote": "Those who says it cannot be done should not interrupt the person doing it.", - "author": "Unknown" + "quote": "据说,就在你死之前,你的生命在你眼前闪过。没错,这就是所谓的生活。", + "author": "泰瑞·普莱契" }, { - "quote": "Even if you fall on your face, you're still moving forward.", - "author": "Victor Kiam" + "quote": "相信你可以,你就成功了一半。", + "author": "西奥多·罗斯福" }, { - "quote": "It's not whether you get knocked down, it's whether you get up.", - "author": "Vince Lombardi" + "quote": "我没有失败。我只是找到了一万种行不通的方法。", + "author": "爱迪生" }, { - "quote": "I dream my painting and I paint my dream.", - "author": "Vincent van Gogh" + "quote": "我们最大的弱点在于放弃。最确定的成功方法永远是再试一次。", + "author": "爱迪生" }, { - "quote": "Let us cultivate our garden.", - "author": "Voltaire" + "quote": "冲突越激烈,胜利就越光荣。", + "author": "托马斯·潘恩" }, { - "quote": "Aim for the moon. If you miss, you may hit a star.", - "author": "W. Clement Stone" + "quote": "我所设想的网络,我们还没有看到。未来仍然比过去要大得多。", + "author": "蒂姆·伯纳斯-李" }, { - "quote": "The way to get started is to quit talking and begin doing.", - "author": "Walt Disney" + "quote": "失败是给成功增添风味的调味品。", + "author": "杜鲁门·卡波特" }, { - "quote": "You miss 100% of the shots you don't take.", - "author": "Wayne Gretzky" + "quote": "那些说这是不可能的人,不应该打断正在做这件事的人。", + "author": "佚名" }, { - "quote": "Don't let yesterday take up too much of today.", - "author": "Will Rogers" + "quote": "用不同的眼光看待平常的事物。", + "author": "维科·马吉斯泰蒂" }, { - "quote": "Even if you're on the right track, you'll get run over if you just sit there.", - "author": "Will Rogers" + "quote": "即使你摔倒在地,你仍然在前进。", + "author": "维克托·基亚姆" }, { - "quote": "Do not wait to strike till the iron is hot; but make it hot by striking.", - "author": "William Butler Yeats" + "quote": "重要的不是你是否被击倒,而是你是否爬起来。", + "author": "文斯·隆巴迪" }, { - "quote": "You cannot swim for new horizons until you have courage to lose sight of the shore.", - "author": "William Faulkner" + "quote": "我梦想我的画,我画我的梦。", + "author": "文森特·梵高" }, { - "quote": "Be not afraid of greatness. Some are born great, some achieve greatness, and others have greatness thrust upon them.", - "author": "William Shakespeare" + "quote": "伟大的事情是由一系列小事情汇聚而成的。", + "author": "文森特·梵高" }, { - "quote": "We know what we are, but not what we may be.", - "author": "William Shakespeare" + "quote": "让我们耕种我们的花园。", + "author": "伏尔泰" }, { - "quote": "In theory there is no difference between theory and practice. In practice there is.", - "author": "Yogi Berra" + "quote": "瞄准月亮。如果你错失目标,你可能会击中一颗恒星。", + "author": "克莱门特·斯通" }, { - "quote": "You can see a lot by just looking.", - "author": "Yogi Berra" + "quote": "开始的方法是停止说话,开始行动。", + "author": "沃尔特·迪斯尼" }, { - "quote": "There is no elevator to success, you have to take the stairs.", - "author": "Zig Ziglar" + "quote": "你不尝试的话,就有 100% 的机会失败。", + "author": "韦恩·格雷茨基" }, { - "quote": "You don't have to be great to start, but you have to start to be great.", - "author": "Zig Ziglar" + "quote": "不要让昨天占据太多的今天。", + "author": "威尔·罗杰斯" + }, + { + "quote": "即使你是在正确的路上,如果你只是坐在那里,你也会被撞倒。", + "author": "威尔·罗杰斯" + }, + { + "quote": "不要等铁热了再打;要用敲打使它变热。", + "author": "威廉·巴特勒·叶芝" + }, + { + "quote": "除非你有勇气离开海岸,否则你无法游向新的地平线。", + "author": "威廉·福克纳" + }, + { + "quote": "不要害怕伟大。 有些人天生伟大,有些人成就伟大,而另一些人则被推向伟大。", + "author": "威廉·莎士比亚" + }, + { + "quote": "我们知道我们是什么,但不知道我们可能成为什么。", + "author": "威廉·莎士比亚" + }, + { + "quote": "从理论上讲,理论和实践之间没有区别。在实践中是有的。", + "author": "约吉·贝拉" + }, + { + "quote": "通过看,你就可以觉察到很多东西。", + "author": "约吉·贝拉" + }, + { + "quote": "成功没有电梯,你必须走楼梯。", + "author": "齐格·齐格勒" + }, + { + "quote": "你不一定要很伟大才能开始,但你必须开始才能变得伟大。", + "author": "齐格·齐格勒" } ] } diff --git a/client/i18n/locales/chinese/translations.json b/client/i18n/locales/chinese/translations.json index bd6710bf1320bb..0db1f14dd66d0c 100644 --- a/client/i18n/locales/chinese/translations.json +++ b/client/i18n/locales/chinese/translations.json @@ -11,11 +11,12 @@ "view": "查看", "view-code": "查看代码", "view-project": "查看项目", + "view-cert-title": "View {{certTitle}}", "show-cert": "显示认证", "claim-cert": "申请认证", "save-progress": "保存进度", - "accepted-honesty": "你已接受我们的《学术诚信条例》", - "agree": "同意", + "accepted-honesty": "You have agreed to our Academic Honesty Policy.", + "agree-honesty": "I agree to freeCodeCamp's Academic Honesty Policy.", "save-portfolio": "保存这个作品集项目", "remove-portfolio": "移除这个作品集项目", "add-portfolio": "增加一个新的作品集项目", @@ -52,7 +53,7 @@ "check-code": "检查您的代码 (Ctrl + Enter)", "check-code-2": "检查你的代码", "reset": "重置", - "reset-code": "重置所有代码", + "reset-step": "Reset This Step", "help": "帮助", "get-help": "获得帮助", "watch-video": "观看视频", @@ -157,7 +158,8 @@ "honesty": "学术诚信条例", "internet": "你在各平台的账号", "portfolio": "作品集设置", - "privacy": "隐私设置" + "privacy": "隐私设置", + "personal-info": "Personal Information" }, "danger": { "heading": "危险区域", @@ -222,16 +224,15 @@ "total-points_plural": "{{count}} 总分", "points": "{{date}} 获得 {{count}} 分", "points_plural": "{{date}} 获得 {{count}} 分", - "screen-shot": "{{title}} 截图", "page-number": "第 {{pageNumber}} 页,共 {{totalPages}} 页" }, "footer": { - "tax-exempt-status": "freeCodeCamp 是捐助者支持的 501(c)(3) 条款下具有免税资格的非营利性组织(税号:82-0779546)。", + "tax-exempt-status": "freeCodeCamp 是捐助者支持的 501(c)(3) 条款下具有免税资格的慈善组织(税号:82-0779546)。", "mission-statement": "我们的使命:帮助人们免费学习编程。我们通过创建成千上万的视频、文章和交互式编程课程——所有内容向公众免费开放——来实现这一目标。学员在世界各地自发成立数千个 freeCodeCamp 学习小组。", "donation-initiatives": "所有给 freeCodeCamp 的捐款都将用于我们的教育项目,购买服务器和其他服务,以及聘用员工。", "donate-text": "你可以<1>在此处进行免税捐赠。", "trending-guides": "精选文章", - "our-nonprofit": "关于我们", + "our-nonprofit": "我们的慈善组织", "links": { "about": "简介", "alumni": "校友网络", @@ -249,6 +250,7 @@ }, "learn": { "heading": "欢迎学习 freeCodeCamp 的课程。", + "skip-to-content": "Skip to content", "welcome-1": "欢迎回来,{{name}}。", "welcome-2": "欢迎来到 freeCodeCamp.org", "start-at-beginning": "如果你刚开始学习编程,我们建议你<0>从头开始。", @@ -264,7 +266,7 @@ "p8": "这套课程需要你进行数千个小时的编程练习。", "p9": "如果你想学习更多数学和计算机科学理论,<0>freeCodeCamp 的 \n YouTube channel 还有数千个小时的视频课程。", "p10": "如果你想获得开发者工作或者成为自由职业开发者找到客户,那么除了编程技能,你还需要搭建自己的社交网络,打造自己作为开发者的影响力。", - "p11": "You can do this on LinkedIn and GitHub, and also on <0>the freeCodeCamp forum.", + "p11": "你还可以在 LinkedIn、Twitter、GitHub 和 <0>freeCodeCamp 论坛 上做到这一点。", "p12": "编程愉快!" }, "upcoming-lessons": "即将上线的课程", @@ -272,6 +274,9 @@ "add-subtitles": "帮助我们完善或添加字幕", "wrong-answer": "抱歉,这个答案不正确。再试一次?", "check-answer": "点击下方按钮,查看你的答案。", + "assignment-not-complete": "Please finish the assignments", + "assignments": "Assignments", + "question": "Question", "solution-link": "解决方案链接", "github-link": "GitHub 链接", "submit-and-go": "提交并访问下一个挑战", @@ -284,7 +289,7 @@ "sign-in-save": "登录以保存你的学习进度", "download-solution": "下载我的解决方案", "percent-complete": "完成 {{percent}}%", - "project-complete": "Completed {{completedChallengesInBlock}} of {{totalChallengesInBlock}} certification projects", + "project-complete": "已完成 {{totalChallengesInBlock}} 认证项目中的 {{completedChallengesInBlock}}", "tried-rsa": "如果你已经尝试了 <0>Read-Search-Ask(阅读-搜索-提问)方法,那么你可以在 freeCodeCamp 论坛请求帮助。", "rsa": "阅读,搜索,提问", "rsa-forum": "在发布新帖子之前 ,请确认你的问题是否<0>已经在论坛上被回答过。", @@ -297,7 +302,6 @@ "certs": "{{title}} 认证" }, "editor-tabs": { - "info": "信息", "code": "编程", "tests": "测试", "restart": "重启", @@ -307,6 +311,10 @@ "notes": "注意", "preview": "预览" }, + "editor-alerts": { + "tab-trapped": "按下选项卡将插入选项卡字符", + "tab-free": "按下选项卡将焦点移动到下一个焦点元素" + }, "help-translate": "我们仍然在翻译以下证书。", "help-translate-link": "帮助我们翻译。", "project-preview-title": "下面是你将构建的项目的预览", @@ -326,16 +334,16 @@ "sorry-hang-in-there": "抱歉,你的代码未通过,坚持一下。", "sorry-dont-giveup": "抱歉,你的代码未通过,不要放弃。", "challenges-completed": "已完成 {{completedCount}}/{{totalChallenges}}", - "season-greetings-fcc": "Season's Greetings from the freeCodeCamp community 🎉", - "if-getting-value": "If you're getting a lot out of freeCodeCamp, now is a great time to donate to support our nonprofit's mission.", - "building-a-university": "We're Building a Free Computer Science University Degree Program", - "if-help-university": "We've already made a ton of progress. Support our charity with the long road ahead." + "season-greetings-fcc": "来自 freeCodeCamp 社区的季节问候 🎉", + "if-getting-value": "如果你从 freeCodeCamp 中获益良多,可以捐款支持我们的慈善组织的使命。", + "building-a-university": "我们正在创建一个免费计算机科学大学学位课程", + "if-help-university": "我们已取得了重大进展。请支持我们的慈善组织完成这项长期事业。" }, "donate": { - "title": "支持我们的非营利组织", + "title": "支持我们的慈善组织", "processing": "我们正在处理你的捐款。", "redirecting": "重新引导中...", - "thanks": "谢谢捐款", + "thanks": "Thanks for donating", "thank-you": "谢谢你成为我们的支持者。", "additional": "你可以使用这个链接 <0>{{url}} 额外进行一次性捐款:", "help-more": "帮助我们做更多", @@ -354,11 +362,10 @@ "your-donation": "你的 ${{usd}} 捐款将帮助世界各地的人们学习 {{hours}} 小时。", "your-donation-2": "你的 ${{usd}} 捐款每月将帮助世界各地的人们学习 {{hours}} 小时。", "your-donation-3": "你的 ${{usd}} 捐款每年将帮助世界各地的人们学习 {{hours}} 小时。", - "become-supporter": "Become a Supporter", - "duration": "成为我们非营利组织的一次性支持者", - "duration-2": "成为我们非营利组织的每月定期支持者", - "duration-3": "成为我们非营利组织的每年定期支持者", - "duration-4": "成为我们非营利组织的支持者", + "become-supporter": "成为支持者", + "duration": "成为我们的慈善组织的一次性支持者", + "duration-2": "成为我们的慈善组织的每月定期支持者", + "duration-4": "成为我们的慈善组织的支持者", "nicely-done": "很棒,你已完成 {{block}}。", "credit-card": "信用卡", "credit-card-2": "或者使用信用卡捐款:", @@ -372,25 +379,25 @@ "email-receipt": "邮箱(我们将把捐款税务收据发送给你):", "need-help": "需要我们帮助处理你的当前或之前的捐款?", "forward-receipt": "将你的捐款收据副本发送至 donors@freecodecamp.org,告诉我们你需要什么帮助。", - "efficiency": "freeCodeCamp 是一个高效率的专注教育的非营利组织。", + "efficiency": "freeCodeCamp 是一个高效率的教育慈善组织。", "why-donate-1": "通过给 freeCodeCamp 捐款,你帮助人们学习新技能以供养家庭。", "why-donate-2": "你也帮助我们创建新的学习资源,你可以利用这些资源拓展自己的技术能力。", "bigger-donation": "给我们额度更大的一次性捐款,或寄一张支票,或通过其他方式给我们捐款?", - "other-ways": "有许多<0>其他方式可以支持我们的非营利组织践行使命.", + "other-ways": "有许多<0>其他方式可以支持我们的慈善组织践行使命.", "failed-pay": "呃,你的转账似乎没有成功,再试一次好吗?", "try-again": "请重试。", "card-number": "你的卡号:", "expiration": "到期日:", "secure-donation": "安全捐款", "faq": "常见问题", - "only-you": "只有你可以看到此消息。祝贺你获得这项认证。获得认证不是一件容易的事情,运营 freeCodeCamp 也不容易,而且需要花费很多。请帮助我们更好地帮助你和世界各地的许多其他人。今天就为我们的非营利组织提供免税捐款,支持我们。", + "only-you": "只有你可以看到此消息。祝贺你获得这项认证。获得认证不是一件容易的事情,运营 freeCodeCamp 也不容易,而且需要花费很多。请帮助我们更好地帮助你和世界各地的许多其他人。今天就为我们的慈善组织提供免税捐款,支持我们。", "get-help": "我如何利用我的捐款得到帮助?", "how-transparent": "freeCodeCamp.org 的透明度如何?", "very-transparent": "我们甚至有一个来自 GuideStar.org 的白金透明度评级。", "download-irs": "你可以<0>在此处下载我们的国税局认定函。", "download-990": "你可以<0>在此处下载我们最新的 990 (年度税务报告)。", "how-efficient": "freeCodeCamp 的效率如何?", - "fcc-budget": "freeCodeCamp 的预算比大多数非营利组织少得多。我们还没有引入专业募捐者,而是 Quincy 自己处理一切相关事务。", + "fcc-budget": "freeCodeCamp 的预算比大多数慈善组织少得多。我们还没有引入专业募捐者,而是 Quincy 自己处理一切相关事务。", "help-millions": "然而,在每年仅有 10 万美元的预算中,我们能够帮助数百万人。", "how-one-time": "我如何进行一次性捐款?", "one-time": "如果你喜欢一次性捐款,你可以在有闲钱时支持 freeCodeCamp 的事业。你可以使用<0>此链接,通过 PayPal 捐你认为合适的金额。", @@ -400,7 +407,7 @@ "can-check": "我可以邮寄实物支票吗?", "yes-check": "是的,我们欢迎支票。你可以将其邮寄给我们:", "how-matching-gift": "我如何从我的雇主那里设置匹配的礼物,或者工资扣除?", - "employers-vary": "这因雇主而异,而我们的非营利组织已经被列入许多大型捐赠匹配数据库。", + "employers-vary": "这因雇主而异,而我们的慈善组织已经被列入许多大型捐赠匹配数据库。", "some-volunteer": "有些人能够为 freeCodeCamp 提供志愿服务,他们的雇主通过每小时志愿服务捐赠一个固定的金额进行匹配。其他雇主会对捐赠者的任何捐赠进行匹配,最高可达某一数额。", "help-matching-gift": "如你需要帮助,请直接给 Quincy 发送电子邮件:quincy@freecodecamp.org", "how-endowment": "如何为 freeCodeCamp.org 设置捐赠礼物?", @@ -411,13 +418,13 @@ "thank-wikimedia": "我们要感谢维基百科基金会为我们提供这种正式文书。", "legacy-gift-questions": "如果你对此过程有任何疑问,请给 Quincy 发送电子邮件到 Quincy@freecodecamp.org。", "how-stock": "如何将股票捐赠给 freeCodeCamp.org?", - "welcome-stock": "我们欢迎你的股票捐赠。请直接为 Quincy 发送电子邮件到 quincy@freecodecamp.org,他可以帮助你做到这一点,并分享我们的非营利经纪业务账户的详细信息。", + "welcome-stock": "我们欢迎你的股票捐赠。请直接给 Quincy 发送电子邮件到 quincy@freecodecamp.org,他可以帮助你,并分享我们的慈善组织的经纪账户的详细信息。", "how-receipt": "我能够收到捐赠收据以从我的税款中扣除我的捐赠吗?", "just-forward": "可以,只需将你交易的收据转发到 donors@freecodecamp.org,告诉我们你想要一个收据以及你的使用场景,我们将发给你一个收据。", "how-update": "我设置了每月捐款,但我需要更新或暂停每月的重复。我如何做?", "take-care-of-this": "只需转发你的每月捐款记录中的一个记录给 donors@freecodecamp.org, 并告诉我们你要做什么。我们会为你处理这个问题,并向你发送确认。", "anything-else": "还有什么关于为 freeCodeCamp.org 捐赠可以了解的吗?", - "other-support": "如果你想要以其他方式支持我们的非营利工作并且它的渠道没有在此列出, 或者如果你有任何问题,请给 Quincy 发送电子邮件到 quincy@freecodecamp.org。" + "other-support": "如果你想要通过此处未列出的其他方式支持我们的慈善组织和它的使命,或者如果你有任何问题,请给 Quincy 发送电子邮件到 quincy@freecodecamp.org。" }, "report": { "sign-in": "你需要先登录才能举报用户", @@ -460,7 +467,8 @@ "iframe-preview": "{{title}} 预览", "iframe-alert": "通常,此链接会将你带到另一个网站!一切正常,这个链接指向:{{externalLink}}。", "iframe-form-submit-alert": "通常这个表单将被提交!工作正常,这将被提交到:{{externalLink}}", - "document-notfound": "找不到文件" + "document-notfound": "找不到文件", + "slow-load-msg": "Looks like this is taking longer than usual, please try refreshing the page." }, "icons": { "gold-cup": "金奖杯", @@ -475,10 +483,11 @@ "hint": "提示", "heart": "爱心", "initial": "初始", + "input-reset": "Clear search terms", "info": "介绍信息", "spacer": "间隔", "toggle": "切换选中标记", - "magnifier": "放大镜" + "magnifier": "Submit search terms" }, "aria": { "fcc-curriculum": "freeCodeCamp 课程", @@ -504,10 +513,11 @@ "step": "步骤", "steps": "步骤", "steps-for": "{{blockTitle}} 的步骤", - "code-example": "{{codeName}} code example" + "code-example": "{{codeName}} 代码示例", + "opens-new-window": "Opens in new window" }, "flash": { - "honest-first": "申请认证之前,你必须先接受我们的《学术诚信条例》", + "honest-first": "To claim a certification, you must first agree to our academic honesty policy", "really-weird": "出现了一些奇怪的情况。如果再出现这种情况,请考虑在 https://github.com/freeCodeCamp/freeCodeCamp/issues/new 提交 issue。", "not-right": "有些不对劲。已生成报告,通知 freeCodeCamp.org 团队。", "went-wrong": "出了点问题,请检查并重试。", @@ -586,7 +596,8 @@ "editor-url": "记得要提交Live App的URL", "http-url": "不能使用不安全的(http)URL。", "own-work-url": "记住要提交你自己的作业", - "publicly-visible-url": "记得要提交一个公开可见的app URL" + "publicly-visible-url": "记得要提交一个公开可见的app URL", + "path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path" }, "certification": { "executive": "执行董事,freeCodeCamp.org", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "猫和狗图像分类器", "Book Recommendation Engine using KNN": "基于 KNN 的图书推荐引擎", "Linear Regression Health Costs Calculator": "线性回归健康成本计算器", - "Neural Network SMS Text Classifier": "神经网络短信分类器" + "Neural Network SMS Text Classifier": "神经网络短信分类器", + "Celestial Bodies Database": "Celestial Bodies Database", + "World Cup Database": "World Cup Database", + "Salon Appointment Scheduler": "Salon Appointment Scheduler", + "Periodic Table Database": "Periodic Table Database", + "Number Guessing Game": "Number Guessing Game", + "Build a freeCodeCamp Forum Homepage": "Build a freeCodeCamp Forum Homepage" } + }, + "title": { + "Responsive Web Design": "Responsive Web Design", + "responsive-web-design": "Responsive Web Design Certification", + "JavaScript Algorithms and Data Structures": "JavaScript Algorithms and Data Structures", + "javascript-algorithms-and-data-structures": "JavaScript Algorithms and Data Structures Certification", + "Front End Development Libraries": "Front End Development Libraries", + "front-end-development-libraries": "Front End Development Libraries Certification", + "Data Visualization": "Data Visualization", + "data-visualization": "Data Visualization Certification", + "Relational Database": "Relational Database", + "relational-database-v8": "Relational Database Certification", + "Back End Development and APIs": "Back End Development and APIs", + "back-end-development-and-apis": "Back End Development and APIs Certification", + "Quality Assurance": "Quality Assurance", + "quality-assurance-v7": "Quality Assurance Certification", + "Scientific Computing with Python": "Scientific Computing with Python", + "scientific-computing-with-python-v7": "Scientific Computing with Python Certification", + "Data Analysis with Python": "Data Analysis with Python", + "data-analysis-with-python-v7": "Data Analysis with Python Certification", + "Information Security": "Information Security", + "information-security-v7": "Information Security Certification", + "Machine Learning with Python": "Machine Learning with Python", + "machine-learning-with-python-v7": "Machine Learning with Python Certification", + "Legacy Front End": "Legacy Front End", + "legacy-front-end": "Front End Certification", + "Legacy Back End": "Legacy Back End", + "legacy-back-end": "Back End Certification", + "Legacy Data Visualization": "Legacy Data Visualization", + "legacy-data-visualization": "Data Visualization Certification", + "Legacy Information Security and Quality Assurance": "Legacy Information Security and Quality Assurance", + "information-security-and-quality-assurance": "Information Security and Quality Assurance Certification", + "Legacy Full Stack Certification": "Legacy Full Stack Certification", + "Legacy Full Stack": "Legacy Full Stack", + "full-stack": "Full Stack Certification" } }, "certification-card": { @@ -724,10 +776,10 @@ "navigate-next": "跳转至下一个练习" }, "signout": { - "heading": "Sign out of your account", - "p1": "Warning: If you continue, your progress will no longer be saved.", - "p2": "This action will sign you out of your account on this device and browser session only. Please confirm if you would like to proceed.", - "certain": "Yes, sign out of my account", - "nevermind": "Nevermind, I don't want to sign out" + "heading": "注销你的账户", + "p1": "警告:如果你继续,你的当前进度将不再被保存。", + "p2": "此操作只会将你在此设备和浏览器会话上的账号注销。请确认你是否要继续。", + "certain": "是的,请注销我的账户", + "nevermind": "算了,我不想注销账户" } } diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index 863446aa4c258c..5b34848fb52dee 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -367,6 +367,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "Learn Functional Programming by Building a Spreadsheet", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Learn Advanced Array Methods by Building a Statistics Calculator", + "intro": ["", ""] } } }, @@ -466,10 +470,7 @@ "In these projects, you'll need to fetch data and parse a dataset, then use D3 to create different data visualizations. Finish them all to earn your Data Visualization certification." ] }, - "d3-dashboard": { - "title": "D3 Dashboard", - "intro": ["", ""] - } + "d3-dashboard": { "title": "D3 Dashboard", "intro": ["", ""] } } }, "relational-database": { @@ -585,7 +586,7 @@ "intro": [ "Until this point, you've only used JavaScript on the front end to add interactivity to a page, solve algorithm challenges, or build an SPA. But JavaScript can also be used on the back end, or server, to build entire web applications.", "Today, one of the popular ways to build applications is through microservices, which are small, modular applications that work together to form a larger whole.", - "In the Back End Development and APIs Certification, you'll learn how to write back end apps with Node.js and npm (Node Package Manager). You'll also build web applications with the Express framework, and build a People Finder microservice with MongoDB and the Mongoose library." + "In the Back End Development and APIs Certification, you'll learn how to write back end apps with Node.js and npm. You'll also build web applications with the Express framework, and build a People Finder microservice with MongoDB and the Mongoose library." ], "note": "", "blocks": { @@ -819,6 +820,24 @@ } } }, + "the-odin-project": { + "title": "The Odin Project", + "intro": [ + "The Odin Project is one of those \"What I wish I had when I was learning\" resources. ", + "Not everyone has access to a computer science education or the funds to attend an intensive coding school and neither of those is right for everyone anyway.", + "This project is designed to fill in the gap for people who are trying to hack it on their own but still want a high quality education." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Learn HTML Foundations", + "intro": ["A description is to be determined"] + }, + "top-build-a-recipe-project": { + "title": "Learn HTML Foundations by Building a Recipe Page", + "intro": ["A description is to be determined"] + } + } + }, "misc-text": { "certification": "{{cert}} Certification", "browse-other": "Browse our other free certifications\n(we recommend doing these in order)", diff --git a/client/i18n/locales/english/translations.json b/client/i18n/locales/english/translations.json index 2ece8d81b3ddf1..64fa3faebab4eb 100644 --- a/client/i18n/locales/english/translations.json +++ b/client/i18n/locales/english/translations.json @@ -11,11 +11,12 @@ "view": "View", "view-code": "View Code", "view-project": "View Project", + "view-cert-title": "View {{certTitle}}", "show-cert": "Show Certification", "claim-cert": "Claim Certification", "save-progress": "Save Progress", - "accepted-honesty": "You have accepted our Academic Honesty Policy.", - "agree": "Agree", + "accepted-honesty": "You have agreed to our Academic Honesty Policy.", + "agree-honesty": "I agree to freeCodeCamp's Academic Honesty Policy.", "save-portfolio": "Save this portfolio item", "remove-portfolio": "Remove this portfolio item", "add-portfolio": "Add a new portfolio Item", @@ -53,7 +54,7 @@ "check-code": "Check Your Code (Ctrl + Enter)", "check-code-2": "Check Your Code", "reset": "Reset", - "reset-code": "Reset Code", + "reset-step": "Reset This Step", "help": "Help", "get-help": "Get Help", "watch-video": "Watch a Video", @@ -158,7 +159,8 @@ "honesty": "Academic Honesty Policy", "internet": "Your Internet Presence", "portfolio": "Portfolio Settings", - "privacy": "Privacy Settings" + "privacy": "Privacy Settings", + "personal-info": "Personal Information" }, "danger": { "heading": "Danger Zone", @@ -223,16 +225,15 @@ "total-points_plural": "{{count}} total points", "points": "{{count}} point on {{date}}", "points_plural": "{{count}} points on {{date}}", - "screen-shot": "A screen shot of {{title}}", "page-number": "{{pageNumber}} of {{totalPages}}" }, "footer": { - "tax-exempt-status": "freeCodeCamp is a donor-supported tax-exempt 501(c)(3) nonprofit organization (United States Federal Tax Identification Number: 82-0779546)", + "tax-exempt-status": "freeCodeCamp is a donor-supported tax-exempt 501(c)(3) charitable organization (United States Federal Tax Identification Number: 82-0779546)", "mission-statement": "Our mission: to help people learn to code for free. We accomplish this by creating thousands of videos, articles, and interactive coding lessons - all freely available to the public. We also have thousands of freeCodeCamp study groups around the world.", "donation-initiatives": "Donations to freeCodeCamp go toward our education initiatives, and help pay for servers, services, and staff.", "donate-text": "You can <1>make a tax-deductible donation here.", "trending-guides": "Trending Guides", - "our-nonprofit": "Our Nonprofit", + "our-nonprofit": "Our Charity", "links": { "about": "About", "alumni": "Alumni Network", @@ -250,6 +251,7 @@ }, "learn": { "heading": "Welcome to freeCodeCamp's curriculum.", + "skip-to-content": "Skip to content", "welcome-1": "Welcome back, {{name}}.", "welcome-2": "Welcome to freeCodeCamp.org", "start-at-beginning": "If you are new to coding, we recommend you <0>start at the beginning.", @@ -273,6 +275,9 @@ "add-subtitles": "Help improve or add subtitles", "wrong-answer": "Sorry, that's not the right answer. Give it another try?", "check-answer": "Click the button below to check your answer.", + "assignment-not-complete": "Please finish the assignments", + "assignments": "Assignments", + "question": "Question", "solution-link": "Solution Link", "github-link": "GitHub Link", "submit-and-go": "Submit & go to next step", @@ -298,7 +303,6 @@ "certs": "{{title}} Certification" }, "editor-tabs": { - "info": "Info", "code": "Code", "tests": "Tests", "restart": "Restart", @@ -308,6 +312,10 @@ "notes": "Notes", "preview": "Preview" }, + "editor-alerts": { + "tab-trapped": "Pressing tab will now insert the tab character", + "tab-free": "Pressing tab will now move focus to the next focusable element" + }, "help-translate": "We are still translating the following certifications.", "help-translate-link": "Help us translate.", "project-preview-title": "Here's a preview of what you will build", @@ -328,12 +336,12 @@ "sorry-dont-giveup": "Sorry, your code does not pass. Don't give up.", "challenges-completed": "{{completedCount}} of {{totalChallenges}} challenges completed", "season-greetings-fcc": "Season's Greetings from the freeCodeCamp community 🎉", - "if-getting-value": "If you're getting a lot out of freeCodeCamp, now is a great time to donate to support our nonprofit's mission.", + "if-getting-value": "If you're getting a lot out of freeCodeCamp, now is a great time to donate to support our charity's mission.", "building-a-university": "We're Building a Free Computer Science University Degree Program", "if-help-university": "We've already made a ton of progress. Support our charity with the long road ahead." }, "donate": { - "title": "Support our nonprofit", + "title": "Support our charity", "processing": "We are processing your donation.", "redirecting": "Redirecting...", "thanks": "Thanks for donating", @@ -356,10 +364,9 @@ "your-donation-2": "Your ${{usd}} donation will provide {{hours}} hours of learning to people around the world each month.", "your-donation-3": "Your ${{usd}} donation will provide {{hours}} hours of learning to people around the world each year.", "become-supporter": "Become a Supporter", - "duration": "Become a one-time supporter of our nonprofit.", - "duration-2": "Become a monthly supporter of our nonprofit.", - "duration-3": "Become an annual supporter of our nonprofit", - "duration-4": "Become a supporter of our nonprofit", + "duration": "Become a one-time supporter of our charity.", + "duration-2": "Become a monthly supporter of our charity.", + "duration-4": "Become a supporter of our charity", "nicely-done": "Nicely done. You just completed {{block}}.", "credit-card": "Credit Card", "credit-card-2": "Or donate with a credit card:", @@ -373,25 +380,25 @@ "email-receipt": "Email (we'll send you a tax-deductible donation receipt):", "need-help": "Need help with your current or past donations?", "forward-receipt": "Forward a copy of your donation receipt to donors@freecodecamp.org and tell us how we can help.", - "efficiency": "freeCodeCamp is a highly efficient education nonprofit.", + "efficiency": "freeCodeCamp is a highly efficient education charity.", "why-donate-1": "When you donate to freeCodeCamp, you help people learn new skills and provide for their families.", "why-donate-2": "You also help us create new resources for you to use to expand your own technology skills.", "bigger-donation": "Want to make a bigger one-time donation, mail us a check, or give in other ways?", - "other-ways": "Here are many <0>other ways you can support our non-profit's mission.", + "other-ways": "Here are many <0>other ways you can support our charity's mission.", "failed-pay": "Uh - oh. It looks like your transaction didn't go through. Could you please try again?", "try-again": "Please try again.", "card-number": "Your Card Number:", "expiration": "Expiration Date:", "secure-donation": "Secure donation", "faq": "Frequently asked questions", - "only-you": "Only you can see this message. Congratulations on earning this certification. It's no easy task. Running freeCodeCamp isn't easy either. Nor is it cheap. Help us help you and many other people around the world. Make a tax-deductible supporting donation to our nonprofit today.", + "only-you": "Only you can see this message. Congratulations on earning this certification. It's no easy task. Running freeCodeCamp isn't easy either. Nor is it cheap. Help us help you and many other people around the world. Make a tax-deductible supporting donation to our charity today.", "get-help": "How can I get help with my donations?", "how-transparent": "How transparent is freeCodeCamp.org?", "very-transparent": "Very. We have a Platinum transparency rating from GuideStar.org.", "download-irs": "You can <0>download our IRS Determination Letter here.", "download-990": "You can <0>download our most recent 990 (annual tax report) here.", "how-efficient": "How efficient is freeCodeCamp?", - "fcc-budget": "freeCodeCamp's budget is much smaller than most comparable nonprofits. We haven't brought in professional fundraisers. Instead, Quincy does everything himself.", + "fcc-budget": "freeCodeCamp's budget is much smaller than most comparable charity. We haven't brought in professional fundraisers. Instead, Quincy does everything himself.", "help-millions": "However, on a budget of only a few hundred thousand dollars per year, we have been able to help millions of people.", "how-one-time": "How can I make a one-time donation?", "one-time": "If you'd prefer to make one-time donations, you can support freeCodeCamp's mission whenever you have cash to spare. You can use <0>this link to donate whatever amount feels right through PayPal.", @@ -401,7 +408,7 @@ "can-check": "Can I mail a physical check?", "yes-check": "Yes, we would welcome a check. You can mail it to us at:", "how-matching-gift": "How can I set up matching gifts from my employer, or payroll deductions?", - "employers-vary": "This varies from employer to employer, and our nonprofit is already listed in many of the big donation-matching databases.", + "employers-vary": "This varies from employer to employer, and our charity is already listed in many of the big donation-matching databases.", "some-volunteer": "Some people are able to volunteer for freeCodeCamp and their employer matches by donating a fixed amount per hour they volunteer. Other employers will match any donations the donors make up to a certain amount", "help-matching-gift": "If you need help with this, please email Quincy directly: quincy@freecodecamp.org", "how-endowment": "How can I set up an Endowment Gift to freeCodeCamp.org?", @@ -412,13 +419,13 @@ "thank-wikimedia": "We would like to thank the Wikimedia Foundation for providing this formal language for us to use.", "legacy-gift-questions": "If you have any questions about this process, please email Quincy at quincy@freecodecamp.org.", "how-stock": "How can I donate stock to freeCodeCamp.org?", - "welcome-stock": "We would welcome your stock donations. Please email Quincy directly and he can help you with this, and share our nonprofit's brokerage account details: quincy@freecodecamp.org.", + "welcome-stock": "We would welcome your stock donations. Please email Quincy directly and he can help you with this, and share our charity's brokerage account details: quincy@freecodecamp.org.", "how-receipt": "Can I get a donation receipt so that I can deduct my donation from my taxes?", "just-forward": "Absolutely. Just forward the receipt from your transaction to donors@freecodecamp.org, tell us you'd like a receipt and any special instructions you may have, and we'll reply with a receipt for you.", "how-update": "I set up a monthly donation, but I need to update or pause the monthly recurrence. How can I do this?", "take-care-of-this": "Just forward one of your monthly donation receipts to donors@freecodecamp.org and tell us what you'd like us to do. We'll take care of this for you and send you confirmation.", "anything-else": "Is there anything else I can learn about donating to freeCodeCamp.org?", - "other-support": "If there is some other way you'd like to support our nonprofit and its mission that isn't listed here, or if you have any questions at all, please email Quincy at quincy@freecodecamp.org." + "other-support": "If there is some other way you'd like to support our charity and its mission that isn't listed here, or if you have any questions at all, please email Quincy at quincy@freecodecamp.org." }, "report": { "sign-in": "You need to be signed in to report a user", @@ -461,7 +468,8 @@ "iframe-preview": "{{title}} preview", "iframe-alert": "Normally this link would bring you to another website! It works. This is a link to: {{externalLink}}", "iframe-form-submit-alert": "Normally this form would be submitted! It works. This will be submitted to: {{externalLink}}", - "document-notfound": "document not found" + "document-notfound": "document not found", + "slow-load-msg": "Looks like this is taking longer than usual, please try refreshing the page." }, "icons": { "gold-cup": "Gold Cup", @@ -476,10 +484,11 @@ "hint": "Hint", "heart": "Heart", "initial": "Initial", + "input-reset": "Clear search terms", "info": "Intro Information", "spacer": "Spacer", "toggle": "Toggle Checkmark", - "magnifier": "magnifier" + "magnifier": "Submit search terms" }, "aria": { "fcc-curriculum": "freeCodeCamp Curriculum", @@ -505,10 +514,11 @@ "step": "Step", "steps": "Steps", "steps-for": "Steps for {{blockTitle}}", - "code-example": "{{codeName}} code example" + "code-example": "{{codeName}} code example", + "opens-new-window": "Opens in new window" }, "flash": { - "honest-first": "To claim a certification, you must first accept our academic honesty policy", + "honest-first": "To claim a certification, you must first agree to our academic honesty policy", "really-weird": "Something really weird happened, if it happens again, please consider raising an issue on https://github.com/freeCodeCamp/freeCodeCamp/issues/new", "not-right": "Something is not quite right. A report has been generated and the freeCodeCamp.org team have been notified", "went-wrong": "Something went wrong, please check and try again", @@ -587,7 +597,8 @@ "editor-url": "Remember to submit the Live App URL.", "http-url": "An unsecure (http) URL cannot be used.", "own-work-url": "Remember to submit your own work.", - "publicly-visible-url": "Remember to submit a publicly visible app URL." + "publicly-visible-url": "Remember to submit a publicly visible app URL.", + "path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path" }, "certification": { "executive": "Executive Director, freeCodeCamp.org", @@ -669,8 +680,49 @@ "Cat and Dog Image Classifier": "Cat and Dog Image Classifier", "Book Recommendation Engine using KNN": "Book Recommendation Engine using KNN", "Linear Regression Health Costs Calculator": "Linear Regression Health Costs Calculator", - "Neural Network SMS Text Classifier": "Neural Network SMS Text Classifier" + "Neural Network SMS Text Classifier": "Neural Network SMS Text Classifier", + "Celestial Bodies Database": "Celestial Bodies Database", + "World Cup Database": "World Cup Database", + "Salon Appointment Scheduler": "Salon Appointment Scheduler", + "Periodic Table Database": "Periodic Table Database", + "Number Guessing Game": "Number Guessing Game", + "Build a freeCodeCamp Forum Homepage": "Build a freeCodeCamp Forum Homepage" } + }, + "title": { + "Responsive Web Design": "Responsive Web Design", + "responsive-web-design": "Responsive Web Design Certification", + "JavaScript Algorithms and Data Structures": "JavaScript Algorithms and Data Structures", + "javascript-algorithms-and-data-structures": "JavaScript Algorithms and Data Structures Certification", + "Front End Development Libraries": "Front End Development Libraries", + "front-end-development-libraries": "Front End Development Libraries Certification", + "Data Visualization": "Data Visualization", + "data-visualization": "Data Visualization Certification", + "Relational Database": "Relational Database", + "relational-database-v8": "Relational Database Certification", + "Back End Development and APIs": "Back End Development and APIs", + "back-end-development-and-apis": "Back End Development and APIs Certification", + "Quality Assurance": "Quality Assurance", + "quality-assurance-v7": "Quality Assurance Certification", + "Scientific Computing with Python": "Scientific Computing with Python", + "scientific-computing-with-python-v7": "Scientific Computing with Python Certification", + "Data Analysis with Python": "Data Analysis with Python", + "data-analysis-with-python-v7": "Data Analysis with Python Certification", + "Information Security": "Information Security", + "information-security-v7": "Information Security Certification", + "Machine Learning with Python": "Machine Learning with Python", + "machine-learning-with-python-v7": "Machine Learning with Python Certification", + "Legacy Front End": "Legacy Front End", + "legacy-front-end": "Front End Certification", + "Legacy Back End": "Legacy Back End", + "legacy-back-end": "Back End Certification", + "Legacy Data Visualization": "Legacy Data Visualization", + "legacy-data-visualization": "Data Visualization Certification", + "Legacy Information Security and Quality Assurance": "Legacy Information Security and Quality Assurance", + "information-security-and-quality-assurance": "Information Security and Quality Assurance Certification", + "Legacy Full Stack Certification": "Legacy Full Stack Certification", + "Legacy Full Stack": "Legacy Full Stack", + "full-stack": "Full Stack Certification" } }, "certification-card": { diff --git a/client/i18n/locales/espanol/intro.json b/client/i18n/locales/espanol/intro.json index 06cd2940c088a6..6b69e55e927ed8 100644 --- a/client/i18n/locales/espanol/intro.json +++ b/client/i18n/locales/espanol/intro.json @@ -1,8 +1,8 @@ { "responsive-web-design": { - "title": "Diseño Web Responsivo Legado", + "title": "Diseño Web Adaptativo Legado", "intro": [ - "En esta Certificación de Diseño Web Responsivo, aprenderás los lenguajes que los desarrolladores utilizan para construir páginas web: HTML (lenguaje de marcado de hipertexto) para el contenido, y CSS (Hojas de estilo en cascada) para el diseño.", + "En esta Certificación de Diseño Web Adaptativo, aprenderás los lenguajes que los desarrolladores utilizan para construir páginas web: HTML (lenguaje de marcado de hipertexto) para el contenido, y CSS (Hojas de estilo en cascada) para el diseño.", "Primero, crearás una aplicación de fotos de gatos para aprender los conceptos básicos de HTML y CSS. Más adelante, aprenderá técnicas modernas como variables CSS mediante la construcción de un pingüino, y las mejores prácticas para la accesibilidad mediante la construcción de un formulario web.", "Finalmente, aprenderás cómo hacer páginas web que respondan a diferentes tamaños de pantalla construyendo una tarjeta de Twitter con Flexbox, y un diseño complejo de blog con CSS Grid." ], @@ -37,9 +37,9 @@ ] }, "responsive-web-design-principles": { - "title": "Principios de diseño web responsivo", + "title": "Principios de diseño web adaptativo", "intro": [ - "Hay muchos dispositivos que pueden acceder a la web, y vienen en todas las formas y tamaños. El diseño web responsivo es la práctica de diseñar sitios web flexibles que pueden responder a diferentes tamaños de pantalla, orientaciones y resoluciones.", + "Hay muchos dispositivos que pueden acceder a la web, y vienen en todas las formas y tamaños. El diseño web adaptativo es la práctica de diseñar sitios web flexibles que pueden responder a diferentes tamaños de pantalla, orientaciones y resoluciones.", "En este curso, aprenderás a usar CSS para que tus páginas web luzcan bien, sin importar en qué dispositivo se vean." ] }, @@ -61,15 +61,15 @@ "title": "Proyectos de diseño web responsivo", "intro": [ "Es hora de poner tus habilidades recién aprendidas a funcionar. Al trabajar en estos proyectos, tendrás la oportunidad de aplicar todas las habilidades, principios y conceptos que has aprendido hasta ahora: HTML, CSS, diseño visual, accesibilidad y más.", - "Completa los cinco proyectos de programación web de abajo para obtener tu certificación de diseño web responsivo." + "Completa los cinco proyectos de programación web de abajo para obtener tu certificación de diseño web adaptativo." ] } } }, "2022/responsive-web-design": { - "title": "(Nuevo) Diseño Web Responsivo", + "title": "(Nuevo) Diseño Web Adaptativo", "intro": [ - "En esta certificación de Diseño Web Responsivo, aprenderás los lenguajes que los desarrolladores usan para construir páginas web: HTML (Lenguaje de Marcado de Hipertexto) para el contenido, y CSS (hojas de estilo en cascada) para el diseño.", + "En esta certificación de Diseño Web Adaptativo, aprenderás los lenguajes que los desarrolladores usan para construir páginas web: HTML (Lenguaje de Marcado de Hipertexto) para el contenido, y CSS (hojas de estilo en cascada) para el diseño.", "Primero, crearás una aplicación de fotos de gatos para aprender los conceptos básicos de HTML y CSS. Más adelante, aprenderás técnicas modernas como variables CSS, mediante la construcción de un pingüino, y las mejores prácticas para la accesibilidad mediante la construcción de un sitio de cuestionarios.", "Por último, aprenderás cómo hacer páginas web que respondan a diferentes tamaños de pantalla, mediante la construcción de una galería de fotos con Flexbox, y un diseño de artículos de revista con CSS Grid." ], @@ -159,17 +159,17 @@ ] }, "learn-responsive-web-design-by-building-a-piano": { - "title": "Aprende diseño web adaptable construyendo un piano", + "title": "Aprende diseño web adaptativo construyendo un piano", "intro": [ - "El diseño web adaptable dice a tu página como debe verse en pantallas de diferentes tamaños.", - "En este curso, usarás CSS y Diseño Responsivo para programar un piano. También aprenderás más sobre las consultas de medios y pseudoselectores." + "El diseño adaptativo indica a tu página web cómo debe verse en pantallas de distintos tamaños.", + "En este curso, usarás CSS y Diseño Adaptativo para programar un piano. También aprenderás más sobre las consultas de medios y pseudoselectores." ] }, "learn-css-flexbox-by-building-a-photo-gallery": { "title": "Aprende CSS Flexbox construyendo una galería de fotos", "intro": [ "Flexbox te ayuda a diseñar tu página web para que se vea bien en cualquier tamaño de pantalla.", - "En este curso, usarás Flexbox para crear una página web de una galería de fotos receptiva." + "En este curso, usarás Flexbox para crear una página web de una galería de fotos adaptativa." ] }, "learn-css-grid-by-building-a-magazine": { @@ -180,7 +180,7 @@ ] }, "learn-typography-by-building-a-nutrition-label": { - "title": "Aprende tipografias compilando una etiqueta nutricional", + "title": "Aprende tipografía construyendo una etiqueta de nutrición", "intro": [ "La tipografía es el arte de diseñar tu texto haciéndolo de fácil lectura y adaptado a su propósito.", "En este curso, usarás tipografía para compilar una página web de etiqueta. Aprenderás cómo estilizar el texto, ajustar altura de línea y la posición de tu texto usando CSS." @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "Aprende programación funcional construyendo una hoja de cálculo", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Learn Advanced Array Methods by Building a Statistics Calculator", + "intro": ["", ""] } } }, @@ -350,8 +354,8 @@ "bootstrap": { "title": "Bootstrap", "intro": [ - "Bootstrap es un framework de la interfaz utilizado para diseñar páginas y aplicaciones web. Tiene un enfoque de desarrollo web centrado en los dispositivos móviles e incluye estilos y clases CSS pre-configurados, además de algunas funciones de JavaScript.", - "En este curso, aprenderás cómo crear sitios web responsivos con Bootstrap, y utilizarás sus clases incluidas para estilizar botones, imágenes, formularios, navegación y otros elementos." + "Bootstrap es un framework front end que se utiliza para diseñar páginas y aplicaciones web adaptativas. Tiene un enfoque de desarrollo web e incluye estilos y clases CSS predefinidos, además de algunas funcionalidades de JavaScript.", + "En este curso, aprenderás cómo crear sitios web adaptativos con Bootstrap, y utilizarás sus clases incluidas para estilizar botones, imágenes, formularios, navegación y otros elementos." ] }, "jquery": { @@ -553,7 +557,7 @@ "intro": [ "Hasta este punto, solo has usado JavaScript en la parte de front-end para agregar interactividad a una página, resolver los desafíos de algoritmos o construir un SPA. Pero JavaScript también se puede utilizar en el back-end, o servidor, para construir aplicaciones web completas.", "Hoy en día, una de las formas populares para construir aplicaciones es a través de microservicios, que son pequeñas aplicaciones modulares que trabajan juntas para formar una aplicación más grande.", - "En la Certificación Desarrollo de Back End y APIs, aprenderás cómo escribir aplicaciones de back-end con Node.js y npm (Node Package Manager). También construirás aplicaciones web con el framework Express, y un microservicio \"People Finder\" con MongoDB y la biblioteca Mongoose." + "In the Back End Development and APIs Certification, you'll learn how to write back end apps with Node.js and npm. You'll also build web applications with the Express framework, and build a People Finder microservice with MongoDB and the Mongoose library." ], "note": "", "blocks": { @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "The Odin Project", + "intro": [ + "The Odin Project is one of those \"What I wish I had when I was learning\" resources. ", + "Not everyone has access to a computer science education or the funds to attend an intensive coding school and neither of those is right for everyone anyway.", + "This project is designed to fill in the gap for people who are trying to hack it on their own but still want a high quality education." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Learn HTML Foundations", + "intro": ["A description is to be determined"] + }, + "top-build-a-recipe-project": { + "title": "Learn HTML Foundations by Building a Recipe Page", + "intro": ["A description is to be determined"] + } + } + }, "misc-text": { "certification": "Certificación de {{cert}}", "browse-other": "Navega por nuestras otras certificaciones gratuitas\n(recomendamos hacerlo en orden)", @@ -797,7 +819,7 @@ "legacy-header": "Cursos Antiguos", "legacy-desc": "Estos cursos ya no forman parte de la ruta de certificación, pero todavía están disponibles para tu aprendizaje.", "legacy-go-back": "Ve a la versión actual del plan de estudios.", - "new-rwd-desc": "Hemos actualizado nuestro plan de estudios de diseño web responsivo. Si anteriormente estabas trabajando en el plan de estudios de diseño web responsivo, ¡tu progreso sigue guardado! Puedes encontrarlo en la sección diseño web responsivo legado.", + "new-rwd-desc": "Hemos actualizado nuestro plan de estudios de diseño web adaptativo. Si anteriormente estabas trabajando en el plan de estudios de diseño web adaptativo, ¡tu progreso sigue guardado! Puedes encontrarlo en la sección diseño web adaptativo legado.", "new-rwd-article": "Te animamos a leer sobre los cambios que hicimos y considerar explorar el plan de estudios actualizado.", "viewing-upcoming-change": "Estás viendo una página beta. ", "go-back-to-learn": "Volver a la versión estable del currículum.", diff --git a/client/i18n/locales/espanol/translations.json b/client/i18n/locales/espanol/translations.json index 90596ce7450b85..57ffea1192ed22 100644 --- a/client/i18n/locales/espanol/translations.json +++ b/client/i18n/locales/espanol/translations.json @@ -11,11 +11,12 @@ "view": "Ver", "view-code": "Mostrar Código", "view-project": "Mostrar Proyecto", + "view-cert-title": "Ver {{certTitle}}", "show-cert": "Mostrar certificación", "claim-cert": "Solicitar certificación", "save-progress": "Guardar progreso", "accepted-honesty": "Has aceptado nuestra Política de Honestidad Académica.", - "agree": "Aceptar", + "agree-honesty": "Estoy de acuerdo con la Política de Honestidad Académica de freeCodeCamp.", "save-portfolio": "Guardar este elemento de portafolio", "remove-portfolio": "Eliminar este elemento de portafolio", "add-portfolio": "Agregar un nuevo elemento de portafolio", @@ -52,7 +53,7 @@ "check-code": "Comprueba tu código (Ctrl + Enter)", "check-code-2": "Comprueba tu código", "reset": "Restablecer", - "reset-code": "Restablecer todo el código", + "reset-step": "Restablecer este paso", "help": "Ayuda", "get-help": "Obtener ayuda", "watch-video": "Ver un Video", @@ -157,7 +158,8 @@ "honesty": "Política de Honestidad Académica", "internet": "Tu presencia en Internet", "portfolio": "Ajustes de portafolio", - "privacy": "Ajustes de privacidad" + "privacy": "Ajustes de privacidad", + "personal-info": "Información Personal" }, "danger": { "heading": "Zona de peligro", @@ -222,16 +224,15 @@ "total-points_plural": "{{count}} puntos en total", "points": "{{count}} punto en {{date}}", "points_plural": "{{count}} puntos en {{date}}", - "screen-shot": "Una captura de pantalla de {{title}}", "page-number": "{{pageNumber}} de {{totalPages}}" }, "footer": { - "tax-exempt-status": "freeCodeCamp es una organización sin fines de lucro exenta de impuestos 501(c)(3) respaldada por donantes (Número de identificación fiscal federal de los Estados Unidos: 82-0779546)", + "tax-exempt-status": "freeCodeCamp es una organización benéfica 501(c)(3) exenta de impuestos apoyada por donantes (Número de Identificación Fiscal Federal De Los Estados Unidos: 82-0779546)", "mission-statement": "Nuestra misión: ayudar a las personas a aprender a programar de forma gratuita. Logramos esto mediante la creación de miles de videos, artículos y lecciones de programación interactivas, todos disponibles gratuitamente para el público. También tenemos miles de grupos de estudio de FreeCodeCamp en todo el mundo.", "donation-initiatives": "Las donaciones a freeCodeCamp se destinan a nuestras iniciativas educativas y ayudan a pagar los servidores, los servicios y el personal.", "donate-text": "Puedes <1>hacer una donación deducible de impuestos aquí.", "trending-guides": "Guías de tendencias", - "our-nonprofit": "Nuestra organización sin fines de lucro", + "our-nonprofit": "Nuestra Caridad", "links": { "about": "Acerca de", "alumni": "Red de ex-Alumnos", @@ -249,6 +250,7 @@ }, "learn": { "heading": "Bienvenido al currículo de freeCodeCamp.", + "skip-to-content": "Skip to content", "welcome-1": "Bienvenido de nuevo, {{name}}.", "welcome-2": "Bienvenido a freeCodeCamp.org", "start-at-beginning": "Si eres nuevo en la programación, te recomendamos <0>comenzar desde el principio.", @@ -264,7 +266,7 @@ "p8": "Y este currículo te brindará miles de horas de práctica de programación.", "p9": "Y si deseas aprender más sobre matemáticas y teoría de la informática, también tenemos miles de horas de cursos en video en <0>el canal de YouTube de freeCodeCamp.", "p10": "Si deseas obtener un trabajo de desarrollador o clientes independientes, las habilidades de programación serán solo una parte del rompecabezas. También necesitas construir tu red personal y tu reputación como desarrollador.", - "p11": "You can do this on LinkedIn and GitHub, and also on <0>the freeCodeCamp forum.", + "p11": "Puedes hacer esto en LinkedIn y GitHub, y también en <0>el foro freeCodeCamp.", "p12": "¡Feliz día programando!" }, "upcoming-lessons": "Próximas lecciones", @@ -272,6 +274,9 @@ "add-subtitles": "Ayudar a mejorar o agregar subtítulos", "wrong-answer": "Lo siento, esa no es la respuesta correcta. ¡Vuelve a intentarlo!", "check-answer": "Haz clic en el botón de abajo para verificar tu respuesta.", + "assignment-not-complete": "Por favor, completa las tareas", + "assignments": "Asignaciones", + "question": "Pregunta", "solution-link": "Enlace a la solución", "github-link": "Enlace de GitHub", "submit-and-go": "Enviar y pasar a mi siguiente desafío", @@ -297,7 +302,6 @@ "certs": "Certificación {{title}}" }, "editor-tabs": { - "info": "Info", "code": "Código", "tests": "Pruebas", "restart": "Reiniciar", @@ -307,6 +311,10 @@ "notes": "Notas", "preview": "Vista" }, + "editor-alerts": { + "tab-trapped": "Presionando la pestaña insertará el carácter de la pestaña", + "tab-free": "Presionando la pestaña ahora se moverá el foco al siguiente elemento enfocable" + }, "help-translate": "Todavía estamos traduciendo las siguientes certificaciones.", "help-translate-link": "Ayúdanos a traducir.", "project-preview-title": "Aquí hay una vista previa de lo que construirás", @@ -326,13 +334,13 @@ "sorry-hang-in-there": "Lo sentimos, su código no pasa. Aguanta ahí.", "sorry-dont-giveup": "Lo sentimos, su código no pasa. No te rindas.", "challenges-completed": "{{completedCount}} de {{totalChallenges}} desafíos completados", - "season-greetings-fcc": "Season's Greetings from the freeCodeCamp community 🎉", - "if-getting-value": "If you're getting a lot out of freeCodeCamp, now is a great time to donate to support our nonprofit's mission.", - "building-a-university": "We're Building a Free Computer Science University Degree Program", - "if-help-university": "We've already made a ton of progress. Support our charity with the long road ahead." + "season-greetings-fcc": "Saludos de Temporada de la comunidad freeCodeCamp 🎉", + "if-getting-value": "Si estás obteniendo mucho de freeCodeCamp, ahora es un buen momento para donar con el fin de apoyar nuestra misión sin fines de lucro.", + "building-a-university": "Estamos construyendo un programa gratuito de grado universitario en ciencias de la computación", + "if-help-university": "Ya hemos hecho un montón de progresos. Apoyamos nuestra caridad con el largo camino por delante." }, "donate": { - "title": "Apoya a nuestra organización sin fines de lucro", + "title": "Apoya nuestra caridad", "processing": "Estamos procesando tu donación.", "redirecting": "Redirigiendo...", "thanks": "Gracias por donar", @@ -354,11 +362,10 @@ "your-donation": "Tu donación de ${{usd}} proporcionará {{hours}} horas de aprendizaje a personas de todo el mundo.", "your-donation-2": "Tu donación de ${{usd}} proporcionará {{hours}} horas de aprendizaje a personas de todo el mundo cada mes.", "your-donation-3": "Tu donación de ${{usd}} proporcionará {{hours}} horas de aprendizaje a personas de todo el mundo cada año.", - "become-supporter": "Become a Supporter", - "duration": "Conviértete en un contribuyente único de nuestra organización sin fines de lucro.", - "duration-2": "Conviértete en un contribuyente mensual de nuestra organización sin fines de lucro.", - "duration-3": "Conviértete en un contribuyente anual de nuestra organización sin fines de lucro", - "duration-4": "Conviértete en un contribuyente de nuestra organización sin fines de lucro", + "become-supporter": "Conviértete en un colaborador", + "duration": "Se un benefactor de nuestra organización benéfica con una donación única.", + "duration-2": "Se un benefactor mensual de nuestra organización benéfica.", + "duration-4": "Se un benefactor de nuestra organización benéfica", "nicely-done": "Bien hecho. Acabas de completar {{block}}.", "credit-card": "Tarjeta de crédito", "credit-card-2": "O dona con una tarjeta de crédito:", @@ -372,25 +379,25 @@ "email-receipt": "Correo electrónico (te enviaremos un recibo de donación deducible de impuestos):", "need-help": "¿Necesitas ayuda con tus donaciones actuales o pasadas?", "forward-receipt": "Envía una copia de tu recibo de donación a donors@freecodecamp.org y dinos cómo podemos ayudar.", - "efficiency": "freeCodeCamp es una organización educativa sin fines de lucro altamente eficiente.", + "efficiency": "freeCodeCamp es una organización benéfica educativa de gran eficacia.", "why-donate-1": "Cuando donas a freeCodeCamp, ayudas a las personas a aprender nuevas habilidades y proveer para sus familias", "why-donate-2": "También nos ayudas a crear nuevos recursos para que los utilices y amplíes tus propias habilidades tecnológicas.", "bigger-donation": "¿Quieres hacer una donación más grande de una sola vez, envíanos un cheque o da de otras maneras?", - "other-ways": "Aquí hay muchas <0>otras formas en las que puedes apoyar la misión de nuestra organización sin fines de lucro.", + "other-ways": "Aquí hay muchas <0>otras formas de apoyar la misión de nuestra organización benéfica.", "failed-pay": "Oh no. Parece que tu transacción no se realizó. ¿Podrías intentarlo de nuevo?", "try-again": "Por favor, intenta de nuevo.", "card-number": "Tu número de tarjeta:", "expiration": "Fecha de vencimiento:", "secure-donation": "Donación segura", "faq": "Preguntas frecuentes", - "only-you": "Solo tú puedes ver este mensaje. Felicitaciones por obtener esta certificación. No es una tarea fácil. Operar freeCodeCamp tampoco es fácil. Ni es barato. Ayúdanos a ayudarte a ti y a muchas otras personas en todo el mundo. Haz una donación de apoyo deducible de impuestos a nuestra organización sin fines de lucro hoy.", + "only-you": "Sólo tu puedes ver este mensaje. Enhorabuena por haber obtenido esta certificación. No es tarea fácil. Administrar freeCodeCamp tampoco es fácil. Tampoco es barato. Ayúdanos a ayudarte a ti y a muchas otras personas de todo el mundo. Haz hoy una donación deducible de impuestos a nuestra organización benéfica.", "get-help": "¿Cómo puedo obtener ayuda con mis donaciones?", "how-transparent": "¿Qué tan transparente es freeCodeCamp.org?", "very-transparent": "Muy Transparente. Tenemos una valoración de transparencia de platino en GuideStar.org.", "download-irs": "Puedes <0>descargar nuestra Carta de Determinación de IRS aquí.", "download-990": "Puedes <0>descargar nuestro 990 más reciente (informe anual de impuestos) aquí.", "how-efficient": "¿Qué tan eficiente es freeCodeCamp?", - "fcc-budget": "El presupuesto de freeCodeCamp es mucho más pequeño que la mayoría de las organizaciones sin fines de lucro comparables. No hemos traído recaudadores de fondos profesionales. En lugar de eso, Quincy hace todo él mismo.", + "fcc-budget": "El presupuesto de freeCodeCamp es mucho menor que el de la mayoría de organizaciones benéficas comparables. No hemos contratado a profesionales para recaudar fondos. En su lugar, Quincy lo hace todo él mismo.", "help-millions": "Sin embargo, con un presupuesto de tan sólo unos cientos de miles de dólares al año, hemos podido ayudar a millones de personas.", "how-one-time": "¿Cómo puedo realizar una donación única?", "one-time": "Si prefieres hacer donaciones únicas, puedes apoyar la misión de freeCodeCamp cuando tengas dinero suficiente para hacer una aportación. Puedes usar <0>este enlace para donar cualquier cantidad que te sea cómodo a través de PayPal.", @@ -400,7 +407,7 @@ "can-check": "¿Puedo enviar un cheque físico?", "yes-check": "Sí, bienvenido sea, aceptamos cheque. Puedes enviarlo a:", "how-matching-gift": "¿Cómo puedo configurar regalos coincidentes de mi empleador o deducciones de nómina?", - "employers-vary": "Esto varía de un empleador a otro, y nuestra organización sin fines de lucro ya se encuentra en muchas de las bases de datos que se ajustan a las grandes donaciones.", + "employers-vary": "This varies from employer to employer, and our charity is already listed in many of the big donation-matching databases.", "some-volunteer": "Algunas personas tienen la posibilidad de ser voluntarias para freeCodeCamp y su empleador iguala al donar una cantidad fija por hora que ofrecen como voluntarios. Otros empleadores igualan cualquier donación que los donantes hagan hasta una cierta cantidad", "help-matching-gift": "Si necesitas ayuda con esto, por favor envía un correo electrónico a Quincy directamente: quincy@freecodecamp.org", "how-endowment": "¿Cómo puedo hacer un regalo de dotación a freeCodeCamp.org?", @@ -411,13 +418,13 @@ "thank-wikimedia": "Nos gustaría dar las gracias a la Fundación Wikimedia por proporcionar este lenguaje formal para que podamos utilizarlo.", "legacy-gift-questions": "Si tienes alguna pregunta sobre este proceso, por favor envía un correo electrónico a Quincy@freecodecamp.org.", "how-stock": "¿Cómo puedo donar acciones a freeCodeCamp.org?", - "welcome-stock": "Agradeceríamos tus donaciones de acciones. Por favor envía un correo electrónico a Quincy directamente y él puede ayudarte con esto, y compartir los detalles de nuestra cuenta de corretaje sin fines de lucro: quincy@freecodecamp.org.", + "welcome-stock": "We would welcome your stock donations. Please email Quincy directly and he can help you with this, and share our charity's brokerage account details: quincy@freecodecamp.org.", "how-receipt": "¿Puedo obtener un recibo de donación para que pueda deducir mi donación de mis impuestos?", "just-forward": "Claro que sí. Solo reenvía el recibo de tu transacción a donors@freecodecamp.org, menciónanos que deseas un recibo y cualquier otra instrucción especial que puedas tener, y te contestaremos con un recibo por ti.", "how-update": "He configurado una donación mensual, pero necesito actualizar o pausar la recurrencia mensual. ¿Cómo puedo hacerlo?", "take-care-of-this": "Manda uno de tus recibos mensuales de donación a donors@freecodecamp.org y dinos lo que te gustaría que hiciéramos. Nos ocuparemos de esto y te enviaremos confirmación.", "anything-else": "¿Hay algo más que pueda aprender sobre cómo hacer una donación a freeCodeCamp.org?", - "other-support": "Si hay alguna otra forma en la que te gustaría apoyar a nuestra organización sin fines de lucro y su misión que no aparece aquí, o si tienes alguna pregunta, envía un correo electrónico a Quincy a quincy@freecodecamp.org." + "other-support": "If there is some other way you'd like to support our charity and its mission that isn't listed here, or if you have any questions at all, please email Quincy at quincy@freecodecamp.org." }, "report": { "sign-in": "Necesitas iniciar sesión para reportar a un usuario", @@ -460,7 +467,8 @@ "iframe-preview": "{{title}} Vista previa", "iframe-alert": "¡Normalmente este link te llevaría a otro sitio web! Funciona. Este es un enlace a: {{externalLink}}", "iframe-form-submit-alert": "¡Normalmente, se enviaría este formulario! Funciona. Esto se enviará a: {{externalLink}}", - "document-notfound": "documento no encontrado" + "document-notfound": "documento no encontrado", + "slow-load-msg": "Looks like this is taking longer than usual, please try refreshing the page." }, "icons": { "gold-cup": "Copa de Oro", @@ -475,10 +483,11 @@ "hint": "Sugerencia", "heart": "Corazón", "initial": "Inicial", + "input-reset": "Clear search terms", "info": "Información de introducción", "spacer": "Espaciador", "toggle": "Alternar marca de verificación", - "magnifier": "lupa" + "magnifier": "Submit search terms" }, "aria": { "fcc-curriculum": "currículo de freeCodeCamp", @@ -504,10 +513,11 @@ "step": "Paso", "steps": "Pasos", "steps-for": "Pasos para {{blockTitle}}", - "code-example": "{{codeName}} code example" + "code-example": "ejemplo de código de {{codeName}}", + "opens-new-window": "Opens in new window" }, "flash": { - "honest-first": "Para reclamar una certificación, primero debes aceptar nuestra política de honestidad académica.", + "honest-first": "To claim a certification, you must first agree to our academic honesty policy", "really-weird": "Sucedió algo realmente extraño. Si vuelve a ocurrir, considera hacer un reporte del problema en https://github.com/freeCodeCamp/freeCodeCamp/issues/new", "not-right": "Algo no está bien. Se ha generado un informe y se ha notificado al equipo de freeCodeCamp.org", "went-wrong": "Algo salió mal, verifica e intenta nuevamente", @@ -586,7 +596,8 @@ "editor-url": "Recuerda enviar la URL de Live App.", "http-url": "No se puede utilizar una URL insegura (http).", "own-work-url": "Recuerda enviar tu propio trabajo.", - "publicly-visible-url": "Recuerda enviar una URL de aplicación visible públicamente." + "publicly-visible-url": "Recuerda enviar una URL de aplicación visible públicamente.", + "path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path" }, "certification": { "executive": "Director Ejecutivo, freeCodeCamp.org", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "Clasificador de imágenes de gatos y perros", "Book Recommendation Engine using KNN": "Motor de recomendación de libros usando KNN", "Linear Regression Health Costs Calculator": "Calculadora de costos de salud por regresión lineal", - "Neural Network SMS Text Classifier": "Clasificador de textos SMS basado en redes neuronales" + "Neural Network SMS Text Classifier": "Clasificador de textos SMS basado en redes neuronales", + "Celestial Bodies Database": "Celestial Bodies Database", + "World Cup Database": "World Cup Database", + "Salon Appointment Scheduler": "Salon Appointment Scheduler", + "Periodic Table Database": "Periodic Table Database", + "Number Guessing Game": "Number Guessing Game", + "Build a freeCodeCamp Forum Homepage": "Build a freeCodeCamp Forum Homepage" } + }, + "title": { + "Responsive Web Design": "Responsive Web Design", + "responsive-web-design": "Responsive Web Design Certification", + "JavaScript Algorithms and Data Structures": "JavaScript Algorithms and Data Structures", + "javascript-algorithms-and-data-structures": "JavaScript Algorithms and Data Structures Certification", + "Front End Development Libraries": "Front End Development Libraries", + "front-end-development-libraries": "Front End Development Libraries Certification", + "Data Visualization": "Data Visualization", + "data-visualization": "Data Visualization Certification", + "Relational Database": "Relational Database", + "relational-database-v8": "Relational Database Certification", + "Back End Development and APIs": "Back End Development and APIs", + "back-end-development-and-apis": "Back End Development and APIs Certification", + "Quality Assurance": "Quality Assurance", + "quality-assurance-v7": "Quality Assurance Certification", + "Scientific Computing with Python": "Scientific Computing with Python", + "scientific-computing-with-python-v7": "Scientific Computing with Python Certification", + "Data Analysis with Python": "Data Analysis with Python", + "data-analysis-with-python-v7": "Data Analysis with Python Certification", + "Information Security": "Information Security", + "information-security-v7": "Information Security Certification", + "Machine Learning with Python": "Machine Learning with Python", + "machine-learning-with-python-v7": "Machine Learning with Python Certification", + "Legacy Front End": "Legacy Front End", + "legacy-front-end": "Front End Certification", + "Legacy Back End": "Legacy Back End", + "legacy-back-end": "Back End Certification", + "Legacy Data Visualization": "Legacy Data Visualization", + "legacy-data-visualization": "Data Visualization Certification", + "Legacy Information Security and Quality Assurance": "Legacy Information Security and Quality Assurance", + "information-security-and-quality-assurance": "Information Security and Quality Assurance Certification", + "Legacy Full Stack Certification": "Legacy Full Stack Certification", + "Legacy Full Stack": "Legacy Full Stack", + "full-stack": "Full Stack Certification" } }, "certification-card": { diff --git a/client/i18n/locales/german/intro.json b/client/i18n/locales/german/intro.json index c7337e2d451230..b23ae9ad6e77b0 100644 --- a/client/i18n/locales/german/intro.json +++ b/client/i18n/locales/german/intro.json @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "Lerne die funktionale Programmierung durch das Erstellen einer Tabellenkalkulation", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Learn Advanced Array Methods by Building a Statistics Calculator", + "intro": ["", ""] } } }, @@ -553,7 +557,7 @@ "intro": [ "Bis zu diesem Punkt hast du JavaScript nur im Front-End verwendet, um einer Seite Interaktivität hinzuzufügen, Aufgaben mit Algorithmen zu lösen oder eine SPA zu bauen. Aber JavaScript kann auch im Back-End, also auf dem Server, verwendet werden, um ganze Webanwendungen zu erstellen.", "Heutzutage ist eine der beliebtesten Arten, Anwendungen zu erstellen, Microservices. Das sind kleine, modulare Anwendungen, die zusammenarbeiten und ein größeres Ganzes bilden.", - "In der Zertifizierung für Back-End-Entwicklung und APIs lernst du, wie du Back-End-Apps mit Node.js und npm (Node Package Manager) schreibst. Du wirst auch Webanwendungen mit dem Express-Framework erstellen und einen Personensuche-Microservice mit MongoDB und der Mongoose-Bibliothek bauen." + "In the Back End Development and APIs Certification, you'll learn how to write back end apps with Node.js and npm. You'll also build web applications with the Express framework, and build a People Finder microservice with MongoDB and the Mongoose library." ], "note": "", "blocks": { @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "The Odin Project", + "intro": [ + "The Odin Project is one of those \"What I wish I had when I was learning\" resources. ", + "Not everyone has access to a computer science education or the funds to attend an intensive coding school and neither of those is right for everyone anyway.", + "This project is designed to fill in the gap for people who are trying to hack it on their own but still want a high quality education." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Learn HTML Foundations", + "intro": ["A description is to be determined"] + }, + "top-build-a-recipe-project": { + "title": "Learn HTML Foundations by Building a Recipe Page", + "intro": ["A description is to be determined"] + } + } + }, "misc-text": { "certification": "{{cert}} Zertifikat", "browse-other": "Stöbere in unseren anderen kostenlosen Zertifizierungen\n(Wir empfehlen, diese der Reihe nach zu erledigen)", diff --git a/client/i18n/locales/german/translations.json b/client/i18n/locales/german/translations.json index 3b59be781e9e2a..0aa7823c328f31 100644 --- a/client/i18n/locales/german/translations.json +++ b/client/i18n/locales/german/translations.json @@ -11,11 +11,12 @@ "view": "Anzeigen", "view-code": "Code anschauen", "view-project": "Projekt anschauen", + "view-cert-title": "View {{certTitle}}", "show-cert": "Zertifikat anzeigen", "claim-cert": "Zertifizierung anfordern", "save-progress": "Fortschritt speichern", - "accepted-honesty": "Du hast unsere Akademische Ehrlichkeitsrichtlinie akzeptiert.", - "agree": "Zustimmen", + "accepted-honesty": "You have agreed to our Academic Honesty Policy.", + "agree-honesty": "I agree to freeCodeCamp's Academic Honesty Policy.", "save-portfolio": "Dieses Portfolioelement speichern", "remove-portfolio": "Dieses Portfolioelement entfernen", "add-portfolio": "Neues Portfolioelement hinzufügen", @@ -52,7 +53,7 @@ "check-code": "Überprüfe deinen Code (Strg + Enter)", "check-code-2": "Prüfe deinen Code", "reset": "Zurücksetzen", - "reset-code": "Den Quellcode zurücksetzen", + "reset-step": "Reset This Step", "help": "Hilfe", "get-help": "Hilfe bekommen", "watch-video": "Ein Video ansehen", @@ -157,7 +158,8 @@ "honesty": "Akademischer Ehrlichkeitskodex", "internet": "Dein Internetauftritt", "portfolio": "Portfolio-Einstellungen", - "privacy": "Privatsphäre-Einstellungen" + "privacy": "Privatsphäre-Einstellungen", + "personal-info": "Personal Information" }, "danger": { "heading": "Gefahrenzone", @@ -222,16 +224,15 @@ "total-points_plural": "{{count}} Gesamtpunkte", "points": "{{count}} Punkt am {{date}}", "points_plural": "{{count}} Punkte am {{date}}", - "screen-shot": "Eine Bildschirmaufnahme von {{title}}", "page-number": "{{pageNumber}} von {{totalPages}}" }, "footer": { - "tax-exempt-status": "freeCodeCamp ist eine von Spendern unterstützte steuerbefreite gemeinnützige Organisation gemäß 501(c)(3) (US-Steueridentifikationsnummer: 82-0779546)", + "tax-exempt-status": "freeCodeCamp is a donor-supported tax-exempt 501(c)(3) charitable organization (United States Federal Tax Identification Number: 82-0779546)", "mission-statement": "Unsere Mission: Menschen dabei zu helfen, kostenlos zu programmieren. Dies erreichen wir, indem wir Tausende von Videos, Artikeln und interaktiven Programmierstunden erstellen, die der Öffentlichkeit frei zugänglich sind. Wir haben auch Tausende von freeCodeCamp-Lerngruppen auf der ganzen Welt.", "donation-initiatives": "Spenden an das freeCodeCamp fließen in unsere Bildungsinitiativen und helfen, Server, Dienstleistungen und Mitarbeiter zu bezahlen.", "donate-text": "Du kannst <1>hier eine steuerlich absetzbare Spende tätigen.", "trending-guides": "Beliebte Guides", - "our-nonprofit": "Unser Non-Profit", + "our-nonprofit": "Our Charity", "links": { "about": "Über", "alumni": "Alumni-Netzwerk", @@ -249,6 +250,7 @@ }, "learn": { "heading": "Willkommen zum Studienplan von freeCodeCamp.", + "skip-to-content": "Skip to content", "welcome-1": "Willkommen zurück, {{name}}.", "welcome-2": "Willkommen auf freeCodeCamp.org", "start-at-beginning": "Wenn Programmieren ganz neu für dich ist, schlagen wir vor, <0>am Anfang zu beginnen.", @@ -272,6 +274,9 @@ "add-subtitles": "Hilf mit Untertitel hinzuzufügen oder zu verbessern", "wrong-answer": "Sorry, das ist nicht die richtige Antwort. Möchtest du noch einen Anlauf wagen?", "check-answer": "Klick unten auf den Button, um deine Antwort zu überprüfen.", + "assignment-not-complete": "Please finish the assignments", + "assignments": "Assignments", + "question": "Question", "solution-link": "Lösungs-Link", "github-link": "GitHub Link", "submit-and-go": "Absenden und zur nächsten Herausforderung gehen", @@ -297,7 +302,6 @@ "certs": "{{title}} Zertifizierung" }, "editor-tabs": { - "info": "Informationen", "code": "Code", "tests": "Tests", "restart": "Neustart", @@ -307,6 +311,10 @@ "notes": "Hinweise", "preview": "Vorschau" }, + "editor-alerts": { + "tab-trapped": "Pressing tab will now insert the tab character", + "tab-free": "Pressing tab will now move focus to the next focusable element" + }, "help-translate": "Wir übersetzen noch die folgenden Zertifikate.", "help-translate-link": "Hilf uns, zu übersetzen.", "project-preview-title": "Hier ist eine Vorschau auf das, was du erstellen wirst", @@ -327,15 +335,15 @@ "sorry-dont-giveup": "Tut mir leid, dein Code funktioniert nicht. Gib nicht auf.", "challenges-completed": "{{completedCount}} von {{totalChallenges}} Herausforderungen erfüllt", "season-greetings-fcc": "Season's Greetings from the freeCodeCamp community 🎉", - "if-getting-value": "If you're getting a lot out of freeCodeCamp, now is a great time to donate to support our nonprofit's mission.", + "if-getting-value": "If you're getting a lot out of freeCodeCamp, now is a great time to donate to support our charity's mission.", "building-a-university": "We're Building a Free Computer Science University Degree Program", "if-help-university": "We've already made a ton of progress. Support our charity with the long road ahead." }, "donate": { - "title": "Unterstütze unsere Non-Profit-Organisation", + "title": "Support our charity", "processing": "Wir bearbeiten deine Spende.", "redirecting": "Weiterleiten...", - "thanks": "Vielen Dank für die Spende", + "thanks": "Thanks for donating", "thank-you": "Vielen Dank für deine Unterstützung.", "additional": "Du kannst eine zusätzliche einmalige Spende in beliebiger Höhe über diesen Link tätigen: <0>{{url}}", "help-more": "Hilf uns, mehr zu tun", @@ -355,10 +363,9 @@ "your-donation-2": "Deine ${{usd}} Spende wird jeden Monat {{hours}} Stunden des Lernens für Menschen auf der ganzen Welt ermöglichen.", "your-donation-3": "Deine ${{usd}} Spende wird jedes Jahr {{hours}} Stunden des Lernens für Menschen auf der ganzen Welt ermöglichen.", "become-supporter": "Become a Supporter", - "duration": "Werde ein einmaliger Unterstützer für unsere gemeinnützigen Organisation.", - "duration-2": "Werde ein monatlicher Unterstützer für unsere gemeinnützigen Organisation.", - "duration-3": "Werde ein jährlicher Unterstützer für unsere gemeinnützigen Organisation", - "duration-4": "Werde ein Unterstützer für unsere gemeinnützigen Organisation", + "duration": "Become a one-time supporter of our charity.", + "duration-2": "Become a monthly supporter of our charity.", + "duration-4": "Become a supporter of our charity", "nicely-done": "Großartig. Du hast soeben {{block}} abgeschlossen.", "credit-card": "Kreditkarte", "credit-card-2": "Oder spende mit einer Kreditkarte:", @@ -372,25 +379,25 @@ "email-receipt": "E-Mail (wir schicken dir eine steuerlich absetzbare Spendenquittung):", "need-help": "Brauchst du Hilfe bei deinen aktuellen oder vergangenen Spenden?", "forward-receipt": "Sende uns eine Kopie deiner Spendenbescheinigung an donors@freecodecamp.org und lass uns wissen, wie wir dir helfen können.", - "efficiency": "freeCodeCamp ist eine hocheffiziente, gemeinnützige Bildungsorganisation.", + "efficiency": "freeCodeCamp is a highly efficient education charity.", "why-donate-1": "Wenn du für freeCodeCamp spendest, hilfst du Menschen, neue Fähigkeiten zu erlernen und ihre Familien zu versorgen.", "why-donate-2": "Du hilfst uns auch neue Angebote zu schaffen, die du selbst nutzen kannst, um deine technischen Fähigkeiten zu erweitern.", "bigger-donation": "Möchtest du eine größere einmalige Spende tätigen, uns einen Scheck schicken oder auf andere Weise spenden?", - "other-ways": "Hier sind viele <0>andere Möglichkeiten, wie du die Mission unserer gemeinnützigen Organisation unterstützen kannst.", + "other-ways": "Here are many <0>other ways you can support our charity's mission.", "failed-pay": "Oh - oh. Es sieht so aus, als ob deine Transaktion nicht durchgeführt werden konnte. Kannst du es bitte noch einmal versuchen?", "try-again": "Bitte versuche es erneut.", "card-number": "Deine Kartennummer:", "expiration": "Ablaufdatum:", "secure-donation": "Sichere Spende", "faq": "Häufig gestellte Fragen", - "only-you": "Nur du kannst diese Nachricht sehen. Herzlichen Glückwunsch zum Erhalt dieses Zertifikats. Es ist keine leichte Aufgabe. Das freeCodeCamp zu leiten, ist auch nicht einfach. Und billig ist es auch nicht. Hilf uns, dir und vielen anderen Menschen auf der ganzen Welt zu helfen. Sende noch heute eine steuerlich absetzbare Spende an unsere gemeinnützige Organisation.", + "only-you": "Only you can see this message. Congratulations on earning this certification. It's no easy task. Running freeCodeCamp isn't easy either. Nor is it cheap. Help us help you and many other people around the world. Make a tax-deductible supporting donation to our charity today.", "get-help": "Wie kann ich Hilfe für meine Spenden bekommen?", "how-transparent": "Wie transparent ist freeCodeCamp.org?", "very-transparent": "Sehr. Wir haben eine Platin-Transparenzbewertung von GuideStar.org.", "download-irs": "Du kannst <0>unseren Feststellungsbescheid der IRS hier herunterladen.", "download-990": "Du kannst <0>hier unseren letzten 990 (Jahressteuerbericht) herunterladen.", "how-efficient": "Wie effizient ist das freeCodeCamp?", - "fcc-budget": "Das Budget von freeCodeCamp ist viel kleiner als das der meisten vergleichbaren gemeinnützigen Organisationen. Wir haben keine professionellen Geldbeschaffer eingestellt. Stattdessen macht Quincy alles selbst.", + "fcc-budget": "freeCodeCamp's budget is much smaller than most comparable charity. We haven't brought in professional fundraisers. Instead, Quincy does everything himself.", "help-millions": "Doch mit einem Budget von nur ein paar hunderttausend Dollar pro Jahr konnten wir Millionen von Menschen helfen.", "how-one-time": "Wie kann ich eine einmalige Spende leisten?", "one-time": "Wenn du lieber einmalig spenden möchtest, kannst du die Mission von freeCodeCamp unterstützen, wann immer du Geld übrig hast. Du kannst <0>diesen Link benutzen, um einen beliebigen Betrag über PayPal zu spenden.", @@ -400,7 +407,7 @@ "can-check": "Kann ich einen Scheck per Post schicken?", "yes-check": "Ja, wir würden uns über einen Scheck freuen. Du kannst ihn per Post an uns schicken:", "how-matching-gift": "Wie kann ich die gleiche Spende von meinem Arbeitgeber erhalten oder von der Gehaltsabrechnung abziehen lassen?", - "employers-vary": "Das ist von Arbeitgeber zu Arbeitgeber unterschiedlich, und unsere gemeinnützige Organisation ist bereits in vielen der großen Spenden-Datenbanken gelistet.", + "employers-vary": "This varies from employer to employer, and our charity is already listed in many of the big donation-matching databases.", "some-volunteer": "Manche Menschen können sich bei freeCodeCamp freiwillig engagieren und ihr Arbeitgeber spendet einen festen Betrag pro Stunde, in der sie sich freiwillig engagieren. Andere Arbeitgeber verdoppeln die Spenden der Spender bis zu einem bestimmten Betrag", "help-matching-gift": "Wenn du dabei Hilfe brauchst, schreibe Quincy bitte direkt eine E-Mail: quincy@freecodecamp.org", "how-endowment": "Wie kann ich freeCodeCamp.org eine Spende zukommen lassen?", @@ -411,13 +418,13 @@ "thank-wikimedia": "Wir möchten uns bei der Wikimedia Foundation dafür bedanken, dass sie uns diese formelle Formulierung zur Verfügung gestellt hat.", "legacy-gift-questions": "Wenn du Fragen zu diesem Verfahren hast, schreibe bitte eine E-Mail an Quincy unter quincy@freecodecamp.org.", "how-stock": "Wie kann ich Aktien für freeCodeCamp.org spenden?", - "welcome-stock": "Wir nehmen deine Aktienspenden gerne entgegen. Schreib Quincy direkt eine E-Mail und er kann dir dabei helfen und dir die Details unseres gemeinnützigen Maklerkontos mitteilen: quincy@freecodecamp.org.", + "welcome-stock": "We would welcome your stock donations. Please email Quincy directly and he can help you with this, and share our charity's brokerage account details: quincy@freecodecamp.org.", "how-receipt": "Kann ich eine Spendenbescheinigung bekommen, damit ich meine Spende von der Steuer absetzen kann?", "just-forward": "Ja, natürlich. Schicke einfach die Quittung deiner Transaktion an donors@freecodecamp.org, sag uns, dass du eine Quittung möchtest und welche besonderen Anweisungen du hast, und wir schicken dir eine Quittung zu.", "how-update": "Ich habe eine monatliche Spende eingerichtet, aber ich muss die monatliche Zahlung aktualisieren oder aussetzen. Wie kann ich das tun?", "take-care-of-this": "Schicke einfach eine deiner monatlichen Spendenquittungen an donors@freecodecamp.org und sag uns, was wir für dich tun sollen. Wir erledigen das für dich und schicken dir eine Bestätigung.", "anything-else": "Gibt es noch etwas, was ich über das Spenden an freeCodeCamp.org erfahren kann?", - "other-support": "Wenn es eine andere Möglichkeit gibt, unsere gemeinnützige Organisation zu unterstützen, die hier nicht aufgeführt ist, oder wenn du Fragen hast, schreibe bitte eine E-Mail an Quincy unter quincy@freecodecamp.org." + "other-support": "If there is some other way you'd like to support our charity and its mission that isn't listed here, or if you have any questions at all, please email Quincy at quincy@freecodecamp.org." }, "report": { "sign-in": "Du musst angemeldet sein, um einen Benutzer zu melden", @@ -460,7 +467,8 @@ "iframe-preview": "{{title}} Vorschau", "iframe-alert": "Normalerweise würde dieser Link dich auf eine andere Website führen! Er funktioniert. Dies ist ein Link zu: {{externalLink}}", "iframe-form-submit-alert": "Normalerweise würde dieses Formular übermittelt werden! Es funktioniert. Dies wird übermittelt an: {{externalLink}}", - "document-notfound": "Dokument wurde nicht gefunden" + "document-notfound": "Dokument wurde nicht gefunden", + "slow-load-msg": "Looks like this is taking longer than usual, please try refreshing the page." }, "icons": { "gold-cup": "Goldpokal", @@ -475,10 +483,11 @@ "hint": "Hinweis", "heart": "Herz", "initial": "Initial", + "input-reset": "Clear search terms", "info": "Einführungsinformationen", "spacer": "Abstandhalter", "toggle": "Häkchen umschalten", - "magnifier": "Lupe" + "magnifier": "Submit search terms" }, "aria": { "fcc-curriculum": "freeCodeCamp Studienplan", @@ -504,10 +513,11 @@ "step": "Schritt", "steps": "Schritte", "steps-for": "Schritte für {{blockTitle}}", - "code-example": "{{codeName}} code example" + "code-example": "{{codeName}} code example", + "opens-new-window": "Opens in new window" }, "flash": { - "honest-first": "Um eine Zertifizierung zu erlangen, musst du zunächst unsere Richtlinie zur akademischen Ehrlichkeit akzeptieren", + "honest-first": "To claim a certification, you must first agree to our academic honesty policy", "really-weird": "Etwas wirklich Seltsames ist passiert. Wenn es wieder passiert, erwäge bitte, einen Fehler auf https://github.com/freeCodeCamp/freeCodeCamp/issues/new zu melden.", "not-right": "Irgendetwas ist nicht in Ordnung. Es wurde ein Bericht erstellt und das freeCodeCamp.org Team wurde benachrichtigt", "went-wrong": "Etwas ist schief gelaufen, bitte überprüfe und versuche es erneut", @@ -586,7 +596,8 @@ "editor-url": "Denke daran, die Live App URL einzureichen.", "http-url": "Eine unsichere (http) URL kann nicht verwendet werden.", "own-work-url": "Denke daran, deine eigene Arbeit einzureichen.", - "publicly-visible-url": "Denke daran, eine öffentlich sichtbare App-URL einzureichen." + "publicly-visible-url": "Denke daran, eine öffentlich sichtbare App-URL einzureichen.", + "path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path" }, "certification": { "executive": "Geschäftsführender Direktor, freeCodeCamp.org", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "Katzen- und Hundebildklassifizierer", "Book Recommendation Engine using KNN": "Buchempfehlungsmaschine mithilfe von KNN", "Linear Regression Health Costs Calculator": "Gesundheitskostenrechner mit einer linearen Regression", - "Neural Network SMS Text Classifier": "SMS-Textklassifizierung mittels neuronalem Netzwerk" + "Neural Network SMS Text Classifier": "SMS-Textklassifizierung mittels neuronalem Netzwerk", + "Celestial Bodies Database": "Celestial Bodies Database", + "World Cup Database": "World Cup Database", + "Salon Appointment Scheduler": "Salon Appointment Scheduler", + "Periodic Table Database": "Periodic Table Database", + "Number Guessing Game": "Number Guessing Game", + "Build a freeCodeCamp Forum Homepage": "Build a freeCodeCamp Forum Homepage" } + }, + "title": { + "Responsive Web Design": "Responsive Web Design", + "responsive-web-design": "Responsive Web Design Certification", + "JavaScript Algorithms and Data Structures": "JavaScript Algorithms and Data Structures", + "javascript-algorithms-and-data-structures": "JavaScript Algorithms and Data Structures Certification", + "Front End Development Libraries": "Front End Development Libraries", + "front-end-development-libraries": "Front End Development Libraries Certification", + "Data Visualization": "Data Visualization", + "data-visualization": "Data Visualization Certification", + "Relational Database": "Relational Database", + "relational-database-v8": "Relational Database Certification", + "Back End Development and APIs": "Back End Development and APIs", + "back-end-development-and-apis": "Back End Development and APIs Certification", + "Quality Assurance": "Quality Assurance", + "quality-assurance-v7": "Quality Assurance Certification", + "Scientific Computing with Python": "Scientific Computing with Python", + "scientific-computing-with-python-v7": "Scientific Computing with Python Certification", + "Data Analysis with Python": "Data Analysis with Python", + "data-analysis-with-python-v7": "Data Analysis with Python Certification", + "Information Security": "Information Security", + "information-security-v7": "Information Security Certification", + "Machine Learning with Python": "Machine Learning with Python", + "machine-learning-with-python-v7": "Machine Learning with Python Certification", + "Legacy Front End": "Legacy Front End", + "legacy-front-end": "Front End Certification", + "Legacy Back End": "Legacy Back End", + "legacy-back-end": "Back End Certification", + "Legacy Data Visualization": "Legacy Data Visualization", + "legacy-data-visualization": "Data Visualization Certification", + "Legacy Information Security and Quality Assurance": "Legacy Information Security and Quality Assurance", + "information-security-and-quality-assurance": "Information Security and Quality Assurance Certification", + "Legacy Full Stack Certification": "Legacy Full Stack Certification", + "Legacy Full Stack": "Legacy Full Stack", + "full-stack": "Full Stack Certification" } }, "certification-card": { diff --git a/client/i18n/locales/italian/intro.json b/client/i18n/locales/italian/intro.json index 8145eb32773fab..981a10c35ce4f6 100644 --- a/client/i18n/locales/italian/intro.json +++ b/client/i18n/locales/italian/intro.json @@ -166,7 +166,7 @@ ] }, "learn-css-flexbox-by-building-a-photo-gallery": { - "title": "Impara il Flexbox CSS costruendo una fotogallery", + "title": "Impara Flexbox CSS costruendo una fotogallery", "intro": [ "Flexbox ti aiuta a progettare la tua pagina web in modo che vada bene su qualsiasi dimensione dello schermo.", "In questo corso, utilizzerai Flexbox per creare una pagina web di una galleria fotografica reattiva." @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "Impara programmazione funzionale creando un foglio di calcolo", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Learn Advanced Array Methods by Building a Statistics Calculator", + "intro": ["", ""] } } }, @@ -553,7 +557,7 @@ "intro": [ "Fino a questo punto, hai usato solo JavaScript sul front-end per aggiungere interattività a una pagina, risolvere sfide algoritmiche o costruire una Single Page Application. Ma JavaScript può essere utilizzato anche nel backend (cioè lato server), per costruire intere applicazioni web.", "Oggi, uno dei modi più popolari per costruire applicazioni è attraverso i microservizi, che sono piccole applicazioni modulari che lavorano insieme per formare qualcosa di più grande.", - "Nella Certificazione Sviluppo Back End e API, imparerai a scrivere app per il backend con Node.js e npm (Node Package Manager). Costruirai anche applicazioni web con il framework Express, e costruirai un microservizio Trova Persone con MongoDB e la libreria Mongoose." + "Nella Certificazione Sviluppo Back End e API, imparerai a scrivere app per il backend con Node.js e npm. Costruirai anche applicazioni web con il framework Express, e costruirai un microservizio Trova Persone con MongoDB e la libreria Mongoose." ], "note": "", "blocks": { @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "The Odin Project", + "intro": [ + "The Odin Project è una di quelle risorse che \"avrei voluto mentre stavo imparando\". ", + "Non tutti hanno accesso a un'educazione all'informatica o ai fondi per frequentare una scuola intensiva di programmazione e, in ogni caso, sono soluzioni non adatte a tutti.", + "Questo progetto è stato ideato per colmare il vuoto per le persone che stanno cercando di farcela da sole ma desiderano un'istruzione di alta qualità." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Impara i Fondamenti di HTML", + "intro": ["A description is to be determined"] + }, + "top-build-a-recipe-project": { + "title": "Impara i Fondamenti di HTML Creando una Pagina di Ricette", + "intro": ["A description is to be determined"] + } + } + }, "misc-text": { "certification": "Certificazione {{cert}}", "browse-other": "Sfoglia le altre nostre certificazioni gratuite\n(consigliamo di seguirle in ordine)", diff --git a/client/i18n/locales/italian/translations.json b/client/i18n/locales/italian/translations.json index b0a17f480911fa..b4a25a5c6470dc 100644 --- a/client/i18n/locales/italian/translations.json +++ b/client/i18n/locales/italian/translations.json @@ -11,11 +11,12 @@ "view": "Visualizza", "view-code": "Visualizza il Codice", "view-project": "Visualizza il Progetto", + "view-cert-title": "Visualizza {{certTitle}}", "show-cert": "Mostra la Certificazione", "claim-cert": "Richiedi la Certificazione", "save-progress": "Salva l'avanzamento", "accepted-honesty": "Hai accettato la nostra Politica di Onestà Accademica.", - "agree": "Accetta", + "agree-honesty": "Accetto la Politica di Onestà Accademica di freeCodeCamp.", "save-portfolio": "Salva questo elemento del portfolio", "remove-portfolio": "Rimuovi questo elemento del portfolio", "add-portfolio": "Aggiungi un nuovo elemento nel portfolio", @@ -52,7 +53,7 @@ "check-code": "Verifica il tuo codice (Ctrl + Invio)", "check-code-2": "Verifica il tuo codice", "reset": "Resetta", - "reset-code": "Resetta tutto il codice", + "reset-step": "Resetta questo step", "help": "Guida", "get-help": "Ottieni Aiuto", "watch-video": "Guarda un video", @@ -80,7 +81,7 @@ "big-heading-1": "Impara a programmare — gratis.", "big-heading-2": "Costruisci progetti.", "big-heading-3": "Ottieni certificazioni.", - "h2-heading": "Dal 2014, più di 40.000 laureati di freeCodeCamp.org hanno ottenuto posti di lavoro presso aziende tecnologiche, tra cui:", + "h2-heading": "Dal 2014, più di 40.000 studenti di freeCodeCamp.org hanno ottenuto posti di lavoro presso aziende tecnologiche, tra cui:", "hero-img-description": "Studenti di un gruppo di studio locale di freeCodeCamp in Corea del Sud.", "as-seen-in": "Hanno parlato di noi:", "testimonials": { @@ -157,7 +158,8 @@ "honesty": "Politica di Onestà Accademica", "internet": "La Tua presenza su Internet", "portfolio": "Impostazioni Portfolio", - "privacy": "Impostazioni Privacy" + "privacy": "Impostazioni Privacy", + "personal-info": "Informazioni personali" }, "danger": { "heading": "Zona di Pericolo", @@ -222,16 +224,15 @@ "total-points_plural": "{{count}} punti totali", "points": "{{count}} punto il {{date}}", "points_plural": "{{count}} punti il {{date}}", - "screen-shot": "Uno screenshot di {{title}}", "page-number": "{{pageNumber}} di {{totalPages}}" }, "footer": { - "tax-exempt-status": "freeCodeCamp è un'organizzazione senza scopo di lucro (United States Federal Tax Identification Number: 82-0779546)", + "tax-exempt-status": "freeCodeCamp è un'organizzazione di beneficenza 501(c)(3) esentasse supportata da donazioni (Numero di identificazione per le tasse federali negli Stati Uniti d'America: 82-0779546)", "mission-statement": "La nostra missione: aiutare le persone a imparare a programmare gratuitamente. Lo facciamo creando migliaia di video, articoli e lezioni di programmazione interattive - tutti liberamente disponibili al pubblico. Abbiamo anche migliaia di gruppi di studio freeCodeCamp in tutto il mondo.", "donation-initiatives": "Le donazioni a freeCodeCamp vanno alle nostre iniziative educative e aiutano a pagare i server, i servizi e il personale.", "donate-text": "Puoi fare una <1>donazione deducibile dalle tasse qui.", "trending-guides": "Guide Di Tendenza", - "our-nonprofit": "Il nostro nonprofit", + "our-nonprofit": "La nostra Charity", "links": { "about": "Informazioni", "alumni": "Rete degli allievi", @@ -249,6 +250,7 @@ }, "learn": { "heading": "Benvenuti nel curriculum di freeCodeCamp.", + "skip-to-content": "Vai al contenuto", "welcome-1": "Bentornato, {{name}}.", "welcome-2": "Benvenuto su freeCodeCamp.org", "start-at-beginning": "Se sei nuovo alla programmazione, ti consigliamo di <0>iniziare dall'inizio.", @@ -272,6 +274,9 @@ "add-subtitles": "Aiuta a migliorare o aggiungi sottotitoli", "wrong-answer": "Siamo spiacenti, non è la risposta giusta. Vuoi riprovare?", "check-answer": "Fai clic sul pulsante qui sotto per controllare la tua risposta.", + "assignment-not-complete": "Per favore completa le attività", + "assignments": "Attività", + "question": "Domande", "solution-link": "Link alla soluzione", "github-link": "Link GitHub", "submit-and-go": "Invia e vai alla prossima sfida", @@ -297,7 +302,6 @@ "certs": "Certificazione {{title}}" }, "editor-tabs": { - "info": "Informazioni", "code": "Codice", "tests": "Test", "restart": "Inizia da capo", @@ -307,6 +311,10 @@ "notes": "Note", "preview": "Anteprima" }, + "editor-alerts": { + "tab-trapped": "Premendo tab ora potrai inserire il carattere tab", + "tab-free": "Premendo tab ora potrai spostare il focus sull'elemento successivo" + }, "help-translate": "Stiamo ancora traducendo le seguenti certificazioni.", "help-translate-link": "Aiutaci con le traduzioni...", "project-preview-title": "Ecco una anticipazione di quello che creerai", @@ -327,12 +335,12 @@ "sorry-dont-giveup": "Il tuo codice non è corretto. Non arrenderti.", "challenges-completed": "{{completedCount}} di {{totalChallenges}} sfide completate", "season-greetings-fcc": "Saluti dalla comunità freeCodeCamp 🎉", - "if-getting-value": "Se stai trovando utile freeCodeCamp, è un ottimo momento per donare e sostenere la missione della nostra nonprofit.", + "if-getting-value": "Se stai trovando utile freeCodeCamp, è un ottimo momento per donare e sostenere la missione del nostro ente di beneficenza.", "building-a-university": "Stiamo creando un corso di laurea gratuito in Scienze Informatiche", "if-help-university": "Abbiamo già fatto tanti progressi. Sostieni il nostro ente benefico con la lunga strada che ci attende." }, "donate": { - "title": "Supporta il nostro no profit", + "title": "Supporta il nostro ente", "processing": "Stiamo elaborando la tua donazione.", "redirecting": "Reindirizzamento...", "thanks": "Grazie per la donazione", @@ -355,10 +363,9 @@ "your-donation-2": "La tua donazione ${{usd}} fornirà {{hours}} ore di apprendimento alle persone di tutto il mondo ogni mese.", "your-donation-3": "La tua donazione di ${{usd}} fornirà {{hours}} ore di apprendimento a persone di tutto il mondo ogni anno.", "become-supporter": "Diventa sostenitore", - "duration": "Diventa un sostenitore una tantum del nostro non-profit.", - "duration-2": "Diventa un sostenitore mensile del nostro non-profit.", - "duration-3": "Diventa un sostenitore annuale del nostro no profit", - "duration-4": "Diventa un sostenitore del nostro non-profit", + "duration": "Diventa un sostenitore una tantum del nostro ente di beneficenza.", + "duration-2": "Diventa un sostenitore mensile del nostro ente di beneficenza.", + "duration-4": "Diventa un sostenitore del nostro ente di beneficenza", "nicely-done": "Ben fatto. Hai appena completato {{block}}.", "credit-card": "Carta di credito", "credit-card-2": "O dona con una carta di credito:", @@ -372,25 +379,25 @@ "email-receipt": "Email (ti invieremo una ricevuta di donazione):", "need-help": "Hai bisogno di aiuto con le tue donazioni attuali o passate?", "forward-receipt": "Inoltra una copia della tua ricevuta di donazione a donors@freecodecamp.org e dicci come possiamo aiutarti.", - "efficiency": "freeCodeCamp è una non-profit dell'educazione altamente efficiente.", + "efficiency": "freeCodeCamp è un'organizzazione altamente efficiente che si dedica all'educazione.", "why-donate-1": "Quando doni a freeCodeCamp, aiuti tante persone a fare proprie nuove competenze e a prendersi cura delle loro famiglie.", "why-donate-2": "Ci aiuterai anche a creare nuove risorse per te da utilizzare per espandere le tue abilità tecnologiche.", "bigger-donation": "Vuoi fare una donazione una tantum più sostanziosa, inviarci un assegno o donare in altri modi?", - "other-ways": "Qui ci sono molti <0>altri modi per supportare la nostra mission non-profit. .", + "other-ways": "Qui ci sono molti <0>altri modi per supportare la missione del nostro ente di beneficenza.", "failed-pay": "Uh - oh. Sembra che la tua transazione non sia passata. Potresti riprovare?", "try-again": "Per favore riprova.", "card-number": "Numero della tua Carta:", "expiration": "Data di scadenza:", "secure-donation": "Donazione sicura", "faq": "Domande frequenti", - "only-you": "Solo tu puoi vedere questo messaggio. Congratulazioni nell'aver ottenuto questa certificazione. Non è una cosa facile. Neanche mantenere attivo freeCodeCamp è facile. E non è neanche economico. Aiutaci ad aiutare te e tante altre persone attorno al mondo. Fai oggi una donazione per supportare la nostra noprofit.", + "only-you": "Solo tu puoi vedere questo messaggio. Congratulazioni per aver ottenuto questa certificazione. Non è una cosa facile. Neanche mantenere attivo freeCodeCamp è facile. E non è neanche economico. Aiutaci ad aiutare te e tante altre persone in tutto il mondo. Fai oggi una donazione per supportare la nostra organizzazione di beneficenza.", "get-help": "Come posso ottenere aiuto con le mie donazioni?", "how-transparent": "Quanto è trasparente freeCodeCamp.org?", "very-transparent": "Un sacco. Abbiamo un giudizio Platino per la trasparenza su GuideStar.org.", "download-irs": "Puoi <0>scaricare la nostra Lettera di Determinazione IRS qui.", "download-990": "È possibile <0>scaricare il nostro più recente 990 (rapporto fiscale annuale) qui.", "how-efficient": "Quanto è efficiente freeCodeCamp?", - "fcc-budget": "Il budget di freeCodeCamp è molto più piccolo della maggior parte delle noprofit comparabili. Non abbiamo usato il servizio di raccoglitori di fondi professionali. Invece, Quincy fa tutto da se.", + "fcc-budget": "Il budget di freeCodeCamp è molto ristretto rispetto alla maggior parte delle organizzazioni di beneficenza comparabili. Non ci siamo rivolti a fundraiser professionisti. Invece, Quincy fa tutto da sé.", "help-millions": "Però, con un budget di poche centinaia di migliaia di dollari per anno, siamo stati in grado di aiutare milioni di persone.", "how-one-time": "Come posso fare una singola donazione non ricorrente?", "one-time": "Se preferisci fare una singola donazione, puoi supportare la missione di freeCodeCamp quando hai qualche soldo in più. Puoi usare <0>questo link per donare qualsiasi ammontare ti senti di dare tramite PayPal.", @@ -399,8 +406,8 @@ "yes-cryptocurrency": "Sì. Per favore manda una email a Quincy a quincy@freecodecamp.org e ti può mandare le informazioni del portafogli di freeCodeCamp. Ti può anche dare una ricevuta se ne hai bisogno per le tasse.", "can-check": "Posso spedire un assegno fisico?", "yes-check": "Sì, te ne saremmo grati. Puoi spedirlo a:", - "how-matching-gift": "Come posso organizzare donazioni combacianti dal mio datore di lavoro, o riduzioni dalla mia busta paga?", - "employers-vary": "Questo varia da datore di lavoro a datore di lavoro, e la nostra noprofit è già elencata in molti dei grandi database di donazioni combacianti.", + "how-matching-gift": "Come posso definire delle matching donation dal mio datore di lavoro, o detrazioni dalla mia busta paga?", + "employers-vary": "Questo varia da datore di lavoro a datore di lavoro, e il nostro ente benefico è già elencato in molti dei grandi database di match giving.", "some-volunteer": "Alcune persone sono in grado di fare volontariato per freeCodeCamp e i loro datori di lavoro combaciano un dato valore per ora del loro tempo donato. Altri combaciano qualsiasi donazione che i donatori fanno con un tetto massimo", "help-matching-gift": "Se hai bisogno di aiuto con questo, per favore manda una mail a Quincy a quincy@freecodecamp.org", "how-endowment": "Come posso organizzare un finanziamento per freeCodeCamp.org?", @@ -411,13 +418,13 @@ "thank-wikimedia": "Vorremmo ringraziare la Fondazione Wikimedia per aver provveduto questo linguaggio formare per il nostro uso.", "legacy-gift-questions": "Se hai domande su questo processo, per favore scrivi a Quincy a quincy@freecodecamp.org.", "how-stock": "Come posso donare azioni a freeCodeCamp.org?", - "welcome-stock": "Saremmo grati per la tua donazione in azioni. Per favore scrivi a Quincy direttamente e ti può aiutare con questo, e condividere con te i dettagli del nostro account di brokerage: quindy@freecodecamp.org.", + "welcome-stock": "Saremmo grati per la tua donazione in azioni. Per favore scrivi direttamente a Quincy, che potrà aiutarti e condividere con te i dettagli del nostro account di brokerage: quincy@freecodecamp.org.", "how-receipt": "Posso avere una ricevuta della mia donazione così da dedurla dalle mie tasse?", "just-forward": "Certo. Basta che inoltri la ricevuta della transazione a donors@freecodecamp.org, dicci che vorresti una ricevuta e qualsiasi istruzione speciale tu abbia, e ti risponderemo con una ricevuta.", "how-update": "Ho impostato una donazione mensile, ma ho bisogno di aggiornarla o metterla in pausa. Come posso fare?", "take-care-of-this": "Inoltra una delle tue ricevute a donors@freecodecamp.org e dicci cosa vorresti fare. Ce ne occuperemo e ti risponderemo con una conferma.", "anything-else": "C'è altro da sapere su donare a freeCodeCamp.org?", - "other-support": "Se ci sono altri modi in cui vorresti supportare la nostra noprofit e la sua missione che non è in questa pagina, o se hai qualsiasi domanda, per favore scrivi a Quincy a quincy@freecodecamp.org." + "other-support": "Se ci sono altri modi in cui vorresti supportare il nostro ente benefico e la sua missione che non sono elencati in questa pagina, o se hai qualsiasi domanda, per favore scrivi a Quincy a quincy@freecodecamp.org." }, "report": { "sign-in": "Devi essere loggato per segnalare un utente", @@ -460,7 +467,8 @@ "iframe-preview": "Anteprima {{title}}", "iframe-alert": "Solitamente questo link ti porterebbe su un altro sito web! Funziona. Questo è un link per {{externalLink}}", "iframe-form-submit-alert": "Normalmente questo modulo sarebbe stato inviato! Funziona. Sarà inviato a: {{externalLink}}", - "document-notfound": "documento non trovato" + "document-notfound": "documento non trovato", + "slow-load-msg": "Sembra che sia necessario più tempo del solito, per favore prova ad aggiornare la pagina." }, "icons": { "gold-cup": "Coppa d'Oro", @@ -475,10 +483,11 @@ "hint": "Suggerimento", "heart": "Cuore", "initial": "Iniziale", + "input-reset": "Cancella termini di ricerca", "info": "Informazioni introduttive", "spacer": "Distanziatore", "toggle": "Attiva/Disattiva segno di spunta", - "magnifier": "lente d'ingrandimento" + "magnifier": "Invia i termini di ricerca" }, "aria": { "fcc-curriculum": "Curriculum di freeCodeCamp", @@ -504,7 +513,8 @@ "step": "Step", "steps": "Step", "steps-for": "Step per {{blockTitle}}", - "code-example": "{{codeName}} code example" + "code-example": "{{codeName}} esempio di codice", + "opens-new-window": "Apri in una nuova finestra" }, "flash": { "honest-first": "Per richiedere una certificazione, è necessario prima accettare la nostra politica di onestà accademica", @@ -586,7 +596,8 @@ "editor-url": "Ricordati di inviare l'URL della Live App.", "http-url": "Non è possibile utilizzare un URL non sicuro (http).", "own-work-url": "Ricordati di inviare il tuo lavoro.", - "publicly-visible-url": "Ricorda di inviare un URL dell'app visibile pubblicamente." + "publicly-visible-url": "Ricorda di inviare un URL dell'app visibile pubblicamente.", + "path-url": "Probabilmente vuoi inviare il percorso root, ovvero https://example.com, non https://example.com/percorso" }, "certification": { "executive": "Direttore esecutivo, freeCodeCamp.org", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "Classificatore di immagini di gatti e cani", "Book Recommendation Engine using KNN": "Motore per la raccomandazione di libri che usa KNN", "Linear Regression Health Costs Calculator": "Calcolatore di costi per la salute con la Regressione Lineare", - "Neural Network SMS Text Classifier": "Classificatore neurale di messaggi SMS" + "Neural Network SMS Text Classifier": "Classificatore neurale di messaggi SMS", + "Celestial Bodies Database": "Database Corpi Celesti", + "World Cup Database": "Database Coppa Del Mondo", + "Salon Appointment Scheduler": "Pianificatore Appuntamento Salone", + "Periodic Table Database": "Database della Tavola Periodica", + "Number Guessing Game": "Gioco di indovinare il numero", + "Build a freeCodeCamp Forum Homepage": "Costruisci l'Homepage del Forum di freeCodeCamp" } + }, + "title": { + "Responsive Web Design": "Web Design Responsivo", + "responsive-web-design": "Certificazione Web Design Responsivo", + "JavaScript Algorithms and Data Structures": "Algoritmi e Strutture Dati in JavaScript", + "javascript-algorithms-and-data-structures": "Certificazione Algoritmi e Strutture Dati in JavaScript", + "Front End Development Libraries": "Librerie di Sviluppo Front End", + "front-end-development-libraries": "Certificazione Librerie di Sviluppo Front End", + "Data Visualization": "Visualizzazione Dati", + "data-visualization": "Certificazione Visualizzazione Dati", + "Relational Database": "Database Relazionale", + "relational-database-v8": "Certificazione Database Relazionale", + "Back End Development and APIs": "Sviluppo Back End e API", + "back-end-development-and-apis": "Certificazione di Sviluppo Back End e API", + "Quality Assurance": "Garanzia di Qualità", + "quality-assurance-v7": "Certificazione Garanzia di Qualità", + "Scientific Computing with Python": "Calcolo Scientifico con Python", + "scientific-computing-with-python-v7": "Certificazione Calcolo Scientifico con Python", + "Data Analysis with Python": "Analisi dei Dati con Python", + "data-analysis-with-python-v7": "Certificazione Analisi dei Dati con Python", + "Information Security": "Sicurezza dell'Informazione", + "information-security-v7": "Certificazione Sicurezza dell'Informazione", + "Machine Learning with Python": "Machine Learning con Python", + "machine-learning-with-python-v7": "Certificazione Machine Learning con Python", + "Legacy Front End": "Front End Legacy", + "legacy-front-end": "Certificazione Front End", + "Legacy Back End": "Back End Legacy", + "legacy-back-end": "Certificazione Back End", + "Legacy Data Visualization": "Visualizzazione Dati Legacy", + "legacy-data-visualization": "Certificazione Visualizzazione Dati", + "Legacy Information Security and Quality Assurance": "Sicurezza delle Informazioni e Garanzia di Qualità Legacy", + "information-security-and-quality-assurance": "Certificazione di Sicurezza delle Informazioni e Garanzia di Qualità", + "Legacy Full Stack Certification": "Certificazione Full Stack Legacy", + "Legacy Full Stack": "Full Stack Legacy", + "full-stack": "Certificazione Full Stack" } }, "certification-card": { diff --git a/client/i18n/locales/japanese/intro.json b/client/i18n/locales/japanese/intro.json index 053833b850d001..8c32e0e042c8c8 100644 --- a/client/i18n/locales/japanese/intro.json +++ b/client/i18n/locales/japanese/intro.json @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "関数型プログラミングの学習: スプレッドシートを作る", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Learn Advanced Array Methods by Building a Statistics Calculator", + "intro": ["", ""] } } }, @@ -553,7 +557,7 @@ "intro": [ "ここまでは、JavaScript をフロントエンドで使用して、ページに対話性を加えたり、アルゴリズムチャレンジを解決したり、SPA を構築したりしてきました。しかし JavaScript は、バックエンド (サーバー) でも使用でき、ウェブアプリケーション全体を構築することができます。", "現在、アプリケーションを構築する一般的な方法の一つはマイクロサービスを使用する方法です。これは、小さなモジュール式のアプリケーションを組み合わせて、より大きな全体を形成する方法です。", - "バックエンド開発と API 認定講座では、Node.js と npm (Node Package Manager) を使用してバックエンドアプリを記述する方法を学習します。また、Express フレームワークでウェブアプリケーションを構築し、そして MongoDB と Mongoose ライブラリで People Finder マイクロサービスを構築します。" + "バックエンド開発と API 認定講座では、Node.js と npm を使用してバックエンドアプリを記述する方法を学習します。Express フレームワークでウェブアプリケーションを構築し、MongoDB と Mongoose ライブラリで People Finder マイクロサービスを構築します。" ], "note": "", "blocks": { @@ -625,10 +629,10 @@ } }, "scientific-computing-with-python": { - "title": "Python を用いた科学的コンピューティング", + "title": "Python を用いた科学技術計算", "intro": [ "Python は現在最も一般的で適応性のあるプログラミング言語です。基本的なスクリプトから機械学習まで幅広く使用することができます。", - "Python を用いた科学的コンピューティング認定講座では、変数、ループ、条件式、そして関数のような、Python の基本を学習します。それから、複雑なデータ構造、ネットワーキング、リレーショナルデータベース、そしてデータ可視化まで素早く強化します。" + "Python を用いた科学技術計算認定講座では、変数、ループ、条件式、そして関数のような、Python の基本を学習します。それから、複雑なデータ構造、ネットワーキング、リレーショナルデータベース、そしてデータ可視化まで素早く強化します。" ], "note": "", "blocks": { @@ -640,9 +644,9 @@ ] }, "scientific-computing-with-python-projects": { - "title": "Python を用いた科学的コンピューティングプロジェクト", + "title": "Python を用いた科学技術計算プロジェクト", "intro": [ - "Python の技能をテストする時です。これらのプロジェクトを完成させることによって、Python の優れた基礎知識をもっていることと、Python を用いた科学的コンピューティング認定証を得る資格があることを証明します。" + "Python の技能をテストする時です。これらのプロジェクトを完成させることによって、Python の優れた基礎知識をもっていることと、Python を用いた科学技術計算認定証を得る資格があることを証明します。" ] } } @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "The Odin Project", + "intro": [ + "The Odin Project is one of those \"What I wish I had when I was learning\" resources. ", + "Not everyone has access to a computer science education or the funds to attend an intensive coding school and neither of those is right for everyone anyway.", + "This project is designed to fill in the gap for people who are trying to hack it on their own but still want a high quality education." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Learn HTML Foundations", + "intro": ["A description is to be determined"] + }, + "top-build-a-recipe-project": { + "title": "Learn HTML Foundations by Building a Recipe Page", + "intro": ["A description is to be determined"] + } + } + }, "misc-text": { "certification": "{{cert}} 認定", "browse-other": "他の無料の認定講座を閲覧する\n(上から順に受講することをお勧めします)", @@ -802,7 +824,7 @@ "viewing-upcoming-change": "ベータ版のページを閲覧中です。 ", "go-back-to-learn": "カリキュラムの安定版へ戻る。", "read-database-cert-article": "続行する前に、こちらのフォーラム投稿をお読みください。", - "enable-cookies": "開始前にサードパーティーの Cookie を有効にしてください。", + "enable-cookies": "サードパーティーの Cookie が有効になっていることを確認してから開始してください。", "english-only": "このセクションのコースは、英語版でのみ利用可能です。現時点ではタイトルと紹介文のみが翻訳に対応しており、レッスン自体は翻訳されておりません。" } } diff --git a/client/i18n/locales/japanese/translations.json b/client/i18n/locales/japanese/translations.json index 8308831b0769af..237a5ade9a5cfc 100644 --- a/client/i18n/locales/japanese/translations.json +++ b/client/i18n/locales/japanese/translations.json @@ -11,11 +11,12 @@ "view": "表示", "view-code": "コードを表示", "view-project": "プロジェクトを表示", + "view-cert-title": "{{certTitle}}を表示", "show-cert": "認定証を表示", "claim-cert": "認定証を取得", "save-progress": "進行状況を保存", - "accepted-honesty": "学問的誠実性ポリシーに同意しました。", - "agree": "同意する", + "accepted-honesty": "You have agreed to our Academic Honesty Policy.", + "agree-honesty": "I agree to freeCodeCamp's Academic Honesty Policy.", "save-portfolio": "このポートフォリオアイテムを保存", "remove-portfolio": "このポートフォリオアイテムを削除", "add-portfolio": "新規ポートフォリオアイテムを追加", @@ -52,7 +53,7 @@ "check-code": "コードをチェック (Ctrl + Enter)", "check-code-2": "コードをチェック", "reset": "リセット", - "reset-code": "全てのコードをリセット", + "reset-step": "Reset This Step", "help": "ヘルプ", "get-help": "助けを求める", "watch-video": "動画を見る", @@ -109,7 +110,7 @@ "data": "アカウントに保存されているデータを確認するには、下の「データをダウンロード」ボタンをクリックしてください", "disabled": "非公開に設定されている場合、認定証は無効化されます。", "private-name": "非公開に設定されている場合、あなたの名前は認定証に表示されません。", - "claim-legacy": "以下の freeCodeCamp 認定証を取得すると、 {{cert}} を受け取ることができます。", + "claim-legacy": "以下の freeCodeCamp 認定証を取得すると、{{cert}}を受け取ることができます。", "for": "{{username}} さんのアカウント設定", "sound-mode": "これは快適なアコースティックギターの音をウェブサイトの至る所へ追加します。エディターにタイプしたり、チャレンジを完了したり、認定証を請求したり、その他いろいろなことをする度に音のフィードバックを受け取ります。", "sound-volume": "キャンプファイアモードの音量:", @@ -157,7 +158,8 @@ "honesty": "学問的誠実性ポリシー", "internet": "他サービスのリンク", "portfolio": "ポートフォリオ設定", - "privacy": "プライバシー設定" + "privacy": "プライバシー設定", + "personal-info": "Personal Information" }, "danger": { "heading": "危険な操作", @@ -222,11 +224,10 @@ "total-points_plural": "合計 {{count}} ポイント", "points": "{{count}} ポイント ({{date}})", "points_plural": "{{count}} ポイント ({{date}})", - "screen-shot": "{{title}} のスクリーンショット", "page-number": "{{pageNumber}} / {{totalPages}}" }, "footer": { - "tax-exempt-status": "freeCodeCamp は皆様のご寄付により支えられている非課税の 501(c)(3) 非営利団体です。(United States Federal Tax Identification Number: 82-0779546)", + "tax-exempt-status": "freeCodeCamp は皆様のご寄付により支えられている非課税の 501(c)(3) 慈善団体です。(United States Federal Tax Identification Number: 82-0779546)", "mission-statement": "私たちのミッション: 人々が無料でコーディングを学べるよう支援することです。その実現のため、何千もの動画、記事、インタラクティブなコーディングレッスンを作成し、すべて無料で公開しています。さらに、数千の freeCodeCamp スタディグループが世界中に存在します。", "donation-initiatives": "freeCodeCamp へのご寄付は教育活動のために用いられ、サーバー、サービス、スタッフなどの費用に充てられます。", "donate-text": "<1>こちらからご寄付をお願いいたします。(場合により税控除可能)", @@ -249,6 +250,7 @@ }, "learn": { "heading": "freeCodeCamp のカリキュラムへようこそ。", + "skip-to-content": "Skip to content", "welcome-1": "{{name}} さん、おかえりなさい。", "welcome-2": "freeCodeCamp.org へようこそ", "start-at-beginning": "コーディングが初めての場合は、<0>最初から開始する ことをお勧めします。", @@ -272,6 +274,9 @@ "add-subtitles": "字幕の改善や追加を支援する", "wrong-answer": "残念、正しい答えではありません。もう一度挑戦してみましょう。", "check-answer": "以下のボタンをクリックして解答を確認してください。", + "assignment-not-complete": "Please finish the assignments", + "assignments": "Assignments", + "question": "Question", "solution-link": "回答のリンク", "github-link": "GitHub のリンク", "submit-and-go": "提出して次のチャレンジに進む", @@ -297,7 +302,6 @@ "certs": "{{title}} 認定講座" }, "editor-tabs": { - "info": "詳細", "code": "コード", "tests": "テスト", "restart": "リスタート", @@ -307,6 +311,10 @@ "notes": "ノート", "preview": "プレビュー" }, + "editor-alerts": { + "tab-trapped": "タブキーを押すとタブ文字が入力されます", + "tab-free": "タブキーを押すと次のフォーカス可能要素にフォーカスします" + }, "help-translate": "以下の認定講座は現在翻訳中です。", "help-translate-link": "翻訳にご協力ください。", "project-preview-title": "これが今から作る物のプレビューです。", @@ -327,16 +335,16 @@ "sorry-dont-giveup": "残念ながら、テストが通りませんでした。諦めないでください。", "challenges-completed": "{{totalChallenges}} 件中 {{completedCount}} 件完了", "season-greetings-fcc": "freeCodeCamp コミュニティから季節のご挨拶🎉", - "if-getting-value": "freeCodeCamp が役に立ったと感じていただけたなら、寄付を通して当非営利団体の使命をご支援いただけますと幸いです。", + "if-getting-value": "freeCodeCamp が役に立ったと感じていただけたなら、寄付を通して当団体の使命をご支援いただけますと幸いです。", "building-a-university": "freeCodeCamp では無料のコンピューターサイエンス学位プログラムの設立に取り組んでいます。", "if-help-university": "すでに順調に進んでいますが、この先更に長い道のりが待っています。ぜひ私たちのチャリティー活動をご支援ください。" }, "donate": { - "title": "非営利団体を支援する", + "title": "当団体への支援", "processing": "いただいた寄付を処理中です。", "redirecting": "リダイレクト中...", "thanks": "寄付ありがとうございます", - "thank-you": "サポーターとなっていただき、ありがとうございます。", + "thank-you": "サポーターとなってくださり、ありがとうございます。", "additional": "任意の金額を、追加で 1 回ずつご寄付いただけるリンクはこちら: <0>{{url}}", "help-more": "私たちのさらなる活動をご支援ください", "error": "寄付の処理に問題が発生しました。", @@ -355,10 +363,9 @@ "your-donation-2": "あなたの {{usd}} ドルのご寄付が、世界中の人々に {{hours}} 時間の学びを毎月提供します。", "your-donation-3": "あなたの {{usd}} ドルのご寄付が、世界中の人々に {{hours}} 時間の学びを毎年提供します。", "become-supporter": "サポーターになる", - "duration": "当非営利団体に一回のご支援をいただけますと幸いです。", - "duration-2": "当非営利団体に毎月のご支援をいただけますと幸いです。", - "duration-3": "当非営利団体に毎年のご支援をいただけますと幸いです。", - "duration-4": "当非営利団体にご支援をいただけますと幸いです。", + "duration": "当団体に一回のご支援をいただけますと幸いです。", + "duration-2": "当団体に毎月のご支援をいただけますと幸いです。", + "duration-4": "当団体にご支援をいただけますと幸いです。", "nicely-done": "おめでとうございます。「{{block}}」を完了しました。", "credit-card": "クレジットカード", "credit-card-2": "またはクレジットカードで寄付する:", @@ -372,25 +379,25 @@ "email-receipt": "Eメール (寄付の領収書をお送りいたします。税控除可能な場合がございます。):", "need-help": "現在または過去の寄付についてお困りでしょうか?", "forward-receipt": "寄付の領収書のコピーを添えて、お問い合わせ内容を donors@freecodecamp.org までお送りください。", - "efficiency": "freeCodeCamp は非常に効率的な、教育分野の非営利団体です。", - "why-donate-1": "freeCodeCamp にご寄付いただくことにより、新しい技能を学習して家族を支えようとしている人々を助けることに繋がります。", - "why-donate-2": "また、あなた自身の技術スキルを高めるための、学習リソースの作成を支援することにもなります。", + "efficiency": "freeCodeCamp は非常に効率的な、教育分野の慈善団体です。", + "why-donate-1": "freeCodeCamp への寄付を通して、新しい技能を習得して家計を支えようと努力している人々を支援できます。", + "why-donate-2": "また、あなた自身の技術スキルを高める学習リソースの作成を支援することにもなります。", "bigger-donation": "より多くの金額による一回の寄付や、小切手の送付、または他の方法をお考えでしょうか?", - "other-ways": "<0>当非営利団体の使命をご支援いただける方法 は他にも多数ございます。", + "other-ways": "<0>当団体の使命を支援する方法 は他にも多数ございます。", "failed-pay": "処理が完了しませんでした。再度お試しください。", "try-again": "再試行してください。", "card-number": "カード番号:", "expiration": "有効期限:", "secure-donation": "セキュアな寄付", "faq": "よくある質問", - "only-you": "このメッセージはあなただけに表示されています。認定証の獲得おめでとうございます。簡単な課題ではなかったことと思います。freeCodeCamp を運営することもまた、簡単ではありません。費用のかからないことでもありません。ぜひ、私たちがあなたを含む世界中の人々のお役に立てるようご支援ください。当非営利団体へのご寄付をお願い申し上げます。(場合により税控除可能)", + "only-you": "このメッセージはあなただけに表示されています。認定証の獲得おめでとうございます。簡単な課題ではなかったことと思います。freeCodeCamp を運営することもまた簡単ではなく、相当の費用もかかります。ぜひ私たちがあなたの、そして世界中の人々の役に立てるようご支援ください。当団体へのご寄付をお願いいたします。(場合により税控除可能)", "get-help": "寄付に関してサポートが必要な場合はどうしたらいいですか?", "how-transparent": "freeCodeCamp.org の透明性はどのような状態ですか?", "very-transparent": "極めて高いと評価されています。私たちは GuideStar.org より、プラチナグレードの透明性評価を受けています。", "download-irs": "<0>こちらで私たちの IRS Determination Letter をダウンロードできます。", "download-990": "<0>こちらで私たちの最新の 990 (税金の年次報告書) をダウンロードできます。", "how-efficient": "freeCodeCamp はどのくらい効率的なのでしょうか?", - "fcc-budget": "freeCodeCamp の予算は、ほとんどの同規模の非営利団体と比べ非常に少ないです。私たちはプロの資金調達者に参加を依頼していません。代わりに、Quincy が自分自身ですべてを行っています。", + "fcc-budget": "freeCodeCamp の予算は、同規模の他の慈善団体に比べ非常に少ない状況です。私たちはプロの資金調達者の力を借りることなく、Quincy 自身がその役目を担っています。", "help-millions": "しかしながら、私たちは年間わずか数十万ドルの予算で、数百万の人々を支援することができています。", "how-one-time": "一回ごとの寄付を行うにはどうしたらいいですか?", "one-time": "一回ごとの寄付をご希望の場合、いつでも経済的なゆとりがある時に、freeCodeCamp のミッションをご支援いただくことができます。<0>こちらのリンクから、PayPal を通して任意の金額を寄付することができます。", @@ -400,7 +407,7 @@ "can-check": "小切手の郵送は可能でしょうか?", "yes-check": "はい、小切手も歓迎しております。こちらの宛先までお送りください:", "how-matching-gift": "どのようにして雇用者からの上乗せ贈与 (マッチングギフト) や、給与所得控除を設定できますか?", - "employers-vary": "これは雇用者によって異なりますが、当非営利団体は大規模な寄付マッチングデータベースの多くに登録されています。", + "employers-vary": "これは雇用者によって異なりますが、当団体は大規模な寄付マッチングデータベースの多くに登録されています。", "some-volunteer": "あるケースでは、freeCodeCamp のためにボランティアの活動を行うことができ、雇用者がボランティアの活動時間ごとの固定金額を寄付することにより上乗せ贈与します。または、雇用者が寄付者が用意した特定の金額の寄付金と同額を上乗せ贈与する場合もあります。", "help-matching-gift": "本件に関してサポートが必要な場合、Quincy まで直接メールにてご連絡ください: quincy@freecodecamp.org", "how-endowment": "freeCodeCamp.org のために基金を設立するにはどうしたらいいですか?", @@ -411,13 +418,13 @@ "thank-wikimedia": "この正式な文面を私たちに提供して下さったウィキメディア財団に感謝申し上げます。", "legacy-gift-questions": "この手順に関するお問い合わせにつきましては、Quincy 宛てに quincy@freecodecamp.org までメールにてご連絡ください。", "how-stock": "株式を freeCodeCamp.org に寄付するにはどうしたらいいですか?", - "welcome-stock": "株式による寄付も歓迎しております。Quincy 宛てに quincy@freecodecamp.org まで直接メールにてご連絡いただければ、当非営利団体の証券口座の詳細も含めご説明いたします。", + "welcome-stock": "株式による寄付も歓迎しております。Quincy 宛てに quincy@freecodecamp.org まで直接メールにてご連絡いただければ、当団体の証券口座の詳細等ご説明いたします。", "how-receipt": "税金から寄付金を控除するために、寄付金の領収書を受け取ることはできますか?", "just-forward": "もちろんです。取引時の領収書を donors@freecodecamp.org まで転送し、領収書を必要とされている旨と、その他特別なご指示がございましたらその点も併せてご連絡ください。領収書を添えて返信いたします。", "how-update": "毎月の寄付を設定しましたが、月次の処理を変更または停止したいです。どうしたらいいですか?", "take-care-of-this": "毎月の寄付の領収書を donors@freecodecamp.org まで転送し、ご希望の変更内容をお伝えください。こちらで処理を行い、確認のご連絡を差し上げます。", "anything-else": "freeCodeCamp.org への寄付についてもっと知ることはできますか?", - "other-support": "こちらに挙げた以外の方法で、当非営利団体とそのミッションを支援したいとお考えの場合、またはその他のお問い合わせつきましては、 Quincy 宛てに quincy@freecodecamp.org までメールでご連絡ください。" + "other-support": "こちらに挙げた以外の方法で当団体を支援したいとお考えの場合、またはその他のお問い合わせつきましては、Quincy 宛てに quincy@freecodecamp.org までメールでご連絡ください。" }, "report": { "sign-in": "ユーザーを報告するためにはサインインする必要があります", @@ -460,7 +467,8 @@ "iframe-preview": "{{title}} のプレビュー", "iframe-alert": "このリンクは通常の環境では他のウェブサイトを開きます。正しく動作しています。これは {{externalLink}} へのリンクです。", "iframe-form-submit-alert": "通常はこれでフォームが送信されます。正しく動作しています。フォームは {{externalLink}} へ送信されます。", - "document-notfound": "ドキュメントが見つかりませんでした" + "document-notfound": "ドキュメントが見つかりませんでした", + "slow-load-msg": "通常より処理に時間がかかっているようです。ページの再読み込みをお試しください。" }, "icons": { "gold-cup": "ゴールドカップ", @@ -475,10 +483,11 @@ "hint": "ヒント", "heart": "ハート", "initial": "初期状態", + "input-reset": "検索キーワードをクリア", "info": "導入情報", "spacer": "スペーサー", "toggle": "トグルチェックマーク", - "magnifier": "虫眼鏡" + "magnifier": "検索キーワードを送信" }, "aria": { "fcc-curriculum": "freeCodeCamp のカリキュラム", @@ -504,10 +513,11 @@ "step": "ステップ", "steps": "ステップ一覧", "steps-for": "「{{blockTitle}}」のステップ一覧", - "code-example": "{{codeName}} code example" + "code-example": "{{codeName}} のコード例", + "opens-new-window": "新しいウィンドウで開く" }, "flash": { - "honest-first": "認定証を請求するには、まず学問的誠実性ポリシーに同意する必要があります。", + "honest-first": "To claim a certification, you must first agree to our academic honesty policy", "really-weird": "予期しない問題が発生しました。この問題が何度も発生するようであれば、https://github.com/freeCodeCamp/freeCodeCamp/issues/new への Issue 登録をご検討ください。", "not-right": "問題が発生しました。レポートが生成され、freeCodeCamp.org チームへ通知されました。", "went-wrong": "問題が発生しました。ご確認の上もう一度お試しください。", @@ -586,7 +596,8 @@ "editor-url": "動作可能なアプリの URL を提出してください。", "http-url": "安全でない (http) URL は使用できません。", "own-work-url": "あなた自身の作品を提出してください。", - "publicly-visible-url": "公開されたアプリの URL を提出してください。" + "publicly-visible-url": "公開されたアプリの URL を提出してください。", + "path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path" }, "certification": { "executive": "freeCodeCamp.org エグゼクティブ・ディレクター", @@ -594,12 +605,12 @@ "issued": "発行日", "fulltext": "<0>ここに <1>{{user}} <2>が freeCodeCamp.org の約 {{time}} 時間の課程に相当する <3>{{title}} <4>開発者認定講座を修了したことを証明します。", "project": { - "heading-legacy-full-stack": "このレガシーフルスタック認定講座の一環として、{{user}} は以下の認定講座を修了しました:", - "heading": "この認定講座の一環として、{{user}} は以下のプロジェクトを完成させ、すべての自動テストスイートに合格しました:", + "heading-legacy-full-stack": "レガシーフルスタック認定講座の一環として、{{user}} は以下の認定講座を修了しました:", + "heading": "この認定講座の一環として、{{user}} は以下のプロジェクトを完成させ、すべての自動テストスイートに合格しました。", "solution": "解答", "no-solution": "解答の表示中にエラーが発生しました。 support@freeCodeCamp.org までメールにてお問い合わせください。", "source": "ソースコード", - "footnote": "これらのプロジェクトのいずれかが <2>学問的誠実性ポリシー に違反すると思われる場合、<5>freeCodeCamp チームに報告 してください。", + "footnote": "これらのプロジェクトのいずれかが<2>学問的誠実性ポリシーに反すると思われる場合は、<5>freeCodeCamp チームに報告してください。", "title": { "Build a Personal Portfolio Webpage": "個人ポートフォリオのウェブページを作成する", "Build a Random Quote Machine": "ランダムクォートマシンを作成する", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "猫と犬の画像分類プログラム", "Book Recommendation Engine using KNN": "KNN を使用した書籍推薦エンジン", "Linear Regression Health Costs Calculator": "線形回帰による医療費の計算プログラム", - "Neural Network SMS Text Classifier": "ニューラルネットワークによる SMS テキスト分類プログラム" + "Neural Network SMS Text Classifier": "ニューラルネットワークによる SMS テキスト分類プログラム", + "Celestial Bodies Database": "天体データベース", + "World Cup Database": "ワールドカップデータベース", + "Salon Appointment Scheduler": "サロン予約スケジューラー", + "Periodic Table Database": "周期表データベース", + "Number Guessing Game": "数当てゲーム", + "Build a freeCodeCamp Forum Homepage": "freeCodeCamp フォーラムのホームページを作成する" } + }, + "title": { + "Responsive Web Design": "レスポンシブウェブデザイン", + "responsive-web-design": "レスポンシブウェブデザイン認定証", + "JavaScript Algorithms and Data Structures": "JavaScript のアルゴリズムとデータ構造", + "javascript-algorithms-and-data-structures": "JavaScript のアルゴリズムとデータ構造認定証", + "Front End Development Libraries": "フロントエンド開発ライブラリ", + "front-end-development-libraries": "フロントエンド開発ライブラリ認定証", + "Data Visualization": "データ可視化", + "data-visualization": "データ可視化認定証", + "Relational Database": "リレーショナルデータベース", + "relational-database-v8": "リレーショナルデータベース認定証", + "Back End Development and APIs": "バックエンド開発と API", + "back-end-development-and-apis": "バックエンド開発と API 認定証", + "Quality Assurance": "品質保証", + "quality-assurance-v7": "品質保証認定証", + "Scientific Computing with Python": "Python を用いた科学技術計算", + "scientific-computing-with-python-v7": "Python を用いた科学技術計算認定証", + "Data Analysis with Python": "Python を用いたデータ分析", + "data-analysis-with-python-v7": "Python を用いたデータ分析認定証", + "Information Security": "情報セキュリティ", + "information-security-v7": "情報セキュリティ認定証", + "Machine Learning with Python": "Python を用いた機械学習", + "machine-learning-with-python-v7": "Python を用いた機械学習認定証", + "Legacy Front End": "(レガシー) フロントエンド", + "legacy-front-end": "フロントエンド認定証", + "Legacy Back End": "(レガシー) バックエンド", + "legacy-back-end": "バックエンド認定証", + "Legacy Data Visualization": "(レガシー) データ可視化", + "legacy-data-visualization": "データ可視化認定証", + "Legacy Information Security and Quality Assurance": "(レガシー) 情報セキュリティと品質保証認定証", + "information-security-and-quality-assurance": "情報セキュリティと品質保証認定証", + "Legacy Full Stack Certification": "(レガシー) フルスタック認定証", + "Legacy Full Stack": "(レガシー) フルスタック", + "full-stack": "フルスタック認定証" } }, "certification-card": { @@ -725,7 +777,7 @@ }, "signout": { "heading": "アカウントからサインアウト", - "p1": "注意: サインアウト後は進行状況が保存されません。", + "p1": "注意: サインアウト状態では進行状況が保存されません。", "p2": "この操作では、このデバイスおよびブラウザーセッションのみを対象にサインアウトされます。サインアウトしてよろしいですか?", "certain": "はい、サインアウトします", "nevermind": "いいえ、サインアウトしません" diff --git a/client/i18n/locales/portuguese/intro.json b/client/i18n/locales/portuguese/intro.json index e6e28507998712..ec714009352a59 100644 --- a/client/i18n/locales/portuguese/intro.json +++ b/client/i18n/locales/portuguese/intro.json @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "Aprenda programação funcional criando uma planilha", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Aprenda métodos de arrays avançados criando uma calculadora de estatística", + "intro": ["", ""] } } }, @@ -553,7 +557,7 @@ "intro": [ "Até esse ponto, você usou JavaScript apenas no front-end para adicionar interatividade a uma página, resolver desafios de algoritmos ou construir uma SPA. Mas o JavaScript também pode ser usado no back-end, ou servidor, para construir aplicações web inteiras.", "Hoje em dia, uma das formas populares de se criar aplicações é através do uso de microsserviços, que são pequenas aplicações modulares que trabalham em conjunto para formar uma aplicação maior inteira.", - "Na certificação de APIs e desenvolvimento de back-end, você aprenderá a escrever aplicações de back-end com o Node.js e o npm (Node Package Manager). Você também vai construir aplicações web com o framework Express e criará um microsserviço de localização de pessoas com o MongoDB e com a biblioteca Mongoose." + "Na certificação de APIs e desenvolvimento de back-end, você aprenderá a escrever aplicações de back-end com o Node.js e o npm. Você também vai construir aplicações web com o framework Express e criará um microsserviço de localização de pessoas com o MongoDB e com a biblioteca Mongoose." ], "note": "", "blocks": { @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "The Odin Project", + "intro": [ + "The Odin Project é um daqueles recursos do tipo \"O que eu gostaria de ter visto quando estava aprendendo\". ", + "Nem todas as pessoas têm acesso à educação em ciência da computação ou aos fundos necessários para frequentar uma escola de programação intensiva. De qualquer modo, não necessariamente, essas duas sejam a solução final para todos que queiram aprender.", + "Este projeto destina-se a preencher a lacuna para aquelas pessoas que tentam buscar suas próprias soluções, mas que continuam procurando uma educação de alta qualidade." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Aprenda o básico de HTML", + "intro": ["Uma descrição deve ser determinada"] + }, + "top-build-a-recipe-project": { + "title": "Aprenda o básico de HTML criando uma página de receitas", + "intro": ["Uma descrição deve ser determinada"] + } + } + }, "misc-text": { "certification": "Certificação {{cert}}", "browse-other": "Navegue por nossas outras certificações gratuitas\n(recomendamos fazer isto em sequência)", diff --git a/client/i18n/locales/portuguese/translations.json b/client/i18n/locales/portuguese/translations.json index 77041c9b3c0c7e..7e5f9e76452879 100644 --- a/client/i18n/locales/portuguese/translations.json +++ b/client/i18n/locales/portuguese/translations.json @@ -11,11 +11,12 @@ "view": "Visualizar", "view-code": "Ver código", "view-project": "Ver o projeto", + "view-cert-title": "Ver {{certTitle}}", "show-cert": "Exibir certificado", "claim-cert": "Solicitar certificação", "save-progress": "Salvar progresso", - "accepted-honesty": "Você aceitou nossa política de honestidade acadêmica.", - "agree": "Aceitar", + "accepted-honesty": "Você concordou com nossa política de honestidade acadêmica.", + "agree-honesty": "Concordo com a Política de Honestidade Acadêmica do FreeCodeCamp.", "save-portfolio": "Salvar esse item de portfólio", "remove-portfolio": "Remover este item de portfólio", "add-portfolio": "Adicionar um novo item de portfólio", @@ -52,7 +53,7 @@ "check-code": "Verifique seu código (Ctrl + Enter)", "check-code-2": "Verifique seu código", "reset": "Redefinir", - "reset-code": "Redefinir todo o código", + "reset-step": "Reiniciar este passo", "help": "Ajuda", "get-help": "Obter ajuda", "watch-video": "Assistir a um vídeo", @@ -157,7 +158,8 @@ "honesty": "Política de honestidade acadêmica", "internet": "Sua presença na internet", "portfolio": "Configurações do portfólio", - "privacy": "Configurações de privacidade" + "privacy": "Configurações de privacidade", + "personal-info": "Informações pessoais" }, "danger": { "heading": "Zona de perigo", @@ -222,16 +224,15 @@ "total-points_plural": "{{count}} pontos no total", "points": "{{count}} ponto em {{date}}", "points_plural": "{{count}} pontos em {{date}}", - "screen-shot": "Uma captura de tela de {{title}}", "page-number": "{{pageNumber}} de {{totalPages}}" }, "footer": { - "tax-exempt-status": "O freeCodeCamp é uma organização sem fins lucrativos apoiada por doadores e isenta de impostos 501(c)(3) (Número de identificação fiscal federal dos Estados Unidos: 82-0779546)", + "tax-exempt-status": "O freeCodeCamp é uma organização beneficente 501(c)(3), isenta de impostos e apoiada por doações (Número de identificação fiscal federal dos Estados Unidos: 82-0779546).", "mission-statement": "Nossa missão: ajudar as pessoas a aprender a programar de graça. Nós conseguimos isso através da criação de milhares de vídeos, artigos e aulas interativas de programação – tudo disponível gratuitamente para o público. Também temos milhares de grupos de estudo do freeCodeCamp espalhados por todo o mundo.", "donation-initiatives": "Doações para o freeCodeCamp vão para as nossas iniciativas educacionais e ajudam a pagar por servidores, serviços e equipe.", "donate-text": "Você pode <1>fazer uma doação dedutível de imposto aqui.", "trending-guides": "Guias em alta", - "our-nonprofit": "Nossa organização sem fins lucrativos", + "our-nonprofit": "Nossa instituição", "links": { "about": "Sobre", "alumni": "Rede de ex-alunos", @@ -249,6 +250,7 @@ }, "learn": { "heading": "Boas-vindas ao currículo do freeCodeCamp.", + "skip-to-content": "Ir para o conteúdo", "welcome-1": "Bem-vindo(a) de volta, {{name}}.", "welcome-2": "Boas-vindas ao freeCodeCamp.org", "start-at-beginning": "Se você é novo em programação, recomendamos que você <0>comece no início.", @@ -272,6 +274,9 @@ "add-subtitles": "Ajudar a melhorar ou adicionar legendas", "wrong-answer": "Desculpe, essa não é a resposta correta. Quer tentar novamente?", "check-answer": "Clique no botão abaixo para verificar sua resposta.", + "assignment-not-complete": "Termine as tarefas", + "assignments": "Tarefas", + "question": "Questão", "solution-link": "Link da solução", "github-link": "Link do GitHub", "submit-and-go": "Enviar e ir para o meu próximo desafio", @@ -297,7 +302,6 @@ "certs": "Certificação {{title}}" }, "editor-tabs": { - "info": "Informações", "code": "Código", "tests": "Testes", "restart": "Reiniciar", @@ -307,6 +311,10 @@ "notes": "Observações", "preview": "Pré-visualizar" }, + "editor-alerts": { + "tab-trapped": "Ao apertar a tecla tab, agora, você vai inserir o caractere de tabulação", + "tab-free": "Ao apertar a tecla tab, agora, você moverá o foco para o próximo elemento que possa ser focado" + }, "help-translate": "Ainda estamos traduzindo as certificações a seguir.", "help-translate-link": "Ajude-nos a traduzir.", "project-preview-title": "Aqui está uma prévia do que você vai criar", @@ -327,12 +335,12 @@ "sorry-dont-giveup": "Desculpe, seu código não passou nos testes. Não desista.", "challenges-completed": "{{completedCount}} de {{totalChallenges}} desafios concluídos", "season-greetings-fcc": "Boas festas de fim de ano, da comunidade do freeCodeCamp 🎉", - "if-getting-value": "Se você está conseguindo tirar proveito do conteúdo do freeCodeCamp, agora é um ótimo momento para fazer sua doação e apoiar nossa missão sem fins lucrativos.", + "if-getting-value": "Se você está conseguindo tirar proveito do conteúdo do freeCodeCamp, agora é um ótimo momento para fazer sua doação e apoiar nossa missão beneficente.", "building-a-university": "Estamos criando um programa gratuito de graduação em Ciência da Computação", "if-help-university": "Já fizemos um progresso enorme. Apoie nossa organização sem fins lucrativos com o longo caminho que temos pela frente." }, "donate": { - "title": "Dê seu apoio à nossa organização sem fins lucrativos", + "title": "Ajude nossa instituição", "processing": "Estamos processando a sua doação.", "redirecting": "Redirecionando...", "thanks": "Agradecemos por sua doação", @@ -355,10 +363,9 @@ "your-donation-2": "Sua doação de US${{usd}} proporcionará {{hours}} horas mensais de aprendizado para pessoas ao redor do mundo.", "your-donation-3": "Sua doação de US${{usd}} proporcionará {{hours}} horas anuais de aprendizado para pessoas ao redor do mundo.", "become-supporter": "Torne-se um apoiador", - "duration": "Torne-se um apoiador por doação única da nossa organização sem fins lucrativos.", - "duration-2": "Torne-se um apoiador mensal da nossa organização sem fins lucrativos.", - "duration-3": "Torne-se um apoiador anual da nossa organização sem fins lucrativos", - "duration-4": "Torne-se um apoiador da nossa organização sem fins lucrativos", + "duration": "Torne-se um apoiador com uma doação única para nossa organização beneficente.", + "duration-2": "Torne-se um apoiador mensal da nossa organização beneficente.", + "duration-4": "Torne-se um apoiador da nossa organização beneficente", "nicely-done": "Bom trabalho. Você acabou de completar {{block}}.", "credit-card": "Cartão de crédito", "credit-card-2": "Ou doe com um cartão de crédito:", @@ -372,25 +379,25 @@ "email-receipt": "E-mail (enviaremos um comprovante de doação):", "need-help": "Precisa de ajuda com suas doações atuais ou anteriores?", "forward-receipt": "Envie uma cópia do recibo de sua doação para donors@freecodecamp.org e nos diga como podemos ajudar.", - "efficiency": "O freeCodeCamp é uma organização educacional, sem fins lucrativos, e altamente eficiente.", + "efficiency": "O freeCodeCamp é uma organização educacional, beneficente e de grande eficácia.", "why-donate-1": "Quando você doa para o freeCodeCamp, você ajuda as pessoas a aprender novas habilidades e sustentar suas famílias.", "why-donate-2": "Você também nos ajuda a criar novos recursos que você pode usar para melhorar as suas próprias habilidades tecnológicas.", "bigger-donation": "Quer fazer uma doação maior de uma única vez, enviar-nos um cheque ou doar de outras maneiras?", - "other-ways": "Aqui estão muitas <0>outras maneiras para ajudar a nossa missão sem fins lucrativos.", + "other-ways": "Aqui estão muitas <0>outras maneiras para ajudar a nossa missão beneficente.", "failed-pay": "Opa. Parece que a sua transação não funcionou. Você poderia tentar de novo?", "try-again": "Tente novamente.", "card-number": "Número do seu cartão:", "expiration": "Data de validade:", "secure-donation": "Doação segura", "faq": "Perguntas frequentes", - "only-you": "Só você pode ver esta mensagem. Parabéns por ganhar este certificado. Não é uma tarefa fácil. Manter o freeCodeCamp também não é fácil. Nem é barato. Ajude-nos a ajudar você e muitas outras pessoas ao redor do mundo. Faça uma dedução de impostos doando para nossa organização sem fins lucrativos hoje.", + "only-you": "Só você pode ver esta mensagem. Parabéns por ganhar este certificado. Não é uma tarefa fácil. Manter o freeCodeCamp também não é fácil. Nem é barato. Ajude-nos a ajudar você e muitas outras pessoas ao redor do mundo. Faça uma dedução de impostos doando para nossa organização beneficente hoje.", "get-help": "Como posso obter ajuda com minhas doações?", "how-transparent": "Qual é o nível de transparência do freeCodeCamp.org?", "very-transparent": "Grande. Temos uma classificação de transparência Platinum do GuideStar.org.", "download-irs": "Você pode <0>baixar nossa Carta de Determinação do IRS aqui.", "download-990": "Você pode <0>baixar nosso último 990 (relatório anual de impostos) aqui.", "how-efficient": "Qual é o nível de eficiência do freeCodeCamp?", - "fcc-budget": "O orçamento do freeCodeCamp é muito menor do que o da maioria das organizações sem fins lucrativos. Não temos profissionais em arrecadação de fundos. Em vez disso, Quincy faz tudo por conta própria.", + "fcc-budget": "O orçamento do freeCodeCamp é muito menor do que o da maioria das organizações beneficentes. Não temos profissionais em arrecadação de fundos. Em vez disso, Quincy faz tudo por conta própria.", "help-millions": "No entanto, com um orçamento de apenas algumas centenas de milhares de dólares por ano, conseguimos ajudar milhões de pessoas.", "how-one-time": "Como posso fazer uma doação única?", "one-time": "Se você preferir fazer doações únicas, pode apoiar a missão do freeCodeCamp sempre que tiver dinheiro sobrando. Você pode usar <0>este link para doar qualquer quantia que sentir que vale a pena através do PayPal.", @@ -400,7 +407,7 @@ "can-check": "Posso enviar um cheque físico?", "yes-check": "Sim, receberemos cheques com satisfação. Você pode nos enviar cheques pelo correio pelo endereço:", "how-matching-gift": "Como eu posso configurar donativos correspondentes do meu empregador, ou deduções na folha de pagamento?", - "employers-vary": "Isso varia de empregador para empregador. Nossa organização sem fins lucrativos já está listada em muitas das grandes bases de dados de doações correspondentes.", + "employers-vary": "Isso varia de empregador para empregador. Nossa organização beneficente já está listada em muitos dos grandes bancos de dados de doações correspondentes.", "some-volunteer": "Algumas pessoas são capazes de se voluntariar para o freeCodeCamp e suas correspondências de empregador, doando uma quantidade fixa por hora que voluntariam. Outros empregadores corresponderão a quaisquer doações que os doadores pagarem até um certo valor", "help-matching-gift": "Se você precisar de ajuda com isso, envie um e-mail para o Quincy diretamente: quincy@freecodecamp.org", "how-endowment": "Como posso configurar um presente de dote para o freeCodeCamp.org?", @@ -411,13 +418,13 @@ "thank-wikimedia": "Gostaríamos de agradecer à Wikimedia Foundation por nos fornecer esta linguagem formal para utilizarmos.", "legacy-gift-questions": "Se você tiver alguma dúvida sobre este processo, envie um e-mail para quincy@freecodecamp.org.", "how-stock": "Como posso doar ações para freeCodeCamp.org?", - "welcome-stock": "Receberemos suas doações em ações com satisfação. Envie um e-mail para o Quincy diretamente e ele pode ajudá-lo com isso e compartilhar os detalhes de nossa conta de corretora sem fins lucrativos: quincy@freecodecamp.org.", + "welcome-stock": "Receberemos suas doações em ações com satisfação. Envie um e-mail para o Quincy diretamente e ele pode ajudá-lo com isso e compartilhar os detalhes da conta de corretora de nossa organização beneficente: quincy@freecodecamp.org.", "how-receipt": "Posso obter um recibo de doação para deduzi-la dos meus impostos?", "just-forward": "Claro. Basta encaminhar o recibo de sua transação para donors@freecodecamp.org, dizer que você gostaria de um recibo e quaisquer instruções especiais que você possa ter, e nós responderemos com um recibo para você.", "how-update": "Criei uma doação mensal, mas preciso atualizar ou pausar a recorrência mensal. Como posso fazer isso?", "take-care-of-this": "Apenas encaminhe um de seus recibos mensais para donors@freecodecamp.org e diga-nos o que você gostaria que fizéssemos. Cuidaremos disso para você e enviaremos sua confirmação.", "anything-else": "Há mais alguma coisa que eu possa aprender sobre doações para freeCodeCamp.org?", - "other-support": "Se você quiser apoiar a nossa organização sem fins lucrativos e a sua missão de alguma outra forma que não estiver listada aqui, ou se você tiver alguma dúvida, envie um e-mail para quincy@freecodecamp.org." + "other-support": "Se você quiser apoiar a nossa organização beneficente e a sua missão de alguma outra forma que não estiver listada aqui, ou se você tiver alguma dúvida, envie um e-mail para quincy@freecodecamp.org." }, "report": { "sign-in": "Você precisa estar logado para denunciar um usuário", @@ -460,7 +467,8 @@ "iframe-preview": "Visualização de {{title}}", "iframe-alert": "Normalmente, este link levaria você para outro site da web! Funciona. Esse é um link para: {{externalLink}}", "iframe-form-submit-alert": "Normalmente, esse formulário seria enviado! Funciona. Ele será enviado para: {{externalLink}}", - "document-notfound": "documento não encontrado" + "document-notfound": "documento não encontrado", + "slow-load-msg": "Parece que está demorando mais do que o normal. Tente atualizar a página." }, "icons": { "gold-cup": "Taça de ouro", @@ -475,10 +483,11 @@ "hint": "Dica", "heart": "Coração", "initial": "Inicial", + "input-reset": "Limpar termos de pesquisa", "info": "Informações introdutórias", "spacer": "Espaçador", "toggle": "Alternar marcação", - "magnifier": "lupa" + "magnifier": "Enviar termos de pesquisa" }, "aria": { "fcc-curriculum": "Currículo do freeCodeCamp", @@ -504,10 +513,11 @@ "step": "Passo", "steps": "Passos", "steps-for": "Passos para {{blockTitle}}", - "code-example": "{{codeName}} code example" + "code-example": "Exemplo de código de {{codeName}}", + "opens-new-window": "Abre em uma nova janela" }, "flash": { - "honest-first": "Para solicitar uma certificação, você precisa primeiro aceitar nossa política de honestidade acadêmica", + "honest-first": "Para solicitar uma certificação, você precisa primeiro concordar com nossa política de honestidade acadêmica", "really-weird": "Algo realmente estranho aconteceu. Se acontecer novamente, considere apresentar um problema pelo endereço https://github.com/freeCodeCamp/freeCodeCamp/issues/new", "not-right": "Algo não está certo. Um relatório foi gerado e a equipe do freeCodeCamp.org foi notificada", "went-wrong": "Algo deu errado. Verifique e tente novamente", @@ -586,7 +596,8 @@ "editor-url": "Lembre-se de enviar o URL do aplicativo em produção.", "http-url": "Não é possível usar um URL (http) inseguro.", "own-work-url": "Lembre-se de enviar o seu próprio trabalho.", - "publicly-visible-url": "Lembre-se de enviar o URL de um aplicativo publicamente visível." + "publicly-visible-url": "Lembre-se de enviar o URL de um aplicativo publicamente visível.", + "path-url": "Você provavelmente vai querer enviar o caminho raiz, ou seja, https://example.com em vez de https://example.com/path" }, "certification": { "executive": "Diretor executivo, freeCodeCamp.org", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "Classificador de imagens de gatos e cachorros", "Book Recommendation Engine using KNN": "Mecanismo de recomendação de livros usando KNN", "Linear Regression Health Costs Calculator": "Calculadora de custos de saúde de regressão linear", - "Neural Network SMS Text Classifier": "Classificador de texto SMS baseado em rede neural" + "Neural Network SMS Text Classifier": "Classificador de texto SMS baseado em rede neural", + "Celestial Bodies Database": "Banco de dados de corpos celestiais", + "World Cup Database": "Banco de dados da Copa do Mundo", + "Salon Appointment Scheduler": "Agendador de compromissos do salão de beleza", + "Periodic Table Database": "Banco de dados da tabela periódica", + "Number Guessing Game": "Jogo de adivinhação de números", + "Build a freeCodeCamp Forum Homepage": "Criar uma página inicial do fórum do freeCodeCamp" } + }, + "title": { + "Responsive Web Design": "Design responsivo para a web", + "responsive-web-design": "Certificação de design responsivo para a web", + "JavaScript Algorithms and Data Structures": "Algoritmos e estruturas de dados em JavaScript", + "javascript-algorithms-and-data-structures": "Certificação de algoritmos e estruturas de dados em JavaScript", + "Front End Development Libraries": "Bibliotecas de desenvolvimento em front-end", + "front-end-development-libraries": "Certificação de desenvolvimento com bibliotecas de front-end", + "Data Visualization": "Visualização de dados", + "data-visualization": "Certificação de visualização de dados", + "Relational Database": "Bancos de dados relacionais", + "relational-database-v8": "Certificação de bancos de dados relacionais", + "Back End Development and APIs": "APIs e desenvolvimento de back-end", + "back-end-development-and-apis": "Certificação de APIs e desenvolvimento de back-end", + "Quality Assurance": "Garantia de qualidade", + "quality-assurance-v7": "Certificação de garantia de qualidade", + "Scientific Computing with Python": "Computação científica em Python", + "scientific-computing-with-python-v7": "Certificação de computação científica em Python", + "Data Analysis with Python": "Análise de dados com Python", + "data-analysis-with-python-v7": "Certificação de análise de dados com Python", + "Information Security": "Segurança da informação", + "information-security-v7": "Certificação de segurança da informação", + "Machine Learning with Python": "Aprendizado de máquina com Python", + "machine-learning-with-python-v7": "Certificação de aprendizagem de máquina com Python", + "Legacy Front End": "Front-end legado", + "legacy-front-end": "Certificação de front-end", + "Legacy Back End": "Back-end legado", + "legacy-back-end": "Certificação de back-end", + "Legacy Data Visualization": "Visualização de dados legada", + "legacy-data-visualization": "Certificação de visualização de dados", + "Legacy Information Security and Quality Assurance": "Segurança da informação e garantia da qualidade legado", + "information-security-and-quality-assurance": "Certificação de segurança da informação e garantia da qualidade", + "Legacy Full Stack Certification": "Certificação de full-stack legada", + "Legacy Full Stack": "Full-stack legado", + "full-stack": "Certificação de full-stack" } }, "certification-card": { diff --git a/client/i18n/locales/ukrainian/intro.json b/client/i18n/locales/ukrainian/intro.json index b725c1a96c7792..7d87231daf963f 100644 --- a/client/i18n/locales/ukrainian/intro.json +++ b/client/i18n/locales/ukrainian/intro.json @@ -335,6 +335,10 @@ "learn-functional-programming-by-building-a-spreadsheet": { "title": "Вивчіть функційне програмування, створивши електронну таблицю", "intro": ["", ""] + }, + "learn-advanced-array-methods-by-building-a-statistics-calculator": { + "title": "Вивчіть передові методи масиву, створивши статистичний калькулятор", + "intro": ["", ""] } } }, @@ -553,7 +557,7 @@ "intro": [ "До цього моменту ви використовували JavaScript тільки для фронтенду, аби зробити вебсторінку інтерактивнішою, розв'язати завдання з алгоритмами, або створити SPA. Але JavaScript можна використовувати й в бекенд, або на сервері, для створення цілих вебзастосунків.", "Сьогодні один із найпопулярніших способів створення застосунків – за допомогою мікросервісів, маленьких модульних застосунків, які разом формують єдине ціле.", - "У сертифікації «Розробка Back End та API» ви навчитеся писати бекенд програми за допомогою Node.js та npm (Node Package Manager). Також, ви створите вебзастосунок за допомогою фреймворку Express та мікросервіс для пошуку людей за допомогою MongoDB і Mongoose library." + "У сертифікації «Розробка Back End та API» ви навчитеся писати бекенд програми за допомогою Node.js та npm. Ви також створите вебзастосунок за допомогою фреймворку Express та мікросервіс для пошуку людей за допомогою MongoDB і бібліотеки Mongoose." ], "note": "", "blocks": { @@ -787,6 +791,24 @@ } } }, + "the-odin-project": { + "title": "Проєкт «Odin»", + "intro": [ + "Проєкт «Odin» є одним з тих ресурсів, про які хотіли б дізнатися ще коли навчались. ", + "Не кожен має доступ до технологічної освіти або коштів, необхідних для відвідування інтенсивної школи. Однак це не остаточне рішення для тих, хто хоче вчитися.", + "Цей проєкт розроблений, щоб заповнити прогалину для людей, які намагаються вчитись самостійно, але все ж таки хочуть високоякісну освіту." + ], + "blocks": { + "top-learn-html-foundations": { + "title": "Вивчіть основи HTML", + "intro": ["Опис буде надано пізніше"] + }, + "top-build-a-recipe-project": { + "title": "Вивчіть основи HTML, побудувавши сторінку з рецептами", + "intro": ["Опис буде надано пізніше"] + } + } + }, "misc-text": { "certification": "Сертифікація «{{cert}}»", "browse-other": "Перегляньте інші безоплатні сертифікації\n(ми рекомендуємо виконувати їх послідовно)", diff --git a/client/i18n/locales/ukrainian/translations.json b/client/i18n/locales/ukrainian/translations.json index c92dcd89329fb3..5e05d9600c079f 100644 --- a/client/i18n/locales/ukrainian/translations.json +++ b/client/i18n/locales/ukrainian/translations.json @@ -11,11 +11,12 @@ "view": "Перегляд", "view-code": "Переглянути код", "view-project": "Переглянути проєкт", + "view-cert-title": "Переглянути {{certTitle}}", "show-cert": "Показати сертифікацію", "claim-cert": "Отримати сертифікацію", "save-progress": "Зберегти прогрес", - "accepted-honesty": "Ви прийняли нашу Політику академічної доброчесності.", - "agree": "Прийняти", + "accepted-honesty": "Ви погодились з нашою політикою академічної доброчесності.", + "agree-honesty": "Я погоджуюсь з політикою академічної доброчесності freeCodeCamp.", "save-portfolio": "Зберегти цей елемент портфоліо", "remove-portfolio": "Видалити цей елемент портфоліо", "add-portfolio": "Додати новий елемент портфоліо", @@ -52,7 +53,7 @@ "check-code": "Перевірити код (Ctrl + Enter)", "check-code-2": "Перевірити код", "reset": "Скинути", - "reset-code": "Скинути весь код", + "reset-step": "Скинути цей крок", "help": "Допомога", "get-help": "Отримати допомогу", "watch-video": "Подивитися відео", @@ -157,7 +158,8 @@ "honesty": "Політика академічної доброчесності", "internet": "Ваші соціальні мережі", "portfolio": "Налаштування портфоліо", - "privacy": "Налаштування конфіденційності" + "privacy": "Налаштування конфіденційності", + "personal-info": "Особиста інформація" }, "danger": { "heading": "Небезпечна зона", @@ -183,7 +185,7 @@ "check": "Будь ласка, перевірте свою електронну пошту, або <0>надішліть запит на новий лист для підтвердження.", "current": "Поточна адреса електронної пошти", "new": "Нова адреса електронної пошти", - "confirm": "Підтвердити нову адресу електронної пошти", + "confirm": "Підтвердіть нову адресу електронної пошти", "weekly": "Надсилати мені щотижневу розсилку від Квінсі" }, "honesty": { @@ -222,7 +224,6 @@ "total-points_plural": "Всього балів: {{count}}", "points": "{{count}}х балів станом на {{date}}", "points_plural": "{{count}}х балів станом на {{date}}", - "screen-shot": "Знімок екрану {{title}}", "page-number": "{{pageNumber}} з {{totalPages}}" }, "footer": { @@ -231,7 +232,7 @@ "donation-initiatives": "Внески до freeCodeCamp йдуть на наші освітні програми та допомагають оплачувати сервери, послуги та персонал.", "donate-text": "Ви можете <1>зробити неоподаткований внесок тут.", "trending-guides": "Популярні статті", - "our-nonprofit": "Наша некомерційна організація", + "our-nonprofit": "Наша організація", "links": { "about": "Про нас", "alumni": "Спільнота випускників", @@ -249,9 +250,10 @@ }, "learn": { "heading": "Ласкаво просимо до навчальної програми freeCodeCamp.", + "skip-to-content": "Перейти до змісту", "welcome-1": "З поверненням, {{name}}.", "welcome-2": "Ласкаво просимо до freeCodeCamp.org", - "start-at-beginning": "Якщо ви новачок у програмуванні, ми рекомендуємо <0>почати з самого початку.", + "start-at-beginning": "Якщо ви новачок у програмуванні, ми рекомендуємо <0>почати з початку.", "read-this": { "heading": "Будь ласка, прочитайте це.", "p1": "freeCodeCamp – це перевірений шлях до вашої першої роботи розробника програмного забезпечення.", @@ -272,6 +274,9 @@ "add-subtitles": "Допомогти покращити або додати субтитри", "wrong-answer": "Нам шкода, але це неправильна відповідь. Спробуєте ще раз?", "check-answer": "Натисніть кнопку нижче, щоб перевірити свою відповідь.", + "assignment-not-complete": "Будь ласка, завершіть завдання", + "assignments": "Завдання", + "question": "Запитання", "solution-link": "Посилання на рішення", "github-link": "Посилання на GitHub", "submit-and-go": "Відправити та перейти до мого наступного завдання", @@ -297,7 +302,6 @@ "certs": "Сертифікація «{{title}}»" }, "editor-tabs": { - "info": "Інформація", "code": "Код", "tests": "Тести", "restart": "Перезапустити", @@ -307,6 +311,10 @@ "notes": "Примітки", "preview": "Попередній перегляд" }, + "editor-alerts": { + "tab-trapped": "При натисканні клавіші tab ви вставите символ табуляції", + "tab-free": "При натисканні клавіші tab ви перемістите фокус на наступний елемент, який можна сфокусувати" + }, "help-translate": "Ми досі перекладаємо наступні сертифікації.", "help-translate-link": "Допоможіть нам з перекладом.", "project-preview-title": "Попередній перегляд того, що ви будете створювати", @@ -332,7 +340,7 @@ "if-help-university": "Ми вже зробили багато роботи. Підтримайте довгий шлях нашої благодійної організації." }, "donate": { - "title": "Підтримати нашу некомерційну організацію", + "title": "Підтримайте нашу організацію", "processing": "Ми опрацьовуємо ваш внесок.", "redirecting": "Переадресація...", "thanks": "Дякуємо за внесок", @@ -357,7 +365,6 @@ "become-supporter": "Зробити внесок", "duration": "Станьте одноразовим спонсором нашої некомерційної організації.", "duration-2": "Станьте спонсором нашої некомерційної організації (щомісячний внесок).", - "duration-3": "Станьте спонсором нашої некомерційної організації (щорічний внесок).", "duration-4": "Станьте спонсором нашої некомерційної організації", "nicely-done": "Чудово. Ви щойно завершили {{block}}.", "credit-card": "Кредитна картка", @@ -460,7 +467,8 @@ "iframe-preview": "Передперегляд {{title}}", "iframe-alert": "Зазвичай це посилання перенесло б вас на інший вебсайт! Воно працює. Це посилання на: {{externalLink}}", "iframe-form-submit-alert": "Зазвичай ця форма буде відправлена! Вона буде відправлена на: {{externalLink}}", - "document-notfound": "документ не знайдено" + "document-notfound": "документ не знайдено", + "slow-load-msg": "Схоже, це займає більше часу, ніж зазвичай. Будь ласка, спробуйте оновити сторінку." }, "icons": { "gold-cup": "Золотий кубок", @@ -475,10 +483,11 @@ "hint": "Підказка", "heart": "Серце", "initial": "Початковий", + "input-reset": "Очистити пошукові запити", "info": "Інформація", "spacer": "Роздільник", "toggle": "Перемкнути галочку", - "magnifier": "лупа" + "magnifier": "Надіслати пошукові запити" }, "aria": { "fcc-curriculum": "Навчальний план freeCodeCamp", @@ -504,10 +513,11 @@ "step": "Крок", "steps": "Кроки", "steps-for": "Кроки для {{blockTitle}}", - "code-example": "{{codeName}} code example" + "code-example": "Приклад коду {{codeName}}", + "opens-new-window": "Відкривається у новому вікні" }, "flash": { - "honest-first": "Щоб отримати сертифікацію, ви повинні спочатку прийняти нашу політику академічної доброчесності", + "honest-first": "Щоб отримати сертифікацію, ви повинні спочатку погодитись з нашою політикою академічної доброчесності", "really-weird": "Щось пішло не так. Якщо це повториться, будь ласка, повідомте про це за посиланням: https://github.com/freeCodeCamp/freeCodeCamp/issues/new", "not-right": "Щось пішло не так. Звіт було сформовано і команду freeCodeCamp.org вже сповістили.", "went-wrong": "Щось пішло не так. Будь ласка, перевірте та повторіть спробу.", @@ -586,7 +596,8 @@ "editor-url": "Не забудьте відправити Live App URL-адресу.", "http-url": "Не можна використовувати ненадійну (http) URL-адресу.", "own-work-url": "Не забудьте відправити власну роботу.", - "publicly-visible-url": "Не забудьте відправити загальнодоступну URL-адресу додатку." + "publicly-visible-url": "Не забудьте відправити загальнодоступну URL-адресу додатку.", + "path-url": "Можливо, ви хочете надіслати кореневий шлях, тобто https://example.com, а не https://example.com/path" }, "certification": { "executive": "Виконавчий директор, freeCodeCamp.org", @@ -668,8 +679,49 @@ "Cat and Dog Image Classifier": "Класифікатор зображень котів і собак", "Book Recommendation Engine using KNN": "Інструмент рекомендацій книг із використанням KNN", "Linear Regression Health Costs Calculator": "Калькулятор лінійної регресії витрат на охорону здоров'я", - "Neural Network SMS Text Classifier": "Нейронна мережа для класифікації текстових SMS" + "Neural Network SMS Text Classifier": "Нейронна мережа для класифікації текстових SMS", + "Celestial Bodies Database": "База даних «Небесні тіла»", + "World Cup Database": "База даних «Чемпіонат світу»", + "Salon Appointment Scheduler": "Планувальник «Записи в салоні»", + "Periodic Table Database": "База даних «Періодична таблиця»", + "Number Guessing Game": "Гра «Вгадай число»", + "Build a freeCodeCamp Forum Homepage": "Створіть головну сторінку для форуму freeCodeCamp" } + }, + "title": { + "Responsive Web Design": "Адаптивний вебдизайн", + "responsive-web-design": "Сертифікація «Адаптивний вебдизайн»", + "JavaScript Algorithms and Data Structures": "Алгоритми JavaScript та структури даних", + "javascript-algorithms-and-data-structures": "Сертифікація «Алгоритми JavaScript та структури даних»", + "Front End Development Libraries": "Бібліотеки Front End", + "front-end-development-libraries": "Сертифікація «Бібліотеки Front End»", + "Data Visualization": "Візуалізація даних", + "data-visualization": "Сертифікація «Візуалізація даних»", + "Relational Database": "Реляційна база даних", + "relational-database-v8": "Сертифікація «Реляційна база даних»", + "Back End Development and APIs": "Розробка Back End та API", + "back-end-development-and-apis": "Сертифікація «Розробка Back End та API»", + "Quality Assurance": "Забезпечення якості", + "quality-assurance-v7": "Сертифікація «Забезпечення якості»", + "Scientific Computing with Python": "Наукові обчислення з Python", + "scientific-computing-with-python-v7": "Сертифікація «Наукові обчислення з Python»", + "Data Analysis with Python": "Аналіз даних з Python", + "data-analysis-with-python-v7": "Сертифікація «Аналіз даних з Python»", + "Information Security": "Інформаційна безпека", + "information-security-v7": "Сертифікація «Інформаційна безпека»", + "Machine Learning with Python": "Машинне навчання з Python", + "machine-learning-with-python-v7": "Сертифікація «Машинне навчання з Python»", + "Legacy Front End": "Застарілий Front End", + "legacy-front-end": "Сертифікація «Front End»", + "Legacy Back End": "Застарілий Back End", + "legacy-back-end": "Сертифікація «Back End»", + "Legacy Data Visualization": "Застаріла візуалізація даних", + "legacy-data-visualization": "Сертифікація «Візуалізація даних»", + "Legacy Information Security and Quality Assurance": "Застаріла інформаційна безпека та забезпечення якості", + "information-security-and-quality-assurance": "Сертифікація «Інформаційна безпека та забезпечення якості»", + "Legacy Full Stack Certification": "Застаріла сертифікація «Full Stack»", + "Legacy Full Stack": "Застарілий Full Stack", + "full-stack": "Сертифікація «Full Stack»" } }, "certification-card": { diff --git a/client/i18n/schema-validation.ts b/client/i18n/schema-validation.ts index 02c0e86a1b6835..d9ccd807d23e10 100644 --- a/client/i18n/schema-validation.ts +++ b/client/i18n/schema-validation.ts @@ -215,7 +215,7 @@ const schemaValidation = ( if ( fileName === 'motivation' && !(fileJson.motivationalQuotes as MotivationalQuotes).every( - (object: object) => + object => Object.prototype.hasOwnProperty.call(object, 'quote') && Object.prototype.hasOwnProperty.call(object, 'author') ) diff --git a/client/package.json b/client/package.json index e9a1870600e159..a625e27daf1f1e 100644 --- a/client/package.json +++ b/client/package.json @@ -6,7 +6,7 @@ "private": true, "engines": { "node": ">=16", - "npm": ">=8" + "pnpm": "7" }, "repository": { "type": "git", @@ -19,44 +19,48 @@ "author": "freeCodeCamp ", "main": "none", "scripts": { - "prebuild": "npm --prefix ../ run create:config && npm run build:workers -- --env production", + "prebuild": "pnpm -w run create:config && pnpm run build:workers --env production", "build": "cross-env NODE_OPTIONS=\"--max-old-space-size=7168\" gatsby build --prefix-paths", "build:workers": "cross-env NODE_OPTIONS=\"--max-old-space-size=7168\" webpack --config ./webpack-workers.js", "clean": "gatsby clean", - "predevelop": "npm --prefix ../ run create:config && npm run build:workers -- --env development", + "predevelop": "pnpm -w run create:config && pnpm run build:workers --env development", "develop": "cross-env NODE_OPTIONS=\"--max-old-space-size=5000\" gatsby develop --inspect=9230", "lint": "ts-node ./i18n/schema-validation.ts", "serve": "gatsby serve -p 8000", "serve-ci": "serve -l 8000 -c serve.json public", - "prestand-alone": "npm run prebuild", + "prestand-alone": "pnpm run prebuild", "stand-alone": "gatsby develop", "validate-keys": "ts-node --project ../tsconfig.json ../tools/scripts/lint/validate-keys" }, "dependencies": { "@babel/plugin-proposal-export-default-from": "7.18.10", "@babel/plugin-proposal-function-bind": "7.18.9", + "@babel/plugin-transform-runtime": "^7.19.6", "@babel/polyfill": "7.12.1", "@babel/preset-env": "7.20.2", "@babel/preset-react": "7.18.6", - "@babel/standalone": "7.20.6", - "@fortawesome/fontawesome-svg-core": "6.2.1", - "@fortawesome/free-brands-svg-icons": "6.2.1", - "@fortawesome/free-solid-svg-icons": "6.2.1", + "@babel/runtime": "^7.20.13", + "@babel/standalone": "7.20.15", + "@fortawesome/fontawesome-svg-core": "6.3.0", + "@fortawesome/free-brands-svg-icons": "6.3.0", + "@fortawesome/free-solid-svg-icons": "6.3.0", "@fortawesome/react-fontawesome": "0.2.0", "@freecodecamp/curriculum-helpers": "1.1.0", "@freecodecamp/loop-protect": "3.0.0", "@freecodecamp/react-bootstrap": "0.32.3", - "@freecodecamp/react-calendar-heatmap": "1.0.0", + "@freecodecamp/react-calendar-heatmap": "1.1.0", "@freecodecamp/strip-comments": "3.0.1", - "@growthbook/growthbook-react": "0.10.1", - "@loadable/component": "5.15.2", + "@growthbook/growthbook-react": "0.12.0", + "@loadable/component": "5.15.3", "@reach/router": "1.3.4", + "@redux-saga/core": "^1.2.2", "@sentry/gatsby": "6.19.7", - "@stripe/react-stripe-js": "1.16.0", - "@stripe/stripe-js": "1.46.0", - "@types/react-scrollable-anchor": "0.6.1", - "algoliasearch": "4.14.2", + "@stripe/react-stripe-js": "1.16.5", + "@stripe/stripe-js": "1.48.0", + "@testing-library/jest-dom": "5.16.5", + "algoliasearch": "4.15.0", "assert": "2.0.0", + "babel-loader": "8.3.0", "babel-plugin-preval": "5.1.0", "babel-plugin-prismjs": "2.1.0", "bezier-easing": "2.1.0", @@ -64,34 +68,38 @@ "buffer": "6.0.3", "chai": "4.3.7", "crypto-browserify": "3.12.0", - "date-fns": "2.27.0", + "date-fns": "2.29.3", "enzyme": "3.11.0", "enzyme-adapter-react-16": "1.15.7", - "final-form": "4.20.7", - "gatsby": "3.14.6", - "gatsby-cli": "3.14.2", + "eslint": "7", + "final-form": "4.20.9", + "gatsby": "3.15.0", + "gatsby-cli": "3.15.0", + "gatsby-link": "3.15.0", "gatsby-plugin-advanced-sitemap": "2.1.0", - "gatsby-plugin-create-client-paths": "3.14.0", - "gatsby-plugin-manifest": "3.14.0", - "gatsby-plugin-postcss": "4.14.0", - "gatsby-plugin-react-helmet": "4.14.0", + "gatsby-plugin-create-client-paths": "3.15.0", + "gatsby-plugin-manifest": "3.15.0", + "gatsby-plugin-pnpm": "^1.2.10", + "gatsby-plugin-postcss": "4.15.0", + "gatsby-plugin-react-helmet": "4.15.0", "gatsby-plugin-remove-serviceworker": "1.0.0", - "gatsby-remark-prismjs": "5.11.0", - "gatsby-source-filesystem": "3.14.0", - "gatsby-transformer-remark": "4.11.0", + "gatsby-remark-prismjs": "5.12.0", + "gatsby-source-filesystem": "3.15.0", + "gatsby-transformer-remark": "4.12.0", "i18next": "20.6.1", - "jquery": "3.6.1", + "jquery": "3.6.3", "lodash": "4.17.21", "lodash-es": "4.17.21", "monaco-editor": "0.28.1", "nanoid": "3.3.4", "normalize-url": "4.5.1", "path-browserify": "1.0.1", - "postcss": "8.4.19", + "postcss": "8.4.21", "prismjs": "1.29.0", "process": "0.11.10", "prop-types": "15.8.1", - "query-string": "7.0.1", + "qrcode.react": "^3.1.0", + "query-string": "7.1.3", "react": "16.14.0", "react-dom": "16.14.0", "react-final-form": "6.5.9", @@ -100,8 +108,8 @@ "react-helmet": "6.1.0", "react-hotkeys": "2.0.0", "react-i18next": "11.18.6", - "react-instantsearch-dom": "6.38.1", - "react-lazy-load": "3.1.14", + "react-instantsearch-core": "6.39.0", + "react-instantsearch-dom": "6.39.0", "react-monaco-editor": "0.40.0", "react-redux": "5.1.2", "react-reflex": "4.0.9", @@ -111,30 +119,56 @@ "react-tooltip": "4.5.1", "react-transition-group": "4.4.5", "react-youtube": "7.14.0", - "redux": "4.2.0", + "redux": "4.2.1", "redux-actions": "2.6.5", "redux-devtools-extension": "2.13.9", "redux-observable": "1.2.0", - "redux-saga": "1.2.1", + "redux-saga": "1.2.2", "reselect": "4.1.7", "rxjs": "6.6.7", - "sanitize-html": "2.7.3", + "sanitize-html": "2.10.0", "sass.js": "0.11.1", "sha-1": "1.0.0", "store": "2.0.12", "stream-browserify": "3.0.0", "tone": "14.7.77", - "typescript": "4.9.3", + "typescript": "4.9.5", "util": "0.12.5", "uuid": "8.3.2", - "validator": "13.7.0" + "validator": "13.9.0" }, "devDependencies": { - "@babel/types": "7.20.5", - "@codesee/babel-plugin-instrument": "0.451.0", - "@codesee/tracker": "0.451.0", + "@babel/types": "7.20.7", + "@codesee/babel-plugin-instrument": "0.525.0", + "@codesee/tracker": "0.525.0", "@testing-library/jest-dom": "5.16.5", "@testing-library/react": "12.1.5", + "@types/chai": "^4.3.4", + "@types/enzyme": "^3.10.12", + "@types/enzyme-adapter-react-16": "1.0.6", + "@types/jest": "27.5.2", + "@types/jquery": "^3.5.16", + "@types/loadable__component": "5.13.4", + "@types/lodash-es": "^4.17.6", + "@types/prismjs": "^1.26.0", + "@types/reach__router": "1.3.11", + "@types/react": "16.14.35", + "@types/react-dom": "16.9.18", + "@types/react-gtm-module": "2.0.1", + "@types/react-helmet": "6.1.6", + "@types/react-instantsearch-core": "6.26.3", + "@types/react-instantsearch-dom": "6.12.3", + "@types/react-redux": "7.1.25", + "@types/react-responsive": "8.0.5", + "@types/react-scrollable-anchor": "0.6.1", + "@types/react-spinkit": "3.0.7", + "@types/react-test-renderer": "16.9.5", + "@types/react-transition-group": "4.4.5", + "@types/redux-actions": "2.6.2", + "@types/sanitize-html": "^2.8.0", + "@types/store": "^2.0.2", + "@types/testing-library__jest-dom": "^5.14.5", + "@types/validator": "^13.7.12", "autoprefixer": "10.4.13", "babel-plugin-transform-imports": "2.0.0", "chokidar": "3.5.3", diff --git a/client/plugins/fcc-source-challenges/package.json b/client/plugins/fcc-source-challenges/package.json index 03a6736cc502ad..8c5688335f0d64 100644 --- a/client/plugins/fcc-source-challenges/package.json +++ b/client/plugins/fcc-source-challenges/package.json @@ -6,7 +6,7 @@ "private": true, "engines": { "node": ">=16", - "npm": ">=8" + "pnpm": "7" }, "repository": { "type": "git", diff --git a/client/plugins/gatsby-remark-node-identity/package.json b/client/plugins/gatsby-remark-node-identity/package.json index 0836df6b52206b..68d344bee43cc1 100644 --- a/client/plugins/gatsby-remark-node-identity/package.json +++ b/client/plugins/gatsby-remark-node-identity/package.json @@ -6,7 +6,7 @@ "private": true, "engines": { "node": ">=16", - "npm": ">=8" + "pnpm": "7" }, "repository": { "type": "git", diff --git a/client/src/__mocks__/completed-challenges.json b/client/src/__mocks__/completed-challenges.json new file mode 100644 index 00000000000000..3f885759559618 --- /dev/null +++ b/client/src/__mocks__/completed-challenges.json @@ -0,0 +1,6572 @@ +[ + { + "id": "bd7123c8c441eddfaeb5bdef", + "completedDate": 1475094716730, + "files": [] + }, + { + "id": "5895f70bf9fc0f352b528e64", + "completedDate": 1537207306322, + "files": [] + }, + { + "id": "5895f700f9fc0f352b528e63", + "completedDate": 1537206156261, + "files": [] + }, + { + "id": "587d8250367417b2b2512c5d", + "completedDate": 1537196341863, + "files": [] + }, + { + "id": "587d824f367417b2b2512c5c", + "completedDate": 1537196128255, + "files": [] + }, + { + "id": "587d824f367417b2b2512c5b", + "completedDate": 1537195761754, + "files": [] + }, + { + "id": "587d824f367417b2b2512c5a", + "completedDate": 1537194934561, + "files": [] + }, + { + "id": "587d824f367417b2b2512c59", + "completedDate": 1537191541514, + "files": [] + }, + { + "id": "587d824e367417b2b2512c58", + "completedDate": 1537191117061, + "files": [] + }, + { + "id": "587d824e367417b2b2512c57", + "completedDate": 1537156833598, + "files": [] + }, + { + "id": "587d824e367417b2b2512c56", + "completedDate": 1537156784572, + "files": [] + }, + { + "id": "587d824e367417b2b2512c55", + "completedDate": 1537156722004, + "files": [] + }, + { + "id": "587d824d367417b2b2512c54", + "completedDate": 1537156654992, + "files": [] + }, + { + "id": "587d824d367417b2b2512c53", + "completedDate": 1537156621303, + "files": [] + }, + { + "id": "587d824d367417b2b2512c52", + "completedDate": 1537156534601, + "files": [] + }, + { + "id": "587d824d367417b2b2512c51", + "completedDate": 1537156456357, + "files": [] + }, + { + "id": "587d824d367417b2b2512c50", + "completedDate": 1537156425359, + "files": [] + }, + { + "id": "587d824c367417b2b2512c4f", + "completedDate": 1537156351862, + "files": [] + }, + { + "id": "587d824c367417b2b2512c4e", + "completedDate": 1537155828325, + "files": [] + }, + { + "id": "587d824c367417b2b2512c4d", + "completedDate": 1537155787245, + "files": [] + }, + { + "id": "587d824c367417b2b2512c4c", + "completedDate": 1537155713207, + "files": [] + }, + { + "id": "587d824b367417b2b2512c4b", + "completedDate": 1537155677686, + "files": [] + }, + { + "id": "587d824b367417b2b2512c4a", + "completedDate": 1537155558649, + "files": [] + }, + { + "id": "587d824b367417b2b2512c49", + "completedDate": 1537155417358, + "files": [] + }, + { + "id": "587d824b367417b2b2512c48", + "completedDate": 1537155376892, + "files": [] + }, + { + "id": "587d824b367417b2b2512c47", + "completedDate": 1537155346597, + "files": [] + }, + { + "id": "587d824a367417b2b2512c46", + "completedDate": 1537155223667, + "files": [] + }, + { + "id": "5e9a0e9ef99a403d019610cd", + "completedDate": 1594737025062, + "files": [] + }, + { + "id": "5e9a0e9ef99a403d019610cc", + "completedDate": 1594737019383, + "files": [] + }, + { + "id": "5e9a0e9ef99a403d019610cb", + "completedDate": 1594737013076, + "files": [] + }, + { + "id": "5e9a0e9ef99a403d019610ca", + "completedDate": 1594737007379, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72da6", + "completedDate": 1594736997931, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72da5", + "completedDate": 1594736991766, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72da4", + "completedDate": 1594736985764, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72da3", + "completedDate": 1594736981667, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72da2", + "completedDate": 1594736977865, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72da1", + "completedDate": 1594736973679, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72da0", + "completedDate": 1594736951770, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d9f", + "completedDate": 1594736947277, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d9e", + "completedDate": 1594736941520, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d9d", + "completedDate": 1594736936531, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d9c", + "completedDate": 1594736931464, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d9b", + "completedDate": 1594736928913, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d9a", + "completedDate": 1594736926241, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d99", + "completedDate": 1594736922879, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d98", + "completedDate": 1594736916015, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d97", + "completedDate": 1594736913489, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d96", + "completedDate": 1594736911022, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d95", + "completedDate": 1594736906356, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d94", + "completedDate": 1594736902879, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d93", + "completedDate": 1594736899068, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d92", + "completedDate": 1594736892768, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d91", + "completedDate": 1594736887031, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d90", + "completedDate": 1594736881826, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d8f", + "completedDate": 1594736878283, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d8e", + "completedDate": 1594736870814, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d8d", + "completedDate": 1594736867216, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d8c", + "completedDate": 1594736860834, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d8b", + "completedDate": 1594736854454, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d8a", + "completedDate": 1594736850998, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d89", + "completedDate": 1594736845393, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d88", + "completedDate": 1594736783329, + "files": [] + }, + { + "id": "5e8f2f13c4cdbe86b5c72d87", + "completedDate": 1594736780706, + "files": [] + }, + { + "id": "5ea9997bbec2e9bc47e94db4", + "completedDate": 1594736766657, + "files": [] + }, + { + "id": "5ea9997bbec2e9bc47e94db3", + "completedDate": 1594736760393, + "files": [] + }, + { + "id": "5ea9997bbec2e9bc47e94db2", + "completedDate": 1594736756583, + "files": [] + }, + { + "id": "5ea9997bbec2e9bc47e94db1", + "completedDate": 1594736752876, + "files": [] + }, + { + "id": "5ea9997bbec2e9bc47e94db0", + "completedDate": 1594736746497, + "files": [] + }, + { + "id": "5ea9997bbec2e9bc47e94daf", + "completedDate": 1594736741574, + "files": [] + }, + { + "id": "5ea9997bbec2e9bc47e94dae", + "completedDate": 1594736737468, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600eda", + "completedDate": 1594736722645, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600ed9", + "completedDate": 1594736717640, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600ed8", + "completedDate": 1594736714767, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600ed7", + "completedDate": 1594736707875, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600ed6", + "completedDate": 1594736702192, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600ed5", + "completedDate": 1594736698412, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600ed4", + "completedDate": 1594736694389, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600ed3", + "completedDate": 1594736687971, + "files": [] + }, + { + "id": "5e9a0a8e09c5df3cc3600ed2", + "completedDate": 1594736682613, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c167", + "completedDate": 1594736675575, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c166", + "completedDate": 1594736668250, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c165", + "completedDate": 1594736665022, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c164", + "completedDate": 1594736659263, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c163", + "completedDate": 1594736655408, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c162", + "completedDate": 1594736649726, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c161", + "completedDate": 1594736645479, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c160", + "completedDate": 1594736641203, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c15f", + "completedDate": 1594736636454, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c15e", + "completedDate": 1594736632226, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c15d", + "completedDate": 1594736627710, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c15c", + "completedDate": 1594736622070, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c15b", + "completedDate": 1594736618054, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c15a", + "completedDate": 1594736614700, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c159", + "completedDate": 1594736608320, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c158", + "completedDate": 1594736602219, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c157", + "completedDate": 1594736598552, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c156", + "completedDate": 1594736593024, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c155", + "completedDate": 1594736580318, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c154", + "completedDate": 1594736568877, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c153", + "completedDate": 1594736563755, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c152", + "completedDate": 1594736552154, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c151", + "completedDate": 1594736546567, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c150", + "completedDate": 1594736539257, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c14f", + "completedDate": 1594736536366, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c14e", + "completedDate": 1594736532795, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c14d", + "completedDate": 1594736530152, + "files": [] + }, + { + "id": "5e9a093a74c4063ca6f7c14c", + "completedDate": 1594736526774, + "files": [] + }, + { + "id": "5e7b9f6a0b6c005b0e76f097", + "completedDate": 1594736494981, + "files": [] + }, + { + "id": "5e7b9f6a0b6c005b0e76f096", + "completedDate": 1594736491249, + "files": [] + }, + { + "id": "5e7b9f690b6c005b0e76f095", + "completedDate": 1594736486246, + "files": [] + }, + { + "id": "5e7b9f190b6c005b0e76f090", + "completedDate": 1594736476917, + "files": [] + }, + { + "id": "5e7b9f180b6c005b0e76f08f", + "completedDate": 1594736461881, + "files": [] + }, + { + "id": "5e7b9f180b6c005b0e76f08e", + "completedDate": 1594736452018, + "files": [] + }, + { + "id": "5e7b9f180b6c005b0e76f08d", + "completedDate": 1594736444874, + "files": [] + }, + { + "id": "5e7b9f180b6c005b0e76f08c", + "completedDate": 1594736437803, + "files": [] + }, + { + "id": "5e7b9f170b6c005b0e76f08b", + "completedDate": 1594736432528, + "files": [] + }, + { + "id": "5e7b9f170b6c005b0e76f08a", + "completedDate": 1594736422051, + "files": [] + }, + { + "id": "5e7b9f170b6c005b0e76f088", + "completedDate": 1594736417716, + "files": [] + }, + { + "id": "5e7b9f170b6c005b0e76f087", + "completedDate": 1594736414175, + "files": [] + }, + { + "id": "5e7b9f160b6c005b0e76f086", + "completedDate": 1594736410906, + "files": [] + }, + { + "id": "5e7b9f160b6c005b0e76f085", + "completedDate": 1594736379721, + "files": [] + }, + { + "id": "5e7b9f150b6c005b0e76f080", + "completedDate": 1594736373639, + "files": [] + }, + { + "id": "5e7b9f150b6c005b0e76f07f", + "completedDate": 1594736365244, + "files": [] + }, + { + "id": "5e7b9f140b6c005b0e76f07e", + "completedDate": 1594736358778, + "files": [] + }, + { + "id": "5e7b9f140b6c005b0e76f07d", + "completedDate": 1594736353015, + "files": [] + }, + { + "id": "5e7b9f0e0b6c005b0e76f07c", + "completedDate": 1594736348722, + "files": [] + }, + { + "id": "5e7b9f0e0b6c005b0e76f07b", + "completedDate": 1594736342374, + "files": [] + }, + { + "id": "5e7b9f0e0b6c005b0e76f07a", + "completedDate": 1594736336127, + "files": [] + }, + { + "id": "5e7b9f0d0b6c005b0e76f076", + "completedDate": 1594736332128, + "files": [] + }, + { + "id": "5e7b9f0d0b6c005b0e76f075", + "completedDate": 1594736324629, + "files": [] + }, + { + "id": "5e7b9f0c0b6c005b0e76f074", + "completedDate": 1594736317130, + "files": [] + }, + { + "id": "5e7b9f0c0b6c005b0e76f073", + "completedDate": 1594736312374, + "files": [] + }, + { + "id": "5e7b9f0c0b6c005b0e76f072", + "completedDate": 1594736298454, + "files": [] + }, + { + "id": "5e7b9f0c0b6c005b0e76f071", + "completedDate": 1594736291062, + "files": [] + }, + { + "id": "5e7b9f0b0b6c005b0e76f070", + "completedDate": 1594736281756, + "files": [] + }, + { + "id": "5e7b9f0b0b6c005b0e76f06f", + "completedDate": 1594736276938, + "files": [] + }, + { + "id": "5e7b9f0b0b6c005b0e76f06e", + "completedDate": 1594736270403, + "files": [] + }, + { + "id": "5e7b9f0b0b6c005b0e76f06d", + "completedDate": 1594736266728, + "files": [] + }, + { + "id": "5e7b9f0a0b6c005b0e76f06c", + "completedDate": 1594736256389, + "files": [] + }, + { + "id": "5e7b9f0a0b6c005b0e76f069", + "completedDate": 1594736249458, + "files": [] + }, + { + "id": "5e7b9f090b6c005b0e76f068", + "completedDate": 1594736240329, + "files": [] + }, + { + "id": "5e7b9f090b6c005b0e76f067", + "completedDate": 1594736231416, + "files": [] + }, + { + "id": "5e7b9f090b6c005b0e76f066", + "completedDate": 1594736222820, + "files": [] + }, + { + "id": "5e7b9f090b6c005b0e76f065", + "completedDate": 1594736189335, + "files": [] + }, + { + "id": "5e7b9f080b6c005b0e76f064", + "completedDate": 1594736184197, + "files": [] + }, + { + "id": "5e7b9f080b6c005b0e76f063", + "completedDate": 1594736179115, + "files": [] + }, + { + "id": "5e7b9f080b6c005b0e76f062", + "completedDate": 1594736170111, + "files": [] + }, + { + "id": "5e7b9f070b6c005b0e76f061", + "completedDate": 1594736166777, + "files": [] + }, + { + "id": "5e7b9f070b6c005b0e76f060", + "completedDate": 1594736155841, + "files": [] + }, + { + "id": "5e7b9f070b6c005b0e76f05f", + "completedDate": 1594736151207, + "files": [] + }, + { + "id": "5e7b9f070b6c005b0e76f05e", + "completedDate": 1594736139632, + "files": [] + }, + { + "id": "5e7b9f070b6c005b0e76f05d", + "completedDate": 1594736134513, + "files": [] + }, + { + "id": "5e7b9f060b6c005b0e76f05c", + "completedDate": 1594736127815, + "files": [] + }, + { + "id": "5e7b9f060b6c005b0e76f05b", + "completedDate": 1594736121855, + "files": [] + }, + { + "id": "5e7b9f060b6c005b0e76f05a", + "completedDate": 1594736116852, + "files": [] + }, + { + "id": "5e7b9f060b6c005b0e76f059", + "completedDate": 1594736110114, + "files": [] + }, + { + "id": "5e7b9f050b6c005b0e76f058", + "completedDate": 1594736099389, + "files": [] + }, + { + "id": "5e7b9f050b6c005b0e76f057", + "completedDate": 1594736079471, + "files": [] + }, + { + "id": "5e7b9f050b6c005b0e76f056", + "completedDate": 1594736073962, + "files": [] + }, + { + "id": "5e6a54c358d3af90110a60a3", + "completedDate": 1594736049167, + "files": [] + }, + { + "id": "5e6a54ba58d3af90110a60a2", + "completedDate": 1594736044195, + "files": [] + }, + { + "id": "5e6a54af58d3af90110a60a1", + "completedDate": 1594736040286, + "files": [] + }, + { + "id": "5e6a54a558d3af90110a60a0", + "completedDate": 1594736018884, + "files": [] + }, + { + "id": "58a25bcff9fc0f352b528e7e", + "completedDate": 1537204939276, + "files": [] + }, + { + "id": "58a25bcff9fc0f352b528e7d", + "completedDate": 1537204689114, + "files": [] + }, + { + "id": "587d7db3367417b2b2512b8f", + "completedDate": 1528836297983, + "files": [] + }, + { + "id": "587d7db3367417b2b2512b8e", + "completedDate": 1528836242517, + "files": [] + }, + { + "id": "587d8251367417b2b2512c64", + "completedDate": 1584724916681, + "files": [] + }, + { + "id": "5a23c84252665b21eecc8040", + "completedDate": 1581377129224, + "files": [] + }, + { + "id": "5900f3881000cf542c50fe9b", + "completedDate": 1581267049205, + "files": [] + }, + { + "id": "5900f3851000cf542c50fe98", + "completedDate": 1581261142636, + "files": [] + }, + { + "id": "5a51eabcad78bf416f316e2a", + "completedDate": 1581259050886, + "files": [] + }, + { + "id": "5900f37b1000cf542c50fe8e", + "completedDate": 1581220627138, + "files": [] + }, + { + "id": "5900f37a1000cf542c50fe8c", + "completedDate": 1563131237063, + "files": [] + }, + { + "id": "5900f3781000cf542c50fe8b", + "completedDate": 1581209840334, + "files": [] + }, + { + "id": "5900f3761000cf542c50fe89", + "completedDate": 1581200258395, + "files": [] + }, + { + "id": "5900f3741000cf542c50fe87", + "completedDate": 1581197527928, + "files": [] + }, + { + "id": "5900f3731000cf542c50fe86", + "completedDate": 1581194166358, + "files": [] + }, + { + "id": "5900f3721000cf542c50fe85", + "completedDate": 1581192983102, + "files": [] + }, + { + "id": "5900f3711000cf542c50fe84", + "completedDate": 1581107068452, + "files": [] + }, + { + "id": "5cdafbb0291309899753167f", + "completedDate": 1574302240996, + "files": [] + }, + { + "id": "5ccfad82bb2dc6c965a848e5", + "completedDate": 1574302514181, + "files": [] + }, + { + "id": "5c3dda8b4d8df89bea71600f", + "completedDate": 1574302492985, + "files": [] + }, + { + "id": "5cdafbe72913098997531682", + "completedDate": 1574302346019, + "files": [] + }, + { + "id": "5cdafbd72913098997531681", + "completedDate": 1574302316716, + "files": [] + }, + { + "id": "5cdafbc32913098997531680", + "completedDate": 1574302286941, + "files": [] + }, + { + "id": "5cddbfd622f1a59093ec611d", + "completedDate": 1574302200001, + "files": [] + }, + { + "id": "5cfa550e84205a357704ccb6", + "completedDate": 1574302164631, + "files": [] + }, + { + "id": "5cd9a70215d3c4e65518328f", + "completedDate": 1574302134656, + "files": [] + }, + { + "id": "5cc0bd7a49b71cb96132e54c", + "completedDate": 1574302122706, + "files": [] + }, + { + "id": "5c6c06847491271903d37cfd", + "completedDate": 1574301689702, + "files": [] + }, + { + "id": "5cfa3679138e7d9595b9d9d4", + "completedDate": 1572140656699, + "files": [] + }, + { + "id": "597f24c1dda4e70f53c79c81", + "completedDate": 1568427791545, + "files": [] + }, + { + "id": "5a23c84252665b21eecc7e82", + "completedDate": 1568426995929, + "files": [] + }, + { + "id": "59669d08d75b60482359409f", + "completedDate": 1568390166116, + "files": [] + }, + { + "id": "594d8d0ab97724821379b1e6", + "completedDate": 1568387040347, + "files": [] + }, + { + "id": "594810f028c0303b75339ad1", + "completedDate": 1568346223877, + "files": [] + }, + { + "id": "596e457071c35c882915b3e4", + "completedDate": 1568334942324, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf0887a", + "completedDate": 1475094757107, + "files": [] + }, + { + "id": "bd7123c9c441eddfaeb4bdef", + "completedDate": 1475173147497, + "files": [] + }, + { + "id": "587d7b89367417b2b2512b49", + "completedDate": 1528729165835, + "files": [] + }, + { + "id": "587d7b8c367417b2b2512b58", + "completedDate": 1528742042170, + "files": [] + }, + { + "id": "587d7b8c367417b2b2512b57", + "completedDate": 1528741796573, + "files": [] + }, + { + "id": "587d7b8c367417b2b2512b56", + "completedDate": 1528740437095, + "files": [] + }, + { + "id": "587d7b8c367417b2b2512b55", + "completedDate": 1528740387410, + "files": [] + }, + { + "id": "5a24bbe0dba28a8d3cbd4c5d", + "completedDate": 1528936352198, + "files": [] + }, + { + "id": "587d7dbc367417b2b2512bb1", + "completedDate": 1528936259926, + "files": [] + }, + { + "id": "5a94fe1369fb03452672e45d", + "completedDate": 1528726237694, + "files": [] + }, + { + "id": "5a94fe0569fb03452672e45c", + "completedDate": 1528726188458, + "files": [] + }, + { + "id": "5a94fdf869fb03452672e45b", + "completedDate": 1528726170915, + "files": [] + }, + { + "id": "5a90376038fddaf9a66b5d3c", + "completedDate": 1528726156897, + "files": [] + }, + { + "id": "5a90375238fddaf9a66b5d3b", + "completedDate": 1528726139703, + "files": [] + }, + { + "id": "5a90374338fddaf9a66b5d3a", + "completedDate": 1528726130365, + "files": [] + }, + { + "id": "5a90373638fddaf9a66b5d39", + "completedDate": 1528726091369, + "files": [] + }, + { + "id": "5a90372638fddaf9a66b5d38", + "completedDate": 1528726069769, + "files": [] + }, + { + "id": "5a9036ee38fddaf9a66b5d37", + "completedDate": 1528726049483, + "files": [] + }, + { + "id": "5a9036ee38fddaf9a66b5d36", + "completedDate": 1528726030349, + "files": [] + }, + { + "id": "5a9036ee38fddaf9a66b5d35", + "completedDate": 1528726016678, + "files": [] + }, + { + "id": "5a9036ee38fddaf9a66b5d34", + "completedDate": 1528725989219, + "files": [] + }, + { + "id": "5a9036e138fddaf9a66b5d33", + "completedDate": 1528725967520, + "files": [] + }, + { + "id": "5a9036d038fddaf9a66b5d32", + "completedDate": 1528725949737, + "files": [] + }, + { + "id": "5a858944d96184f06fd60d61", + "completedDate": 1528725909984, + "files": [] + }, + { + "id": "587d8255367417b2b2512c73", + "completedDate": 1544535146554, + "files": [] + }, + { + "id": "587d8254367417b2b2512c71", + "completedDate": 1544451674921, + "files": [] + }, + { + "id": "587d825b367417b2b2512c8d", + "completedDate": 1544365302994, + "files": [] + }, + { + "id": "587d8254367417b2b2512c70", + "completedDate": 1544279548091, + "files": [] + }, + { + "id": "587d8255367417b2b2512c72", + "completedDate": 1544128168268, + "files": [] + }, + { + "id": "587d8253367417b2b2512c6b", + "completedDate": 1544016209200, + "files": [] + }, + { + "id": "8d1323c8c441eddfaeb5bdef", + "completedDate": 1543963893788, + "files": [] + }, + { + "id": "8d1923c8c441eddfaeb5bdef", + "completedDate": 1543842286217, + "files": [] + }, + { + "id": "587d8255367417b2b2512c74", + "completedDate": 1539709034423, + "files": [] + }, + { + "id": "587d8250367417b2b2512c60", + "completedDate": 1539311762179, + "files": [] + }, + { + "id": "587d824a367417b2b2512c45", + "completedDate": 1538239274460, + "solution": "https://fcc-message-bored.glitch.me/", + "githubLink": "https://github.com/moT01/FCC-Message-Board", + "challengeType": 4, + "files": [] + }, + { + "id": "587d824a367417b2b2512c44", + "completedDate": 1537981270657, + "solution": "https://fcc-stock-check.glitch.me/", + "githubLink": "https://github.com/moT01/FCC-Stock-Checker", + "challengeType": 4, + "files": [] + }, + { + "id": "587d824a367417b2b2512c43", + "completedDate": 1537758214498, + "solution": "https://fcc-person-library.glitch.me/", + "githubLink": "https://github.com/moT01/FCC-Personal-Library", + "challengeType": 4, + "files": [] + }, + { + "id": "587d8249367417b2b2512c42", + "completedDate": 1537738041237, + "solution": "https://fcc-issues-tracker.glitch.me/", + "githubLink": "https://github.com/moT01/FCC-Issue-Tracker", + "challengeType": 4, + "files": [] + }, + { + "id": "5b7d72c338cd7e35b63f3e14", + "completedDate": 1537653616955, + "files": [] + }, + { + "id": "587d8249367417b2b2512c41", + "completedDate": 1537559766968, + "solution": "https://fcc-metric-convert.glitch.me/", + "githubLink": "https://github.com/moT01/FCC-Metric-Converter", + "challengeType": 4, + "files": [] + }, + { + "id": "58966a17f9fc0f352b528e6d", + "completedDate": 1537230386653, + "solution": "https://torch-player.glitch.me/", + "files": [] + }, + { + "id": "589690e6f9fc0f352b528e6e", + "completedDate": 1537223809877, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "58a25c98f9fc0f352b528e7f", + "completedDate": 1537222634385, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "58965611f9fc0f352b528e6c", + "completedDate": 1537214717318, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "5895f70ef9fc0f352b528e6b", + "completedDate": 1537214579404, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "5895f70df9fc0f352b528e6a", + "completedDate": 1537211858590, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "5895f70df9fc0f352b528e69", + "completedDate": 1537210025542, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "5895f70df9fc0f352b528e68", + "completedDate": 1537209494409, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "5895f70cf9fc0f352b528e67", + "completedDate": 1537208702252, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "5895f70cf9fc0f352b528e66", + "completedDate": 1537208136182, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "5895f70cf9fc0f352b528e65", + "completedDate": 1537207848068, + "solution": "https://eager-harmony.glitch.me/", + "files": [] + }, + { + "id": "58a25bcef9fc0f352b528e7c", + "completedDate": 1537200206872, + "solution": "https://seemly-fighter.glitch.me/", + "files": [] + }, + { + "id": "587d8249367417b2b2512c40", + "completedDate": 1537199372195, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8249367417b2b2512c3f", + "completedDate": 1537199285395, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8249367417b2b2512c3e", + "completedDate": 1537198926071, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8248367417b2b2512c3d", + "completedDate": 1537198824551, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8248367417b2b2512c3c", + "completedDate": 1537198750481, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8248367417b2b2512c3b", + "completedDate": 1537198630082, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8248367417b2b2512c3a", + "completedDate": 1537198391567, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8247367417b2b2512c39", + "completedDate": 1537198316053, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8247367417b2b2512c38", + "completedDate": 1537197942090, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8247367417b2b2512c37", + "completedDate": 1537197832144, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d8247367417b2b2512c36", + "completedDate": 1537196939178, + "solution": "https://tidy-roadway.glitch.me/", + "files": [] + }, + { + "id": "587d7fa6367417b2b2512bbf", + "completedDate": 1537144978531, + "solution": "https://codepen.io/moT01/full/rZxZMq/", + "challengeType": 3, + "files": [] + }, + { + "id": "587d7dae367417b2b2512b7c", + "completedDate": 1528904752503, + "files": [] + }, + { + "id": "5a5d02bd919fcf9ca8cf46cb", + "completedDate": 1535377692723, + "solution": "https://mot01.github.io/FCC-Light-Bright/", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7168d8c242eddfaeb5bd13", + "completedDate": 1488665231772, + "solution": "http://codepen.io/moT01/pen/JEMxoj?editors=1010", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7178d8c242eddfaeb5bd13", + "completedDate": 1488665256488, + "solution": "http://codepen.io/moT01/pen/zNLPmV", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7188d8c242eddfaeb5bd13", + "completedDate": 1488665304243, + "solution": "http://codepen.io/moT01/pen/NdLxNB", + "challengeType": 3, + "files": [] + }, + { + "id": "587d7fa6367417b2b2512bc0", + "completedDate": 1535244078849, + "solution": "https://codepen.io/moT01/full/rrKwzy/", + "challengeType": 3, + "files": [] + }, + { + "id": "587d825a367417b2b2512c89", + "completedDate": 1534614153746, + "files": [] + }, + { + "id": "587d8259367417b2b2512c86", + "completedDate": 1534256923082, + "files": [] + }, + { + "id": "587d8259367417b2b2512c85", + "completedDate": 1534253945342, + "files": [] + }, + { + "id": "8d5123c8c441eddfaeb5bdef", + "completedDate": 1534222674479, + "files": [] + }, + { + "id": "bd7158d8c443edefaeb5bdef", + "completedDate": 1498077591986, + "solution": "https://mixed-tadpole.glitch.me/", + "challengeType": 4, + "files": [] + }, + { + "id": "bd7158d8c443edefaeb5bdff", + "completedDate": 1498090900090, + "solution": "https://phase-continent.glitch.me/", + "challengeType": 4, + "files": [] + }, + { + "id": "bd7158d8c443edefaeb5bd0e", + "completedDate": 1499384769762, + "solution": "https://ash-airport.glitch.me/", + "challengeType": 4, + "files": [] + }, + { + "id": "bd7158d8c443edefaeb5bd0f", + "completedDate": 1500911711138, + "solution": "https://zenith-double.glitch.me/", + "challengeType": 4, + "files": [] + }, + { + "id": "5a8b073d06fa14fcfde687aa", + "completedDate": 1533833478381, + "solution": "https://fcc-exercise-tracker.herokuapp.com/", + "challengeType": 3, + "files": [] + }, + { + "id": "587d7faf367417b2b2512be9", + "completedDate": 1533313441660, + "files": [] + }, + { + "id": "587d7faf367417b2b2512be8", + "completedDate": 1533313429792, + "files": [] + }, + { + "id": "587d7fae367417b2b2512be7", + "completedDate": 1533313418548, + "files": [] + }, + { + "id": "587d7fae367417b2b2512be6", + "completedDate": 1533313409789, + "files": [] + }, + { + "id": "587d7fae367417b2b2512be5", + "completedDate": 1533313394341, + "files": [] + }, + { + "id": "587d7fae367417b2b2512be4", + "completedDate": 1533313287461, + "files": [] + }, + { + "id": "587d7fae367417b2b2512be3", + "completedDate": 1533312971665, + "files": [] + }, + { + "id": "587d7fad367417b2b2512be2", + "completedDate": 1533312379130, + "files": [] + }, + { + "id": "587d7fad367417b2b2512be1", + "completedDate": 1533305186377, + "files": [] + }, + { + "id": "587d7fad367417b2b2512bdf", + "completedDate": 1533305081870, + "files": [] + }, + { + "id": "587d7fac367417b2b2512bde", + "completedDate": 1533304893213, + "files": [] + }, + { + "id": "587d7fac367417b2b2512bdd", + "completedDate": 1533304473980, + "files": [] + }, + { + "id": "587d7fac367417b2b2512bdc", + "completedDate": 1533304357934, + "files": [] + }, + { + "id": "587d7fac367417b2b2512bdb", + "completedDate": 1533304277919, + "files": [] + }, + { + "id": "587d7fab367417b2b2512bda", + "completedDate": 1533304195179, + "files": [] + }, + { + "id": "587d7fab367417b2b2512bd9", + "completedDate": 1533304040401, + "files": [] + }, + { + "id": "587d7fab367417b2b2512bd8", + "completedDate": 1533303510955, + "files": [] + }, + { + "id": "587d7fab367417b2b2512bd7", + "completedDate": 1533303204725, + "files": [] + }, + { + "id": "587d7faa367417b2b2512bd6", + "completedDate": 1533302881077, + "files": [] + }, + { + "id": "587d7faa367417b2b2512bd4", + "completedDate": 1533302797436, + "files": [] + }, + { + "id": "587d7faa367417b2b2512bd3", + "completedDate": 1533302682051, + "files": [] + }, + { + "id": "587d7faa367417b2b2512bd2", + "completedDate": 1533302419381, + "files": [] + }, + { + "id": "587d7fa9367417b2b2512bd1", + "completedDate": 1533302159045, + "files": [] + }, + { + "id": "587d7fa9367417b2b2512bd0", + "completedDate": 1533302136821, + "files": [] + }, + { + "id": "587d7fa9367417b2b2512bcf", + "completedDate": 1533301974907, + "files": [] + }, + { + "id": "587d7fa9367417b2b2512bce", + "completedDate": 1533301957042, + "files": [] + }, + { + "id": "587d7fa8367417b2b2512bcd", + "completedDate": 1533301918702, + "files": [] + }, + { + "id": "587d7fa8367417b2b2512bcc", + "completedDate": 1533301841955, + "files": [] + }, + { + "id": "587d7fa8367417b2b2512bcb", + "completedDate": 1533301722365, + "files": [] + }, + { + "id": "587d7fa8367417b2b2512bca", + "completedDate": 1533301610183, + "files": [] + }, + { + "id": "587d7fa8367417b2b2512bc9", + "completedDate": 1533301532665, + "files": [] + }, + { + "id": "587d7fa7367417b2b2512bc8", + "completedDate": 1533301461772, + "files": [] + }, + { + "id": "587d7fa7367417b2b2512bc7", + "completedDate": 1533301438297, + "files": [] + }, + { + "id": "587d7fa7367417b2b2512bc6", + "completedDate": 1533301332393, + "files": [] + }, + { + "id": "587d7fa7367417b2b2512bc5", + "completedDate": 1533301304031, + "files": [] + }, + { + "id": "587d7fa7367417b2b2512bc4", + "completedDate": 1533301245248, + "files": [] + }, + { + "id": "587d78b0367417b2b2512b05", + "completedDate": 1533273771014, + "solution": "https://codepen.io/moT01/full/JBvzNL/", + "challengeType": 3, + "files": [] + }, + { + "id": "587d78af367417b2b2512b04", + "completedDate": 1533265342064, + "solution": "https://codepen.io/moT01/full/qKyKYL/", + "challengeType": 3, + "files": [] + }, + { + "id": "bad87fee1348bd9aedc08830", + "completedDate": 1475096459663, + "files": [] + }, + { + "id": "587d7fb9367417b2b2512c12", + "completedDate": 1533055320751, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb8367417b2b2512c11", + "completedDate": 1533055049560, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb8367417b2b2512c10", + "completedDate": 1533055004536, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb8367417b2b2512c0f", + "completedDate": 1533054957664, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb8367417b2b2512c0e", + "completedDate": 1533054810266, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb7367417b2b2512c0d", + "completedDate": 1533054731172, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb7367417b2b2512c0c", + "completedDate": 1533054681787, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb7367417b2b2512c0b", + "completedDate": 1533054615086, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb7367417b2b2512c0a", + "completedDate": 1533054496430, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb6367417b2b2512c09", + "completedDate": 1533054359282, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb6367417b2b2512c07", + "completedDate": 1533053012175, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb6367417b2b2512c06", + "completedDate": 1533049464594, + "solution": "https://fcc-mongo-mongoose.glitch.me/", + "files": [] + }, + { + "id": "587d7fb2367417b2b2512bf8", + "completedDate": 1533047350131, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb2367417b2b2512bf7", + "completedDate": 1533047240645, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb2367417b2b2512bf6", + "completedDate": 1533046595396, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb2367417b2b2512bf5", + "completedDate": 1533046425247, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb1367417b2b2512bf4", + "completedDate": 1533044706441, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb1367417b2b2512bf3", + "completedDate": 1533044029688, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb1367417b2b2512bf2", + "completedDate": 1533043449812, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb1367417b2b2512bf1", + "completedDate": 1533043268417, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb0367417b2b2512bf0", + "completedDate": 1533042013904, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb0367417b2b2512bef", + "completedDate": 1533041880166, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb0367417b2b2512bee", + "completedDate": 1533041574196, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb0367417b2b2512bed", + "completedDate": 1533041397592, + "solution": "https://fcc-basic-node-and-express.glitch.me/", + "files": [] + }, + { + "id": "587d7fb5367417b2b2512c04", + "completedDate": 1533041014569, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb5367417b2b2512c03", + "completedDate": 1533040923088, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb5367417b2b2512c02", + "completedDate": 1533040901236, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb5367417b2b2512c01", + "completedDate": 1533040847451, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb4367417b2b2512c00", + "completedDate": 1533040209131, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb4367417b2b2512bff", + "completedDate": 1533040168518, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb4367417b2b2512bfe", + "completedDate": 1533040145047, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb4367417b2b2512bfd", + "completedDate": 1533040107526, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb3367417b2b2512bfc", + "completedDate": 1533040049025, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7fb3367417b2b2512bfb", + "completedDate": 1533039944300, + "solution": "https://fcc-manage-npm-packages.glitch.me/", + "files": [] + }, + { + "id": "587d7dbc367417b2b2512bae", + "completedDate": 1532961147572, + "solution": "https://fcc-drum-machine.herokuapp.com/", + "challengeType": 3, + "files": [] + }, + { + "id": "5a24c314108439a4d403614a", + "completedDate": 1532794780112, + "files": [] + }, + { + "id": "5a24c314108439a4d4036149", + "completedDate": 1532794700815, + "files": [] + }, + { + "id": "587d7fa6367417b2b2512bc3", + "completedDate": 1531937190203, + "files": [] + }, + { + "id": "5a24c314108439a4d4036148", + "completedDate": 1531489006830, + "files": [] + }, + { + "id": "587d7b83367417b2b2512b37", + "completedDate": 1531486599992, + "files": [] + }, + { + "id": "5a24c314108439a4d4036147", + "completedDate": 1531482969362, + "files": [] + }, + { + "id": "5a24c314108439a4d4036146", + "completedDate": 1531482790969, + "files": [] + }, + { + "id": "5a24c314108439a4d4036145", + "completedDate": 1531481644030, + "files": [] + }, + { + "id": "5a24c314108439a4d4036144", + "completedDate": 1531481355387, + "files": [] + }, + { + "id": "5a24c314108439a4d4036143", + "completedDate": 1531453571962, + "files": [] + }, + { + "id": "5a24c314108439a4d4036142", + "completedDate": 1531453316042, + "files": [] + }, + { + "id": "5a24c314108439a4d4036141", + "completedDate": 1531445056603, + "files": [] + }, + { + "id": "5a24c314108439a4d403615b", + "completedDate": 1531443499567, + "files": [] + }, + { + "id": "5a24c314108439a4d403615a", + "completedDate": 1531433896792, + "files": [] + }, + { + "id": "5a24c314108439a4d4036159", + "completedDate": 1531433516627, + "files": [] + }, + { + "id": "5a24c314108439a4d4036158", + "completedDate": 1531433335857, + "files": [] + }, + { + "id": "5a24c314108439a4d4036157", + "completedDate": 1531432774927, + "files": [] + }, + { + "id": "5a24c314108439a4d4036156", + "completedDate": 1531432281650, + "files": [] + }, + { + "id": "5a24c314108439a4d4036155", + "completedDate": 1531431898900, + "files": [] + }, + { + "id": "5a24c314108439a4d4036154", + "completedDate": 1531429369572, + "files": [] + }, + { + "id": "5a24c314108439a4d4036153", + "completedDate": 1531429194225, + "files": [] + }, + { + "id": "5a24c314108439a4d4036152", + "completedDate": 1531429071050, + "files": [] + }, + { + "id": "5a24c314108439a4d4036151", + "completedDate": 1531428817943, + "files": [] + }, + { + "id": "5a24c314108439a4d4036150", + "completedDate": 1531428663065, + "files": [] + }, + { + "id": "5a24c314108439a4d403614c", + "completedDate": 1531428487038, + "files": [] + }, + { + "id": "5a24c314108439a4d403614b", + "completedDate": 1531428433090, + "files": [] + }, + { + "id": "5900f3701000cf542c50fe83", + "completedDate": 1530277993244, + "files": [] + }, + { + "id": "5900f36f1000cf542c50fe82", + "completedDate": 1530277838465, + "files": [] + }, + { + "id": "5900f36e1000cf542c50fe81", + "completedDate": 1530222499479, + "files": [] + }, + { + "id": "5900f36e1000cf542c50fe80", + "completedDate": 1530221644777, + "files": [] + }, + { + "id": "594810f028c0303b75339acb", + "completedDate": 1530015953369, + "files": [] + }, + { + "id": "587d78af367417b2b2512b03", + "completedDate": 1529938009424, + "solution": "https://codepen.io/moT01/pen/LrrjGz?editors=1010", + "challengeType": 3, + "files": [] + }, + { + "id": "5a9d7286424fe3d0e10cad13", + "completedDate": 1528719842749, + "files": [] + }, + { + "id": "587d8250367417b2b2512c5f", + "completedDate": 1529584582909, + "files": [] + }, + { + "id": "587d8250367417b2b2512c5e", + "completedDate": 1529584233498, + "files": [] + }, + { + "id": "587d8253367417b2b2512c6a", + "completedDate": 1529584147462, + "files": [] + }, + { + "id": "587d7fa6367417b2b2512bc2", + "completedDate": 1529186003814, + "files": [] + }, + { + "id": "5a24c314108439a4d403614f", + "completedDate": 1529179243536, + "files": [] + }, + { + "id": "5a24c314108439a4d403614e", + "completedDate": 1528981776099, + "files": [] + }, + { + "id": "5a24c314108439a4d403614d", + "completedDate": 1528981744994, + "files": [] + }, + { + "id": "5a24c314108439a4d403618d", + "completedDate": 1528950851660, + "files": [] + }, + { + "id": "5a24c314108439a4d403618c", + "completedDate": 1528950719262, + "files": [] + }, + { + "id": "5a24c314108439a4d403618b", + "completedDate": 1528950396682, + "files": [] + }, + { + "id": "5a24c314108439a4d403618a", + "completedDate": 1528950304924, + "files": [] + }, + { + "id": "5a24c314108439a4d4036189", + "completedDate": 1528949805386, + "files": [] + }, + { + "id": "5a24c314108439a4d4036188", + "completedDate": 1528949697883, + "files": [] + }, + { + "id": "5a24c314108439a4d4036187", + "completedDate": 1528949067606, + "files": [] + }, + { + "id": "5a24c314108439a4d4036185", + "completedDate": 1528948451001, + "files": [] + }, + { + "id": "5a24c314108439a4d4036184", + "completedDate": 1528946998407, + "files": [] + }, + { + "id": "5a24c314108439a4d4036183", + "completedDate": 1528946875698, + "files": [] + }, + { + "id": "5a24c314108439a4d4036182", + "completedDate": 1528946566042, + "files": [] + }, + { + "id": "5a24c314108439a4d4036181", + "completedDate": 1528946437132, + "files": [] + }, + { + "id": "5a24c314108439a4d4036180", + "completedDate": 1528946299272, + "files": [] + }, + { + "id": "5a24c314108439a4d403617f", + "completedDate": 1528946192923, + "files": [] + }, + { + "id": "5a24c314108439a4d403617e", + "completedDate": 1528945856282, + "files": [] + }, + { + "id": "5a24c314108439a4d403617d", + "completedDate": 1528945678448, + "files": [] + }, + { + "id": "5a24c314108439a4d403617c", + "completedDate": 1528945645295, + "files": [] + }, + { + "id": "5a24c314108439a4d403617b", + "completedDate": 1528945579541, + "files": [] + }, + { + "id": "5a24c314108439a4d403617a", + "completedDate": 1528945447719, + "files": [] + }, + { + "id": "5a24c314108439a4d4036179", + "completedDate": 1528945385287, + "files": [] + }, + { + "id": "5a24c314108439a4d4036178", + "completedDate": 1528945197650, + "files": [] + }, + { + "id": "5a24c314108439a4d4036177", + "completedDate": 1528944290718, + "files": [] + }, + { + "id": "5a24c314108439a4d4036176", + "completedDate": 1528943870093, + "files": [] + }, + { + "id": "5a24c314108439a4d4036174", + "completedDate": 1528943740058, + "files": [] + }, + { + "id": "5a24c314108439a4d4036173", + "completedDate": 1528943671264, + "files": [] + }, + { + "id": "5a24c314108439a4d4036172", + "completedDate": 1528943603260, + "files": [] + }, + { + "id": "5a24c314108439a4d4036171", + "completedDate": 1528943535660, + "files": [] + }, + { + "id": "5a24c314108439a4d4036170", + "completedDate": 1528943507508, + "files": [] + }, + { + "id": "5a24c314108439a4d403616f", + "completedDate": 1528943479564, + "files": [] + }, + { + "id": "5a24c314108439a4d403616e", + "completedDate": 1528943277939, + "files": [] + }, + { + "id": "5a24c314108439a4d403616d", + "completedDate": 1528943091046, + "files": [] + }, + { + "id": "5a24c314108439a4d403616c", + "completedDate": 1528942897945, + "files": [] + }, + { + "id": "5a24c314108439a4d403616b", + "completedDate": 1528942802253, + "files": [] + }, + { + "id": "5a24c314108439a4d403616a", + "completedDate": 1528942758495, + "files": [] + }, + { + "id": "5a24c314108439a4d4036169", + "completedDate": 1528942646063, + "files": [] + }, + { + "id": "5a24c314108439a4d4036168", + "completedDate": 1528937140246, + "files": [] + }, + { + "id": "5a24c314108439a4d4036167", + "completedDate": 1528936992425, + "files": [] + }, + { + "id": "5a24c314108439a4d4036166", + "completedDate": 1528936887008, + "files": [] + }, + { + "id": "5a24c314108439a4d4036165", + "completedDate": 1528936818982, + "files": [] + }, + { + "id": "5a24c314108439a4d4036164", + "completedDate": 1528936765216, + "files": [] + }, + { + "id": "5a24c314108439a4d4036163", + "completedDate": 1528936729634, + "files": [] + }, + { + "id": "5a24c314108439a4d4036162", + "completedDate": 1528936661343, + "files": [] + }, + { + "id": "5a24c314108439a4d4036161", + "completedDate": 1528936547644, + "files": [] + }, + { + "id": "5a24c314108439a4d4036160", + "completedDate": 1528936507205, + "files": [] + }, + { + "id": "5a24bbe0dba28a8d3cbd4c5f", + "completedDate": 1528936468035, + "files": [] + }, + { + "id": "5a24bbe0dba28a8d3cbd4c5e", + "completedDate": 1528936381238, + "files": [] + }, + { + "id": "587d7fa5367417b2b2512bbd", + "completedDate": 1528934178753, + "files": [] + }, + { + "id": "587d7dbf367417b2b2512bbc", + "completedDate": 1528934096231, + "files": [] + }, + { + "id": "587d7dbf367417b2b2512bbb", + "completedDate": 1528934051468, + "files": [] + }, + { + "id": "587d7dbf367417b2b2512bba", + "completedDate": 1528933852430, + "files": [] + }, + { + "id": "587d7dbe367417b2b2512bb9", + "completedDate": 1528933741473, + "files": [] + }, + { + "id": "587d7dbe367417b2b2512bb8", + "completedDate": 1528933566151, + "files": [] + }, + { + "id": "587d7dbd367417b2b2512bb6", + "completedDate": 1528933360001, + "files": [] + }, + { + "id": "587d7dbd367417b2b2512bb5", + "completedDate": 1528933151245, + "files": [] + }, + { + "id": "587d7dbd367417b2b2512bb4", + "completedDate": 1528933108643, + "files": [] + }, + { + "id": "587d7dab367417b2b2512b70", + "completedDate": 1528930450509, + "files": [] + }, + { + "id": "587d7dab367417b2b2512b6f", + "completedDate": 1528930224869, + "files": [] + }, + { + "id": "587d7dab367417b2b2512b6e", + "completedDate": 1528929785830, + "files": [] + }, + { + "id": "587d7dab367417b2b2512b6d", + "completedDate": 1528929659099, + "files": [] + }, + { + "id": "587d7daa367417b2b2512b6c", + "completedDate": 1528927786126, + "files": [] + }, + { + "id": "587d7daa367417b2b2512b6b", + "completedDate": 1528927735717, + "files": [] + }, + { + "id": "587d7da9367417b2b2512b6a", + "completedDate": 1528927426415, + "files": [] + }, + { + "id": "587d7da9367417b2b2512b69", + "completedDate": 1528927327998, + "files": [] + }, + { + "id": "587d7da9367417b2b2512b68", + "completedDate": 1528927215860, + "files": [] + }, + { + "id": "587d7da9367417b2b2512b67", + "completedDate": 1528926108930, + "files": [] + }, + { + "id": "587d7da9367417b2b2512b66", + "completedDate": 1528926045666, + "files": [] + }, + { + "id": "9d7123c8c441eeafaeb5bdef", + "completedDate": 1528925941088, + "files": [] + }, + { + "id": "587d7b90367417b2b2512b65", + "completedDate": 1528925068599, + "files": [] + }, + { + "id": "587d7b8f367417b2b2512b64", + "completedDate": 1528924576412, + "files": [] + }, + { + "id": "587d7b8f367417b2b2512b63", + "completedDate": 1528917162952, + "files": [] + }, + { + "id": "587d7b8f367417b2b2512b62", + "completedDate": 1528916520035, + "files": [] + }, + { + "id": "587d7b8f367417b2b2512b61", + "completedDate": 1528916239317, + "files": [] + }, + { + "id": "587d7b8f367417b2b2512b60", + "completedDate": 1528909518505, + "files": [] + }, + { + "id": "587d7b8e367417b2b2512b5f", + "completedDate": 1528909162568, + "files": [] + }, + { + "id": "587d7b8e367417b2b2512b5e", + "completedDate": 1528909113205, + "files": [] + }, + { + "id": "587d7b8e367417b2b2512b5d", + "completedDate": 1528908970552, + "files": [] + }, + { + "id": "587d7b8e367417b2b2512b5c", + "completedDate": 1528908568106, + "files": [] + }, + { + "id": "587d7b8d367417b2b2512b5b", + "completedDate": 1528908421803, + "files": [] + }, + { + "id": "587d7db2367417b2b2512b8c", + "completedDate": 1528908345735, + "files": [] + }, + { + "id": "587d7db2367417b2b2512b8b", + "completedDate": 1528908123161, + "files": [] + }, + { + "id": "587d7db2367417b2b2512b8a", + "completedDate": 1528908033352, + "files": [] + }, + { + "id": "587d7db2367417b2b2512b89", + "completedDate": 1528907854219, + "files": [] + }, + { + "id": "587d7db1367417b2b2512b88", + "completedDate": 1528907672414, + "files": [] + }, + { + "id": "587d7db1367417b2b2512b87", + "completedDate": 1528907527117, + "files": [] + }, + { + "id": "587d7db1367417b2b2512b86", + "completedDate": 1528905869367, + "files": [] + }, + { + "id": "587d7db1367417b2b2512b85", + "completedDate": 1528905798962, + "files": [] + }, + { + "id": "587d7db0367417b2b2512b84", + "completedDate": 1528905563215, + "files": [] + }, + { + "id": "587d7db0367417b2b2512b83", + "completedDate": 1528905463958, + "files": [] + }, + { + "id": "587d7db0367417b2b2512b82", + "completedDate": 1528905321583, + "files": [] + }, + { + "id": "587d7db0367417b2b2512b81", + "completedDate": 1528905197504, + "files": [] + }, + { + "id": "587d7daf367417b2b2512b80", + "completedDate": 1528905158628, + "files": [] + }, + { + "id": "587d7daf367417b2b2512b7f", + "completedDate": 1528905128321, + "files": [] + }, + { + "id": "587d7daf367417b2b2512b7e", + "completedDate": 1528905019142, + "files": [] + }, + { + "id": "587d7daf367417b2b2512b7d", + "completedDate": 1528904850131, + "files": [] + }, + { + "id": "587d7dae367417b2b2512b7b", + "completedDate": 1528904663799, + "files": [] + }, + { + "id": "587d7dae367417b2b2512b7a", + "completedDate": 1528904554118, + "files": [] + }, + { + "id": "587d7dae367417b2b2512b79", + "completedDate": 1528904459368, + "files": [] + }, + { + "id": "587d7dad367417b2b2512b78", + "completedDate": 1528904402413, + "files": [] + }, + { + "id": "587d7dad367417b2b2512b77", + "completedDate": 1528904383963, + "files": [] + }, + { + "id": "587d7dad367417b2b2512b76", + "completedDate": 1528904346017, + "files": [] + }, + { + "id": "587d7dad367417b2b2512b75", + "completedDate": 1528904316135, + "files": [] + }, + { + "id": "587d7dac367417b2b2512b74", + "completedDate": 1528904261166, + "files": [] + }, + { + "id": "587d7dac367417b2b2512b73", + "completedDate": 1528904235855, + "files": [] + }, + { + "id": "579e2a2c335b9d72dd32e05c", + "completedDate": 1528904005293, + "files": [] + }, + { + "id": "587d7b7d367417b2b2512b1f", + "completedDate": 1528902841678, + "files": [] + }, + { + "id": "587d7b7d367417b2b2512b1e", + "completedDate": 1528902745590, + "files": [] + }, + { + "id": "587d7b7d367417b2b2512b1d", + "completedDate": 1528902722538, + "files": [] + }, + { + "id": "587d7b7d367417b2b2512b1c", + "completedDate": 1528902424707, + "files": [] + }, + { + "id": "587d7b7c367417b2b2512b1b", + "completedDate": 1528902294822, + "files": [] + }, + { + "id": "587d7b7c367417b2b2512b1a", + "completedDate": 1528902266174, + "files": [] + }, + { + "id": "587d7b7c367417b2b2512b19", + "completedDate": 1528902204888, + "files": [] + }, + { + "id": "587d7b7c367417b2b2512b18", + "completedDate": 1528902177052, + "files": [] + }, + { + "id": "587d7b7b367417b2b2512b16", + "completedDate": 1528901096407, + "files": [] + }, + { + "id": "587d7b7b367417b2b2512b15", + "completedDate": 1528900938052, + "files": [] + }, + { + "id": "587d7b7b367417b2b2512b14", + "completedDate": 1528900292192, + "files": [] + }, + { + "id": "587d7b7b367417b2b2512b17", + "completedDate": 1528900239045, + "files": [] + }, + { + "id": "587d7b7b367417b2b2512b13", + "completedDate": 1528900119504, + "files": [] + }, + { + "id": "587d7b7a367417b2b2512b12", + "completedDate": 1528900024682, + "files": [] + }, + { + "id": "587d78b3367417b2b2512b11", + "completedDate": 1528899739768, + "files": [] + }, + { + "id": "587d7b86367417b2b2512b3d", + "completedDate": 1528899440260, + "files": [] + }, + { + "id": "587d7b86367417b2b2512b3c", + "completedDate": 1528899295294, + "files": [] + }, + { + "id": "587d7b86367417b2b2512b3b", + "completedDate": 1528899043297, + "files": [] + }, + { + "id": "587d7b85367417b2b2512b3a", + "completedDate": 1528898859706, + "files": [] + }, + { + "id": "587d7b85367417b2b2512b39", + "completedDate": 1528898815395, + "files": [] + }, + { + "id": "587d7b85367417b2b2512b38", + "completedDate": 1528898783470, + "files": [] + }, + { + "id": "587d7b84367417b2b2512b37", + "completedDate": 1528898766004, + "files": [] + }, + { + "id": "587d7b84367417b2b2512b36", + "completedDate": 1528898255471, + "files": [] + }, + { + "id": "587d7b84367417b2b2512b35", + "completedDate": 1528897930802, + "files": [] + }, + { + "id": "587d7b84367417b2b2512b34", + "completedDate": 1528897909366, + "files": [] + }, + { + "id": "587d7b83367417b2b2512b33", + "completedDate": 1528897491942, + "files": [] + }, + { + "id": "587d7dbb367417b2b2512bac", + "completedDate": 1528858212055, + "files": [] + }, + { + "id": "587d7dbb367417b2b2512bab", + "completedDate": 1528857340061, + "files": [] + }, + { + "id": "587d7dbb367417b2b2512baa", + "completedDate": 1528857023208, + "files": [] + }, + { + "id": "587d7dba367417b2b2512ba9", + "completedDate": 1528845356403, + "files": [] + }, + { + "id": "587d7dba367417b2b2512ba8", + "completedDate": 1528843914026, + "files": [] + }, + { + "id": "587d7db9367417b2b2512ba7", + "completedDate": 1528843852819, + "files": [] + }, + { + "id": "587d7db9367417b2b2512ba6", + "completedDate": 1528843812163, + "files": [] + }, + { + "id": "587d7db9367417b2b2512ba5", + "completedDate": 1528843718606, + "files": [] + }, + { + "id": "587d7db9367417b2b2512ba4", + "completedDate": 1528842968052, + "files": [] + }, + { + "id": "587d7db8367417b2b2512ba3", + "completedDate": 1528842950539, + "files": [] + }, + { + "id": "587d7db8367417b2b2512ba2", + "completedDate": 1528842903133, + "files": [] + }, + { + "id": "587d7db8367417b2b2512ba1", + "completedDate": 1528842665151, + "files": [] + }, + { + "id": "5d712346c441eddfaeb5bdef", + "completedDate": 1528842647554, + "files": [] + }, + { + "id": "587d7db8367417b2b2512ba0", + "completedDate": 1528842629216, + "files": [] + }, + { + "id": "587d7db7367417b2b2512b9f", + "completedDate": 1528842603772, + "files": [] + }, + { + "id": "587d7db7367417b2b2512b9e", + "completedDate": 1528842544267, + "files": [] + }, + { + "id": "587d7db7367417b2b2512b9d", + "completedDate": 1528842515275, + "files": [] + }, + { + "id": "587d7db7367417b2b2512b9c", + "completedDate": 1528840984420, + "files": [] + }, + { + "id": "587d7db6367417b2b2512b9b", + "completedDate": 1528840909886, + "files": [] + }, + { + "id": "587d7db6367417b2b2512b9a", + "completedDate": 1528840649575, + "files": [] + }, + { + "id": "587d7db6367417b2b2512b99", + "completedDate": 1528839703992, + "files": [] + }, + { + "id": "587d7db6367417b2b2512b98", + "completedDate": 1528839624615, + "files": [] + }, + { + "id": "587d7db5367417b2b2512b97", + "completedDate": 1528839545835, + "files": [] + }, + { + "id": "587d7db5367417b2b2512b96", + "completedDate": 1528839487667, + "files": [] + }, + { + "id": "587d7db5367417b2b2512b95", + "completedDate": 1528836793048, + "files": [] + }, + { + "id": "587d7db5367417b2b2512b94", + "completedDate": 1528836647039, + "files": [] + }, + { + "id": "587d7db4367417b2b2512b93", + "completedDate": 1528836578373, + "files": [] + }, + { + "id": "587d7db4367417b2b2512b92", + "completedDate": 1528836503102, + "files": [] + }, + { + "id": "587d7db4367417b2b2512b91", + "completedDate": 1528836411536, + "files": [] + }, + { + "id": "587d7db4367417b2b2512b90", + "completedDate": 1528836347810, + "files": [] + }, + { + "id": "587d78b2367417b2b2512b10", + "completedDate": 1528745824285, + "files": [] + }, + { + "id": "587d78b2367417b2b2512b0f", + "completedDate": 1528742744006, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78b2367417b2b2512b0e", + "completedDate": 1528742701214, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a661e0f1068aca922b3ef17", + "completedDate": 1528742156096, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b7e367417b2b2512b20", + "completedDate": 1528742135455, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b8d367417b2b2512b59", + "completedDate": 1528742085698, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b8c367417b2b2512b54", + "completedDate": 1528734640861, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b8b367417b2b2512b53", + "completedDate": 1528733256806, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b8b367417b2b2512b50", + "completedDate": 1528732942662, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b8a367417b2b2512b4f", + "completedDate": 1528732804161, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b8a367417b2b2512b4e", + "completedDate": 1528732349407, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b8a367417b2b2512b4d", + "completedDate": 1528732036101, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b8a367417b2b2512b4c", + "completedDate": 1528731931778, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b89367417b2b2512b4b", + "completedDate": 1528729490152, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b89367417b2b2512b4a", + "completedDate": 1528729413355, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b89367417b2b2512b48", + "completedDate": 1528729040300, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b88367417b2b2512b47", + "completedDate": 1528728452978, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b88367417b2b2512b46", + "completedDate": 1528727990105, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b88367417b2b2512b45", + "completedDate": 1528727957080, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b88367417b2b2512b44", + "completedDate": 1528727575858, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b87367417b2b2512b43", + "completedDate": 1528727550058, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "598f48a36c8c40764b4e52b3", + "completedDate": 1528727417343, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b87367417b2b2512b42", + "completedDate": 1528727376633, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b87367417b2b2512b41", + "completedDate": 1528727272659, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b87367417b2b2512b40", + "completedDate": 1528727249380, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b87367417b2b2512b3f", + "completedDate": 1528727222148, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b7e367417b2b2512b21", + "completedDate": 1528727058038, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b7e367417b2b2512b24", + "completedDate": 1528726960708, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b7e367417b2b2512b22", + "completedDate": 1528726712992, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7b7e367417b2b2512b23", + "completedDate": 1528726687584, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a2efd662fb457916e1fe604", + "completedDate": 1528726654446, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "599a789b454f2bbd91a3ff4d", + "completedDate": 1528726636685, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "598e8944f009e646fc236146", + "completedDate": 1528726619417, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a94fe8569fb03452672e464", + "completedDate": 1528726554461, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a94fe7769fb03452672e463", + "completedDate": 1528726497738, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a94fe6269fb03452672e462", + "completedDate": 1528726457422, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a94fe5469fb03452672e461", + "completedDate": 1528726444838, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a94fe4469fb03452672e460", + "completedDate": 1528726409080, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a94fe3669fb03452672e45f", + "completedDate": 1528726361621, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a94fe2669fb03452672e45e", + "completedDate": 1528726329537, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78af367417b2b2512b00", + "completedDate": 1528725885250, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ae367417b2b2512aff", + "completedDate": 1528725862565, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ae367417b2b2512afe", + "completedDate": 1528725844043, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ae367417b2b2512afd", + "completedDate": 1528725812152, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ae367417b2b2512afc", + "completedDate": 1528725789525, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ad367417b2b2512afb", + "completedDate": 1528725762069, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ad367417b2b2512afa", + "completedDate": 1528725687987, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ad367417b2b2512af9", + "completedDate": 1528725643242, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ad367417b2b2512af8", + "completedDate": 1528725613909, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ac367417b2b2512af7", + "completedDate": 1528725556408, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ac367417b2b2512af6", + "completedDate": 1528725501244, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ac367417b2b2512af5", + "completedDate": 1528725475416, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ac367417b2b2512af4", + "completedDate": 1528725460248, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ab367417b2b2512af3", + "completedDate": 1528725430078, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ab367417b2b2512af2", + "completedDate": 1528725404445, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ab367417b2b2512af1", + "completedDate": 1528725386000, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78ab367417b2b2512af0", + "completedDate": 1528725349292, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78b1367417b2b2512b0c", + "completedDate": 1528725216220, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78b1367417b2b2512b0a", + "completedDate": 1528725059356, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78b1367417b2b2512b09", + "completedDate": 1528724874946, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78b0367417b2b2512b08", + "completedDate": 1528724820768, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7790367417b2b2512ab1", + "completedDate": 1528724720753, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7790367417b2b2512ab0", + "completedDate": 1528724642030, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7790367417b2b2512aaf", + "completedDate": 1528724605739, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778f367417b2b2512aae", + "completedDate": 1528724413398, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778f367417b2b2512aad", + "completedDate": 1528724356893, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778f367417b2b2512aac", + "completedDate": 1528724320641, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778e367417b2b2512aab", + "completedDate": 1528724190931, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778d367417b2b2512aaa", + "completedDate": 1528724078184, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778c367417b2b2512aa9", + "completedDate": 1528723974611, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778b367417b2b2512aa8", + "completedDate": 1528723909826, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778b367417b2b2512aa7", + "completedDate": 1528723549159, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778a367417b2b2512aa6", + "completedDate": 1528723491384, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d778a367417b2b2512aa5", + "completedDate": 1528723445304, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7789367417b2b2512aa4", + "completedDate": 1528723391089, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7788367417b2b2512aa3", + "completedDate": 1528723213266, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7788367417b2b2512aa2", + "completedDate": 1528723191539, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7787367417b2b2512aa1", + "completedDate": 1528723128518, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d774e367417b2b2512aa0", + "completedDate": 1528723095947, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d774e367417b2b2512a9f", + "completedDate": 1528723074570, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d774d367417b2b2512a9e", + "completedDate": 1528723032367, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d774c367417b2b2512a9d", + "completedDate": 1528723016297, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d774c367417b2b2512a9c", + "completedDate": 1528722884705, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a9367417b2b2512ae9", + "completedDate": 1528722189711, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a9367417b2b2512aea", + "completedDate": 1528722142299, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a9367417b2b2512ae8", + "completedDate": 1528722053070, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a8367417b2b2512ae7", + "completedDate": 1528722032467, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a8367417b2b2512ae6", + "completedDate": 1528721995155, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a8367417b2b2512ae5", + "completedDate": 1528721976152, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a8367417b2b2512ae4", + "completedDate": 1528721951775, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a8367417b2b2512ae3", + "completedDate": 1528721899118, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a7367417b2b2512ae2", + "completedDate": 1528721881145, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a7367417b2b2512ae1", + "completedDate": 1528721845732, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "58a7a6ebf9a6318348e2d5aa", + "completedDate": 1528721796290, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a7367417b2b2512ae0", + "completedDate": 1528721775709, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a7367417b2b2512adf", + "completedDate": 1528721631734, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a6367417b2b2512ade", + "completedDate": 1528721516690, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a6367417b2b2512add", + "completedDate": 1528721308692, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a6367417b2b2512adc", + "completedDate": 1528721257100, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a6367417b2b2512adb", + "completedDate": 1528721238402, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a5367417b2b2512ada", + "completedDate": 1528721220923, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a5367417b2b2512ad9", + "completedDate": 1528721198021, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a5367417b2b2512ad8", + "completedDate": 1528721176164, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a5367417b2b2512ad7", + "completedDate": 1528721108378, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a5367417b2b2512ad6", + "completedDate": 1528721076608, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a4367417b2b2512ad5", + "completedDate": 1528721029351, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a4367417b2b2512ad4", + "completedDate": 1528720989595, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a4367417b2b2512ad3", + "completedDate": 1528720962932, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a4367417b2b2512ad2", + "completedDate": 1528720915835, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a3367417b2b2512ad1", + "completedDate": 1528720843738, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a3367417b2b2512ad0", + "completedDate": 1528720815216, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a3367417b2b2512acf", + "completedDate": 1528720802544, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78a3367417b2b2512ace", + "completedDate": 1528720790009, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781e367417b2b2512acc", + "completedDate": 1528720770993, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781e367417b2b2512acb", + "completedDate": 1528720747104, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781e367417b2b2512aca", + "completedDate": 1528720721929, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781e367417b2b2512ac9", + "completedDate": 1528720703105, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781d367417b2b2512ac8", + "completedDate": 1528720670005, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781d367417b2b2512ac5", + "completedDate": 1528720645332, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781c367417b2b2512ac4", + "completedDate": 1528720634778, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781c367417b2b2512ac3", + "completedDate": 1528720625208, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781c367417b2b2512ac2", + "completedDate": 1528720592433, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781c367417b2b2512ac0", + "completedDate": 1528720543076, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781c367417b2b2512abf", + "completedDate": 1528720526234, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781b367417b2b2512abe", + "completedDate": 1528720510632, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781b367417b2b2512abd", + "completedDate": 1528720467749, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781b367417b2b2512abc", + "completedDate": 1528720453878, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781b367417b2b2512abb", + "completedDate": 1528720413342, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781b367417b2b2512aba", + "completedDate": 1528720403159, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781a367417b2b2512ab9", + "completedDate": 1528720194712, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781a367417b2b2512ab8", + "completedDate": 1528720178074, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d781a367417b2b2512ab7", + "completedDate": 1528720151746, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7791367417b2b2512ab5", + "completedDate": 1528720134400, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7791367417b2b2512ab4", + "completedDate": 1528720124159, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d7791367417b2b2512ab3", + "completedDate": 1528720108175, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a9d72ad424fe3d0e10cad16", + "completedDate": 1528720042777, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a9d72a1424fe3d0e10cad15", + "completedDate": 1528719982834, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a9d7295424fe3d0e10cad14", + "completedDate": 1528719930392, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a9d727a424fe3d0e10cad12", + "completedDate": 1528719809651, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a9d726c424fe3d0e10cad11", + "completedDate": 1528719689520, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "5a9d725e424fe3d0e10cad10", + "completedDate": 1528719579787, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad82fee1322bd9aedf08721", + "completedDate": 1528719519470, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "58c383d33e2e3259241f3076", + "completedDate": 1528719468043, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78aa367417b2b2512aec", + "completedDate": 1528719392137, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "587d78aa367417b2b2512aed", + "completedDate": 1528719352474, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad88fee1348bd9aedf08816", + "completedDate": 1528685796989, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aecf08801", + "completedDate": 1528684512716, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244dd", + "completedDate": 1475258032598, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "660add10cb82ac38a17513be", + "completedDate": 1515450994243, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244de", + "completedDate": 1475258201433, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08801", + "completedDate": 1475094786951, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08804", + "completedDate": 1475094833566, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08833", + "completedDate": 1475094870641, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fed1348bd9aedf08833", + "completedDate": 1475094890483, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08803", + "completedDate": 1475094925451, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08805", + "completedDate": 1475095000824, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aecf08806", + "completedDate": 1475095068584, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aefe08806", + "completedDate": 1475095126954, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08806", + "completedDate": 1475095220729, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aede08807", + "completedDate": 1475095251313, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08807", + "completedDate": 1475095315463, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08808", + "completedDate": 1475095349372, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08812", + "completedDate": 1475095439395, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9acdf08812", + "completedDate": 1475095537795, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9bedf08813", + "completedDate": 1475095645490, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08814", + "completedDate": 1475095674621, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08815", + "completedDate": 1475095702447, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08816", + "completedDate": 1475095780920, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aede08817", + "completedDate": 1475095851150, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08817", + "completedDate": 1475095890671, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08820", + "completedDate": 1475095950614, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08827", + "completedDate": 1475096026221, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08828", + "completedDate": 1475096146254, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08829", + "completedDate": 1475096175545, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08830", + "completedDate": 1475096220710, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aede08830", + "completedDate": 1475096258812, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedd08830", + "completedDate": 1475096412586, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08834", + "completedDate": 1475096574019, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08835", + "completedDate": 1475096736280, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedd08835", + "completedDate": 1475096767113, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aede08835", + "completedDate": 1475096824274, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fed1348bd9aede07836", + "completedDate": 1475096878286, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87eee1348bd9aede07836", + "completedDate": 1475096925946, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87dee1348bd9aede07836", + "completedDate": 1475096968597, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad88fee1348bd9aedf08825", + "completedDate": 1475097030436, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08822", + "completedDate": 1475097048908, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08823", + "completedDate": 1475097079567, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08824", + "completedDate": 1475097122623, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1248bd9aedf08824", + "completedDate": 1475097163693, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08826", + "completedDate": 1475097197806, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9afdf08726", + "completedDate": 1475097220823, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08736", + "completedDate": 1475097245742, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08746", + "completedDate": 1475097305636, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08756", + "completedDate": 1475097367679, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf04756", + "completedDate": 1475097441406, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd8aedf06756", + "completedDate": 1475097504209, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf06756", + "completedDate": 1475097605201, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf07756", + "completedDate": 1475097675710, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08726", + "completedDate": 1475102179284, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08721", + "completedDate": 1475102344318, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08719", + "completedDate": 1475102399325, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aede08718", + "completedDate": 1475102447915, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad82fee1348bd9aedf08721", + "completedDate": 1475102528619, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9acde08712", + "completedDate": 1475102639748, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9acde08812", + "completedDate": 1475102771357, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd8acde08812", + "completedDate": 1475102802266, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348cd8acdf08812", + "completedDate": 1475102852811, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348cd8acef08812", + "completedDate": 1475102997685, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348cd8acef08811", + "completedDate": 1475103090510, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348cd8acef08813", + "completedDate": 1475103173521, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348ce8acef08814", + "completedDate": 1475103241775, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad88fee1348ce8acef08815", + "completedDate": 1475103767585, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1347bd9aedf08845", + "completedDate": 1475103941867, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08845", + "completedDate": 1475104193824, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "560add10cb82ac38a17513be", + "completedDate": 1475104385115, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "560add37cb82ac38a17513bf", + "completedDate": 1475105708678, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "560add56cb82ac38a17513c0", + "completedDate": 1475105917537, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "560add71cb82ac38a17513c2", + "completedDate": 1475105957457, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "560adf65cb82ac38a17513c2", + "completedDate": 1475106219178, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "560add8ccb82ac38a17513c4", + "completedDate": 1475106445148, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "bad87fee1348bd9aede08845", + "completedDate": 1475107618308, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedd08845", + "completedDate": 1475107867871, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedc08845", + "completedDate": 1475108019303, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedb08845", + "completedDate": 1475108135358, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aeda08845", + "completedDate": 1475108802536, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed908845", + "completedDate": 1475108989462, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908845", + "completedDate": 1475109094598, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908846", + "completedDate": 1475109155433, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908746", + "completedDate": 1475109179986, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9bec908846", + "completedDate": 1475109200468, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908847", + "completedDate": 1475109232567, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908848", + "completedDate": 1475109272839, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908849", + "completedDate": 1475109317110, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908850", + "completedDate": 1475109360603, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908852", + "completedDate": 1475109405858, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908853", + "completedDate": 1475109460239, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908854", + "completedDate": 1475109523665, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908855", + "completedDate": 1475109597253, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908856", + "completedDate": 1475109699779, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aec908857", + "completedDate": 1475109754181, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "573c96eac9a6be092d7830c1", + "completedDate": 1475120191143, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "560ade65cb82ac38a17513c2", + "completedDate": 1475120213223, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "570add8ccb82ac38a17513c3", + "completedDate": 1475120317675, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "560add8ccb81ac38a17513c4", + "completedDate": 1475120349142, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "bad87fee1348bd9acdd08826", + "completedDate": 1475120453111, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9bedc08826", + "completedDate": 1475120559183, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aedc08826", + "completedDate": 1475120631184, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aeda08826", + "completedDate": 1475120755306, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aeda08726", + "completedDate": 1475120779449, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed908626", + "completedDate": 1475121062291, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed918626", + "completedDate": 1475121104072, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed908826", + "completedDate": 1475121170178, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed808826", + "completedDate": 1475121219834, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "564944c91be2204b269d51e3", + "completedDate": 1475121806404, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed708826", + "completedDate": 1475121839535, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed608826", + "completedDate": 1475121896777, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed508826", + "completedDate": 1475121971349, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed308826", + "completedDate": 1475122255862, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed208826", + "completedDate": 1475122353496, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed108826", + "completedDate": 1475122451433, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aed008826", + "completedDate": 1475122549646, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bad87fee1348bd9aecb08826", + "completedDate": 1475122606323, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "bd7158d8c442eddfbeb5bd1f", + "completedDate": 1475123013392, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "bd7158d8c442eddfaeb5bd18", + "completedDate": 1475164643824, + "solution": "https://codepen.io/moT01/pen/ZpJpKp", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7123c9c443eddfaeb5bdef", + "completedDate": 1475173197683, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244a8", + "completedDate": 1475173236795, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244a9", + "completedDate": 1475173254001, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244aa", + "completedDate": 1475173281010, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244ab", + "completedDate": 1475173381082, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c11feddfaeb3bdef", + "completedDate": 1475173390858, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c11feddfaeb4bdef", + "completedDate": 1475173413711, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1231c1c11feddfaeb5bdef", + "completedDate": 1475173423698, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c11feddfaeb6bdef", + "completedDate": 1475173438268, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244ac", + "completedDate": 1475173465003, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244ad", + "completedDate": 1475173477062, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1391c1c11feddfaeb4bdef", + "completedDate": 1475173519510, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7993c9c69feddfaeb7bdef", + "completedDate": 1475173533104, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7993c9ca9feddfaeb7bdef", + "completedDate": 1475173564954, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244ae", + "completedDate": 1475176291002, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244af", + "completedDate": 1475176331489, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b0", + "completedDate": 1475176352871, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b1", + "completedDate": 1475176403989, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b2", + "completedDate": 1475176422046, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b3", + "completedDate": 1475176590196, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7123c9c444eddfaeb5bdef", + "completedDate": 1475176632734, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b5", + "completedDate": 1475176719867, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b4", + "completedDate": 1475176819114, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b6", + "completedDate": 1475176908316, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b7", + "completedDate": 1475176990858, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b8", + "completedDate": 1475177105048, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244b9", + "completedDate": 1475177174580, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244ed", + "completedDate": 1475177236572, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7123c9c448eddfaeb5bdef", + "completedDate": 1475177278183, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7123c9c549eddfaeb5bdef", + "completedDate": 1475179313868, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244ba", + "completedDate": 1475179482988, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7123c9c450eddfaeb5bdef", + "completedDate": 1475179518666, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7123c9c451eddfaeb5bdef", + "completedDate": 1475179613795, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7123c9c452eddfaeb5bdef", + "completedDate": 1475179659278, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244bb", + "completedDate": 1475179965317, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7993c9c69feddfaeb8bdef", + "completedDate": 1475180000714, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c11feddfaeb7bdef", + "completedDate": 1475180039289, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392ca", + "completedDate": 1475180095658, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c11feddfaeb8bdef", + "completedDate": 1475181698926, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56592a60ddddeae28f7aa8e1", + "completedDate": 1475181780041, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392cb", + "completedDate": 1475181833413, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392cc", + "completedDate": 1475183501952, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392cd", + "completedDate": 1475183525070, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392ce", + "completedDate": 1475183590132, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244bc", + "completedDate": 1475183698232, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392cf", + "completedDate": 1475183805400, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244bd", + "completedDate": 1475246542486, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244be", + "completedDate": 1475246816353, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244bf", + "completedDate": 1475246928293, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244c0", + "completedDate": 1475246987475, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244c2", + "completedDate": 1475247140834, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244c3", + "completedDate": 1475247240302, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244c6", + "completedDate": 1475249114465, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7123c9c441eddfaeb5bdef", + "completedDate": 1475249172491, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c12feddfaeb3bdef", + "completedDate": 1475249802320, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d0", + "completedDate": 1475255137391, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d1", + "completedDate": 1475255166071, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d2", + "completedDate": 1475255268194, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d3", + "completedDate": 1475255346517, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d4", + "completedDate": 1475255395602, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d5", + "completedDate": 1475255430440, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d6", + "completedDate": 1475255447772, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d7", + "completedDate": 1475255476799, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d8", + "completedDate": 1475255568397, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244d9", + "completedDate": 1475255614997, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244da", + "completedDate": 1475255683109, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244db", + "completedDate": 1475255732118, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "5690307fddb111c6084545d7", + "completedDate": 1475255808973, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244dc", + "completedDate": 1475256242575, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "5664820f61c48e80c9fa476c", + "completedDate": 1475256945917, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7158d8c443eddfaeb5bdee", + "completedDate": 1515450964126, + "solution": "https://pinter.herokuapp.com/#/", + "challengeType": 4, + "files": [] + }, + { + "id": "bad87fee1348bd9aedf08802", + "completedDate": 1475094814477, + "solution": null, + "challengeType": null, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244df", + "completedDate": 1475258308371, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244e0", + "completedDate": 1475258479391, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "5679ceb97cbaa8c51670a16b", + "completedDate": 1475259156604, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244c4", + "completedDate": 1475259288195, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "565bbe00e9cc8ac0725390f4", + "completedDate": 1475262913431, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392d0", + "completedDate": 1475266763329, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244c7", + "completedDate": 1475266806568, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244c8", + "completedDate": 1475266879713, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244c9", + "completedDate": 1475267928028, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392d1", + "completedDate": 1475267998292, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392d2", + "completedDate": 1475268069965, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56bbb991ad1ed5201cd392d3", + "completedDate": 1475268145412, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244ca", + "completedDate": 1475297124064, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "567af2437cbaa8c51670a16c", + "completedDate": 1475297309457, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244cb", + "completedDate": 1475297597704, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244cc", + "completedDate": 1475297776784, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244cd", + "completedDate": 1475297918874, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244cf", + "completedDate": 1475519963758, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c11feddfaeb5bdef", + "completedDate": 1475520469953, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56104e9e514f539506016a5c", + "completedDate": 1475520549003, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56105e7b514f539506016a5e", + "completedDate": 1475520602983, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "5675e877dbd60be8ad28edc6", + "completedDate": 1475520969902, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244e1", + "completedDate": 1475521239678, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c11feddfaeb1bdef", + "completedDate": 1475521320287, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "5688e62ea601b2482ff8422b", + "completedDate": 1475524381505, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c11feddfaeb9bdef", + "completedDate": 1475524515916, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c12feddfaeb1bdef", + "completedDate": 1475524655165, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c12feddfaeb2bdef", + "completedDate": 1475543615965, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c12feddfaeb6bdef", + "completedDate": 1475543695668, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7128d8c441eddfbeb5bddf", + "completedDate": 1475544021850, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "cf1111c1c12feddfaeb7bdef", + "completedDate": 1475544296945, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c12feddfaeb8bdef", + "completedDate": 1475544467549, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c13feddfaeb3bdef", + "completedDate": 1475544513783, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c15feddfaeb1bdef", + "completedDate": 1475544570212, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c15feddfaeb2bdef", + "completedDate": 1475544847062, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c15feddfaeb4bdef", + "completedDate": 1475545110298, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "563cfb55594311ffcb333c70", + "completedDate": 1475545212806, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c15feddfaeb3bdef", + "completedDate": 1475547779361, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c15feddfaeb7bdef", + "completedDate": 1475547932256, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c15feddfaeb8bdef", + "completedDate": 1475548117909, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c15feddfaeb9bdef", + "completedDate": 1475548202572, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c16feddfaeb1bdef", + "completedDate": 1475548720499, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c16feddfaeb2bdef", + "completedDate": 1475548785961, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c16feddfaeb3bdef", + "completedDate": 1475548816796, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c16feddfaeb4bdef", + "completedDate": 1475548955141, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c16feddfaeb5bdef", + "completedDate": 1475549004864, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7158d2c442eddfbeb5bd1f", + "completedDate": 1475549039674, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "a202eed8fc186c8434cb6d61", + "completedDate": 1475549776986, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a302f7aae1aa3152a5b413bc", + "completedDate": 1475550618044, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "aaa48de84e1ecc7c742e1124", + "completedDate": 1475551824473, + "solution": "\nfunction palindrome(str) {\n \n //remove all punctuation and spaces\n var str1 = str.replace(/[^A-Za-z0-9]/g, '');\n //make all lower case\n var str2 = str1.toLowerCase();\n console.log(str2);\n \n var str3 = str2.split('').reverse().join('');\n console.log(str3);\n \n if (str2 === str3)\n {\n return true;\n }\n \n else\n { \n return false;\n }\n}\n\n\n\npalindrome(\"eye\");\n", + "challengeType": 5, + "files": [] + }, + { + "id": "a26cbbe9ad8655a977e1ceb5", + "completedDate": 1475552516511, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "ab6137d4e35944e21037b769", + "completedDate": 1475553251232, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a789b3483989747d63b0e427", + "completedDate": 1475553881835, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "acda2fb1324d9b0fa741e6b5", + "completedDate": 1475554349724, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "afcc8d540bea9ea2669306b6", + "completedDate": 1475555795487, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "af2170cad53daa0770fabdea", + "completedDate": 1475594634836, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "ac6993d51946422351508a41", + "completedDate": 1475598636059, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a9bd25c716030ec90084d8a1", + "completedDate": 1475622950421, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "ab31c21b530c0dafa9e241ee", + "completedDate": 1475628875890, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "adf08ec01beb4f99fc7a68f2", + "completedDate": 1475634954182, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a39963a4c10bc8b4d4f06d7e", + "completedDate": 1476834441854, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a24c1a4622e3c05097f71d67", + "completedDate": 1476839147914, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "56533eb9ac21ba0edf2244e2", + "completedDate": 1476843234983, + "solution": "\nfunction rot13(str) { // LBH QVQ VG!\n //var arr0 = str.split(\"\");\n var arr = [];\n var arr2 = [];\n var newstr = \"\";\n //concat array to string\n //var str3 = String.fromCharCode(65);\n //var str2 = 'did'.charCodeAt(0);\n \n for (i=0; i= 65 && str.charCodeAt(i) <= 77) //A-M\n {\n filler = str.charCodeAt(i) + 13;\n arr.push(filler);\n }\n else if (str.charCodeAt(i) > 77 && str.charCodeAt(i) <= 90) //N-Z\n {\n filler = str.charCodeAt(i) - 13;\n arr.push(filler);\n }\n else //all other characters !, .*?\n {\n filler = str.charCodeAt(i);\n arr.push(filler);\n }\n }\n \n for (j=0; j=1000) {\n newArr.push(\"M\"); \n num -= 1000;\n }\n \n if (num >= 900) {\n newArr.push(\"CM\");\n num -= 900;\n }\n \n if (num >= 500) {\n newArr.push(\"D\");\n num -= 500;\n }\n \n if (num >= 400) {\n newArr.push(\"CD\");\n num -= 400;\n }\n \n while (num >= 100) { \n newArr.push(\"C\");\n num -= 100;\n }\n\n if (num >= 90) {\n newArr.push(\"XC\");\n num -= 90;\n }\n \n if (num >= 50) {\n newArr.push(\"L\");\n num -= 50;\n }\n \n if (num >= 40) {\n newArr.push(\"XL\");\n num -= 40;\n }\n \n while (num >= 10) {\n newArr.push(\"X\");\n num -= 10;\n }\n \n if (num >= 9) {\n newArr.push(\"IX\");\n num -= 9;\n }\n \n if (num >= 5) {\n newArr.push(\"V\");\n num -= 5;\n }\n \n if (num >= 4) {\n newArr.push(\"IV\");\n num -= 4;\n }\n \n while (num > 0) {\n newArr.push(\"I\");\n num -= 1;\n }\n \n result = newArr.join();\n result = result.replace(/,/g,\"\");\n console.log(result);\n return result;\n}\n\nconvertToRoman(36);\n", + "challengeType": 5, + "files": [] + }, + { + "id": "a0b5010f579e69b815e7c5d6", + "completedDate": 1477512598599, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "aa7697ea2477d1316795783b", + "completedDate": 1477516427303, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "afd15382cdfb22c9efe8b7de", + "completedDate": 1477519032167, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "af7588ade1100bde429baf20", + "completedDate": 1477520894164, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a77dbc43c33f39daa4429b4f", + "completedDate": 1477521441905, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a105e963526e7de52b219be9", + "completedDate": 1477523752866, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a6b0bb188d873cb2c8729495", + "completedDate": 1477529331616, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a5229172f011153519423690", + "completedDate": 1477535395217, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a8d97bd4c764e91f9d2bda01", + "completedDate": 1477592139677, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "af4afb223120f7348cdfc9fd", + "completedDate": 1478129569493, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "bd7158d8c442eddfaeb5bd19", + "completedDate": 1479175997023, + "solution": "http://codepen.io/moT01/pen/LRoxrQ", + "challengeType": 3, + "files": [] + }, + { + "id": "a8e512fbe388ac2f9198f0fa", + "completedDate": 1481583669528, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a103376db3ba46b2d50db289", + "completedDate": 1481587010971, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a3bfc1673c0526e06d3ac698", + "completedDate": 1481608493885, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "ae9defd7acaf69703ab432ea", + "completedDate": 1481736052042, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a6e40f1041b06c996f7b2406", + "completedDate": 1481736237406, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a5deed1811a43193f9f1c841", + "completedDate": 1481740006290, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "ab306dbdcc907c7ddfc30830", + "completedDate": 1481745472605, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a10d2431ad0c6a099a4b8b52", + "completedDate": 1481746815383, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a97fd23d9b809dac9921074f", + "completedDate": 1481758984188, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a3f503de51cfab748ff001aa", + "completedDate": 1481824947299, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a56138aff60341a09ed6c480", + "completedDate": 1481837456810, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a3f503de51cf954ede28891d", + "completedDate": 1481845736605, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "56b15f15632298c12f315184", + "completedDate": 1481860652201, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315185", + "completedDate": 1481860854284, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31518f", + "completedDate": 1481861004554, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31518e", + "completedDate": 1481862599572, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31518c", + "completedDate": 1481862758623, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31518d", + "completedDate": 1481862797677, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31518b", + "completedDate": 1481862861505, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31518a", + "completedDate": 1481862919212, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315189", + "completedDate": 1481863139471, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315188", + "completedDate": 1481863215509, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315187", + "completedDate": 1481863487868, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315186", + "completedDate": 1481863524852, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7129d8a441eddfbeb5bddf", + "completedDate": 1481863610234, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7126d8c441eddfbeb5bddf", + "completedDate": 1481863731854, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7125d8c441eddfbeb5bddf", + "completedDate": 1481864211145, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7122d8c441eddfbeb5bddf", + "completedDate": 1481864321324, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7124d8c441eddfbeb5bddf", + "completedDate": 1481864475753, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7123d8c441eddfbeb5bddf", + "completedDate": 1481864582256, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7121d8c441eddfbeb5bddf", + "completedDate": 1481864696095, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7120d8c441eddfbeb5bddf", + "completedDate": 1481864846892, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd712fd8c441eddfbeb5bddf", + "completedDate": 1481864954292, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd712ed8c441eddfbeb5bddf", + "completedDate": 1481865043747, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd712dd8c441eddfbeb5bddf", + "completedDate": 1481865144055, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd712cd8c441eddfbeb5bddf", + "completedDate": 1481865164967, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31510f", + "completedDate": 1481865503851, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7129d80441eddfbeb5bddf", + "completedDate": 1481865687477, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7129d8b441eddfbeb5bddf", + "completedDate": 1481866381587, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7029d8c441eddfbeb5bddf", + "completedDate": 1481868133911, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd712ad8c441eddfbeb5bddf", + "completedDate": 1481868315911, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7119d8c441eddfbeb5bddf", + "completedDate": 1481868379586, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd712bd8c441eddfbeb5bddf", + "completedDate": 1481868532739, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "bd7129d89441eddfbeb5bddf", + "completedDate": 1481868862816, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315183", + "completedDate": 1481897167093, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315182", + "completedDate": 1481897290924, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315181", + "completedDate": 1481897771281, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f315180", + "completedDate": 1481898177819, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31517f", + "completedDate": 1481898276836, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31517e", + "completedDate": 1481898787535, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31517d", + "completedDate": 1481898913196, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31517c", + "completedDate": 1481899378324, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31517b", + "completedDate": 1481899595427, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "56b15f15632298c12f31517a", + "completedDate": 1481900212775, + "solution": null, + "challengeType": 6, + "files": [] + }, + { + "id": "a2f1d72d9b908d0bd72bb9f6", + "completedDate": 1481903430810, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "aff0395860f5d3034dc0bfc9", + "completedDate": 1482122509252, + "solution": "\nfunction telephoneCheck(str) {\n \n var tests = /^(1|1[\\s-])?(\\d{3}|\\d{3}[\\s-]|\\(\\d{3}\\)|\\(\\d{3}\\)\\s)(\\d{3}|\\d{3}[\\s-])\\d{4}$/g;\n return tests.test(str);\n}\n\n\n\ntelephoneCheck(\"555-555-5555\");\n", + "challengeType": 5, + "files": [] + }, + { + "id": "a7bf700cd123b9a54eef01d5", + "completedDate": 1482185656510, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "a19f0fbe1872186acd434d5a", + "completedDate": 1482201811080, + "solution": null, + "challengeType": 5, + "files": [] + }, + { + "id": "aa2e6f85cab2ab736c9a9b24", + "completedDate": 1482248818632, + "solution": "\nfunction checkCashRegister(price, cash, cid) {\n var changeleft = Math.round((cash-price)*100)/100, changetotal = Math.round((cash-price)*100)/100, totalcid = 0, arr = [], temp = 0, temp2 = 0;\n\n var values = [[\"PENNY\", 0.01], \n [\"NICKEL\", 0.05], \n [\"DIME\", 0.10], \n [\"QUARTER\", 0.25], \n [\"ONE\", 1.00], \n [\"FIVE\", 5.00], \n [\"TEN\", 10.00], \n [\"TWENTY\", 20.00], \n [\"ONE HUNDRED\", 100.00]];\n \n //this get the cash in the till\n for(var i=0; i= value && cid[j][1] >= value) {\n changeleft = Math.round((changeleft-value)*100)/100;\n cid[j][1] = Math.round((cid[j][1]-value)*100)/ 100;\n totalcid = Math.round((totalcid-value)*100)/100;\n temp = Math.round((temp+value)*100)/100;\n }\n temp2 = Math.round((temp2+temp)*100)/100;\n if(temp !== 0) {\n arr.push([values[j][0],temp]);\n }\n }\n \n for(var k=8; k>=0; k--) {\n getchange(k, values[k][1]);\n }\n\n if(temp2 < changetotal) {\n return \"Insufficient Funds\";\n }\n if(totalcid !== 0) {\n return arr;\n } else {\n return \"Closed\";\n }\n}", + "challengeType": 5, + "files": [] + }, + { + "id": "bd7158d8c442eddfaeb5bd1c", + "completedDate": 1484354051397, + "solution": "http://codepen.io/moT01/pen/jyqrNr", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7158d8c442eddfaeb5bd1f", + "completedDate": 1484776063352, + "solution": "http://codepen.io/moT01/pen/WRGERp", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7158d8c442eddfaeb5bd0f", + "completedDate": 1485204463074, + "solution": "http://codepen.io/moT01/pen/PbrzQo", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7158d8c442eedfaeb5bd1c", + "completedDate": 1485204700866, + "solution": "http://codepen.io/moT01/pen/egOKqO", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7158d8c442eddfaeb5bd17", + "completedDate": 1485289601534, + "solution": "http://codepen.io/moT01/pen/rWxJoa", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7158d8c242eddfaeb5bd13", + "completedDate": 1485315439137, + "solution": "http://codepen.io/moT01/pen/vgOaoJ", + "challengeType": 3, + "files": [] + }, + { + "id": "561add10cb82ac38a17513be", + "completedDate": 1485316065499, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "cf1111c1c16feddfaeb6bdef", + "completedDate": 1485467383567, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "cf1111c1c16feddfaeb7bdef", + "completedDate": 1485467595207, + "solution": null, + "challengeType": 1, + "files": [] + }, + { + "id": "bd7154d8c242eddfaeb5bd13", + "completedDate": 1488664622012, + "solution": "http://codepen.io/moT01/pen/aJzJQg", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7155d8c242eddfaeb5bd13", + "completedDate": 1488665107117, + "solution": "http://codepen.io/moT01/pen/ygwEaK", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7157d8c242eddfaeb5bd13", + "completedDate": 1488665153261, + "solution": "http://codepen.io/moT01/pen/egrZzr", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7156d8c242eddfaeb5bd13", + "completedDate": 1488665196848, + "solution": "http://codepen.io/moT01/pen/ggBEWY", + "challengeType": 3, + "files": [] + }, + { + "id": "58d9cc820ce2197370032a13", + "completedDate": 1490789539522, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "bd7198d8c242eddfaeb5bd13", + "completedDate": 1490790216213, + "solution": "http://codepen.io/moT01/pen/EWmYPq", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7108d8c242eddfaeb5bd13", + "completedDate": 1491529027827, + "solution": "http://codepen.io/moT01/full/dvEgav/", + "challengeType": 3, + "files": [] + }, + { + "id": "bd7153d8c242eddfaeb5bd13", + "completedDate": 1491530360535, + "solution": "http://codepen.io/moT01/full/OpOOxg/", + "challengeType": 3, + "files": [] + }, + { + "id": "561add10cb82ac38a17513b3", + "completedDate": 1491530482152, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "bd7353d8c341eddeaeb5bd0f", + "completedDate": 1496195906794, + "solution": null, + "challengeType": 2, + "files": [] + }, + { + "id": "bd7153d8c441eddfaeb5bd0f", + "completedDate": 1496235235066, + "solution": null, + "challengeType": 2, + "files": [] + }, + { + "id": "bd7153d8c441eddfaeb5bdff", + "completedDate": 1496603882718, + "solution": null, + "challengeType": 2, + "files": [] + }, + { + "id": "bd7153d8c441eddfaeb5bdfe", + "completedDate": 1496603911653, + "solution": null, + "challengeType": 2, + "files": [] + }, + { + "id": "bd7153d8c441eddfaeb5bdfd", + "completedDate": 1496603991361, + "solution": null, + "challengeType": 2, + "files": [] + }, + { + "id": "bd7153d8c441eddfaeb5bd1f", + "completedDate": 1496752318061, + "solution": null, + "challengeType": 2, + "files": [] + }, + { + "id": "bd7243d8c341eddeaeb5bd0f", + "completedDate": 1497409186851, + "solution": null, + "challengeType": 2, + "files": [] + }, + { + "id": "576d6e1b12fd92c4207a9cbd", + "completedDate": 1497411084548, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "bd7158d8c443edefaeb5bdee", + "completedDate": 1500083078110, + "solution": "https://web-searcher.glitch.me/", + "challengeType": 4, + "files": [] + }, + { + "id": "bd7158d8c443eddfaeb5bcef", + "completedDate": 1500911842686, + "solution": null, + "challengeType": 7, + "files": [] + }, + { + "id": "bd7158d8c443eddfaeb5bdef", + "completedDate": 1503596314310, + "solution": "https://vote-app.glitch.me/", + "challengeType": 4, + "files": [] + }, + { + "id": "bd7158d8c443eddfaeb5bd0e", + "completedDate": 1504564623846, + "solution": "http://mystocks.glitch.me/", + "challengeType": 4, + "files": [] + }, + { + "id": "bd7158d8c443eddfaeb5bdff", + "completedDate": 1509469714079, + "solution": "https://yoyo44.herokuapp.com/", + "challengeType": 4, + "files": [] + }, + { + "id": "bd7158d8c443eddfaeb5bd0f", + "completedDate": 1513966678577, + "solution": "https://book-fcc.herokuapp.com/", + "challengeType": 4, + "files": [] + }, + { + "id": "561abd10cb81ac38a17513bc", + "completedDate": 1528930836376, + "challengeType": 7, + "files": [] + }, + { + "id": "561acd10cb82ac38a17513bc", + "completedDate": 1532961178690, + "challengeType": 7, + "files": [] + }, + { + "id": "561add10cb82ac38a17513bc", + "completedDate": 1533273784477, + "challengeType": 7, + "files": [] + }, + { + "id": "561add10cb82ac38a17523bc", + "completedDate": 1533833480936, + "challengeType": 7, + "files": [] + }, + { + "id": "5a553ca864b52e1d8bceea14", + "completedDate": 1537145017407, + "challengeType": 7, + "files": [] + }, + { + "id": "561add10cb82ac38a17213bc", + "completedDate": 1538239301985, + "challengeType": 7, + "files": [] + }, + { + "id": "602da04c22201c65d2a019f4", + "completedDate": 1642566694752, + "files": [] + }, + { + "id": "602d9ff222201c65d2a019f2", + "completedDate": 1642566450182, + "files": [] + }, + { + "id": "5fa323cdaf6a73463d590659", + "completedDate": 1642566442917, + "files": [] + }, + { + "id": "5f32db63eb37f7e17323f459", + "completedDate": 1642566429622, + "files": [] + }, + { + "id": "5f87ac112ae598023a42df1a", + "completedDate": 1642566416673, + "files": [] + }, + { + "id": "5f5b969a05380d2179fe6e18", + "completedDate": 1642566406680, + "files": [] + }, + { + "id": "602da0de22201c65d2a019f6", + "completedDate": 1642566390464, + "files": [] + }, + { + "id": "5f9771307d4d22b9d2b75a94", + "completedDate": 1642566369992, + "files": [] + }, + { + "id": "618590adb0730ca724e37672", + "completedDate": 1642566358706, + "files": [] + }, + { + "id": "602da0c222201c65d2a019f5", + "completedDate": 1642566353635, + "files": [] + }, + { + "id": "5f5904ac738bc2fa9efecf5a", + "completedDate": 1642566336874, + "files": [] + }, + { + "id": "5f1a4ef5d5d6b5ab580fc6ae", + "completedDate": 1642566305566, + "files": [] + }, + { + "id": "5f2c289f164c29556da632fd", + "completedDate": 1642566297762, + "files": [] + }, + { + "id": "5ea8adfab628f68d805bfc5e", + "completedDate": 1642566255203, + "files": [] + }, + { + "id": "606243f50267e718b1e755f4", + "completedDate": 1642615978255, + "challengeType": 7, + "files": [] + }, + { + "id": "6145f685797bd30df9784e8c", + "completedDate": 1668803655086, + "files": [] + } +] diff --git a/client/src/__mocks__/edges.json b/client/src/__mocks__/edges.json new file mode 100644 index 00000000000000..13c3dfaf155b20 --- /dev/null +++ b/client/src/__mocks__/edges.json @@ -0,0 +1,32462 @@ +[ + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/add-a-text-alternative-to-images-for-visually-impaired-accessibility", + "blockName": "Applied Accessibility" + }, + "id": "587d774c367417b2b2512a9c", + "title": "Add a Text Alternative to Images for Visually Impaired Accessibility" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/add-an-accessible-date-picker", + "blockName": "Applied Accessibility" + }, + "id": "587d778b367417b2b2512aa8", + "title": "Add an Accessible Date Picker" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-carefully-choosing-colors-that-convey-information", + "blockName": "Applied Accessibility" + }, + "id": "587d778f367417b2b2512aad", + "title": "Avoid Colorblindness Issues by Carefully Choosing Colors that Convey Information" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-using-sufficient-contrast", + "blockName": "Applied Accessibility" + }, + "id": "587d778f367417b2b2512aac", + "title": "Avoid Colorblindness Issues by Using Sufficient Contrast" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/give-links-meaning-by-using-descriptive-link-text", + "blockName": "Applied Accessibility" + }, + "id": "587d778f367417b2b2512aae", + "title": "Give Links Meaning by Using Descriptive Link Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/improve-accessibility-of-audio-content-with-the-audio-element", + "blockName": "Applied Accessibility" + }, + "id": "587d7789367417b2b2512aa4", + "title": "Improve Accessibility of Audio Content with the audio Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/improve-chart-accessibility-with-the-figure-element", + "blockName": "Applied Accessibility" + }, + "id": "587d778a367417b2b2512aa5", + "title": "Improve Chart Accessibility with the figure Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/improve-form-field-accessibility-with-the-label-element", + "blockName": "Applied Accessibility" + }, + "id": "587d778a367417b2b2512aa6", + "title": "Improve Form Field Accessibility with the label Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/improve-readability-with-high-contrast-text", + "blockName": "Applied Accessibility" + }, + "id": "587d778e367417b2b2512aab", + "title": "Improve Readability with High Contrast Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/jump-straight-to-the-content-using-the-main-element", + "blockName": "Applied Accessibility" + }, + "id": "587d774e367417b2b2512a9f", + "title": "Jump Straight to the Content Using the main Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/know-when-alt-text-should-be-left-blank", + "blockName": "Applied Accessibility" + }, + "id": "587d774c367417b2b2512a9d", + "title": "Know When Alt Text Should be Left Blank" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/make-elements-only-visible-to-a-screen-reader-by-using-custom-css", + "blockName": "Applied Accessibility" + }, + "id": "587d778d367417b2b2512aaa", + "title": "Make Elements Only Visible to a Screen Reader by Using Custom CSS" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/make-links-navigable-with-html-access-keys", + "blockName": "Applied Accessibility" + }, + "id": "587d7790367417b2b2512aaf", + "title": "Make Links Navigable with HTML Access Keys" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-footer-landmark", + "blockName": "Applied Accessibility" + }, + "id": "587d7788367417b2b2512aa3", + "title": "Make Screen Reader Navigation Easier with the footer Landmark" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-header-landmark", + "blockName": "Applied Accessibility" + }, + "id": "587d7787367417b2b2512aa1", + "title": "Make Screen Reader Navigation Easier with the header Landmark" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-nav-landmark", + "blockName": "Applied Accessibility" + }, + "id": "587d7788367417b2b2512aa2", + "title": "Make Screen Reader Navigation Easier with the nav Landmark" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/standardize-times-with-the-html5-datetime-attribute", + "blockName": "Applied Accessibility" + }, + "id": "587d778c367417b2b2512aa9", + "title": "Standardize Times with the HTML5 datetime Attribute" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/use-headings-to-show-hierarchical-relationships-of-content", + "blockName": "Applied Accessibility" + }, + "id": "587d774d367417b2b2512a9e", + "title": "Use Headings to Show Hierarchical Relationships of Content" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/use-tabindex-to-add-keyboard-focus-to-an-element", + "blockName": "Applied Accessibility" + }, + "id": "587d7790367417b2b2512ab0", + "title": "Use tabindex to Add Keyboard Focus to an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/use-tabindex-to-specify-the-order-of-keyboard-focus-for-several-elements", + "blockName": "Applied Accessibility" + }, + "id": "587d7790367417b2b2512ab1", + "title": "Use tabindex to Specify the Order of Keyboard Focus for Several Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/wrap-content-in-the-article-element", + "blockName": "Applied Accessibility" + }, + "id": "587d774e367417b2b2512aa0", + "title": "Wrap Content in the article Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-accessibility/wrap-radio-buttons-in-a-fieldset-element-for-better-accessibility", + "blockName": "Applied Accessibility" + }, + "id": "587d778b367417b2b2512aa7", + "title": "Wrap Radio Buttons in a fieldset Element for Better Accessibility" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/add-a-box-shadow-to-a-card-like-element", + "blockName": "Applied Visual Design" + }, + "id": "587d781b367417b2b2512abe", + "title": "Add a box-shadow to a Card-like Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/adjust-the-background-color-property-of-text", + "blockName": "Applied Visual Design" + }, + "id": "587d781b367417b2b2512abc", + "title": "Adjust the background-color Property of Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/adjust-the-color-of-various-elements-to-complementary-colors", + "blockName": "Applied Visual Design" + }, + "id": "587d78a4367417b2b2512ad3", + "title": "Adjust the Color of Various Elements to Complementary Colors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/adjust-the-height-of-an-element-using-the-height-property", + "blockName": "Applied Visual Design" + }, + "id": "587d7791367417b2b2512ab5", + "title": "Adjust the Height of an Element Using the height Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/adjust-the-hover-state-of-an-anchor-tag", + "blockName": "Applied Visual Design" + }, + "id": "587d781d367417b2b2512ac8", + "title": "Adjust the Hover State of an Anchor Tag" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/adjust-the-hue-of-a-color", + "blockName": "Applied Visual Design" + }, + "id": "587d78a4367417b2b2512ad4", + "title": "Adjust the Hue of a Color" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/adjust-the-size-of-a-heading-element-versus-a-paragraph-element", + "blockName": "Applied Visual Design" + }, + "id": "587d781b367417b2b2512abd", + "title": "Adjust the Size of a Heading Element Versus a Paragraph Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/adjust-the-tone-of-a-color", + "blockName": "Applied Visual Design" + }, + "id": "587d78a4367417b2b2512ad5", + "title": "Adjust the Tone of a Color" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/adjust-the-width-of-an-element-using-the-width-property", + "blockName": "Applied Visual Design" + }, + "id": "587d7791367417b2b2512ab4", + "title": "Adjust the Width of an Element Using the width Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/animate-elements-at-variable-rates", + "blockName": "Applied Visual Design" + }, + "id": "587d78a8367417b2b2512ae5", + "title": "Animate Elements at Variable Rates" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/animate-elements-continually-using-an-infinite-animation-count", + "blockName": "Applied Visual Design" + }, + "id": "587d78a8367417b2b2512ae3", + "title": "Animate Elements Continually Using an Infinite Animation Count" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/animate-multiple-elements-at-variable-rates", + "blockName": "Applied Visual Design" + }, + "id": "587d78a8367417b2b2512ae6", + "title": "Animate Multiple Elements at Variable Rates" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/center-an-element-horizontally-using-the-margin-property", + "blockName": "Applied Visual Design" + }, + "id": "587d78a3367417b2b2512ad0", + "title": "Center an Element Horizontally Using the margin Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/change-an-elements-relative-position", + "blockName": "Applied Visual Design" + }, + "id": "587d781e367417b2b2512ac9", + "title": "Change an Element's Relative Position" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/change-animation-timing-with-keywords", + "blockName": "Applied Visual Design" + }, + "id": "587d78a8367417b2b2512ae7", + "title": "Change Animation Timing with Keywords" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/change-the-position-of-overlapping-elements-with-the-z-index-property", + "blockName": "Applied Visual Design" + }, + "id": "587d78a3367417b2b2512acf", + "title": "Change the Position of Overlapping Elements with the z-index Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/create-a-gradual-css-linear-gradient", + "blockName": "Applied Visual Design" + }, + "id": "587d78a5367417b2b2512ad6", + "title": "Create a Gradual CSS Linear Gradient" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/create-a-graphic-using-css", + "blockName": "Applied Visual Design" + }, + "id": "587d78a6367417b2b2512add", + "title": "Create a Graphic Using CSS" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/create-a-horizontal-line-using-the-hr-element", + "blockName": "Applied Visual Design" + }, + "id": "587d781b367417b2b2512abb", + "title": "Create a Horizontal Line Using the hr Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/create-a-more-complex-shape-using-css-and-html", + "blockName": "Applied Visual Design" + }, + "id": "587d78a6367417b2b2512ade", + "title": "Create a More Complex Shape Using CSS and HTML" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/create-movement-using-css-animation", + "blockName": "Applied Visual Design" + }, + "id": "587d78a7367417b2b2512ae1", + "title": "Create Movement Using CSS Animation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/create-texture-by-adding-a-subtle-pattern-as-a-background-image", + "blockName": "Applied Visual Design" + }, + "id": "587d78a5367417b2b2512ad8", + "title": "Create Texture by Adding a Subtle Pattern as a Background Image" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/create-visual-balance-using-the-text-align-property", + "blockName": "Applied Visual Design" + }, + "id": "587d7791367417b2b2512ab3", + "title": "Create Visual Balance Using the text-align Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/create-visual-direction-by-fading-an-element-from-left-to-right", + "blockName": "Applied Visual Design" + }, + "id": "587d78a7367417b2b2512ae2", + "title": "Create Visual Direction by Fading an Element from Left to Right" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/decrease-the-opacity-of-an-element", + "blockName": "Applied Visual Design" + }, + "id": "587d781c367417b2b2512abf", + "title": "Decrease the Opacity of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/learn-about-complementary-colors", + "blockName": "Applied Visual Design" + }, + "id": "587d78a3367417b2b2512ad1", + "title": "Learn about Complementary Colors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/learn-about-tertiary-colors", + "blockName": "Applied Visual Design" + }, + "id": "587d78a4367417b2b2512ad2", + "title": "Learn about Tertiary Colors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/learn-how-bezier-curves-work", + "blockName": "Applied Visual Design" + }, + "id": "587d78a9367417b2b2512ae8", + "title": "Learn How Bezier Curves Work" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/learn-how-the-css-keyframes-and-animation-properties-work", + "blockName": "Applied Visual Design" + }, + "id": "587d78a7367417b2b2512adf", + "title": "Learn How the CSS @keyframes and animation Properties Work" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/lock-an-element-to-its-parent-with-absolute-positioning", + "blockName": "Applied Visual Design" + }, + "id": "587d781e367417b2b2512acb", + "title": "Lock an Element to its Parent with Absolute Positioning" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/lock-an-element-to-the-browser-window-with-fixed-positioning", + "blockName": "Applied Visual Design" + }, + "id": "587d781e367417b2b2512acc", + "title": "Lock an Element to the Browser Window with Fixed Positioning" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/make-a-css-heartbeat-using-an-infinite-animation-count", + "blockName": "Applied Visual Design" + }, + "id": "587d78a8367417b2b2512ae4", + "title": "Make a CSS Heartbeat using an Infinite Animation Count" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/make-motion-more-natural-using-a-bezier-curve", + "blockName": "Applied Visual Design" + }, + "id": "587d78a9367417b2b2512aea", + "title": "Make Motion More Natural Using a Bezier Curve" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/modify-fill-mode-of-an-animation", + "blockName": "Applied Visual Design" + }, + "id": "58a7a6ebf9a6318348e2d5aa", + "title": "Modify Fill Mode of an Animation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/move-a-relatively-positioned-element-with-css-offsets", + "blockName": "Applied Visual Design" + }, + "id": "587d781e367417b2b2512aca", + "title": "Move a Relatively Positioned Element with CSS Offsets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/push-elements-left-or-right-with-the-float-property", + "blockName": "Applied Visual Design" + }, + "id": "587d78a3367417b2b2512ace", + "title": "Push Elements Left or Right with the float Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/set-the-font-size-for-multiple-heading-elements", + "blockName": "Applied Visual Design" + }, + "id": "587d781c367417b2b2512ac2", + "title": "Set the font-size for Multiple Heading Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/set-the-font-size-of-paragraph-text", + "blockName": "Applied Visual Design" + }, + "id": "587d781c367417b2b2512ac4", + "title": "Set the font-size of Paragraph Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/set-the-font-weight-for-multiple-heading-elements", + "blockName": "Applied Visual Design" + }, + "id": "587d781c367417b2b2512ac3", + "title": "Set the font-weight for Multiple Heading Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/set-the-line-height-of-paragraphs", + "blockName": "Applied Visual Design" + }, + "id": "587d781d367417b2b2512ac5", + "title": "Set the line-height of Paragraphs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-a-bezier-curve-to-move-a-graphic", + "blockName": "Applied Visual Design" + }, + "id": "587d78a9367417b2b2512ae9", + "title": "Use a Bezier Curve to Move a Graphic" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-a-css-linear-gradient-to-create-a-striped-element", + "blockName": "Applied Visual Design" + }, + "id": "587d78a5367417b2b2512ad7", + "title": "Use a CSS Linear Gradient to Create a Striped Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-css-animation-to-change-the-hover-state-of-a-button", + "blockName": "Applied Visual Design" + }, + "id": "587d78a7367417b2b2512ae0", + "title": "Use CSS Animation to Change the Hover State of a Button" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-css-transform-property-skewx-to-skew-an-element-along-the-x-axis", + "blockName": "Applied Visual Design" + }, + "id": "587d78a6367417b2b2512adb", + "title": "Use the CSS Transform Property skewX to Skew an Element Along the X-Axis" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-css-transform-property-skewy-to-skew-an-element-along-the-y-axis", + "blockName": "Applied Visual Design" + }, + "id": "587d78a6367417b2b2512adc", + "title": "Use the CSS Transform Property skewY to Skew an Element Along the Y-Axis" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-css-transform-scale-property-to-change-the-size-of-an-element", + "blockName": "Applied Visual Design" + }, + "id": "587d78a5367417b2b2512ad9", + "title": "Use the CSS Transform scale Property to Change the Size of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-css-transform-scale-property-to-scale-an-element-on-hover", + "blockName": "Applied Visual Design" + }, + "id": "587d78a5367417b2b2512ada", + "title": "Use the CSS Transform scale Property to Scale an Element on Hover" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-em-tag-to-italicize-text", + "blockName": "Applied Visual Design" + }, + "id": "587d781a367417b2b2512ab9", + "title": "Use the em Tag to Italicize Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-s-tag-to-strikethrough-text", + "blockName": "Applied Visual Design" + }, + "id": "587d781b367417b2b2512aba", + "title": "Use the s Tag to Strikethrough Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-strong-tag-to-make-text-bold", + "blockName": "Applied Visual Design" + }, + "id": "587d781a367417b2b2512ab7", + "title": "Use the strong Tag to Make Text Bold" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-text-transform-property-to-make-text-uppercase", + "blockName": "Applied Visual Design" + }, + "id": "587d781c367417b2b2512ac0", + "title": "Use the text-transform Property to Make Text Uppercase" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/applied-visual-design/use-the-u-tag-to-underline-text", + "blockName": "Applied Visual Design" + }, + "id": "587d781a367417b2b2512ab8", + "title": "Use the u Tag to Underline Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/add-a-negative-margin-to-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08823", + "title": "Add a Negative Margin to an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/add-borders-around-your-elements", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9bedf08813", + "title": "Add Borders Around Your Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/add-different-margins-to-each-side-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1248bd9aedf08824", + "title": "Add Different Margins to Each Side of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/add-different-padding-to-each-side-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08824", + "title": "Add Different Padding to Each Side of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/add-rounded-corners-with-border-radius", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08814", + "title": "Add Rounded Corners with border-radius" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/adjust-the-margin-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08822", + "title": "Adjust the Margin of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/adjust-the-padding-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad88fee1348bd9aedf08825", + "title": "Adjust the Padding of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/attach-a-fallback-value-to-a-css-variable", + "blockName": "Basic CSS" + }, + "id": "5a9d7286424fe3d0e10cad13", + "title": "Attach a Fallback value to a CSS Variable" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/change-a-variable-for-a-specific-area", + "blockName": "Basic CSS" + }, + "id": "5a9d72a1424fe3d0e10cad15", + "title": "Change a variable for a specific area" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/change-the-color-of-text", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08803", + "title": "Change the Color of Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/change-the-font-size-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08806", + "title": "Change the Font Size of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/create-a-custom-css-variable", + "blockName": "Basic CSS" + }, + "id": "5a9d726c424fe3d0e10cad11", + "title": "Create a custom CSS Variable" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/give-a-background-color-to-a-div-element", + "blockName": "Basic CSS" + }, + "id": "bad87fed1348bd9aede07836", + "title": "Give a Background Color to a div Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/import-a-google-font", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08807", + "title": "Import a Google Font" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/improve-compatibility-with-browser-fallbacks", + "blockName": "Basic CSS" + }, + "id": "5b7d72c338cd7e35b63f3e14", + "title": "Improve Compatibility with Browser Fallbacks" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/inherit-css-variables", + "blockName": "Basic CSS" + }, + "id": "5a9d7295424fe3d0e10cad14", + "title": "Inherit CSS Variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/inherit-styles-from-the-body-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08746", + "title": "Inherit Styles from the Body Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/make-circular-images-with-a-border-radius", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08815", + "title": "Make Circular Images with a border-radius" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/override-all-other-styles-by-using-important", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf07756", + "title": "Override All Other Styles by using Important" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/override-class-declarations-by-styling-id-attributes", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd8aedf06756", + "title": "Override Class Declarations by Styling ID Attributes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/override-class-declarations-with-inline-styles", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf06756", + "title": "Override Class Declarations with Inline Styles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/override-styles-in-subsequent-css", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf04756", + "title": "Override Styles in Subsequent CSS" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/prioritize-one-style-over-another", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08756", + "title": "Prioritize One Style Over Another" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/set-the-font-family-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aede08807", + "title": "Set the Font Family of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/set-the-id-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87eee1348bd9aede07836", + "title": "Set the id of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/size-your-images", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9acdf08812", + "title": "Size Your Images" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/specify-how-fonts-should-degrade", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08808", + "title": "Specify How Fonts Should Degrade" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/style-multiple-elements-with-a-css-class", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aefe08806", + "title": "Style Multiple Elements with a CSS Class" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/style-the-html-body-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08736", + "title": "Style the HTML Body Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/understand-absolute-versus-relative-units", + "blockName": "Basic CSS" + }, + "id": "bad82fee1322bd9aedf08721", + "title": "Understand Absolute versus Relative Units" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-a-css-class-to-style-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aecf08806", + "title": "Use a CSS Class to Style an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-a-custom-css-variable", + "blockName": "Basic CSS" + }, + "id": "5a9d727a424fe3d0e10cad12", + "title": "Use a custom CSS Variable" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-a-media-query-to-change-a-variable", + "blockName": "Basic CSS" + }, + "id": "5a9d72ad424fe3d0e10cad16", + "title": "Use a media query to change a variable" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-abbreviated-hex-code", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08719", + "title": "Use Abbreviated Hex Code" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-an-id-attribute-to-style-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87dee1348bd9aede07836", + "title": "Use an id Attribute to Style an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-attribute-selectors-to-style-elements", + "blockName": "Basic CSS" + }, + "id": "58c383d33e2e3259241f3076", + "title": "Use Attribute Selectors to Style Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-margin-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9afdf08726", + "title": "Use Clockwise Notation to Specify the Margin of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-clockwise-notation-to-specify-the-padding-of-an-element", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08826", + "title": "Use Clockwise Notation to Specify the Padding of an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-css-selectors-to-style-elements", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08805", + "title": "Use CSS Selectors to Style Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-css-variables-to-change-several-elements-at-once", + "blockName": "Basic CSS" + }, + "id": "5a9d725e424fe3d0e10cad10", + "title": "Use CSS Variables to change several elements at once" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-hex-code-for-specific-colors", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08726", + "title": "Use Hex Code for Specific Colors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-hex-code-to-mix-colors", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aedf08721", + "title": "Use Hex Code to Mix Colors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-rgb-to-mix-colors", + "blockName": "Basic CSS" + }, + "id": "bad82fee1348bd9aedf08721", + "title": "Use RGB to Mix Colors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-css/use-rgb-values-to-color-elements", + "blockName": "Basic CSS" + }, + "id": "bad87fee1348bd9aede08718", + "title": "Use RGB values to Color Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/add-a-submit-button-to-a-form", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedd08830", + "title": "Add a Submit Button to a Form" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/add-images-to-your-website", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08812", + "title": "Add Images to Your Website" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/add-placeholder-text-to-a-text-field", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08830", + "title": "Add Placeholder Text to a Text Field" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/check-radio-buttons-and-checkboxes-by-default", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedd08835", + "title": "Check Radio Buttons and Checkboxes by Default" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/comment-out-html", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08804", + "title": "Comment out HTML" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/create-a-bulleted-unordered-list", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08827", + "title": "Create a Bulleted Unordered List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/create-a-form-element", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aede08830", + "title": "Create a Form Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/create-a-set-of-checkboxes", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08835", + "title": "Create a Set of Checkboxes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/create-a-set-of-radio-buttons", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08834", + "title": "Create a Set of Radio Buttons" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/create-a-text-field", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08829", + "title": "Create a Text Field" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/create-an-ordered-list", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08828", + "title": "Create an Ordered List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/declare-the-doctype-of-an-html-document", + "blockName": "Basic HTML and HTML5" + }, + "id": "587d78aa367417b2b2512aed", + "title": "Declare the Doctype of an HTML Document" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/define-the-head-and-body-of-an-html-document", + "blockName": "Basic HTML and HTML5" + }, + "id": "587d78aa367417b2b2512aec", + "title": "Define the Head and Body of an HTML Document" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/delete-html-elements", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fed1348bd9aedf08833", + "title": "Delete HTML Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/fill-in-the-blank-with-placeholder-text", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08833", + "title": "Fill in the Blank with Placeholder Text" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/headline-with-the-h2-element", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf0887a", + "title": "Headline with the h2 Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/inform-with-the-paragraph-element", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08801", + "title": "Inform with the Paragraph Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/introduction-to-html5-elements", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aecf08801", + "title": "Introduction to HTML5 Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/link-to-external-pages-with-anchor-elements", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08816", + "title": "Link to External Pages with Anchor Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/link-to-internal-sections-of-a-page-with-anchor-elements", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad88fee1348bd9aedf08816", + "title": "Link to Internal Sections of a Page with Anchor Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/make-dead-links-using-the-hash-symbol", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08817", + "title": "Make Dead Links Using the Hash Symbol" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/nest-an-anchor-element-within-a-paragraph", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aede08817", + "title": "Nest an Anchor Element within a Paragraph" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/nest-many-elements-within-a-single-div-element", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aede08835", + "title": "Nest Many Elements within a Single div Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/say-hello-to-html-elements", + "blockName": "Basic HTML and HTML5" + }, + "id": "bd7123c8c441eddfaeb5bdef", + "title": "Say Hello to HTML Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/turn-an-image-into-a-link", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08820", + "title": "Turn an Image into a Link" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/uncomment-html", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedf08802", + "title": "Uncomment HTML" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/use-html5-to-require-a-field", + "blockName": "Basic HTML and HTML5" + }, + "id": "bad87fee1348bd9aedc08830", + "title": "Use HTML5 to Require a Field" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/basic-html-and-html5/use-the-value-attribute-with-radio-buttons-and-checkboxes", + "blockName": "Basic HTML and HTML5" + }, + "id": "5c6c06847491271903d37cfd", + "title": "Use the value attribute with Radio Buttons and Checkboxes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/add-flex-superpowers-to-the-tweet-embed", + "blockName": "CSS Flexbox" + }, + "id": "587d78ab367417b2b2512af1", + "title": "Add Flex Superpowers to the Tweet Embed" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/align-elements-using-the-align-items-property", + "blockName": "CSS Flexbox" + }, + "id": "587d78ad367417b2b2512af8", + "title": "Align Elements Using the align-items Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/align-elements-using-the-justify-content-property", + "blockName": "CSS Flexbox" + }, + "id": "587d78ac367417b2b2512af6", + "title": "Align Elements Using the justify-content Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/apply-the-flex-direction-property-to-create-a-column-in-the-tweet-embed", + "blockName": "CSS Flexbox" + }, + "id": "587d78ac367417b2b2512af5", + "title": "Apply the flex-direction Property to Create a Column in the Tweet Embed" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/apply-the-flex-direction-property-to-create-rows-in-the-tweet-embed", + "blockName": "CSS Flexbox" + }, + "id": "587d78ab367417b2b2512af3", + "title": "Apply the flex-direction Property to Create Rows in the Tweet Embed" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-display-flex-to-position-two-boxes", + "blockName": "CSS Flexbox" + }, + "id": "587d78ab367417b2b2512af0", + "title": "Use display: flex to Position Two Boxes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-align-items-property-in-the-tweet-embed", + "blockName": "CSS Flexbox" + }, + "id": "587d78ad367417b2b2512af9", + "title": "Use the align-items Property in the Tweet Embed" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-align-self-property", + "blockName": "CSS Flexbox" + }, + "id": "587d78af367417b2b2512b00", + "title": "Use the align-self Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-flex-basis-property-to-set-the-initial-size-of-an-item", + "blockName": "CSS Flexbox" + }, + "id": "587d78ae367417b2b2512afd", + "title": "Use the flex-basis Property to Set the Initial Size of an Item" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-flex-direction-property-to-make-a-column", + "blockName": "CSS Flexbox" + }, + "id": "587d78ac367417b2b2512af4", + "title": "Use the flex-direction Property to Make a Column" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-flex-direction-property-to-make-a-row", + "blockName": "CSS Flexbox" + }, + "id": "587d78ab367417b2b2512af2", + "title": "Use the flex-direction Property to Make a Row" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-flex-grow-property-to-expand-items", + "blockName": "CSS Flexbox" + }, + "id": "587d78ae367417b2b2512afc", + "title": "Use the flex-grow Property to Expand Items" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-flex-shorthand-property", + "blockName": "CSS Flexbox" + }, + "id": "587d78ae367417b2b2512afe", + "title": "Use the flex Shorthand Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-flex-shrink-property-to-shrink-items", + "blockName": "CSS Flexbox" + }, + "id": "587d78ad367417b2b2512afb", + "title": "Use the flex-shrink Property to Shrink Items" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-flex-wrap-property-to-wrap-a-row-or-column", + "blockName": "CSS Flexbox" + }, + "id": "587d78ad367417b2b2512afa", + "title": "Use the flex-wrap Property to Wrap a Row or Column" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-justify-content-property-in-the-tweet-embed", + "blockName": "CSS Flexbox" + }, + "id": "587d78ac367417b2b2512af7", + "title": "Use the justify-content Property in the Tweet Embed" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-flexbox/use-the-order-property-to-rearrange-items", + "blockName": "CSS Flexbox" + }, + "id": "587d78ae367417b2b2512aff", + "title": "Use the order Property to Rearrange Items" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/add-columns-with-grid-template-columns", + "blockName": "CSS Grid" + }, + "id": "5a9036d038fddaf9a66b5d32", + "title": "Add Columns with grid-template-columns" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/add-gaps-faster-with-grid-gap", + "blockName": "CSS Grid" + }, + "id": "5a9036ee38fddaf9a66b5d37", + "title": "Add Gaps Faster with grid-gap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/add-rows-with-grid-template-rows", + "blockName": "CSS Grid" + }, + "id": "5a9036e138fddaf9a66b5d33", + "title": "Add Rows with grid-template-rows" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/align-all-items-horizontally-using-justify-items", + "blockName": "CSS Grid" + }, + "id": "5a90376038fddaf9a66b5d3c", + "title": "Align All Items Horizontally using justify-items" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/align-all-items-vertically-using-align-items", + "blockName": "CSS Grid" + }, + "id": "5a94fdf869fb03452672e45b", + "title": "Align All Items Vertically using align-items" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/align-an-item-horizontally-using-justify-self", + "blockName": "CSS Grid" + }, + "id": "5a90374338fddaf9a66b5d3a", + "title": "Align an Item Horizontally using justify-self" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/align-an-item-vertically-using-align-self", + "blockName": "CSS Grid" + }, + "id": "5a90375238fddaf9a66b5d3b", + "title": "Align an Item Vertically using align-self" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/create-a-column-gap-using-grid-column-gap", + "blockName": "CSS Grid" + }, + "id": "5a9036ee38fddaf9a66b5d35", + "title": "Create a Column Gap Using grid-column-gap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/create-a-row-gap-using-grid-row-gap", + "blockName": "CSS Grid" + }, + "id": "5a9036ee38fddaf9a66b5d36", + "title": "Create a Row Gap using grid-row-gap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/create-flexible-layouts-using-auto-fill", + "blockName": "CSS Grid" + }, + "id": "5a94fe5469fb03452672e461", + "title": "Create Flexible Layouts Using auto-fill" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/create-flexible-layouts-using-auto-fit", + "blockName": "CSS Grid" + }, + "id": "5a94fe6269fb03452672e462", + "title": "Create Flexible Layouts Using auto-fit" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/create-grids-within-grids", + "blockName": "CSS Grid" + }, + "id": "5a94fe8569fb03452672e464", + "title": "Create Grids within Grids" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/create-your-first-css-grid", + "blockName": "CSS Grid" + }, + "id": "5a858944d96184f06fd60d61", + "title": "Create Your First CSS Grid" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/divide-the-grid-into-an-area-template", + "blockName": "CSS Grid" + }, + "id": "5a94fe0569fb03452672e45c", + "title": "Divide the Grid Into an Area Template" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/limit-item-size-using-the-minmax-function", + "blockName": "CSS Grid" + }, + "id": "5a94fe4469fb03452672e460", + "title": "Limit Item Size Using the minmax Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/place-items-in-grid-areas-using-the-grid-area-property", + "blockName": "CSS Grid" + }, + "id": "5a94fe1369fb03452672e45d", + "title": "Place Items in Grid Areas Using the grid-area Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/reduce-repetition-using-the-repeat-function", + "blockName": "CSS Grid" + }, + "id": "5a94fe3669fb03452672e45f", + "title": "Reduce Repetition Using the repeat Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/use-css-grid-units-to-change-the-size-of-columns-and-rows", + "blockName": "CSS Grid" + }, + "id": "5a9036ee38fddaf9a66b5d34", + "title": "Use CSS Grid units to Change the Size of Columns and Rows" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/use-grid-area-without-creating-an-areas-template", + "blockName": "CSS Grid" + }, + "id": "5a94fe2669fb03452672e45e", + "title": "Use grid-area Without Creating an Areas Template" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/use-grid-column-to-control-spacing", + "blockName": "CSS Grid" + }, + "id": "5a90372638fddaf9a66b5d38", + "title": "Use grid-column to Control Spacing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/use-grid-row-to-control-spacing", + "blockName": "CSS Grid" + }, + "id": "5a90373638fddaf9a66b5d39", + "title": "Use grid-row to Control Spacing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/css-grid/use-media-queries-to-create-responsive-layouts", + "blockName": "CSS Grid" + }, + "id": "5a94fe7769fb03452672e463", + "title": "Use Media Queries to Create Responsive Layouts" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-principles/create-a-media-query", + "blockName": "Responsive Web Design Principles" + }, + "id": "587d78b0367417b2b2512b08", + "title": "Create a Media Query" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-principles/make-an-image-responsive", + "blockName": "Responsive Web Design Principles" + }, + "id": "587d78b1367417b2b2512b09", + "title": "Make an Image Responsive" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-principles/make-typography-responsive", + "blockName": "Responsive Web Design Principles" + }, + "id": "587d78b1367417b2b2512b0c", + "title": "Make Typography Responsive" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-principles/use-a-retina-image-for-higher-resolution-displays", + "blockName": "Responsive Web Design Principles" + }, + "id": "587d78b1367417b2b2512b0a", + "title": "Use a Retina Image for Higher Resolution Displays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage", + "blockName": "Responsive Web Design Projects" + }, + "id": "bd7158d8c242eddfaeb5bd13", + "title": "Build a Personal Portfolio Webpage" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-projects/build-a-product-landing-page", + "blockName": "Responsive Web Design Projects" + }, + "id": "587d78af367417b2b2512b04", + "title": "Build a Product Landing Page" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-projects/build-a-survey-form", + "blockName": "Responsive Web Design Projects" + }, + "id": "587d78af367417b2b2512b03", + "title": "Build a Survey Form" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-projects/build-a-technical-documentation-page", + "blockName": "Responsive Web Design Projects" + }, + "id": "587d78b0367417b2b2512b05", + "title": "Build a Technical Documentation Page" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/responsive-web-design/responsive-web-design-projects/build-a-tribute-page", + "blockName": "Responsive Web Design Projects" + }, + "id": "bd7158d8c442eddfaeb5bd18", + "title": "Build a Tribute Page" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/boo-who", + "blockName": "Basic Algorithm Scripting" + }, + "id": "a77dbc43c33f39daa4429b4f", + "title": "Boo who" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/chunky-monkey", + "blockName": "Basic Algorithm Scripting" + }, + "id": "a9bd25c716030ec90084d8a1", + "title": "Chunky Monkey" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/confirm-the-ending", + "blockName": "Basic Algorithm Scripting" + }, + "id": "acda2fb1324d9b0fa741e6b5", + "title": "Confirm the Ending" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/convert-celsius-to-fahrenheit", + "blockName": "Basic Algorithm Scripting" + }, + "id": "56533eb9ac21ba0edf2244b3", + "title": "Convert Celsius to Fahrenheit" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/factorialize-a-number", + "blockName": "Basic Algorithm Scripting" + }, + "id": "a302f7aae1aa3152a5b413bc", + "title": "Factorialize a Number" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/falsy-bouncer", + "blockName": "Basic Algorithm Scripting" + }, + "id": "adf08ec01beb4f99fc7a68f2", + "title": "Falsy Bouncer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/find-the-longest-word-in-a-string", + "blockName": "Basic Algorithm Scripting" + }, + "id": "a26cbbe9ad8655a977e1ceb5", + "title": "Find the Longest Word in a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/finders-keepers", + "blockName": "Basic Algorithm Scripting" + }, + "id": "a6e40f1041b06c996f7b2406", + "title": "Finders Keepers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/mutations", + "blockName": "Basic Algorithm Scripting" + }, + "id": "af2170cad53daa0770fabdea", + "title": "Mutations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/repeat-a-string-repeat-a-string", + "blockName": "Basic Algorithm Scripting" + }, + "id": "afcc8d540bea9ea2669306b6", + "title": "Repeat a String Repeat a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/return-largest-numbers-in-arrays", + "blockName": "Basic Algorithm Scripting" + }, + "id": "a789b3483989747d63b0e427", + "title": "Return Largest Numbers in Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/reverse-a-string", + "blockName": "Basic Algorithm Scripting" + }, + "id": "a202eed8fc186c8434cb6d61", + "title": "Reverse a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/slice-and-splice", + "blockName": "Basic Algorithm Scripting" + }, + "id": "579e2a2c335b9d72dd32e05c", + "title": "Slice and Splice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/title-case-a-sentence", + "blockName": "Basic Algorithm Scripting" + }, + "id": "ab6137d4e35944e21037b769", + "title": "Title Case a Sentence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/truncate-a-string", + "blockName": "Basic Algorithm Scripting" + }, + "id": "ac6993d51946422351508a41", + "title": "Truncate a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-algorithm-scripting/where-do-i-belong", + "blockName": "Basic Algorithm Scripting" + }, + "id": "a24c1a4622e3c05097f71d67", + "title": "Where do I Belong" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/access-an-arrays-contents-using-bracket-notation", + "blockName": "Basic Data Structures" + }, + "id": "5a661e0f1068aca922b3ef17", + "title": "Access an Array's Contents Using Bracket Notation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/access-property-names-with-bracket-notation", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7c367417b2b2512b1a", + "title": "Access Property Names with Bracket Notation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/add-items-to-an-array-with-push-and-unshift", + "blockName": "Basic Data Structures" + }, + "id": "587d78b2367417b2b2512b0e", + "title": "Add Items to an Array with push() and unshift()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/add-items-using-splice", + "blockName": "Basic Data Structures" + }, + "id": "587d78b3367417b2b2512b11", + "title": "Add Items Using splice()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/add-key-value-pairs-to-javascript-objects", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7c367417b2b2512b18", + "title": "Add Key-Value Pairs to JavaScript Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/check-for-the-presence-of-an-element-with-indexof", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7b367417b2b2512b14", + "title": "Check For The Presence of an Element With indexOf()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/check-if-an-object-has-a-property", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7d367417b2b2512b1c", + "title": "Check if an Object has a Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/combine-arrays-with-the-spread-operator", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7b367417b2b2512b17", + "title": "Combine Arrays with the Spread Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/copy-an-array-with-the-spread-operator", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7b367417b2b2512b13", + "title": "Copy an Array with the Spread Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/copy-array-items-using-slice", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7a367417b2b2512b12", + "title": "Copy Array Items Using slice()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/create-complex-multi-dimensional-arrays", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7b367417b2b2512b16", + "title": "Create complex multi-dimensional arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/generate-an-array-of-all-object-keys-with-object-keys", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7d367417b2b2512b1e", + "title": "Generate an Array of All Object Keys with Object.keys()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/iterate-through-all-an-arrays-items-using-for-loops", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7b367417b2b2512b15", + "title": "Iterate Through All an Array's Items Using For Loops" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/iterate-through-the-keys-of-an-object-with-a-for---in-statement", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7d367417b2b2512b1d", + "title": "Iterate Through the Keys of an Object with a for...in Statement" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/modify-an-array-stored-in-an-object", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7d367417b2b2512b1f", + "title": "Modify an Array Stored in an Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/modify-an-object-nested-within-an-object", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7c367417b2b2512b19", + "title": "Modify an Object Nested Within an Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/remove-items-from-an-array-with-pop-and-shift", + "blockName": "Basic Data Structures" + }, + "id": "587d78b2367417b2b2512b0f", + "title": "Remove Items from an Array with pop() and shift()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice", + "blockName": "Basic Data Structures" + }, + "id": "587d78b2367417b2b2512b10", + "title": "Remove Items Using splice()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/use-an-array-to-store-a-collection-of-data", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7e367417b2b2512b20", + "title": "Use an Array to Store a Collection of Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-data-structures/use-the-delete-keyword-to-remove-object-properties", + "blockName": "Basic Data Structures" + }, + "id": "587d7b7c367417b2b2512b1b", + "title": "Use the delete Keyword to Remove Object Properties" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/access-array-data-with-indexes", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392ca", + "title": "Access Array Data with Indexes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes", + "blockName": "Basic JavaScript" + }, + "id": "56592a60ddddeae28f7aa8e1", + "title": "Access Multi-Dimensional Arrays With Indexes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244cd", + "title": "Accessing Nested Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244cc", + "title": "Accessing Nested Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-bracket-notation", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244c8", + "title": "Accessing Object Properties with Bracket Notation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-dot-notation", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244c7", + "title": "Accessing Object Properties with Dot Notation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-variables", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244c9", + "title": "Accessing Object Properties with Variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/add-new-properties-to-a-javascript-object", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392d2", + "title": "Add New Properties to a JavaScript Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/add-two-numbers-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c11feddfaeb3bdef", + "title": "Add Two Numbers with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/adding-a-default-option-in-switch-statements", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244de", + "title": "Adding a Default Option in Switch Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/appending-variables-to-strings", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244ed", + "title": "Appending Variables to Strings" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/assigning-the-value-of-one-variable-to-another", + "blockName": "Basic JavaScript" + }, + "id": "5ee127a03c3b35dd45426493", + "title": "Assigning the Value of One Variable to Another" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/assignment-with-a-returned-value", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244c3", + "title": "Assignment with a Returned Value" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/build-javascript-objects", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392d0", + "title": "Build JavaScript Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/chaining-if-else-statements", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244dc", + "title": "Chaining If Else Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c441eddfaeb4bdef", + "title": "Comment Your JavaScript Code" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-equality-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d0", + "title": "Comparison with the Equality Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d4", + "title": "Comparison with the Greater Than Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-or-equal-to-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d5", + "title": "Comparison with the Greater Than Or Equal To Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-inequality-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d2", + "title": "Comparison with the Inequality Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d6", + "title": "Comparison with the Less Than Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-or-equal-to-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d7", + "title": "Comparison with the Less Than Or Equal To Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-strict-equality-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d1", + "title": "Comparison with the Strict Equality Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-strict-inequality-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d3", + "title": "Comparison with the Strict Inequality Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d8", + "title": "Comparisons with the Logical And Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-or-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244d9", + "title": "Comparisons with the Logical Or Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-addition", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244af", + "title": "Compound Assignment With Augmented Addition" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-division", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b2", + "title": "Compound Assignment With Augmented Division" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-multiplication", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b1", + "title": "Compound Assignment With Augmented Multiplication" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-subtraction", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b0", + "title": "Compound Assignment With Augmented Subtraction" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-plus-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b7", + "title": "Concatenating Strings with Plus Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-the-plus-equals-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b8", + "title": "Concatenating Strings with the Plus Equals Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/constructing-strings-with-variables", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b9", + "title": "Constructing Strings with Variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/count-backwards-with-a-for-loop", + "blockName": "Basic JavaScript" + }, + "id": "56105e7b514f539506016a5e", + "title": "Count Backwards With a For Loop" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/counting-cards", + "blockName": "Basic JavaScript" + }, + "id": "565bbe00e9cc8ac0725390f4", + "title": "Counting Cards" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/create-decimal-numbers-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "cf1391c1c11feddfaeb4bdef", + "title": "Create Decimal Numbers with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/declare-a-read-only-variable-with-the-const-keyword", + "blockName": "Basic JavaScript" + }, + "id": "587d7b87367417b2b2512b41", + "title": "Declare a Read-Only Variable with the const Keyword" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/declare-javascript-variables", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c443eddfaeb5bdef", + "title": "Declare JavaScript Variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/declare-string-variables", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c444eddfaeb5bdef", + "title": "Declare String Variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/decrement-a-number-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244ad", + "title": "Decrement a Number with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/delete-properties-from-a-javascript-object", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392d3", + "title": "Delete Properties from a JavaScript Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/divide-one-decimal-by-another-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "bd7993c9ca9feddfaeb7bdef", + "title": "Divide One Decimal by Another with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/divide-one-number-by-another-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c11feddfaeb6bdef", + "title": "Divide One Number by Another with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b6", + "title": "Escape Sequences in Strings" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/escaping-literal-quotes-in-strings", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b5", + "title": "Escaping Literal Quotes in Strings" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/explore-differences-between-the-var-and-let-keywords", + "blockName": "Basic JavaScript" + }, + "id": "587d7b87367417b2b2512b3f", + "title": "Explore Differences Between the var and let Keywords" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/find-the-length-of-a-string", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c448eddfaeb5bdef", + "title": "Find the Length of a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/finding-a-remainder-in-javascript", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244ae", + "title": "Finding a Remainder in JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/generate-random-fractions-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c11feddfaeb9bdef", + "title": "Generate Random Fractions with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c12feddfaeb1bdef", + "title": "Generate Random Whole Numbers with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/generate-random-whole-numbers-within-a-range", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c12feddfaeb2bdef", + "title": "Generate Random Whole Numbers within a Range" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/global-scope-and-functions", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244be", + "title": "Global Scope and Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/global-vs--local-scope-in-functions", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244c0", + "title": "Global vs. Local Scope in Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/golf-code", + "blockName": "Basic JavaScript" + }, + "id": "5664820f61c48e80c9fa476c", + "title": "Golf Code" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/increment-a-number-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244ac", + "title": "Increment a Number with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244a9", + "title": "Initializing Variables with the Assignment Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/introducing-else-if-statements", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244db", + "title": "Introducing Else If Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/introducing-else-statements", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244da", + "title": "Introducing Else Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/iterate-odd-numbers-with-a-for-loop", + "blockName": "Basic JavaScript" + }, + "id": "56104e9e514f539506016a5c", + "title": "Iterate Odd Numbers With a For Loop" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop", + "blockName": "Basic JavaScript" + }, + "id": "5675e877dbd60be8ad28edc6", + "title": "Iterate Through an Array with a For Loop" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/iterate-with-javascript-do---while-loops", + "blockName": "Basic JavaScript" + }, + "id": "5a2efd662fb457916e1fe604", + "title": "Iterate with JavaScript Do...While Loops" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/iterate-with-javascript-for-loops", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c11feddfaeb5bdef", + "title": "Iterate with JavaScript For Loops" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/iterate-with-javascript-while-loops", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c11feddfaeb1bdef", + "title": "Iterate with JavaScript While Loops" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244bf", + "title": "Local Scope and Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/logical-order-in-if-else-statements", + "blockName": "Basic JavaScript" + }, + "id": "5690307fddb111c6084545d7", + "title": "Logical Order in If Else Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-pop", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392cc", + "title": "Manipulate Arrays With pop()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-push", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392cb", + "title": "Manipulate Arrays With push()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-shift", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392cd", + "title": "Manipulate Arrays With shift()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-unshift", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392ce", + "title": "Manipulate Arrays With unshift()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/manipulating-complex-objects", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244cb", + "title": "Manipulating Complex Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/modify-array-data-with-indexes", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c11feddfaeb8bdef", + "title": "Modify Array Data With Indexes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/multiple-identical-options-in-switch-statements", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244df", + "title": "Multiple Identical Options in Switch Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/multiply-two-decimals-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "bd7993c9c69feddfaeb7bdef", + "title": "Multiply Two Decimals with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/multiply-two-numbers-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "cf1231c1c11feddfaeb5bdef", + "title": "Multiply Two Numbers with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/nest-one-array-within-another-array", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c11feddfaeb7bdef", + "title": "Nest one Array within Another Array" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/nesting-for-loops", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244e1", + "title": "Nesting For Loops" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/passing-values-to-functions-with-arguments", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244bd", + "title": "Passing Values to Functions with Arguments" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/practice-comparing-different-values", + "blockName": "Basic JavaScript" + }, + "id": "599a789b454f2bbd91a3ff4d", + "title": "Practice comparing different values" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/profile-lookup", + "blockName": "Basic JavaScript" + }, + "id": "5688e62ea601b2482ff8422b", + "title": "Profile Lookup" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244b4", + "title": "Quoting Strings with Single Quotes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/record-collection", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244cf", + "title": "Record Collection" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/replace-loops-using-recursion", + "blockName": "Basic JavaScript" + }, + "id": "5cfa3679138e7d9595b9d9d4", + "title": "Replace Loops using Recursion" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/replacing-if-else-chains-with-switch", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244e0", + "title": "Replacing If Else Chains with Switch" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/return-a-value-from-a-function-with-return", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244c2", + "title": "Return a Value from a Function with Return" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/return-early-pattern-for-functions", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244c4", + "title": "Return Early Pattern for Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/returning-boolean-values-from-functions", + "blockName": "Basic JavaScript" + }, + "id": "5679ceb97cbaa8c51670a16b", + "title": "Returning Boolean Values from Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244dd", + "title": "Selecting from Many Options with Switch Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/shopping-list", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244bc", + "title": "Shopping List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/stand-in-line", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244c6", + "title": "Stand in Line" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/store-multiple-values-in-one-variable-using-javascript-arrays", + "blockName": "Basic JavaScript" + }, + "id": "bd7993c9c69feddfaeb8bdef", + "title": "Store Multiple Values in one Variable using JavaScript Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/storing-values-with-the-assignment-operator", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244a8", + "title": "Storing Values with the Assignment Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c11feddfaeb4bdef", + "title": "Subtract One Number from Another with JavaScript" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/testing-objects-for-properties", + "blockName": "Basic JavaScript" + }, + "id": "567af2437cbaa8c51670a16c", + "title": "Testing Objects for Properties" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/understand-string-immutability", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244ba", + "title": "Understand String Immutability" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/understanding-boolean-values", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c441eddfaeb5bdef", + "title": "Understanding Boolean Values" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/understanding-case-sensitivity-in-variables", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244ab", + "title": "Understanding Case Sensitivity in Variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function", + "blockName": "Basic JavaScript" + }, + "id": "598e8944f009e646fc236146", + "title": "Understanding Undefined Value returned from a Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/understanding-uninitialized-variables", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244aa", + "title": "Understanding Uninitialized Variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/updating-object-properties", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392d1", + "title": "Updating Object Properties" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-first-character-in-a-string", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c549eddfaeb5bdef", + "title": "Use Bracket Notation to Find the First Character in a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-last-character-in-a-string", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c451eddfaeb5bdef", + "title": "Use Bracket Notation to Find the Last Character in a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-character-in-a-string", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c450eddfaeb5bdef", + "title": "Use Bracket Notation to Find the Nth Character in a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-to-last-character-in-a-string", + "blockName": "Basic JavaScript" + }, + "id": "bd7123c9c452eddfaeb5bdef", + "title": "Use Bracket Notation to Find the Nth-to-Last Character in a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-conditional-logic-with-if-statements", + "blockName": "Basic JavaScript" + }, + "id": "cf1111c1c12feddfaeb3bdef", + "title": "Use Conditional Logic with If Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-multiple-conditional-ternary-operators", + "blockName": "Basic JavaScript" + }, + "id": "587d7b7e367417b2b2512b21", + "title": "Use Multiple Conditional (Ternary) Operators" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown", + "blockName": "Basic JavaScript" + }, + "id": "5cd9a70215d3c4e65518328f", + "title": "Use Recursion to Create a Countdown" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers", + "blockName": "Basic JavaScript" + }, + "id": "5cc0bd7a49b71cb96132e54c", + "title": "Use Recursion to Create a Range of Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-the-conditional-ternary-operator", + "blockName": "Basic JavaScript" + }, + "id": "587d7b7e367417b2b2512b24", + "title": "Use the Conditional (Ternary) Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-the-parseint-function-with-a-radix", + "blockName": "Basic JavaScript" + }, + "id": "587d7b7e367417b2b2512b22", + "title": "Use the parseInt Function with a Radix" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/use-the-parseint-function", + "blockName": "Basic JavaScript" + }, + "id": "587d7b7e367417b2b2512b23", + "title": "Use the parseInt Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/using-objects-for-lookups", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244ca", + "title": "Using Objects for Lookups" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/word-blanks", + "blockName": "Basic JavaScript" + }, + "id": "56533eb9ac21ba0edf2244bb", + "title": "Word Blanks" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/basic-javascript/write-reusable-javascript-with-functions", + "blockName": "Basic JavaScript" + }, + "id": "56bbb991ad1ed5201cd392cf", + "title": "Write Reusable JavaScript with Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/catch-arguments-passed-in-the-wrong-order-when-calling-a-function", + "blockName": "Debugging" + }, + "id": "587d7b85367417b2b2512b3a", + "title": "Catch Arguments Passed in the Wrong Order When Calling a Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/catch-missing-open-and-closing-parenthesis-after-a-function-call", + "blockName": "Debugging" + }, + "id": "587d7b85367417b2b2512b39", + "title": "Catch Missing Open and Closing Parenthesis After a Function Call" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/catch-misspelled-variable-and-function-names", + "blockName": "Debugging" + }, + "id": "587d7b84367417b2b2512b35", + "title": "Catch Misspelled Variable and Function Names" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/catch-mixed-usage-of-single-and-double-quotes", + "blockName": "Debugging" + }, + "id": "587d7b84367417b2b2512b37", + "title": "Catch Mixed Usage of Single and Double Quotes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/catch-off-by-one-errors-when-using-indexing", + "blockName": "Debugging" + }, + "id": "587d7b86367417b2b2512b3b", + "title": "Catch Off By One Errors When Using Indexing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/catch-unclosed-parentheses-brackets-braces-and-quotes", + "blockName": "Debugging" + }, + "id": "587d7b84367417b2b2512b36", + "title": "Catch Unclosed Parentheses, Brackets, Braces and Quotes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/catch-use-of-assignment-operator-instead-of-equality-operator", + "blockName": "Debugging" + }, + "id": "587d7b85367417b2b2512b38", + "title": "Catch Use of Assignment Operator Instead of Equality Operator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/prevent-infinite-loops-with-a-valid-terminal-condition", + "blockName": "Debugging" + }, + "id": "587d7b86367417b2b2512b3d", + "title": "Prevent Infinite Loops with a Valid Terminal Condition" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/understanding-the-differences-between-the-freecodecamp-and-browser-console", + "blockName": "Debugging" + }, + "id": "587d7b83367417b2b2512b37", + "title": "Understanding the Differences between the freeCodeCamp and Browser Console" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/use-caution-when-reinitializing-variables-inside-a-loop", + "blockName": "Debugging" + }, + "id": "587d7b86367417b2b2512b3c", + "title": "Use Caution When Reinitializing Variables Inside a Loop" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/use-the-javascript-console-to-check-the-value-of-a-variable", + "blockName": "Debugging" + }, + "id": "587d7b83367417b2b2512b33", + "title": "Use the JavaScript Console to Check the Value of a Variable" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/debugging/use-typeof-to-check-the-type-of-a-variable", + "blockName": "Debugging" + }, + "id": "587d7b84367417b2b2512b34", + "title": "Use typeof to Check the Type of a Variable" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords", + "blockName": "ES6" + }, + "id": "587d7b87367417b2b2512b40", + "title": "Compare Scopes of the var and let Keywords" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject", + "blockName": "ES6" + }, + "id": "5cdafbc32913098997531680", + "title": "Complete a Promise with resolve and reject" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/create-a-javascript-promise", + "blockName": "ES6" + }, + "id": "5cdafbb0291309899753167f", + "title": "Create a JavaScript Promise" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/create-a-module-script", + "blockName": "ES6" + }, + "id": "5cddbfd622f1a59093ec611d", + "title": "Create a Module Script" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default", + "blockName": "ES6" + }, + "id": "587d7b8c367417b2b2512b58", + "title": "Create an Export Fallback with export default" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/create-strings-using-template-literals", + "blockName": "ES6" + }, + "id": "587d7b8a367417b2b2512b4e", + "title": "Create Strings using Template Literals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then", + "blockName": "ES6" + }, + "id": "5cdafbd72913098997531681", + "title": "Handle a Fulfilled Promise with then" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch", + "blockName": "ES6" + }, + "id": "5cdafbe72913098997531682", + "title": "Handle a Rejected Promise with catch" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/import-a-default-export", + "blockName": "ES6" + }, + "id": "587d7b8d367417b2b2512b59", + "title": "Import a Default Export" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const", + "blockName": "ES6" + }, + "id": "587d7b87367417b2b2512b42", + "title": "Mutate an Array Declared with const" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/prevent-object-mutation", + "blockName": "ES6" + }, + "id": "598f48a36c8c40764b4e52b3", + "title": "Prevent Object Mutation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/reuse-javascript-code-using-import", + "blockName": "ES6" + }, + "id": "587d7b8c367417b2b2512b55", + "title": "Reuse JavaScript Code Using import" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/set-default-parameters-for-your-functions", + "blockName": "ES6" + }, + "id": "587d7b88367417b2b2512b46", + "title": "Set Default Parameters for Your Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use--to-import-everything-from-a-file", + "blockName": "ES6" + }, + "id": "587d7b8c367417b2b2512b57", + "title": "Use * to Import Everything from a File" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-arrow-functions-to-write-concise-anonymous-functions", + "blockName": "ES6" + }, + "id": "587d7b87367417b2b2512b43", + "title": "Use Arrow Functions to Write Concise Anonymous Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-class-syntax-to-define-a-constructor-function", + "blockName": "ES6" + }, + "id": "587d7b8b367417b2b2512b53", + "title": "Use class Syntax to Define a Constructor Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-assign-variables-from-arrays", + "blockName": "ES6" + }, + "id": "587d7b89367417b2b2512b4b", + "title": "Use Destructuring Assignment to Assign Variables from Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-assign-variables-from-nested-objects", + "blockName": "ES6" + }, + "id": "587d7b89367417b2b2512b4a", + "title": "Use Destructuring Assignment to Assign Variables from Nested Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-assign-variables-from-objects", + "blockName": "ES6" + }, + "id": "587d7b89367417b2b2512b49", + "title": "Use Destructuring Assignment to Assign Variables from Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-extract-values-from-objects", + "blockName": "ES6" + }, + "id": "5cfa550e84205a357704ccb6", + "title": "Use Destructuring Assignment to Extract Values from Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters", + "blockName": "ES6" + }, + "id": "587d7b8a367417b2b2512b4d", + "title": "Use Destructuring Assignment to Pass an Object as a Function's Parameters" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements", + "blockName": "ES6" + }, + "id": "587d7b8a367417b2b2512b4c", + "title": "Use Destructuring Assignment with the Rest Parameter to Reassign Array Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-export-to-share-a-code-block", + "blockName": "ES6" + }, + "id": "587d7b8c367417b2b2512b56", + "title": "Use export to Share a Code Block" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-getters-and-setters-to-control-access-to-an-object", + "blockName": "ES6" + }, + "id": "587d7b8c367417b2b2512b54", + "title": "Use getters and setters to Control Access to an Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters", + "blockName": "ES6" + }, + "id": "587d7b88367417b2b2512b47", + "title": "Use the Rest Parameter with Function Parameters" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/use-the-spread-operator-to-evaluate-arrays-in-place", + "blockName": "ES6" + }, + "id": "587d7b89367417b2b2512b48", + "title": "Use the Spread Operator to Evaluate Arrays In-Place" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/write-arrow-functions-with-parameters", + "blockName": "ES6" + }, + "id": "587d7b88367417b2b2512b44", + "title": "Write Arrow Functions with Parameters" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6", + "blockName": "ES6" + }, + "id": "587d7b8b367417b2b2512b50", + "title": "Write Concise Declarative Functions with ES6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/es6/write-concise-object-literal-declarations-using-object-property-shorthand", + "blockName": "ES6" + }, + "id": "587d7b8a367417b2b2512b4f", + "title": "Write Concise Object Literal Declarations Using Object Property Shorthand" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/add-elements-to-the-end-of-an-array-using-concat-instead-of-push", + "blockName": "Functional Programming" + }, + "id": "587d7da9367417b2b2512b67", + "title": "Add Elements to the End of an Array Using concat Instead of push" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/apply-functional-programming-to-convert-strings-to-url-slugs", + "blockName": "Functional Programming" + }, + "id": "587d7dab367417b2b2512b6d", + "title": "Apply Functional Programming to Convert Strings to URL Slugs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming", + "blockName": "Functional Programming" + }, + "id": "587d7b8e367417b2b2512b5e", + "title": "Avoid Mutations and Side Effects Using Functional Programming" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method", + "blockName": "Functional Programming" + }, + "id": "587d7daa367417b2b2512b6c", + "title": "Combine an Array into a String Using the join Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/combine-two-arrays-using-the-concat-method", + "blockName": "Functional Programming" + }, + "id": "587d7da9367417b2b2512b66", + "title": "Combine Two Arrays Using the concat Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype", + "blockName": "Functional Programming" + }, + "id": "587d7b8f367417b2b2512b62", + "title": "Implement map on a Prototype" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/implement-the-filter-method-on-a-prototype", + "blockName": "Functional Programming" + }, + "id": "587d7b8f367417b2b2512b64", + "title": "Implement the filter Method on a Prototype" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application", + "blockName": "Functional Programming" + }, + "id": "587d7dab367417b2b2512b70", + "title": "Introduction to Currying and Partial Application" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming", + "blockName": "Functional Programming" + }, + "id": "587d7b8d367417b2b2512b5b", + "title": "Learn About Functional Programming" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function", + "blockName": "Functional Programming" + }, + "id": "587d7b8e367417b2b2512b5f", + "title": "Pass Arguments to Avoid External Dependence in a Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions", + "blockName": "Functional Programming" + }, + "id": "587d7b8f367417b2b2512b60", + "title": "Refactor Global Variables Out of Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice", + "blockName": "Functional Programming" + }, + "id": "9d7123c8c441eeafaeb5bdef", + "title": "Remove Elements from an Array Using slice Instead of splice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array", + "blockName": "Functional Programming" + }, + "id": "587d7da9367417b2b2512b6a", + "title": "Return a Sorted Array Without Changing the Original Array" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/return-part-of-an-array-using-the-slice-method", + "blockName": "Functional Programming" + }, + "id": "587d7b90367417b2b2512b65", + "title": "Return Part of an Array Using the slice Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/sort-an-array-alphabetically-using-the-sort-method", + "blockName": "Functional Programming" + }, + "id": "587d7da9367417b2b2512b69", + "title": "Sort an Array Alphabetically using the sort Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/split-a-string-into-an-array-using-the-split-method", + "blockName": "Functional Programming" + }, + "id": "587d7daa367417b2b2512b6b", + "title": "Split a String into an Array Using the split Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology", + "blockName": "Functional Programming" + }, + "id": "587d7b8e367417b2b2512b5c", + "title": "Understand Functional Programming Terminology" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/understand-the-hazards-of-using-imperative-code", + "blockName": "Functional Programming" + }, + "id": "587d7b8e367417b2b2512b5d", + "title": "Understand the Hazards of Using Imperative Code" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem", + "blockName": "Functional Programming" + }, + "id": "587d7b88367417b2b2512b45", + "title": "Use Higher-Order Functions map, filter, or reduce to Solve a Complex Problem" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/use-the-every-method-to-check-that-every-element-in-an-array-meets-a-criteria", + "blockName": "Functional Programming" + }, + "id": "587d7dab367417b2b2512b6e", + "title": "Use the every Method to Check that Every Element in an Array Meets a Criteria" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/use-the-filter-method-to-extract-data-from-an-array", + "blockName": "Functional Programming" + }, + "id": "587d7b8f367417b2b2512b63", + "title": "Use the filter Method to Extract Data from an Array" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array", + "blockName": "Functional Programming" + }, + "id": "587d7b8f367417b2b2512b61", + "title": "Use the map Method to Extract Data from an Array" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data", + "blockName": "Functional Programming" + }, + "id": "587d7da9367417b2b2512b68", + "title": "Use the reduce Method to Analyze Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/functional-programming/use-the-some-method-to-check-that-any-elements-in-an-array-meet-a-criteria", + "blockName": "Functional Programming" + }, + "id": "587d7dab367417b2b2512b6f", + "title": "Use the some Method to Check that Any Elements in an Array Meet a Criteria" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/arguments-optional", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a97fd23d9b809dac9921074f", + "title": "Arguments Optional" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/binary-agents", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a8d97bd4c764e91f9d2bda01", + "title": "Binary Agents" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/convert-html-entities", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a6b0bb188d873cb2c8729495", + "title": "Convert HTML Entities" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/diff-two-arrays", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a5de63ebea8dbee56860f4f2", + "title": "Diff Two Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/dna-pairing", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "afd15382cdfb22c9efe8b7de", + "title": "DNA Pairing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/drop-it", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a5deed1811a43193f9f1c841", + "title": "Drop it" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a10d2431ad0c6a099a4b8b52", + "title": "Everything Be True" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/make-a-person", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a2f1d72d9b908d0bd72bb9f6", + "title": "Make a Person" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/map-the-debris", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "af4afb223120f7348cdfc9fd", + "title": "Map the Debris" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/missing-letters", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "af7588ade1100bde429baf20", + "title": "Missing letters" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/pig-latin", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "aa7697ea2477d1316795783b", + "title": "Pig Latin" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/search-and-replace", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a0b5010f579e69b815e7c5d6", + "title": "Search and Replace" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/seek-and-destroy", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a39963a4c10bc8b4d4f06d7e", + "title": "Seek and Destroy" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "ae9defd7acaf69703ab432ea", + "title": "Smallest Common Multiple" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sorted-union", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a105e963526e7de52b219be9", + "title": "Sorted Union" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/spinal-tap-case", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a103376db3ba46b2d50db289", + "title": "Spinal Tap Case" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/steamroller", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "ab306dbdcc907c7ddfc30830", + "title": "Steamroller" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-numbers-in-a-range", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a3566b1109230028080c9345", + "title": "Sum All Numbers in a Range" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a5229172f011153519423690", + "title": "Sum All Odd Fibonacci Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-primes", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a3bfc1673c0526e06d3ac698", + "title": "Sum All Primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou", + "blockName": "Intermediate Algorithm Scripting" + }, + "id": "a8e512fbe388ac2f9198f0fa", + "title": "Wherefore art thou" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/caesars-cipher", + "blockName": "JavaScript Algorithms and Data Structures Projects" + }, + "id": "56533eb9ac21ba0edf2244e2", + "title": "Caesars Cipher" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register", + "blockName": "JavaScript Algorithms and Data Structures Projects" + }, + "id": "aa2e6f85cab2ab736c9a9b24", + "title": "Cash Register" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker", + "blockName": "JavaScript Algorithms and Data Structures Projects" + }, + "id": "aaa48de84e1ecc7c742e1124", + "title": "Palindrome Checker" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/roman-numeral-converter", + "blockName": "JavaScript Algorithms and Data Structures Projects" + }, + "id": "a7f4d8f2483413a6ce226cac", + "title": "Roman Numeral Converter" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator", + "blockName": "JavaScript Algorithms and Data Structures Projects" + }, + "id": "aff0395860f5d3034dc0bfc9", + "title": "Telephone Number Validator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db1367417b2b2512b87", + "title": "Add Methods After Inheritance" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/change-the-prototype-to-a-new-object", + "blockName": "Object Oriented Programming" + }, + "id": "587d7daf367417b2b2512b7f", + "title": "Change the Prototype to a New Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/create-a-basic-javascript-object", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dac367417b2b2512b73", + "title": "Create a Basic JavaScript Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dad367417b2b2512b75", + "title": "Create a Method on an Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/define-a-constructor-function", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dad367417b2b2512b77", + "title": "Define a Constructor Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dae367417b2b2512b79", + "title": "Extend Constructors to Receive Arguments" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db0367417b2b2512b84", + "title": "Inherit Behaviors from a Supertype" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties", + "blockName": "Object Oriented Programming" + }, + "id": "587d7daf367417b2b2512b7d", + "title": "Iterate Over All Properties" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/make-code-more-reusable-with-the-this-keyword", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dad367417b2b2512b76", + "title": "Make Code More Reusable with the this Keyword" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/override-inherited-methods", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db1367417b2b2512b88", + "title": "Override Inherited Methods" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype", + "blockName": "Object Oriented Programming" + }, + "id": "587d7daf367417b2b2512b80", + "title": "Remember to Set the Constructor Property when Changing the Prototype" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db1367417b2b2512b86", + "title": "Reset an Inherited Constructor Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/set-the-childs-prototype-to-an-instance-of-the-parent", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db1367417b2b2512b85", + "title": "Set the Child's Prototype to an Instance of the Parent" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dae367417b2b2512b7b", + "title": "Understand Own Properties" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property", + "blockName": "Object Oriented Programming" + }, + "id": "587d7daf367417b2b2512b7e", + "title": "Understand the Constructor Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db2367417b2b2512b8b", + "title": "Understand the Immediately Invoked Function Expression (IIFE)" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-prototype-chain", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db0367417b2b2512b82", + "title": "Understand the Prototype Chain" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/understand-where-an-objects-prototype-comes-from", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db0367417b2b2512b81", + "title": "Understand Where an Object’s Prototype Comes From" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/use-a-constructor-to-create-objects", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dad367417b2b2512b78", + "title": "Use a Constructor to Create Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db2367417b2b2512b89", + "title": "Use a Mixin to Add Common Behavior Between Unrelated Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/use-an-iife-to-create-a-module", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db2367417b2b2512b8c", + "title": "Use an IIFE to Create a Module" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db2367417b2b2512b8a", + "title": "Use Closure to Protect Properties Within an Object from Being Modified Externally" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dac367417b2b2512b74", + "title": "Use Dot Notation to Access the Properties of an Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself", + "blockName": "Object Oriented Programming" + }, + "id": "587d7db0367417b2b2512b83", + "title": "Use Inheritance So You Don't Repeat Yourself" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dae367417b2b2512b7c", + "title": "Use Prototype Properties to Reduce Duplicate Code" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/object-oriented-programming/verify-an-objects-constructor-with-instanceof", + "blockName": "Object Oriented Programming" + }, + "id": "587d7dae367417b2b2512b7a", + "title": "Verify an Object's Constructor with instanceof" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/check-for-all-or-none", + "blockName": "Regular Expressions" + }, + "id": "587d7dba367417b2b2512ba8", + "title": "Check for All or None" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/check-for-mixed-grouping-of-characters", + "blockName": "Regular Expressions" + }, + "id": "5c3dda8b4d8df89bea71600f", + "title": "Check For Mixed Grouping of Characters" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/extract-matches", + "blockName": "Regular Expressions" + }, + "id": "587d7db4367417b2b2512b92", + "title": "Extract Matches" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/find-characters-with-lazy-matching", + "blockName": "Regular Expressions" + }, + "id": "587d7db6367417b2b2512b9b", + "title": "Find Characters with Lazy Matching" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/find-more-than-the-first-match", + "blockName": "Regular Expressions" + }, + "id": "587d7db4367417b2b2512b93", + "title": "Find More Than the First Match" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/find-one-or-more-criminals-in-a-hunt", + "blockName": "Regular Expressions" + }, + "id": "587d7db7367417b2b2512b9c", + "title": "Find One or More Criminals in a Hunt" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/ignore-case-while-matching", + "blockName": "Regular Expressions" + }, + "id": "587d7db4367417b2b2512b91", + "title": "Ignore Case While Matching" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-a-literal-string-with-different-possibilities", + "blockName": "Regular Expressions" + }, + "id": "587d7db4367417b2b2512b90", + "title": "Match a Literal String with Different Possibilities" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-all-letters-and-numbers", + "blockName": "Regular Expressions" + }, + "id": "587d7db7367417b2b2512b9f", + "title": "Match All Letters and Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-all-non-numbers", + "blockName": "Regular Expressions" + }, + "id": "587d7db8367417b2b2512ba1", + "title": "Match All Non-Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-all-numbers", + "blockName": "Regular Expressions" + }, + "id": "5d712346c441eddfaeb5bdef", + "title": "Match All Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-anything-with-wildcard-period", + "blockName": "Regular Expressions" + }, + "id": "587d7db5367417b2b2512b94", + "title": "Match Anything with Wildcard Period" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-beginning-string-patterns", + "blockName": "Regular Expressions" + }, + "id": "587d7db7367417b2b2512b9d", + "title": "Match Beginning String Patterns" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-characters-that-occur-one-or-more-times", + "blockName": "Regular Expressions" + }, + "id": "587d7db6367417b2b2512b99", + "title": "Match Characters that Occur One or More Times" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-characters-that-occur-zero-or-more-times", + "blockName": "Regular Expressions" + }, + "id": "587d7db6367417b2b2512b9a", + "title": "Match Characters that Occur Zero or More Times" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-ending-string-patterns", + "blockName": "Regular Expressions" + }, + "id": "587d7db7367417b2b2512b9e", + "title": "Match Ending String Patterns" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-everything-but-letters-and-numbers", + "blockName": "Regular Expressions" + }, + "id": "587d7db8367417b2b2512ba0", + "title": "Match Everything But Letters and Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-letters-of-the-alphabet", + "blockName": "Regular Expressions" + }, + "id": "587d7db5367417b2b2512b96", + "title": "Match Letters of the Alphabet" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-literal-strings", + "blockName": "Regular Expressions" + }, + "id": "587d7db3367417b2b2512b8f", + "title": "Match Literal Strings" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-non-whitespace-characters", + "blockName": "Regular Expressions" + }, + "id": "587d7db9367417b2b2512ba4", + "title": "Match Non-Whitespace Characters" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-numbers-and-letters-of-the-alphabet", + "blockName": "Regular Expressions" + }, + "id": "587d7db5367417b2b2512b97", + "title": "Match Numbers and Letters of the Alphabet" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-single-character-with-multiple-possibilities", + "blockName": "Regular Expressions" + }, + "id": "587d7db5367417b2b2512b95", + "title": "Match Single Character with Multiple Possibilities" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-single-characters-not-specified", + "blockName": "Regular Expressions" + }, + "id": "587d7db6367417b2b2512b98", + "title": "Match Single Characters Not Specified" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/match-whitespace", + "blockName": "Regular Expressions" + }, + "id": "587d7db8367417b2b2512ba3", + "title": "Match Whitespace" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/positive-and-negative-lookahead", + "blockName": "Regular Expressions" + }, + "id": "587d7dba367417b2b2512ba9", + "title": "Positive and Negative Lookahead" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/remove-whitespace-from-start-and-end", + "blockName": "Regular Expressions" + }, + "id": "587d7dbb367417b2b2512bac", + "title": "Remove Whitespace from Start and End" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/restrict-possible-usernames", + "blockName": "Regular Expressions" + }, + "id": "587d7db8367417b2b2512ba2", + "title": "Restrict Possible Usernames" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/reuse-patterns-using-capture-groups", + "blockName": "Regular Expressions" + }, + "id": "587d7dbb367417b2b2512baa", + "title": "Reuse Patterns Using Capture Groups" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/specify-exact-number-of-matches", + "blockName": "Regular Expressions" + }, + "id": "587d7db9367417b2b2512ba7", + "title": "Specify Exact Number of Matches" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/specify-only-the-lower-number-of-matches", + "blockName": "Regular Expressions" + }, + "id": "587d7db9367417b2b2512ba6", + "title": "Specify Only the Lower Number of Matches" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/specify-upper-and-lower-number-of-matches", + "blockName": "Regular Expressions" + }, + "id": "587d7db9367417b2b2512ba5", + "title": "Specify Upper and Lower Number of Matches" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/use-capture-groups-to-search-and-replace", + "blockName": "Regular Expressions" + }, + "id": "587d7dbb367417b2b2512bab", + "title": "Use Capture Groups to Search and Replace" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/javascript-algorithms-and-data-structures/regular-expressions/using-the-test-method", + "blockName": "Regular Expressions" + }, + "id": "587d7db3367417b2b2512b8e", + "title": "Using the Test Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/add-elements-within-your-bootstrap-wells", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908849", + "title": "Add Elements within Your Bootstrap Wells" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/add-font-awesome-icons-to-all-of-our-buttons", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aedc08845", + "title": "Add Font Awesome Icons to all of our Buttons" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/add-font-awesome-icons-to-our-buttons", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aedd08845", + "title": "Add Font Awesome Icons to our Buttons" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/add-id-attributes-to-bootstrap-elements", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908853", + "title": "Add id Attributes to Bootstrap Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/apply-the-default-bootstrap-button-style", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908850", + "title": "Apply the Default Bootstrap Button Style" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/call-out-optional-actions-with-btn-info", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348cd8acef08813", + "title": "Call out Optional Actions with btn-info" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/center-text-with-bootstrap", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd8acde08812", + "title": "Center Text with Bootstrap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/create-a-block-element-bootstrap-button", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348cd8acef08812", + "title": "Create a Block Element Bootstrap Button" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/create-a-bootstrap-button", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348cd8acdf08812", + "title": "Create a Bootstrap Button" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/create-a-bootstrap-headline", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908846", + "title": "Create a Bootstrap Headline" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/create-a-bootstrap-row", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9bec908846", + "title": "Create a Bootstrap Row" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/create-a-class-to-target-with-jquery-selectors", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908852", + "title": "Create a Class to Target with jQuery Selectors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/create-a-custom-heading", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aede08845", + "title": "Create a Custom Heading" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/create-bootstrap-wells", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908848", + "title": "Create Bootstrap Wells" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/ditch-custom-css-for-bootstrap", + "blockName": "Bootstrap" + }, + "id": "bad87fee1347bd9aedf08845", + "title": "Ditch Custom CSS for Bootstrap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/give-each-element-a-unique-id", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908855", + "title": "Give Each Element a Unique id" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/house-our-page-within-a-bootstrap-container-fluid-div", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908746", + "title": "House our page within a Bootstrap container-fluid div" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/label-bootstrap-buttons", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908856", + "title": "Label Bootstrap Buttons" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/label-bootstrap-wells", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908854", + "title": "Label Bootstrap Wells" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/line-up-form-elements-responsively-with-bootstrap", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908845", + "title": "Line up Form Elements Responsively with Bootstrap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/make-images-mobile-responsive", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9acde08812", + "title": "Make Images Mobile Responsive" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/responsively-style-checkboxes", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aeda08845", + "title": "Responsively Style Checkboxes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/responsively-style-radio-buttons", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aedb08845", + "title": "Responsively Style Radio Buttons" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/split-your-bootstrap-row", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908847", + "title": "Split Your Bootstrap Row" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/style-text-inputs-as-form-controls", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aed908845", + "title": "Style Text Inputs as Form Controls" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/taste-the-bootstrap-button-color-rainbow", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348cd8acef08811", + "title": "Taste the Bootstrap Button Color Rainbow" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/use-a-span-to-target-inline-elements", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aedf08845", + "title": "Use a span to Target Inline Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/use-comments-to-clarify-code", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9aec908857", + "title": "Use Comments to Clarify Code" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/use-responsive-design-with-bootstrap-fluid-containers", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348bd9acde08712", + "title": "Use Responsive Design with Bootstrap Fluid Containers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/use-the-bootstrap-grid-to-put-elements-side-by-side", + "blockName": "Bootstrap" + }, + "id": "bad88fee1348ce8acef08815", + "title": "Use the Bootstrap Grid to Put Elements Side By Side" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/bootstrap/warn-your-users-of-a-dangerous-action-with-btn-danger", + "blockName": "Bootstrap" + }, + "id": "bad87fee1348ce8acef08814", + "title": "Warn Your Users of a Dangerous Action with btn-danger" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/front-end-development-libraries-projects/build-a-25--5-clock", + "blockName": "Front End Development Libraries Projects" + }, + "id": "bd7158d8c442eddfaeb5bd0f", + "title": "Build a 25 + 5 Clock" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine", + "blockName": "Front End Development Libraries Projects" + }, + "id": "587d7dbc367417b2b2512bae", + "title": "Build a Drum Machine" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator", + "blockName": "Front End Development Libraries Projects" + }, + "id": "bd7158d8c442eddfaeb5bd17", + "title": "Build a JavaScript Calculator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/front-end-development-libraries-projects/build-a-markdown-previewer", + "blockName": "Front End Development Libraries Projects" + }, + "id": "bd7157d8c242eddfaeb5bd13", + "title": "Build a Markdown Previewer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/front-end-development-libraries-projects/build-a-random-quote-machine", + "blockName": "Front End Development Libraries Projects" + }, + "id": "bd7158d8c442eddfaeb5bd13", + "title": "Build a Random Quote Machine" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/change-text-inside-an-element-using-jquery", + "blockName": "jQuery" + }, + "id": "564944c91be2204b269d51e3", + "title": "Change Text Inside an Element Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/change-the-css-of-an-element-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed908826", + "title": "Change the CSS of an Element Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/clone-an-element-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed508826", + "title": "Clone an Element Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/delete-your-jquery-functions", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aeda08726", + "title": "Delete Your jQuery Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/disable-an-element-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed808826", + "title": "Disable an Element Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/learn-how-script-tags-and-document-ready-work", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9acdd08826", + "title": "Learn How Script Tags and Document Ready Work" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/remove-an-element-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed708826", + "title": "Remove an Element Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/remove-classes-from-an-element-with-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed918626", + "title": "Remove Classes from an Element with jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/target-a-specific-child-of-an-element-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed108826", + "title": "Target a Specific Child of an Element Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/target-elements-by-class-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aedc08826", + "title": "Target Elements by Class Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/target-elements-by-id-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aeda08826", + "title": "Target Elements by id Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/target-even-elements-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed008826", + "title": "Target Even Elements Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/target-html-elements-with-selectors-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9bedc08826", + "title": "Target HTML Elements with Selectors Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/target-the-children-of-an-element-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed208826", + "title": "Target the Children of an Element Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/target-the-parent-of-an-element-using-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed308826", + "title": "Target the Parent of an Element Using jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/target-the-same-element-with-multiple-jquery-selectors", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed908626", + "title": "Target the Same Element with Multiple jQuery Selectors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/use-appendto-to-move-elements-with-jquery", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aed608826", + "title": "Use appendTo to Move Elements with jQuery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/jquery/use-jquery-to-modify-the-entire-page", + "blockName": "jQuery" + }, + "id": "bad87fee1348bd9aecb08826", + "title": "Use jQuery to Modify the Entire Page" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/access-props-using-this-props", + "blockName": "React" + }, + "id": "5a24c314108439a4d403616e", + "title": "Access Props Using this.props" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/add-comments-in-jsx", + "blockName": "React" + }, + "id": "5a24bbe0dba28a8d3cbd4c5e", + "title": "Add Comments in JSX" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/add-event-listeners", + "blockName": "React" + }, + "id": "5a24c314108439a4d403617e", + "title": "Add Event Listeners" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/add-inline-styles-in-react", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036182", + "title": "Add Inline Styles in React" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/bind-this-to-a-class-method", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036174", + "title": "Bind 'this' to a Class Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/change-inline-css-conditionally-based-on-component-state", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036189", + "title": "Change Inline CSS Conditionally Based on Component State" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/compose-react-components", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036166", + "title": "Compose React Components" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/create-a-complex-jsx-element", + "blockName": "React" + }, + "id": "5a24bbe0dba28a8d3cbd4c5d", + "title": "Create a Complex JSX Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/create-a-component-with-composition", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036164", + "title": "Create a Component with Composition" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/create-a-controlled-form", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036179", + "title": "Create a Controlled Form" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/create-a-controlled-input", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036178", + "title": "Create a Controlled Input" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/create-a-react-component", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036163", + "title": "Create a React Component" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/create-a-simple-jsx-element", + "blockName": "React" + }, + "id": "587d7dbc367417b2b2512bb1", + "title": "Create a Simple JSX Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/create-a-stateful-component", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036170", + "title": "Create a Stateful Component" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/create-a-stateless-functional-component", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036162", + "title": "Create a Stateless Functional Component" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/define-an-html-class-in-jsx", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036160", + "title": "Define an HTML Class in JSX" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/give-sibling-elements-a-unique-key-attribute", + "blockName": "React" + }, + "id": "5a24c314108439a4d403618b", + "title": "Give Sibling Elements a Unique Key Attribute" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/introducing-inline-styles", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036181", + "title": "Introducing Inline Styles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/learn-about-self-closing-jsx-tags", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036161", + "title": "Learn About Self-Closing JSX Tags" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/optimize-re-renders-with-shouldcomponentupdate", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036180", + "title": "Optimize Re-Renders with shouldComponentUpdate" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/override-default-props", + "blockName": "React" + }, + "id": "5a24c314108439a4d403616c", + "title": "Override Default Props" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/pass-a-callback-as-props", + "blockName": "React" + }, + "id": "5a24c314108439a4d403617b", + "title": "Pass a Callback as Props" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/pass-an-array-as-props", + "blockName": "React" + }, + "id": "5a24c314108439a4d403616a", + "title": "Pass an Array as Props" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/pass-props-to-a-stateless-functional-component", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036169", + "title": "Pass Props to a Stateless Functional Component" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/pass-state-as-props-to-child-components", + "blockName": "React" + }, + "id": "5a24c314108439a4d403617a", + "title": "Pass State as Props to Child Components" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/render-a-class-component-to-the-dom", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036167", + "title": "Render a Class Component to the DOM" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/render-conditionally-from-props", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036188", + "title": "Render Conditionally from Props" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/render-html-elements-to-the-dom", + "blockName": "React" + }, + "id": "5a24bbe0dba28a8d3cbd4c5f", + "title": "Render HTML Elements to the DOM" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/render-react-on-the-server-with-rendertostring", + "blockName": "React" + }, + "id": "5a24c314108439a4d403618d", + "title": "Render React on the Server with renderToString" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/render-state-in-the-user-interface-another-way", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036172", + "title": "Render State in the User Interface Another Way" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/render-state-in-the-user-interface", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036171", + "title": "Render State in the User Interface" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/render-with-an-if-else-condition", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036184", + "title": "Render with an If-Else Condition" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/review-using-props-with-stateless-functional-components", + "blockName": "React" + }, + "id": "5a24c314108439a4d403616f", + "title": "Review Using Props with Stateless Functional Components" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/set-state-with-this-setstate", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036173", + "title": "Set State with this.setState" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use--for-a-more-concise-conditional", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036185", + "title": "Use && for a More Concise Conditional" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-a-ternary-expression-for-conditional-rendering", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036187", + "title": "Use a Ternary Expression for Conditional Rendering" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-advanced-javascript-in-react-render-method", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036183", + "title": "Use Advanced JavaScript in React Render Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-array-filter-to-dynamically-filter-an-array", + "blockName": "React" + }, + "id": "5a24c314108439a4d403618c", + "title": "Use Array.filter() to Dynamically Filter an Array" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-array-map-to-dynamically-render-elements", + "blockName": "React" + }, + "id": "5a24c314108439a4d403618a", + "title": "Use Array.map() to Dynamically Render Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-default-props", + "blockName": "React" + }, + "id": "5a24c314108439a4d403616b", + "title": "Use Default Props" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-proptypes-to-define-the-props-you-expect", + "blockName": "React" + }, + "id": "5a24c314108439a4d403616d", + "title": "Use PropTypes to Define the Props You Expect" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-react-to-render-nested-components", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036165", + "title": "Use React to Render Nested Components" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-state-to-toggle-an-element", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036176", + "title": "Use State to Toggle an Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-the-lifecycle-method-componentdidmount", + "blockName": "React" + }, + "id": "5a24c314108439a4d403617d", + "title": "Use the Lifecycle Method componentDidMount" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/use-the-lifecycle-method-componentwillmount", + "blockName": "React" + }, + "id": "5a24c314108439a4d403617c", + "title": "Use the Lifecycle Method componentWillMount" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/write-a-react-component-from-scratch", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036168", + "title": "Write a React Component from Scratch" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react/write-a-simple-counter", + "blockName": "React" + }, + "id": "5a24c314108439a4d4036177", + "title": "Write a Simple Counter" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/connect-redux-to-react", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036147", + "title": "Connect Redux to React" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/connect-redux-to-the-messages-app", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036148", + "title": "Connect Redux to the Messages App" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/extract-local-state-into-redux", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036149", + "title": "Extract Local State into Redux" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/extract-state-logic-to-redux", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036143", + "title": "Extract State Logic to Redux" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/getting-started-with-react-redux", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036141", + "title": "Getting Started with React Redux" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/manage-state-locally-first", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036142", + "title": "Manage State Locally First" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/map-dispatch-to-props", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036146", + "title": "Map Dispatch to Props" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/map-state-to-props", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036145", + "title": "Map State to Props" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/moving-forward-from-here", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d403614a", + "title": "Moving Forward From Here" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/react-and-redux/use-provider-to-connect-redux-to-react", + "blockName": "React and Redux" + }, + "id": "5a24c314108439a4d4036144", + "title": "Use Provider to Connect Redux to React" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/combine-multiple-reducers", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036154", + "title": "Combine Multiple Reducers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/copy-an-object-with-object-assign", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d403615b", + "title": "Copy an Object with Object.assign" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/create-a-redux-store", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d403614b", + "title": "Create a Redux Store" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/define-a-redux-action", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d403614d", + "title": "Define a Redux Action" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/define-an-action-creator", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d403614e", + "title": "Define an Action Creator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/dispatch-an-action-event", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d403614f", + "title": "Dispatch an Action Event" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/get-state-from-the-redux-store", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d403614c", + "title": "Get State from the Redux Store" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/handle-an-action-in-the-store", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036150", + "title": "Handle an Action in the Store" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/never-mutate-state", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036158", + "title": "Never Mutate State" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/register-a-store-listener", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036153", + "title": "Register a Store Listener" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/remove-an-item-from-an-array", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d403615a", + "title": "Remove an Item from an Array" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/send-action-data-to-the-store", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036155", + "title": "Send Action Data to the Store" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/use-a-switch-statement-to-handle-multiple-actions", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036151", + "title": "Use a Switch Statement to Handle Multiple Actions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/use-const-for-action-types", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036152", + "title": "Use const for Action Types" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/use-middleware-to-handle-asynchronous-actions", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036156", + "title": "Use Middleware to Handle Asynchronous Actions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/use-the-spread-operator-on-arrays", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036159", + "title": "Use the Spread Operator on Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/redux/write-a-counter-with-redux", + "blockName": "Redux" + }, + "id": "5a24c314108439a4d4036157", + "title": "Write a Counter with Redux" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/apply-a-style-until-a-condition-is-met-with-while", + "blockName": "Sass" + }, + "id": "587d7dbf367417b2b2512bbb", + "title": "Apply a Style Until a Condition is Met with @while" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/create-reusable-css-with-mixins", + "blockName": "Sass" + }, + "id": "587d7dbd367417b2b2512bb6", + "title": "Create Reusable CSS with Mixins" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/extend-one-set-of-css-styles-to-another-element", + "blockName": "Sass" + }, + "id": "587d7fa5367417b2b2512bbd", + "title": "Extend One Set of CSS Styles to Another Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/nest-css-with-sass", + "blockName": "Sass" + }, + "id": "587d7dbd367417b2b2512bb5", + "title": "Nest CSS with Sass" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/split-your-styles-into-smaller-chunks-with-partials", + "blockName": "Sass" + }, + "id": "587d7dbf367417b2b2512bbc", + "title": "Split Your Styles into Smaller Chunks with Partials" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/store-data-with-sass-variables", + "blockName": "Sass" + }, + "id": "587d7dbd367417b2b2512bb4", + "title": "Store Data with Sass Variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/use-each-to-map-over-items-in-a-list", + "blockName": "Sass" + }, + "id": "587d7dbf367417b2b2512bba", + "title": "Use @each to Map Over Items in a List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/use-for-to-create-a-sass-loop", + "blockName": "Sass" + }, + "id": "587d7dbe367417b2b2512bb9", + "title": "Use @for to Create a Sass Loop" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles", + "blockName": "Sass" + }, + "id": "587d7dbe367417b2b2512bb8", + "title": "Use @if and @else to Add Logic To Your Styles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-projects/visualize-data-with-a-bar-chart", + "blockName": "Data Visualization Projects" + }, + "id": "bd7168d8c242eddfaeb5bd13", + "title": "Visualize Data with a Bar Chart" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-projects/visualize-data-with-a-choropleth-map", + "blockName": "Data Visualization Projects" + }, + "id": "587d7fa6367417b2b2512bbf", + "title": "Visualize Data with a Choropleth Map" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-projects/visualize-data-with-a-heat-map", + "blockName": "Data Visualization Projects" + }, + "id": "bd7188d8c242eddfaeb5bd13", + "title": "Visualize Data with a Heat Map" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-projects/visualize-data-with-a-scatterplot-graph", + "blockName": "Data Visualization Projects" + }, + "id": "bd7178d8c242eddfaeb5bd13", + "title": "Visualize Data with a Scatterplot Graph" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-projects/visualize-data-with-a-treemap-diagram", + "blockName": "Data Visualization Projects" + }, + "id": "587d7fa6367417b2b2512bc0", + "title": "Visualize Data with a Treemap Diagram" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-a-hover-effect-to-a-d3-element", + "blockName": "Data Visualization with D3" + }, + "id": "587d7faa367417b2b2512bd4", + "title": "Add a Hover Effect to a D3 Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-a-tooltip-to-a-d3-element", + "blockName": "Data Visualization with D3" + }, + "id": "587d7faa367417b2b2512bd6", + "title": "Add a Tooltip to a D3 Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-attributes-to-the-circle-elements", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fab367417b2b2512bd8", + "title": "Add Attributes to the Circle Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-axes-to-a-visualization", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fad367417b2b2512bdf", + "title": "Add Axes to a Visualization" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-classes-with-d3", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa7367417b2b2512bc8", + "title": "Add Classes with D3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-document-elements-with-d3", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa6367417b2b2512bc2", + "title": "Add Document Elements with D3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-inline-styling-to-elements", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa7367417b2b2512bc6", + "title": "Add Inline Styling to Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-labels-to-d3-elements", + "blockName": "Data Visualization with D3" + }, + "id": "587d7faa367417b2b2512bd2", + "title": "Add Labels to D3 Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/add-labels-to-scatter-plot-circles", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fab367417b2b2512bd9", + "title": "Add Labels to Scatter Plot Circles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/change-styles-based-on-data", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa7367417b2b2512bc7", + "title": "Change Styles Based on Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/change-the-color-of-an-svg-element", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa9367417b2b2512bd1", + "title": "Change the Color of an SVG Element" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/change-the-presentation-of-a-bar-chart", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa8367417b2b2512bca", + "title": "Change the Presentation of a Bar Chart" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/create-a-bar-for-each-data-point-in-the-set", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa8367417b2b2512bcd", + "title": "Create a Bar for Each Data Point in the Set" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/create-a-linear-scale-with-d3", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fab367417b2b2512bda", + "title": "Create a Linear Scale with D3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/create-a-scatterplot-with-svg-circles", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fab367417b2b2512bd7", + "title": "Create a Scatterplot with SVG Circles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/display-shapes-with-svg", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa8367417b2b2512bcc", + "title": "Display Shapes with SVG" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/dynamically-change-the-height-of-each-bar", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa9367417b2b2512bcf", + "title": "Dynamically Change the Height of Each Bar" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/dynamically-set-the-coordinates-for-each-bar", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa9367417b2b2512bce", + "title": "Dynamically Set the Coordinates for Each Bar" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/invert-svg-elements", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa9367417b2b2512bd0", + "title": "Invert SVG Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/learn-about-svg-in-d3", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa8367417b2b2512bcb", + "title": "Learn About SVG in D3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/select-a-group-of-elements-with-d3", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa6367417b2b2512bc3", + "title": "Select a Group of Elements with D3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/set-a-domain-and-a-range-on-a-scale", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fac367417b2b2512bdb", + "title": "Set a Domain and a Range on a Scale" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/style-d3-labels", + "blockName": "Data Visualization with D3" + }, + "id": "587d7faa367417b2b2512bd3", + "title": "Style D3 Labels" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/update-the-height-of-an-element-dynamically", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa8367417b2b2512bc9", + "title": "Update the Height of an Element Dynamically" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/use-a-pre-defined-scale-to-place-elements", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fac367417b2b2512bde", + "title": "Use a Pre-Defined Scale to Place Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/use-dynamic-scales", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fac367417b2b2512bdd", + "title": "Use Dynamic Scales" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/use-the-d3-max-and-d3-min-functions-to-find-minimum-and-maximum-values-in-a-dataset", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fac367417b2b2512bdc", + "title": "Use the d3.max and d3.min Functions to Find Minimum and Maximum Values in a Dataset" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/work-with-data-in-d3", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa7367417b2b2512bc4", + "title": "Work with Data in D3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/data-visualization-with-d3/work-with-dynamic-data-in-d3", + "blockName": "Data Visualization with D3" + }, + "id": "587d7fa7367417b2b2512bc5", + "title": "Work with Dynamic Data in D3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/access-the-json-data-from-an-api", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7fae367417b2b2512be4", + "title": "Access the JSON Data from an API" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/change-text-with-click-events", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7fad367417b2b2512be2", + "title": "Change Text with click Events" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/convert-json-data-to-html", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7fae367417b2b2512be5", + "title": "Convert JSON Data to HTML" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/get-geolocation-data-to-find-a-users-gps-coordinates", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7faf367417b2b2512be8", + "title": "Get Geolocation Data to Find A User's GPS Coordinates" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method", + "blockName": "JSON APIs and Ajax" + }, + "id": "5ccfad82bb2dc6c965a848e5", + "title": "Get JSON with the JavaScript fetch method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/get-json-with-the-javascript-xmlhttprequest-method", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7fae367417b2b2512be3", + "title": "Get JSON with the JavaScript XMLHttpRequest Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/handle-click-events-with-javascript-using-the-onclick-property", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7fad367417b2b2512be1", + "title": "Handle Click Events with JavaScript using the onclick property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/post-data-with-the-javascript-xmlhttprequest-method", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7faf367417b2b2512be9", + "title": "Post Data with the JavaScript XMLHttpRequest Method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/pre-filter-json-to-get-the-data-you-need", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7fae367417b2b2512be7", + "title": "Pre-filter JSON to Get the Data You Need" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-visualization/json-apis-and-ajax/render-images-from-data-sources", + "blockName": "JSON APIs and Ajax" + }, + "id": "587d7fae367417b2b2512be6", + "title": "Render Images from Data Sources" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker", + "blockName": "Back End Development and APIs Projects" + }, + "id": "5a8b073d06fa14fcfde687aa", + "title": "Exercise Tracker" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/back-end-development-and-apis-projects/file-metadata-microservice", + "blockName": "Back End Development and APIs Projects" + }, + "id": "bd7158d8c443edefaeb5bd0f", + "title": "File Metadata Microservice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/back-end-development-and-apis-projects/request-header-parser-microservice", + "blockName": "Back End Development and APIs Projects" + }, + "id": "bd7158d8c443edefaeb5bdff", + "title": "Request Header Parser Microservice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/back-end-development-and-apis-projects/timestamp-microservice", + "blockName": "Back End Development and APIs Projects" + }, + "id": "bd7158d8c443edefaeb5bdef", + "title": "Timestamp Microservice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/back-end-development-and-apis-projects/url-shortener-microservice", + "blockName": "Back End Development and APIs Projects" + }, + "id": "bd7158d8c443edefaeb5bd0e", + "title": "URL Shortener Microservice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/chain-middleware-to-create-a-time-server", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb1367417b2b2512bf4", + "title": "Chain Middleware to Create a Time Server" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/get-data-from-post-requests", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb2367417b2b2512bf8", + "title": "Get Data from POST Requests" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/get-query-parameter-input-from-the-client", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb2367417b2b2512bf6", + "title": "Get Query Parameter Input from the Client" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/get-route-parameter-input-from-the-client", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb2367417b2b2512bf5", + "title": "Get Route Parameter Input from the Client" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/implement-a-root-level-request-logger-middleware", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb1367417b2b2512bf3", + "title": "Implement a Root-Level Request Logger Middleware" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/meet-the-node-console", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb0367417b2b2512bed", + "title": "Meet the Node console" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/serve-an-html-file", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb0367417b2b2512bef", + "title": "Serve an HTML File" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/serve-json-on-a-specific-route", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb1367417b2b2512bf1", + "title": "Serve JSON on a Specific Route" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/serve-static-assets", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb0367417b2b2512bf0", + "title": "Serve Static Assets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/start-a-working-express-server", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb0367417b2b2512bee", + "title": "Start a Working Express Server" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/use-body-parser-to-parse-post-requests", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb2367417b2b2512bf7", + "title": "Use body-parser to Parse POST Requests" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/basic-node-and-express/use-the--env-file", + "blockName": "Basic Node and Express" + }, + "id": "587d7fb1367417b2b2512bf2", + "title": "Use the .env File" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/add-a-description-to-your-package-json", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb3367417b2b2512bfc", + "title": "Add a Description to Your package.json" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/add-a-license-to-your-package-json", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb4367417b2b2512bfe", + "title": "Add a License to Your package.json" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/add-a-version-to-your-package-json", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb4367417b2b2512bff", + "title": "Add a Version to Your package.json" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/add-keywords-to-your-package-json", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb4367417b2b2512bfd", + "title": "Add Keywords to Your package.json" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/expand-your-project-with-external-packages-from-npm", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb4367417b2b2512c00", + "title": "Expand Your Project with External Packages from npm" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/how-to-use-package-json-the-core-of-any-node-js-project-or-npm-package", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb3367417b2b2512bfb", + "title": "How to Use package.json, the Core of Any Node.js Project or npm Package" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/manage-npm-dependencies-by-understanding-semantic-versioning", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb5367417b2b2512c01", + "title": "Manage npm Dependencies By Understanding Semantic Versioning" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/remove-a-package-from-your-dependencies", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb5367417b2b2512c04", + "title": "Remove a Package from Your Dependencies" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb5367417b2b2512c03", + "title": "Use the Caret-Character to Use the Latest Minor Version of a Dependency" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/managing-packages-with-npm/use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency", + "blockName": "Managing Packages with Npm" + }, + "id": "587d7fb5367417b2b2512c02", + "title": "Use the Tilde-Character to Always Use the Latest Patch Version of a Dependency" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/chain-search-query-helpers-to-narrow-search-results", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb9367417b2b2512c12", + "title": "Chain Search Query Helpers to Narrow Search Results" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/create-a-model", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb6367417b2b2512c07", + "title": "Create a Model" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/create-and-save-a-record-of-a-model", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb6367417b2b2512c09", + "title": "Create and Save a Record of a Model" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/create-many-records-with-model-create", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb7367417b2b2512c0a", + "title": "Create Many Records with model.create()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/delete-many-documents-with-model-remove", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb8367417b2b2512c11", + "title": "Delete Many Documents with model.remove()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/delete-one-document-using-model-findbyidandremove", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb8367417b2b2512c10", + "title": "Delete One Document Using model.findByIdAndRemove" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/install-and-set-up-mongoose", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb6367417b2b2512c06", + "title": "Install and Set Up Mongoose" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/perform-classic-updates-by-running-find-edit-then-save", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb8367417b2b2512c0e", + "title": "Perform Classic Updates by Running Find, Edit, then Save" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/perform-new-updates-on-a-document-using-model-findoneandupdate", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb8367417b2b2512c0f", + "title": "Perform New Updates on a Document Using model.findOneAndUpdate()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/use-model-find-to-search-your-database", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb7367417b2b2512c0b", + "title": "Use model.find() to Search Your Database" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/use-model-findbyid-to-search-your-database-by-id", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb7367417b2b2512c0d", + "title": "Use model.findById() to Search Your Database By _id" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/back-end-development-and-apis/mongodb-and-mongoose/use-model-findone-to-return-a-single-matching-document-from-your-database", + "blockName": "MongoDB and Mongoose" + }, + "id": "587d7fb7367417b2b2512c0c", + "title": "Use model.findOne() to Return a Single Matching Document from Your Database" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/announce-new-users", + "blockName": "Advanced Node and Express" + }, + "id": "589fc832f9fc0f352b528e78", + "title": "Announce New Users" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/authentication-strategies", + "blockName": "Advanced Node and Express" + }, + "id": "5895f70df9fc0f352b528e68", + "title": "Authentication Strategies" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/authentication-with-socket-io", + "blockName": "Advanced Node and Express" + }, + "id": "589fc831f9fc0f352b528e77", + "title": "Authentication with Socket.IO" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/clean-up-your-project-with-modules", + "blockName": "Advanced Node and Express" + }, + "id": "589690e6f9fc0f352b528e6e", + "title": "Clean Up Your Project with Modules" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/communicate-by-emitting", + "blockName": "Advanced Node and Express" + }, + "id": "589fc831f9fc0f352b528e75", + "title": "Communicate by Emitting" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/create-new-middleware", + "blockName": "Advanced Node and Express" + }, + "id": "5895f70df9fc0f352b528e6a", + "title": "Create New Middleware" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/handle-a-disconnect", + "blockName": "Advanced Node and Express" + }, + "id": "589fc831f9fc0f352b528e76", + "title": "Handle a Disconnect" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/hashing-your-passwords", + "blockName": "Advanced Node and Express" + }, + "id": "58a25c98f9fc0f352b528e7f", + "title": "Hashing Your Passwords" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/how-to-put-a-profile-together", + "blockName": "Advanced Node and Express" + }, + "id": "5895f70ef9fc0f352b528e6b", + "title": "How to Put a Profile Together" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/how-to-use-passport-strategies", + "blockName": "Advanced Node and Express" + }, + "id": "5895f70df9fc0f352b528e69", + "title": "How to Use Passport Strategies" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/implement-the-serialization-of-a-passport-user", + "blockName": "Advanced Node and Express" + }, + "id": "5895f70cf9fc0f352b528e67", + "title": "Implement the Serialization of a Passport User" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/implementation-of-social-authentication-ii", + "blockName": "Advanced Node and Express" + }, + "id": "589a69f5f9fc0f352b528e71", + "title": "Implementation of Social Authentication II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/implementation-of-social-authentication-iii", + "blockName": "Advanced Node and Express" + }, + "id": "589a8eb3f9fc0f352b528e72", + "title": "Implementation of Social Authentication III" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/implementation-of-social-authentication", + "blockName": "Advanced Node and Express" + }, + "id": "589a69f5f9fc0f352b528e70", + "title": "Implementation of Social Authentication" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/logging-a-user-out", + "blockName": "Advanced Node and Express" + }, + "id": "58965611f9fc0f352b528e6c", + "title": "Logging a User Out" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/registration-of-new-users", + "blockName": "Advanced Node and Express" + }, + "id": "58966a17f9fc0f352b528e6d", + "title": "Registration of New Users" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/send-and-display-chat-messages", + "blockName": "Advanced Node and Express" + }, + "id": "589fc832f9fc0f352b528e79", + "title": "Send and Display Chat Messages" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/serialization-of-a-user-object", + "blockName": "Advanced Node and Express" + }, + "id": "5895f70cf9fc0f352b528e66", + "title": "Serialization of a User Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/set-up-a-template-engine", + "blockName": "Advanced Node and Express" + }, + "id": "5895f700f9fc0f352b528e63", + "title": "Set up a Template Engine" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/set-up-passport", + "blockName": "Advanced Node and Express" + }, + "id": "5895f70cf9fc0f352b528e65", + "title": "Set up Passport" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/set-up-the-environment", + "blockName": "Advanced Node and Express" + }, + "id": "589fc830f9fc0f352b528e74", + "title": "Set up the Environment" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/advanced-node-and-express/use-a-template-engines-powers", + "blockName": "Advanced Node and Express" + }, + "id": "5895f70bf9fc0f352b528e64", + "title": "Use a Template Engine's Powers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/assert-deep-equality-with--deepequal-and--notdeepequal", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824c367417b2b2512c4c", + "title": "Assert Deep Equality with .deepEqual and .notDeepEqual" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/compare-the-properties-of-two-elements", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824c367417b2b2512c4d", + "title": "Compare the Properties of Two Elements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824a367417b2b2512c46", + "title": "Learn How JavaScript Assertions Work" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/run-functional-tests-on-an-api-response-using-chai-http-iii---put-method", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824f367417b2b2512c5a", + "title": "Run Functional Tests on an API Response using Chai-HTTP III - PUT method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/run-functional-tests-on-an-api-response-using-chai-http-iv---put-method", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824f367417b2b2512c5b", + "title": "Run Functional Tests on an API Response using Chai-HTTP IV - PUT method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/run-functional-tests-on-api-endpoints-using-chai-http-ii", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824f367417b2b2512c59", + "title": "Run Functional Tests on API Endpoints using Chai-HTTP II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/run-functional-tests-on-api-endpoints-using-chai-http", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824e367417b2b2512c58", + "title": "Run Functional Tests on API Endpoints using Chai-HTTP" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/run-functional-tests-using-a-headless-browser-ii", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "5f8884f4c46685731aabfc41", + "title": "Run Functional Tests Using a Headless Browser II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/run-functional-tests-using-a-headless-browser", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d8250367417b2b2512c5d", + "title": "Run Functional Tests Using a Headless Browser" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/simulate-actions-using-a-headless-browser", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824f367417b2b2512c5c", + "title": "Simulate Actions Using a Headless Browser" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-for-truthiness", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824b367417b2b2512c49", + "title": "Test for Truthiness" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-a-string-contains-a-substring", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824d367417b2b2512c53", + "title": "Test if a String Contains a Substring" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-a-value-falls-within-a-specific-range", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824c367417b2b2512c4f", + "title": "Test if a Value Falls within a Specific Range" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-a-value-is-a-string", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824d367417b2b2512c52", + "title": "Test if a Value is a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-a-value-is-an-array", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824d367417b2b2512c50", + "title": "Test if a Value is an Array" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-a-value-is-of-a-specific-data-structure-type", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824e367417b2b2512c56", + "title": "Test if a Value is of a Specific Data Structure Type" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-a-variable-or-function-is-defined", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824b367417b2b2512c47", + "title": "Test if a Variable or Function is Defined" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-an-array-contains-an-item", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824d367417b2b2512c51", + "title": "Test if an Array Contains an Item" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-an-object-has-a-property", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824e367417b2b2512c55", + "title": "Test if an Object has a Property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-an-object-is-an-instance-of-a-constructor", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824e367417b2b2512c57", + "title": "Test if an Object is an Instance of a Constructor" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/test-if-one-value-is-below-or-at-least-as-large-as-another", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824c367417b2b2512c4e", + "title": "Test if One Value is Below or At Least as Large as Another" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/use-assert-isok-and-assert-isnotok", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824b367417b2b2512c48", + "title": "Use Assert.isOK and Assert.isNotOK" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/use-regular-expressions-to-test-a-string", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824d367417b2b2512c54", + "title": "Use Regular Expressions to Test a String" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/use-the-double-equals-to-assert-equality", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824b367417b2b2512c4a", + "title": "Use the Double Equals to Assert Equality" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-and-testing-with-chai/use-the-triple-equals-to-assert-strict-equality", + "blockName": "Quality Assurance and Testing with Chai" + }, + "id": "587d824b367417b2b2512c4b", + "title": "Use the Triple Equals to Assert Strict Equality" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-projects/american-british-translator", + "blockName": "Quality Assurance Projects" + }, + "id": "5e601c0d5ac9d0ecd8b94afe", + "title": "American British Translator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-projects/issue-tracker", + "blockName": "Quality Assurance Projects" + }, + "id": "587d8249367417b2b2512c42", + "title": "Issue Tracker" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-projects/metric-imperial-converter", + "blockName": "Quality Assurance Projects" + }, + "id": "587d8249367417b2b2512c41", + "title": "Metric-Imperial Converter" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-projects/personal-library", + "blockName": "Quality Assurance Projects" + }, + "id": "587d824a367417b2b2512c43", + "title": "Personal Library" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/quality-assurance/quality-assurance-projects/sudoku-solver", + "blockName": "Quality Assurance Projects" + }, + "id": "5e601bf95ac9d0ecd8b94afd", + "title": "Sudoku Solver" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/build-your-own-functions", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f060b6c005b0e76f05b", + "title": "Build your own Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/comparing-and-sorting-tuples", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0b0b6c005b0e76f06d", + "title": "Comparing and Sorting Tuples" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/conditional-execution", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f050b6c005b0e76f058", + "title": "Conditional Execution" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/data-visualization-mailing-lists", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f6a0b6c005b0e76f097", + "title": "Data Visualization: Mailing Lists" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/data-visualization-page-rank", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f6a0b6c005b0e76f096", + "title": "Data Visualization: Page Rank" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/dictionaries-and-loops", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0a0b6c005b0e76f069", + "title": "Dictionaries and Loops" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/dictionaries-common-applications", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f090b6c005b0e76f068", + "title": "Dictionaries: Common Applications" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/files-as-a-sequence", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f080b6c005b0e76f063", + "title": "Files as a Sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/intermediate-expressions", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f050b6c005b0e76f057", + "title": "Intermediate Expressions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/intermediate-strings", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f070b6c005b0e76f061", + "title": "Intermediate Strings" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/introduction-elements-of-python", + "blockName": "Python for Everybody" + }, + "id": "5e6a54c358d3af90110a60a3", + "title": "Introduction: Elements of Python" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/introduction-hardware-architecture", + "blockName": "Python for Everybody" + }, + "id": "5e6a54af58d3af90110a60a1", + "title": "Introduction: Hardware Architecture" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/introduction-python-as-a-language", + "blockName": "Python for Everybody" + }, + "id": "5e6a54ba58d3af90110a60a2", + "title": "Introduction: Python as a Language" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/introduction-why-program", + "blockName": "Python for Everybody" + }, + "id": "5e6a54a558d3af90110a60a0", + "title": "Introduction: Why Program?" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/iterations-definite-loops", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f070b6c005b0e76f05d", + "title": "Iterations: Definite Loops" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/iterations-loop-idioms", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f070b6c005b0e76f05e", + "title": "Iterations: Loop Idioms" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/iterations-more-patterns", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f070b6c005b0e76f05f", + "title": "Iterations: More Patterns" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/loops-and-iterations", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f060b6c005b0e76f05c", + "title": "Loops and Iterations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/make-a-relational-database", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f170b6c005b0e76f08b", + "title": "Make a Relational Database" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/more-conditional-structures", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f060b6c005b0e76f059", + "title": "More Conditional Structures" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/networking-protocol", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0c0b6c005b0e76f072", + "title": "Networking Protocol" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/networking-text-processing", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0c0b6c005b0e76f074", + "title": "Networking: Text Processing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/networking-using-urllib-in-python", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0d0b6c005b0e76f075", + "title": "Networking: Using urllib in Python" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/networking-web-scraping-with-python", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0d0b6c005b0e76f076", + "title": "Networking: Web Scraping with Python" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/networking-with-python", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0c0b6c005b0e76f071", + "title": "Networking with Python" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/networking-write-a-web-browser", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0c0b6c005b0e76f073", + "title": "Networking: Write a Web Browser" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/object-lifecycle", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f170b6c005b0e76f087", + "title": "Object Lifecycle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/objects-a-sample-class", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f160b6c005b0e76f086", + "title": "Objects: A Sample Class" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/objects-inheritance", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f170b6c005b0e76f088", + "title": "Objects: Inheritance" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/python-dictionaries", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f090b6c005b0e76f067", + "title": "Python Dictionaries" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/python-functions", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f060b6c005b0e76f05a", + "title": "Python Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/python-lists", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f080b6c005b0e76f064", + "title": "Python Lists" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/python-objects", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f160b6c005b0e76f085", + "title": "Python Objects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/reading-files", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f080b6c005b0e76f062", + "title": "Reading Files" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/regular-expressions-matching-and-extracting-data", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0b0b6c005b0e76f06f", + "title": "Regular Expressions: Matching and Extracting Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/regular-expressions-practical-applications", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0b0b6c005b0e76f070", + "title": "Regular Expressions: Practical Applications" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/regular-expressions", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0b0b6c005b0e76f06e", + "title": "Regular Expressions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/relational-database-design", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f180b6c005b0e76f08c", + "title": "Relational Database Design" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/relational-databases-and-sqlite", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f170b6c005b0e76f08a", + "title": "Relational Databases and SQLite" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/relational-databases-join-operation", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f180b6c005b0e76f08f", + "title": "Relational Databases: Join Operation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/relational-databases-many-to-many-relationships", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f190b6c005b0e76f090", + "title": "Relational Databases: Many-to-many Relationships" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/relational-databases-relationship-building", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f180b6c005b0e76f08e", + "title": "Relational Databases: Relationship Building" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/representing-relationships-in-a-relational-database", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f180b6c005b0e76f08d", + "title": "Representing Relationships in a Relational Database" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/strings-and-lists", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f090b6c005b0e76f066", + "title": "Strings and Lists" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/strings-in-python", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f070b6c005b0e76f060", + "title": "Strings in Python" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/the-tuples-collection", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0a0b6c005b0e76f06c", + "title": "The Tuples Collection" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/using-web-services", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0e0b6c005b0e76f07a", + "title": "Using Web Services" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/variables-expressions-and-statements", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f050b6c005b0e76f056", + "title": "Variables, Expressions, and Statements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/visualizing-data-with-python", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f690b6c005b0e76f095", + "title": "Visualizing Data with Python" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/web-services-api-rate-limiting-and-security", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f150b6c005b0e76f080", + "title": "Web Services: API Rate Limiting and Security" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/web-services-apis", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f150b6c005b0e76f07f", + "title": "Web Services: APIs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/web-services-json", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f140b6c005b0e76f07d", + "title": "Web Services: JSON" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/web-services-service-oriented-approach", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f140b6c005b0e76f07e", + "title": "Web Services: Service Oriented Approach" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/web-services-xml-schema", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0e0b6c005b0e76f07c", + "title": "Web Services: XML Schema" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/web-services-xml", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f0e0b6c005b0e76f07b", + "title": "Web Services: XML" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/python-for-everybody/working-with-lists", + "blockName": "Python for Everybody" + }, + "id": "5e7b9f090b6c005b0e76f065", + "title": "Working with Lists" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/scientific-computing-with-python-projects/arithmetic-formatter", + "blockName": "Scientific Computing with Python Projects" + }, + "id": "5e44412c903586ffb414c94c", + "title": "Arithmetic Formatter" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/scientific-computing-with-python-projects/budget-app", + "blockName": "Scientific Computing with Python Projects" + }, + "id": "5e44413e903586ffb414c94e", + "title": "Budget App" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/scientific-computing-with-python-projects/polygon-area-calculator", + "blockName": "Scientific Computing with Python Projects" + }, + "id": "5e444147903586ffb414c94f", + "title": "Polygon Area Calculator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/scientific-computing-with-python-projects/probability-calculator", + "blockName": "Scientific Computing with Python Projects" + }, + "id": "5e44414f903586ffb414c950", + "title": "Probability Calculator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator", + "blockName": "Scientific Computing with Python Projects" + }, + "id": "5e444136903586ffb414c94d", + "title": "Time Calculator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/data-analysis-example-a", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c14d", + "title": "Data Analysis Example A" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/data-analysis-example-b", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c14e", + "title": "Data Analysis Example B" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/data-cleaning-and-visualizations", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c160", + "title": "Data Cleaning and Visualizations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/data-cleaning-duplicates", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c15f", + "title": "Data Cleaning Duplicates" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/data-cleaning-introduction", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c15d", + "title": "Data Cleaning Introduction" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/data-cleaning-with-dataframes", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c15e", + "title": "Data Cleaning with DataFrames" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/how-to-use-jupyter-notebooks-intro", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c14f", + "title": "How to use Jupyter Notebooks Intro" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/introduction-to-data-analysis", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c14c", + "title": "Introduction to Data Analysis" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-cells", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c150", + "title": "Jupyter Notebooks Cells" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-importing-and-exporting-data", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c151", + "title": "Jupyter Notebooks Importing and Exporting Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/numpy-algebra-and-size", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c157", + "title": "Numpy Algebra and Size" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/numpy-arrays", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c154", + "title": "Numpy Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/numpy-boolean-arrays", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c156", + "title": "Numpy Boolean Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-a", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c152", + "title": "Numpy Introduction A" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-b", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c153", + "title": "Numpy Introduction B" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/numpy-operations", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c155", + "title": "Numpy Operations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/pandas-conditional-selection-and-modifying-dataframes", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c15b", + "title": "Pandas Conditional Selection and Modifying DataFrames" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/pandas-creating-columns", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c15c", + "title": "Pandas Creating Columns" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/pandas-dataframes", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c15a", + "title": "Pandas DataFrames" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/pandas-indexing-and-conditional-selection", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c159", + "title": "Pandas Indexing and Conditional Selection" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/pandas-introduction", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c158", + "title": "Pandas Introduction" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/parsing-html-and-saving-data", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c164", + "title": "Parsing HTML and Saving Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/python-functions-and-collections", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c166", + "title": "Python Functions and Collections" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/python-introduction", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c165", + "title": "Python Introduction" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/python-iteration-and-modules", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c167", + "title": "Python Iteration and Modules" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/reading-data-csv-and-txt", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c162", + "title": "Reading Data CSV and TXT" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/reading-data-from-databases", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c163", + "title": "Reading Data from Databases" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-course/reading-data-introduction", + "blockName": "Data Analysis with Python Course" + }, + "id": "5e9a093a74c4063ca6f7c161", + "title": "Reading Data Introduction" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-projects/demographic-data-analyzer", + "blockName": "Data Analysis with Python Projects" + }, + "id": "5e46f7e5ac417301a38fb929", + "title": "Demographic Data Analyzer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-projects/mean-variance-standard-deviation-calculator", + "blockName": "Data Analysis with Python Projects" + }, + "id": "5e46f7e5ac417301a38fb928", + "title": "Mean-Variance-Standard Deviation Calculator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-projects/medical-data-visualizer", + "blockName": "Data Analysis with Python Projects" + }, + "id": "5e46f7f8ac417301a38fb92a", + "title": "Medical Data Visualizer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-projects/page-view-time-series-visualizer", + "blockName": "Data Analysis with Python Projects" + }, + "id": "5e46f802ac417301a38fb92b", + "title": "Page View Time Series Visualizer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor", + "blockName": "Data Analysis with Python Projects" + }, + "id": "5e4f5c4b570f7e3a4949899f", + "title": "Sea Level Predictor" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/accessing-and-changing-elements-rows-columns", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600ed4", + "title": "Accessing and Changing Elements, Rows, Columns" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/basics-of-numpy", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600ed3", + "title": "Basics of Numpy" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/copying-arrays-warning", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600ed7", + "title": "Copying Arrays Warning" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/initialize-array-problem", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600ed6", + "title": "Initialize Array Problem" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/initializing-different-arrays", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600ed5", + "title": "Initializing Different Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/loading-data-and-advanced-indexing", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600eda", + "title": "Loading Data and Advanced Indexing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/mathematics", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600ed8", + "title": "Mathematics" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/reorganizing-arrays", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600ed9", + "title": "Reorganizing Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/data-analysis-with-python/numpy/what-is-numpy", + "blockName": "Numpy" + }, + "id": "5e9a0a8e09c5df3cc3600ed2", + "title": "What is NumPy" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-projects/anonymous-message-board", + "blockName": "Information Security Projects" + }, + "id": "587d824a367417b2b2512c45", + "title": "Anonymous Message Board" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-projects/port-scanner", + "blockName": "Information Security Projects" + }, + "id": "5e46f979ac417301a38fb932", + "title": "Port Scanner" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-projects/secure-real-time-multiplayer-game", + "blockName": "Information Security Projects" + }, + "id": "5e601c775ac9d0ecd8b94aff", + "title": "Secure Real Time Multiplayer Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-projects/sha-1-password-cracker", + "blockName": "Information Security Projects" + }, + "id": "5e46f983ac417301a38fb933", + "title": "SHA-1 Password Cracker" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-projects/stock-price-checker", + "blockName": "Information Security Projects" + }, + "id": "587d824a367417b2b2512c44", + "title": "Stock Price Checker" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/ask-browsers-to-access-your-site-via-https-only-with-helmet-hsts", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8248367417b2b2512c3c", + "title": "Ask Browsers to Access Your Site via HTTPS Only with helmet.hsts()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/avoid-inferring-the-response-mime-type-with-helmet-nosniff", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8248367417b2b2512c3a", + "title": "Avoid Inferring the Response MIME Type with helmet.noSniff()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/configure-helmet-using-the-parent-helmet-middleware", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8249367417b2b2512c40", + "title": "Configure Helmet Using the ‘parent’ helmet() Middleware" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/disable-client-side-caching-with-helmet-nocache", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8249367417b2b2512c3e", + "title": "Disable Client-Side Caching with helmet.noCache()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/disable-dns-prefetching-with-helmet-dnsprefetchcontrol", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8248367417b2b2512c3d", + "title": "Disable DNS Prefetching with helmet.dnsPrefetchControl()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/hash-and-compare-passwords-asynchronously", + "blockName": "Information Security with HelmetJS" + }, + "id": "58a25bcff9fc0f352b528e7d", + "title": "Hash and Compare Passwords Asynchronously" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/hash-and-compare-passwords-synchronously", + "blockName": "Information Security with HelmetJS" + }, + "id": "58a25bcff9fc0f352b528e7e", + "title": "Hash and Compare Passwords Synchronously" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/hide-potentially-dangerous-information-using-helmet-hidepoweredby", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8247367417b2b2512c37", + "title": "Hide Potentially Dangerous Information Using helmet.hidePoweredBy()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/install-and-require-helmet", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8247367417b2b2512c36", + "title": "Install and Require Helmet" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/mitigate-the-risk-of-clickjacking-with-helmet-frameguard", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8247367417b2b2512c38", + "title": "Mitigate the Risk of Clickjacking with helmet.frameguard()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/mitigate-the-risk-of-cross-site-scripting-xss-attacks-with-helmet-xssfilter", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8247367417b2b2512c39", + "title": "Mitigate the Risk of Cross Site Scripting (XSS) Attacks with helmet.xssFilter()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/prevent-ie-from-opening-untrusted-html-with-helmet-ienoopen", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8248367417b2b2512c3b", + "title": "Prevent IE from Opening Untrusted HTML with helmet.ieNoOpen()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/set-a-content-security-policy-with-helmet-contentsecuritypolicy", + "blockName": "Information Security with HelmetJS" + }, + "id": "587d8249367417b2b2512c3f", + "title": "Set a Content Security Policy with helmet.contentSecurityPolicy()" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/information-security-with-helmetjs/understand-bcrypt-hashes", + "blockName": "Information Security with HelmetJS" + }, + "id": "58a25bcef9fc0f352b528e7c", + "title": "Understand BCrypt Hashes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/python-for-penetration-testing/creating-a-tcp-client", + "blockName": "Python for Penetration Testing" + }, + "id": "5ea9997bbec2e9bc47e94db0", + "title": "Creating a TCP Client" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/python-for-penetration-testing/developing-a-banner-grabber", + "blockName": "Python for Penetration Testing" + }, + "id": "5ea9997bbec2e9bc47e94db3", + "title": "Developing a Banner Grabber" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/python-for-penetration-testing/developing-a-port-scanner", + "blockName": "Python for Penetration Testing" + }, + "id": "5ea9997bbec2e9bc47e94db4", + "title": "Developing a Port Scanner" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/python-for-penetration-testing/developing-an-nmap-scanner-part-1", + "blockName": "Python for Penetration Testing" + }, + "id": "5ea9997bbec2e9bc47e94db1", + "title": "Developing an Nmap Scanner part 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/python-for-penetration-testing/developing-an-nmap-scanner-part-2", + "blockName": "Python for Penetration Testing" + }, + "id": "5ea9997bbec2e9bc47e94db2", + "title": "Developing an Nmap Scanner part 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/python-for-penetration-testing/introduction-and-setup", + "blockName": "Python for Penetration Testing" + }, + "id": "5ea9997bbec2e9bc47e94dae", + "title": "Introduction and Setup" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/information-security/python-for-penetration-testing/understanding-sockets-and-creating-a-tcp-server", + "blockName": "Python for Penetration Testing" + }, + "id": "5ea9997bbec2e9bc47e94daf", + "title": "Understanding Sockets and Creating a TCP Server" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/find-the-symmetric-difference", + "blockName": "Algorithms" + }, + "id": "a3f503de51cf954ede28891d", + "title": "Find the Symmetric Difference" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/implement-binary-search", + "blockName": "Algorithms" + }, + "id": "61abc7ebf3029b56226de5b6", + "title": "Implement Binary Search" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/implement-bubble-sort", + "blockName": "Algorithms" + }, + "id": "8d5123c8c441eddfaeb5bdef", + "title": "Implement Bubble Sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/implement-insertion-sort", + "blockName": "Algorithms" + }, + "id": "587d8259367417b2b2512c86", + "title": "Implement Insertion Sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/implement-merge-sort", + "blockName": "Algorithms" + }, + "id": "587d825c367417b2b2512c8f", + "title": "Implement Merge Sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/implement-quick-sort", + "blockName": "Algorithms" + }, + "id": "587d825a367417b2b2512c89", + "title": "Implement Quick Sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/implement-selection-sort", + "blockName": "Algorithms" + }, + "id": "587d8259367417b2b2512c85", + "title": "Implement Selection Sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/inventory-update", + "blockName": "Algorithms" + }, + "id": "a56138aff60341a09ed6c480", + "title": "Inventory Update" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/no-repeats-please", + "blockName": "Algorithms" + }, + "id": "a7bf700cd123b9a54eef01d5", + "title": "No Repeats Please" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/algorithms/pairwise", + "blockName": "Algorithms" + }, + "id": "a3f503de51cfab748ff001aa", + "title": "Pairwise" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/add-a-new-element-to-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8257367417b2b2512c7b", + "title": "Add a New Element to a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/add-elements-at-a-specific-index-in-a-linked-list", + "blockName": "Data Structures" + }, + "id": "587d8252367417b2b2512c67", + "title": "Add Elements at a Specific Index in a Linked List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/adjacency-list", + "blockName": "Data Structures" + }, + "id": "587d8256367417b2b2512c77", + "title": "Adjacency List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/adjacency-matrix", + "blockName": "Data Structures" + }, + "id": "587d8256367417b2b2512c78", + "title": "Adjacency Matrix" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/breadth-first-search", + "blockName": "Data Structures" + }, + "id": "587d825c367417b2b2512c90", + "title": "Breadth-First Search" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/check-if-an-element-is-present-in-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8257367417b2b2512c7c", + "title": "Check if an Element is Present in a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/check-if-tree-is-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "5cc0c1b32479e176caf3b422", + "title": "Check if Tree is Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-circular-queue", + "blockName": "Data Structures" + }, + "id": "587d8255367417b2b2512c75", + "title": "Create a Circular Queue" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-doubly-linked-list", + "blockName": "Data Structures" + }, + "id": "587d825a367417b2b2512c87", + "title": "Create a Doubly Linked List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-hash-table", + "blockName": "Data Structures" + }, + "id": "587d825b367417b2b2512c8e", + "title": "Create a Hash Table" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-linked-list-class", + "blockName": "Data Structures" + }, + "id": "587d8251367417b2b2512c62", + "title": "Create a Linked List Class" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-map-data-structure", + "blockName": "Data Structures" + }, + "id": "8d5823c8c441eddfaeb5bdef", + "title": "Create a Map Data Structure" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-priority-queue-class", + "blockName": "Data Structures" + }, + "id": "587d8255367417b2b2512c74", + "title": "Create a Priority Queue Class" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-queue-class", + "blockName": "Data Structures" + }, + "id": "587d8250367417b2b2512c60", + "title": "Create a Queue Class" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-set-class", + "blockName": "Data Structures" + }, + "id": "8d1323c8c441eddfaeb5bdef", + "title": "Create a Set Class" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-stack-class", + "blockName": "Data Structures" + }, + "id": "587d8250367417b2b2512c5f", + "title": "Create a Stack Class" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-a-trie-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8259367417b2b2512c84", + "title": "Create a Trie Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-an-es6-javascript-map", + "blockName": "Data Structures" + }, + "id": "587d825b367417b2b2512c8d", + "title": "Create an ES6 JavaScript Map" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/create-and-add-to-sets-in-es6", + "blockName": "Data Structures" + }, + "id": "587d8254367417b2b2512c70", + "title": "Create and Add to Sets in ES6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/delete-a-leaf-node-in-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8258367417b2b2512c80", + "title": "Delete a Leaf Node in a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/delete-a-node-with-one-child-in-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8258367417b2b2512c81", + "title": "Delete a Node with One Child in a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/delete-a-node-with-two-children-in-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8258367417b2b2512c82", + "title": "Delete a Node with Two Children in a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/depth-first-search", + "blockName": "Data Structures" + }, + "id": "587d825d367417b2b2512c96", + "title": "Depth-First Search" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/find-the-minimum-and-maximum-height-of-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8257367417b2b2512c7d", + "title": "Find the Minimum and Maximum Height of a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/find-the-minimum-and-maximum-value-in-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8256367417b2b2512c7a", + "title": "Find the Minimum and Maximum Value in a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/implement-heap-sort-with-a-min-heap", + "blockName": "Data Structures" + }, + "id": "587d825b367417b2b2512c8c", + "title": "Implement Heap Sort with a Min Heap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/incidence-matrix", + "blockName": "Data Structures" + }, + "id": "587d8256367417b2b2512c79", + "title": "Incidence Matrix" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/insert-an-element-into-a-max-heap", + "blockName": "Data Structures" + }, + "id": "587d825a367417b2b2512c8a", + "title": "Insert an Element into a Max Heap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/invert-a-binary-tree", + "blockName": "Data Structures" + }, + "id": "587d8259367417b2b2512c83", + "title": "Invert a Binary Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/learn-how-a-stack-works", + "blockName": "Data Structures" + }, + "id": "587d8250367417b2b2512c5e", + "title": "Learn how a Stack Works" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/perform-a-difference-on-two-sets-of-data", + "blockName": "Data Structures" + }, + "id": "587d8254367417b2b2512c6e", + "title": "Perform a Difference on Two Sets of Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/perform-a-subset-check-on-two-sets-of-data", + "blockName": "Data Structures" + }, + "id": "587d8254367417b2b2512c6f", + "title": "Perform a Subset Check on Two Sets of Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/perform-a-union-on-two-sets", + "blockName": "Data Structures" + }, + "id": "587d8253367417b2b2512c6c", + "title": "Perform a Union on Two Sets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/perform-an-intersection-on-two-sets-of-data", + "blockName": "Data Structures" + }, + "id": "587d8253367417b2b2512c6d", + "title": "Perform an Intersection on Two Sets of Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/remove-an-element-from-a-max-heap", + "blockName": "Data Structures" + }, + "id": "587d825b367417b2b2512c8b", + "title": "Remove an Element from a Max Heap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/remove-elements-from-a-linked-list-by-index", + "blockName": "Data Structures" + }, + "id": "587d8251367417b2b2512c65", + "title": "Remove Elements from a Linked List by Index" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/remove-elements-from-a-linked-list", + "blockName": "Data Structures" + }, + "id": "587d8251367417b2b2512c63", + "title": "Remove Elements from a Linked List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/remove-items-from-a-set-in-es6", + "blockName": "Data Structures" + }, + "id": "587d8254367417b2b2512c71", + "title": "Remove items from a set in ES6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/reverse-a-doubly-linked-list", + "blockName": "Data Structures" + }, + "id": "587d825a367417b2b2512c88", + "title": "Reverse a Doubly Linked List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/search-within-a-linked-list", + "blockName": "Data Structures" + }, + "id": "587d8251367417b2b2512c64", + "title": "Search within a Linked List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/typed-arrays", + "blockName": "Data Structures" + }, + "id": "587d8253367417b2b2512c6a", + "title": "Typed Arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/use--has-and--size-on-an-es6-set", + "blockName": "Data Structures" + }, + "id": "587d8255367417b2b2512c72", + "title": "Use .has and .size on an ES6 Set" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/use-breadth-first-search-in-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8258367417b2b2512c7f", + "title": "Use Breadth First Search in a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/use-depth-first-search-in-a-binary-search-tree", + "blockName": "Data Structures" + }, + "id": "587d8257367417b2b2512c7e", + "title": "Use Depth First Search in a Binary Search Tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/use-spread-and-notes-for-es5-set-integration", + "blockName": "Data Structures" + }, + "id": "587d8255367417b2b2512c73", + "title": "Use Spread and Notes for ES5 Set() Integration" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/data-structures/work-with-nodes-in-a-linked-list", + "blockName": "Data Structures" + }, + "id": "587d8251367417b2b2512c61", + "title": "Work with Nodes in a Linked List" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-1-multiples-of-3-and-5", + "blockName": "Project Euler" + }, + "id": "5900f36e1000cf542c50fe80", + "title": "Problem 1: Multiples of 3 and 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-10-summation-of-primes", + "blockName": "Project Euler" + }, + "id": "5900f3761000cf542c50fe89", + "title": "Problem 10: Summation of primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-100-arranged-probability", + "blockName": "Project Euler" + }, + "id": "5900f3d01000cf542c50fee3", + "title": "Problem 100: Arranged probability" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-101-optimum-polynomial", + "blockName": "Project Euler" + }, + "id": "5900f3d21000cf542c50fee4", + "title": "Problem 101: Optimum polynomial" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-102-triangle-containment", + "blockName": "Project Euler" + }, + "id": "5900f3d21000cf542c50fee5", + "title": "Problem 102: Triangle containment" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-103-special-subset-sums-optimum", + "blockName": "Project Euler" + }, + "id": "5900f3d61000cf542c50fee7", + "title": "Problem 103: Special subset sums: optimum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-104-pandigital-fibonacci-ends", + "blockName": "Project Euler" + }, + "id": "5900f3d51000cf542c50fee6", + "title": "Problem 104: Pandigital Fibonacci ends" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-105-special-subset-sums-testing", + "blockName": "Project Euler" + }, + "id": "5900f3d61000cf542c50fee8", + "title": "Problem 105: Special subset sums: testing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-106-special-subset-sums-meta-testing", + "blockName": "Project Euler" + }, + "id": "5900f3d71000cf542c50fee9", + "title": "Problem 106: Special subset sums: meta-testing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-107-minimal-network", + "blockName": "Project Euler" + }, + "id": "5900f3d91000cf542c50feea", + "title": "Problem 107: Minimal network" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-108-diophantine-reciprocals-i", + "blockName": "Project Euler" + }, + "id": "5900f3d91000cf542c50feeb", + "title": "Problem 108: Diophantine Reciprocals I" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-109-darts", + "blockName": "Project Euler" + }, + "id": "5900f3db1000cf542c50feec", + "title": "Problem 109: Darts" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-11-largest-product-in-a-grid", + "blockName": "Project Euler" + }, + "id": "5900f3781000cf542c50fe8a", + "title": "Problem 11: Largest product in a grid" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-110-diophantine-reciprocals-ii", + "blockName": "Project Euler" + }, + "id": "5900f3db1000cf542c50feed", + "title": "Problem 110: Diophantine Reciprocals II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-111-primes-with-runs", + "blockName": "Project Euler" + }, + "id": "5900f3db1000cf542c50feee", + "title": "Problem 111: Primes with runs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-112-bouncy-numbers", + "blockName": "Project Euler" + }, + "id": "5900f3dd1000cf542c50feef", + "title": "Problem 112: Bouncy numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-113-non-bouncy-numbers", + "blockName": "Project Euler" + }, + "id": "5900f3dd1000cf542c50fef0", + "title": "Problem 113: Non-bouncy numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-114-counting-block-combinations-i", + "blockName": "Project Euler" + }, + "id": "5900f3e01000cf542c50fef2", + "title": "Problem 114: Counting block combinations I" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-115-counting-block-combinations-ii", + "blockName": "Project Euler" + }, + "id": "5900f3df1000cf542c50fef1", + "title": "Problem 115: Counting block combinations II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-116-red-green-or-blue-tiles", + "blockName": "Project Euler" + }, + "id": "5900f3e01000cf542c50fef3", + "title": "Problem 116: Red, green or blue tiles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-117-red-green-and-blue-tiles", + "blockName": "Project Euler" + }, + "id": "5900f3e21000cf542c50fef4", + "title": "Problem 117: Red, green, and blue tiles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-118-pandigital-prime-sets", + "blockName": "Project Euler" + }, + "id": "5900f3e21000cf542c50fef5", + "title": "Problem 118: Pandigital prime sets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-119-digit-power-sum", + "blockName": "Project Euler" + }, + "id": "5900f3e41000cf542c50fef6", + "title": "Problem 119: Digit power sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-12-highly-divisible-triangular-number", + "blockName": "Project Euler" + }, + "id": "5900f3781000cf542c50fe8b", + "title": "Problem 12: Highly divisible triangular number" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-120-square-remainders", + "blockName": "Project Euler" + }, + "id": "5900f3e41000cf542c50fef7", + "title": "Problem 120: Square remainders" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-121-disc-game-prize-fund", + "blockName": "Project Euler" + }, + "id": "5900f3e51000cf542c50fef8", + "title": "Problem 121: Disc game prize fund" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-122-efficient-exponentiation", + "blockName": "Project Euler" + }, + "id": "5900f3e61000cf542c50fef9", + "title": "Problem 122: Efficient exponentiation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-123-prime-square-remainders", + "blockName": "Project Euler" + }, + "id": "5900f3e71000cf542c50fefa", + "title": "Problem 123: Prime square remainders" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-124-ordered-radicals", + "blockName": "Project Euler" + }, + "id": "5900f3e81000cf542c50fefb", + "title": "Problem 124: Ordered radicals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-125-palindromic-sums", + "blockName": "Project Euler" + }, + "id": "5900f3e91000cf542c50fefc", + "title": "Problem 125: Palindromic sums" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-126-cuboid-layers", + "blockName": "Project Euler" + }, + "id": "5900f3ea1000cf542c50fefd", + "title": "Problem 126: Cuboid layers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-127-abc-hits", + "blockName": "Project Euler" + }, + "id": "5900f3ec1000cf542c50fefe", + "title": "Problem 127: abc-hits" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-128-hexagonal-tile-differences", + "blockName": "Project Euler" + }, + "id": "5900f3ec1000cf542c50feff", + "title": "Problem 128: Hexagonal tile differences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-129-repunit-divisibility", + "blockName": "Project Euler" + }, + "id": "5900f3ef1000cf542c50ff01", + "title": "Problem 129: Repunit divisibility" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-13-large-sum", + "blockName": "Project Euler" + }, + "id": "5900f37a1000cf542c50fe8c", + "title": "Problem 13: Large sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-130-composites-with-prime-repunit-property", + "blockName": "Project Euler" + }, + "id": "5900f3ee1000cf542c50ff00", + "title": "Problem 130: Composites with prime repunit property" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-131-prime-cube-partnership", + "blockName": "Project Euler" + }, + "id": "5900f3ef1000cf542c50ff02", + "title": "Problem 131: Prime cube partnership" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-132-large-repunit-factors", + "blockName": "Project Euler" + }, + "id": "5900f3f11000cf542c50ff03", + "title": "Problem 132: Large repunit factors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-133-repunit-nonfactors", + "blockName": "Project Euler" + }, + "id": "5900f3f21000cf542c50ff04", + "title": "Problem 133: Repunit nonfactors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-134-prime-pair-connection", + "blockName": "Project Euler" + }, + "id": "5900f3f21000cf542c50ff05", + "title": "Problem 134: Prime pair connection" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-135-same-differences", + "blockName": "Project Euler" + }, + "id": "5900f3f31000cf542c50ff06", + "title": "Problem 135: Same differences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-136-singleton-difference", + "blockName": "Project Euler" + }, + "id": "5900f3f51000cf542c50ff07", + "title": "Problem 136: Singleton difference" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-137-fibonacci-golden-nuggets", + "blockName": "Project Euler" + }, + "id": "5900f3f51000cf542c50ff08", + "title": "Problem 137: Fibonacci golden nuggets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-138-special-isosceles-triangles", + "blockName": "Project Euler" + }, + "id": "5900f3f61000cf542c50ff09", + "title": "Problem 138: Special isosceles triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-139-pythagorean-tiles", + "blockName": "Project Euler" + }, + "id": "5900f3f71000cf542c50ff0a", + "title": "Problem 139: Pythagorean tiles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-14-longest-collatz-sequence", + "blockName": "Project Euler" + }, + "id": "5900f37a1000cf542c50fe8d", + "title": "Problem 14: Longest Collatz sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-140-modified-fibonacci-golden-nuggets", + "blockName": "Project Euler" + }, + "id": "5900f3fa1000cf542c50ff0c", + "title": "Problem 140: Modified Fibonacci golden nuggets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-141-investigating-progressive-numbers-n-which-are-also-square", + "blockName": "Project Euler" + }, + "id": "5900f3f91000cf542c50ff0b", + "title": "Problem 141: Investigating progressive numbers, n, which are also square" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-142-perfect-square-collection", + "blockName": "Project Euler" + }, + "id": "5900f3fa1000cf542c50ff0d", + "title": "Problem 142: Perfect Square Collection" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-143-investigating-the-torricelli-point-of-a-triangle", + "blockName": "Project Euler" + }, + "id": "5900f3fc1000cf542c50ff0e", + "title": "Problem 143: Investigating the Torricelli point of a triangle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-144-investigating-multiple-reflections-of-a-laser-beam", + "blockName": "Project Euler" + }, + "id": "5900f3fc1000cf542c50ff0f", + "title": "Problem 144: Investigating multiple reflections of a laser beam" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-145-how-many-reversible-numbers-are-there-below-one-billion", + "blockName": "Project Euler" + }, + "id": "5900f3fd1000cf542c50ff10", + "title": "Problem 145: How many reversible numbers are there below one-billion?" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-146-investigating-a-prime-pattern", + "blockName": "Project Euler" + }, + "id": "5900f3fe1000cf542c50ff11", + "title": "Problem 146: Investigating a Prime Pattern" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-147-rectangles-in-cross-hatched-grids", + "blockName": "Project Euler" + }, + "id": "5900f3ff1000cf542c50ff12", + "title": "Problem 147: Rectangles in cross-hatched grids" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-148-exploring-pascals-triangle", + "blockName": "Project Euler" + }, + "id": "5900f4021000cf542c50ff14", + "title": "Problem 148: Exploring Pascal's triangle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-149-searching-for-a-maximum-sum-subsequence", + "blockName": "Project Euler" + }, + "id": "5900f4021000cf542c50ff13", + "title": "Problem 149: Searching for a maximum-sum subsequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-15-lattice-paths", + "blockName": "Project Euler" + }, + "id": "5900f37b1000cf542c50fe8e", + "title": "Problem 15: Lattice paths" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-150-searching-a-triangular-array-for-a-sub-triangle-having-minimum-sum", + "blockName": "Project Euler" + }, + "id": "5900f4031000cf542c50ff15", + "title": "Problem 150: Searching a triangular array for a sub-triangle having minimum-sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-151-paper-sheets-of-standard-sizes-an-expected-value-problem", + "blockName": "Project Euler" + }, + "id": "5900f4031000cf542c50ff16", + "title": "Problem 151: Paper sheets of standard sizes: an expected-value problem" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-152-writing-one-half-as-a-sum-of-inverse-squares", + "blockName": "Project Euler" + }, + "id": "5900f4041000cf542c50ff17", + "title": "Problem 152: Writing one half as a sum of inverse squares" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-153-investigating-gaussian-integers", + "blockName": "Project Euler" + }, + "id": "5900f4051000cf542c50ff18", + "title": "Problem 153: Investigating Gaussian Integers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-154-exploring-pascals-pyramid", + "blockName": "Project Euler" + }, + "id": "5900f4071000cf542c50ff19", + "title": "Problem 154: Exploring Pascal's pyramid" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-155-counting-capacitor-circuits", + "blockName": "Project Euler" + }, + "id": "5900f4081000cf542c50ff1a", + "title": "Problem 155: Counting Capacitor Circuits" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-156-counting-digits", + "blockName": "Project Euler" + }, + "id": "5900f4091000cf542c50ff1b", + "title": "Problem 156: Counting Digits" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-157-solving-the-diophantine-equation", + "blockName": "Project Euler" + }, + "id": "5900f4091000cf542c50ff1c", + "title": "Problem 157: Solving the diophantine equation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-158-exploring-strings-for-which-only-one-character-comes-lexicographically-after-its-neighbour-to-the-left", + "blockName": "Project Euler" + }, + "id": "5900f40a1000cf542c50ff1d", + "title": "Problem 158: Exploring strings for which only one character comes lexicographically after its neighbour to the left" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-159-digital-root-sums-of-factorisations", + "blockName": "Project Euler" + }, + "id": "5900f40c1000cf542c50ff1e", + "title": "Problem 159: Digital root sums of factorisations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-16-power-digit-sum", + "blockName": "Project Euler" + }, + "id": "5900f37d1000cf542c50fe8f", + "title": "Problem 16: Power digit sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-160-factorial-trailing-digits", + "blockName": "Project Euler" + }, + "id": "5900f40d1000cf542c50ff1f", + "title": "Problem 160: Factorial trailing digits" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-161-triominoes", + "blockName": "Project Euler" + }, + "id": "5900f40d1000cf542c50ff20", + "title": "Problem 161: Triominoes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-162-hexadecimal-numbers", + "blockName": "Project Euler" + }, + "id": "5900f40e1000cf542c50ff21", + "title": "Problem 162: Hexadecimal numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-163-cross-hatched-triangles", + "blockName": "Project Euler" + }, + "id": "5900f40f1000cf542c50ff22", + "title": "Problem 163: Cross-hatched triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-164-numbers-for-which-no-three-consecutive-digits-have-a-sum-greater-than-a-given-value", + "blockName": "Project Euler" + }, + "id": "5900f4111000cf542c50ff23", + "title": "Problem 164: Numbers for which no three consecutive digits have a sum greater than a given value" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-165-intersections", + "blockName": "Project Euler" + }, + "id": "5900f4111000cf542c50ff24", + "title": "Problem 165: Intersections" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-166-criss-cross", + "blockName": "Project Euler" + }, + "id": "5900f4131000cf542c50ff25", + "title": "Problem 166: Criss Cross" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-167-investigating-ulam-sequences", + "blockName": "Project Euler" + }, + "id": "5900f4141000cf542c50ff26", + "title": "Problem 167: Investigating Ulam sequences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-168-number-rotations", + "blockName": "Project Euler" + }, + "id": "5900f4151000cf542c50ff27", + "title": "Problem 168: Number Rotations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-169-exploring-the-number-of-different-ways-a-number-can-be-expressed-as-a-sum-of-powers-of-2", + "blockName": "Project Euler" + }, + "id": "5900f4151000cf542c50ff28", + "title": "Problem 169: Exploring the number of different ways a number can be expressed as a sum of powers of 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-17-number-letter-counts", + "blockName": "Project Euler" + }, + "id": "5900f37d1000cf542c50fe90", + "title": "Problem 17: Number letter counts" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-170-find-the-largest-0-to-9-pandigital-that-can-be-formed-by-concatenating-products", + "blockName": "Project Euler" + }, + "id": "5900f4161000cf542c50ff29", + "title": "Problem 170: Find the largest 0 to 9 pandigital that can be formed by concatenating products" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-171-finding-numbers-for-which-the-sum-of-the-squares-of-the-digits-is-a-square", + "blockName": "Project Euler" + }, + "id": "5900f4181000cf542c50ff2a", + "title": "Problem 171: Finding numbers for which the sum of the squares of the digits is a square" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-172-investigating-numbers-with-few-repeated-digits", + "blockName": "Project Euler" + }, + "id": "5900f4181000cf542c50ff2b", + "title": "Problem 172: Investigating numbers with few repeated digits" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-173-using-up-to-one-million-tiles-how-many-different-hollow-square-laminae-can-be-formed", + "blockName": "Project Euler" + }, + "id": "5900f41a1000cf542c50ff2c", + "title": "Problem 173: Using up to one million tiles how many different \"hollow\" square laminae can be formed?" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-174-counting-the-number-of-hollow-square-laminae-that-can-form-one-two-three-----distinct-arrangements", + "blockName": "Project Euler" + }, + "id": "5900f41a1000cf542c50ff2d", + "title": "Problem 174: Counting the number of \"hollow\" square laminae that can form one, two, three, ... distinct arrangements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-175-fractions-involving-the-number-of-different-ways-a-number-can-be-expressed-as-a-sum-of-powers-of-2", + "blockName": "Project Euler" + }, + "id": "5900f41c1000cf542c50ff2e", + "title": "Problem 175: Fractions involving the number of different ways a number can be expressed as a sum of powers of 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-176-right-angled-triangles-that-share-a-cathetus", + "blockName": "Project Euler" + }, + "id": "5900f41c1000cf542c50ff2f", + "title": "Problem 176: Right-angled triangles that share a cathetus" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-177-integer-angled-quadrilaterals", + "blockName": "Project Euler" + }, + "id": "5900f41e1000cf542c50ff30", + "title": "Problem 177: Integer angled Quadrilaterals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-178-step-numbers", + "blockName": "Project Euler" + }, + "id": "5900f41e1000cf542c50ff31", + "title": "Problem 178: Step Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-179-consecutive-positive-divisors", + "blockName": "Project Euler" + }, + "id": "5900f41f1000cf542c50ff32", + "title": "Problem 179: Consecutive positive divisors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-18-maximum-path-sum-i", + "blockName": "Project Euler" + }, + "id": "5900f37e1000cf542c50fe91", + "title": "Problem 18: Maximum path sum I" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-180-rational-zeros-of-a-function-of-three-variables", + "blockName": "Project Euler" + }, + "id": "5900f4201000cf542c50ff33", + "title": "Problem 180: Rational zeros of a function of three variables" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-181-investigating-in-how-many-ways-objects-of-two-different-colours-can-be-grouped", + "blockName": "Project Euler" + }, + "id": "5900f4231000cf542c50ff34", + "title": "Problem 181: Investigating in how many ways objects of two different colours can be grouped" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-182-rsa-encryption", + "blockName": "Project Euler" + }, + "id": "5900f4231000cf542c50ff35", + "title": "Problem 182: RSA encryption" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-183-maximum-product-of-parts", + "blockName": "Project Euler" + }, + "id": "5900f4231000cf542c50ff36", + "title": "Problem 183: Maximum product of parts" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-184-triangles-containing-the-origin", + "blockName": "Project Euler" + }, + "id": "5900f4241000cf542c50ff37", + "title": "Problem 184: Triangles containing the origin" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-185-number-mind", + "blockName": "Project Euler" + }, + "id": "5900f4251000cf542c50ff38", + "title": "Problem 185: Number Mind" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-186-connectedness-of-a-network", + "blockName": "Project Euler" + }, + "id": "5900f4281000cf542c50ff39", + "title": "Problem 186: Connectedness of a network" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-187-semiprimes", + "blockName": "Project Euler" + }, + "id": "5900f4291000cf542c50ff3a", + "title": "Problem 187: Semiprimes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-188-the-hyperexponentiation-of-a-number", + "blockName": "Project Euler" + }, + "id": "5900f4291000cf542c50ff3b", + "title": "Problem 188: The hyperexponentiation of a number" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-189-tri-colouring-a-triangular-grid", + "blockName": "Project Euler" + }, + "id": "5900f4291000cf542c50ff3c", + "title": "Problem 189: Tri-colouring a triangular grid" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-19-counting-sundays", + "blockName": "Project Euler" + }, + "id": "5900f37f1000cf542c50fe92", + "title": "Problem 19: Counting Sundays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-190-maximising-a-weighted-product", + "blockName": "Project Euler" + }, + "id": "5900f42b1000cf542c50ff3d", + "title": "Problem 190: Maximising a weighted product" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-191-prize-strings", + "blockName": "Project Euler" + }, + "id": "5900f42b1000cf542c50ff3e", + "title": "Problem 191: Prize Strings" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-192-best-approximations", + "blockName": "Project Euler" + }, + "id": "5900f42c1000cf542c50ff3f", + "title": "Problem 192: Best Approximations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-193-squarefree-numbers", + "blockName": "Project Euler" + }, + "id": "5900f42f1000cf542c50ff41", + "title": "Problem 193: Squarefree Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-194-coloured-configurations", + "blockName": "Project Euler" + }, + "id": "5900f42f1000cf542c50ff40", + "title": "Problem 194: Coloured Configurations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-195-inscribed-circles-of-triangles-with-one-angle-of-60-degrees", + "blockName": "Project Euler" + }, + "id": "5900f4311000cf542c50ff43", + "title": "Problem 195: Inscribed circles of triangles with one angle of 60 degrees" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-196-prime-triplets", + "blockName": "Project Euler" + }, + "id": "5900f4301000cf542c50ff42", + "title": "Problem 196: Prime triplets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-197-investigating-the-behaviour-of-a-recursively-defined-sequence", + "blockName": "Project Euler" + }, + "id": "5900f4311000cf542c50ff44", + "title": "Problem 197: Investigating the behaviour of a recursively defined sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-198-ambiguous-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4331000cf542c50ff45", + "title": "Problem 198: Ambiguous Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-199-iterative-circle-packing", + "blockName": "Project Euler" + }, + "id": "5900f4341000cf542c50ff46", + "title": "Problem 199: Iterative Circle Packing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-2-even-fibonacci-numbers", + "blockName": "Project Euler" + }, + "id": "5900f36e1000cf542c50fe81", + "title": "Problem 2: Even Fibonacci Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-20-factorial-digit-sum", + "blockName": "Project Euler" + }, + "id": "5900f3801000cf542c50fe93", + "title": "Problem 20: Factorial digit sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-200-find-the-200th-prime-proof-sqube-containing-the-contiguous-sub-string-200", + "blockName": "Project Euler" + }, + "id": "5900f4351000cf542c50ff47", + "title": "Problem 200: Find the 200th prime-proof sqube containing the contiguous sub-string \"200\"" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-201-subsets-with-a-unique-sum", + "blockName": "Project Euler" + }, + "id": "5900f4361000cf542c50ff48", + "title": "Problem 201: Subsets with a unique sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-202-laserbeam", + "blockName": "Project Euler" + }, + "id": "5900f4371000cf542c50ff49", + "title": "Problem 202: Laserbeam" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-203-squarefree-binomial-coefficients", + "blockName": "Project Euler" + }, + "id": "5900f4381000cf542c50ff4a", + "title": "Problem 203: Squarefree Binomial Coefficients" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-204-generalised-hamming-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4381000cf542c50ff4b", + "title": "Problem 204: Generalised Hamming Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-205-dice-game", + "blockName": "Project Euler" + }, + "id": "5900f4391000cf542c50ff4c", + "title": "Problem 205: Dice Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-206-concealed-square", + "blockName": "Project Euler" + }, + "id": "5900f43a1000cf542c50ff4d", + "title": "Problem 206: Concealed Square" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-207-integer-partition-equations", + "blockName": "Project Euler" + }, + "id": "5900f43c1000cf542c50ff4e", + "title": "Problem 207: Integer partition equations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-208-robot-walks", + "blockName": "Project Euler" + }, + "id": "5900f43f1000cf542c50ff51", + "title": "Problem 208: Robot Walks" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-209-circular-logic", + "blockName": "Project Euler" + }, + "id": "5900f43e1000cf542c50ff4f", + "title": "Problem 209: Circular Logic" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-21-amicable-numbers", + "blockName": "Project Euler" + }, + "id": "5900f3811000cf542c50fe94", + "title": "Problem 21: Amicable numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-210-obtuse-angled-triangles", + "blockName": "Project Euler" + }, + "id": "5900f43e1000cf542c50ff50", + "title": "Problem 210: Obtuse Angled Triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-211-divisor-square-sum", + "blockName": "Project Euler" + }, + "id": "5900f43f1000cf542c50ff52", + "title": "Problem 211: Divisor Square Sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-212-combined-volume-of-cuboids", + "blockName": "Project Euler" + }, + "id": "5900f4411000cf542c50ff53", + "title": "Problem 212: Combined Volume of Cuboids" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-213-flea-circus", + "blockName": "Project Euler" + }, + "id": "5900f4411000cf542c50ff54", + "title": "Problem 213: Flea Circus" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-214-totient-chains", + "blockName": "Project Euler" + }, + "id": "5900f4421000cf542c50ff55", + "title": "Problem 214: Totient Chains" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-215-crack-free-walls", + "blockName": "Project Euler" + }, + "id": "5900f4431000cf542c50ff56", + "title": "Problem 215: Crack-free Walls" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-216-investigating-the-primality-of-numbers-of-the-form-2n2-1", + "blockName": "Project Euler" + }, + "id": "5900f4451000cf542c50ff57", + "title": "Problem 216: Investigating the primality of numbers of the form 2n2-1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-217-balanced-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4461000cf542c50ff58", + "title": "Problem 217: Balanced Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-218-perfect-right-angled-triangles", + "blockName": "Project Euler" + }, + "id": "5900f4461000cf542c50ff59", + "title": "Problem 218: Perfect right-angled triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-219-skew-cost-coding", + "blockName": "Project Euler" + }, + "id": "5900f4481000cf542c50ff5a", + "title": "Problem 219: Skew-cost coding" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-22-names-scores", + "blockName": "Project Euler" + }, + "id": "5a51eabcad78bf416f316e2a", + "title": "Problem 22: Names scores" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-220-heighway-dragon", + "blockName": "Project Euler" + }, + "id": "5900f4481000cf542c50ff5b", + "title": "Problem 220: Heighway Dragon" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-221-alexandrian-integers", + "blockName": "Project Euler" + }, + "id": "5900f4491000cf542c50ff5c", + "title": "Problem 221: Alexandrian Integers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-222-sphere-packing", + "blockName": "Project Euler" + }, + "id": "5900f44b1000cf542c50ff5d", + "title": "Problem 222: Sphere Packing" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-223-almost-right-angled-triangles-i", + "blockName": "Project Euler" + }, + "id": "5900f44b1000cf542c50ff5e", + "title": "Problem 223: Almost right-angled triangles I" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-224-almost-right-angled-triangles-ii", + "blockName": "Project Euler" + }, + "id": "5900f44e1000cf542c50ff5f", + "title": "Problem 224: Almost right-angled triangles II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-225-tribonacci-non-divisors", + "blockName": "Project Euler" + }, + "id": "5900f44e1000cf542c50ff60", + "title": "Problem 225: Tribonacci non-divisors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-226-a-scoop-of-blancmange", + "blockName": "Project Euler" + }, + "id": "5900f4511000cf542c50ff62", + "title": "Problem 226: A Scoop of Blancmange" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-227-the-chase", + "blockName": "Project Euler" + }, + "id": "5900f44f1000cf542c50ff61", + "title": "Problem 227: The Chase" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-228-minkowski-sums", + "blockName": "Project Euler" + }, + "id": "5900f4511000cf542c50ff63", + "title": "Problem 228: Minkowski Sums" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-229-four-representations-using-squares", + "blockName": "Project Euler" + }, + "id": "5900f4521000cf542c50ff64", + "title": "Problem 229: Four Representations using Squares" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-23-non-abundant-sums", + "blockName": "Project Euler" + }, + "id": "5900f3831000cf542c50fe96", + "title": "Problem 23: Non-abundant sums" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-230-fibonacci-words", + "blockName": "Project Euler" + }, + "id": "5900f4531000cf542c50ff65", + "title": "Problem 230: Fibonacci Words" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-231-the-prime-factorisation-of-binomial-coefficients", + "blockName": "Project Euler" + }, + "id": "5900f4531000cf542c50ff66", + "title": "Problem 231: The prime factorisation of binomial coefficients" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-232-the-race", + "blockName": "Project Euler" + }, + "id": "5900f4551000cf542c50ff67", + "title": "Problem 232: The Race" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-233-lattice-points-on-a-circle", + "blockName": "Project Euler" + }, + "id": "5900f4551000cf542c50ff68", + "title": "Problem 233: Lattice points on a circle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-234-semidivisible-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4571000cf542c50ff69", + "title": "Problem 234: Semidivisible numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-235-an-arithmetic-geometric-sequence", + "blockName": "Project Euler" + }, + "id": "5900f4571000cf542c50ff6a", + "title": "Problem 235: An Arithmetic Geometric sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-236-luxury-hampers", + "blockName": "Project Euler" + }, + "id": "5900f4591000cf542c50ff6b", + "title": "Problem 236: Luxury Hampers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-237-tours-on-a-4-x-n-playing-board", + "blockName": "Project Euler" + }, + "id": "5900f4591000cf542c50ff6c", + "title": "Problem 237: Tours on a 4 x n playing board" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-238-infinite-string-tour", + "blockName": "Project Euler" + }, + "id": "5900f45b1000cf542c50ff6d", + "title": "Problem 238: Infinite string tour" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-239-twenty-two-foolish-primes", + "blockName": "Project Euler" + }, + "id": "5900f45c1000cf542c50ff6e", + "title": "Problem 239: Twenty-two Foolish Primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-24-lexicographic-permutations", + "blockName": "Project Euler" + }, + "id": "5900f3841000cf542c50fe97", + "title": "Problem 24: Lexicographic permutations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-240-top-dice", + "blockName": "Project Euler" + }, + "id": "5900f45d1000cf542c50ff6f", + "title": "Problem 240: Top Dice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-241-perfection-quotients", + "blockName": "Project Euler" + }, + "id": "5900f45d1000cf542c50ff70", + "title": "Problem 241: Perfection Quotients" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-242-odd-triplets", + "blockName": "Project Euler" + }, + "id": "5900f45f1000cf542c50ff71", + "title": "Problem 242: Odd Triplets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-243-resilience", + "blockName": "Project Euler" + }, + "id": "5900f4601000cf542c50ff73", + "title": "Problem 243: Resilience" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-244-sliders", + "blockName": "Project Euler" + }, + "id": "5900f4601000cf542c50ff72", + "title": "Problem 244: Sliders" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-245-coresilience", + "blockName": "Project Euler" + }, + "id": "5900f4621000cf542c50ff74", + "title": "Problem 245: Coresilience" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-246-tangents-to-an-ellipse", + "blockName": "Project Euler" + }, + "id": "5900f4621000cf542c50ff75", + "title": "Problem 246: Tangents to an ellipse" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-247-squares-under-a-hyperbola", + "blockName": "Project Euler" + }, + "id": "5900f4641000cf542c50ff76", + "title": "Problem 247: Squares under a hyperbola" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-248-numbers-for-which-eulers-totient-function-equals-13", + "blockName": "Project Euler" + }, + "id": "5900f4651000cf542c50ff77", + "title": "Problem 248: Numbers for which Euler’s totient function equals 13!" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-249-prime-subset-sums", + "blockName": "Project Euler" + }, + "id": "5900f4671000cf542c50ff79", + "title": "Problem 249: Prime Subset Sums" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-25-1000-digit-fibonacci-number", + "blockName": "Project Euler" + }, + "id": "5900f3851000cf542c50fe98", + "title": "Problem 25: 1000-digit Fibonacci number" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-250-250250", + "blockName": "Project Euler" + }, + "id": "5900f4661000cf542c50ff78", + "title": "Problem 250: 250250" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-251-cardano-triplets", + "blockName": "Project Euler" + }, + "id": "5900f4671000cf542c50ff7a", + "title": "Problem 251: Cardano Triplets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-252-convex-holes", + "blockName": "Project Euler" + }, + "id": "5900f4691000cf542c50ff7b", + "title": "Problem 252: Convex Holes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-253-tidying-up", + "blockName": "Project Euler" + }, + "id": "5900f4691000cf542c50ff7c", + "title": "Problem 253: Tidying up" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-254-sums-of-digit-factorials", + "blockName": "Project Euler" + }, + "id": "5900f46b1000cf542c50ff7d", + "title": "Problem 254: Sums of Digit Factorials" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-255-rounded-square-roots", + "blockName": "Project Euler" + }, + "id": "5900f46d1000cf542c50ff7f", + "title": "Problem 255: Rounded Square Roots" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-256-tatami-free-rooms", + "blockName": "Project Euler" + }, + "id": "5900f46c1000cf542c50ff7e", + "title": "Problem 256: Tatami-Free Rooms" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-257-angular-bisectors", + "blockName": "Project Euler" + }, + "id": "5900f46e1000cf542c50ff80", + "title": "Problem 257: Angular Bisectors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-258-a-lagged-fibonacci-sequence", + "blockName": "Project Euler" + }, + "id": "5900f46e1000cf542c50ff81", + "title": "Problem 258: A lagged Fibonacci sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-259-reachable-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4701000cf542c50ff82", + "title": "Problem 259: Reachable Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-26-reciprocal-cycles", + "blockName": "Project Euler" + }, + "id": "5900f3861000cf542c50fe99", + "title": "Problem 26: Reciprocal cycles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-260-stone-game", + "blockName": "Project Euler" + }, + "id": "5900f4701000cf542c50ff83", + "title": "Problem 260: Stone Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-261-pivotal-square-sums", + "blockName": "Project Euler" + }, + "id": "5900f4711000cf542c50ff84", + "title": "Problem 261: Pivotal Square Sums" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-262-mountain-range", + "blockName": "Project Euler" + }, + "id": "5900f4731000cf542c50ff85", + "title": "Problem 262: Mountain Range" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-263-an-engineers-dream-come-true", + "blockName": "Project Euler" + }, + "id": "5900f4741000cf542c50ff86", + "title": "Problem 263: An engineers' dream come true" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-264-triangle-centres", + "blockName": "Project Euler" + }, + "id": "5900f4751000cf542c50ff87", + "title": "Problem 264: Triangle Centres" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-265-binary-circles", + "blockName": "Project Euler" + }, + "id": "5900f4761000cf542c50ff88", + "title": "Problem 265: Binary Circles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-266-pseudo-square-root", + "blockName": "Project Euler" + }, + "id": "5900f4771000cf542c50ff89", + "title": "Problem 266: Pseudo Square Root" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-267-billionaire", + "blockName": "Project Euler" + }, + "id": "5900f4771000cf542c50ff8a", + "title": "Problem 267: Billionaire" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-268-counting-numbers-with-at-least-four-distinct-prime-factors-less-than-100", + "blockName": "Project Euler" + }, + "id": "5900f4791000cf542c50ff8b", + "title": "Problem 268: Counting numbers with at least four distinct prime factors less than 100" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-269-polynomials-with-at-least-one-integer-root", + "blockName": "Project Euler" + }, + "id": "5900f4791000cf542c50ff8c", + "title": "Problem 269: Polynomials with at least one integer root" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-27-quadratic-primes", + "blockName": "Project Euler" + }, + "id": "5900f3871000cf542c50fe9a", + "title": "Problem 27: Quadratic primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-270-cutting-squares", + "blockName": "Project Euler" + }, + "id": "5900f47c1000cf542c50ff8e", + "title": "Problem 270: Cutting Squares" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-271-modular-cubes-part-1", + "blockName": "Project Euler" + }, + "id": "5900f47b1000cf542c50ff8d", + "title": "Problem 271: Modular Cubes, part 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-272-modular-cubes-part-2", + "blockName": "Project Euler" + }, + "id": "5900f47d1000cf542c50ff8f", + "title": "Problem 272: Modular Cubes, part 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-273-sum-of-squares", + "blockName": "Project Euler" + }, + "id": "5900f47e1000cf542c50ff90", + "title": "Problem 273: Sum of Squares" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-274-divisibility-multipliers", + "blockName": "Project Euler" + }, + "id": "5900f47f1000cf542c50ff91", + "title": "Problem 274: Divisibility Multipliers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-275-balanced-sculptures", + "blockName": "Project Euler" + }, + "id": "5900f4801000cf542c50ff92", + "title": "Problem 275: Balanced Sculptures" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-276-primitive-triangles", + "blockName": "Project Euler" + }, + "id": "5900f4801000cf542c50ff93", + "title": "Problem 276: Primitive Triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-277-a-modified-collatz-sequence", + "blockName": "Project Euler" + }, + "id": "5900f4811000cf542c50ff94", + "title": "Problem 277: A Modified Collatz sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-278-linear-combinations-of-semiprimes", + "blockName": "Project Euler" + }, + "id": "5900f4831000cf542c50ff95", + "title": "Problem 278: Linear Combinations of Semiprimes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-279-triangles-with-integral-sides-and-an-integral-angle", + "blockName": "Project Euler" + }, + "id": "5900f4841000cf542c50ff96", + "title": "Problem 279: Triangles with integral sides and an integral angle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-28-number-spiral-diagonals", + "blockName": "Project Euler" + }, + "id": "5900f3881000cf542c50fe9b", + "title": "Problem 28: Number spiral diagonals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-280-ant-and-seeds", + "blockName": "Project Euler" + }, + "id": "5900f4841000cf542c50ff97", + "title": "Problem 280: Ant and seeds" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-281-pizza-toppings", + "blockName": "Project Euler" + }, + "id": "5900f4861000cf542c50ff98", + "title": "Problem 281: Pizza Toppings" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-282-the-ackermann-function", + "blockName": "Project Euler" + }, + "id": "5900f4861000cf542c50ff99", + "title": "Problem 282: The Ackermann function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-283-integer-sided-triangles-for-which-the-area--perimeter-ratio-is-integral", + "blockName": "Project Euler" + }, + "id": "5900f4881000cf542c50ff9a", + "title": "Problem 283: Integer sided triangles for which the area / perimeter ratio is integral" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-284-steady-squares", + "blockName": "Project Euler" + }, + "id": "5900f4891000cf542c50ff9b", + "title": "Problem 284: Steady Squares" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-285-pythagorean-odds", + "blockName": "Project Euler" + }, + "id": "5900f48a1000cf542c50ff9c", + "title": "Problem 285: Pythagorean odds" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-286-scoring-probabilities", + "blockName": "Project Euler" + }, + "id": "5900f48a1000cf542c50ff9d", + "title": "Problem 286: Scoring probabilities" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-287-quadtree-encoding-a-simple-compression-algorithm", + "blockName": "Project Euler" + }, + "id": "5900f48b1000cf542c50ff9e", + "title": "Problem 287: Quadtree encoding (a simple compression algorithm)" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-288-an-enormous-factorial", + "blockName": "Project Euler" + }, + "id": "5900f48d1000cf542c50ff9f", + "title": "Problem 288: An enormous factorial" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-289-eulerian-cycles", + "blockName": "Project Euler" + }, + "id": "5900f48d1000cf542c50ffa0", + "title": "Problem 289: Eulerian Cycles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-29-distinct-powers", + "blockName": "Project Euler" + }, + "id": "5900f3891000cf542c50fe9c", + "title": "Problem 29: Distinct powers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-290-digital-signature", + "blockName": "Project Euler" + }, + "id": "5900f48f1000cf542c50ffa1", + "title": "Problem 290: Digital Signature" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-291-panaitopol-primes", + "blockName": "Project Euler" + }, + "id": "5900f48f1000cf542c50ffa2", + "title": "Problem 291: Panaitopol Primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-292-pythagorean-polygons", + "blockName": "Project Euler" + }, + "id": "5900f4911000cf542c50ffa3", + "title": "Problem 292: Pythagorean Polygons" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-293-pseudo-fortunate-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4931000cf542c50ffa4", + "title": "Problem 293: Pseudo-Fortunate Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-294-sum-of-digits---experience-23", + "blockName": "Project Euler" + }, + "id": "5900f4931000cf542c50ffa5", + "title": "Problem 294: Sum of digits - experience #23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-295-lenticular-holes", + "blockName": "Project Euler" + }, + "id": "5900f4931000cf542c50ffa6", + "title": "Problem 295: Lenticular holes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-296-angular-bisector-and-tangent", + "blockName": "Project Euler" + }, + "id": "5900f4941000cf542c50ffa7", + "title": "Problem 296: Angular Bisector and Tangent" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-297-zeckendorf-representation", + "blockName": "Project Euler" + }, + "id": "5900f4951000cf542c50ffa8", + "title": "Problem 297: Zeckendorf Representation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-298-selective-amnesia", + "blockName": "Project Euler" + }, + "id": "5900f4971000cf542c50ffa9", + "title": "Problem 298: Selective Amnesia" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-299-three-similar-triangles", + "blockName": "Project Euler" + }, + "id": "5900f4971000cf542c50ffaa", + "title": "Problem 299: Three similar triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-3-largest-prime-factor", + "blockName": "Project Euler" + }, + "id": "5900f36f1000cf542c50fe82", + "title": "Problem 3: Largest prime factor" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-30-digit-n-powers", + "blockName": "Project Euler" + }, + "id": "5900f38a1000cf542c50fe9d", + "title": "Problem 30: Digit n powers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-300-protein-folding", + "blockName": "Project Euler" + }, + "id": "5900f49a1000cf542c50ffac", + "title": "Problem 300: Protein folding" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-301-nim", + "blockName": "Project Euler" + }, + "id": "5900f4991000cf542c50ffab", + "title": "Problem 301: Nim" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-302-strong-achilles-numbers", + "blockName": "Project Euler" + }, + "id": "5900f49b1000cf542c50ffad", + "title": "Problem 302: Strong Achilles Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-303-multiples-with-small-digits", + "blockName": "Project Euler" + }, + "id": "5900f49b1000cf542c50ffae", + "title": "Problem 303: Multiples with small digits" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-304-primonacci", + "blockName": "Project Euler" + }, + "id": "5900f49d1000cf542c50ffaf", + "title": "Problem 304: Primonacci" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-305-reflexive-position", + "blockName": "Project Euler" + }, + "id": "5900f49d1000cf542c50ffb0", + "title": "Problem 305: Reflexive Position" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-306-paper-strip-game", + "blockName": "Project Euler" + }, + "id": "5900f49f1000cf542c50ffb1", + "title": "Problem 306: Paper-strip Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-307-chip-defects", + "blockName": "Project Euler" + }, + "id": "5900f4a01000cf542c50ffb2", + "title": "Problem 307: Chip Defects" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-308-an-amazing-prime-generating-automaton", + "blockName": "Project Euler" + }, + "id": "5900f4a11000cf542c50ffb3", + "title": "Problem 308: An amazing Prime-generating Automaton" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-309-integer-ladders", + "blockName": "Project Euler" + }, + "id": "5900f4a11000cf542c50ffb4", + "title": "Problem 309: Integer Ladders" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-31-coin-sums", + "blockName": "Project Euler" + }, + "id": "5900f38b1000cf542c50fe9e", + "title": "Problem 31: Coin sums" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-310-nim-square", + "blockName": "Project Euler" + }, + "id": "5900f4a21000cf542c50ffb5", + "title": "Problem 310: Nim Square" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-311-biclinic-integral-quadrilaterals", + "blockName": "Project Euler" + }, + "id": "5900f4a31000cf542c50ffb6", + "title": "Problem 311: Biclinic Integral Quadrilaterals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-312-cyclic-paths-on-sierpiski-graphs", + "blockName": "Project Euler" + }, + "id": "5900f4a51000cf542c50ffb7", + "title": "Problem 312: Cyclic paths on Sierpiński graphs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-313-sliding-game", + "blockName": "Project Euler" + }, + "id": "5900f4a61000cf542c50ffb8", + "title": "Problem 313: Sliding game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-314-the-mouse-on-the-moon", + "blockName": "Project Euler" + }, + "id": "5900f4a71000cf542c50ffb9", + "title": "Problem 314: The Mouse on the Moon" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-315-digital-root-clocks", + "blockName": "Project Euler" + }, + "id": "5900f4a71000cf542c50ffba", + "title": "Problem 315: Digital root clocks" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-316-numbers-in-decimal-expansions", + "blockName": "Project Euler" + }, + "id": "5900f4a81000cf542c50ffbb", + "title": "Problem 316: Numbers in decimal expansions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-317-firecracker", + "blockName": "Project Euler" + }, + "id": "5900f4aa1000cf542c50ffbc", + "title": "Problem 317: Firecracker" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-318-2011-nines", + "blockName": "Project Euler" + }, + "id": "5900f4ab1000cf542c50ffbd", + "title": "Problem 318: 2011 nines" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-319-bounded-sequences", + "blockName": "Project Euler" + }, + "id": "5900f4ab1000cf542c50ffbe", + "title": "Problem 319: Bounded Sequences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-32-pandigital-products", + "blockName": "Project Euler" + }, + "id": "5900f38c1000cf542c50fe9f", + "title": "Problem 32: Pandigital products" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-320-factorials-divisible-by-a-huge-integer", + "blockName": "Project Euler" + }, + "id": "5900f4ae1000cf542c50ffbf", + "title": "Problem 320: Factorials divisible by a huge integer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-321-swapping-counters", + "blockName": "Project Euler" + }, + "id": "5900f4ae1000cf542c50ffc0", + "title": "Problem 321: Swapping Counters" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-322-binomial-coefficients-divisible-by-10", + "blockName": "Project Euler" + }, + "id": "5900f4af1000cf542c50ffc1", + "title": "Problem 322: Binomial coefficients divisible by 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-323-bitwise-or-operations-on-random-integers", + "blockName": "Project Euler" + }, + "id": "5900f4b01000cf542c50ffc2", + "title": "Problem 323: Bitwise-OR operations on random integers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-324-building-a-tower", + "blockName": "Project Euler" + }, + "id": "5900f4b11000cf542c50ffc3", + "title": "Problem 324: Building a tower" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-325-stone-game-ii", + "blockName": "Project Euler" + }, + "id": "5900f4b11000cf542c50ffc4", + "title": "Problem 325: Stone Game II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-326-modulo-summations", + "blockName": "Project Euler" + }, + "id": "5900f4b21000cf542c50ffc5", + "title": "Problem 326: Modulo Summations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-327-rooms-of-doom", + "blockName": "Project Euler" + }, + "id": "5900f4b31000cf542c50ffc6", + "title": "Problem 327: Rooms of Doom" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-328-lowest-cost-search", + "blockName": "Project Euler" + }, + "id": "5900f4b41000cf542c50ffc7", + "title": "Problem 328: Lowest-cost Search" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-329-prime-frog", + "blockName": "Project Euler" + }, + "id": "5900f4b51000cf542c50ffc8", + "title": "Problem 329: Prime Frog" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-33-digit-cancelling-fractions", + "blockName": "Project Euler" + }, + "id": "5900f38d1000cf542c50fea0", + "title": "Problem 33: Digit cancelling fractions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-330-eulers-number", + "blockName": "Project Euler" + }, + "id": "5900f4b71000cf542c50ffc9", + "title": "Problem 330: Euler's Number" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-331-cross-flips", + "blockName": "Project Euler" + }, + "id": "5900f4b71000cf542c50ffca", + "title": "Problem 331: Cross flips" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-332-spherical-triangles", + "blockName": "Project Euler" + }, + "id": "5900f4b91000cf542c50ffcb", + "title": "Problem 332: Spherical triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-333-special-partitions", + "blockName": "Project Euler" + }, + "id": "5900f4b91000cf542c50ffcc", + "title": "Problem 333: Special partitions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-334-spilling-the-beans", + "blockName": "Project Euler" + }, + "id": "5900f4ba1000cf542c50ffcd", + "title": "Problem 334: Spilling the beans" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-335-gathering-the-beans", + "blockName": "Project Euler" + }, + "id": "5900f4bd1000cf542c50ffce", + "title": "Problem 335: Gathering the beans" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-336-maximix-arrangements", + "blockName": "Project Euler" + }, + "id": "5900f4bd1000cf542c50ffcf", + "title": "Problem 336: Maximix Arrangements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-337-totient-stairstep-sequences", + "blockName": "Project Euler" + }, + "id": "5900f4be1000cf542c50ffd0", + "title": "Problem 337: Totient Stairstep Sequences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-338-cutting-rectangular-grid-paper", + "blockName": "Project Euler" + }, + "id": "5900f4be1000cf542c50ffd1", + "title": "Problem 338: Cutting Rectangular Grid Paper" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-339-peredur-fab-efrawg", + "blockName": "Project Euler" + }, + "id": "5900f4c01000cf542c50ffd2", + "title": "Problem 339: Peredur fab Efrawg" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-34-digit-factorials", + "blockName": "Project Euler" + }, + "id": "5900f38e1000cf542c50fea1", + "title": "Problem 34: Digit factorials" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-340-crazy-function", + "blockName": "Project Euler" + }, + "id": "5900f4c21000cf542c50ffd4", + "title": "Problem 340: Crazy Function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-341-golombs-self-describing-sequence", + "blockName": "Project Euler" + }, + "id": "5900f4c11000cf542c50ffd3", + "title": "Problem 341: Golomb's self-describing sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-342-the-totient-of-a-square-is-a-cube", + "blockName": "Project Euler" + }, + "id": "5900f4c31000cf542c50ffd5", + "title": "Problem 342: The totient of a square is a cube" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-343-fractional-sequences", + "blockName": "Project Euler" + }, + "id": "5900f4c41000cf542c50ffd6", + "title": "Problem 343: Fractional Sequences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-344-silver-dollar-game", + "blockName": "Project Euler" + }, + "id": "5900f4c51000cf542c50ffd7", + "title": "Problem 344: Silver dollar game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-345-matrix-sum", + "blockName": "Project Euler" + }, + "id": "5900f4c81000cf542c50ffda", + "title": "Problem 345: Matrix Sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-346-strong-repunits", + "blockName": "Project Euler" + }, + "id": "5900f4c71000cf542c50ffd8", + "title": "Problem 346: Strong Repunits" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-347-largest-integer-divisible-by-two-primes", + "blockName": "Project Euler" + }, + "id": "5900f4c81000cf542c50ffd9", + "title": "Problem 347: Largest integer divisible by two primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-348-sum-of-a-square-and-a-cube", + "blockName": "Project Euler" + }, + "id": "5900f4c81000cf542c50ffdb", + "title": "Problem 348: Sum of a square and a cube" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-349-langtons-ant", + "blockName": "Project Euler" + }, + "id": "5900f4ca1000cf542c50ffdc", + "title": "Problem 349: Langton's ant" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-35-circular-primes", + "blockName": "Project Euler" + }, + "id": "5900f38f1000cf542c50fea2", + "title": "Problem 35: Circular primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-350-constraining-the-least-greatest-and-the-greatest-least", + "blockName": "Project Euler" + }, + "id": "5900f4cb1000cf542c50ffdd", + "title": "Problem 350: Constraining the least greatest and the greatest least" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-351-hexagonal-orchards", + "blockName": "Project Euler" + }, + "id": "5900f4cb1000cf542c50ffde", + "title": "Problem 351: Hexagonal orchards" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-352-blood-tests", + "blockName": "Project Euler" + }, + "id": "5900f4cd1000cf542c50ffdf", + "title": "Problem 352: Blood tests" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-353-risky-moon", + "blockName": "Project Euler" + }, + "id": "5900f4cd1000cf542c50ffe0", + "title": "Problem 353: Risky moon" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-354-distances-in-a-bees-honeycomb", + "blockName": "Project Euler" + }, + "id": "5900f4cf1000cf542c50ffe1", + "title": "Problem 354: Distances in a bee's honeycomb" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-355-maximal-coprime-subset", + "blockName": "Project Euler" + }, + "id": "5900f4d01000cf542c50ffe2", + "title": "Problem 355: Maximal coprime subset" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-356-largest-roots-of-cubic-polynomials", + "blockName": "Project Euler" + }, + "id": "5900f4d01000cf542c50ffe3", + "title": "Problem 356: Largest roots of cubic polynomials" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-357-prime-generating-integers", + "blockName": "Project Euler" + }, + "id": "5900f4d11000cf542c50ffe4", + "title": "Problem 357: Prime generating integers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-358-cyclic-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4d21000cf542c50ffe5", + "title": "Problem 358: Cyclic numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-359-hilberts-new-hotel", + "blockName": "Project Euler" + }, + "id": "5900f4d31000cf542c50ffe6", + "title": "Problem 359: Hilbert's New Hotel" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-36-double-base-palindromes", + "blockName": "Project Euler" + }, + "id": "5900f3901000cf542c50fea3", + "title": "Problem 36: Double-base palindromes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-360-scary-sphere", + "blockName": "Project Euler" + }, + "id": "5900f4d41000cf542c50ffe7", + "title": "Problem 360: Scary Sphere" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-361-subsequence-of-thue-morse-sequence", + "blockName": "Project Euler" + }, + "id": "5900f4d51000cf542c50ffe8", + "title": "Problem 361: Subsequence of Thue-Morse sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-362-squarefree-factors", + "blockName": "Project Euler" + }, + "id": "5900f4d61000cf542c50ffe9", + "title": "Problem 362: Squarefree factors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-363-bzier-curves", + "blockName": "Project Euler" + }, + "id": "5900f4d91000cf542c50ffeb", + "title": "Problem 363: Bézier Curves" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-364-comfortable-distance", + "blockName": "Project Euler" + }, + "id": "5900f4d91000cf542c50ffea", + "title": "Problem 364: Comfortable distance" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-365-a-huge-binomial-coefficient", + "blockName": "Project Euler" + }, + "id": "5900f4da1000cf542c50ffec", + "title": "Problem 365: A huge binomial coefficient" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-366-stone-game-iii", + "blockName": "Project Euler" + }, + "id": "5900f4da1000cf542c50ffed", + "title": "Problem 366: Stone Game III" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-367-bozo-sort", + "blockName": "Project Euler" + }, + "id": "5900f4db1000cf542c50ffee", + "title": "Problem 367: Bozo sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-368-a-kempner-like-series", + "blockName": "Project Euler" + }, + "id": "5900f4dd1000cf542c50ffef", + "title": "Problem 368: A Kempner-like series" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-369-badugi", + "blockName": "Project Euler" + }, + "id": "5900f4de1000cf542c50fff0", + "title": "Problem 369: Badugi" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-37-truncatable-primes", + "blockName": "Project Euler" + }, + "id": "5900f3911000cf542c50fea4", + "title": "Problem 37: Truncatable primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-370-geometric-triangles", + "blockName": "Project Euler" + }, + "id": "5900f4de1000cf542c50fff1", + "title": "Problem 370: Geometric triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-371-licence-plates", + "blockName": "Project Euler" + }, + "id": "5900f4e01000cf542c50fff2", + "title": "Problem 371: Licence plates" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-372-pencils-of-rays", + "blockName": "Project Euler" + }, + "id": "5900f4e11000cf542c50fff3", + "title": "Problem 372: Pencils of rays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-373-circumscribed-circles", + "blockName": "Project Euler" + }, + "id": "5900f4e11000cf542c50fff4", + "title": "Problem 373: Circumscribed Circles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-374-maximum-integer-partition-product", + "blockName": "Project Euler" + }, + "id": "5900f4e51000cf542c50fff6", + "title": "Problem 374: Maximum Integer Partition Product" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-375-minimum-of-subsequences", + "blockName": "Project Euler" + }, + "id": "5900f4e41000cf542c50fff5", + "title": "Problem 375: Minimum of subsequences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-376-nontransitive-sets-of-dice", + "blockName": "Project Euler" + }, + "id": "5900f4e51000cf542c50fff7", + "title": "Problem 376: Nontransitive sets of dice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-377-sum-of-digits-experience-13", + "blockName": "Project Euler" + }, + "id": "5900f4e51000cf542c50fff8", + "title": "Problem 377: Sum of digits, experience 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-378-triangle-triples", + "blockName": "Project Euler" + }, + "id": "5900f4e61000cf542c50fff9", + "title": "Problem 378: Triangle Triples" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-379-least-common-multiple-count", + "blockName": "Project Euler" + }, + "id": "5900f4e81000cf542c50fffa", + "title": "Problem 379: Least common multiple count" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-38-pandigital-multiples", + "blockName": "Project Euler" + }, + "id": "5900f3931000cf542c50fea5", + "title": "Problem 38: Pandigital multiples" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-380-amazing-mazes", + "blockName": "Project Euler" + }, + "id": "5900f4e81000cf542c50fffb", + "title": "Problem 380: Amazing Mazes!" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-381-prime-k-factorial", + "blockName": "Project Euler" + }, + "id": "5900f4ea1000cf542c50fffc", + "title": "Problem 381: (prime-k) factorial" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-382-generating-polygons", + "blockName": "Project Euler" + }, + "id": "5900f4eb1000cf542c50fffd", + "title": "Problem 382: Generating polygons" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-383-divisibility-comparison-between-factorials", + "blockName": "Project Euler" + }, + "id": "5900f4ed1000cf542c50ffff", + "title": "Problem 383: Divisibility comparison between factorials" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-384-rudin-shapiro-sequence", + "blockName": "Project Euler" + }, + "id": "5900f4ed1000cf542c50fffe", + "title": "Problem 384: Rudin-Shapiro sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-385-ellipses-inside-triangles", + "blockName": "Project Euler" + }, + "id": "5900f4ee1000cf542c510000", + "title": "Problem 385: Ellipses inside triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-386-maximum-length-of-an-antichain", + "blockName": "Project Euler" + }, + "id": "5900f4ef1000cf542c510001", + "title": "Problem 386: Maximum length of an antichain" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-387-harshad-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4f11000cf542c510003", + "title": "Problem 387: Harshad Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-388-distinct-lines", + "blockName": "Project Euler" + }, + "id": "5900f4f11000cf542c510002", + "title": "Problem 388: Distinct Lines" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-389-platonic-dice", + "blockName": "Project Euler" + }, + "id": "5900f4f21000cf542c510004", + "title": "Problem 389: Platonic Dice" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-39-integer-right-triangles", + "blockName": "Project Euler" + }, + "id": "5900f3931000cf542c50fea6", + "title": "Problem 39: Integer right triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-390-triangles-with-non-rational-sides-and-integral-area", + "blockName": "Project Euler" + }, + "id": "5900f4f21000cf542c510005", + "title": "Problem 390: Triangles with non rational sides and integral area" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-391-hopping-game", + "blockName": "Project Euler" + }, + "id": "5900f4f31000cf542c510006", + "title": "Problem 391: Hopping Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-392-enmeshed-unit-circle", + "blockName": "Project Euler" + }, + "id": "5900f4f41000cf542c510007", + "title": "Problem 392: Enmeshed unit circle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-393-migrating-ants", + "blockName": "Project Euler" + }, + "id": "5900f4f61000cf542c510008", + "title": "Problem 393: Migrating ants" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-394-eating-pie", + "blockName": "Project Euler" + }, + "id": "5900f4f71000cf542c510009", + "title": "Problem 394: Eating pie" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-395-pythagorean-tree", + "blockName": "Project Euler" + }, + "id": "5900f4f71000cf542c51000a", + "title": "Problem 395: Pythagorean tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-396-weak-goodstein-sequence", + "blockName": "Project Euler" + }, + "id": "5900f4f81000cf542c51000b", + "title": "Problem 396: Weak Goodstein sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-397-triangle-on-parabola", + "blockName": "Project Euler" + }, + "id": "5900f4f91000cf542c51000c", + "title": "Problem 397: Triangle on parabola" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-398-cutting-rope", + "blockName": "Project Euler" + }, + "id": "5900f4fa1000cf542c51000d", + "title": "Problem 398: Cutting rope" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-399-squarefree-fibonacci-numbers", + "blockName": "Project Euler" + }, + "id": "5900f4fc1000cf542c51000e", + "title": "Problem 399: Squarefree Fibonacci Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-4-largest-palindrome-product", + "blockName": "Project Euler" + }, + "id": "5900f3701000cf542c50fe83", + "title": "Problem 4: Largest palindrome product" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-40-champernownes-constant", + "blockName": "Project Euler" + }, + "id": "5900f3941000cf542c50fea7", + "title": "Problem 40: Champernowne's constant" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-400-fibonacci-tree-game", + "blockName": "Project Euler" + }, + "id": "5900f4fe1000cf542c510010", + "title": "Problem 400: Fibonacci tree game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-401-sum-of-squares-of-divisors", + "blockName": "Project Euler" + }, + "id": "5900f4fd1000cf542c51000f", + "title": "Problem 401: Sum of squares of divisors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-402-integer-valued-polynomials", + "blockName": "Project Euler" + }, + "id": "5900f4ff1000cf542c510011", + "title": "Problem 402: Integer-valued polynomials" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-403-lattice-points-enclosed-by-parabola-and-line", + "blockName": "Project Euler" + }, + "id": "5900f5001000cf542c510013", + "title": "Problem 403: Lattice points enclosed by parabola and line" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-404-crisscross-ellipses", + "blockName": "Project Euler" + }, + "id": "5900f5001000cf542c510012", + "title": "Problem 404: Crisscross Ellipses" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-405-a-rectangular-tiling", + "blockName": "Project Euler" + }, + "id": "5900f5021000cf542c510014", + "title": "Problem 405: A rectangular tiling" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-406-guessing-game", + "blockName": "Project Euler" + }, + "id": "5900f5021000cf542c510015", + "title": "Problem 406: Guessing Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-407-idempotents", + "blockName": "Project Euler" + }, + "id": "5900f5041000cf542c510016", + "title": "Problem 407: Idempotents" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-408-admissible-paths-through-a-grid", + "blockName": "Project Euler" + }, + "id": "5900f5091000cf542c51001b", + "title": "Problem 408: Admissible paths through a grid" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-409-nim-extreme", + "blockName": "Project Euler" + }, + "id": "5900f5061000cf542c510017", + "title": "Problem 409: Nim Extreme" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-41-pandigital-prime", + "blockName": "Project Euler" + }, + "id": "5900f3951000cf542c50fea8", + "title": "Problem 41: Pandigital prime" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-410-circle-and-tangent-line", + "blockName": "Project Euler" + }, + "id": "5900f5071000cf542c510018", + "title": "Problem 410: Circle and tangent line" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-411-uphill-paths", + "blockName": "Project Euler" + }, + "id": "5900f5081000cf542c510019", + "title": "Problem 411: Uphill paths" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-412-gnomon-numbering", + "blockName": "Project Euler" + }, + "id": "5900f5081000cf542c51001a", + "title": "Problem 412: Gnomon numbering" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-413-one-child-numbers", + "blockName": "Project Euler" + }, + "id": "5900f50a1000cf542c51001c", + "title": "Problem 413: One-child Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-414-kaprekar-constant", + "blockName": "Project Euler" + }, + "id": "5900f50b1000cf542c51001d", + "title": "Problem 414: Kaprekar constant" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-415-titanic-sets", + "blockName": "Project Euler" + }, + "id": "5900f50c1000cf542c51001e", + "title": "Problem 415: Titanic sets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-416-a-frogs-trip", + "blockName": "Project Euler" + }, + "id": "5900f50e1000cf542c510020", + "title": "Problem 416: A frog's trip" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-417-reciprocal-cycles-ii", + "blockName": "Project Euler" + }, + "id": "5900f50d1000cf542c51001f", + "title": "Problem 417: Reciprocal cycles II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-418-factorisation-triples", + "blockName": "Project Euler" + }, + "id": "5900f50f1000cf542c510021", + "title": "Problem 418: Factorisation triples" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-419-look-and-say-sequence", + "blockName": "Project Euler" + }, + "id": "5900f5101000cf542c510022", + "title": "Problem 419: Look and say sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-42-coded-triangle-numbers", + "blockName": "Project Euler" + }, + "id": "5900f3961000cf542c50fea9", + "title": "Problem 42: Coded triangle numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-420-2x2-positive-integer-matrix", + "blockName": "Project Euler" + }, + "id": "5900f5111000cf542c510023", + "title": "Problem 420: 2x2 positive integer matrix" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-421-prime-factors-of-n151", + "blockName": "Project Euler" + }, + "id": "5900f5131000cf542c510024", + "title": "Problem 421: Prime factors of n^15+1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-422-sequence-of-points-on-a-hyperbola", + "blockName": "Project Euler" + }, + "id": "5900f5131000cf542c510025", + "title": "Problem 422: Sequence of points on a hyperbola" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-423-consecutive-die-throws", + "blockName": "Project Euler" + }, + "id": "5900f5141000cf542c510027", + "title": "Problem 423: Consecutive die throws" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-424-kakuro", + "blockName": "Project Euler" + }, + "id": "5900f5141000cf542c510026", + "title": "Problem 424: Kakuro" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-425-prime-connection", + "blockName": "Project Euler" + }, + "id": "5900f5151000cf542c510028", + "title": "Problem 425: Prime connection" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-426-box-ball-system", + "blockName": "Project Euler" + }, + "id": "5900f5171000cf542c510029", + "title": "Problem 426: Box-ball system" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-427-n-sequences", + "blockName": "Project Euler" + }, + "id": "5900f5181000cf542c51002a", + "title": "Problem 427: n-sequences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-428-necklace-of-circles", + "blockName": "Project Euler" + }, + "id": "5900f5191000cf542c51002b", + "title": "Problem 428: Necklace of Circles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-429-sum-of-squares-of-unitary-divisors", + "blockName": "Project Euler" + }, + "id": "5900f5191000cf542c51002c", + "title": "Problem 429: Sum of squares of unitary divisors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-43-sub-string-divisibility", + "blockName": "Project Euler" + }, + "id": "5900f3971000cf542c50feaa", + "title": "Problem 43: Sub-string divisibility" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-430-range-flips", + "blockName": "Project Euler" + }, + "id": "5900f51a1000cf542c51002d", + "title": "Problem 430: Range flips" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-431-square-space-silo", + "blockName": "Project Euler" + }, + "id": "5900f51b1000cf542c51002e", + "title": "Problem 431: Square Space Silo" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-432-totient-sum", + "blockName": "Project Euler" + }, + "id": "5900f51e1000cf542c510030", + "title": "Problem 432: Totient sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-433-steps-in-euclids-algorithm", + "blockName": "Project Euler" + }, + "id": "5900f51d1000cf542c51002f", + "title": "Problem 433: Steps in Euclid's algorithm" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-434-rigid-graphs", + "blockName": "Project Euler" + }, + "id": "5900f51f1000cf542c510031", + "title": "Problem 434: Rigid graphs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-435-polynomials-of-fibonacci-numbers", + "blockName": "Project Euler" + }, + "id": "5900f5201000cf542c510032", + "title": "Problem 435: Polynomials of Fibonacci numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-436-unfair-wager", + "blockName": "Project Euler" + }, + "id": "5900f5221000cf542c510033", + "title": "Problem 436: Unfair wager" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-437-fibonacci-primitive-roots", + "blockName": "Project Euler" + }, + "id": "5900f5241000cf542c510036", + "title": "Problem 437: Fibonacci primitive roots" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-438-integer-part-of-polynomial-equations-solutions", + "blockName": "Project Euler" + }, + "id": "5900f5231000cf542c510034", + "title": "Problem 438: Integer part of polynomial equation's solutions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-439-sum-of-sum-of-divisors", + "blockName": "Project Euler" + }, + "id": "5900f5231000cf542c510035", + "title": "Problem 439: Sum of sum of divisors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-44-pentagon-numbers", + "blockName": "Project Euler" + }, + "id": "5900f3981000cf542c50feab", + "title": "Problem 44: Pentagon numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-440-gcd-and-tiling", + "blockName": "Project Euler" + }, + "id": "5900f5241000cf542c510037", + "title": "Problem 440: GCD and Tiling" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-441-the-inverse-summation-of-coprime-couples", + "blockName": "Project Euler" + }, + "id": "5900f5261000cf542c510038", + "title": "Problem 441: The inverse summation of coprime couples" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-442-eleven-free-integers", + "blockName": "Project Euler" + }, + "id": "5900f5271000cf542c510039", + "title": "Problem 442: Eleven-free integers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-443-gcd-sequence", + "blockName": "Project Euler" + }, + "id": "5900f5271000cf542c51003a", + "title": "Problem 443: GCD sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-444-the-roundtable-lottery", + "blockName": "Project Euler" + }, + "id": "5900f52a1000cf542c51003b", + "title": "Problem 444: The Roundtable Lottery" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-445-retractions-a", + "blockName": "Project Euler" + }, + "id": "5900f52a1000cf542c51003c", + "title": "Problem 445: Retractions A" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-446-retractions-b", + "blockName": "Project Euler" + }, + "id": "5900f52c1000cf542c51003d", + "title": "Problem 446: Retractions B" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-447-retractions-c", + "blockName": "Project Euler" + }, + "id": "5900f52c1000cf542c51003e", + "title": "Problem 447: Retractions C" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-448-average-least-common-multiple", + "blockName": "Project Euler" + }, + "id": "5900f52c1000cf542c51003f", + "title": "Problem 448: Average least common multiple" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-449-chocolate-covered-candy", + "blockName": "Project Euler" + }, + "id": "5900f52d1000cf542c510040", + "title": "Problem 449: Chocolate covered candy" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-45-triangular-pentagonal-and-hexagonal", + "blockName": "Project Euler" + }, + "id": "5900f3991000cf542c50feac", + "title": "Problem 45: Triangular, pentagonal, and hexagonal" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-450-hypocycloid-and-lattice-points", + "blockName": "Project Euler" + }, + "id": "5900f52e1000cf542c510041", + "title": "Problem 450: Hypocycloid and Lattice points" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-451-modular-inverses", + "blockName": "Project Euler" + }, + "id": "5900f5311000cf542c510042", + "title": "Problem 451: Modular inverses" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-452-long-products", + "blockName": "Project Euler" + }, + "id": "5900f5311000cf542c510043", + "title": "Problem 452: Long Products" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-453-lattice-quadrilaterals", + "blockName": "Project Euler" + }, + "id": "5900f5311000cf542c510044", + "title": "Problem 453: Lattice Quadrilaterals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-454-diophantine-reciprocals-iii", + "blockName": "Project Euler" + }, + "id": "5900f5331000cf542c510045", + "title": "Problem 454: Diophantine reciprocals III" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-455-powers-with-trailing-digits", + "blockName": "Project Euler" + }, + "id": "5900f5331000cf542c510046", + "title": "Problem 455: Powers With Trailing Digits" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-456-triangles-containing-the-origin-ii", + "blockName": "Project Euler" + }, + "id": "5900f5351000cf542c510047", + "title": "Problem 456: Triangles containing the origin II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-457-a-polynomial-modulo-the-square-of-a-prime", + "blockName": "Project Euler" + }, + "id": "5900f5361000cf542c510048", + "title": "Problem 457: A polynomial modulo the square of a prime" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-458-permutations-of-project", + "blockName": "Project Euler" + }, + "id": "5900f5361000cf542c510049", + "title": "Problem 458: Permutations of Project" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-459-flipping-game", + "blockName": "Project Euler" + }, + "id": "5900f5371000cf542c51004a", + "title": "Problem 459: Flipping game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-46-goldbachs-other-conjecture", + "blockName": "Project Euler" + }, + "id": "5900f39a1000cf542c50fead", + "title": "Problem 46: Goldbach's other conjecture" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-460-an-ant-on-the-move", + "blockName": "Project Euler" + }, + "id": "5900f5381000cf542c51004b", + "title": "Problem 460: An ant on the move" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-461-almost-pi", + "blockName": "Project Euler" + }, + "id": "5900f53a1000cf542c51004c", + "title": "Problem 461: Almost Pi" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-462-permutation-of-3-smooth-numbers", + "blockName": "Project Euler" + }, + "id": "5900f53b1000cf542c51004d", + "title": "Problem 462: Permutation of 3-smooth numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-463-a-weird-recurrence-relation", + "blockName": "Project Euler" + }, + "id": "5900f53c1000cf542c51004e", + "title": "Problem 463: A weird recurrence relation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-464-mbius-function-and-intervals", + "blockName": "Project Euler" + }, + "id": "5900f53d1000cf542c51004f", + "title": "Problem 464: Möbius function and intervals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-465-polar-polygons", + "blockName": "Project Euler" + }, + "id": "5900f53d1000cf542c510050", + "title": "Problem 465: Polar polygons" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-466-distinct-terms-in-a-multiplication-table", + "blockName": "Project Euler" + }, + "id": "5900f53e1000cf542c510051", + "title": "Problem 466: Distinct terms in a multiplication table" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-467-superinteger", + "blockName": "Project Euler" + }, + "id": "5900f5411000cf542c510052", + "title": "Problem 467: Superinteger" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-468-smooth-divisors-of-binomial-coefficients", + "blockName": "Project Euler" + }, + "id": "5900f5411000cf542c510054", + "title": "Problem 468: Smooth divisors of binomial coefficients" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-469-empty-chairs", + "blockName": "Project Euler" + }, + "id": "5900f5411000cf542c510053", + "title": "Problem 469: Empty chairs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-47-distinct-primes-factors", + "blockName": "Project Euler" + }, + "id": "5900f39c1000cf542c50feae", + "title": "Problem 47: Distinct primes factors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-470-super-ramvok", + "blockName": "Project Euler" + }, + "id": "5900f5431000cf542c510055", + "title": "Problem 470: Super Ramvok" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-471-triangle-inscribed-in-ellipse", + "blockName": "Project Euler" + }, + "id": "5900f5431000cf542c510056", + "title": "Problem 471: Triangle inscribed in ellipse" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-472-comfortable-distance-ii", + "blockName": "Project Euler" + }, + "id": "5900f5451000cf542c510057", + "title": "Problem 472: Comfortable Distance II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-473-phigital-number-base", + "blockName": "Project Euler" + }, + "id": "5900f5461000cf542c510058", + "title": "Problem 473: Phigital number base" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-474-last-digits-of-divisors", + "blockName": "Project Euler" + }, + "id": "5900f5471000cf542c510059", + "title": "Problem 474: Last digits of divisors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-475-music-festival", + "blockName": "Project Euler" + }, + "id": "5900f5481000cf542c51005a", + "title": "Problem 475: Music festival" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-476-circle-packing-ii", + "blockName": "Project Euler" + }, + "id": "5900f5481000cf542c51005b", + "title": "Problem 476: Circle Packing II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-477-number-sequence-game", + "blockName": "Project Euler" + }, + "id": "5900f54a1000cf542c51005c", + "title": "Problem 477: Number Sequence Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-478-mixtures", + "blockName": "Project Euler" + }, + "id": "5900f54c1000cf542c51005e", + "title": "Problem 478: Mixtures" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-479-roots-on-the-rise", + "blockName": "Project Euler" + }, + "id": "5900f54b1000cf542c51005d", + "title": "Problem 479: Roots on the Rise" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-48-self-powers", + "blockName": "Project Euler" + }, + "id": "5900f39c1000cf542c50feaf", + "title": "Problem 48: Self powers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-480-the-last-question", + "blockName": "Project Euler" + }, + "id": "5900f54c1000cf542c51005f", + "title": "Problem 480: The Last Question" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-49-prime-permutations", + "blockName": "Project Euler" + }, + "id": "5900f39d1000cf542c50feb0", + "title": "Problem 49: Prime permutations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-5-smallest-multiple", + "blockName": "Project Euler" + }, + "id": "5900f3711000cf542c50fe84", + "title": "Problem 5: Smallest multiple" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-50-consecutive-prime-sum", + "blockName": "Project Euler" + }, + "id": "5900f39e1000cf542c50feb1", + "title": "Problem 50: Consecutive prime sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-51-prime-digit-replacements", + "blockName": "Project Euler" + }, + "id": "5900f39f1000cf542c50feb2", + "title": "Problem 51: Prime digit replacements" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-52-permuted-multiples", + "blockName": "Project Euler" + }, + "id": "5900f3a01000cf542c50feb3", + "title": "Problem 52: Permuted multiples" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-53-combinatoric-selections", + "blockName": "Project Euler" + }, + "id": "5900f3a11000cf542c50feb4", + "title": "Problem 53: Combinatoric selections" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-54-poker-hands", + "blockName": "Project Euler" + }, + "id": "5900f3a21000cf542c50feb5", + "title": "Problem 54: Poker hands" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-55-lychrel-numbers", + "blockName": "Project Euler" + }, + "id": "5900f3a31000cf542c50feb6", + "title": "Problem 55: Lychrel numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-56-powerful-digit-sum", + "blockName": "Project Euler" + }, + "id": "5900f3a41000cf542c50feb7", + "title": "Problem 56: Powerful digit sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-57-square-root-convergents", + "blockName": "Project Euler" + }, + "id": "5900f3a51000cf542c50feb8", + "title": "Problem 57: Square root convergents" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-58-spiral-primes", + "blockName": "Project Euler" + }, + "id": "5900f3a61000cf542c50feb9", + "title": "Problem 58: Spiral primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-59-xor-decryption", + "blockName": "Project Euler" + }, + "id": "5900f3a81000cf542c50feba", + "title": "Problem 59: XOR decryption" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-6-sum-square-difference", + "blockName": "Project Euler" + }, + "id": "5900f3721000cf542c50fe85", + "title": "Problem 6: Sum square difference" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-60-prime-pair-sets", + "blockName": "Project Euler" + }, + "id": "5900f3a81000cf542c50febb", + "title": "Problem 60: Prime pair sets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-61-cyclical-figurate-numbers", + "blockName": "Project Euler" + }, + "id": "5900f3a91000cf542c50febc", + "title": "Problem 61: Cyclical figurate numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-62-cubic-permutations", + "blockName": "Project Euler" + }, + "id": "5900f3aa1000cf542c50febd", + "title": "Problem 62: Cubic permutations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-63-powerful-digit-counts", + "blockName": "Project Euler" + }, + "id": "5900f3ab1000cf542c50febe", + "title": "Problem 63: Powerful digit counts" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-64-odd-period-square-roots", + "blockName": "Project Euler" + }, + "id": "5900f3ac1000cf542c50febf", + "title": "Problem 64: Odd period square roots" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-65-convergents-of-e", + "blockName": "Project Euler" + }, + "id": "5900f3ad1000cf542c50fec0", + "title": "Problem 65: Convergents of e" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-66-diophantine-equation", + "blockName": "Project Euler" + }, + "id": "5900f3ae1000cf542c50fec1", + "title": "Problem 66: Diophantine equation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-67-maximum-path-sum-ii", + "blockName": "Project Euler" + }, + "id": "5900f3b01000cf542c50fec2", + "title": "Problem 67: Maximum path sum II" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-68-magic-5-gon-ring", + "blockName": "Project Euler" + }, + "id": "5900f3b01000cf542c50fec3", + "title": "Problem 68: Magic 5-gon ring" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-69-totient-maximum", + "blockName": "Project Euler" + }, + "id": "5900f3b11000cf542c50fec4", + "title": "Problem 69: Totient maximum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-7-10001st-prime", + "blockName": "Project Euler" + }, + "id": "5900f3731000cf542c50fe86", + "title": "Problem 7: 10001st prime" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-70-totient-permutation", + "blockName": "Project Euler" + }, + "id": "5900f3b21000cf542c50fec5", + "title": "Problem 70: Totient permutation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-71-ordered-fractions", + "blockName": "Project Euler" + }, + "id": "5900f3b31000cf542c50fec6", + "title": "Problem 71: Ordered fractions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-72-counting-fractions", + "blockName": "Project Euler" + }, + "id": "5900f3b41000cf542c50fec7", + "title": "Problem 72: Counting fractions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-73-counting-fractions-in-a-range", + "blockName": "Project Euler" + }, + "id": "5900f3b61000cf542c50fec8", + "title": "Problem 73: Counting fractions in a range" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-74-digit-factorial-chains", + "blockName": "Project Euler" + }, + "id": "5900f3b61000cf542c50fec9", + "title": "Problem 74: Digit factorial chains" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-75-singular-integer-right-triangles", + "blockName": "Project Euler" + }, + "id": "5900f3b71000cf542c50feca", + "title": "Problem 75: Singular integer right triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-76-counting-summations", + "blockName": "Project Euler" + }, + "id": "5900f3b81000cf542c50fecb", + "title": "Problem 76: Counting summations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-77-prime-summations", + "blockName": "Project Euler" + }, + "id": "5900f3b91000cf542c50fecc", + "title": "Problem 77: Prime summations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-78-coin-partitions", + "blockName": "Project Euler" + }, + "id": "5900f3ba1000cf542c50fecd", + "title": "Problem 78: Coin partitions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-79-passcode-derivation", + "blockName": "Project Euler" + }, + "id": "5900f3bb1000cf542c50fece", + "title": "Problem 79: Passcode derivation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-8-largest-product-in-a-series", + "blockName": "Project Euler" + }, + "id": "5900f3741000cf542c50fe87", + "title": "Problem 8: Largest product in a series" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-80-square-root-digital-expansion", + "blockName": "Project Euler" + }, + "id": "5900f3bc1000cf542c50fecf", + "title": "Problem 80: Square root digital expansion" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-81-path-sum-two-ways", + "blockName": "Project Euler" + }, + "id": "5900f3bd1000cf542c50fed0", + "title": "Problem 81: Path sum: two ways" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-82-path-sum-three-ways", + "blockName": "Project Euler" + }, + "id": "5900f3be1000cf542c50fed1", + "title": "Problem 82: Path sum: three ways" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-83-path-sum-four-ways", + "blockName": "Project Euler" + }, + "id": "5900f3bf1000cf542c50fed2", + "title": "Problem 83: Path sum: four ways" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-84-monopoly-odds", + "blockName": "Project Euler" + }, + "id": "5900f3c11000cf542c50fed3", + "title": "Problem 84: Monopoly odds" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-85-counting-rectangles", + "blockName": "Project Euler" + }, + "id": "5900f3c11000cf542c50fed4", + "title": "Problem 85: Counting rectangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-86-cuboid-route", + "blockName": "Project Euler" + }, + "id": "5900f3c31000cf542c50fed5", + "title": "Problem 86: Cuboid route" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-87-prime-power-triples", + "blockName": "Project Euler" + }, + "id": "5900f3c51000cf542c50fed8", + "title": "Problem 87: Prime power triples" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-88-product-sum-numbers", + "blockName": "Project Euler" + }, + "id": "5900f3c51000cf542c50fed6", + "title": "Problem 88: Product-sum numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-89-roman-numerals", + "blockName": "Project Euler" + }, + "id": "5900f3c51000cf542c50fed7", + "title": "Problem 89: Roman numerals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-9-special-pythagorean-triplet", + "blockName": "Project Euler" + }, + "id": "5900f3761000cf542c50fe88", + "title": "Problem 9: Special Pythagorean triplet" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-90-cube-digit-pairs", + "blockName": "Project Euler" + }, + "id": "5900f3c61000cf542c50fed9", + "title": "Problem 90: Cube digit pairs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-91-right-triangles-with-integer-coordinates", + "blockName": "Project Euler" + }, + "id": "5900f3c71000cf542c50feda", + "title": "Problem 91: Right triangles with integer coordinates" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-92-square-digit-chains", + "blockName": "Project Euler" + }, + "id": "5900f3c81000cf542c50fedb", + "title": "Problem 92: Square digit chains" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-93-arithmetic-expressions", + "blockName": "Project Euler" + }, + "id": "5900f3ca1000cf542c50fedc", + "title": "Problem 93: Arithmetic expressions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-94-almost-equilateral-triangles", + "blockName": "Project Euler" + }, + "id": "5900f3ca1000cf542c50fedd", + "title": "Problem 94: Almost equilateral triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-95-amicable-chains", + "blockName": "Project Euler" + }, + "id": "5900f3cc1000cf542c50fede", + "title": "Problem 95: Amicable chains" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-96-su-doku", + "blockName": "Project Euler" + }, + "id": "5900f3cc1000cf542c50fedf", + "title": "Problem 96: Su Doku" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-97-large-non-mersenne-prime", + "blockName": "Project Euler" + }, + "id": "5900f3ce1000cf542c50fee0", + "title": "Problem 97: Large non-Mersenne prime" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-98-anagramic-squares", + "blockName": "Project Euler" + }, + "id": "5900f3cf1000cf542c50fee1", + "title": "Problem 98: Anagramic squares" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/project-euler/problem-99-largest-exponential", + "blockName": "Project Euler" + }, + "id": "5900f3d01000cf542c50fee2", + "title": "Problem 99: Largest exponential" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/100-doors", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339acb", + "title": "100 doors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/24-game", + "blockName": "Rosetta Code" + }, + "id": "5951e88f64ebf159166a1176", + "title": "24 game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/9-billion-names-of-god-the-integer", + "blockName": "Rosetta Code" + }, + "id": "5949b579404977fbaefcd736", + "title": "9 billion names of God the integer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/abc-problem", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339acc", + "title": "ABC Problem" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/abundant-deficient-and-perfect-number-classifications", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339acd", + "title": "Abundant, deficient and perfect number classifications" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/accumulator-factory", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ace", + "title": "Accumulator factory" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/ackermann-function", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339acf", + "title": "Ackermann function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/align-columns", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad0", + "title": "Align columns" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/amicable-pairs", + "blockName": "Rosetta Code" + }, + "id": "5949b579404977fbaefcd737", + "title": "Amicable pairs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/averagesmode", + "blockName": "Rosetta Code" + }, + "id": "594d8d0ab97724821379b1e6", + "title": "Averages/Mode" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/averagespythagorean-means", + "blockName": "Rosetta Code" + }, + "id": "594d966a1467eb84194f0086", + "title": "Averages/Pythagorean means" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/averagesroot-mean-square", + "blockName": "Rosetta Code" + }, + "id": "594da033de4190850b893874", + "title": "Averages/Root mean square" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/babbage-problem", + "blockName": "Rosetta Code" + }, + "id": "594db4d0dedb4c06a2a4cefd", + "title": "Babbage problem" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/balanced-brackets", + "blockName": "Rosetta Code" + }, + "id": "594dc6c729e5700999302b45", + "title": "Balanced brackets" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/circles-of-given-radius-through-two-points", + "blockName": "Rosetta Code" + }, + "id": "5951815dd895584b06884620", + "title": "Circles of given radius through two points" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/closest-pair-problem", + "blockName": "Rosetta Code" + }, + "id": "5951a53863c8a34f02bf1bdc", + "title": "Closest-pair problem" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/combinations", + "blockName": "Rosetta Code" + }, + "id": "5958469238c0d8d2632f46db", + "title": "Combinations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/comma-quibbling", + "blockName": "Rosetta Code" + }, + "id": "596e414344c3b2872167f0fe", + "title": "Comma quibbling" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/compare-a-list-of-strings", + "blockName": "Rosetta Code" + }, + "id": "596e457071c35c882915b3e4", + "title": "Compare a list of strings" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/convert-seconds-to-compound-duration", + "blockName": "Rosetta Code" + }, + "id": "596fd036dc1ab896c5db98b1", + "title": "Convert seconds to compound duration" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/count-occurrences-of-a-substring", + "blockName": "Rosetta Code" + }, + "id": "596fda99c69f779975a1b67d", + "title": "Count occurrences of a substring" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/count-the-coins", + "blockName": "Rosetta Code" + }, + "id": "59713bd26bdeb8a594fb9413", + "title": "Count the coins" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/cramers-rule", + "blockName": "Rosetta Code" + }, + "id": "59713da0a428c1a62d7db430", + "title": "Cramer's rule" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/cumulative-standard-deviation", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e03", + "title": "Cumulative standard deviation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/cusip", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e05", + "title": "CUSIP" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/cut-a-rectangle", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e06", + "title": "Cut a rectangle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/date-format", + "blockName": "Rosetta Code" + }, + "id": "59669d08d75b60482359409f", + "title": "Date format" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/date-manipulation", + "blockName": "Rosetta Code" + }, + "id": "5966c21cf732a95f1b67dd28", + "title": "Date manipulation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/day-of-the-week", + "blockName": "Rosetta Code" + }, + "id": "5966f99c45e8976909a85575", + "title": "Day of the week" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/deal-cards-for-freecell", + "blockName": "Rosetta Code" + }, + "id": "59694356a6e7011f7f1c5f4e", + "title": "Deal cards for FreeCell" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/deepcopy", + "blockName": "Rosetta Code" + }, + "id": "596a8888ab7c01048de257d5", + "title": "Deepcopy" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/define-a-primitive-data-type", + "blockName": "Rosetta Code" + }, + "id": "597089c87eec450c68aa1643", + "title": "Define a primitive data type" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/department-numbers", + "blockName": "Rosetta Code" + }, + "id": "59f40b17e79dbf1ab720ed7a", + "title": "Department Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/discordian-date", + "blockName": "Rosetta Code" + }, + "id": "59f4eafba0343628bb682785", + "title": "Discordian date" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/dot-product", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e1e", + "title": "Dot product" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/element-wise-operations", + "blockName": "Rosetta Code" + }, + "id": "599c333915e0ea32d04d4bec", + "title": "Element-wise operations" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/emirp-primes", + "blockName": "Rosetta Code" + }, + "id": "599d0ba974141b0f508b37d5", + "title": "Emirp primes" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/entropy", + "blockName": "Rosetta Code" + }, + "id": "599d15309e88c813a40baf58", + "title": "Entropy" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/equilibrium-index", + "blockName": "Rosetta Code" + }, + "id": "5987fd532b954e0f21b5d3f6", + "title": "Equilibrium index" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/ethiopian-multiplication", + "blockName": "Rosetta Code" + }, + "id": "599d1566a02b571412643b84", + "title": "Ethiopian multiplication" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/euler-method", + "blockName": "Rosetta Code" + }, + "id": "59880443fb36441083c6c20e", + "title": "Euler method" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/evaluate-binomial-coefficients", + "blockName": "Rosetta Code" + }, + "id": "598de241872ef8353c58a7a2", + "title": "Evaluate binomial coefficients" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/execute-a-markov-algorithm", + "blockName": "Rosetta Code" + }, + "id": "59e09e6d412c5939baa02d16", + "title": "Execute a Markov algorithm" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/execute-brain", + "blockName": "Rosetta Code" + }, + "id": "59e0a8df964e4540d5abe599", + "title": "Execute Brain****" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/extensible-prime-generator", + "blockName": "Rosetta Code" + }, + "id": "598ee8b91b410510ae82efef", + "title": "Extensible prime generator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/factorial", + "blockName": "Rosetta Code" + }, + "id": "597b2b2a2702b44414742771", + "title": "Factorial" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/factors-of-a-mersenne-number", + "blockName": "Rosetta Code" + }, + "id": "598eea87e5cf4b116c3ff81a", + "title": "Factors of a Mersenne number" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/factors-of-an-integer", + "blockName": "Rosetta Code" + }, + "id": "597f1e7fbc206f0e9ba95dc4", + "title": "Factors of an integer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/farey-sequence", + "blockName": "Rosetta Code" + }, + "id": "59c3ec9f15068017c96eb8a3", + "title": "Farey sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/fibonacci-n-step-number-sequences", + "blockName": "Rosetta Code" + }, + "id": "598eef80ba501f1268170e1e", + "title": "Fibonacci n-step number sequences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/fibonacci-sequence", + "blockName": "Rosetta Code" + }, + "id": "597f24c1dda4e70f53c79c81", + "title": "Fibonacci sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/fibonacci-word", + "blockName": "Rosetta Code" + }, + "id": "5992e222d397f00d21122931", + "title": "Fibonacci word" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/fizzbuzz", + "blockName": "Rosetta Code" + }, + "id": "5e9ddb06ec35240f39657419", + "title": "FizzBuzz" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/fractran", + "blockName": "Rosetta Code" + }, + "id": "5a7dad05be01840e1778a0d1", + "title": "Fractran" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/gamma-function", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e76", + "title": "Gamma function" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/gaussian-elimination", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e77", + "title": "Gaussian elimination" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/general-fizzbuzz", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e78", + "title": "General FizzBuzz" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/generate-lower-case-ascii-alphabet", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e7a", + "title": "Generate lower case ASCII alphabet" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/generatorexponential", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e7b", + "title": "Generator/Exponential" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/gray-code", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e80", + "title": "Gray code" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/greatest-common-divisor", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e82", + "title": "Greatest common divisor" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/greatest-subsequential-sum", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7e84", + "title": "Greatest subsequential sum" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/hailstone-sequence", + "blockName": "Rosetta Code" + }, + "id": "595608ff8bcd7a50bd490181", + "title": "Hailstone sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/happy-numbers", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad1", + "title": "Happy numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/harshad-or-niven-series", + "blockName": "Rosetta Code" + }, + "id": "595668ca4cfe1af2fb9818d4", + "title": "Harshad or Niven series" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/hash-from-two-arrays", + "blockName": "Rosetta Code" + }, + "id": "595671d4d2cdc305f0d5b36f", + "title": "Hash from two arrays" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/hash-join", + "blockName": "Rosetta Code" + }, + "id": "5956795bc9e2c415eb244de1", + "title": "Hash join" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/heronian-triangles", + "blockName": "Rosetta Code" + }, + "id": "595b98f8b5a2245e243aa831", + "title": "Heronian triangles" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/hofstadter-figure-figure-sequences", + "blockName": "Rosetta Code" + }, + "id": "59622f89e4e137560018a40e", + "title": "Hofstadter Figure-Figure sequences" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/hofstadter-q-sequence", + "blockName": "Rosetta Code" + }, + "id": "59637c4d89f6786115efd814", + "title": "Hofstadter Q sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/i-before-e-except-after-c", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7eb0", + "title": "I before E except after C" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/iban", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7eaf", + "title": "IBAN" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/identity-matrix", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7eb1", + "title": "Identity matrix" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/iterated-digits-squaring", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ec1", + "title": "Iterated digits squaring" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/jaro-distance", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ec2", + "title": "Jaro distance" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/jortsort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ec4", + "title": "JortSort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/josephus-problem", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ec5", + "title": "Josephus problem" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/k-d-tree", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ecb", + "title": "K-d tree" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/kaprekar-numbers", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7eca", + "title": "Kaprekar numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/knapsack-problem0-1", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ed1", + "title": "Knapsack problem/0-1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/knapsack-problembounded", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ed2", + "title": "Knapsack problem/Bounded" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/knapsack-problemcontinuous", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ed3", + "title": "Knapsack problem/Continuous" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/knapsack-problemunbounded", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ed4", + "title": "Knapsack problem/Unbounded" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/knights-tour", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ed5", + "title": "Knight's tour" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/largest-int-from-concatenated-ints", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7edb", + "title": "Largest int from concatenated ints" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/last-friday-of-each-month", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7edc", + "title": "Last Friday of each month" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/last-letter-first-letter", + "blockName": "Rosetta Code" + }, + "id": "5e4ce2b6ac708cc68c1df25e", + "title": "Last letter-first letter" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/leap-year", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ede", + "title": "Leap year" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/least-common-multiple", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7edf", + "title": "Least common multiple" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/left-factorials", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ee0", + "title": "Left factorials" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/letter-frequency", + "blockName": "Rosetta Code" + }, + "id": "5e4ce2bbac708cc68c1df25f", + "title": "Letter frequency" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/levenshtein-distance", + "blockName": "Rosetta Code" + }, + "id": "5e4ce2eaac708cc68c1df260", + "title": "Levenshtein distance" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/linear-congruential-generator", + "blockName": "Rosetta Code" + }, + "id": "5e4ce2f5ac708cc68c1df261", + "title": "Linear congruential generator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/long-multiplication", + "blockName": "Rosetta Code" + }, + "id": "5e4ce2a1ac708cc68c1df25d", + "title": "Long multiplication" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/longest-common-subsequence", + "blockName": "Rosetta Code" + }, + "id": "5e6dd1278e6ca105cde40ea9", + "title": "Longest common subsequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/longest-increasing-subsequence", + "blockName": "Rosetta Code" + }, + "id": "5e6dd139859c290b6ab80292", + "title": "Longest increasing subsequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/longest-string-challenge", + "blockName": "Rosetta Code" + }, + "id": "5e6dd14192286d95fc43046e", + "title": "Longest string challenge" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/look-and-say-sequence", + "blockName": "Rosetta Code" + }, + "id": "5e6dd14797f5ce267c2f19d0", + "title": "Look-and-say sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/loop-over-multiple-arrays-simultaneously", + "blockName": "Rosetta Code" + }, + "id": "5e6dd15004c88cf00d2a78b3", + "title": "Loop over multiple arrays simultaneously" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/lu-decomposition", + "blockName": "Rosetta Code" + }, + "id": "5e6decd8ec8d7db960950d1c", + "title": "LU decomposition" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/lucas-lehmer-test", + "blockName": "Rosetta Code" + }, + "id": "5e6dee7749a0b85a3f1fc7d5", + "title": "Lucas-Lehmer test" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/ludic-numbers", + "blockName": "Rosetta Code" + }, + "id": "5ea281203167d2b0bdefca00", + "title": "Ludic numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/luhn-test-of-credit-card-numbers", + "blockName": "Rosetta Code" + }, + "id": "5ea28156e79528a9ab248f27", + "title": "Luhn test of credit card numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/lychrel-numbers", + "blockName": "Rosetta Code" + }, + "id": "5ea2815a8640bcc6cb7dab3c", + "title": "Lychrel numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/lzw-compression", + "blockName": "Rosetta Code" + }, + "id": "5ea2815e364d9a2222ea55f8", + "title": "LZW compression" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/s-expressions", + "blockName": "Rosetta Code" + }, + "id": "59667989bf71cf555dd5d2ff", + "title": "S-Expressions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sailors-coconuts-and-a-monkey-problem", + "blockName": "Rosetta Code" + }, + "id": "59da22823d04c95919d46269", + "title": "Sailors, coconuts and a monkey problem" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/search-a-list-of-records", + "blockName": "Rosetta Code" + }, + "id": "5eb3e497b8d6d7f63c5517ea", + "title": "Search a list of records" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sedols", + "blockName": "Rosetta Code" + }, + "id": "59d9c6bc214c613ba73ff012", + "title": "SEDOLs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/self-describing-numbers", + "blockName": "Rosetta Code" + }, + "id": "5eaf48389ee512d4d103684b", + "title": "Self Describing Numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/self-referential-sequence", + "blockName": "Rosetta Code" + }, + "id": "5eb3e4a21f462f409d656c73", + "title": "Self-referential sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/semiprime", + "blockName": "Rosetta Code" + }, + "id": "5eb3e4aa847216613aa81983", + "title": "Semiprime" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/set-consolidation", + "blockName": "Rosetta Code" + }, + "id": "5eb3e4af7d0e7b760b46cedc", + "title": "Set consolidation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/set-of-real-numbers", + "blockName": "Rosetta Code" + }, + "id": "5eb3e4b20aa93c437f9e9717", + "title": "Set of real numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sha-1", + "blockName": "Rosetta Code" + }, + "id": "5eb3e4b5f629b9a07429a5d2", + "title": "SHA-1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sha-256", + "blockName": "Rosetta Code" + }, + "id": "5eb3e4c3a894c333d2811a3f", + "title": "SHA-256" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sort-an-array-of-composite-structures", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc7ffe", + "title": "Sort an array of composite structures" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sort-disjoint-sublist", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8000", + "title": "Sort disjoint sublist" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sort-stability", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8014", + "title": "Sort stability" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sort-using-a-custom-comparator", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8016", + "title": "Sort using a custom comparator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmsbead-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8001", + "title": "Sorting algorithms/Bead sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmsbogosort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8002", + "title": "Sorting algorithms/Bogosort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmscocktail-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8004", + "title": "Sorting algorithms/Cocktail sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmscomb-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8005", + "title": "Sorting algorithms/Comb sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmsgnome-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8007", + "title": "Sorting algorithms/Gnome sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmspancake-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc800b", + "title": "Sorting algorithms/Pancake sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmspermutation-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc800c", + "title": "Sorting algorithms/Permutation sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmsshell-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8010", + "title": "Sorting algorithms/Shell sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmsstooge-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8012", + "title": "Sorting algorithms/Stooge sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sorting-algorithmsstrand-sort", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8013", + "title": "Sorting algorithms/Strand sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/soundex", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8017", + "title": "Soundex" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/spiral-matrix", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc801c", + "title": "Spiral matrix" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/split-a-character-string-based-on-change-of-character", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc801d", + "title": "Split a character string based on change of character" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/state-name-puzzle", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8024", + "title": "State name puzzle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/stern-brocot-sequence", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8028", + "title": "Stern-Brocot sequence" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/straddling-checkerboard", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8029", + "title": "Straddling checkerboard" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/stream-merge", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc802a", + "title": "Stream Merge" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/strip-control-codes-and-extended-characters-from-a-string", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8036", + "title": "Strip control codes and extended characters from a string" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/subleq", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8038", + "title": "Subleq" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sudoku", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc803c", + "title": "Sudoku" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sum-digits-of-an-integer", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc803f", + "title": "Sum digits of an integer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sum-multiples-of-3-and-5", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8040", + "title": "Sum multiples of 3 and 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sum-of-a-series", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8041", + "title": "Sum of a series" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sum-of-squares", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8042", + "title": "Sum of squares" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sum-to-100", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8043", + "title": "Sum to 100" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/sutherland-hodgman-polygon-clipping", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8045", + "title": "Sutherland-Hodgman polygon clipping" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/symmetric-difference", + "blockName": "Rosetta Code" + }, + "id": "5a23c84252665b21eecc8046", + "title": "Symmetric difference" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/taxicab-numbers", + "blockName": "Rosetta Code" + }, + "id": "594ecc0d9a8cf816e3340187", + "title": "Taxicab numbers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/tokenize-a-string-with-escaping", + "blockName": "Rosetta Code" + }, + "id": "594faaab4e2a8626833e9c3d", + "title": "Tokenize a string with escaping" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/top-rank-per-group", + "blockName": "Rosetta Code" + }, + "id": "595011cba5a81735713873bd", + "title": "Top rank per group" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/topological-sort", + "blockName": "Rosetta Code" + }, + "id": "594fa2746886f41f7d8bf225", + "title": "Topological sort" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/towers-of-hanoi", + "blockName": "Rosetta Code" + }, + "id": "5951ed8945deab770972ae56", + "title": "Towers of Hanoi" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/vector-cross-product", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad2", + "title": "Vector cross product" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/vector-dot-product", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad3", + "title": "Vector dot product" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/word-frequency", + "blockName": "Rosetta Code" + }, + "id": "5e94a54cc7b022105bf0fd2c", + "title": "Word frequency" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/word-wrap", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad4", + "title": "Word wrap" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/y-combinator", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad5", + "title": "Y combinator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/zeckendorf-number-representation", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad6", + "title": "Zeckendorf number representation" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/zhang-suen-thinning-algorithm", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad7", + "title": "Zhang-Suen thinning algorithm" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/rosetta-code/zig-zag-matrix", + "blockName": "Rosetta Code" + }, + "id": "594810f028c0303b75339ad8", + "title": "Zig-zag matrix" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-freecodecamp-forum-homepage", + "blockName": "Take Home Projects" + }, + "id": "bd7156d8c242eddfaeb5bd13", + "title": "Build a freeCodeCamp Forum Homepage" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-light-bright-app", + "blockName": "Take Home Projects" + }, + "id": "5a5d02bd919fcf9ca8cf46cb", + "title": "Build a Light-Bright App" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-nightlife-coordination-app", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c443eddfaeb5bdff", + "title": "Build a Nightlife Coordination App" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-pinterest-clone", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c443eddfaeb5bdee", + "title": "Build a Pinterest Clone" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-pong-game", + "blockName": "Take Home Projects" + }, + "id": "5a4b7fcdb66f799f199e11db", + "title": "Build a Pong Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-recipe-box", + "blockName": "Take Home Projects" + }, + "id": "bd7155d8c242eddfaeb5bd13", + "title": "Build a Recipe Box" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-roguelike-dungeon-crawler-game", + "blockName": "Take Home Projects" + }, + "id": "bd7153d8c242eddfaeb5bd13", + "title": "Build a Roguelike Dungeon Crawler Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-simon-game", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c442eddfaeb5bd1c", + "title": "Build a Simon Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-tic-tac-toe-game", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c442eedfaeb5bd1c", + "title": "Build a Tic Tac Toe Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-voting-app", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c443eddfaeb5bdef", + "title": "Build a Voting App" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-a-wikipedia-viewer", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c442eddfaeb5bd19", + "title": "Build a Wikipedia Viewer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-an-image-search-abstraction-layer", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c443edefaeb5bdee", + "title": "Build an Image Search Abstraction Layer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/build-the-game-of-life", + "blockName": "Take Home Projects" + }, + "id": "bd7154d8c242eddfaeb5bd13", + "title": "Build the Game of Life" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/chart-the-stock-market", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c443eddfaeb5bd0e", + "title": "Chart the Stock Market" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/manage-a-book-trading-club", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c443eddfaeb5bd0f", + "title": "Manage a Book Trading Club" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/map-data-across-the-globe", + "blockName": "Take Home Projects" + }, + "id": "bd7108d8c242eddfaeb5bd13", + "title": "Map Data Across the Globe" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/p2p-video-chat-application", + "blockName": "Take Home Projects" + }, + "id": "bd7150d8c442eddfafb5bd1c", + "title": "P2P Video Chat Application" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/show-national-contiguity-with-a-force-directed-graph", + "blockName": "Take Home Projects" + }, + "id": "bd7198d8c242eddfaeb5bd13", + "title": "Show National Contiguity with a Force Directed Graph" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/show-the-local-weather", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c442eddfaeb5bd10", + "title": "Show the Local Weather" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/coding-interview-prep/take-home-projects/use-the-twitch-json-api", + "blockName": "Take Home Projects" + }, + "id": "bd7158d8c442eddfaeb5bd1f", + "title": "Use the Twitch JSON API" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/how-neural-networks-work/deep-learning-demystified", + "blockName": "How Neural Networks Work" + }, + "id": "5e9a0e9ef99a403d019610cc", + "title": "Deep Learning Demystified" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/how-neural-networks-work/how-convolutional-neural-networks-work", + "blockName": "How Neural Networks Work" + }, + "id": "5e9a0e9ef99a403d019610cd", + "title": "How Convolutional Neural Networks work" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/how-neural-networks-work/how-deep-neural-networks-work", + "blockName": "How Neural Networks Work" + }, + "id": "5e9a0e9ef99a403d019610ca", + "title": "How Deep Neural Networks Work" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/how-neural-networks-work/recurrent-neural-networks-rnn-and-long-short-term-memory-lstm", + "blockName": "How Neural Networks Work" + }, + "id": "5e9a0e9ef99a403d019610cb", + "title": "Recurrent Neural Networks RNN and Long Short Term Memory LSTM" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/machine-learning-with-python-projects/book-recommendation-engine-using-knn", + "blockName": "Machine Learning with Python Projects" + }, + "id": "5e46f8e3ac417301a38fb92f", + "title": "Book Recommendation Engine using KNN" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/machine-learning-with-python-projects/cat-and-dog-image-classifier", + "blockName": "Machine Learning with Python Projects" + }, + "id": "5e46f8dcac417301a38fb92e", + "title": "Cat and Dog Image Classifier" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/machine-learning-with-python-projects/linear-regression-health-costs-calculator", + "blockName": "Machine Learning with Python Projects" + }, + "id": "5e46f8edac417301a38fb930", + "title": "Linear Regression Health Costs Calculator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/machine-learning-with-python-projects/neural-network-sms-text-classifier", + "blockName": "Machine Learning with Python Projects" + }, + "id": "5e46f8edac417301a38fb931", + "title": "Neural Network SMS Text Classifier" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/machine-learning-with-python-projects/rock-paper-scissors", + "blockName": "Machine Learning with Python Projects" + }, + "id": "5e46f8d6ac417301a38fb92d", + "title": "Rock Paper Scissors" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/conclusion", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72da6", + "title": "Conclusion" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/convolutional-neural-networks-evaluating-the-model", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d99", + "title": "Convolutional Neural Networks: Evaluating the Model" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/convolutional-neural-networks-picking-a-pretrained-model", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d9a", + "title": "Convolutional Neural Networks: Picking a Pretrained Model" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/convolutional-neural-networks-the-convolutional-layer", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d97", + "title": "Convolutional Neural Networks: The Convolutional Layer" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/convolutional-neural-networks", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d96", + "title": "Convolutional Neural Networks" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms-building-the-model", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d8e", + "title": "Core Learning Algorithms: Building the Model" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms-classification", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d8d", + "title": "Core Learning Algorithms: Classification" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms-clustering", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d8f", + "title": "Core Learning Algorithms: Clustering" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms-hidden-markov-models", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d90", + "title": "Core Learning Algorithms: Hidden Markov Models" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms-the-training-process", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d8c", + "title": "Core Learning Algorithms: The Training Process" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms-training-and-testing-data", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d8b", + "title": "Core Learning Algorithms: Training and Testing Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms-using-probabilities-to-make-predictions", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d91", + "title": "Core Learning Algorithms: Using Probabilities to make Predictions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms-working-with-data", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d8a", + "title": "Core Learning Algorithms: Working with Data" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/core-learning-algorithms", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d89", + "title": "Core Learning Algorithms" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/creating-a-convolutional-neural-network", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d98", + "title": "Creating a Convolutional Neural Network" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/introduction-machine-learning-fundamentals", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d87", + "title": "Introduction: Machine Learning Fundamentals" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/introduction-to-tensorflow", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d88", + "title": "Introduction to TensorFlow" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/natural-language-processing-with-rnns-building-the-model", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72da1", + "title": "Natural Language Processing With RNNs: Building the Model" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/natural-language-processing-with-rnns-create-a-play-generator", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72da0", + "title": "Natural Language Processing With RNNs: Create a Play Generator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/natural-language-processing-with-rnns-making-predictions", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d9f", + "title": "Natural Language Processing With RNNs: Making Predictions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/natural-language-processing-with-rnns-part-2", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d9c", + "title": "Natural Language Processing With RNNs: Part 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/natural-language-processing-with-rnns-recurring-neural-networks", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d9d", + "title": "Natural Language Processing With RNNs: Recurring Neural Networks" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/natural-language-processing-with-rnns-sentiment-analysis", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d9e", + "title": "Natural Language Processing With RNNs: Sentiment Analysis" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/natural-language-processing-with-rnns-training-the-model", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72da2", + "title": "Natural Language Processing With RNNs: Training the Model" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/natural-language-processing-with-rnns", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d9b", + "title": "Natural Language Processing With RNNs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/neural-networks-activation-functions", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d93", + "title": "Neural Networks: Activation Functions" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/neural-networks-creating-a-model", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d95", + "title": "Neural Networks: Creating a Model" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/neural-networks-optimizers", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d94", + "title": "Neural Networks: Optimizers" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/neural-networks-with-tensorflow", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72d92", + "title": "Neural Networks with TensorFlow" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/reinforcement-learning-with-q-learning-example", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72da5", + "title": "Reinforcement Learning With Q-Learning: Example" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/reinforcement-learning-with-q-learning-part-2", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72da4", + "title": "Reinforcement Learning With Q-Learning: Part 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/machine-learning-with-python/tensorflow/reinforcement-learning-with-q-learning", + "blockName": "TensorFlow" + }, + "id": "5e8f2f13c4cdbe86b5c72da3", + "title": "Reinforcement Learning With Q-Learning" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/build-a-celestial-bodies-database-project/build-a-celestial-bodies-database", + "blockName": "Build A Celestial Bodies Database Project" + }, + "id": "5f1a4ef5d5d6b5ab580fc6ae", + "title": "Build a Celestial Bodies Database" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/build-a-number-guessing-game-project/build-a-number-guessing-game", + "blockName": "Build A Number Guessing Game Project" + }, + "id": "602da04c22201c65d2a019f4", + "title": "Build a Number Guessing Game" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/build-a-periodic-table-database-project/build-a-periodic-table-database", + "blockName": "Build A Periodic Table Database Project" + }, + "id": "602d9ff222201c65d2a019f2", + "title": "Build a Periodic Table Database" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/build-a-salon-appointment-scheduler-project/build-a-salon-appointment-scheduler", + "blockName": "Build A Salon Appointment Scheduler Project" + }, + "id": "5f87ac112ae598023a42df1a", + "title": "Build a Salon Appointment Scheduler" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/build-a-world-cup-database-project/build-a-world-cup-database", + "blockName": "Build A World Cup Database Project" + }, + "id": "5f9771307d4d22b9d2b75a94", + "title": "Build a World Cup Database" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-advanced-bash-by-building-a-kitty-ipsum-translator/build-a-kitty-ipsum-translator", + "blockName": "Learn Advanced Bash By Building A Kitty Ipsum Translator" + }, + "id": "602da0de22201c65d2a019f6", + "title": "Build a Kitty Ipsum Translator" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-bash-and-sql-by-building-a-bike-rental-shop/build-a-bike-rental-shop", + "blockName": "Learn Bash and Sql By Building A Bike Rental Shop" + }, + "id": "5f5b969a05380d2179fe6e18", + "title": "Build a Bike Rental Shop" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-bash-by-building-a-boilerplate/build-a-boilerplate", + "blockName": "Learn Bash By Building A Boilerplate" + }, + "id": "5ea8adfab628f68d805bfc5e", + "title": "Build a Boilerplate" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-bash-scripting-by-building-five-programs/build-five-programs", + "blockName": "Learn Bash Scripting By Building Five Programs" + }, + "id": "5f5904ac738bc2fa9efecf5a", + "title": "Build Five Programs" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-git-by-building-an-sql-reference-object/build-an-sql-reference-object", + "blockName": "Learn Git By Building An Sql Reference Object" + }, + "id": "5fa323cdaf6a73463d590659", + "title": "Build an SQL Reference Object" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-nano-by-building-a-castle/build-a-castle", + "blockName": "Learn Nano By Building A Castle" + }, + "id": "5f32db63eb37f7e17323f459", + "title": "Build a Castle" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-relational-databases-by-building-a-mario-database/build-a-mario-database", + "blockName": "Learn Relational Databases By Building A Mario Database" + }, + "id": "5f2c289f164c29556da632fd", + "title": "Build a Mario Database" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-sql-by-building-a-student-database-part-1/build-a-student-database-part-1", + "blockName": "Learn Sql By Building A Student Database Part 1" + }, + "id": "602da0c222201c65d2a019f5", + "title": "Build a Student Database: Part 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/relational-database/learn-sql-by-building-a-student-database-part-2/build-a-student-database-part-2", + "blockName": "Learn Sql By Building A Student Database Part 2" + }, + "id": "618590adb0730ca724e37672", + "title": "Build a Student Database: Part 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/build-a-personal-portfolio-webpage-project/build-a-personal-portfolio-webpage", + "blockName": "Build A Personal Portfolio Webpage Project" + }, + "id": "bd7158d8c242eddfaeb5bd13", + "title": "Build a Personal Portfolio Webpage" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/build-a-product-landing-page-project/build-a-product-landing-page", + "blockName": "Build A Product Landing Page Project" + }, + "id": "587d78af367417b2b2512b04", + "title": "Build a Product Landing Page" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/build-a-survey-form-project/build-a-survey-form", + "blockName": "Build A Survey Form Project" + }, + "id": "587d78af367417b2b2512b03", + "title": "Build a Survey Form" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/build-a-technical-documentation-page-project/build-a-technical-documentation-page", + "blockName": "Build A Technical Documentation Page Project" + }, + "id": "587d78b0367417b2b2512b05", + "title": "Build a Technical Documentation Page" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/build-a-tribute-page-project/build-a-tribute-page", + "blockName": "Build A Tribute Page Project" + }, + "id": "bd7158d8c442eddfaeb5bd18", + "title": "Build a Tribute Page" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-2", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "613297a923965e0703b64796", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-3", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61329b210dac0b08047fd6ab", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-4", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61329d52e5010e08d9b9d66b", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-5", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6133acc353338c0bba9cb553", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-6", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6133d11ef548f51f876149e3", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-7", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "613e2546d0594208229ada50", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-8", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "613e275749ebd008e74bb62e", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-9", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6140827cff96e906bd38fc2b", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-10", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6140883f74224508174794c0", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-11", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61408e4ae3e35d08feb260eb", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-12", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61408f155e798909b6908712", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-13", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614090d5a22b6f0a5a6b464c", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-14", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6141fabd6f75610664e908fd", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-15", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6141fed65b61320743da5894", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-16", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614202874ca576084fca625f", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-17", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614206033d366c090ca7dd42", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-18", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61435e3c0679a306c20f1acc", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-19", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6143610161323a081b249c19", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-20", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6143639d5eddc7094161648c", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-21", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6143908b6aafb00a659ca189", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-22", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6143920c8eafb00b735746ce", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-23", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6143931a113bb80c45546287", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-24", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614394fb41985e0d2012a93e", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-25", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6143956ed76ed60e012faa51", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-26", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614396f7ae83f20ea6f9f4b3", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-27", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6143cb26f7edff2dc28f7da5", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-28", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6144e818fd5ea704fe56081d", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-29", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6144f8dc6849e405dd8bb829", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-30", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145e6eeaa66c605eb087fe9", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-32", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145e8b5080a5f06bb0223d0", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-33", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145eb5f08a38a0786c7a80c", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-34", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145ed1f22caab087630aaad", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-35", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145ee65e2e1530938cb594d", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-36", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145f02240ff8f09f7ec913c", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-37", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145f14f019a4b0adb94b051", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-38", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145f3a5cd9be60b9459cdd6", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-39", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145f47393fbe70c4d885f9c", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-40", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145f59029474c0d3dc1c8b8", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-41", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145f685797bd30df9784e8c", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-42", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145f829ac6a920ebf5797d7", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-43", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145f8f8bcd4370f6509078e", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-44", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145fb5018cb5b100cb2a88c", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-45", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6145fc3707fc3310c277f5c8", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-46", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614796cb8086be482d60e0ac", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-47", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6147a14ef5668b5881ef2297", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-48", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614878f7a412310647873015", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-49", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61487b77d4a37707073a64e5", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-50", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61487da611a65307e78d2c20", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-51", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61487f703571b60899055cf9", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-52", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614880dc16070e093e29bc56", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-53", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614883b6fa720e09fb167de9", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-54", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614884c1f5d6f30ab3d78cde", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-55", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "61488ecfd05e290b5712e6da", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-56", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148d99cdc7acd0c519862cb", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-57", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148da157cc0bd0d06df5c0a", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-58", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148dc095264000dce348bf5", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-59", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148dcaaf2e8750e6cb4501a", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-60", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148dd31d210990f0fb140f8", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-61", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148defa9c01520fb9d178a0", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-62", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148dfab9b54c110577de165", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-63", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148e0bcc13efd10f7d7a6a9", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-64", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148e161ecec9511941f8833", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-65", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148e28706b34912340fd042", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-66", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148e335c1edd512d00e4691", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-67", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148e41c728f65138addf9cc", + "title": "Step 67" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-68", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6148e5aeb102e3142de026a2", + "title": "Step 68" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-1", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "614ccc21ea91ef1736b9b578", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-accessibility-by-building-a-quiz/step-31", + "blockName": "Learn Accessibility by Building a Quiz" + }, + "id": "6351e7a8684bf5377c4ee7f7", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-1", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f33071498eb2472b87ddee4", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-2", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3313e74582ad9d063e3a38", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-3", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f331e55dfab7a896e53c3a1", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-4", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3326b143638ee1a09ff1e3", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-5", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f33294a6af5e9188dbdb8f3", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-6", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f332a88dc25a0fd25c7687a", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-7", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f332b23c2045fb843337579", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-11", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f344f9c805cd193c33d829c", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-10", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f344fad8bf01691e71a30eb", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-9", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f344fbc22624a2976425065", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-8", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f344fc1520b6719f2e35605", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-13", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3477ae34c1239cafe128be", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-15", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3477ae8466a9a3d2cc953c", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-12", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3477ae9675db8bb7655b30", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-14", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3477aefa51bfc29327200b", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-16", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3477cb2e27333b1ab2b955", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-18", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3477cb303c5cb61b43aa9b", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-17", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3477cbcb6ba47918c1da92", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-19", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f34a1fd611d003edeafd681", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-24", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f356ed60785e1f3e9850b6e", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-22", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f356ed60a5decd94ab66986", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-26", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f356ed6199b0cdef1d2be8f", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-21", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f356ed63c7807a4f1e6d054", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-23", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f356ed63e0fa262326eef05", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-25", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f356ed656a336993abd9f7c", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-27", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f356ed69db0a491745e2bb6", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-20", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f356ed6cf6eab5f15f5cfe6", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-29", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f35e5c4321f818cdc4bed30", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-28", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f35e5c44359872a137bd98f", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-38", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3c866d0fc037f7311b4ac8", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-32", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3c866d28d7ad0de6470505", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-31", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3c866d5414453fc2d7b480", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-30", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3c866daec9a49519871816", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-37", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3c866dbf362f99b9a0c6d0", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-39", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3c866dd0d0275f01d4d847", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-36", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3c866de7a5b784048f94b1", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-41", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3cade94c6576e7f7b7953f", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-42", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3cade9993019e26313fa8e", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-46", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3cade99dda4e6071a85dfd", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-40", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3cade9fa77275d9f4efe62", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-66", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e01f288a026d709587", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-56", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e03d719d5ac4738993", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-55", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e04559b939080db057", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-54", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e050279c7a4a7101d3", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-57", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e05473f91f948724ab", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-58", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e056bdde6ae6892ba2", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-60", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e06d34faac0447fc44", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-63", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e07276f782bb46b93d", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-48", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e0819d4f23ca7285e6", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-61", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e087d56ed3ffdc36be", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-64", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e0a81099d9a697b550", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-65", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e0b431cc215bb16f55", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-47", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e0e0c3feaebcf647ad", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-59", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e0e9629bad967cd71e", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-53", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e0eaa7da26e3d34d78", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-62", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3ef6e0f8c230bdd2349716", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-67", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f3f26fa39591db45e5cd7a0", + "title": "Step 67" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-68", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f459225127805351a6ad057", + "title": "Step 68" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-69", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f459a7ceb8b5c446656d88b", + "title": "Step 69" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-70", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f459cf202c2a3472fae6a9f", + "title": "Step 70" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-71", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f459fd48bdc98491ca6d1a3", + "title": "Step 71" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-72", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45a05977e2fa49d9119437", + "title": "Step 72" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-73", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45a276c093334f0f6e9df4", + "title": "Step 73" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-74", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45a5a7c49a8251f0bdb527", + "title": "Step 74" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-78", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45a66d4a2b0453301e5a26", + "title": "Step 78" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-79", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45b0731d39e15d54df4dfc", + "title": "Step 79" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-80", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45b25e7ec2405f166b9de1", + "title": "Step 80" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-81", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45b3c93c027860d9298dbd", + "title": "Step 81" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-82", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45b45d099f3e621fbbb256", + "title": "Step 82" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-83", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45b4c81cea7763550e40df", + "title": "Step 83" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-84", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f45b715301bbf667badc04a", + "title": "Step 84" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-85", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f46e270702a8456a664f0df", + "title": "Step 85" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-86", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f46e36e745ead58487aabf2", + "title": "Step 86" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-87", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f46e7a4750dd05b5a673920", + "title": "Step 87" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-88", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f46e8284aae155c83015dee", + "title": "Step 88" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-77", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f46ede1ff8fec5ba656b44c", + "title": "Step 77" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-75", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f46fc57528aa1c4b5ea7c2e", + "title": "Step 75" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-76", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f4701b942c824109626c3d8", + "title": "Step 76" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-89", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f475bb508746c16c9431d42", + "title": "Step 89" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-90", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f475e1c7f71a61d913836c6", + "title": "Step 90" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-45", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f47633757ae3469f2d33d2e", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-91", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f47fe7e31980053a8d4403b", + "title": "Step 91" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-49", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f716ad029ee4053c7027a7a", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-52", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f716bee5838c354c728a7c5", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-43", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f7691dafd882520797cd2f0", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-44", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f7692f7c5b3ce22a57788b6", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-33", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f769541be494f25449b292f", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-34", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f76967fad478126d6552b0d", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-35", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f769702e6e33127d14aa120", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-50", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f7b87422a560036fd03ccff", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-basic-css-by-building-a-cafe-menu/step-51", + "blockName": "Learn Basic CSS by Building a Cafe Menu" + }, + "id": "5f7b88d37b1f98386f04edc0", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-1", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140c7e645d8e905819f1dd4", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-2", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140c9d35015ae0ba0c250e8", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-3", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140cbeec34e970dfe75e710", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-4", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140cd32d018ed0f600eefce", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-6", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140cdebd39d6a101e747529", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-7", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140cfc08ca9c5128c3e6478", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-8", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d0069049f5139d78da40", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-9", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d10d50636e14695013b2", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-10", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d1a351e88f159ed54fca", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-11", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d263016325162fd076fe", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-12", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d2b687a2cd17bac5730c", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-13", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d36b8b747718b50d4b7a", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-14", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d3dc359b371b1a21d783", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-15", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d4bc9db3c81c51a09ab7", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-16", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140d94b5fab7f1d73c9bedb", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-17", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140dc5e13d0c81e7496f182", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-18", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140dd77e0bc5a1f70bd7466", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-19", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140de31b1f5b420410728ff", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-20", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140df547f09402144e40b92", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-21", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140e0d875ec16262f26432b", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-22", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6140f4b5c1555a2960de1e5f", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-23", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "614100d7d335bb2a5ff74f1f", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-24", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "61410126fa3a6d2b3cda502e", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-25", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6141019eadec6d2c6c6f007b", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-26", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6141026ec9882f2d39dcf2b8", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-27", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6169ab1aaeb4cd1174def700", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-28", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6169b1357fcb701bb5efc619", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-29", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "6169b284950e171d8d0bb16a", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-animation-by-building-a-ferris-wheel/step-5", + "blockName": "Learn CSS Animation by Building a Ferris Wheel" + }, + "id": "617ace7d831f9c16a569b38a", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-1", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61695197ac34f0407e339882", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-2", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61695ab9f6ffe951c16d03dd", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-3", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61695c4aad56f95497c19583", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-4", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61695d1fbc003856628bf561", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-5", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616965351e74d4689eb6de30", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-6", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616968c2c94c8071b349c146", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-7", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61696ef7ac756c829f9e4048", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-8", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616971b3cd990186b66c99a1", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-9", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616d3a67ccf800ad94ec89ae", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-10", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616d47bc9eedc4bc7f621bec", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-11", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616d4a84b756d9c4b8255093", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-12", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616d50b93ba424d6282c99cf", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-13", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616d525007b8c5d8b3308b1c", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-14", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616d55bd160a95e22453a081", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-15", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "616d595270d902f0e7086e18", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-16", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61764c602bee6974e7790f35", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-17", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61764f23ea21477b76f3b80f", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-18", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61764f7e5240eb7ccc7f6a0a", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-19", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61764fdda535587e1fefb3aa", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-20", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "6176519636a76b810ab1219a", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-21", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617b65579ce424bf5f02ca73", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-22", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617b8b38f32bf2080a140675", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-23", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617b8e0d93a8d10d9a90e720", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-24", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617b92b9de349513466f6156", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-25", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617b954d9f4f6217a749380e", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-26", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617b97abd9f3f61d1590b815", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-27", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617b9ad735109e217284e095", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-28", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617bb5624a75e86463b7e638", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-29", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617bb77353188166af43f3ac", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-30", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617bb9fdef27bc6aa0470ac2", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-31", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617bbb6b97a83f6d1f7d6e38", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-32", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617bc3386dc7d07d6469bf20", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-33", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617bc4824e233180553a8069", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-34", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "617bd6ec666b1da2587e4e37", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-35", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "618a00ed1ca871a2b3aca0cb", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-36", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "618a0927005553b74bfa05ae", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-37", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "618a0b2befb143baefab632b", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-38", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "618a1275e873dcc803c2d1aa", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-39", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "618a132676346ac9f7fd59dd", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-40", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "618a16873520a8d088ffdf44", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-41", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "618a16d21bd3dad1bb3aa8ef", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-42", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "619b72a0db211f1c29afb906", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-43", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "619b7396e57b771f903be90d", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-44", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "619b7424f43ec9215e538afe", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-45", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "619b74fa777a2b2473c94f82", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-46", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "619b761916dac02643940022", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-47", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "619b7c3c83de403126b69c1e", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-48", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "619b7fd56aa2253778bcf5f7", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-49", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a489b8579e87364b2d2cdb", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-50", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a493ead935c148d2b76312", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-53", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a498399534644f59cff05e", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-54", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a49d15bdbb5e57cc6fd280", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-55", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a4a53c4459446dc134a1c6", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-56", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a4a6e908bc34725b4c25ac", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-57", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a4a7877da33a73a1c1723e", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-58", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a4ac092eb21e7dbfe61c33", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-59", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a4acbb5587197f68544d00", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-60", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a4ada3aabeec822b2975d9", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-61", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a4ae5f29eb5584187201c3", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-63", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a5be9833e7dc178de2af10", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-64", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a5bfe091060f1d6a629dd0", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-65", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a5c906ab73313316e342f0", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-66", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a5ca57f50ded36d33eef96", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-67", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a5d594b887335228ee6533", + "title": "Step 67" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-68", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a5d6701ee08953ca375243", + "title": "Step 68" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-69", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a5d79c858bef560e26c685", + "title": "Step 69" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-70", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61a5d7ef1cfcf45764df07a2", + "title": "Step 70" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-71", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61adc60b69cd4b87739d2174", + "title": "Step 71" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-79", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61adc91467b5d59328b9f781", + "title": "Step 79" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-80", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61add79e739a5faee9d96080", + "title": "Step 80" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-81", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61add929e41980b1edbdba7e", + "title": "Step 81" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-82", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61addaf7e83988b59a7d18ff", + "title": "Step 82" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-83", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61ade49b2dad60c076cbd32d", + "title": "Step 83" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-72", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b092eb9e7fc020b43b1bb2", + "title": "Step 72" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-73", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b093179e7fc020b43b1bb3", + "title": "Step 73" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-74", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b093219e7fc020b43b1bb4", + "title": "Step 74" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-75", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b093329e7fc020b43b1bb5", + "title": "Step 75" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-76", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b093429e7fc020b43b1bb6", + "title": "Step 76" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-77", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b0934c9e7fc020b43b1bb7", + "title": "Step 77" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-78", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b0936d9e7fc020b43b1bb8", + "title": "Step 78" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-51", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b095989e7fc020b43b1bb9", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-52", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b095a79e7fc020b43b1bba", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-62", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b095c79e7fc020b43b1bbb", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-84", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b09f739aa6572d2064f9b8", + "title": "Step 84" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-85", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b0a1b2af494934b7ec1a72", + "title": "Step 85" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-86", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b0a44a6b865738ba49b9fb", + "title": "Step 86" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-87", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b306305810f1c9040ce5a2", + "title": "Step 87" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-88", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b30995968123ceb6b76167", + "title": "Step 88" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-89", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b30a286c228bd0c493c09a", + "title": "Step 89" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-90", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b31287fb580ae75a486047", + "title": "Step 90" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-91", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b315e76a63b3ecbbb11b75", + "title": "Step 91" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-92", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b3183655ec10efd8c0bb07", + "title": "Step 92" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-93", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b31a451057fff645ec09be", + "title": "Step 93" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-colors-by-building-a-set-of-colored-markers/step-94", + "blockName": "Learn CSS Colors by Building a Set of Colored Markers" + }, + "id": "61b31cd7b0c76bfc076b4719", + "title": "Step 94" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-1", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "61537485c4f2a624f18d7794", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-2", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "61537a8054753e2f1f2a1574", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-3", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "61537bb9b1a29430ac15ad38", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-4", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "61537c5f81f0cf325b4a854c", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-5", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "61537c9eecea6a335db6da79", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-6", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "61537d86bdc3dd343688fceb", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-7", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "615380dff67172357fcf0425", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-9", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153893900438b4643590367", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-10", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153897c27f6334716ee5abe", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-11", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "615389bd81347947ea7ba896", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-12", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153908a366afb4d57185c8d", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-13", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "615392916d83fa4f02f7e2cf", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-14", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153938dce8b294ff8f5a4e9", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-15", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153947986535e5117e60615", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-16", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "61539e07e7430b528fbffe21", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-17", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "61539f32a206bd53ec116465", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-18", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153a04847abee57a3a406ac", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-19", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153a3485f0b20591d26d2a1", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-20", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153a3952facd25a83fe8083", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-21", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "6153a3ebb4f7f05b8401b716", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-flexbox-by-building-a-photo-gallery/step-8", + "blockName": "Learn CSS Flexbox by Building a Photo Gallery" + }, + "id": "615f171d05def3218035dc85", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-1", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "61437d575fb98f57fa8f7f36", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-2", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "614385513d91ae5c251c2052", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-3", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143862a5e54455d262c212e", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-4", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143869bb45bd85e3b1926aa", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-7", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "614387cbefeeba5f3654a291", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-9", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "614389f601bb4f611db98563", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-10", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "61438b5b66d76a6264430f2a", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-11", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "61438ec09438696391076d6a", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-12", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "61439dc084fa5f659cf75d7c", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-13", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "61439dfc811e12666b04be6f", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-14", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "61439e33e4fb7967609e0c83", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-15", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143a1a228f7d068ab16a130", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-16", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143a73279ce6369de4b9bcc", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-17", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143a778bffc206ac6b1dbe3", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-18", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143a83fcc32c26bcfae3efa", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-19", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143b97c06c3306d23d5da47", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-20", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143b9e1f5035c6e5f2a8231", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-21", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143bb50e8e48c6f5ef9d8d5", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-22", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143c2a363865c715f1a3f72", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-23", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143cd08fe927072ca3a371d", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-24", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143cdf48b634a747de42104", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-25", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143d003ad9e9d76766293ec", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-26", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6143d2842b497779bad947de", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-27", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144d66a5358db0c80628757", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-28", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144d7dbdd3e580da730ff45", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-29", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144de308591ec10e27d5383", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-30", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144e1ba93e435127a7f516d", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-31", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144ee46a9d6e614c598cc05", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-32", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144ee790af79815ad15a832", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-33", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144f1410990ea17187a722b", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-34", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144f3818bfbc51844152e36", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-35", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144f42204c8c8195f1f3345", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-36", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6144f47b7c631e1a6f304dd5", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-37", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148b07081759c2c691166a9", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-38", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148b0d764e4192e5712ed92", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-39", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148b185ef37522f688316b0", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-40", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148b30464daf630848c21d4", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-41", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148b4b150434734143db6f2", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-42", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148b5623efa8f369f2c3643", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-44", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148b59ef318e03875f35c4a", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-45", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148bd62bbb8c83a5f1fc1b3", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-46", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148be3d605d6b3ca9425d11", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-47", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148be82ca63c63daa8cca49", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-48", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148bf49fcc7913f05dbf9b7", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-49", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148bfc43df3bc40fe0e6405", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-50", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148c004ffc8434252940dc3", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-51", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148c224ecb157439bc5247c", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-52", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148c434bd731d45617a76c6", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-53", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148c5036ddad94692a66230", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-54", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148c58bace368497fb11bcf", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-55", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148c6aa9981d74af202125e", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-56", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148c721e74ecd4c619ae51c", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-57", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148ceaf5d897d4d8b3554b3", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-58", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148cf094b3f2b4e8a032c63", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-59", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d0b863d10d50544ace0e", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-60", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d1bdf39c5b5186f5974b", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-61", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d1f9eb63c252e1f8acc4", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-62", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d2444d01ab541e64a1e4", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-63", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d33e31fccf558696c745", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-64", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d3fff5186b57123d97e2", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-65", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d4d57b965358c9fa38bf", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-66", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d7720f0db36775db868a", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-67", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d94fdf6a5d6899f8ff15", + "title": "Step 67" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-68", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148d9825b50a3698aeee644", + "title": "Step 68" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-69", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148e162e255676ae0da6a76", + "title": "Step 69" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-70", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148e19c3e26436be0155690", + "title": "Step 70" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-71", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148e246146b646cf4255f0c", + "title": "Step 71" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-72", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148e2dcdd60306dd77d41cc", + "title": "Step 72" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-73", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148e4d6861a486f60681f36", + "title": "Step 73" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-74", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148e5a204d99e70343a63e4", + "title": "Step 74" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-75", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148e62a6f768f71c4f04828", + "title": "Step 75" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-76", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148e789329dc9736ce59b85", + "title": "Step 76" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-77", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148f34ebedc2274bceeb99c", + "title": "Step 77" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-78", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148f600cde42b7670c2611f", + "title": "Step 78" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-79", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148f693e0728f77c87f3020", + "title": "Step 79" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-80", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6148f6f7d8914c78e93136ca", + "title": "Step 80" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-43", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "614e0e503b110f76d3ac2ff6", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-6", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "614e0e588f0e8a772a8a81a6", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-5", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6165d3b702a5d92ad970b30c", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-grid-by-building-a-magazine/step-8", + "blockName": "Learn CSS Grid by Building a Magazine" + }, + "id": "6169cd8a558aa8434e0ad7f6", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-1", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619665c9abd72906f3ad30f9", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-2", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61967e74a8e3690ab6292daa", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-3", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61968df2acd5550bf1616c34", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-5", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61968e9243a4090cc805531c", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-6", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61968f8877c6720d6d61aaf5", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-7", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619691693bc14b0e528f5a20", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-8", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196928658b6010f28c39484", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-10", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619692ff79f5770fc6d8c0b4", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-11", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196990f966e8f10a40094f6", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-12", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619699c10a0f6e11591d73c4", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-13", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61969aa6acef5b12200f672e", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-14", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61969c487ced6f12db8fef94", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-15", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61969d66cfcdba137d021558", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-16", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61969e7451455614217e901b", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-17", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196adc17f77a714d51485f2", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-18", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196aead7ac7bf1584b17a7f", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-19", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196ce0415498d2463989e84", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-20", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196cee94c6da1253809dff9", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-21", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196d00a5d7292262bc02f4c", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-22", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196d0cda039d026f7f78d1e", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-24", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196d213d99f16287bff22ae", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-25", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196d2c0f22ca0293107c048", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-26", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196d32d1340d829f0f6f57d", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-27", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196d41d40bf9b2aaea5d520", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-28", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6197cff995d03905b0cca8ad", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-29", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6197f40a16afea068c7e60c8", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-9", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6197f667297bb30a552ce017", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-30", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61993b72e874e709b8dfd666", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-31", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61993cf26a8e0f0a553db223", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-32", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61993dbb35adf30b10d49e38", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-33", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61993e9adc9e9a0bb4d28fff", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-34", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6199409834ccaf0d10736596", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-35", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6199429802b7c10dc79ff871", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-36", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619943285a41720e6370d985", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-37", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619943876b706d0f35c01dbc", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-38", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6199442866286d0ff421a4fc", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-39", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619bcf239fc15905ecd66fce", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-40", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619be73b3c806006ccc00bb0", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-41", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619be7af7b0bf60770f5d2a4", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-42", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619be80062551a080e32c821", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-43", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619be8ce4ea49008c5bfbc30", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-44", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619be946958c6009844f1dee", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-45", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619c155df0063a0a3fec0e32", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-46", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619c16debd0c270b01c5ce38", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-47", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619cfdf2e63ddf05feab86ad", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-48", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d019488f98c06acbbb71a", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-49", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d022dc8400c0763829a17", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-50", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d02c7bc95bf0827a5d296", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-51", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d033915012509031f309a", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-52", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d03dadadb6509a16f4f5f", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-53", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0503e03a790a4179d463", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-54", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d05c54dabca0b10058235", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-55", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0882f54bf40bdc4671ed", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-56", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d090cd8d6db0c93dc5087", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-57", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0b51ca42ed0d74582186", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-58", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0bc9cb05360e1bf549c3", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-59", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0c1594c38c0ebae75878", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-60", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0d18ca99870f884a7bff", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-61", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0daf214542102739b0da", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-62", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0e56f9ca9710fcb974e3", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-63", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0eec0ac40611b41e2ccc", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-64", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d0fc9825c271253df28d4", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-65", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d102d786c3d13124c37c6", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-66", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d107edf7ddf13cc77106a", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-67", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d10cc98145f14820399c5", + "title": "Step 67" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-68", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d115e2adcd71538e82ebb", + "title": "Step 68" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-69", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d11e6d5ef9515d2a16033", + "title": "Step 69" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-70", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d129a417d0716a94de913", + "title": "Step 70" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-71", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d1340361095175f4b5115", + "title": "Step 71" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-72", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d15797b580c1828b05426", + "title": "Step 72" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-73", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d15d955d9d418c4487bbc", + "title": "Step 73" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-74", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d1629a8adc61960ca8b40", + "title": "Step 74" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-75", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d1c5fc9f8941a400955da", + "title": "Step 75" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-76", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d1dab9ff3421ae1976991", + "title": "Step 76" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-77", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d1deb8b04811b8839ffe4", + "title": "Step 77" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-78", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d1e7a8e81a61c5a819dc4", + "title": "Step 78" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-79", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d1ed33c9a071cf657a0d6", + "title": "Step 79" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-80", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d1fb5d244c31db8a7fdb7", + "title": "Step 80" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-81", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d204bd73ae51e743b8e94", + "title": "Step 81" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-82", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d20b12996101f430920fb", + "title": "Step 82" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-83", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d21fe6a3f9b2016be9d9d", + "title": "Step 83" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-84", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d229b0e542520cd91c685", + "title": "Step 84" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-85", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d23089e787e216a7043d6", + "title": "Step 85" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-86", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d237a107c10221ed743fa", + "title": "Step 86" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-87", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d26b12e651022d80cd017", + "title": "Step 87" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-88", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d2712853306238f41828e", + "title": "Step 88" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-89", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d2b7a84e78b246f2d17a2", + "title": "Step 89" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-90", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d2bd9c1d43c2526e96f1f", + "title": "Step 90" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-91", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d2d4e80400325ff89664a", + "title": "Step 91" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-92", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d2ebc81ba81271460850d", + "title": "Step 92" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-93", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d2f0e9440bc27caee1cec", + "title": "Step 93" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-94", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d2fd3ff4f772882e3d998", + "title": "Step 94" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-95", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d30350883802921bfcccc", + "title": "Step 95" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-96", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d324f5915c929f36ae91d", + "title": "Step 96" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-97", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d32c7fa21f32aaa91d499", + "title": "Step 97" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-98", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d333b738e3c2b5d58b095", + "title": "Step 98" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-99", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d337765b9f02c10e93722", + "title": "Step 99" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-100", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d33c51140292cc5a21742", + "title": "Step 100" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-101", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d3482f505452d861d0f62", + "title": "Step 101" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-102", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d3561a951bf2e41a24f10", + "title": "Step 102" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-103", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d36103839c82efa95dd34", + "title": "Step 103" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-104", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "619d3711d04d623000013e9e", + "title": "Step 104" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-4", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "61a8fe15a6a31306e60d1e89", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-1", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98c9", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-2", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98ca", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-3", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98cb", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-4", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98cc", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-5", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98cd", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-6", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98ce", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-7", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98cf", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-8", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d0", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-9", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d1", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-10", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d2", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-11", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d3", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-12", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d4", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-13", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d5", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-14", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d6", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-15", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d7", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-16", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d8", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-17", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98d9", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-18", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98da", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-19", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98db", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-20", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98dc", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-21", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98dd", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-22", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98de", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-23", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98df", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-24", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e0", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-25", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e1", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-26", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e2", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-27", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e3", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-28", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e4", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-29", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e5", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-30", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e6", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-31", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e7", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-32", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e8", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-33", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98e9", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-34", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98ea", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-35", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98eb", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-36", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98ec", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-37", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98ed", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-38", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98ee", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-39", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98ef", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-40", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f0", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-41", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f1", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-42", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f2", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-43", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f3", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-44", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f4", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-45", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f5", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-46", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f6", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-47", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f7", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-48", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f8", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-49", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98f9", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-50", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98fa", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-51", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98fb", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-52", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98fc", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-53", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98fd", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-54", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98fe", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-55", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e98ff", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-56", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9900", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-57", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9901", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-58", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9902", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-59", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9903", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-60", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9904", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-61", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9905", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-62", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9906", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-63", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9907", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-64", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9908", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-65", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9909", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-66", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e990a", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-67", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e990b", + "title": "Step 67" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-68", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e990c", + "title": "Step 68" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-69", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e990d", + "title": "Step 69" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-70", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e990e", + "title": "Step 70" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-71", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e990f", + "title": "Step 71" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-72", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9910", + "title": "Step 72" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-73", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9911", + "title": "Step 73" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-74", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9912", + "title": "Step 74" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-75", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9913", + "title": "Step 75" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-76", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9914", + "title": "Step 76" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-106", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9915", + "title": "Step 106" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-77", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9916", + "title": "Step 77" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-78", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9917", + "title": "Step 78" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-79", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9918", + "title": "Step 79" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-80", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9919", + "title": "Step 80" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-81", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e991a", + "title": "Step 81" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-82", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e991b", + "title": "Step 82" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-83", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e991c", + "title": "Step 83" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-84", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e991d", + "title": "Step 84" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-85", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e991e", + "title": "Step 85" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-86", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e991f", + "title": "Step 86" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-87", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9920", + "title": "Step 87" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-88", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9921", + "title": "Step 88" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-89", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9922", + "title": "Step 89" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-90", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9923", + "title": "Step 90" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-91", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9924", + "title": "Step 91" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-92", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9925", + "title": "Step 92" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-93", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9926", + "title": "Step 93" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-94", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9927", + "title": "Step 94" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-95", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9928", + "title": "Step 95" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-96", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9929", + "title": "Step 96" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-97", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e992a", + "title": "Step 97" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-98", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e992b", + "title": "Step 98" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-99", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e992c", + "title": "Step 99" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-100", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e992d", + "title": "Step 100" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-101", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e992e", + "title": "Step 101" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-102", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e992f", + "title": "Step 102" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-103", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9930", + "title": "Step 103" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-109", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9931", + "title": "Step 109" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-104", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9932", + "title": "Step 104" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-105", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9933", + "title": "Step 105" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-107", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9934", + "title": "Step 107" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-108", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9935", + "title": "Step 108" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-110", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9936", + "title": "Step 110" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-111", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9937", + "title": "Step 111" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-112", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9938", + "title": "Step 112" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-113", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e9939", + "title": "Step 113" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-114", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e993a", + "title": "Step 114" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-115", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e993b", + "title": "Step 115" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-116", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e993c", + "title": "Step 116" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-117", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e993d", + "title": "Step 117" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-variables-by-building-a-city-skyline/step-118", + "blockName": "Learn CSS Variables by Building a City Skyline" + }, + "id": "5d822fd413a79914d39e993e", + "title": "Step 118" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-1", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc174fcf86c76b9248c6eb2", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-2", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc1798ff86c76b9248c6eb3", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-3", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc17d3bf86c76b9248c6eb4", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-4", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc17dc8f86c76b9248c6eb5", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-5", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc2385ff86c76b9248c6eb7", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-6", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc23991f86c76b9248c6eb8", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-7", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc23f9bf86c76b9248c6eba", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-8", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc24073f86c76b9248c6ebb", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-9", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc24165f86c76b9248c6ebc", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-10", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dc24614f86c76b9248c6ebd", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-11", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ddbd81294d8ddc1510a8e56", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-12", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfa22d1b521be39a3de7be0", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-14", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfa2407b521be39a3de7be1", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-15", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfa30b9eacea3f48c6300ad", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-18", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfa3589eacea3f48c6300ae", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-19", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfa371beacea3f48c6300af", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-20", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfa37b9eacea3f48c6300b0", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-21", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfb5ecbeacea3f48c6300b1", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-22", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfb6250eacea3f48c6300b2", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-23", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfb655eeacea3f48c6300b3", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-24", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5dfb6a35eacea3f48c6300b4", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-25", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d0", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-26", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d1", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-27", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d2", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-28", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d3", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-32", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d4", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-34", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d5", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-35", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d6", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-36", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d7", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-37", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d8", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-40", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804d9", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-42", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804da", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-41", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804db", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-44", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804dc", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-45", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804dd", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-48", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804de", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-46", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804df", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-50", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804e1", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-54", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804e2", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-58", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804e3", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-61", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804e5", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-62", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804e7", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-63", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804e8", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-64", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804e9", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-65", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804ea", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-66", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804eb", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-67", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804ec", + "title": "Step 67" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-68", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5ef9b03c81a63668521804ee", + "title": "Step 68" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-29", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efada803cbd2bbdab94e332", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-30", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efae0543cbd2bbdab94e333", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-31", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efae16e3cbd2bbdab94e334", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-38", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efb23e70dc218d6c85f89b1", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-43", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efb2c990dc218d6c85f89b2", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-56", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efc4f528d6a74d05e68af74", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-57", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efc518e8d6a74d05e68af75", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-55", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efc54138d6a74d05e68af76", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-59", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5efc575c8d6a74d05e68af77", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-47", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f05a1d8e233dff4a68508d8", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-16", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f07be6ef7412fbad0c5626b", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-17", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f07c98cdb9413cbd4b16750", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-33", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f07fb1579dc934717801375", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-51", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f0d48e7b435f13ab6550051", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-52", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f0d4ab1b435f13ab6550052", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-53", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f0d4d04b435f13ab6550053", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-49", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f1a80975fc4bcae0edb3497", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-60", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "5f1a89f1190aff21ae42105a", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-69", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "62bb4009e3458a128ff57d5d", + "title": "Step 69" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-13", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "62dabe2ef403a12d5d295273", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-by-building-a-cat-photo-app/step-39", + "blockName": "Learn HTML by Building a Cat Photo App" + }, + "id": "7cf9b03d81a65668421804c3", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-1", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60eebd07ea685b0e777b5583", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-2", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f027099a15b00485563dd2", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-3", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f027c87bc98f050395c139", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-4", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f0286404aefb0562a4fdf9", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-6", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f02e7361b68405e27b62a5", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-7", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f030d388cb74067cf291c3", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-8", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f1922fcbd2410527b3bd89", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-9", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f1a5e2d2c23707a4f9a660", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-10", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f1a9cbd23023082e149fee", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-11", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f5c3e399ff1a05629964e4", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-13", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f5cb8875ab6a0610f05071", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-14", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f5d2776c854e069560fbe6", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-15", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f5dc35c07ac1078f140916", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-16", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f803d5241e6a0433a523a1", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-17", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f805f813eaf2049bc2ceea", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-19", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f80e0081e0f2052ae5b505", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-20", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f81167d0d4910809f88945", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-21", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f81616cff80508badf9ad5", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-22", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f83e7bfc09900959f41e20", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-23", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f84ec41116b209c280ba91", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-24", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f852f645b5310a8264f555", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-25", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f85a62fb30c80bcea0cedb", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-26", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f8604682407e0d017bbf7f", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-27", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60f8618d191b940d62038513", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-28", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fab4a123ce4b04526b082b", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-30", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fab8367d35de04e5cb7929", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-31", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fab9f17fa294054b74228c", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-32", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fabf0dd4959805dbae09e6", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-33", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fac4095512d3066053d73c", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-34", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fac56271087806def55b33", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-35", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fac8d7fdfaee0796934f20", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-36", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60faca286cb48b07f6482970", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-37", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60facde2d0dc61085b41063f", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-39", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60facf914c7b9b08d7510c2c", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-40", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fad0a812d9890938524f50", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-41", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fad1cafcde010995e15306", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-42", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fad6dfcc0d930a59becf12", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-43", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fad8e6148f310bba7890b1", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-44", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fad99e09f9d30c1657e790", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-45", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fadb18058e950c73925279", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-46", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fadce90f85c50d0bb0dd4f", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-48", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fadd972e6ffe0d6858fa2d", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-49", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fadfa2b540b70dcfa8b771", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-50", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fc219d333e37046f474a6e", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-51", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fc22d1e64d1b04cdd4e602", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-52", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60fc236dc04532052926fdac", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-53", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffe1bc30415f042faea936", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-54", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffe3936796ac04959285a9", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-55", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffe4f4ec18cd04dc470c56", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-56", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffe69ee377c6055e192a46", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-57", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffe7d8aae62c05bcc9e7eb", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-58", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffe8a5ceb0e90618db06d9", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-59", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffe947a868ec068f7850f6", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-60", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffe9cb47809106eda2f2c9", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-61", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffec2825da1007509ddd06", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-62", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffecefac971607ae73c60f", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-63", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "60ffefd6479a3d084fb77cbc", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-47", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "62b30924c5e4ef0daba23b5e", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-5", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "62cc5b1779e4d313466f73c5", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-18", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "62ff8b9dab5ac88e4d3d43a3", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-29", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "62ff8e998d3e7eae14d6ae3b", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-38", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "62ff919a7b5612c0670923a5", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-html-forms-by-building-a-registration-form/step-12", + "blockName": "Learn HTML Forms by Building a Registration Form" + }, + "id": "63541ef4f96cd82e8e6c788a", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-1", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51578", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-2", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51579", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-4", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5157a", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-5", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5157b", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-6", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5157c", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-7", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5157d", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-8", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5157e", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-9", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5157f", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-10", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51580", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-11", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51581", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-12", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51582", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-13", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51583", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-14", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51584", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-15", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51585", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-16", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51586", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-17", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51587", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-18", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51588", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-19", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51589", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-20", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5158a", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-21", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5158b", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-22", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5158c", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-23", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5158d", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-24", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5158e", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-25", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5158f", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-26", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51590", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-27", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51591", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-28", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51592", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-29", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51593", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-30", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51594", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-31", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51595", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-32", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51596", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-33", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51597", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-34", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51598", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-35", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c51599", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-36", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5159a", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-37", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5159b", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-38", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5159c", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-39", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5159d", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-40", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5159e", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-42", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c5159f", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-43", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a0", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-44", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a1", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-45", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a2", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-46", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a3", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-47", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a4", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-48", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a5", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-49", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a6", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-50", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a7", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-51", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a8", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-52", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515a9", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-53", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515aa", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-54", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515ab", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-55", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515ac", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-56", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515ad", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-57", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515ae", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-58", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515af", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-59", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b0", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-60", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b1", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-61", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b2", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-62", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b3", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-63", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b4", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-64", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b5", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-65", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b6", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-66", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b7", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-67", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b8", + "title": "Step 67" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-68", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515b9", + "title": "Step 68" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-69", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515ba", + "title": "Step 69" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-70", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515bc", + "title": "Step 70" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-79", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515bd", + "title": "Step 79" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-80", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515be", + "title": "Step 80" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-81", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515bf", + "title": "Step 81" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-82", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515c0", + "title": "Step 82" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-83", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515c1", + "title": "Step 83" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-84", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515c2", + "title": "Step 84" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-85", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515c3", + "title": "Step 85" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-86", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515c4", + "title": "Step 86" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-87", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515c5", + "title": "Step 87" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-88", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515c6", + "title": "Step 88" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-89", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b69a66b6ddb80858c515c7", + "title": "Step 89" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-3", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60b80da8676fb3227967a731", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-75", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60ba890832b4940f24d1936b", + "title": "Step 75" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-74", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60ba89123a445e0f5c9e4022", + "title": "Step 74" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-73", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60ba8913f1704c0f7a8906b8", + "title": "Step 73" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-72", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60ba89146b25080f99ab54ad", + "title": "Step 72" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-71", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60ba8914bab51f0fb8228e9c", + "title": "Step 71" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-76", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60ba929345ab0714a3743655", + "title": "Step 76" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-77", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60ba9296d4d6b414c1b10995", + "title": "Step 77" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-78", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60ba92987c1e4914dfa7a0b9", + "title": "Step 78" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-intermediate-css-by-building-a-picasso-painting/step-41", + "blockName": "Learn Intermediate CSS by Building a Picasso Painting" + }, + "id": "60bad32219ebcb4a8810ac6a", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-1", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd5a93fd62bb35968adeab", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-2", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd6343fb42013d99bcd7f3", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-3", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd66c687e610436494c6f1", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-4", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd67a656743144844941cb", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-5", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd6ab779390f49148773bb", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-6", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd6b7c83dbf54a08cf0498", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-7", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd6cc9475a784b7776233e", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-8", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd70336ebb3e4f62ee81ba", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-9", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd719788899952e67692b9", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-10", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd71d596e8f253b9408b39", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-11", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd75ea7f663457612dba02", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-12", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd7648a7ba2e5882436831", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-13", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd778081276b59d59abad6", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-14", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd77f7ad2aeb5ae34d07d6", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-15", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd78621573aa5e8b512f5e", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-16", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd7a160ed17960e971f28b", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-17", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd7b3fcaa5406257abc5d1", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-18", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd8e491324ce717da97ffe", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-19", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd8fd08af43372f02952d0", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-20", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd9126aa72a474301fc49f", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-21", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd933ba685de776a94997e", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-22", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd94056e0355785fbba4d3", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-23", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd986ddbcbd47ba8fbc5ec", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-24", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd990577d8227dd93fbeeb", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-25", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd9a4ff2fc4481b9157bd7", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-26", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd9ad665a4a282c8106be3", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-27", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd9b7285bde783ad5b8aac", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-28", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fd9d9fbdfe078800317055", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-29", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fda307bde0b091cf7d884a", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-30", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fda339eadcfd92a6812bed", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-31", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fdac1e31692f9a9ad97295", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-32", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fdaea3999cb19d76ce717b", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-33", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fdaf9ff894b6a084ecdc1b", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-34", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fdafe6f07fd7a1c6785bc2", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-35", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "61fdb04d9939f0a26ca51c2b", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-36", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620159cd5431aa34bc6a4c9c", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-37", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62015a5da1c95c358f079ebb", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-38", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62015cd2654a1139321a89d2", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-39", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62015d8942384c3aed48329e", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-40", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620167374bb8b4455cd11125", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-41", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620174ed519dd7506c1a4b61", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-42", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620175b3710a0951cfa86edf", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-43", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201782cc420715562f36271", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-44", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620179bc0a6a2358c72b90ad", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-45", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62017b6f47454059bf2d3bd1", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-46", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62017f47c87be96457c49f46", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-47", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62017fa5bbef406580ceb44f", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-48", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62018243f046a368fab8ffb6", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-49", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201830cb0c74b69f1b41635", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-50", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620186f4b6b8356d2def576b", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-51", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62018ba1aa263770c953be66", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-52", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62018c3e94434a71af1d5eaa", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-53", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62018ec29b3ae674f40bef31", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-54", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "62019093fe30e278e797d2f6", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-55", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620191707bc65579ddd3ce15", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-56", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620192a767533a7ad19d96d7", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-57", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201995d9ab88e80f1989dce", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-58", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "620199c7a7a32c81d4db3410", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-59", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201a1a7af32c287bd6b8183", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-60", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201a1cc668a34888f5b2f52", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-61", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201a20d742f5c89736c8cfb", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-62", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201a42e39bf3b95b6a33bf3", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-63", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201a4adcc6414968b391592", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-64", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201a5258af7b398b030bfaf", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-more-about-css-pseudo-selectors-by-building-a-balance-sheet/step-65", + "blockName": "Learn More About CSS Pseudo Selectors By Building A Balance Sheet" + }, + "id": "6201a59be346d399c21d10b1", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-1", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e6afc009b450a437940a1", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-2", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e77aba7ca691f598feb02", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-3", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e78af05201622d4bab8aa", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-4", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e7d1c29fb872d6384379c", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-5", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e804c54d5e7308d7ebe56", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-6", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e813b3ba67633222cbe54", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-7", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e8279827a28352ce83a72", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-8", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e83ec2eca1e370f830511", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-9", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e89562043183c86df287c", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-10", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e89d254fe5d3df7d6693d", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-11", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e8eebe3a6dc3fcc33a66f", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-12", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e95ef2e4bdf41f69067f9", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-13", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e96fc87fe8e44f69f7ec5", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-14", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e98f3245c98475e49cfc6", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-15", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e9a21381a1949327512e6", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-16", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e9d142affc44a453655db", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-17", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612e9f1e7e5ccd4fa9ada0be", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-18", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ea4c4993aba52ab4aa32e", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-19", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ea97df5742154772f312e", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-20", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ead8788d28655ef8db056", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-21", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612eaf56b7ba3257fdbfb0db", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-22", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612eb4893b63c75bb9251ddf", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-23", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612eb75153591b5e3b1ab65e", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-24", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612eb7ca8c275d5f89c73333", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-25", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612eb8e984cd73677a92b7e9", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-26", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612eb934f64a4d6890a45518", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-27", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ebcba99bfa46a15370b11", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-28", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ebe7fe6d07e6b76d1cae2", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-29", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ebedec97e096c8bf64999", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-30", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ebf9a210f2b6d77001e68", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-31", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ec0490ae8626e9adf82e4", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-32", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ec19d5268da7074941f84", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-responsive-web-design-by-building-a-piano/step-33", + "blockName": "Learn Responsive Web Design by Building a Piano" + }, + "id": "612ec29c84b9a6718b1f5cec", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-1", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6996a", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-2", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6996b", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-3", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6996c", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-4", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6996d", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-5", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6996e", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-6", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6996f", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-7", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69970", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-8", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69971", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-9", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69972", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-10", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69973", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-11", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69974", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-12", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69975", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-13", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69976", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-14", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69977", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-15", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69978", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-16", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69979", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-17", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6997a", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-18", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6997b", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-19", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6997c", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-20", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6997d", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-21", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6997e", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-22", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6997f", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-23", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69980", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-24", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69981", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-25", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69982", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-26", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69983", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-27", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69984", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-28", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69986", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-29", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69987", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-30", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69988", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-31", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69989", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-32", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6998a", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-33", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6998b", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-34", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6998c", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-35", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6998d", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-36", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6998e", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-37", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad6998f", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-38", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69990", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-39", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69991", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-40", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69992", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-41", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69993", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-42", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69994", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-43", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69995", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-44", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69996", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-the-css-box-model-by-building-a-rothko-painting/step-45", + "blockName": "Learn the CSS Box Model by Building a Rothko Painting" + }, + "id": "60a3e3396c7b40068ad69997", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-1", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f2abbe7d18d49a1e0e1c8", + "title": "Step 1" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-2", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f2d4150fe0d4cbd0f2628", + "title": "Step 2" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-3", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f34948891834dd77655a6", + "title": "Step 3" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-4", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f34ecc1091b4fd5a8a484", + "title": "Step 4" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-5", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f357957e370510f21ea16", + "title": "Step 5" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-6", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f378014c2da526a109c81", + "title": "Step 6" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-7", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f38279e5c3d53692ea441", + "title": "Step 7" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-8", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f38cabc64e3556f98cc1a", + "title": "Step 8" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-9", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f3949f58e12577dcefb00", + "title": "Step 9" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-10", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f39d7da41b15851fa3fb9", + "title": "Step 10" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-11", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f3b091162165948e1cb33", + "title": "Step 11" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-12", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f3cafd794015aa9547a6d", + "title": "Step 12" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-13", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f3d9e59db4b5b8e960762", + "title": "Step 13" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-14", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f3e1b7233ee5c7595771f", + "title": "Step 14" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-15", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f3e4af8008c5d494d3afe", + "title": "Step 15" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-16", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f3ed16592445e57941aec", + "title": "Step 16" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-17", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f405b89a7ec5f8e2d11f4", + "title": "Step 17" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-18", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f40b01f680e608d360ed4", + "title": "Step 18" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-19", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f4172e9eec061d6456221", + "title": "Step 19" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-20", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f41c979787462e76dab90", + "title": "Step 20" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-21", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f423cf65d5864132a0956", + "title": "Step 21" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-22", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f42a021625f656101ef93", + "title": "Step 22" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-23", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f4bfb9de4a16703b56eb6", + "title": "Step 23" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-24", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f4ce9d877b668417c0c42", + "title": "Step 24" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-25", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f4dde9d72e3694cb9ee3b", + "title": "Step 25" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-26", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f4ec58334106a4170c2a8", + "title": "Step 26" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-27", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f4f9e4a40566b776a8f38", + "title": "Step 27" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-28", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f50473cc0196c6dd3892a", + "title": "Step 28" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-29", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f51257a8a516d80b6c743", + "title": "Step 29" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-30", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f51e4e5b24a6e80eccce1", + "title": "Step 30" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-31", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f522dea4f776f64dc3e91", + "title": "Step 31" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-32", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f5486b8fd4b71633f69b0", + "title": "Step 32" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-33", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f575b50b91e72af079480", + "title": "Step 33" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-34", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f5af373a68e744a3c5a76", + "title": "Step 34" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-35", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f5c1cb7575c7551ed8a40", + "title": "Step 35" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-36", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f5fd85d0062761f288364", + "title": "Step 36" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-37", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f61338c8ca176d6445574", + "title": "Step 37" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-38", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f666ac5edea782feb7e75", + "title": "Step 38" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-39", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f671b6d1919792745aa5d", + "title": "Step 39" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-40", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f6823d0815b7a991f2a75", + "title": "Step 40" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-41", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f6a7d4ba8037bc086c2c7", + "title": "Step 41" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-42", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f6b2d164f81809efd9bdc", + "title": "Step 42" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-43", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f6cc778f7698258467596", + "title": "Step 43" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-44", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f6fddaac1e083502d3e6a", + "title": "Step 44" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-45", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f70077a4ff98424236c1e", + "title": "Step 45" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-46", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f72a872354a850d4f533e", + "title": "Step 46" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-47", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f74a71f1e498619e38ee8", + "title": "Step 47" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-48", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f7ad94380408d971d14f6", + "title": "Step 48" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-49", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f7bc680f7168ea01ebf99", + "title": "Step 49" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-50", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f7c71eab8218f846e4503", + "title": "Step 50" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-51", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f7d489a581590d1350288", + "title": "Step 51" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-52", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f7de4487b64919bb4aa5e", + "title": "Step 52" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-53", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f7e7281626a92bbd62da8", + "title": "Step 53" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-54", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f7ecb09de9a938ef94756", + "title": "Step 54" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-55", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f7fa959ab75948f96a0d6", + "title": "Step 55" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-56", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f808d85793195b0f53be9", + "title": "Step 56" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-57", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f829d07b18f96f6f6684b", + "title": "Step 57" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-58", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f83ef928ec9982b785b6a", + "title": "Step 58" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-59", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f84f246e8ba98e3cd97be", + "title": "Step 59" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-60", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f887466db4ba14b5342cc", + "title": "Step 60" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-61", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f89e055040ba294719d2f", + "title": "Step 61" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-62", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f8bfe0f30a1a3c340356b", + "title": "Step 62" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-63", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f8f1223601fa546e93f31", + "title": "Step 63" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-64", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f905fbd1017a65ca224eb", + "title": "Step 64" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-65", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f94786869e1a7fec54375", + "title": "Step 65" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-typography-by-building-a-nutrition-label/step-66", + "blockName": "Learn Typography by Building a Nutrition Label" + }, + "id": "615f951dff9317a900ef683f", + "title": "Step 66" + } + } + }, + { + "node": { + "challenge": { + "fields": { + "slug": "/learn/2022/responsive-web-design/learn-css-transforms-by-building-a-penguin/step-23", + "blockName": "Learn CSS Transforms by Building a Penguin" + }, + "id": "6196d1ac33c68d27dcda5796", + "title": "Step 23" + } + } + } +] diff --git a/client/src/__mocks__/fileMock.ts b/client/src/__mocks__/file-mock.ts similarity index 100% rename from client/src/__mocks__/fileMock.ts rename to client/src/__mocks__/file-mock.ts diff --git a/client/src/__mocks__/styleMock.ts b/client/src/__mocks__/style-mock.ts similarity index 100% rename from client/src/__mocks__/styleMock.ts rename to client/src/__mocks__/style-mock.ts diff --git a/client/src/analytics/index.ts b/client/src/analytics/index.ts new file mode 100644 index 00000000000000..32a21405122791 --- /dev/null +++ b/client/src/analytics/index.ts @@ -0,0 +1,25 @@ +import TagManager from 'react-gtm-module'; + +import { + devAnalyticsId, + prodAnalyticsId, + prodAnalyticsESId +} from '../../../config/analytics-settings'; + +import envData from '../../../config/env.json'; + +const { deploymentEnv, clientLocale } = envData; + +const analyticsIDSelector = () => { + if (deploymentEnv === 'staging') return devAnalyticsId; + else if (clientLocale === 'espanol') return prodAnalyticsESId; + else return prodAnalyticsId; +}; + +const gtmId = analyticsIDSelector(); + +if (typeof document !== `undefined`) { + TagManager.initialize({ gtmId }); +} + +export default TagManager; diff --git a/client/src/analytics/index.tsx b/client/src/analytics/index.tsx deleted file mode 100644 index 8362761097bd8e..00000000000000 --- a/client/src/analytics/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import ReactGA from 'react-ga'; -import { - devAnalyticsId, - prodAnalyticsId -} from '../../../config/analytics-settings'; -import envData from '../../../config/env.json'; - -const { deploymentEnv } = envData; - -const analyticsId: string = - deploymentEnv === 'staging' - ? (devAnalyticsId as string) - : (prodAnalyticsId as string); - -ReactGA.initialize(analyticsId); - -export default ReactGA; diff --git a/client/src/assets/icons/API-icon.tsx b/client/src/assets/icons/api.tsx similarity index 100% rename from client/src/assets/icons/API-icon.tsx rename to client/src/assets/icons/api.tsx diff --git a/client/src/assets/icons/certification-icon.tsx b/client/src/assets/icons/certification.tsx similarity index 100% rename from client/src/assets/icons/certification-icon.tsx rename to client/src/assets/icons/certification.tsx diff --git a/client/src/assets/icons/D3-icon.tsx b/client/src/assets/icons/d3.tsx similarity index 100% rename from client/src/assets/icons/D3-icon.tsx rename to client/src/assets/icons/d3.tsx diff --git a/client/src/assets/icons/Database-icon.tsx b/client/src/assets/icons/database.tsx similarity index 100% rename from client/src/assets/icons/Database-icon.tsx rename to client/src/assets/icons/database.tsx diff --git a/client/src/assets/icons/FreeCodeCamp-logo.tsx b/client/src/assets/icons/freecodecamp.tsx similarity index 100% rename from client/src/assets/icons/FreeCodeCamp-logo.tsx rename to client/src/assets/icons/freecodecamp.tsx diff --git a/client/src/assets/icons/help.tsx b/client/src/assets/icons/help.tsx index f745414e83a791..e6d3760857c9cd 100644 --- a/client/src/assets/icons/help.tsx +++ b/client/src/assets/icons/help.tsx @@ -1,20 +1,47 @@ import React from 'react'; +const wrapper = { + display: 'grid', + placeItems: 'center', + position: 'relative', + padding: 'inherit' +} as React.CSSProperties; + +const speechBubbleIcon = { + position: 'absolute' +} as React.CSSProperties; + +const questionMarkIcon = { + position: 'absolute', + top: '-3px', + width: '9px' +} as React.CSSProperties; + function Help( props: JSX.IntrinsicAttributes & React.SVGProps ): JSX.Element { return ( <> - +
+ + + + + + +
); } diff --git a/client/src/assets/icons/index.tsx b/client/src/assets/icons/index.tsx index 45f29522fd6003..528a9ef7746573 100644 --- a/client/src/assets/icons/index.tsx +++ b/client/src/assets/icons/index.tsx @@ -1,17 +1,18 @@ import React from 'react'; import { SuperBlocks } from '../../../../config/certification-settings'; -import APIIcon from './API-icon'; -import D3Icon from './D3-icon'; -import DatabaseIcon from './Database-icon'; -import JavaScriptIcon from './JavaScript-icon'; -import ReactIcon from './React-icon'; -import TensorflowIcon from './Tensorflow-icon'; +import APIIcon from './api'; +import D3Icon from './d3'; +import DatabaseIcon from './database'; +import JavaScriptIcon from './javascript'; +import ReactIcon from './react'; +import TensorflowIcon from './tensorflow'; import Algorithm from './algorithm'; import Analytics from './analytics'; import Clipboard from './clipboard'; -import PythonIcon from './python-icon'; +import PythonIcon from './python'; import ResponsiveDesign from './responsive-design'; import Shield from './shield'; +import VikingHelmet from './viking-helmet'; const iconMap = { [SuperBlocks.RespWebDesignNew]: ResponsiveDesign, @@ -27,7 +28,8 @@ const iconMap = { [SuperBlocks.DataAnalysisPy]: Analytics, [SuperBlocks.InfoSec]: Shield, [SuperBlocks.MachineLearningPy]: TensorflowIcon, - [SuperBlocks.CodingInterviewPrep]: Algorithm + [SuperBlocks.CodingInterviewPrep]: Algorithm, + [SuperBlocks.TheOdinProject]: VikingHelmet }; const generateIconComponent = ( diff --git a/client/src/assets/icons/input-reset.tsx b/client/src/assets/icons/input-reset.tsx new file mode 100644 index 00000000000000..25c5311b8a236f --- /dev/null +++ b/client/src/assets/icons/input-reset.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +const InputReset = (): JSX.Element => { + const { t } = useTranslation(); + + return ( + <> + {t('icons.input-reset')} + + + + + ); +}; + +InputReset.displayName = 'InputReset'; +export default InputReset; diff --git a/client/src/assets/icons/JavaScript-icon.tsx b/client/src/assets/icons/javascript.tsx similarity index 100% rename from client/src/assets/icons/JavaScript-icon.tsx rename to client/src/assets/icons/javascript.tsx diff --git a/client/src/assets/icons/Magnifier.tsx b/client/src/assets/icons/magnifier.tsx similarity index 93% rename from client/src/assets/icons/Magnifier.tsx rename to client/src/assets/icons/magnifier.tsx index 42e5a13c1e2e97..9c6faed41623a2 100644 --- a/client/src/assets/icons/Magnifier.tsx +++ b/client/src/assets/icons/magnifier.tsx @@ -6,7 +6,7 @@ const Magnifier = (): JSX.Element => { return ( <> - {t('icons.Magnifier')} + {t('icons.magnifier')} - {t('icons.spacer')}

placeholder

- {{ title: certTitle }} + + {{ title: t(`certification.title.${certTitle}`, certTitle) }} +

{{ time: completionTime }}

@@ -366,6 +354,9 @@ const ShowCertification = (props: ShowCertificationProps): JSX.Element => {

{t('certification.executive')}

+ + +

{t('certification.verify', { certURL: certURL })} diff --git a/client/src/client-only-routes/show-project-links.tsx b/client/src/client-only-routes/show-project-links.tsx index cbe56ea2a05228..94d8a603759e46 100644 --- a/client/src/client-only-routes/show-project-links.tsx +++ b/client/src/client-only-routes/show-project-links.tsx @@ -1,14 +1,15 @@ +import { Table } from '@freecodecamp/react-bootstrap'; import { find, first } from 'lodash-es'; import React, { useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { connect } from 'react-redux'; +import { Link, Spacer } from '../components/helpers'; import ProjectModal from '../components/SolutionViewer/ProjectModal'; -import { Spacer, Link } from '../components/helpers'; import { CompletedChallenge, User } from '../redux/prop-types'; import { - projectMap, - legacyProjectMap + legacyProjectMap, + projectMap } from '../resources/cert-and-project-map'; import { SolutionDisplayWidget } from '../components/solution-display-widget'; @@ -16,8 +17,8 @@ import ProjectPreviewModal from '../templates/Challenges/components/project-prev import { openModal } from '../templates/Challenges/redux/actions'; -import '../components/layouts/project-links.css'; import { regeneratePathAndHistory } from '../../../utils/polyvinyl'; +import '../components/layouts/project-links.css'; interface ShowProjectLinksProps { certName: string; name: string; @@ -82,6 +83,7 @@ const ShowProjectLinks = (props: ShowProjectLinksProps): JSX.Element => { { const { certSlug } = first(mapToUse) as { certSlug: string }; const certLocation = `/certification/${username}/${certSlug}`; return ( -

  • - - {t(`certification.project.title.${cert.title}`, cert.title)} - -
  • + + + + {t(`certification.title.${cert.title}`, cert.title)} + + + ); }); } @@ -125,12 +124,14 @@ const ShowProjectLinks = (props: ShowProjectLinksProps): JSX.Element => { id: string; }[]; return project.map(({ link, title, id }) => ( -
  • - - {t(`certification.project.title.${title}`, title)} - - : {getProjectSolution(id, title)} -
  • + + + + {t(`certification.project.title.${title}`, title)} + + + {getProjectSolution(id, title)} + )); }; @@ -160,7 +161,15 @@ const ShowProjectLinks = (props: ShowProjectLinksProps): JSX.Element => { { user: name } )} -
      {renderProjectsFor(certName)}
    + + + + + + + + {renderProjectsFor(certName)} +
    {t('profile.challenge')}{t('settings.labels.solution')}
    { const MAX_LOGS_SIZE = 64 * 1024; let logs: string[] = []; + function flushLogs() { if (logs.length) { ctx.postMessage({ @@ -21,16 +22,38 @@ const __utils = (() => { } } - const oldLog = ctx.console.log.bind(ctx.console); - function proxyLog(...args: string[]) { + function pushLogs(logs: string[], args: string[]) { // eslint-disable-next-line @typescript-eslint/no-unsafe-return logs.push(args.map(arg => __format(arg)).join(' ')); if (logs.join('\n').length > MAX_LOGS_SIZE) { flushLogs(); } + } + + const oldLog = ctx.console.log.bind(ctx.console); + function proxyLog(...args: string[]) { + pushLogs(logs, args); return oldLog(...args); } + const oldInfo = ctx.console.info.bind(ctx.console); + function proxyInfo(...args: string[]) { + pushLogs(logs, args); + return oldInfo(...args); + } + + const oldWarn = ctx.console.warn.bind(ctx.console); + function proxyWarn(...args: string[]) { + pushLogs(logs, args); + return oldWarn(...args); + } + + const oldError = ctx.console.error.bind(ctx.console); + function proxyError(...args: string[]) { + pushLogs(logs, args); + return oldError(...args); + } + // unless data.type is truthy, this sends data out to the testRunner function postResult(data: unknown) { flushLogs(); @@ -47,6 +70,9 @@ const __utils = (() => { const toggleProxyLogger = (on: unknown) => { ctx.console.log = on ? proxyLog : oldLog; + ctx.console.info = on ? proxyInfo : oldInfo; + ctx.console.warn = on ? proxyWarn : oldWarn; + ctx.console.error = on ? proxyError : oldError; }; return { diff --git a/client/src/components/Donation/donate-form.tsx b/client/src/components/Donation/donate-form.tsx index 4c5a91307c5a87..164cf6f6fc7173 100644 --- a/client/src/components/Donation/donate-form.tsx +++ b/client/src/components/Donation/donate-form.tsx @@ -9,40 +9,49 @@ import { createSelector } from 'reselect'; import { amountsConfig, durationsConfig, - defaultAmount, defaultDonation, modalDefaultDonation } from '../../../../config/donation-settings'; import { defaultDonationFormState } from '../../redux'; -import { - addDonation, - updateDonationFormState, - postChargeStripe, - postChargeStripeCard -} from '../../redux/actions'; +import { updateDonationFormState, postCharge } from '../../redux/actions'; import { isSignedInSelector, userSelector, isDonatingSelector, signInLoadingSelector, - donationFormStateSelector, - isVariantASelector + donationFormStateSelector } from '../../redux/selectors'; import Spacer from '../helpers/spacer'; import { Themes } from '../settings/theme'; import DonateCompletion from './donate-completion'; import PatreonButton from './patreon-button'; -import type { AddDonationData } from './paypal-button'; import PaypalButton from './paypal-button'; -import StripeCardForm, { HandleAuthentication } from './stripe-card-form'; +import StripeCardForm from './stripe-card-form'; import WalletsWrapper from './walletsButton'; import SecurityLockIcon from './security-lock-icon'; +import { + PaymentProvider, + PaymentContext, + PostPayment, + HandleAuthentication, + DonationApprovalData, + DonationAmount, + DonationConfig +} from './types'; import './donation.css'; -const numToCommas = (num: number): string => +const numToCommas = (num: number) => num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,'); +// the number is used to indicate to the doner about how much hours of free education their dontation will provide. +const contributedHoursOfFreeEduction = 50; +const convertAmountToUSD = 100; +const convertToTimeContributed = (amount: number) => + numToCommas((amount / convertAmountToUSD) * contributedHoursOfFreeEduction); +const formattedAmountLabel = (amount: number) => + numToCommas(amount / convertAmountToUSD); + type DonateFormState = { processing: boolean; redirecting: boolean; @@ -54,23 +63,26 @@ type DonateFormState = { }; }; -type DonateFormComponentState = { - donationAmount: number; - donationDuration: string; -}; +type DonateFormComponentState = DonationConfig; + +type PostCharge = (data: { + paymentProvider: PaymentProvider; + paymentContext: PaymentContext; + amount: number; + duration: string; + data?: DonationApprovalData; + token?: Token; + email?: string; + name?: string | undefined; + paymentMethodId?: string; + handleAuthentication?: HandleAuthentication; +}) => void; type DonateFormProps = { - addDonation: (data: unknown) => unknown; - postChargeStripe: (data: unknown) => unknown; - postChargeStripeCard: (data: { - paymentMethodId: string; - amount: number; - duration: string; - handleAuthentication: HandleAuthentication; - }) => void; + postCharge: PostCharge; defaultTheme?: Themes; email: string; - handleProcessing: (duration: string, amount: number, action: string) => void; + handleProcessing?: () => void; donationFormState: DonateFormState; isMinimalForm?: boolean; isSignedIn: boolean; @@ -81,8 +93,8 @@ type DonateFormProps = { { usd, hours }?: { usd?: string | number; hours?: string } ) => string; theme: Themes; - updateDonationFormState: (state: AddDonationData) => unknown; - isVariantA: boolean; + updateDonationFormState: (state: DonationApprovalData) => unknown; + paymentContext: PaymentContext; }; const mapStateToProps = createSelector( @@ -91,30 +103,37 @@ const mapStateToProps = createSelector( isDonatingSelector, donationFormStateSelector, userSelector, - isVariantASelector, ( showLoading: DonateFormProps['showLoading'], isSignedIn: DonateFormProps['isSignedIn'], isDonating: DonateFormProps['isDonating'], donationFormState: DonateFormState, - { email, theme }: { email: string; theme: Themes }, - isVariantA: boolean + { email, theme }: { email: string; theme: Themes } ) => ({ isSignedIn, isDonating, showLoading, donationFormState, email, - theme, - isVariantA + theme }) ); const mapDispatchToProps = { - addDonation, - updateDonationFormState, - postChargeStripe, - postChargeStripeCard + postCharge, + updateDonationFormState +}; + +const PaymentButtonsLoader = () => { + return ( +
    + +
    + ); }; class DonateForm extends Component { @@ -124,27 +143,20 @@ class DonateForm extends Component { constructor(props: DonateFormProps) { super(props); - this.durations = durationsConfig as { - month: 'monthly'; - onetime: 'one-time'; - }; + this.durations = durationsConfig; this.amounts = amountsConfig; - const initialAmountAndDuration = this.props.isMinimalForm + const initialAmountAndDuration: DonationConfig = this.props.isMinimalForm ? modalDefaultDonation : defaultDonation; this.state = { ...initialAmountAndDuration }; this.onDonationStateChange = this.onDonationStateChange.bind(this); - this.getActiveDonationAmount = this.getActiveDonationAmount.bind(this); this.getDonationButtonLabel = this.getDonationButtonLabel.bind(this); this.handleSelectAmount = this.handleSelectAmount.bind(this); - this.handleSelectDuration = this.handleSelectDuration.bind(this); this.resetDonation = this.resetDonation.bind(this); - this.postStripeDonation = this.postStripeDonation.bind(this); - this.postStripeCardDonation = this.postStripeCardDonation.bind(this); - this.postPatreonRedirect = this.postPatreonRedirect.bind(this); + this.postPayment = this.postPayment.bind(this); this.handlePaymentButtonLoad = this.handlePaymentButtonLoad.bind(this); } @@ -152,7 +164,7 @@ class DonateForm extends Component { this.resetDonation(); } - onDonationStateChange(donationState: AddDonationData) { + onDonationStateChange(donationState: DonationApprovalData) { // scroll to top window.scrollTo(0, 0); this.props.updateDonationFormState({ @@ -171,30 +183,12 @@ class DonateForm extends Component { }); } - // onload - getActiveDonationAmount( - durationSelected: 'month' | 'onetime', - amountSelected: number - ): number { - return this.amounts[durationSelected].includes(amountSelected) - ? amountSelected - : defaultAmount[durationSelected] || this.amounts[durationSelected][0]; - } - - convertToTimeContributed(amount: number) { - return numToCommas((amount / 100) * 50); - } - - getFormattedAmountLabel(amount: number): string { - return `${numToCommas(amount / 100)}`; - } - getDonationButtonLabel() { const { donationAmount, donationDuration } = this.state; const { t } = this.props; - const usd = this.getFormattedAmountLabel(donationAmount); + const usd = formattedAmountLabel(donationAmount); let donationBtnLabel = t('donate.confirm'); - if (donationDuration === 'onetime') { + if (donationDuration === 'one-time') { donationBtnLabel = t('donate.confirm-2', { usd: usd }); @@ -209,98 +203,41 @@ class DonateForm extends Component { return donationBtnLabel; } - handleSelectDuration(donationDuration: 'month' | 'onetime') { - const donationAmount = this.getActiveDonationAmount(donationDuration, 0); - this.setState({ donationDuration, donationAmount }); - } - - postStripeDonation( - token: Token, - payerEmail: string | undefined, - payerName: string | undefined - ) { - const { email } = this.props; + postPayment = ({ + paymentProvider, + data, + payerEmail, + payerName, + token, + paymentMethodId, + handleAuthentication + }: PostPayment): void => { const { donationAmount: amount, donationDuration: duration } = this.state; - payerEmail = email ? email : payerEmail; - window.scrollTo(0, 0); - // change the donation modal button label to close - // or display the close button for the cert donation section - if (this.props.handleProcessing) { - this.props.handleProcessing(duration, amount, 'Stripe payment submition'); - } - this.props.postChargeStripe({ - token, - amount, - duration, - email: payerEmail, - name: payerName - }); - } + const { paymentContext, email } = this.props; - postStripeCardDonation( - paymentMethodId: string, - handleAuthentication: HandleAuthentication - ) { - const { donationAmount: amount, donationDuration: duration } = this.state; - this.props.handleProcessing( - duration, - amount, - 'Stripe card payment submission' - ); - this.props.postChargeStripeCard({ - paymentMethodId, + this.props.postCharge({ + paymentProvider, + paymentContext, amount, duration, + data, + token, + email: email || payerEmail, + name: payerName, + paymentMethodId, handleAuthentication }); - } - - postPatreonRedirect() { - const { donationAmount: amount, donationDuration: duration } = this.state; - this.props.handleProcessing( - duration, - amount, - 'Patreon payment redirection' - ); - } + if (this.props.handleProcessing) this.props.handleProcessing(); + }; - handleSelectAmount(donationAmount: number) { + handleSelectAmount(donationAmount: DonationAmount) { this.setState({ donationAmount }); } - renderDonationDescription() { - const { donationAmount, donationDuration } = this.state; - const { t } = this.props; - const usd = this.getFormattedAmountLabel(donationAmount); - const hours = this.convertToTimeContributed(donationAmount); - - let donationDescription = t('donate.your-donation-3', { usd, hours }); - - if (donationDuration === 'onetime') { - donationDescription = t('donate.your-donation', { usd, hours }); - } else if (donationDuration === 'month') { - donationDescription = t('donate.your-donation-2', { usd, hours }); - } - - return

    {donationDescription}

    ; - } - resetDonation() { return this.props.updateDonationFormState({ ...defaultDonationFormState }); } - paymentButtonsLoader() { - return ( -
    - -
    - ); - } - renderCompletion(props: { processing: boolean; redirecting: boolean; @@ -316,21 +253,18 @@ class DonateForm extends Component { const { donationAmount, donationDuration } = this.state; const { donationFormState: { loading, processing }, - handleProcessing, - addDonation, defaultTheme, theme, t, isMinimalForm, isSignedIn, - isDonating, - isVariantA + isDonating } = this.props; const priorityTheme = defaultTheme ? defaultTheme : theme; - const isOneTime = donationDuration === 'onetime'; + const isOneTime = donationDuration === 'one-time'; const walletlabel = `${t( isOneTime ? 'donate.wallet-label' : 'donate.wallet-label-1', - { usd: donationAmount / 100 } + { usd: donationAmount / convertAmountToUSD } )}:`; const showMinimalPayments = isSignedIn && (isMinimalForm || !isDonating); @@ -346,41 +280,38 @@ class DonateForm extends Component { {t('donate.secure-donation')} - {loading.stripe && loading.paypal && this.paymentButtonsLoader()} + {loading.stripe && loading.paypal && } {(!loading.stripe || !loading.paypal) && ( - + )} {showMinimalPayments && ( <>
    {t('donate.or-card')}
    )} @@ -390,9 +321,21 @@ class DonateForm extends Component { } renderPageForm() { + const { donationAmount, donationDuration } = this.state; + const { t } = this.props; + const usd = formattedAmountLabel(donationAmount); + const hours = convertToTimeContributed(donationAmount); + + let donationDescription = t('donate.your-donation-3', { usd, hours }); + + if (donationDuration === 'one-time') { + donationDescription = t('donate.your-donation', { usd, hours }); + } else if (donationDuration === 'month') { + donationDescription = t('donate.your-donation-2', { usd, hours }); + } return ( <> -
    {this.renderDonationDescription()}
    +

    {donationDescription}

    {this.renderButtonGroup()}
    ); diff --git a/client/src/components/Donation/donation-modal.tsx b/client/src/components/Donation/donation-modal.tsx index c6b12f97380d33..f87e0bb17ad7cd 100644 --- a/client/src/components/Donation/donation-modal.tsx +++ b/client/src/components/Donation/donation-modal.tsx @@ -6,7 +6,10 @@ import { connect } from 'react-redux'; import { goToAnchor } from 'react-scrollable-anchor'; import { bindActionCreators, Dispatch, AnyAction } from 'redux'; import { createSelector } from 'reselect'; -import { modalDefaultDonation } from '../../../../config/donation-settings'; +import { + modalDefaultDonation, + PaymentContext +} from '../../../../config/donation-settings'; import Cup from '../../assets/icons/cup'; import Heart from '../../assets/icons/heart'; @@ -20,10 +23,12 @@ import { playTone } from '../../utils/tone'; import { Spacer } from '../helpers'; import DonateForm from './donate-form'; +type RecentlyClaimedBlock = null | { block: string; superBlock: string }; + const mapStateToProps = createSelector( isDonationModalOpenSelector, recentlyClaimedBlockSelector, - (show: boolean, recentlyClaimedBlock: string) => ({ + (show: boolean, recentlyClaimedBlock: RecentlyClaimedBlock) => ({ show, recentlyClaimedBlock }) @@ -43,7 +48,7 @@ type DonateModalProps = { closeDonationModal: typeof closeDonationModal; executeGA: typeof executeGA; location?: WindowLocation; - recentlyClaimedBlock: string; + recentlyClaimedBlock: RecentlyClaimedBlock; show: boolean; }; @@ -56,49 +61,30 @@ function DonateModal({ }: DonateModalProps): JSX.Element { const [closeLabel, setCloseLabel] = React.useState(false); const { t } = useTranslation(); - const handleProcessing = ( - duration: string, - amount: number, - action: string - ) => { - executeGA({ - type: 'event', - data: { - category: 'Donation', - action: `Modal ${action}`, - label: duration, - value: amount - } - }); + const handleProcessing = () => { setCloseLabel(true); }; useEffect(() => { if (show) { void playTone('donation'); - executeGA({ type: 'modal', data: '/donation-modal' }); + executeGA({ event: 'pageview', pagePath: '/donation-modal' }); executeGA({ - type: 'event', - data: { - category: 'Donation View', - action: `Displayed ${ - recentlyClaimedBlock ? 'block' : 'progress' - } donation modal`, - nonInteraction: true - } + event: 'donationview', + action: `Displayed ${ + recentlyClaimedBlock !== null ? 'Block' : 'Progress' + } Donation Modal` }); } }, [show, recentlyClaimedBlock, executeGA]); - const getDonationText = () => { + const getCommonDonationText = () => { const donationDuration = modalDefaultDonation.donationDuration; switch (donationDuration) { - case 'onetime': + case 'one-time': return {t('donate.duration')}; case 'month': return {t('donate.duration-2')}; - case 'year': - return {t('donate.duration-3')}; default: return {t('donate.duration-4')}; } @@ -111,32 +97,28 @@ function DonateModal({ } }; - const blockDonationText = ( + const donationText = (
    - -
    - - {!closeLabel && ( - - {t('donate.nicely-done', { block: recentlyClaimedBlock })} -
    - {getDonationText()} - + {recentlyClaimedBlock !== null ? ( + + ) : ( + )} -
    -
    - ); - - const progressDonationText = ( -
    -
    -
    {!closeLabel && ( - {getDonationText()} + {recentlyClaimedBlock !== null && ( + + {t('donate.nicely-done', { + block: t( + `intro:${recentlyClaimedBlock.superBlock}.blocks.${recentlyClaimedBlock.block}.title` + ) + })} + + )} + {getCommonDonationText()} )} @@ -151,13 +133,14 @@ function DonateModal({ show={show} > - {recentlyClaimedBlock ? blockDonationText : progressDonationText} + {donationText} diff --git a/client/src/components/Donation/donation-text-components.tsx b/client/src/components/Donation/donation-text-components.tsx index 8df1792ca2fc48..208f989ccfda67 100644 --- a/client/src/components/Donation/donation-text-components.tsx +++ b/client/src/components/Donation/donation-text-components.tsx @@ -47,11 +47,13 @@ const FaqItem = ( const [isExpanded, setExpanded] = useState(false); return (
    - {isExpanded && ( <> diff --git a/client/src/components/Donation/donation.css b/client/src/components/Donation/donation.css index b955c1dc26067a..2bb6675f6e148e 100644 --- a/client/src/components/Donation/donation.css +++ b/client/src/components/Donation/donation.css @@ -224,7 +224,7 @@ margin-bottom: 3px; } .amount-values.btn-group > .btn:first-child { - margin-left: 2px; + margin-inline-start: 2px; margin-bottom: 3px; } .amount-values.btn-group .btn + .btn { @@ -519,11 +519,17 @@ a.patreon-button:hover { } .separator:not(:empty)::before { - margin-right: 0.25em; + margin-inline-end: 0.25em; } .separator:not(:empty)::after { - margin-left: 0.25em; + margin-inline-start: 0.25em; +} + +.faq-item h3 { + font-size: 1rem; + line-height: 1.5; + margin: 0; } .faq-item div { @@ -550,7 +556,7 @@ a.patreon-button:hover { margin-bottom: 0; padding: 0 4px; left: 0; - margin-left: -2px; + margin-inline-start: -2px; } .confirm-donation-btn svg.svg-inline--fa.fa-lock { diff --git a/client/src/components/Donation/patreon-button.tsx b/client/src/components/Donation/patreon-button.tsx index 7ea2702dcf13df..d40b355e1c3852 100644 --- a/client/src/components/Donation/patreon-button.tsx +++ b/client/src/components/Donation/patreon-button.tsx @@ -1,21 +1,23 @@ import React from 'react'; import { donationUrls, - patreonDefaultPledgeAmount + patreonDefaultPledgeAmount, + PaymentProvider } from '../../../../config/donation-settings'; import envData from '../../../../config/env.json'; import PatreonLogo from '../../assets/images/components/patreon-logo'; +import { PostPayment } from './types'; const { patreonClientId }: { patreonClientId: string | null } = envData as { patreonClientId: string | null; }; interface PatreonButtonProps { - postPatreonRedirect: () => void; + postPayment: (arg0: PostPayment) => void; } const PatreonButton = ({ - postPatreonRedirect + postPayment }: PatreonButtonProps): JSX.Element | null => { if ( !patreonClientId || @@ -36,7 +38,7 @@ const PatreonButton = ({ className='patreon-button link-button' data-patreon-widget-type='become-patron-button' href={href} - onClick={postPatreonRedirect} + onClick={() => postPayment({ paymentProvider: PaymentProvider.Patreon })} rel='noreferrer' target='_blank' > diff --git a/client/src/components/Donation/paypal-button-script-loader.tsx b/client/src/components/Donation/paypal-button-script-loader.tsx index 501164c47545dc..aa14fc5f724692 100644 --- a/client/src/components/Donation/paypal-button-script-loader.tsx +++ b/client/src/components/Donation/paypal-button-script-loader.tsx @@ -4,7 +4,7 @@ import ReactDOM from 'react-dom'; import { scriptLoader, scriptRemover } from '../../utils/script-loaders'; -import type { AddDonationData } from './paypal-button'; +import type { DonationApprovalData } from './types'; /* eslint-disable @typescript-eslint/naming-convention */ type PayPalButtonScriptLoaderProps = { @@ -30,7 +30,7 @@ type PayPalButtonScriptLoaderProps = { ) => unknown; isSubscription: boolean; onApprove: ( - data: AddDonationData, + data: DonationApprovalData, actions?: { order: { capture: () => Promise } } ) => unknown; isPaypalLoading: boolean; @@ -66,7 +66,7 @@ declare global { } } -export class PayPalButtonScriptLoader extends Component< +export default class PayPalButtonScriptLoader extends Component< PayPalButtonScriptLoaderProps, PayPalButtonScriptLoaderState > { @@ -188,7 +188,7 @@ export class PayPalButtonScriptLoader extends Component< onApprove={ isSubscription ? ( - data: AddDonationData, + data: DonationApprovalData, actions: { order: { capture: () => Promise } } ) => onApprove(data, actions) : ( diff --git a/client/src/components/Donation/paypal-button.test.tsx b/client/src/components/Donation/paypal-button.test.tsx deleted file mode 100644 index 5c60f0ec5d349e..00000000000000 --- a/client/src/components/Donation/paypal-button.test.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { render } from '@testing-library/react'; -import React from 'react'; -import { Themes } from '../settings/theme'; - -import { PaypalButton } from './paypal-button'; - -const commonProps = { - donationAmount: 500, - donationDuration: 'month', - handleProcessing: () => null, - isDonating: false, - onDonationStateChange: () => null, - isPaypalLoading: true, - t: jest.fn(), - theme: Themes.Night, - handlePaymentButtonLoad: jest.fn(), - isMinimalForm: true -}; - -const donationData = { - redirecting: false, - processing: false, - success: false, - error: null -}; - -jest.mock('../../analytics'); - -describe('', () => { - it('does not call addDonate api on payment approval when user is not signed ', () => { - const ref = React.createRef(); - const isSubscription = true; - const addDonation = jest.fn(); - render( - - ); - - ref.current?.handleApproval(donationData, isSubscription); - expect(addDonation).toBeCalledTimes(0); - }); - it('calls addDonate api on payment approval when user is signed in', () => { - const ref = React.createRef(); - const isSubscription = true; - const addDonation = jest.fn(); - render( - - ); - - ref.current?.handleApproval(donationData, isSubscription); - expect(addDonation).toBeCalledTimes(1); - }); -}); diff --git a/client/src/components/Donation/paypal-button.tsx b/client/src/components/Donation/paypal-button.tsx index 7d51b8063a7e31..3e54d4fd1190ee 100644 --- a/client/src/components/Donation/paypal-button.tsx +++ b/client/src/components/Donation/paypal-button.tsx @@ -5,23 +5,23 @@ import { createSelector } from 'reselect'; import { paypalConfigurator, paypalConfigTypes, - defaultDonation + defaultDonation, + PaymentProvider } from '../../../../config/donation-settings'; import envData from '../../../../config/env.json'; import { userSelector, signInLoadingSelector } from '../../redux/selectors'; import { Themes } from '../settings/theme'; -import { PayPalButtonScriptLoader } from './paypal-button-script-loader'; +import { + DonationApprovalData, + PostPayment, + DonationDuration, + DonationAmount +} from './types'; +import PayPalButtonScriptLoader from './paypal-button-script-loader'; type PaypalButtonProps = { - addDonation: (data: AddDonationData) => void; - isSignedIn: boolean; - donationAmount: number; - donationDuration: string; - handleProcessing: ( - duration: string, - amount: number, - action: string - ) => unknown; + donationAmount: DonationAmount; + donationDuration: DonationDuration; isDonating: boolean; onDonationStateChange: ({ redirecting, @@ -35,13 +35,13 @@ type PaypalButtonProps = { error: string | null; }) => void; isPaypalLoading: boolean; - skipAddDonation?: boolean; t: (label: string) => string; ref?: Ref; theme: Themes; isSubscription?: boolean; handlePaymentButtonLoad: (provider: 'stripe' | 'paypal') => void; isMinimalForm: boolean | undefined; + postPayment: (arg0: PostPayment) => void; }; type PaypalButtonState = { @@ -50,17 +50,6 @@ type PaypalButtonState = { planId: string | null; }; -export interface AddDonationData { - redirecting: boolean; - processing: boolean; - success: boolean; - error: string | null; - loading?: { - stripe: boolean; - paypal: boolean; - }; -} - const { paypalClientId, deploymentEnv @@ -70,10 +59,7 @@ const { deploymentEnv: 'staging' | 'live'; }; -export class PaypalButton extends Component< - PaypalButtonProps, - PaypalButtonState -> { +class PaypalButton extends Component { static displayName = 'PaypalButton'; state: PaypalButtonState = { amount: defaultDonation.donationAmount, @@ -82,7 +68,6 @@ export class PaypalButton extends Component< }; constructor(props: PaypalButtonProps) { super(props); - this.handleApproval = this.handleApproval.bind(this); } static getDerivedStateFromProps( @@ -90,8 +75,8 @@ export class PaypalButton extends Component< ): PaypalButtonState { const { donationAmount, donationDuration } = props; const configurationObj: { - amount: number; - duration: string; + amount: DonationAmount; + duration: DonationDuration; planId: string | null; } = paypalConfigurator( donationAmount, @@ -105,30 +90,10 @@ export class PaypalButton extends Component< return { ...configurationObj }; } - handleApproval = (data: AddDonationData, isSubscription: boolean): void => { - const { amount, duration } = this.state; - const { isSignedIn = false } = this.props; - - // If the user is signed in and the payment is subscritipn call the api - if (isSignedIn && isSubscription) { - this.props.addDonation(data); - } - - this.props.handleProcessing(duration, amount, 'Paypal payment submission'); - - // Show success anytime because the payment has gone through paypal - this.props.onDonationStateChange({ - redirecting: false, - processing: false, - success: true, - error: data.error ? data.error : null - }); - }; - render(): JSX.Element | null { const { duration, planId, amount } = this.state; const { t, theme, isPaypalLoading, isMinimalForm } = this.props; - const isSubscription = duration !== 'onetime'; + const isSubscription = duration !== 'one-time'; const buttonColor = theme === Themes.Night ? 'white' : 'gold'; if (!paypalClientId) { return null; @@ -177,8 +142,11 @@ export class PaypalButton extends Component< isMinimalForm={isMinimalForm} isPaypalLoading={isPaypalLoading} isSubscription={isSubscription} - onApprove={(data: AddDonationData) => { - this.handleApproval(data, isSubscription); + onApprove={(data: DonationApprovalData) => { + this.props.postPayment({ + paymentProvider: PaymentProvider.Paypal, + data + }); }} onCancel={() => { this.props.onDonationStateChange({ diff --git a/client/src/components/Donation/stripe-card-form.tsx b/client/src/components/Donation/stripe-card-form.tsx index deb1d9c0f2e7db..f10ac62de7081b 100644 --- a/client/src/components/Donation/stripe-card-form.tsx +++ b/client/src/components/Donation/stripe-card-form.tsx @@ -9,33 +9,23 @@ import { import { loadStripe } from '@stripe/stripe-js'; import type { StripeCardNumberElementChangeEvent, - StripeCardExpiryElementChangeEvent, - PaymentIntentResult + StripeCardExpiryElementChangeEvent } from '@stripe/stripe-js'; import React, { useState } from 'react'; +import { PaymentProvider } from '../../../../config/donation-settings'; import envData from '../../../../config/env.json'; import { Themes } from '../settings/theme'; -import { AddDonationData } from './paypal-button'; -import SecurityLockIcon from './security-lock-icon'; +import { DonationApprovalData, PostPayment } from './types'; const { stripePublicKey }: { stripePublicKey: string | null } = envData; -export type HandleAuthentication = ( - clientSecret: string, - paymentMethod: string -) => Promise; - interface FormPropTypes { - onDonationStateChange: (donationState: AddDonationData) => void; - postStripeCardDonation: ( - paymentMethodId: string, - handleAuthentication: HandleAuthentication - ) => void; + onDonationStateChange: (donationState: DonationApprovalData) => void; + postPayment: (arg0: PostPayment) => void; t: (label: string) => string; theme: Themes; processing: boolean; - isVariantA: boolean; } interface Element { @@ -50,9 +40,8 @@ const StripeCardForm = ({ theme, t, onDonationStateChange, - postStripeCardDonation, - processing, - isVariantA + postPayment, + processing }: FormPropTypes): JSX.Element => { const [isSubmissionValid, setSubmissionValidity] = useState(true); const [isTokenizing, setTokenizing] = useState(false); @@ -124,7 +113,11 @@ const StripeCardForm = ({ error: t('donate.went-wrong') }); } else if (paymentMethod) - postStripeCardDonation(paymentMethod.id, handleAuthentication); + postPayment({ + paymentProvider: PaymentProvider.StripeCard, + paymentMethodId: paymentMethod.id, + handleAuthentication + }); } } return setTokenizing(false); @@ -170,7 +163,6 @@ const StripeCardForm = ({ disabled={!stripe || !elements || isSubmitting} type='submit' > - {!isVariantA && } {t('buttons.donate')} diff --git a/client/src/components/Donation/types.ts b/client/src/components/Donation/types.ts new file mode 100644 index 00000000000000..956c8da1518ec5 --- /dev/null +++ b/client/src/components/Donation/types.ts @@ -0,0 +1,37 @@ +import type { Token, PaymentIntentResult } from '@stripe/stripe-js'; + +export type PaymentContext = 'modal' | 'donate page' | 'certificate'; +export type PaymentProvider = 'patreon' | 'paypal' | 'stripe' | 'stripe card'; + +export type HandleAuthentication = ( + clientSecret: string, + paymentMethod: string +) => Promise; + +export type DonationAmount = 500 | 1000 | 2000 | 3000 | 4000 | 5000; +export type DonationDuration = 'one-time' | 'month'; +export interface DonationConfig { + donationAmount: DonationAmount; + donationDuration: DonationDuration; +} + +export interface PostPayment { + paymentProvider: PaymentProvider; + data?: DonationApprovalData; + token?: Token; + payerEmail?: string | undefined; + payerName?: string | undefined; + paymentMethodId?: string; + handleAuthentication?: HandleAuthentication; +} + +export interface DonationApprovalData { + redirecting: boolean; + processing: boolean; + success: boolean; + error: string | null; + loading?: { + stripe: boolean; + paypal: boolean; + }; +} diff --git a/client/src/components/Donation/walletsButton.tsx b/client/src/components/Donation/walletsButton.tsx index c3831744609f9d..668b279ee6085a 100644 --- a/client/src/components/Donation/walletsButton.tsx +++ b/client/src/components/Donation/walletsButton.tsx @@ -8,7 +8,8 @@ import type { Token, PaymentRequest } from '@stripe/stripe-js'; import React, { useState, useEffect } from 'react'; import envData from '../../../../config/env.json'; import { Themes } from '../settings/theme'; -import { AddDonationData } from './paypal-button'; +import { PaymentProvider } from '../../../../config/donation-settings'; +import { DonationApprovalData, PostPayment } from './types'; const { stripePublicKey }: { stripePublicKey: string | null } = envData; @@ -16,12 +17,8 @@ interface WrapperProps { label: string; amount: number; theme: Themes; - postStripeDonation: ( - token: Token, - payerEmail: string | undefined, - payerName: string | undefined - ) => void; - onDonationStateChange: (donationState: AddDonationData) => void; + postPayment: (arg0: PostPayment) => void; + onDonationStateChange: (donationState: DonationApprovalData) => void; refreshErrorMessage: string; handlePaymentButtonLoad: (provider: 'stripe' | 'paypal') => void; } @@ -35,7 +32,7 @@ const WalletsButton = ({ amount, theme, refreshErrorMessage, - postStripeDonation, + postPayment, onDonationStateChange, handlePaymentButtonLoad }: WalletsButtonProps) => { @@ -63,7 +60,12 @@ const WalletsButton = ({ const { token, payerEmail, payerName } = event; setToken(token); event.complete('success'); - postStripeDonation(token, payerEmail, payerName); + postPayment({ + paymentProvider: PaymentProvider.Stripe, + token, + payerEmail, + payerName + }); }); void pr.canMakePayment().then(canMakePaymentRes => { @@ -74,7 +76,7 @@ const WalletsButton = ({ checkpaymentPossiblity(false); } }); - }, [label, amount, stripe, postStripeDonation, handlePaymentButtonLoad]); + }, [label, amount, stripe, postPayment, handlePaymentButtonLoad]); const displayRefreshError = (): void => { onDonationStateChange({ diff --git a/client/src/components/Flash/index.tsx b/client/src/components/Flash/index.tsx index 6accd829365ded..e753212cf45df4 100644 --- a/client/src/components/Flash/index.tsx +++ b/client/src/components/Flash/index.tsx @@ -1,5 +1,5 @@ import { Alert } from '@freecodecamp/react-bootstrap'; -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { useTranslation } from 'react-i18next'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import { FlashState } from '../../redux/types'; @@ -15,45 +15,24 @@ type FlashProps = { function Flash({ flashMessage, removeFlashMessage }: FlashProps): JSX.Element { const { type, message, id, variables } = flashMessage; const { t } = useTranslation(); - const [flashMessageHeight, setFlashMessageHeight] = useState(0); - - useEffect(() => { - const flashMessageElem: HTMLElement | null = - document.querySelector('.flash-message'); - setFlashMessageHeight(flashMessageElem?.offsetHeight || 0); - document.documentElement.style.setProperty( - '--flash-message-height', - `${flashMessageHeight}px` - ); - }, [flashMessageHeight]); function handleClose() { - document.documentElement.style.setProperty('--flash-message-height', '0px'); removeFlashMessage(); } return ( - <> - - - - {t(message, variables)} - - - - {flashMessage && ( -
    - )} - + + + + {t(message, variables)} + + + ); } diff --git a/client/src/components/Footer/footer.css b/client/src/components/Footer/footer.css index 69748558984d31..730b1096829151 100644 --- a/client/src/components/Footer/footer.css +++ b/client/src/components/Footer/footer.css @@ -10,12 +10,8 @@ } .footer-container { - margin-right: auto; - margin-left: auto; - padding-left: 15px; - padding-right: 15px; - padding-top: 40px; - padding-bottom: 40px; + margin-inline: auto; + padding: 40px 15px; font-size: 16px; overflow-x: hidden; } @@ -57,8 +53,7 @@ display: flex; flex-direction: column; flex: 0 0 100%; - padding-left: 15px; - padding-right: 15px; + padding-inline: 15px; font-size: 16px; } @@ -77,8 +72,7 @@ flex: 1 0 90%; display: flex; flex-direction: column; - padding-left: 15px; - padding-right: 15px; + padding-inline: 15px; margin-bottom: 30px; } @@ -125,7 +119,7 @@ p.footer-donation a:hover { flex-direction: row; } .footer-right { - padding-left: 15px; + padding-inline-start: 15px; } .footer-col-1, .footer-col-2, @@ -152,7 +146,7 @@ p.footer-donation a:hover { flex-direction: column; } .footer-right { - padding-left: 0; + padding-inline-start: 0; } .footer-container .col-spacer { margin-top: 40px; diff --git a/client/src/components/FourOhFour/404.css b/client/src/components/FourOhFour/404.css index ebc2607d8efc52..ef87fe44c3f41d 100644 --- a/client/src/components/FourOhFour/404.css +++ b/client/src/components/FourOhFour/404.css @@ -15,7 +15,8 @@ .quote-wrapper { background-color: var(--tertiary-background); - padding: 20px 20px 20px 42px; + padding-inline: 42px 20px; + padding-block: 20px; border-width: 0; position: relative; max-width: 980px; @@ -34,7 +35,7 @@ color: var(--tertiary-color); font-family: 'Arial', sans-serif; font-style: normal; - padding-left: 15px; + padding-inline-start: 15px; padding-top: 5px; position: absolute; border-radius: 0; diff --git a/client/src/components/Header/components/nav-links.tsx b/client/src/components/Header/components/nav-links.tsx index dc9bd246338de5..bd6da9d1a3364e 100644 --- a/client/src/components/Header/components/nav-links.tsx +++ b/client/src/components/Header/components/nav-links.tsx @@ -1,6 +1,3 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -/* eslint-disable @typescript-eslint/no-unsafe-call */ -// @ts-nocheck import { faCheckSquare, faHeart, @@ -11,7 +8,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React, { Component, Fragment, createRef } from 'react'; import { TFunction, withTranslation } from 'react-i18next'; import { connect } from 'react-redux'; -import envData from '../../../../../config/env.json'; +import { clientLocale, radioLocation } from '../../../../../config/env.json'; import { availableLangs, LangNames, @@ -26,14 +23,6 @@ import { Themes } from '../../settings/theme'; import LanguageGlobe from '../../../assets/icons/language-globe'; import { User } from '../../../redux/prop-types'; -interface NavigationLocationApi { - clientLocale: string; - radioLocation: string; - apiLocation: string; -} - -const { clientLocale, radioLocation } = envData as NavigationLocationApi; - const locales = availableLangs.client.filter( lang => !hiddenLangs.includes(lang) ); @@ -50,10 +39,10 @@ interface NavLinksProps { t: TFunction; showMenu: () => void; hideMenu: () => void; - toggleNightMode: (theme: Themes) => void; + toggleNightMode: (theme: Themes) => Themes; user?: User; navigate?: (location: string) => void; - showLanguageMenu: (elementToFocus: HTMLButtonElement) => void; + showLanguageMenu: (elementToFocus: HTMLButtonElement | null) => void; hideLanguageMenu: () => void; menuButtonRef: React.RefObject; openSignoutModal: () => void; @@ -65,7 +54,7 @@ const mapDispatchToProps = { openSignoutModal }; -export class NavLinks extends Component { +class NavLinks extends Component { static displayName: string; langButtonRef: React.RefObject; firstLangOptionRef: React.RefObject; @@ -95,11 +84,14 @@ export class NavLinks extends Component { ); } - getPreviousMenuItem(target: HTMLButtonElement): HTMLButtonElement { + getPreviousMenuItem(target: HTMLButtonElement | null) { const { menuButtonRef } = this.props; const previousSibling = target?.closest('.nav-list > li')?.previousElementSibling; - return previousSibling?.querySelector('a, button') ?? menuButtonRef.current; + const previousButton = previousSibling?.querySelector< + HTMLButtonElement | HTMLAnchorElement + >('a, button'); + return previousButton ?? menuButtonRef.current; } handleLanguageChange = (event: React.MouseEvent): void => { @@ -144,7 +136,9 @@ export class NavLinks extends Component { } }; - handleMenuKeyDown = (event: React.KeyboardEvent): void => { + handleMenuKeyDown = ( + event: React.KeyboardEvent + ) => { const { menuButtonRef, hideMenu } = this.props; if (event.key === 'Escape') { menuButtonRef.current?.focus(); @@ -153,7 +147,7 @@ export class NavLinks extends Component { } }; - handleLanguageButtonClick = (): void => { + handleLanguageButtonClick = () => { const { isLanguageMenuDisplayed, hideLanguageMenu, showLanguageMenu } = this.props; if (isLanguageMenuDisplayed) { @@ -163,38 +157,72 @@ export class NavLinks extends Component { } }; + handleSignOutKeys = ( + event: React.KeyboardEvent + ) => { + const { menuButtonRef, hideMenu } = this.props; + const DoKeyPress = new Map void }>([ + [ + 'Escape', + { + select: () => { + menuButtonRef.current?.focus(); + hideMenu(); + event.preventDefault(); + } + } + ], + [ + 'Tab', + { + select: () => { + const camperPressedTheShiftKey = event.shiftKey; + if (!camperPressedTheShiftKey) { + hideMenu(); + } + } + } + ] + ]); + DoKeyPress.get(event.key)?.select(); + }; handleLanguageButtonKeyDown = ( event: React.KeyboardEvent ): void => { const { menuButtonRef, showLanguageMenu, hideMenu } = this.props; - interface DoKeyPressProp { - Escape: () => void; - ArrowDown: () => void; - ArrowUp: () => void; - } - - // eslint naming convention should be ignored in key press function, because following the name convention harms accessiblity. - - const DoKeyPress: DoKeyPressProp = { - // eslint-disable-next-line @typescript-eslint/naming-convention - Escape: () => { - menuButtonRef.current?.focus(); - hideMenu(); - event.preventDefault(); - }, - // eslint-disable-next-line @typescript-eslint/naming-convention - ArrowDown: () => { - showLanguageMenu(this.firstLangOptionRef.current); - event.preventDefault(); - }, - // eslint-disable-next-line @typescript-eslint/naming-convention - ArrowUp: () => { - showLanguageMenu(this.lastLangOptionRef.current); - event.preventDefault(); - } - }; - DoKeyPress[event.key]?.(); + // the strings in map need to start with a Capital latter, because event.key preduce a string that starts with a capital latter + const DoKeyPress = new Map void }>([ + [ + 'Escape', + { + select: () => { + menuButtonRef.current?.focus(); + hideMenu(); + event.preventDefault(); + } + } + ], + [ + 'ArrowDown', + { + select: () => { + showLanguageMenu(this.firstLangOptionRef.current); + event.preventDefault(); + } + } + ], + [ + 'ArrowUp', + { + select: () => { + showLanguageMenu(this.lastLangOptionRef.current); + event.preventDefault(); + } + } + ] + ]); + DoKeyPress.get(event.key)?.select(); }; handleLanguageMenuKeyDown = ( @@ -209,70 +237,93 @@ export class NavLinks extends Component { this.lastLangOptionRef.current?.focus(); event.preventDefault(); }; - const DoKeyPress = { - // eslint-disable-next-line @typescript-eslint/naming-convention - Tab: () => { - if (!event.shiftKey) { - // Let the Tab work as normal. - hideLanguageMenu(); - // Close the menu if focus is now outside of the menu. This will - // happen when there is no Sign Out menu item. - setTimeout(() => { - const currentlyFocusedElement = document.activeElement; - if ( - currentlyFocusedElement && - !currentlyFocusedElement.closest('.nav-list') - ) { - hideMenu(); + const DoKeyPress = new Map void }>([ + [ + 'Tab', + { + select: () => { + if (!event.shiftKey) { + // Let the Tab work as normal. + hideLanguageMenu(); + // Close the menu if focus is now outside of the menu. This will + // happen when there is no Sign Out menu item. + setTimeout(() => { + const currentlyFocusedElement = document.activeElement; + if ( + currentlyFocusedElement && + !currentlyFocusedElement.closest('.nav-list') + ) { + hideMenu(); + } + }, 200); + return; } - }, 200); - return; + // Because FF adds an extra Tab stop to the lang menu (because it + // is scrollable) we need to manually focus the previous menu item. + const currentButton = this.langButtonRef.current; + this.getPreviousMenuItem(currentButton)?.focus(); + hideLanguageMenu(); + event.preventDefault(); + } } - // Because FF adds an extra Tab stop to the lang menu (because it - // is scrollable) we need to manually focus the previous menu item. - this.getPreviousMenuItem(this.langButtonRef.current).focus(); - hideLanguageMenu(); - event.preventDefault(); - }, - // eslint-disable-next-line @typescript-eslint/naming-convention - ArrowUp: () => { - const ArrowUpItemToFocus = - event.target === this.firstLangOptionRef.current - ? this.lastLangOptionRef.current - : (event.currentTarget.parentNode?.previousSibling - ?.firstChild as HTMLElement); - ArrowUpItemToFocus?.focus(); - event.preventDefault(); - }, - // eslint-disable-next-line @typescript-eslint/naming-convention - ArrowDown: () => { - const ArrowDownItemToFocus = - event.target === this.lastLangOptionRef.current - ? this.firstLangOptionRef.current - : (event.currentTarget.parentNode?.nextSibling - ?.firstChild as HTMLElement); - ArrowDownItemToFocus?.focus(); - event.preventDefault(); - }, - // eslint-disable-next-line @typescript-eslint/naming-convention - Escape: () => { - // Set focus to language button first so we don't lose focus - // for screen readers. - this.langButtonRef.current?.focus(); - hideLanguageMenu(); - event.preventDefault(); - }, - Home: focusFirstLanguageMenuItem, - PageUp: focusFirstLanguageMenuItem, - End: focusLastLanguageMenuItem, - PageDown: focusLastLanguageMenuItem - }; - DoKeyPress[event.key]?.(); + ], + [ + 'Escape', + { + select: () => { + this.langButtonRef.current?.focus(); + hideLanguageMenu(); + event.preventDefault(); + } + } + ], + [ + 'ArrowDown', + { + select: () => { + const isFocusOnLastLanguageOption = + event.target === this.lastLangOptionRef.current; + const selectCancelButton = this.firstLangOptionRef.current?.focus(); + const selectNextLanguage = ( + event.currentTarget.parentNode?.nextSibling + ?.firstChild as HTMLButtonElement + )?.focus(); + isFocusOnLastLanguageOption + ? selectCancelButton + : selectNextLanguage; + event.preventDefault(); + } + } + ], + [ + 'ArrowUp', + { + select: () => { + const isFocusOnCancelButton = + event.target === this.firstLangOptionRef.current; + const selectLastLanguage = this.lastLangOptionRef.current?.focus(); + // selectPreviousLanguage is a childNode and doesn't have focus property but it still works somehow, + // IDK how it works, and how to please TypeScript, for now I am lying to TypeScript + const selectPreviousLanguage = ( + event.currentTarget.parentNode?.previousSibling + ?.firstChild as HTMLButtonElement + )?.focus(); + isFocusOnCancelButton ? selectLastLanguage : selectPreviousLanguage; + event.preventDefault(); + } + } + ], + ['Home', { select: focusFirstLanguageMenuItem }], + ['PageUp', { select: focusFirstLanguageMenuItem }], + ['End', { select: focusLastLanguageMenuItem }], + ['PageDown', { select: focusLastLanguageMenuItem }] + ]); + DoKeyPress.get(event.key)?.select(); }; // Added to the last item in the nav menu. Will close the menu if // the user Tabs out of the menu. - handleBlur = (event: React.FocusEvent): void => { + handleBlur = (event: React.FocusEvent) => { const { hideMenu, menuButtonRef } = this.props; if ( event.relatedTarget && @@ -296,9 +347,11 @@ export class NavLinks extends Component { fetchState, t, toggleNightMode, - user: { isDonating = false, username, theme } + user }: NavLinksProps = this.props; - + const currentUserDonating = user?.isDonating; + const currentUserName = user?.username; + const currentUserTheme = user?.theme; const { pending } = fetchState; return pending ? ( @@ -310,7 +363,7 @@ export class NavLinks extends Component { isLanguageMenuDisplayed ? ' display-lang-menu' : '' }`} > - {isDonating ? ( + {currentUserDonating ? (
  • {t('donate.thanks')} @@ -338,14 +391,14 @@ export class NavLinks extends Component { {t('buttons.curriculum')}
  • - {username && ( - + {currentUserName && ( + <>
  • {t('buttons.profile')} @@ -360,7 +413,7 @@ export class NavLinks extends Component { {t('buttons.settings')}
  • -
    + )}
  • {
  • + {/* + The div existences create edge case in which camper skips the change language, + when they press "shift+tab" on signout button whenever signout focus events uses `getPreviousMenuItem`. + To fix this we need to remove `div`, but this creates a bug which close the menu when someone interact with it any other way except the keyboard. + This is a complexy and footgun that can break the site without notices and we shouldn't carry, + to sort this we need to remove the div and make focus events simpler, but that's a ToDo for later. + */}
  • - {username && ( - -
  • - -
  • -
    + {currentUserName && ( +
  • + +
  • )} ); @@ -518,4 +579,7 @@ export class NavLinks extends Component { NavLinks.displayName = 'NavLinks'; +/* eslint-disable @typescript-eslint/ban-ts-comment */ +//@ts-ignore +// to please TypeScript, action.js needs to be migrated to TypeScript export default connect(null, mapDispatchToProps)(withTranslation()(NavLinks)); diff --git a/client/src/components/Header/components/nav-logo.tsx b/client/src/components/Header/components/nav-logo.tsx index 94111b149c73f5..393b8f32df0fef 100644 --- a/client/src/components/Header/components/nav-logo.tsx +++ b/client/src/components/Header/components/nav-logo.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import FreeCodeCampLogo from '../../../assets/icons/FreeCodeCamp-logo'; +import FreeCodeCampLogo from '../../../assets/icons/freecodecamp'; const NavLogo = (): JSX.Element => { const { t } = useTranslation(); diff --git a/client/src/components/Header/components/universal-nav.css b/client/src/components/Header/components/universal-nav.css index c8bed3e19d6eaf..83d8dec691c000 100644 --- a/client/src/components/Header/components/universal-nav.css +++ b/client/src/components/Header/components/universal-nav.css @@ -21,7 +21,7 @@ .universal-nav-left { display: flex; flex: 1 0 33%; - margin-left: 0; + margin-inline-start: 0; z-index: 2000; } @@ -41,6 +41,7 @@ display: flex; justify-content: flex-end; align-items: center; + gap: 10px; flex: 1 0 33%; height: var(--header-height); } @@ -82,7 +83,6 @@ justify-content: flex-end; width: 100vw; height: auto; - margin: 0 0 0 -12px; padding: 0; list-style: none; max-width: 15rem; @@ -313,14 +313,14 @@ button.nav-link[aria-disabled='true'] { .nav-skeleton { height: var(--header-height); - margin-right: 15px; + margin-inline-end: 15px; width: 350px; } .nav-list .fcc-loader { padding: 0 40px; - margin-left: 35px; - margin-right: 25px; + margin-inline-start: 35px; + margin-inline-end: 25px; } .toggle-button-nav { @@ -332,7 +332,6 @@ button.nav-link[aria-disabled='true'] { background-color: var(--theme-color); cursor: pointer; max-height: calc(var(--header-height) - 8px); - margin-right: 10px; display: flex; align-items: center; } @@ -436,8 +435,8 @@ button.nav-link[aria-disabled='true'] { .signup-btn { max-height: calc(var(--header-height) - 6px); padding: 4px 12px; - margin-left: 2px; - font-family: 'Hack-ZeroSlash', monospace !important; + margin-inline-start: 2px; + font-family: 'Hack-ZeroSlash', monospace; display: flex; align-items: center; justify-content: center; @@ -445,16 +444,12 @@ button.nav-link[aria-disabled='true'] { .universal-nav-right .fcc_searchBar { position: absolute; - top: 0; + top: var(--header-height); left: 0; } .universal-nav-right .fcc_searchBar .ais-SearchBox-form { - width: 100vw; - height: var(--search-box-form); max-width: unset; - padding: 0 15px; - left: 0; } /* In mobile layout, prevent search input from hanging around if the @@ -475,26 +470,24 @@ button.nav-link[aria-disabled='true'] { display: none; } -.universal-nav-right .ais-SearchBox-input { +.universal-nav-right .ais-SearchBox-form { width: calc(100vw - 17rem); - padding-left: 27px; + margin-inline-start: 15px; } .universal-nav-right .fcc_searchBar .ais-Hits { width: calc(100vw - 17rem); } -.universal-nav-right .fcc_searchBar .ais-SearchBox-submit { - top: unset; - margin-top: 19px; - left: 18px; -} - .ais-SearchBox-input:focus { + box-sizing: content-box; + margin-inline-start: -30px; + padding-inline: 35px; outline: 3px solid var(--blue-mid); } -.ais-SearchBox-submit:focus { +.ais-SearchBox-submit:focus, +.ais-SearchBox-reset:focus { outline: 3px solid var(--blue-mid); } @@ -528,10 +521,6 @@ button.nav-link[aria-disabled='true'] { } .fcc_searchBar .ais-SearchBox-form { - display: flex; - position: absolute; - top: var(--header-height); - left: 15px; max-width: calc(100vw - 350px); } @@ -560,17 +549,13 @@ button.nav-link[aria-disabled='true'] { } .universal-nav-right .fcc_searchBar .ais-SearchBox-form { - width: 100%; + width: calc(100% - 30px); } .display-menu { max-height: calc(100vh - var(--header-height) * 2); } - .universal-nav-right .ais-SearchBox-input { - width: calc(100vw - 30px); - } - .universal-nav-right .fcc_searchBar .ais-Hits { width: calc(100% - 30px); } diff --git a/client/src/components/Header/components/universal-nav.tsx b/client/src/components/Header/components/universal-nav.tsx index ea1ce8aec2d6b7..c2eb7da86a9684 100644 --- a/client/src/components/Header/components/universal-nav.tsx +++ b/client/src/components/Header/components/universal-nav.tsx @@ -26,7 +26,7 @@ interface UniversalNavProps { searchBarRef?: React.RefObject; showMenu: () => void; hideMenu: () => void; - showLanguageMenu: (elementToFocus: HTMLButtonElement) => void; + showLanguageMenu: (elementToFocus: HTMLButtonElement | null) => void; hideLanguageMenu: () => void; user?: User; } diff --git a/client/src/components/Header/index.tsx b/client/src/components/Header/index.tsx index 54a6532bb4cae9..d55e39a397e94b 100644 --- a/client/src/components/Header/index.tsx +++ b/client/src/components/Header/index.tsx @@ -13,6 +13,7 @@ import './header.css'; interface HeaderProps { fetchState: { pending: boolean }; user: User; + skipButtonText: string; } export class Header extends React.Component< HeaderProps, @@ -46,6 +47,8 @@ export class Header extends React.Component< // the search bar should not toggle the menu this.searchBarRef.current && !this.searchBarRef.current.contains(eventTarget) && + // don't count clicks on searcn bar inputs reset button + !eventTarget.closest('.ais-SearchBox-reset') && // don't count clicks on language button/menu !eventTarget.closest('.nav-lang') && // don't count clicks on disabled elements @@ -69,9 +72,9 @@ export class Header extends React.Component< } // elementToFocus must be a link in the language menu - showLanguageMenu(elementToFocus: HTMLButtonElement): void { + showLanguageMenu(elementToFocus: HTMLButtonElement | null): void { this.setState({ isLanguageMenuDisplayed: true }, () => - elementToFocus.focus() + elementToFocus?.focus() ); } @@ -81,7 +84,7 @@ export class Header extends React.Component< render(): JSX.Element { const { displayMenu, isLanguageMenuDisplayed } = this.state; - const { fetchState, user } = this.props; + const { fetchState, user, skipButtonText } = this.props; return ( <> @@ -93,7 +96,7 @@ export class Header extends React.Component<
    - Skip To Content + {skipButtonText} ; -function SolutionViewer({ challengeFiles, solution }: Props) { +function SolutionViewer({ challengeFiles, solution }: Props): JSX.Element { const isLegacy = !challengeFiles || !challengeFiles.length; const solutions = isLegacy ? [ diff --git a/client/src/components/app-mount-notifier.test.tsx b/client/src/components/app-mount-notifier.test.tsx index 78c83e1ba8b7dd..215d99c94c04b9 100644 --- a/client/src/components/app-mount-notifier.test.tsx +++ b/client/src/components/app-mount-notifier.test.tsx @@ -5,10 +5,9 @@ import { Provider } from 'react-redux'; import { i18nextCodes } from '../../../config/i18n'; import i18nTestConfig from '../../i18n/config-for-tests'; -import { createStore } from '../redux/createStore'; +import { createStore } from '../redux/create-store'; import AppMountNotifier from './app-mount-notifier'; -jest.mock('react-ga'); jest.unmock('react-i18next'); type Language = keyof typeof i18nextCodes; diff --git a/client/src/components/formHelpers/__snapshots__/block-save-wrapper.test.tsx.snap b/client/src/components/formHelpers/__snapshots__/block-save-wrapper.test.tsx.snap deleted file mode 100644 index b088aec7c3c3ee..00000000000000 --- a/client/src/components/formHelpers/__snapshots__/block-save-wrapper.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[` snapshot 1`] = ` -
    -
    -
    -`; diff --git a/client/src/components/formHelpers/block-save-button.tsx b/client/src/components/formHelpers/block-save-button.tsx deleted file mode 100644 index 2adad66ffd39c1..00000000000000 --- a/client/src/components/formHelpers/block-save-button.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Button } from '@freecodecamp/react-bootstrap'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -function BlockSaveButton(props?: Record): JSX.Element { - const { t } = useTranslation(); - return ( - - ); -} - -BlockSaveButton.displayName = 'BlockSaveButton'; - -export default BlockSaveButton; diff --git a/client/src/components/formHelpers/block-save-wrapper.test.tsx b/client/src/components/formHelpers/block-save-wrapper.test.tsx deleted file mode 100644 index 25e9acff3bc76c..00000000000000 --- a/client/src/components/formHelpers/block-save-wrapper.test.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { render } from '@testing-library/react'; -import React from 'react'; - -import BlockSaveWrapper from './block-save-wrapper'; - -test(' snapshot', () => { - const { container } = render(); - - expect(container).toMatchSnapshot(); -}); diff --git a/client/src/components/formHelpers/block-save-wrapper.tsx b/client/src/components/formHelpers/block-save-wrapper.tsx deleted file mode 100644 index 79186be5deb97e..00000000000000 --- a/client/src/components/formHelpers/block-save-wrapper.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; - -const style = { - padding: '0 15px' -}; - -function BlockSaveWrapper({ - children -}: { - children?: React.ReactElement | null; -}): JSX.Element { - return
    {children}
    ; -} - -BlockSaveWrapper.displayName = 'BlockSaveWrapper'; - -export default BlockSaveWrapper; diff --git a/client/src/components/formHelpers/form-fields.tsx b/client/src/components/formHelpers/form-fields.tsx index 226367262125b9..7c9b0afec05d3d 100644 --- a/client/src/components/formHelpers/form-fields.tsx +++ b/client/src/components/formHelpers/form-fields.tsx @@ -14,7 +14,8 @@ import { localhostValidator, composeValidators, fCCValidator, - httpValidator + httpValidator, + pathValidator } from './form-validators'; import './form-field.css'; @@ -65,7 +66,8 @@ function FormFields(props: FormFieldsProps): JSX.Element { name === 'githubLink' || isEditorLinkAllowed ? null : editorValidator, fCCValidator, httpValidator, - isLocalLinkAllowed ? null : localhostValidator + isLocalLinkAllowed ? null : localhostValidator, + pathValidator )(value); const message: string = (error || validationError || @@ -102,8 +104,7 @@ function FormFields(props: FormFieldsProps): JSX.Element { name in placeholders ? placeholders[name] : ''; const isURL = types[name] === 'url'; return ( - - + {type === 'hidden' ? null : ( {label} @@ -124,15 +125,13 @@ function FormFields(props: FormFieldsProps): JSX.Element { value={value as string} onBlur={() => markAsBlured(i)} /> - - {blured[i] && - nullOrWarning( + {blured[i] && nullOrWarning( value as string, !pristine && error, isURL, name )} - + ); }} diff --git a/client/src/components/formHelpers/form-validators.tsx b/client/src/components/formHelpers/form-validators.tsx index 99b6058c8fda0c..96ddef7e96c26f 100644 --- a/client/src/components/formHelpers/form-validators.tsx +++ b/client/src/components/formHelpers/form-validators.tsx @@ -9,6 +9,14 @@ const fCCRegex = const localhostRegex = /localhost:/; const httpRegex = /http(?!s|([^s]+?localhost))/; +function isPathRoot(urlString: string): boolean { + try { + return new URL(urlString).pathname !== '/'; + } catch { + return false; + } +} + export const editorValidator = (value: string): React.ReactElement | null => editorRegex.test(value) ? validation.editor-url : null; @@ -23,6 +31,9 @@ export const localhostValidator = (value: string): React.ReactElement | null => export const httpValidator = (value: string): React.ReactElement | null => httpRegex.test(value) ? validation.http-url : null; +export const pathValidator = (value: string): React.ReactElement | null => + isPathRoot(value) ? validation.path-url : null; + type Validator = (value: string) => React.ReactElement | null; export function composeValidators(...validators: (Validator | null)[]) { return (value: string): ReturnType | null => diff --git a/client/src/components/formHelpers/form.test.tsx b/client/src/components/formHelpers/form.test.tsx index 6cd7d7ef5b0d10..abed826ca06851 100644 --- a/client/src/components/formHelpers/form.test.tsx +++ b/client/src/components/formHelpers/form.test.tsx @@ -1,9 +1,9 @@ import { render, fireEvent, screen } from '@testing-library/react'; import React from 'react'; -import Form, { FormProps } from './form'; +import { StrictSolutionForm, StrictSolutionFormProps } from './form'; -const defaultTestProps: FormProps = { +const defaultTestProps: StrictSolutionFormProps = { buttonText: 'Submit', formFields: [ { name: 'name', label: 'name Label' }, @@ -21,7 +21,7 @@ const defaultTestProps: FormProps = { }; test('should render', () => { - render(
    ); + render(); const nameInput = screen.getByLabelText(/name Label/); expect(nameInput).not.toBeRequired(); @@ -41,7 +41,7 @@ test('should render with default values', () => { const nameValue = 'John'; render( - { }; const websiteValue = 'http://mysite.com'; - render(); + render(); const websiteInput = screen.getByLabelText(/WebSite label/); fireEvent.change(websiteInput, { target: { value: websiteValue } }); diff --git a/client/src/components/formHelpers/form.tsx b/client/src/components/formHelpers/form.tsx index 4d20f32b8ad3fa..d99a2b14de813c 100644 --- a/client/src/components/formHelpers/form.tsx +++ b/client/src/components/formHelpers/form.tsx @@ -3,6 +3,7 @@ import React, { FormEvent } from 'react'; import { Form } from 'react-final-form'; import normalizeUrl from 'normalize-url'; +import BlockSaveButton from '../helpers/form/block-save-button'; import { localhostValidator, editorValidator, @@ -12,9 +13,6 @@ import { } from './form-validators'; import FormFields, { FormOptions } from './form-fields'; -import { default as BlockSaveButton } from './block-save-button'; -// import { default as BlockSaveWrapper } from './block-save-wrapper'; - type URLValues = { [key: string]: string; }; @@ -71,27 +69,25 @@ function formatUrlValues( return validatedValues; } -export type FormProps = { +export type StrictSolutionFormProps = { buttonText?: string; enableSubmit?: boolean; formFields: { name: string; label: string }[]; - hideButton?: boolean; id: string; initialValues?: Record; options: FormOptions; submit: (values: ValidatedValues, ...args: unknown[]) => void; }; -function DynamicForm({ +export const StrictSolutionForm = ({ id, formFields, initialValues, options, submit, buttonText, - enableSubmit, - hideButton -}: FormProps): JSX.Element { + enableSubmit +}: StrictSolutionFormProps): JSX.Element => { return ( - {!hideButton && ( - - {buttonText ? buttonText : null} - - )} + + {buttonText} + )} ); -} - -DynamicForm.displayName = 'DynamicForm'; - -export default DynamicForm; +}; diff --git a/client/src/components/formHelpers/index.tsx b/client/src/components/formHelpers/index.tsx deleted file mode 100644 index d1f6f04d5e854b..00000000000000 --- a/client/src/components/formHelpers/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { default as Form, ValidatedValues } from './form'; - -export { default as BlockSaveButton } from './block-save-button'; -export { default as BlockSaveWrapper } from './block-save-wrapper'; -export { Form, ValidatedValues }; diff --git a/client/src/components/helpers/__snapshots__/loader.test.tsx.snap b/client/src/components/helpers/__snapshots__/loader.test.tsx.snap index 6dab24a5651529..d754d42ea6762d 100644 --- a/client/src/components/helpers/__snapshots__/loader.test.tsx.snap +++ b/client/src/components/helpers/__snapshots__/loader.test.tsx.snap @@ -14,6 +14,12 @@ exports[` matches the fullScreen render snapshot 1`] = `
    +
    +

    + misc.slow-load-msg +

    `; diff --git a/client/src/components/formHelpers/__snapshots__/block-save-button.test.tsx.snap b/client/src/components/helpers/form/__snapshots__/block-save-button.test.tsx.snap similarity index 100% rename from client/src/components/formHelpers/__snapshots__/block-save-button.test.tsx.snap rename to client/src/components/helpers/form/__snapshots__/block-save-button.test.tsx.snap diff --git a/client/src/components/formHelpers/block-save-button.test.tsx b/client/src/components/helpers/form/block-save-button.test.tsx similarity index 100% rename from client/src/components/formHelpers/block-save-button.test.tsx rename to client/src/components/helpers/form/block-save-button.test.tsx diff --git a/client/src/components/helpers/form/block-save-button.tsx b/client/src/components/helpers/form/block-save-button.tsx index fc26e84fbd8f89..901ff0fcf57427 100644 --- a/client/src/components/helpers/form/block-save-button.tsx +++ b/client/src/components/helpers/form/block-save-button.tsx @@ -4,17 +4,20 @@ import { useTranslation } from 'react-i18next'; function BlockSaveButton({ children, + bgSize, ...restProps }: { children?: React.ReactNode; disabled?: boolean; + bgSize?: string; }): JSX.Element { const { t } = useTranslation(); return ( + +
  • + +
  • +
  • + profile.page-number +
  • +
  • + +
  • +
  • + +
  • + + +
    +
    +`; diff --git a/client/src/components/profile/components/certifications.tsx b/client/src/components/profile/components/certifications.tsx index 0fe7ddef26cfd7..2f92efa040469b 100644 --- a/client/src/components/profile/components/certifications.tsx +++ b/client/src/components/profile/components/certifications.tsx @@ -1,5 +1,4 @@ import { Col, Row } from '@freecodecamp/react-bootstrap'; -import { curry } from 'lodash-es'; import React, { Fragment } from 'react'; import { useTranslation } from 'react-i18next'; import { connect } from 'react-redux'; @@ -40,9 +39,15 @@ interface CertificationProps { username: string; } -function renderCertShow(username: string, cert: CurrentCert): React.ReactNode { - return cert.show ? ( - +interface CertButtonProps { + cert: CurrentCert; + username: string; +} + +function CertButton({ username, cert }: CertButtonProps): JSX.Element { + const { t } = useTranslation(); + return ( + <> - View {cert.title} + {t('buttons.view-cert-title', { + certTitle: t(`certification.title.${cert.certSlug}`) + })} - - ) : null; + + ); } function Certificates({ @@ -67,13 +74,16 @@ function Certificates({ username }: CertificationProps): JSX.Element { const { t } = useTranslation(); - const renderCertShowWithUsername = curry(renderCertShow)(username); return (

    {t('profile.fcc-certs')}


    {hasModernCert && currentCerts ? ( - currentCerts.map(renderCertShowWithUsername) + currentCerts + .filter(({ show }) => show) + .map(cert => ( + + )) ) : (

    {t('profile.no-certs')}

    )} @@ -82,7 +92,16 @@ function Certificates({

    {t('settings.headings.legacy-certs')}


    - {legacyCerts && legacyCerts.map(renderCertShowWithUsername)} + {legacyCerts && + legacyCerts + .filter(({ show }) => show) + .map(cert => ( + + ))}
    ) : null} diff --git a/client/src/components/profile/components/portfolio.css b/client/src/components/profile/components/portfolio.css index 86b3a30871d175..14f2b245488e13 100644 --- a/client/src/components/profile/components/portfolio.css +++ b/client/src/components/profile/components/portfolio.css @@ -1,10 +1,113 @@ -.portfolio-heading.media-heading { - border-bottom: 1px solid var(--quaternary-background); - padding-bottom: 10px; +.portfolio-container { + display: grid; + position: relative; + border: 1px solid var(--secondary-color); + gap: 1rem 1rem; + grid-template-columns: repeat(3, 1fr); + margin-top: 1em; + margin-bottom: 3em; } + .portfolio-screen-shot { - width: 150px; - min-width: 150px; + display: block; + width: 100%; + height: 100%; + object-fit: cover; + grid-column: 1/-1; + grid-row: 1; +} + +.portfolio-container h3 { + grid-column: 1/ -1; + grid-row: 2; + margin-block: 1em; +} + +#link-icon { + margin-inline-start: 1em; +} + +.portfolio-container a { + display: flex; + align-items: center; + justify-content: center; + grid-column: 1/ -1; + grid-row: 4; + font-size: unset; + justify-self: end; + width: 40%; + background-color: var(--primary-color); + color: var(--primary-background); + padding: 0.5rem; + border-radius: 15px; + padding-inline: 4rem; + margin: 1em; + text-decoration: none; + /* prevent line breaks in Chinese/Japanese/Korean */ + word-break: keep-all; +} + +.portfolio-container a::after { + content: ''; + position: absolute; + inset: 0; + width: 100%; + height: 100%; + z-index: 1; +} + +.portfolio-container a:is(:hover, :focus, :focus-visible) { + outline: 2px solid var(--blue-mid); + outline-offset: 2px; +} + +.portfolio-container p { + display: -webkit-box; + -webkit-box-orient: vertical; + overflow: hidden; + grid-column: 1/ -1; + grid-row: 3; +} + +@media (max-width: 994px) { + .portfolio-screen-shot { + max-height: 300px; + } + + .portfolio-container h3 { + margin: 0.5rem; + } + + .portfolio-container p { + margin: 1rem; + } +} + +@media (min-width: 995px) { + .portfolio-container { + grid-template-rows: minmax(75px, 1fr) minmax(125px, 1fr) 75px; + grid-template-columns: 300px 1.2fr; + } + + .portfolio-screen-shot { + grid-column: 1; + grid-row: 1 / -1; + } + + .portfolio-container h3 { + grid-column: 2; + grid-row: 1; + } + + .portfolio-container p { + grid-column: 2; + grid-row: 2; + } + + .portfolio-container a { + grid-column: 2; + grid-row: 3; + } } /* Timeline pagination */ @@ -34,13 +137,13 @@ } .timeline-cert-link { - margin-right: 20px; + margin-inline-end: 20px; } .timeline-cert-link > svg { display: inline-block; height: 25px; width: auto; - margin-left: 10px; + margin-inline-start: 10px; position: absolute; } diff --git a/client/src/components/profile/components/portfolio.tsx b/client/src/components/profile/components/portfolio.tsx index 4e361dcadfa57a..f5edd7ae43a6b8 100644 --- a/client/src/components/profile/components/portfolio.tsx +++ b/client/src/components/profile/components/portfolio.tsx @@ -1,7 +1,7 @@ -import { Media } from '@freecodecamp/react-bootstrap'; import React from 'react'; import { useTranslation } from 'react-i18next'; - +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faArrowUpRightFromSquare } from '@fortawesome/free-solid-svg-icons'; import type { Portfolio as PortfolioData } from '../../../redux/prop-types'; import { FullWidthRow } from '../../helpers'; @@ -20,25 +20,21 @@ function Portfolio({ portfolio = [] }: PortfolioProps): JSX.Element | null {

    {t('profile.portfolio')}

    {portfolio.map(({ title, url, image, description, id }) => ( - - - {image && ( - {t('profile.screen-shot', - )} - - - - - {title} - - -

    {description}

    -
    -
    +
    +

    {title}

    +

    {description}

    + + {t('buttons.view')} + + {title}, {t('aria.opens-new-window')} + + + + + {image && ( + + )} +
    ))}
    diff --git a/client/src/components/profile/components/time-line.test.tsx b/client/src/components/profile/components/time-line.test.tsx index 6256c9e731425b..2fb3e4c866944e 100644 --- a/client/src/components/profile/components/time-line.test.tsx +++ b/client/src/components/profile/components/time-line.test.tsx @@ -4,10 +4,9 @@ import { useStaticQuery } from 'gatsby'; import React from 'react'; import { render, screen } from '../../../../utils/test-utils'; -import { createStore } from '../../../redux/createStore'; +import { createStore } from '../../../redux/create-store'; import TimeLine from './time-line'; -jest.mock('react-ga'); const store = createStore(); beforeEach(() => { @@ -57,7 +56,9 @@ describe('', () => { it('Render button when only solution is present', () => { // @ts-expect-error render(, store); - const showViewButton = screen.getByRole('link', { name: 'buttons.view' }); + const showViewButton = screen.getByRole('link', { + name: 'buttons.view settings.labels.solution-for (aria.opens-new-window)' + }); expect(showViewButton).toHaveAttribute( 'href', 'https://github.com/freeCodeCamp/freeCodeCamp' @@ -84,7 +85,9 @@ describe('', () => { // @ts-expect-error render(, store); - const viewButtons = screen.getAllByRole('button', { name: 'buttons.view' }); + const viewButtons = screen.getAllByRole('button', { + name: 'buttons.view settings.labels.solution-for' + }); viewButtons.forEach(button => { expect(button).toBeInTheDocument(); }); diff --git a/client/src/components/profile/components/time-line.tsx b/client/src/components/profile/components/time-line.tsx index 3efef9267ccaa7..38f65146227d93 100644 --- a/client/src/components/profile/components/time-line.tsx +++ b/client/src/components/profile/components/time-line.tsx @@ -1,6 +1,6 @@ import { Button, Modal, Table } from '@freecodecamp/react-bootstrap'; import Loadable from '@loadable/component'; -import { useStaticQuery, graphql } from 'gatsby'; +import { graphql, useStaticQuery } from 'gatsby'; import { reverse, sortBy } from 'lodash-es'; import React, { useMemo, useState } from 'react'; import { TFunction, withTranslation } from 'react-i18next'; @@ -14,16 +14,14 @@ import { getTitleFromId } from '../../../../../utils'; import { regeneratePathAndHistory } from '../../../../../utils/polyvinyl'; -import CertificationIcon from '../../../assets/icons/certification-icon'; +import CertificationIcon from '../../../assets/icons/certification'; import { CompletedChallenge } from '../../../redux/prop-types'; import ProjectPreviewModal from '../../../templates/Challenges/components/project-preview-modal'; import { openModal } from '../../../templates/Challenges/redux/actions'; -import { FullWidthRow, Link } from '../../helpers'; +import { Link, FullWidthRow } from '../../helpers'; import { SolutionDisplayWidget } from '../../solution-display-widget'; import TimelinePagination from './timeline-pagination'; -import './timeline.css'; - const SolutionViewer = Loadable( () => import('../../SolutionViewer/SolutionViewer') ); @@ -105,12 +103,15 @@ function TimelineInner({ function renderViewButton( completedChallenge: CompletedChallenge ): React.ReactNode { + const { id } = completedChallenge; + const projectTitle = idToNameMap.get(id)?.challengeTitle || ''; return ( viewSolution(completedChallenge)} showProjectPreview={() => viewProject(completedChallenge)} - displayContext={'timeline'} + displayContext='timeline' > ); } @@ -164,75 +165,73 @@ function TimelineInner({ const endIndex = pageNo * ITEMS_PER_PAGE; return ( - <> - -

    {t('profile.timeline')}

    - {completedMap.length === 0 ? ( -

    - {t('profile.none-completed')}  - {t('profile.get-started')} -

    - ) : ( - - - - - - - - - - {sortedTimeline.slice(startIndex, endIndex).map(renderCompletion)} - -
    {t('profile.challenge')}{t('settings.labels.solution')}{t('profile.completed')}
    - )} - {id && ( - - - - {`${username}'s Solution to ${ - idToNameMap.get(id)?.challengeTitle ?? '' - }`} - - - - - - - - - - )} - {totalPages > 1 && ( - - )} -
    + +

    {t('profile.timeline')}

    + {completedMap.length === 0 ? ( +

    + {t('profile.none-completed')}  + {t('profile.get-started')} +

    + ) : ( + + + + + + + + + + {sortedTimeline.slice(startIndex, endIndex).map(renderCompletion)} + +
    {t('profile.challenge')}{t('settings.labels.solution')}{t('profile.completed')}
    + )} + {id && ( + + + + {`${username}'s Solution to ${ + idToNameMap.get(id)?.challengeTitle ?? '' + }`} + + + + + + + + + + )} + {totalPages > 1 && ( + + )} - +
    ); } /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call*/ -function useIdToNameMap(): Map { +function useIdToNameMap(t: TFunction): Map { const { allChallengeNode: { edges } } = useStaticQuery(graphql` @@ -255,8 +254,12 @@ function useIdToNameMap(): Map { `); const idToNameMap = new Map(); for (const id of getCertIds()) { + const challengeTitle = getTitleFromId(id); idToNameMap.set(id, { - challengeTitle: `${getTitleFromId(id)} Certification`, + challengeTitle: `${t( + `certification.title.${challengeTitle}`, + challengeTitle + )} Certification`, certPath: getPathFromID(id) }); } @@ -286,8 +289,8 @@ function useIdToNameMap(): Map { } const Timeline = (props: TimelineProps): JSX.Element => { - const idToNameMap = useIdToNameMap(); - const { completedMap } = props; + const { completedMap, t } = props; + const idToNameMap = useIdToNameMap(t); // Get the sorted timeline along with total page count. const { sortedTimeline, totalPages } = useMemo(() => { const sortedTimeline = reverse( diff --git a/client/src/components/profile/components/timeline-buttons.test.js b/client/src/components/profile/components/timeline-buttons.test.js new file mode 100644 index 00000000000000..6a4b619bb1b458 --- /dev/null +++ b/client/src/components/profile/components/timeline-buttons.test.js @@ -0,0 +1,64 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { Provider } from 'react-redux'; + +import { createStore } from '../../../redux/create-store'; +import completedChallenges from '../../../__mocks__/completed-challenges.json'; +import Timeline from './time-line'; + +Date.prototype.toLocaleString = jest.fn(() => 'Dec 29, 2022'); +Date.prototype.toISOString = jest.fn(() => '2016-09-28T20:31:56.730Z'); + +jest.mock('../../../analytics'); + +jest.mock('gatsby', () => { + const edges = require('../../../__mocks__/edges.json'); + const React = require('react'); + const gatsby = jest.requireActual('gatsby'); + return { + ...gatsby, + useStaticQuery: jest.fn().mockReturnValue({ + allChallengeNode: { + edges: edges + } + }), + graphql: jest.fn(), + Link: jest + .fn() + .mockImplementation( + ({ + activeClassName, + activeStyle, + getProps, + innerRef, + partiallyActive, + ref, + replace, + to, + ...rest + }) => + React.createElement('a', { + ...rest, + href: to, + gatsby: 'true' + }) + ) + }; +}); + +it('should check certification page consistency', () => { + const tree = renderer + .create( + + {}} + /> + + ) + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); diff --git a/client/src/components/profile/components/timeline.css b/client/src/components/profile/components/timeline.css deleted file mode 100644 index 475089a5d1c2b9..00000000000000 --- a/client/src/components/profile/components/timeline.css +++ /dev/null @@ -1,3 +0,0 @@ -.timeline-row .solutions-dropdown .dropdown { - width: 100%; -} diff --git a/client/src/components/search/searchBar/search-bar-optimized.tsx b/client/src/components/search/searchBar/search-bar-optimized.tsx index cea824cfec0b98..68be861c9408ca 100644 --- a/client/src/components/search/searchBar/search-bar-optimized.tsx +++ b/client/src/components/search/searchBar/search-bar-optimized.tsx @@ -1,6 +1,7 @@ -import React, { useState } from 'react'; +import React, { useState, useRef } from 'react'; import { useTranslation } from 'react-i18next'; -import Magnifier from '../../../assets/icons/Magnifier'; +import Magnifier from '../../../assets/icons/magnifier'; +import InputReset from '../../../assets/icons/input-reset'; import { searchPageUrl } from '../../../utils/algolia-locale-setup'; type Props = { @@ -12,6 +13,7 @@ const SearchBarOptimized = ({ innerRef }: Props): JSX.Element => { const placeholder = t('search.placeholder'); const searchUrl = searchPageUrl; const [value, setValue] = useState(''); + const inputElementRef = useRef(null); const onChange = (event: React.ChangeEvent) => setValue(event.target.value); const onSubmit = (event: React.FormEvent) => { @@ -20,6 +22,10 @@ const SearchBarOptimized = ({ innerRef }: Props): JSX.Element => { window.open(`${searchUrl}?query=${encodeURIComponent(value)}`, '_blank'); } }; + const onClick = () => { + setValue(''); + inputElementRef.current?.focus(); + }; return (
    @@ -32,11 +38,14 @@ const SearchBarOptimized = ({ innerRef }: Props): JSX.Element => { onSubmit={onSubmit} role='search' > + { spellCheck='false' type='search' value={value} + ref={inputElementRef} /> - + {value && ( + + )}
    diff --git a/client/src/components/search/searchBar/search-bar.tsx b/client/src/components/search/searchBar/search-bar.tsx index bb614287e74b25..f244b99d8dbe11 100644 --- a/client/src/components/search/searchBar/search-bar.tsx +++ b/client/src/components/search/searchBar/search-bar.tsx @@ -187,6 +187,8 @@ export class SearchBar extends Component { render(): JSX.Element { const { isDropdownEnabled, isSearchFocused, innerRef, t } = this.props; const { index } = this.state; + const submitTitle = t ? t('icons.magnifier') : ''; + const resetTitle = t ? t('icons.input-reset') : ''; const placeholder = t ? t('search.placeholder') : ''; return ( @@ -210,7 +212,11 @@ export class SearchBar extends Component { this.handleSearch(e); }} showLoadingIndicator={false} - translations={{ placeholder }} + translations={{ + submitTitle: submitTitle, + resetTitle: resetTitle, + placeholder: placeholder + }} /> diff --git a/client/src/components/search/searchBar/searchbar-base.css b/client/src/components/search/searchBar/searchbar-base.css index d72a6c1076b6e0..cda535b090ca93 100644 --- a/client/src/components/search/searchBar/searchbar-base.css +++ b/client/src/components/search/searchBar/searchbar-base.css @@ -80,7 +80,7 @@ align-items: center; } .ais-HierarchicalMenu-list .ais-HierarchicalMenu-list { - margin-left: 1em; + margin-inline-start: 1em; } .ais-PoweredBy-logo { display: block; @@ -115,7 +115,7 @@ width: 100%; } .ais-RangeSlider .rheostat-handle { - margin-left: -12px; + margin-inline-start: -12px; top: -7px; } .ais-RangeSlider .rheostat-background { @@ -141,7 +141,7 @@ cursor: grab; } .rheostat-marker { - margin-left: -1px; + margin-inline-start: -1px; position: absolute; width: 1px; height: 5px; @@ -151,7 +151,7 @@ height: 9px; } .rheostat-value { - margin-left: 50%; + margin-inline-start: 50%; padding-top: 15px; position: absolute; text-align: center; @@ -159,7 +159,7 @@ transform: translateX(-50%); } .rheostat-tooltip { - margin-left: 50%; + margin-inline-start: 50%; position: absolute; top: -22px; text-align: center; @@ -302,7 +302,7 @@ a[class^='ais-'] { flex-wrap: wrap; } .ais-CurrentRefinements-item { - margin-right: 0.3rem; + margin-inline-end: 0.3rem; margin-top: 0.3rem; padding: 0.3rem 0.5rem; display: -webkit-box; @@ -312,13 +312,13 @@ a[class^='ais-'] { border-radius: 0px; } .ais-CurrentRefinements-category { - margin-left: 0.3em; + margin-inline-start: 0.3em; display: -webkit-box; display: -ms-flexbox; display: flex; } .ais-CurrentRefinements-delete { - margin-left: 0.3rem; + margin-inline-start: 0.3rem; } .ais-CurrentRefinements-label, .ais-CurrentRefinements-categoryLabel, @@ -332,7 +332,7 @@ a[class^='ais-'] { white-space: nowrap; } .ais-CurrentRefinements-reset + .ais-CurrentRefinements-list { - margin-left: 0.3rem; + margin-inline-start: 0.3rem; } .ais-HierarchicalMenu-link, .ais-Menu-link { @@ -348,7 +348,7 @@ a[class^='ais-'] { line-height: 1.5; } .ais-HierarchicalMenu-link:after { - margin-left: 0.3em; + margin-inline-start: 0.3em; content: ''; width: 10px; height: 10px; @@ -399,7 +399,7 @@ a[class^='ais-'] { .ais-Hits-list, .ais-Results-list { margin-top: -1rem; - margin-left: -1rem; + margin-inline-start: -1rem; display: -webkit-box; display: -ms-flexbox; display: flex; @@ -417,7 +417,7 @@ a[class^='ais-'] { .ais-Hits-item, .ais-Results-item { margin-top: 1rem; - margin-left: 1rem; + margin-inline-start: 1rem; padding: 1rem; width: calc(25% - 1rem); } @@ -439,7 +439,8 @@ a[class^='ais-'] { -webkit-appearance: none; -moz-appearance: none; appearance: none; - padding: 0.3rem 2rem 0.3rem 0.3rem; + padding-block: 0.3rem; + padding-inline: 0.3rem 2rem; background-color: #fff; background-image: url('data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M0 7.33l2.829-2.83 9.175 9.339 9.167-9.339 2.829 2.83-11.996 12.17z%27 fill%3D%22%233A4570%22 /%3E%3C/svg%3E'); background-repeat: no-repeat; @@ -470,7 +471,7 @@ a[class^='ais-'] { margin: 0 0.3rem; } .ais-RangeInput-submit { - margin-left: 0.3rem; + margin-inline-start: 0.3rem; -webkit-appearance: none; -moz-appearance: none; appearance: none; @@ -499,7 +500,7 @@ a[class^='ais-'] { justify-content: center; } .ais-Pagination-item + .ais-Pagination-item { - margin-left: 0.3rem; + margin-inline-start: 0.3rem; } .ais-Pagination-link { padding: 0.3rem 0.6rem; @@ -539,7 +540,7 @@ a[class^='ais-'] { font-size: 0.8rem; } .ais-PoweredBy-logo { - margin-left: 0.3rem; + margin-inline-start: 0.3rem; } .ais-RangeSlider .rheostat-progress { background-color: #495588; @@ -569,7 +570,7 @@ a[class^='ais-'] { line-height: 1.5; } .ais-RatingMenu-link > * + * { - margin-left: 0.3rem; + margin-inline-start: 0.3rem; } .ais-RatingMenu-starIcon { position: relative; @@ -612,35 +613,19 @@ a[class^='ais-'] { color: var(--gray-15); } .ais-SearchBox-submit, -.ais-SearchBox-reset, -.ais-SearchBox-loadingIndicator { +.ais-SearchBox-reset { -webkit-appearance: none; -moz-appearance: none; appearance: none; - position: absolute; z-index: 100; width: 20px; height: 20px; - top: 50%; - right: 0.3rem; - -webkit-transform: translateY(-50%); - transform: translateY(-50%); } .ais-SearchBox-reset { - right: 0.3rem; -} -.ais-SearchBox-submitIcon, -.ais-SearchBox-resetIcon, -.ais-SearchBox-loadingIcon { - position: absolute; - top: 50%; - left: 50%; - -webkit-transform: translateX(-50%) translateY(-50%); - transform: translateX(-50%) translateY(-50%); + margin-inline-start: 10px; } .ais-SearchBox-submitIcon path, -.ais-SearchBox-resetIcon path, -.ais-SearchBox-loadingIndicator { +.ais-SearchBox-resetIcon path { fill: var(--gray-15); } .ais-SearchBox-submitIcon { diff --git a/client/src/components/search/searchBar/searchbar.css b/client/src/components/search/searchBar/searchbar.css index 24dd7653adea98..f4ac394d740316 100644 --- a/client/src/components/search/searchBar/searchbar.css +++ b/client/src/components/search/searchBar/searchbar.css @@ -1,6 +1,5 @@ .fcc_searchBar { flex-grow: 1; - padding: 0 10px; max-height: 33px; font-family: 'Lato', sans-serif; } @@ -10,21 +9,31 @@ color: var(--gray-00); } -.ais-SearchBox-reset { +.ais-SearchBox-loadingIndicator { display: none; } .ais-SearchBox-input { - padding: 0 10px 0 30px; + padding-block: 0; + padding-inline-start: 5px; font-size: 18px; display: inline-block; - margin-top: 6px; height: 26px; } +.ais-SearchBox-submit, +.ais-SearchBox-reset { + height: 26px; + width: 26px; + background-color: var(--gray-75); +} + .ais-SearchBox-submit { - left: 0.3rem; - top: 59.5%; + padding-inline: 3px; +} + +.ais-SearchBox-reset { + padding-block: 0 2px; } .fcc_searchBar .ais-SearchBox-input, @@ -35,19 +44,9 @@ } .fcc_searchBar .ais-Hits { - top: 70px; - width: calc(100vw - 350px); left: 15px; } -.fcc_searchBar .ais-SearchBox-form { - margin-bottom: 0; - display: flex; - position: absolute; - top: var(--header-height); - right: 5px; -} - /* hits */ .fcc_searchBar .ais-Highlight-highlighted { background-color: transparent; @@ -125,39 +124,44 @@ and arrow keys */ font-weight: 300; } +.fcc_searchBar .ais-SearchBox-form { + display: grid; + grid-template-columns: 26px auto 36px; + grid-template-areas: 'submit input reset'; + margin-bottom: 0; + gap: 0.25em; + margin-top: 6px; + background-color: var(--gray-75); +} + .ais-SearchBox-input { - width: calc(100vw - 350px); + grid-area: input; } -.fcc_searchBar .ais-SearchBox-form { - display: flex; - position: absolute; - top: var(--header-height); - right: 15px; +.ais-SearchBox-submit { + grid-area: submit; } -@media (min-width: 980px) { +.ais-SearchBox-reset { + grid-area: reset; +} + +@media (min-width: 981px) { .ais-SearchBox-input { width: 100%; - max-width: 500px; + max-width: 100%; } .fcc_searchBar { position: relative; - max-width: 520px; + max-width: 500px; } .fcc_searchBar .ais-Hits { top: auto; - width: calc(100% - 20px); - max-width: 500px; - left: 10px; + width: 100%; + max-width: 100%; + left: 0px; } .fcc_searchBar .ais-SearchBox-form { - display: flex; - position: static; top: auto; - right: 15px; - } - .ais-SearchBox-submit { - left: 0.85rem; } } diff --git a/client/src/components/search/searchPage/search-page-hits.css b/client/src/components/search/searchPage/search-page-hits.css index 49203b77478db6..8524f416705253 100644 --- a/client/src/components/search/searchPage/search-page-hits.css +++ b/client/src/components/search/searchPage/search-page-hits.css @@ -8,7 +8,7 @@ display: flex; flex-direction: column; align-items: center; - margin-left: 0; + margin-inline-start: 0; border: 1px solid #efefef; } diff --git a/client/src/components/seo/index.tsx b/client/src/components/seo/index.tsx index 9abb02284cfff8..25b40ca884ad4b 100644 --- a/client/src/components/seo/index.tsx +++ b/client/src/components/seo/index.tsx @@ -17,10 +17,23 @@ interface SiteData { }; } +interface Item { + '@type': 'Course'; + url: string; + name: string; + description?: string; + provider: { + '@type': 'Organization'; + name: string; + sameAs: string; + nonprofitStatus: string; + }; +} + interface ListItem { '@type': 'ListItem'; position: number; - item: object; + item: Item; } interface StructuredData { diff --git a/client/src/components/settings/__snapshots__/Honesty.test.tsx.snap b/client/src/components/settings/__snapshots__/Honesty.test.tsx.snap index 9e6d5accbde998..86dcb3e0089989 100644 --- a/client/src/components/settings/__snapshots__/Honesty.test.tsx.snap +++ b/client/src/components/settings/__snapshots__/Honesty.test.tsx.snap @@ -2,7 +2,6 @@ exports[` snapshot when isHonest is false: Honesty 1`] = `
    @@ -14,16 +13,16 @@ exports[` snapshot when isHonest is false: Honesty 1`] = > -
    @@ -31,7 +30,6 @@ exports[` snapshot when isHonest is false: Honesty 1`] = exports[` snapshot when isHonest is true: HonestyAccepted 1`] = `
    @@ -43,18 +41,16 @@ exports[` snapshot when isHonest is true: HonestyAccepted > -
    diff --git a/client/src/components/settings/__snapshots__/settings-button.test.js.snap b/client/src/components/settings/__snapshots__/settings-button.test.js.snap new file mode 100644 index 00000000000000..078295f084bc52 --- /dev/null +++ b/client/src/components/settings/__snapshots__/settings-button.test.js.snap @@ -0,0 +1,2336 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should check certification button consistency 1`] = ` +Array [ +
    + , +
    + , +
    + , +
    + , +
    + , +
    + , +
    + , +
    + , +
    + , +
    + , +
    + , +] +`; + +exports[`should check legacy certification button consistency 1`] = ` +Array [ +
    +
    +
    +

    + certification.title.Legacy Front End +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + settings.labels.project-name + + settings.labels.solution +
    + + certification.project.title.Build a Personal Portfolio Webpage + + +
    + + certification.project.title.Build a Random Quote Machine + + +
    + + certification.project.title.Build a 25 + 5 Clock + + +
    + + certification.project.title.Build a JavaScript Calculator + + +
    + + certification.project.title.Show the Local Weather + + +
    + + certification.project.title.Use the TwitchTV JSON API + + +
    + + certification.project.title.Build a Tribute Page + + +
    + + certification.project.title.Build a Wikipedia Viewer + + +
    + + certification.project.title.Build a Tic Tac Toe Game + + +
    + + certification.project.title.Build a Simon Game + + +
    + + buttons.claim-cert + + + Legacy Front End + + +
    +
    +
    , +
    +
    +
    +

    + certification.title.Legacy Back End +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + settings.labels.project-name + + settings.labels.solution +
    + + certification.project.title.Timestamp Microservice + + +
    + + certification.project.title.Request Header Parser Microservice + + +
    + + certification.project.title.URL Shortener Microservice + + +
    + + certification.project.title.Image Search Abstraction Layer + + +
    + + certification.project.title.File Metadata Microservice + + +
    + + certification.project.title.Build a Voting App + + +
    + + certification.project.title.Build a Nightlife Coordination App + + +
    + + certification.project.title.Chart the Stock Market + + +
    + + certification.project.title.Manage a Book Trading Club + + +
    + + certification.project.title.Build a Pinterest Clone + + +
    + + buttons.claim-cert + + + Legacy Back End + + +
    +
    +
    , +
    +
    +
    +

    + certification.title.Legacy Data Visualization +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + settings.labels.project-name + + settings.labels.solution +
    + + certification.project.title.Build a Markdown Previewer + + +
    + + certification.project.title.Build a freeCodeCamp Forum Homepage + + +
    + + certification.project.title.Build a Recipe Box + + +
    + + certification.project.title.Build the Game of Life + + +
    + + certification.project.title.Build a Roguelike Dungeon Crawler Game + + +
    + + certification.project.title.Visualize Data with a Bar Chart + + +
    + + certification.project.title.Visualize Data with a Scatterplot Graph + + +
    + + certification.project.title.Visualize Data with a Heat Map + + +
    + + certification.project.title.Show National Contiguity with a Force Directed Graph + + +
    + + certification.project.title.Map Data Across the Globe + + +
    + + buttons.claim-cert + + + Legacy Data Visualization + + +
    +
    +
    , +
    + , +] +`; diff --git a/client/src/components/settings/about.tsx b/client/src/components/settings/about.tsx index 61f5ff7d96cc7f..6653fcbb57c20d 100644 --- a/client/src/components/settings/about.tsx +++ b/client/src/components/settings/about.tsx @@ -15,6 +15,7 @@ import SoundSettings from './sound'; import ThemeSettings, { Themes } from './theme'; import UsernameSettings from './username'; import KeyboardShortcutsSettings from './keyboard-shortcuts'; +import SectionHeader from './section-header'; type FormValues = { name: string; @@ -47,6 +48,18 @@ type AboutState = { isPictureUrlValid: boolean; }; +const ShowImageValidationWarning = ({ + alertContent +}: { + alertContent: string; +}) => { + return ( + + {alertContent} + + ); +}; + class AboutSettings extends Component { validationImage: HTMLImageElement; static displayName: string; @@ -78,7 +91,6 @@ class AboutSettings extends Component { picture === formValues.picture && about === formValues.about ) { - // eslint-disable-next-line react/no-did-update-set-state return this.setState({ originalValues: { name, @@ -106,7 +118,7 @@ class AboutSettings extends Component { e.preventDefault(); const { formValues } = this.state; const { submitNewAbout } = this.props; - if (this.state.isPictureUrlValid === true) { + if (this.state.isPictureUrlValid === true && !this.isFormPristine()) { return this.setState({ formClicked: true }, () => submitNewAbout(formValues) ); @@ -169,21 +181,6 @@ class AboutSettings extends Component { })); }; - showImageValidationWarning = () => { - const { t } = this.props; - if (this.state.isPictureUrlValid === false) { - return ( - - - {t('validation.url-not-image')} - - - ); - } else { - return true; - } - }; - handleAboutChange = (e: React.FormEvent) => { const value = (e.target as HTMLInputElement).value.slice(0); return this.setState(state => ({ @@ -209,53 +206,69 @@ class AboutSettings extends Component { toggleKeyboardShortcuts } = this.props; return ( -
    + <> -
    + + {t('settings.headings.personal-info')}
    - - - {t('settings.labels.name')} - - - - - - {t('settings.labels.location')} - - - - - - {t('settings.labels.picture')} - - - {this.showImageValidationWarning()} - - - - {t('settings.labels.about')} - - - - +
    + + + {t('settings.labels.name')} + + + + + + {t('settings.labels.location')} + + + + + + {t('settings.labels.picture')} + + + {!this.state.isPictureUrlValid && ( + + )} + + + + {t('settings.labels.about')} + + + +
    + + {t('buttons.save')}{' '} + + {t('settings.headings.personal-info')} + +
    @@ -270,7 +283,7 @@ class AboutSettings extends Component { toggleKeyboardShortcuts={toggleKeyboardShortcuts} /> -
    + ); } } diff --git a/client/src/components/settings/certification.css b/client/src/components/settings/certification.css index 421d2fc376a270..428cfc95f03756 100644 --- a/client/src/components/settings/certification.css +++ b/client/src/components/settings/certification.css @@ -1,9 +1,3 @@ -.certification-settings .solutions-dropdown, -.certification-settings .solutions-dropdown .dropdown-menu, -.certification-settings .solutions-dropdown .dropdown { - width: 100%; -} - .certification-settings tr { height: 57px; } diff --git a/client/src/components/settings/certification.js b/client/src/components/settings/certification.js index 4d970cc195ae36..7a59a882df3b26 100644 --- a/client/src/components/settings/certification.js +++ b/client/src/components/settings/certification.js @@ -213,9 +213,10 @@ export class CertificationSettings extends Component { ); }; @@ -227,7 +228,7 @@ export class CertificationSettings extends Component {

    - {certName} + {t(`certification.title.${certName}`, certName)}

    @@ -265,7 +266,9 @@ export class CertificationSettings extends Component { .map(({ link, title, id }) => ( @@ -337,20 +341,30 @@ export class CertificationSettings extends Component { return ( -

    Legacy Full Stack Certification

    +

    + {t('certification.title.Legacy Full Stack Certification')} +

    {t('settings.claim-legacy', { - cert: 'Legacy Full Stack Certification' + cert: t('certification.title.Legacy Full Stack Certification') })}

      -
    • Responsive Web Design
    • -
    • JavaScript Algorithms and Data Structures
    • -
    • Front End Development Libraries
    • -
    • Data Visualization
    • -
    • Back End Development and APIs
    • -
    • Legacy Information Security and Quality Assurance
    • +
    • {t('certification.title.Responsive Web Design')}
    • +
    • + {t( + 'certification.title.JavaScript Algorithms and Data Structures' + )} +
    • +
    • {t('certification.title.Front End Development Libraries')}
    • +
    • {t('certification.title.Data Visualization')}
    • +
    • {t('certification.title.Back End Development and APIs')}
    • +
    • + {t( + 'certification.title.Legacy Information Security and Quality Assurance' + )} +
    diff --git a/client/src/components/settings/certification.test.tsx b/client/src/components/settings/certification.test.tsx index de7969d34a6e81..2c6e033ace133d 100644 --- a/client/src/components/settings/certification.test.tsx +++ b/client/src/components/settings/certification.test.tsx @@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; import { Provider } from 'react-redux'; -import { createStore } from '../../redux/createStore'; +import { createStore } from '../../redux/create-store'; import { CertificationSettings } from './certification'; @@ -20,7 +20,7 @@ describe('', () => { expect( screen.getByRole('link', { - name: 'buttons.show-cert' + name: /^buttons.show-cert\s+\S+/ }) ).toHaveAttribute( 'href', @@ -33,7 +33,7 @@ describe('', () => { renderWithRedux(); const allClaimedCerts = screen.getAllByRole('link', { - name: 'buttons.show-cert' + name: /^buttons.show-cert\s+\S+/ }); allClaimedCerts.forEach(cert => { @@ -49,7 +49,7 @@ describe('', () => { renderWithRedux(); const allClaimedCerts = screen.getAllByRole('link', { - name: 'buttons.show-cert' + name: /^buttons.show-cert\s+\S+/ }); allClaimedCerts.forEach(cert => { @@ -65,7 +65,7 @@ describe('', () => { expect( screen.getByRole('link', { - name: 'buttons.view' + name: 'buttons.view settings.labels.solution-for (aria.opens-new-window)' }) ).toHaveAttribute('href', 'https://github.com/freeCodeCamp/freeCodeCamp'); }); diff --git a/client/src/components/settings/danger-zone.tsx b/client/src/components/settings/danger-zone.tsx index 3ca233acb02690..c795c269e9c272 100644 --- a/client/src/components/settings/danger-zone.tsx +++ b/client/src/components/settings/danger-zone.tsx @@ -12,11 +12,11 @@ import ResetModal from './reset-modal'; import './danger-zone.css'; -type DangerZoneProps = { +interface DangerZoneProps { deleteAccount: () => void; resetProgress: () => void; t: TFunction; -}; +} const mapStateToProps = () => ({}); const mapDispatchToProps = (dispatch: Dispatch) => @@ -42,50 +42,48 @@ function DangerZone({ deleteAccount, resetProgress, t }: DangerZoneProps) { } return ( -
    - - - {t('settings.danger.heading')} + + + {t('settings.danger.heading')} + +

    {t('settings.danger.be-careful')}

    + + + + -

    {t('settings.danger.be-careful')}

    - - - - - - -
    +
    +
    - - -
    -
    + + +
    ); } diff --git a/client/src/components/settings/delete-modal.tsx b/client/src/components/settings/delete-modal.tsx index 06899ff6cebfd6..74a6a8b4229ac8 100644 --- a/client/src/components/settings/delete-modal.tsx +++ b/client/src/components/settings/delete-modal.tsx @@ -14,7 +14,7 @@ type DeleteModalProps = { function DeleteModal(props: DeleteModalProps): JSX.Element { const { show, onHide } = props; - const email = 'team@freecodecamp.org'; + const email = 'support@freecodecamp.org'; const { t } = useTranslation(); return ( @@ -170,43 +173,54 @@ function EmailSettings({ )} -
    + e.preventDefault() })} + > {t('settings.email.current')} {currentEmail} - - {t('settings.email.new')} - - {newEmailValidationMessage ? ( - {newEmailValidationMessage} - ) : null} - - - {t('settings.email.confirm')} - - {confirmEmailValidationMessage ? ( - {confirmEmailValidationMessage} - ) : null} - +
    + + {t('settings.email.new')} + + {newEmailValidationMessage ? ( + {newEmailValidationMessage} + ) : null} + + + {t('settings.email.confirm')} + + {confirmEmailValidationMessage ? ( + {confirmEmailValidationMessage} + ) : null} + +
    + aria-disabled={isDisabled} + bgSize='lg' + {...(isDisabled && { tabIndex: -1 })} + > + {t('buttons.save')}{' '} + {t('settings.email.heading')} +
    diff --git a/client/src/components/settings/honesty.css b/client/src/components/settings/honesty.css index 0e2c7b36d4e166..dd0d550b49fcf9 100644 --- a/client/src/components/settings/honesty.css +++ b/client/src/components/settings/honesty.css @@ -1,6 +1,5 @@ .honesty-panel p { - margin-left: 10px; - margin-right: 10px; + margin-inline: 10px; font-family: 'Lato', sans-serif; } @@ -8,11 +7,6 @@ padding-top: 15px; } -.honesty-policy .disabled-agreed p { - margin-top: 0; - margin-bottom: 0; -} - .honesty-panel .btn-invert { color: var(--primary-background); } diff --git a/client/src/components/settings/honesty.tsx b/client/src/components/settings/honesty.tsx index c8db8c62c9dac4..b8c54e31d969f5 100644 --- a/client/src/components/settings/honesty.tsx +++ b/client/src/components/settings/honesty.tsx @@ -15,33 +15,25 @@ type HonestyProps = { const Honesty = ({ isHonest, updateIsHonest }: HonestyProps): JSX.Element => { const { t } = useTranslation(); - const button = isHonest ? ( - - ) : ( - - ); + const buttonText = isHonest + ? t('buttons.accepted-honesty') + : t('buttons.agree-honesty'); + return ( -
    +
    {t('settings.headings.honesty')} -
    - {button} +
    ); diff --git a/client/src/components/settings/internet.tsx b/client/src/components/settings/internet.tsx index 06d9c52fc9fcca..9b12a90c8e21a6 100644 --- a/client/src/components/settings/internet.tsx +++ b/client/src/components/settings/internet.tsx @@ -66,7 +66,6 @@ class InternetSettings extends Component { twitter !== originalValues.twitter || website !== originalValues.website ) { - // eslint-disable-next-line react/no-did-update-set-state return this.setState({ originalValues: { githubProfile, linkedin, twitter, website } }); @@ -179,71 +178,78 @@ class InternetSettings extends Component { const { state: websiteValidation, message: websiteValidationMessage } = this.getValidationStateFor(website); - + const isDisabled = this.isFormPristine() || !this.isFormValid(); return ( <> {t('settings.headings.internet')}
    - - GitHub - - {this.renderCheck(githubProfile, githubProfileValidation)} - {this.renderHelpBlock(githubProfileValidationMessage)} - - - LinkedIn - - {this.renderCheck(linkedin, linkedinValidation)} - {this.renderHelpBlock(linkedinValidationMessage)} - - - Twitter - - {this.renderCheck(twitter, twitterValidation)} - {this.renderHelpBlock(twitterValidationMessage)} - - - {t('settings.labels.personal')} - - {this.renderCheck(website, websiteValidation)} - {this.renderHelpBlock(websiteValidationMessage)} - +
    + + GitHub + + {this.renderCheck(githubProfile, githubProfileValidation)} + {this.renderHelpBlock(githubProfileValidationMessage)} + + + LinkedIn + + {this.renderCheck(linkedin, linkedinValidation)} + {this.renderHelpBlock(linkedinValidationMessage)} + + + Twitter + + {this.renderCheck(twitter, twitterValidation)} + {this.renderHelpBlock(twitterValidationMessage)} + + + {t('settings.labels.personal')} + + {this.renderCheck(website, websiteValidation)} + {this.renderHelpBlock(websiteValidationMessage)} + +
    + aria-disabled={isDisabled} + bgSize='lg' + {...(isDisabled && { tabIndex: -1 })} + > + {t('buttons.save')}{' '} + {t('settings.headings.internet')} +
    diff --git a/client/src/components/settings/portfolio.tsx b/client/src/components/settings/portfolio.tsx index 370277f1975526..f339c0237fc62a 100644 --- a/client/src/components/settings/portfolio.tsx +++ b/client/src/components/settings/portfolio.tsx @@ -84,11 +84,6 @@ class PortfolioSettings extends Component { }); }; - handleSubmit = (e: React.FormEvent, id: string) => { - e.preventDefault(); - this.updateItem(id); - }; - updateItem = (id: string) => { const { portfolio, unsavedItemId } = this.state; if (unsavedItemId === id) { @@ -218,101 +213,107 @@ class PortfolioSettings extends Component { ); const { state: descriptionState, message: descriptionMessage } = this.getDescriptionValidation(description); + + const isDisabled = + pristine || + !title || + !isURL(url, { + protocols: ['http', 'https'], + /* eslint-disable camelcase, @typescript-eslint/naming-convention */ + require_tld: true, + require_protocol: true + /* eslint-enable camelcase, @typescript-eslint/naming-convention */ + }); + + const handleSubmit = (e: React.FormEvent, id: string) => { + e.preventDefault(); + if (isDisabled) return null; + return this.updateItem(id); + }; + return ( -
    - -
    this.handleSubmit(e, id)}> - - {t('settings.labels.title')} - - {titleMessage ? {titleMessage} : null} - - - {t('settings.labels.url')} - - {urlMessage ? {urlMessage} : null} - - - {t('settings.labels.image')} - - {imageMessage ? {imageMessage} : null} - - - {t('settings.labels.description')} - - {descriptionMessage ? ( - {descriptionMessage} - ) : null} - - - {t('buttons.save-portfolio')} - - - - - {index + 1 !== arr.length && ( - <> - -
    - - - )} -
    -
    + +
    handleSubmit(e, id)} id='portfolio-items'> + + {t('settings.labels.title')} + + {titleMessage ? {titleMessage} : null} + + + {t('settings.labels.url')} + + {urlMessage ? {urlMessage} : null} + + + {t('settings.labels.image')} + + {imageMessage ? {imageMessage} : null} + + + {t('settings.labels.description')} + + {descriptionMessage ? ( + {descriptionMessage} + ) : null} + + + {t('buttons.save-portfolio')} + + + + + {index + 1 !== arr.length && ( + <> + +
    + + + )} +
    ); }; diff --git a/client/src/components/settings/privacy.tsx b/client/src/components/settings/privacy.tsx index 2bc13252fda99e..ccb6ea49b2725c 100644 --- a/client/src/components/settings/privacy.tsx +++ b/client/src/components/settings/privacy.tsx @@ -60,99 +60,103 @@ function PrivacySettings({

    {t('settings.privacy')}

    - - - - - - - - - - +
    + + + + + + + + + + +
    diff --git a/client/src/components/settings/settings-button.test.js b/client/src/components/settings/settings-button.test.js new file mode 100644 index 00000000000000..8cc9778688a0d5 --- /dev/null +++ b/client/src/components/settings/settings-button.test.js @@ -0,0 +1,48 @@ +import renderer from 'react-test-renderer'; + +import { + legacyProjectMap, + projectMap +} from '../../resources/cert-and-project-map'; +import { CertificationSettings } from './certification'; + +const props = { t: val => val }; + +const certificationSettings = new CertificationSettings(props); + +const { renderCertifications } = certificationSettings; + +beforeAll(() => { + projectMap['JavaScript Algorithms and Data Structures'] = projectMap[ + 'JavaScript Algorithms and Data Structures' + ].map(v => ({ + ...v, + link: 'javascript' + })); +}); + +it('should check legacy certification button consistency', () => { + const legacyCertifications = Object.keys(legacyProjectMap); + + const tree = renderer + .create( + legacyCertifications.map(certName => + renderCertifications(certName, legacyProjectMap) + ) + ) + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); + +it('should check certification button consistency', () => { + const certifications = Object.keys(projectMap); + + const tree = renderer + .create( + certifications.map(certName => renderCertifications(certName, projectMap)) + ) + .toJSON(); + + expect(tree).toMatchSnapshot(); +}); diff --git a/client/src/components/settings/toggle-setting.css b/client/src/components/settings/toggle-setting.css index c2c0677ffe028e..e7ba31526ea25a 100644 --- a/client/src/components/settings/toggle-setting.css +++ b/client/src/components/settings/toggle-setting.css @@ -11,7 +11,7 @@ } .toggle-setting-container .btn-group { - padding-left: 5px; + padding-inline: 5px; } .toggle-setting-container > .form-group > * { diff --git a/client/src/components/settings/username.tsx b/client/src/components/settings/username.tsx index 5c146c20b7d678..59755e71ef407c 100644 --- a/client/src/components/settings/username.tsx +++ b/client/src/components/settings/username.tsx @@ -96,7 +96,6 @@ class UsernameSettings extends Component { const { username } = this.props; const { formValue } = this.state; if (prevUsername !== username && prevFormValue === formValue) { - // eslint-disable-next-line react/no-did-update-set-state return this.setState({ isFormPristine: username === formValue, submitClicked: false, @@ -210,7 +209,8 @@ class UsernameSettings extends Component { submitClicked } = this.state; const { isValidUsername, t, validating } = this.props; - + const isDisabled = + !(isValidUsername && valid && !isFormPristine) || submitClicked; return (
    { onChange={this.handleChange} value={formValue} data-cy='username-input' + id='username-settings' /> @@ -234,10 +235,13 @@ class UsernameSettings extends Component { this.renderAlerts(validating, error, isValidUsername)} + aria-disabled={isDisabled} + bgSize='lg' + {...(isDisabled && { tabIndex: -1 })} + > + {t('buttons.save')}{' '} + {t('settings.labels.username')} + ); diff --git a/client/src/components/solution-display-widget/index.tsx b/client/src/components/solution-display-widget/index.tsx index 13ba1de6dfdce6..b720163ae25165 100644 --- a/client/src/components/solution-display-widget/index.tsx +++ b/client/src/components/solution-display-widget/index.tsx @@ -1,18 +1,15 @@ import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { - Button, - DropdownButton, - MenuItem -} from '@freecodecamp/react-bootstrap'; +import { Button, Dropdown, MenuItem } from '@freecodecamp/react-bootstrap'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { CompletedChallenge } from '../../redux/prop-types'; import { getSolutionDisplayType } from '../../utils/solution-display-type'; - +import './solution-display-widget.css'; interface Props { completedChallenge: CompletedChallenge; dataCy?: string; + projectTitle: string; showUserCode: () => void; showProjectPreview?: () => void; displayContext: 'timeline' | 'settings' | 'certification'; @@ -21,45 +18,74 @@ interface Props { export function SolutionDisplayWidget({ completedChallenge, dataCy, + projectTitle, showUserCode, showProjectPreview, displayContext -}: Props) { +}: Props): JSX.Element | null { const { id, solution, githubLink } = completedChallenge; const { t } = useTranslation(); const viewText = t('buttons.view'); const viewCode = t('buttons.view-code'); const viewProject = t('buttons.view-project'); - + // We need to add a random number for dropdown button id's since there may be + // two dropdowns for the same project on the page. + const randomIdSuffix = Math.floor(Math.random() * 1_000_000); const ShowFilesSolutionForCertification = ( - + ); const ShowProjectAndGithubLinkForCertification = ( - <> - - {t('certification.project.solution')} - - ,{' '} - - {t('certification.project.source')} - - + + + {viewText}{' '} + + {t('settings.labels.solution-for', { projectTitle })} + + + + + {t('certification.project.solution')} + ({t('aria.opens-new-window')}) + + + + {t('certification.project.source')} + ({t('aria.opens-new-window')}) + + + + ); const ShowProjectLinkForCertification = ( - - {t('certification.project.solution')} - + {viewText}{' '} + + {t('settings.labels.solution-for', { projectTitle })} ( + {t('aria.opens-new-window')}) + + + ); const MissingSolutionComponentForCertification = ( <>{t('certification.project.no-solution')} @@ -70,57 +96,67 @@ export function SolutionDisplayWidget({ bsStyle='primary' className='btn-invert' data-cy={dataCy} - id={`btn-for-${id}`} onClick={showUserCode} > - {viewText} + {viewText}{' '} + + {t('settings.labels.solution-for', { projectTitle })} + ); const ShowMultifileProjectSolution = (
    - - - {viewCode} - - - {viewProject} - - + + + {viewText}{' '} + + {t('settings.labels.solution-for', { projectTitle })} + + + + + {viewCode} + + + {viewProject} + + +
    ); const ShowProjectAndGithubLinks = (
    - - - {t('buttons.frontend')} - - - {t('buttons.backend')} - - + + + {viewText}{' '} + + {t('settings.labels.solution-for', { projectTitle })} + + + + + {t('buttons.frontend')}{' '} + ({t('aria.opens-new-window')}) + + + + {t('buttons.backend')}{' '} + ({t('aria.opens-new-window')}) + + + +
    ); const ShowProjectLink = ( @@ -129,11 +165,15 @@ export function SolutionDisplayWidget({ bsStyle='primary' className='btn-invert' href={solution} - id={`btn-for-${id}`} rel='noopener noreferrer' target='_blank' > - {viewText} + {viewText}{' '} + + {t('settings.labels.solution-for', { projectTitle })} ( + {t('aria.opens-new-window')}) + + ); const MissingSolutionComponent = diff --git a/client/src/components/solution-display-widget/solution-display-widget.css b/client/src/components/solution-display-widget/solution-display-widget.css new file mode 100644 index 00000000000000..4bff674e52343d --- /dev/null +++ b/client/src/components/solution-display-widget/solution-display-widget.css @@ -0,0 +1,3 @@ +.solutions-dropdown a[role='menuitem'] { + text-decoration: none; +} diff --git a/client/src/declarations.d.ts b/client/src/declarations.d.ts index 5591e3a3edc2f9..f56ab2a3e99385 100644 --- a/client/src/declarations.d.ts +++ b/client/src/declarations.d.ts @@ -38,3 +38,5 @@ declare var MathJax: { Queue: (attributes: unknown[]) => void; }; }; + +declare module 'monaco-editor/esm/vs/base/common/platform.js'; diff --git a/client/src/pages/__snapshots__/email-sign-up.test.js.snap b/client/src/pages/__snapshots__/email-sign-up.test.js.snap index 1931f92d7b40b7..c6fc3a404dc5a2 100644 --- a/client/src/pages/__snapshots__/email-sign-up.test.js.snap +++ b/client/src/pages/__snapshots__/email-sign-up.test.js.snap @@ -13,7 +13,6 @@ exports[` Non-Authenticated user "not accepted terms and conditio className="col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1 col-xs-12" >
    Non-Authenticated user "not accepted terms and conditio learn.read-this.heading
    Non-Authenticated user "not accepted terms and conditio misc.quincy
    Non-Authenticated user "not accepted terms and conditio misc.email-blast

    Non-Authenticated user "not accepted terms and conditio className="col-xs-12" >
    void; @@ -58,28 +55,12 @@ function DonatePage({ }: DonatePageProps) { useEffect(() => { executeGA({ - type: 'event', - data: { - category: 'Donation View', - action: `Displayed donate page`, - nonInteraction: true - } + event: 'donationview', + action: `Displayed Donate Page` }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - function handleProcessing(duration: string, amount: number, action: string) { - executeGA({ - type: 'event', - data: { - category: 'Donation', - action: `donate page ${action}`, - label: duration, - value: amount - } - }); - } - return showLoading ? ( ) : ( @@ -110,7 +91,7 @@ function DonatePage({
    - + diff --git a/client/src/pages/learn.tsx b/client/src/pages/learn.tsx index b534563989170f..0ae210ae9fddda 100644 --- a/client/src/pages/learn.tsx +++ b/client/src/pages/learn.tsx @@ -11,6 +11,7 @@ import Intro from '../components/Intro'; import Map from '../components/Map'; import { Spacer } from '../components/helpers'; import LearnLayout from '../components/layouts/learn'; +import { defaultDonation } from '../../../config/donation-settings'; import { isSignedInSelector, userSelector, @@ -82,11 +83,10 @@ function LearnPage({ const onDonationAlertClick = () => { executeGA({ - type: 'event', - data: { - category: 'Donation Related', - action: `learn donation alert click` - } + event: 'donationrelated', + action: `Learn Donation Alert Click`, + duration: defaultDonation.donationDuration, + amount: defaultDonation.donationAmount }); }; return ( diff --git a/client/src/pages/learn/2022/javascript-algorithms-and-data-structures/learn-advanced-array-methods-by-building-a-statistics-calculator/index.md b/client/src/pages/learn/2022/javascript-algorithms-and-data-structures/learn-advanced-array-methods-by-building-a-statistics-calculator/index.md new file mode 100644 index 00000000000000..608a7a57643363 --- /dev/null +++ b/client/src/pages/learn/2022/javascript-algorithms-and-data-structures/learn-advanced-array-methods-by-building-a-statistics-calculator/index.md @@ -0,0 +1,10 @@ +--- +title: Introduction to the Learn Advanced Array Methods by Building a Statistics Calculator +block: learn-advanced-array-methods-by-building-a-statistics-calculator +superBlock: JavaScript Algorithms and Data Structures +isBeta: true +--- + +## Introduction to the Learn Advanced Array Methods by Building a Statistics Calculator + +This is a test for the new project-based curriculum. diff --git a/client/src/pages/learn/the-odin-project/index.md b/client/src/pages/learn/the-odin-project/index.md new file mode 100644 index 00000000000000..e600d4a733413d --- /dev/null +++ b/client/src/pages/learn/the-odin-project/index.md @@ -0,0 +1,9 @@ +--- +title: The Odin Project +superBlock: the-odin-project +certification: the-odin-project +--- + +## The Odin project + +The Odin Project is one of those "What I wish I had when I was learning" resources. Not everyone has access to a computer science education or the funds to attend an intensive coding school and neither of those is right for everyone anyway. This project is designed to fill in the gap for people who are trying to hack it on their own but still want a high quality education. diff --git a/client/src/pages/learn/the-odin-project/top-build-a-recipe-page-project/index.md b/client/src/pages/learn/the-odin-project/top-build-a-recipe-page-project/index.md new file mode 100644 index 00000000000000..39bc4dc70b8006 --- /dev/null +++ b/client/src/pages/learn/the-odin-project/top-build-a-recipe-page-project/index.md @@ -0,0 +1,9 @@ +--- +title: The Odin Project +superBlock: the-odin-project +certification: the-odin-project +--- + +## The Odin project + +Description is to be determined diff --git a/client/src/pages/learn/the-odin-project/top-learn-html-foundations/index.md b/client/src/pages/learn/the-odin-project/top-learn-html-foundations/index.md new file mode 100644 index 00000000000000..39bc4dc70b8006 --- /dev/null +++ b/client/src/pages/learn/the-odin-project/top-learn-html-foundations/index.md @@ -0,0 +1,9 @@ +--- +title: The Odin Project +superBlock: the-odin-project +certification: the-odin-project +--- + +## The Odin project + +Description is to be determined diff --git a/client/src/redux/action-types.js b/client/src/redux/action-types.js index 22465beb90f397..4053c80dab9a76 100644 --- a/client/src/redux/action-types.js +++ b/client/src/redux/action-types.js @@ -23,19 +23,17 @@ export const actionTypes = createTypes( 'showCodeAlly', 'submitComplete', 'updateComplete', - 'updateCurrentChallengeId', 'updateFailed', 'updateDonationFormState', 'updateUserToken', + 'postChargeProcessing', + 'updateAllChallengesInfo', ...createAsyncTypes('fetchUser'), - ...createAsyncTypes('addDonation'), - ...createAsyncTypes('createStripeSession'), - ...createAsyncTypes('postChargeStripe'), + ...createAsyncTypes('postCharge'), ...createAsyncTypes('fetchProfileForUser'), ...createAsyncTypes('acceptTerms'), ...createAsyncTypes('showCert'), ...createAsyncTypes('reportUser'), - ...createAsyncTypes('postChargeStripeCard'), ...createAsyncTypes('deleteUserToken'), ...createAsyncTypes('saveChallenge') ], diff --git a/client/src/redux/actions.js b/client/src/redux/actions.js index a540a71d58cd76..38608a046bc411 100644 --- a/client/src/redux/actions.js +++ b/client/src/redux/actions.js @@ -53,28 +53,16 @@ export const fetchUser = createAction(actionTypes.fetchUser); export const fetchUserComplete = createAction(actionTypes.fetchUserComplete); export const fetchUserError = createAction(actionTypes.fetchUserError); -export const addDonation = createAction(actionTypes.addDonation); -export const addDonationComplete = createAction( - actionTypes.addDonationComplete +export const updateAllChallengesInfo = createAction( + actionTypes.updateAllChallengesInfo ); -export const addDonationError = createAction(actionTypes.addDonationError); -export const postChargeStripe = createAction(actionTypes.postChargeStripe); -export const postChargeStripeComplete = createAction( - actionTypes.postChargeStripeComplete -); -export const postChargeStripeError = createAction( - actionTypes.postChargeStripeError -); -export const postChargeStripeCard = createAction( - actionTypes.postChargeStripeCard -); -export const postChargeStripeCardComplete = createAction( - actionTypes.postChargeStripeCardComplete -); -export const postChargeStripeCardError = createAction( - actionTypes.postChargeStripeCardError +export const postCharge = createAction(actionTypes.postCharge); +export const postChargeProcessing = createAction( + actionTypes.postChargeProcessing ); +export const postChargeComplete = createAction(actionTypes.postChargeComplete); +export const postChargeError = createAction(actionTypes.postChargeError); export const fetchProfileForUser = createAction( actionTypes.fetchProfileForUser @@ -106,9 +94,5 @@ export const hideCodeAlly = createAction(actionTypes.hideCodeAlly); export const showCodeAlly = createAction(actionTypes.showCodeAlly); export const tryToShowCodeAlly = createAction(actionTypes.tryToShowCodeAlly); -export const updateCurrentChallengeId = createAction( - actionTypes.updateCurrentChallengeId -); - export const closeSignoutModal = createAction(actionTypes.closeSignoutModal); export const openSignoutModal = createAction(actionTypes.openSignoutModal); diff --git a/client/src/redux/cookieValues.js b/client/src/redux/cookie-values.js similarity index 100% rename from client/src/redux/cookieValues.js rename to client/src/redux/cookie-values.js diff --git a/client/src/redux/createStore.js b/client/src/redux/create-store.js similarity index 86% rename from client/src/redux/createStore.js rename to client/src/redux/create-store.js index 75e19ea50174a1..93918f35dea3ca 100644 --- a/client/src/redux/createStore.js +++ b/client/src/redux/create-store.js @@ -5,9 +5,9 @@ import createSagaMiddleware from 'redux-saga'; import envData from '../../../config/env.json'; import { isBrowser } from '../../utils'; -import rootEpic from './rootEpic'; -import rootReducer from './rootReducer'; -import rootSaga from './rootSaga'; +import rootEpic from './root-epic'; +import rootReducer from './root-reducer'; +import rootSaga from './root-saga'; const { environment } = envData; @@ -47,8 +47,8 @@ export const createStore = () => { epicMiddleware.run(rootEpic); if (module.hot) { // Enable Webpack hot module replacement for reducers - module.hot.accept('./rootReducer', () => { - const nextRootReducer = require('./rootReducer'); + module.hot.accept('./root-reducer', () => { + const nextRootReducer = require('./root-reducer'); store.replaceReducer(nextRootReducer); }); } diff --git a/client/src/redux/donation-saga.js b/client/src/redux/donation-saga.js index 73f0a9f5822fbb..245f3cf7940518 100644 --- a/client/src/redux/donation-saga.js +++ b/client/src/redux/donation-saga.js @@ -14,22 +14,23 @@ import { postChargeStripe, postChargeStripeCard } from '../utils/ajax'; +import { stringifyDonationEvents } from '../utils/analyticsStrings'; +import { PaymentProvider } from '../../../config/donation-settings'; import { actionTypes as appTypes } from './action-types'; import { - addDonationComplete, - addDonationError, openDonationModal, - postChargeStripeCardComplete, - postChargeStripeCardError, - postChargeStripeComplete, - postChargeStripeError, + postChargeComplete, + postChargeProcessing, + postChargeError, preventBlockDonationRequests, - preventProgressDonationRequests + preventProgressDonationRequests, + executeGA } from './actions'; import { isDonatingSelector, recentlyClaimedBlockSelector, - shouldRequestDonationSelector + shouldRequestDonationSelector, + isSignedInSelector } from './selectors'; const defaultDonationErrorMessage = i18next.t('donate.error-2'); @@ -49,33 +50,74 @@ function* showDonateModalSaga() { } } -function* addDonationSaga({ payload }) { - try { - yield call(addDonation, payload); - yield put(addDonationComplete()); - yield call(setDonationCookie); - } catch (error) { - const data = - error.response && error.response.data - ? error.response.data - : { - message: defaultDonationErrorMessage - }; - yield put(addDonationError(data.message)); +export function* postChargeSaga({ + payload, + payload: { + paymentProvider, + paymentContext, + amount, + duration, + handleAuthentication, + paymentMethodId } -} - -function* postChargeStripeSaga({ payload }) { +}) { try { - yield call(postChargeStripe, payload); - yield put(postChargeStripeComplete()); - yield call(setDonationCookie); + if (paymentProvider !== PaymentProvider.Patreon) { + yield put(postChargeProcessing()); + } + + if (paymentProvider === PaymentProvider.Stripe) { + yield call(postChargeStripe, payload); + } else if (paymentProvider === PaymentProvider.StripeCard) { + const optimizedPayload = { paymentMethodId, amount, duration }; + const response = yield call(postChargeStripeCard, optimizedPayload); + const error = response?.data?.error; + if (error) { + yield stripeCardErrorHandler( + error, + handleAuthentication, + error.client_secret, + response.paymentMethodId, + optimizedPayload + ); + + //if the authentication does not throw an error, add a donation + yield call(addDonation, { amount, duration }); + } + } else if (paymentProvider === PaymentProvider.Paypal) { + // If the user is signed in and the payment goes through call api + let isSignedIn = yield select(isSignedInSelector); + // look into skip add donation + // what to do with "data" that comes throug + if (isSignedIn) yield call(addDonation, { amount, duration }); + } + if ( + [ + PaymentProvider.Paypal, + PaymentProvider.Stripe, + PaymentProvider.StripeCard + ].includes(paymentProvider) + ) { + yield put(postChargeComplete()); + yield call(setDonationCookie); + } + yield put( + executeGA({ + event: + paymentProvider === PaymentProvider.Patreon + ? 'donationrelated' + : 'donation', + action: stringifyDonationEvents(paymentContext, paymentProvider), + duration, + amount + }) + ); } catch (error) { const err = error.response && error.response.data ? error.response.data.error : defaultDonationErrorMessage; - yield put(postChargeStripeError(err)); + yield put(postChargeError(err)); } } @@ -99,40 +141,16 @@ function* stripeCardErrorHandler( } } -function* postChargeStripeCardSaga({ - payload: { paymentMethodId, amount, duration, handleAuthentication } -}) { - try { - const optimizedPayload = { paymentMethodId, amount, duration }; - const { - data: { error } - } = yield call(postChargeStripeCard, optimizedPayload); - if (error) { - yield stripeCardErrorHandler( - error, - handleAuthentication, - error.client_secret, - paymentMethodId, - optimizedPayload - ); - } - yield call(addDonation, optimizedPayload); - yield put(postChargeStripeCardComplete()); - yield call(setDonationCookie); - } catch (error) { - const errorMessage = error.message || defaultDonationErrorMessage; - yield put(postChargeStripeCardError(errorMessage)); - } -} - -function* setDonationCookie() { - const isDonating = yield select(isDonatingSelector); - const isDonorCookieSet = document.cookie - .split(';') - .some(item => item.trim().startsWith('isDonor=true')); - if (isDonating) { - if (!isDonorCookieSet) { - document.cookie = 'isDonor=true'; +export function* setDonationCookie() { + if (document?.cookie) { + const isDonating = yield select(isDonatingSelector); + const isDonorCookieSet = document.cookie + .split(';') + .some(item => item.trim().startsWith('isDonor=true')); + if (isDonating) { + if (!isDonorCookieSet) { + document.cookie = 'isDonor=true'; + } } } } @@ -140,9 +158,7 @@ function* setDonationCookie() { export function createDonationSaga(types) { return [ takeEvery(types.tryToShowDonationModal, showDonateModalSaga), - takeEvery(types.addDonation, addDonationSaga), - takeLeading(types.postChargeStripe, postChargeStripeSaga), - takeLeading(types.postChargeStripeCard, postChargeStripeCardSaga), + takeLeading(types.postCharge, postChargeSaga), takeEvery(types.fetchUserComplete, setDonationCookie) ]; } diff --git a/client/src/redux/donation-saga.test.js b/client/src/redux/donation-saga.test.js new file mode 100644 index 00000000000000..d7fa3de10a6ce5 --- /dev/null +++ b/client/src/redux/donation-saga.test.js @@ -0,0 +1,124 @@ +import { expectSaga } from 'redux-saga-test-plan'; +import { + postChargeStripe, + postChargeStripeCard, + addDonation +} from '../utils/ajax'; +import { postChargeSaga, setDonationCookie } from './donation-saga.js'; +import { postChargeComplete, postChargeProcessing, executeGA } from './actions'; + +jest.mock('../utils/ajax'); +jest.mock('../analytics'); + +const postChargeDataMock = { + payload: { + paymentProvider: 'stripe', + paymentContext: 'donate page', + amount: '500', + duration: 'monthly', + handleAuthentication: jest.fn(), + paymentMethodId: '123456' + } +}; + +const analyticsDataMock = { + event: 'donation', + action: 'Donate Page Stripe Payment Submission', + duration: 'monthly', + amount: '500' +}; + +describe('donation-saga', () => { + it('calls postChargeStrip for Stripe', () => { + return expectSaga(postChargeSaga, postChargeDataMock) + .put(postChargeProcessing()) + .call(postChargeStripe, postChargeDataMock.payload) + .put(postChargeComplete()) + .call(setDonationCookie) + .put(executeGA(analyticsDataMock)) + .run(); + }); + + it('calls postChargeStripCard for Stripe Card', () => { + const stripeCardDataMock = { + payload: { ...postChargeDataMock.payload, paymentProvider: 'stripe card' } + }; + + const stripeCardAnalyticsDataMock = analyticsDataMock; + stripeCardAnalyticsDataMock.action = + 'Donate Page Stripe Card Payment Submission'; + + const { paymentMethodId, amount, duration } = stripeCardDataMock.payload; + const optimizedPayload = { paymentMethodId, amount, duration }; + return expectSaga(postChargeSaga, stripeCardDataMock) + .put(postChargeProcessing()) + .call(postChargeStripeCard, optimizedPayload) + .put(postChargeComplete()) + .call(setDonationCookie) + .put(executeGA(stripeCardAnalyticsDataMock)) + .run(); + }); + + it('calls addDonate for Paypal if user signed in', () => { + const paypalDataMock = { + payload: { ...postChargeDataMock.payload, paymentProvider: 'paypal' } + }; + + const paypalAnalyticsDataMock = analyticsDataMock; + paypalAnalyticsDataMock.action = 'Donate Page Paypal Payment Submission'; + + const storeMock = { + app: { + appUsername: 'devuser' + } + }; + + const { amount, duration } = paypalDataMock.payload; + return expectSaga(postChargeSaga, paypalDataMock) + .withState(storeMock) + .put(postChargeProcessing()) + .call(addDonation, { amount, duration }) + .put(postChargeComplete()) + .call(setDonationCookie) + .put(executeGA(paypalAnalyticsDataMock)) + .run(); + }); + + it('does not call addDonate for Paypal if user not signed in', () => { + const paypalDataMock = { + payload: { ...postChargeDataMock.payload, paymentProvider: 'paypal' } + }; + + const paypalAnalyticsDataMock = analyticsDataMock; + paypalAnalyticsDataMock.action = 'Donate Page Paypal Payment Submission'; + + const storeMock = { + app: {} + }; + + return expectSaga(postChargeSaga, paypalDataMock) + .withState(storeMock) + .put(postChargeProcessing()) + .not.call.fn(addDonation) + .put(postChargeComplete()) + .call(setDonationCookie) + .put(executeGA(paypalAnalyticsDataMock)) + .run(); + }); + + it('does not call api for Patreon', () => { + const patreonDataMock = { + payload: { ...postChargeDataMock.payload, paymentProvider: 'patreon' } + }; + + const patreonAnalyticsDataMock = analyticsDataMock; + patreonAnalyticsDataMock.action = 'Donate Page Patreon Payment Redirection'; + patreonAnalyticsDataMock.event = 'donationrelated'; + return expectSaga(postChargeSaga, patreonDataMock) + .not.call.fn(addDonation) + .not.call.fn(postChargeStripeCard) + .not.call.fn(postChargeStripe) + .put(executeGA(patreonAnalyticsDataMock)) + .run(); + }); +}); diff --git a/client/src/redux/fetch-user-saga.js b/client/src/redux/fetch-user-saga.js index 6e9dadac818f31..826cccc06978ff 100644 --- a/client/src/redux/fetch-user-saga.js +++ b/client/src/redux/fetch-user-saga.js @@ -1,5 +1,5 @@ import { call, put, takeEvery } from 'redux-saga/effects'; - +import store from 'store'; import { getSessionUser, getUserProfile } from '../utils/ajax'; import { fetchProfileForUserComplete, @@ -7,7 +7,7 @@ import { fetchUserComplete, fetchUserError } from './actions'; -import { jwt } from './cookieValues'; +import { jwt } from './cookie-values'; function* fetchSessionUser() { if (!jwt) { @@ -19,6 +19,13 @@ function* fetchSessionUser() { data: { user = {}, result = '', sessionMeta = {} } } = yield call(getSessionUser); const appUser = user[result] || {}; + + const [userId] = Object.keys(user); + + const sound = user[userId].sound; + + store.set('fcc-sound', sound); + yield put( fetchUserComplete({ user: appUser, username: result, sessionMeta }) ); diff --git a/client/src/redux/ga-saga.js b/client/src/redux/ga-saga.js index 9b94094a5168c2..98ef478479ef16 100644 --- a/client/src/redux/ga-saga.js +++ b/client/src/redux/ga-saga.js @@ -1,57 +1,34 @@ -/* eslint-disable camelcase */ -import { all, call, select, takeEvery } from 'redux-saga/effects'; - -import { aBTestConfig } from '../../../config/donation-settings'; -import ga from '../analytics'; -import { emailToABVariant } from '../utils/A-B-tester'; -import { - completedChallengesSelector, - completionCountSelector, - emailSelector, - recentlyClaimedBlockSelector -} from './selectors'; - -const GaTypes = { event: ga.event, page: ga.pageview, modal: ga.modalview }; - -function* callGaType({ payload: { type, data } }) { - if ( - type === 'event' && - data.category.toLowerCase().includes('donation') && - aBTestConfig.isTesting - ) { - const email = yield select(emailSelector); - - // a b test results are only reported when user is signed in and has email - if (email) { - const completedChallengeTotal = yield select(completedChallengesSelector); - const completedChallengeSession = yield select(completionCountSelector); - let viewType = null; - - // set the modal type - if (data.action.toLowerCase().includes('modal')) { - const recentlyClaimedBlock = yield select(recentlyClaimedBlockSelector); - viewType = recentlyClaimedBlock ? 'block' : 'progress'; +import { all, call, takeEvery } from 'redux-saga/effects'; +import TagManager from '../analytics'; + +function* callGaType({ + payload: { action, duration, amount, event, pagePath } +}) { + if (event === 'pageview') { + yield call(TagManager.dataLayer, { + dataLayer: { + event, + pagePath } - - const customDimensions = { - // URL; - dimension1: window.location.href, - // Challenges_Completed_Session - dimension2: completedChallengeSession, - // Challenges_Completed_Total - dimension3: completedChallengeTotal.length, - // Test_Type - dimension4: aBTestConfig.type, - // Test_Variation - dimension5: emailToABVariant(email).isVariantA ? 'A' : 'B', - // View_Type - dimension6: viewType - }; - ga.set(customDimensions); - } + }); + } else if (event === 'donationview') { + yield call(TagManager.dataLayer, { + dataLayer: { + event, + action + } + }); + } else { + // donation and donationrelated + yield call(TagManager.dataLayer, { + dataLayer: { + event, + action, + duration, + amount + } + }); } - - yield call(GaTypes[type], data); } export function* createGaSaga(types) { diff --git a/client/src/redux/ga-saga.test.js b/client/src/redux/ga-saga.test.js index 47c7026caa13d0..7911349727e04e 100644 --- a/client/src/redux/ga-saga.test.js +++ b/client/src/redux/ga-saga.test.js @@ -1,24 +1,21 @@ import { expectSaga } from 'redux-saga-test-plan'; -import ga from '../analytics'; +import TagManager from '../analytics'; import { actionTypes } from './action-types'; import { createGaSaga } from './ga-saga'; - jest.mock('../analytics'); describe('ga-saga', () => { it('calls GA after executeGA action', () => { - const GaTypes = { event: ga.event, page: ga.pageview, modal: ga.modalview }; const mockEventPayload = { - type: 'event', - data: { - category: 'Map Challenge Click', - action: '/learn' - } + action: 'Learn Donation Alert Click', + amount: 500, + duration: 'month', + event: 'donationrelated' }; return ( expectSaga(createGaSaga, actionTypes) // Assert that the `call` with expected paramater will eventually happen. - .call(GaTypes.event, mockEventPayload.data) + .call(TagManager.dataLayer, { dataLayer: mockEventPayload }) // Dispatch any actions that the saga will `take`. .dispatch({ type: actionTypes.executeGA, payload: mockEventPayload }) diff --git a/client/src/redux/index.js b/client/src/redux/index.js index a87e06c2ce0180..a8679853f167ee 100644 --- a/client/src/redux/index.js +++ b/client/src/redux/index.js @@ -22,7 +22,7 @@ import { createShowCertSaga } from './show-cert-saga'; import updateCompleteEpic from './update-complete-epic'; import { createUserTokenSaga } from './user-token-saga'; -export const defaultFetchState = { +const defaultFetchState = { pending: true, complete: false, errored: false, @@ -40,7 +40,7 @@ export const defaultDonationFormState = { } }; -export const initialState = { +const initialState = { appUsername: '', recentlyClaimedBlock: null, canRequestProgressDonation: true, @@ -55,6 +55,10 @@ export const initialState = { userFetchState: { ...defaultFetchState }, + allChallengesInfo: { + challengeEdges: [], + certificateNodes: [] + }, userProfileFetchState: { ...defaultFetchState }, @@ -122,11 +126,11 @@ export const reducer = handleActions( ...state, donationFormState: { ...state.donationFormState, ...payload } }), - [actionTypes.addDonation]: state => ({ + [actionTypes.postChargeProcessing]: state => ({ ...state, donationFormState: { ...defaultDonationFormState, processing: true } }), - [actionTypes.addDonationComplete]: state => { + [actionTypes.postChargeComplete]: state => { const { appUsername } = state; return { ...state, @@ -141,55 +145,13 @@ export const reducer = handleActions( donationFormState: { ...defaultDonationFormState, success: true } }; }, - [actionTypes.addDonationError]: (state, { payload }) => ({ + [actionTypes.postChargeError]: (state, { payload }) => ({ ...state, donationFormState: { ...defaultDonationFormState, error: payload } }), - [actionTypes.postChargeStripe]: state => ({ - ...state, - donationFormState: { ...defaultDonationFormState, processing: true } - }), - [actionTypes.postChargeStripeComplete]: state => { - const { appUsername } = state; - return { - ...state, - user: { - ...state.user, - [appUsername]: { - ...state.user[appUsername], - isDonating: true - } - }, - - donationFormState: { ...defaultDonationFormState, success: true } - }; - }, - [actionTypes.postChargeStripeError]: (state, { payload }) => ({ + [actionTypes.updateAllChallengesInfo]: (state, { payload }) => ({ ...state, - donationFormState: { ...defaultDonationFormState, error: payload } - }), - [actionTypes.postChargeStripeCard]: state => ({ - ...state, - donationFormState: { ...defaultDonationFormState, processing: true } - }), - [actionTypes.postChargeStripeCardComplete]: state => { - const { appUsername } = state; - return { - ...state, - user: { - ...state.user, - [appUsername]: { - ...state.user[appUsername], - isDonating: true - } - }, - - donationFormState: { ...defaultDonationFormState, success: true } - }; - }, - [actionTypes.postChargeStripeCardError]: (state, { payload }) => ({ - ...state, - donationFormState: { ...defaultDonationFormState, error: payload } + allChallengesInfo: { ...payload } }), [actionTypes.fetchUser]: state => ({ ...state, diff --git a/client/src/redux/prop-types.ts b/client/src/redux/prop-types.ts index aed72b85469a71..062b201a3ebfe5 100644 --- a/client/src/redux/prop-types.ts +++ b/client/src/redux/prop-types.ts @@ -1,78 +1,8 @@ -import PropTypes from 'prop-types'; import { HandlerProps } from 'react-reflex'; import { SuperBlocks } from '../../../config/certification-settings'; import { Themes } from '../components/settings/theme'; import { certMap } from '../resources/cert-and-project-map'; -export const UserPropType = PropTypes.shape({ - about: PropTypes.string, - completedChallenges: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string, - solution: PropTypes.string, - githubLink: PropTypes.string, - challengeType: PropTypes.number, - completedDate: PropTypes.number, - challengeFiles: PropTypes.array - }) - ), - email: PropTypes.string, - githubProfile: PropTypes.string, - is2018DataVisCert: PropTypes.bool, - isApisMicroservicesCert: PropTypes.bool, - isBackEndCert: PropTypes.bool, - isDataVisCert: PropTypes.bool, - isEmailVerified: PropTypes.bool, - isFrontEndCert: PropTypes.bool, - isFrontEndLibsCert: PropTypes.bool, - isFullStackCert: PropTypes.bool, - isHonest: PropTypes.bool, - isInfosecQaCert: PropTypes.bool, - isQaCertV7: PropTypes.bool, - isInfosecCertV7: PropTypes.bool, - isJsAlgoDataStructCert: PropTypes.bool, - isRelationalDatabaseCertV8: PropTypes.bool, - isRespWebDesignCert: PropTypes.bool, - isSciCompPyCertV7: PropTypes.bool, - isDataAnalysisPyCertV7: PropTypes.bool, - isMachineLearningPyCertV7: PropTypes.bool, - linkedin: PropTypes.string, - location: PropTypes.string, - name: PropTypes.string, - picture: PropTypes.string, - points: PropTypes.number, - portfolio: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - title: PropTypes.string, - url: PropTypes.string, - image: PropTypes.string, - description: PropTypes.string - }) - ), - savedChallenges: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string, - challengeFiles: PropTypes.array - }) - ), - sendQuincyEmail: PropTypes.bool, - sound: PropTypes.bool, - theme: PropTypes.string, - keyboardShortcuts: PropTypes.bool, - twitter: PropTypes.string, - username: PropTypes.string, - website: PropTypes.string -}); - -export const CurrentCertsPropType = PropTypes.arrayOf( - PropTypes.shape({ - show: PropTypes.bool, - title: PropTypes.string, - certSlug: PropTypes.string - }) -); - export type Steps = { isHonest?: boolean; currentCerts?: Array; @@ -96,7 +26,7 @@ export type MarkdownRemark = { superBlock: SuperBlocks; // TODO: make enum like superBlock certification: string; - title: typeof certMap[number]['title']; + title: (typeof certMap)[number]['title']; }; headings: [ { @@ -117,7 +47,11 @@ export type MarkdownRemark = { }; }; -type Question = { text: string; answers: string[]; solution: number }; +type Question = { + text: string; + answers: string[]; + solution: number; +}; type Fields = { slug: string; blockName: string; tests: Test[] }; type Required = { link: string; @@ -185,6 +119,7 @@ export type ChallengeNode = { isPrivate: boolean; order: number; question: Question; + assignments: string[]; required: Required[]; solutions: { [T in FileKey]: FileKeyChallenge; @@ -207,6 +142,19 @@ export type ChallengeNode = { }; }; +export type CertificateNode = { + challenge: { + // TODO: use enum + certification: string; + tests: { id: string }[]; + }; +}; + +export type AllChallengesInfo = { + challengeEdges: { node: ChallengeNode }[]; + certificateNodes: CertificateNode[]; +}; + export type AllChallengeNode = { edges: [ { @@ -342,6 +290,7 @@ export type ChallengeMeta = { block: string; id: string; introPath: string; + isFirstStep: boolean; nextChallengePath: string; prevChallengePath: string; removeComments: boolean; diff --git a/client/src/redux/rootEpic.js b/client/src/redux/root-epic.js similarity index 84% rename from client/src/redux/rootEpic.js rename to client/src/redux/root-epic.js index dd956348596234..81a0a6d771268e 100644 --- a/client/src/redux/rootEpic.js +++ b/client/src/redux/root-epic.js @@ -1,7 +1,7 @@ import { combineEpics } from 'redux-observable'; import { epics as challengeEpics } from '../templates/Challenges/redux'; -import { epics as appEpics } from './'; +import { epics as appEpics } from '.'; const rootEpic = combineEpics(...appEpics, ...challengeEpics); diff --git a/client/src/redux/rootReducer.js b/client/src/redux/root-reducer.js similarity index 95% rename from client/src/redux/rootReducer.js rename to client/src/redux/root-reducer.js index 6c20a0672dd7d5..056083926f15b1 100644 --- a/client/src/redux/rootReducer.js +++ b/client/src/redux/root-reducer.js @@ -16,7 +16,7 @@ import { import { ns as appNameSpace } from './action-types'; import { ns as settingsNameSpace, reducer as settings } from './settings'; import { FlashApp as flashNameSpace } from './types'; -import { reducer as app } from './'; +import { reducer as app } from '.'; export default combineReducers({ [appNameSpace]: app, diff --git a/client/src/redux/rootSaga.js b/client/src/redux/root-saga.js similarity index 89% rename from client/src/redux/rootSaga.js rename to client/src/redux/root-saga.js index ec83d4a5b6ee1f..f2d293bebd311a 100644 --- a/client/src/redux/rootSaga.js +++ b/client/src/redux/root-saga.js @@ -3,7 +3,7 @@ import { all } from 'redux-saga/effects'; import { sagas as challengeSagas } from '../templates/Challenges/redux'; import errorSagas from './error-saga'; import { sagas as settingsSagas } from './settings'; -import { sagas as appSagas } from './'; +import { sagas as appSagas } from '.'; export default function* rootSaga() { yield all([...errorSagas, ...appSagas, ...challengeSagas, ...settingsSagas]); diff --git a/client/src/redux/save-challenge-saga.js b/client/src/redux/save-challenge-saga.js index be0ad140992ff0..4c109abe4e7b0a 100644 --- a/client/src/redux/save-challenge-saga.js +++ b/client/src/redux/save-challenge-saga.js @@ -17,7 +17,7 @@ import { import { saveChallengeComplete } from './actions'; import { savedChallengesSelector } from './selectors'; -export function* saveChallengeSaga() { +function* saveChallengeSaga() { const { id, challengeType } = yield select(challengeMetaSelector); const { challengeFiles } = yield select(challengeDataSelector); const savedChallenges = yield select(savedChallengesSelector); diff --git a/client/src/redux/selectors.js b/client/src/redux/selectors.js index e9a561d6067527..eb6c71697c5f22 100644 --- a/client/src/redux/selectors.js +++ b/client/src/redux/selectors.js @@ -1,5 +1,4 @@ import { SuperBlocks } from '../../../config/certification-settings'; -import { emailToABVariant } from '../utils/A-B-tester'; import { ns as MainApp } from './action-types'; export const savedChallengesSelector = state => @@ -13,13 +12,7 @@ export const currentChallengeIdSelector = state => state[MainApp].currentChallengeId; export const emailSelector = state => userSelector(state).email; -export const isVariantASelector = state => { - const email = emailSelector(state); - // if the user is not signed in and the user info is not available. - // always return A the control variant - if (!email) return true; - return emailToABVariant(email).isVariantA; -}; + export const isDonatingSelector = state => userSelector(state).isDonating; export const isOnlineSelector = state => state[MainApp].isOnline; export const isServerOnlineSelector = state => state[MainApp].isServerOnline; @@ -209,6 +202,8 @@ export const certificatesByNameSelector = username => state => { }; export const userFetchStateSelector = state => state[MainApp].userFetchState; +export const allChallengesInfoSelector = state => + state[MainApp].allChallengesInfo; export const userProfileFetchStateSelector = state => state[MainApp].userProfileFetchState; export const usernameSelector = state => state[MainApp].appUsername; @@ -217,5 +212,3 @@ export const userSelector = state => { return state[MainApp].user[username] || {}; }; - -export const sessionMetaSelector = state => state[MainApp].sessionMeta; diff --git a/client/src/redux/types.ts b/client/src/redux/types.ts index 0c56a1c4bd0735..0288b1363b56d0 100644 --- a/client/src/redux/types.ts +++ b/client/src/redux/types.ts @@ -49,17 +49,3 @@ interface DefaultDonationFormState { success: boolean; error: null | string; } - -export const defaultFetchState = { - pending: true, - complete: false, - errored: false, - error: null -}; - -export const defaultDonationFormState = { - redirecting: false, - processing: false, - success: false, - error: '' -}; diff --git a/client/src/resources/cert-and-project-map.ts b/client/src/resources/cert-and-project-map.ts index 198d658fa35d6e..06b34efbe58f99 100644 --- a/client/src/resources/cert-and-project-map.ts +++ b/client/src/resources/cert-and-project-map.ts @@ -747,7 +747,7 @@ function getJavaScriptAlgoPath(project: string) { } const titles = certMap.map(({ title }) => title); -type Title = typeof titles[number]; +type Title = (typeof titles)[number]; const legacyProjectMap: Partial> = {}; const projectMap: Partial> = {}; diff --git a/client/src/resources/honesty-policy.tsx b/client/src/resources/honesty-policy.tsx index dea6b82c460441..2a3a3f489ed651 100644 --- a/client/src/resources/honesty-policy.tsx +++ b/client/src/resources/honesty-policy.tsx @@ -3,7 +3,7 @@ import { Trans, useTranslation } from 'react-i18next'; const HonestyPolicy = (): JSX.Element => { const { t } = useTranslation(); - const email = 'team@freecodecamp.org'; + const email = 'support@freecodecamp.org'; return ( <> diff --git a/client/src/templates/Challenges/classic/classic.css b/client/src/templates/Challenges/classic/classic.css index 62a31f1bfb17d3..77dd98535192d8 100644 --- a/client/src/templates/Challenges/classic/classic.css +++ b/client/src/templates/Challenges/classic/classic.css @@ -45,6 +45,11 @@ background-color: var(--tc-white) !important; } +.monaco-editor-tabs { + display: flex; + margin: 0; +} + .monaco-editor .view-overlays .current-line { width: auto !important; right: 15px; @@ -67,7 +72,7 @@ } #mobile-layout .nav-tabs { - margin-left: 2px; + margin-inline-start: 2px; display: flex; } @@ -112,6 +117,27 @@ display: flex; } +#mobile-layout #mobile-layout-pane-instructions { + overflow-y: auto; +} + +#mobile-layout-pane-instructions:focus-visible { + outline: 3px solid var(--blue-mid); + outline-offset: -2px; +} + +@supports not selector(:focus-visible) { + #mobile-layout-pane-instructions:focus { + outline: 3px solid var(--blue-mid); + outline-offset: -2px; + } +} + +#mobile-layout .nav-tabs > li.active > a { + color: var(--quaternary-color); + background-color: var(--quaternary-background); +} + #mobile-layout .monaco-editor-tabs { padding: 10px; width: 100%; diff --git a/client/src/templates/Challenges/classic/desktop-layout.tsx b/client/src/templates/Challenges/classic/desktop-layout.tsx index 197ba8251006de..4db35ed76194a9 100644 --- a/client/src/templates/Challenges/classic/desktop-layout.tsx +++ b/client/src/templates/Challenges/classic/desktop-layout.tsx @@ -1,6 +1,8 @@ import { first } from 'lodash-es'; -import React, { ReactElement } from 'react'; +import React, { useState, useEffect, ReactElement } from 'react'; import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex'; +import { createSelector } from 'reselect'; +import { connect } from 'react-redux'; import { sortChallengeFiles } from '../../../../../utils/sort-challengefiles'; import { GoogleTagManager } from '../../../analytics/google-tag-manater'; import { Segment } from '../../../analytics/segment'; @@ -9,6 +11,13 @@ import { ChallengeFiles, ResizeProps } from '../../../redux/prop-types'; +import { setShowPreviewPortal, setShowPreviewPane } from '../redux/actions'; +import { + portalWindowSelector, + showPreviewPortalSelector, + showPreviewPaneSelector, + isAdvancingToChallengeSelector +} from '../redux/selectors'; import PreviewPortal from '../components/preview-portal'; import ActionRow from './action-row'; import { @@ -26,6 +35,8 @@ interface DesktopLayoutProps { hasNotes: boolean; hasPreview: boolean; instructions: ReactElement; + isAdvancing: boolean; + isFirstStep: boolean; layoutState: { codePane: Pane; editorPane: Pane; @@ -40,23 +51,83 @@ interface DesktopLayoutProps { testOutput: ReactElement; visibleEditors: { [key: string]: boolean }; windowTitle: string; + showPreviewPortal: boolean; + showPreviewPane: boolean; + setShowPreviewPortal: (arg: boolean) => void; + setShowPreviewPane: (arg: boolean) => void; + portalWindow: null | Window; } const reflexProps = { propagateDimensions: true }; +const mapDispatchToProps = { + setShowPreviewPortal, + setShowPreviewPane +}; + +const mapStateToProps = createSelector( + isAdvancingToChallengeSelector, + showPreviewPortalSelector, + showPreviewPaneSelector, + portalWindowSelector, + + ( + isAdvancing: boolean, + showPreviewPortal: boolean, + showPreviewPane: boolean, + portalWindow: null | Window + ) => ({ + isAdvancing, + showPreviewPortal, + showPreviewPane, + portalWindow + }) +); + const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => { const { - layoutState: { - showInstructions, - showNotes, - showPreviewPane, - showPreviewPortal, - showConsole - }, - togglePane - } = useDesktopLayoutState(); + showPreviewPane, + showPreviewPortal, + setShowPreviewPane, + setShowPreviewPortal, + portalWindow + } = props; + + const [showNotes, setShowNotes] = useState(false); + const [showConsole, setShowConsole] = useState(false); + const [showInstructions, setShowInstuctions] = useState(true); + + const togglePane = (pane: string): void => { + switch (pane) { + case 'showPreviewPane': + if (!showPreviewPane && showPreviewPortal) setShowPreviewPortal(false); + setShowPreviewPane(!showPreviewPane); + portalWindow?.close(); + break; + case 'showPreviewPortal': + if (!showPreviewPortal && showPreviewPane) setShowPreviewPane(false); + setShowPreviewPortal(!showPreviewPortal); + if (showPreviewPortal) portalWindow?.close(); + break; + case 'showConsole': + setShowConsole(!showConsole); + break; + case 'showNotes': + setShowNotes(!showNotes); + break; + case 'showInstructions': + setShowInstuctions(!showInstructions); + break; + default: + setShowInstuctions(true); + setShowConsole(false); + setShowPreviewPane(true); + setShowPreviewPortal(false); + setShowNotes(false); + } + }; const getChallengeFile = () => { const { challengeFiles } = props; @@ -70,6 +141,8 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => { testOutput, hasNotes, hasPreview, + isAdvancing, + isFirstStep, layoutState, notes, preview, @@ -78,6 +151,18 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => { windowTitle } = props; + // on mount + useEffect(() => { + if (isFirstStep) { + setShowPreviewPortal(false); + portalWindow?.close(); + setShowPreviewPane(true); + } else if (!isAdvancing && !showPreviewPane && !showPreviewPortal) { + togglePane('showPreviewPane'); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + const challengeFile = getChallengeFile(); const projectBasedChallenge = hasEditableBoundaries; const displayPreviewPane = hasPreview && showPreviewPane; @@ -181,12 +266,12 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => { {displayPreviewPortal && ( { - togglePane({ - panel: DesktopLayoutPanels.PreviewPortal, - setVisible: false - }); - }} + // togglePane={() => { + // togglePane({ + // panel: DesktopLayoutPanels.PreviewPortal, + // setVisible: false + // }); + // }} windowTitle={windowTitle} > {preview} @@ -198,4 +283,4 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => { DesktopLayout.displayName = 'DesktopLayout'; -export default DesktopLayout; +export default connect(mapStateToProps, mapDispatchToProps)(DesktopLayout); diff --git a/client/src/templates/Challenges/classic/editor.css b/client/src/templates/Challenges/classic/editor.css index 0288f12dbf2269..7e70bab2ae72a7 100644 --- a/client/src/templates/Challenges/classic/editor.css +++ b/client/src/templates/Challenges/classic/editor.css @@ -66,7 +66,7 @@ textarea.inputarea { } .editor-lower-jaw { - padding: 0 15px 15px 0px; + padding: 0 15px 15px 0; } .editor-upper-jaw { @@ -81,14 +81,15 @@ textarea.inputarea { .challenge-description-header { display: flex; + gap: 7px; } .description-container h1 { font-family: 'Hack-ZeroSlash', monospace; font-size: 0.889rem; font-weight: 700; - line-height: 1; - margin: 0 0 0.6rem; + line-height: 1.1; + margin: 0.1em 0 0.6rem; display: flex; align-items: center; @@ -129,8 +130,7 @@ textarea.inputarea { .myEditableLineDecoration { background-color: var(--tc-blue-140); width: 15px !important; - margin-left: 5px !important; - margin-right: 5px !important; + margin-inline: 5px !important; } .myEditableLineDecoration.tests-passed { @@ -233,5 +233,5 @@ textarea.inputarea { } .lower-jaw-icon-bar > button:last-child { - margin-right: 0; + margin-inline-end: 0; } diff --git a/client/src/templates/Challenges/classic/editor.tsx b/client/src/templates/Challenges/classic/editor.tsx index 49b49cf851de73..590ddc4ccc1bbe 100644 --- a/client/src/templates/Challenges/classic/editor.tsx +++ b/client/src/templates/Challenges/classic/editor.tsx @@ -7,6 +7,7 @@ import type { editor // eslint-disable-next-line import/no-duplicates } from 'monaco-editor/esm/vs/editor/editor.api'; +import { OS } from 'monaco-editor/esm/vs/base/common/platform.js'; import Prism from 'prismjs'; import React, { useEffect, @@ -74,7 +75,6 @@ import LowerJaw from './lower-jaw'; import './editor.css'; -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call const MonacoEditor = Loadable(() => import('react-monaco-editor')); const currentYear = new Date().getFullYear(); @@ -275,7 +275,6 @@ const Editor = (props: EditorProps): JSX.Element => { noteIndex: number; shouldPlay: boolean | undefined; }>({ - // eslint-disable-next-line no-undefined sampler: undefined, noteIndex: 0, shouldPlay: store.get('fcc-sound') as boolean | undefined @@ -384,6 +383,14 @@ const Editor = (props: EditorProps): JSX.Element => { } }; + const isTabTrapped = () => !!(store.get('monacoTabTrapped') ?? true); + + // Monaco uses the contextKey 'editorTabMovesFocus' to control how it + // reacts to the Tab key. Setting it to true allows the user to tab + // out of the editor. False keeps it inside the editor and creates a tab. + const setMonacoTabTrapped = (trapped: boolean) => + dataRef.current.editor?.createContextKey('editorTabMovesFocus', !trapped); + const editorDidMount = ( editor: editor.IStandaloneCodeEditor, monaco: typeof monacoEditor @@ -417,6 +424,24 @@ const Editor = (props: EditorProps): JSX.Element => { return accessibility; }; + const setTabTrapped = (trapped: boolean) => { + setMonacoTabTrapped(trapped); + store.set('monacoTabTrapped', trapped); + ariaAlert( + `${ + trapped + ? t('learn.editor-alerts.tab-trapped') + : t('learn.editor-alerts.tab-free') + }` + ); + }; + + // By default, Tab will be trapped in the monaco editor, so we only need to + // check if the user has turned this off. + if (!isTabTrapped()) { + setTabTrapped(false); + } + const accessibilityMode = storedAccessibilityMode(); editor.updateOptions({ accessibilitySupport: accessibilityMode ? 'on' : 'auto' @@ -462,11 +487,23 @@ const Editor = (props: EditorProps): JSX.Element => { null, () => {} ); + // Make toggle tab setting in editor permanent + const tabFocusHotkeys = + OS === 2 /* Macintosh/iOS */ + ? monaco.KeyMod.WinCtrl | monaco.KeyMod.Shift | monaco.KeyCode.KEY_M + : monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_M; + // @ts-ignore + editor._standaloneKeybindingService.addDynamicKeybinding( + 'editor.action.toggleTabFocusMode', + tabFocusHotkeys, + () => { + setTabTrapped(!isTabTrapped()); + } + ); /* eslint-enable */ editor.addAction({ id: 'execute-challenge', label: 'Run tests', - /* eslint-disable no-bitwise */ keybindings: [ monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, monaco.KeyMod.WinCtrl | monaco.KeyCode.Enter @@ -709,14 +746,7 @@ const Editor = (props: EditorProps): JSX.Element => { )}`; jawHeading.appendChild(challengeTitle); const checkmark = ReactDOMServer.renderToStaticMarkup( - + ); const completedChallengeHeader = document.createElement('div'); completedChallengeHeader.innerHTML = checkmark; @@ -803,12 +833,9 @@ const Editor = (props: EditorProps): JSX.Element => { // has changed or if content is dragged between regions) const coveringRange = getLinesCoveringEditableRegion(); - const editableRegionBoundaries = - (coveringRange && [ - coveringRange.startLineNumber - 1, - coveringRange.endLineNumber + 1 - ]) ?? - undefined; + const editableRegionBoundaries = coveringRange + ? [coveringRange.startLineNumber - 1, coveringRange.endLineNumber + 1] + : []; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (player.current.sampler?.loaded && player.current.shouldPlay) { @@ -1051,7 +1078,6 @@ const Editor = (props: EditorProps): JSX.Element => { updateEditableRegion(coveringRange, { model }); } }; - // If the content has changed, the zones may need moving. Rather than // working out if they have to for a particular content change, we simply // ask monaco to update regardless. @@ -1184,6 +1210,11 @@ const Editor = (props: EditorProps): JSX.Element => { useEffect(() => { const editor = dataRef.current.editor; editor?.layout(); + // layout() resets the monaco tab trapping back to default (true), so we + // need to untrap it if the user had it set to false. + if (!isTabTrapped()) { + setMonacoTabTrapped(false); + } if (hasEditableRegion()) { updateDescriptionZone(); updateOutputZone(); @@ -1199,10 +1230,15 @@ const Editor = (props: EditorProps): JSX.Element => { }); } - const { theme } = props; - const editorTheme = theme === Themes.Night ? 'vs-dark-custom' : 'vs-custom'; + const { isSignedIn, theme } = props; + const preferDarkScheme = window.matchMedia( + '(prefers-color-scheme: dark)' + ).matches; + const isDarkTheme = + theme === Themes.Night || (preferDarkScheme && !isSignedIn); + const editorTheme = isDarkTheme ? 'vs-dark-custom' : 'vs-custom'; return ( - }> + }> { currentTab: this.props.hasEditableBoundaries ? Tab.Editor : Tab.Instructions }; - switchTab = (tab: Tab) => { + switchTab = (tab: Tab): void => { this.setState({ currentTab: tab }); }; - handleKeyDown = () => this.props.updateUsingKeyboardInTablist(true); + handleKeyDown = (): void => this.props.updateUsingKeyboardInTablist(true); - handleClick = () => this.props.updateUsingKeyboardInTablist(false); + handleClick = (): void => this.props.updateUsingKeyboardInTablist(false); - render() { + render(): JSX.Element { const { currentTab } = this.state; const { hasEditableBoundaries, diff --git a/client/src/templates/Challenges/classic/show.tsx b/client/src/templates/Challenges/classic/show.tsx index 5acbb1cc6c9924..06b9292c862ee7 100644 --- a/client/src/templates/Challenges/classic/show.tsx +++ b/client/src/templates/Challenges/classic/show.tsx @@ -43,7 +43,8 @@ import { previewMounted, updateChallengeMeta, openModal, - setEditorFocusability + setEditorFocusability, + setIsAdvancing } from '../redux/actions'; import { visibleEditorsSelector, @@ -89,7 +90,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => cancelTests, previewMounted, openModal, - setEditorFocusability + setEditorFocusability, + setIsAdvancing }, dispatch ); @@ -119,6 +121,7 @@ interface ShowClassicProps { updateChallengeMeta: (arg0: ChallengeMeta) => void; openModal: (modal: string) => void; setEditorFocusability: (canFocus: boolean) => void; + setIsAdvancing: (arg: boolean) => void; previewMounted: () => void; savedChallenges: CompletedChallenge[]; visibleEditors: VisibleEditors; @@ -300,6 +303,7 @@ class ShowClassic extends Component { initTests, updateChallengeMeta, openModal, + setIsAdvancing, savedChallenges, data: { challengeNode: { @@ -335,6 +339,7 @@ class ShowClassic extends Component { helpCategory }); challengeMounted(challengeMeta.id); + setIsAdvancing(false); } componentWillUnmount() { @@ -481,7 +486,8 @@ class ShowClassic extends Component { const { executeChallenge, pageContext: { - challengeMeta: { nextChallengePath, prevChallengePath } + challengeMeta: { isFirstStep, nextChallengePath, prevChallengePath }, + projectPreview: { challengeData, showProjectPreview } }, challengeFiles, visibleEditors, @@ -543,6 +549,7 @@ class ShowClassic extends Component { instructions={this.renderInstructionsPanel({ showToolPanel: true })} + isFirstStep={isFirstStep} layoutState={this.state.layout} notes={this.renderNotes(notes)} preview={this.renderPreview()} diff --git a/client/src/templates/Challenges/codeally/codeally.css b/client/src/templates/Challenges/codeally/codeally.css index 87db255121618e..37cebb6822b0f8 100644 --- a/client/src/templates/Challenges/codeally/codeally.css +++ b/client/src/templates/Challenges/codeally/codeally.css @@ -2,14 +2,6 @@ font-family: 'Lato', sans-serif; } -.ca-btn-padding { - padding: 0 15px; -} - -.ca-btn-padding button { +button[aria-described-by='codeally-cookie-warning'] { font-size: 1.1rem; } - -.ca-btn-margin { - margin-bottom: 5px; -} diff --git a/client/src/templates/Challenges/codeally/show.tsx b/client/src/templates/Challenges/codeally/show.tsx index 8b27e8cab2d1e4..bfa95dab6ab152 100644 --- a/client/src/templates/Challenges/codeally/show.tsx +++ b/client/src/templates/Challenges/codeally/show.tsx @@ -229,9 +229,6 @@ class ShowCodeAlly extends Component { challenge => challenge.id === challengeId ); - const breadcrumbs = document.querySelector('.breadcrumbs-demo'); - showCodeAlly && breadcrumbs?.remove(); - return showCodeAlly ? ( @@ -239,7 +236,6 @@ class ShowCodeAlly extends Component { className='codeally-frame' data-cy='codeally-frame' name={`codeAlly${Date.now()}`} - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions sandbox='allow-modals allow-forms allow-popups allow-scripts allow-same-origin' src={`https://codeally.io/embed/?repoUrl=${url}&${goBackTo}&${envVariables}&${tempToken}&${date}`} title='Editor' @@ -293,7 +289,7 @@ class ShowCodeAlly extends Component { style={{ height: '15px', width: '15px', - marginLeft: '7px' + marginInlineEnd: '7px' }} /> )} @@ -306,29 +302,20 @@ class ShowCodeAlly extends Component { )} - + {challengeType === challengeTypes.codeAllyCert + ? t('buttons.click-start-project') + : t('buttons.click-start-course')} + {isSignedIn && challengeType === challengeTypes.codeAllyCert && ( <> @@ -340,7 +327,7 @@ class ShowCodeAlly extends Component { style={{ height: '15px', width: '15px', - marginLeft: '7px' + marginInlineStart: '7px' }} /> )} diff --git a/client/src/templates/Challenges/components/Hotkeys.tsx b/client/src/templates/Challenges/components/Hotkeys.tsx index 5bc514b96e7f70..761ba839af557b 100644 --- a/client/src/templates/Challenges/components/Hotkeys.tsx +++ b/client/src/templates/Challenges/components/Hotkeys.tsx @@ -4,12 +4,14 @@ import { HotKeys, GlobalHotKeys } from 'react-hotkeys'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { ChallengeFiles, Test, User } from '../../../redux/prop-types'; +import { isChallenge } from '../../../utils/path-parsers'; import { userSelector } from '../../../redux/selectors'; import { setEditorFocusability, submitChallenge, - openModal + openModal, + setIsAdvancing } from '../redux/actions'; import { canFocusEditorSelector, @@ -40,7 +42,8 @@ const mapStateToProps = createSelector( const mapDispatchToProps = { setEditorFocusability, submitChallenge, - openShortcutsModal: () => openModal('shortcuts') + openShortcutsModal: () => openModal('shortcuts'), + setIsAdvancing }; const keyMap = { @@ -66,6 +69,7 @@ interface HotkeysProps { nextChallengePath: string; prevChallengePath: string; setEditorFocusability: (arg0: boolean) => void; + setIsAdvancing: (arg0: boolean) => void; tests: Test[]; usesMultifileEditor?: boolean; openShortcutsModal: () => void; @@ -83,6 +87,7 @@ function Hotkeys({ nextChallengePath, prevChallengePath, setEditorFocusability, + setIsAdvancing, submitChallenge, tests, usesMultifileEditor, @@ -130,10 +135,16 @@ function Hotkeys({ }, navigationMode: () => setEditorFocusability(false), navigatePrev: () => { - if (!canFocusEditor) void navigate(prevChallengePath); + if (!canFocusEditor) { + if (isChallenge(prevChallengePath)) setIsAdvancing(true); + void navigate(prevChallengePath); + } }, navigateNext: () => { - if (!canFocusEditor) void navigate(nextChallengePath); + if (!canFocusEditor) { + if (isChallenge(nextChallengePath)) setIsAdvancing(true); + void navigate(nextChallengePath); + } }, showShortcuts: (e: React.KeyboardEvent) => { if (!canFocusEditor && e.shiftKey && e.key === '?') { diff --git a/client/src/templates/Challenges/components/ResetModal.tsx b/client/src/templates/Challenges/components/ResetModal.tsx index 80db75daeb71cc..c0ec30d9223c85 100644 --- a/client/src/templates/Challenges/components/ResetModal.tsx +++ b/client/src/templates/Challenges/components/ResetModal.tsx @@ -48,7 +48,7 @@ function withActions(...fns: Array<() => void>) { function ResetModal({ reset, close, isOpen }: ResetModalProps): JSX.Element { const { t } = useTranslation(); if (isOpen) { - executeGA({ type: 'modal', data: '/reset-modal' }); + executeGA({ event: 'pageview', pagePath: '/reset-modal' }); } return ( project.id === currentChallengeId ); }); + return ( <>
    @@ -130,7 +131,7 @@ export class CompletionModalBody extends PureComponent<
    - {isCertificationProject && ( + {isCertificationProject && totalChallengesInBlock > 0 && ( {t('learn.project-complete', { completedChallengesInBlock, diff --git a/client/src/templates/Challenges/components/completion-modal.css b/client/src/templates/Challenges/components/completion-modal.css index bd4ee5bda34f89..b62125c860b6df 100644 --- a/client/src/templates/Challenges/components/completion-modal.css +++ b/client/src/templates/Challenges/components/completion-modal.css @@ -16,7 +16,7 @@ display: flex; flex-direction: column; justify-content: space-evenly; - padding-left: 30px; + padding-inline-start: 30px; } .completion-challenge-details { diff --git a/client/src/templates/Challenges/components/completion-modal.test.tsx b/client/src/templates/Challenges/components/completion-modal.test.tsx index 19aeb5efdccd7e..7d151bd0588dbe 100644 --- a/client/src/templates/Challenges/components/completion-modal.test.tsx +++ b/client/src/templates/Challenges/components/completion-modal.test.tsx @@ -1,4 +1,4 @@ -import { getCompletedPercent } from './completion-modal'; +import { getCompletedPercentage } from '../../../utils/get-completion-percentage'; jest.mock('../../../analytics'); @@ -8,16 +8,16 @@ const completedChallengesIds = ['1', '3', '5'], fakeCompletedChallengesIds = ['1', '3', '5', '7', '8']; describe('', () => { - describe('getCompletedPercent', () => { + describe('getCompletedPercentage', () => { it('returns 25 if one out of four challenges are complete', () => { - expect(getCompletedPercent([], currentBlockIds, currentBlockIds[1])).toBe( - 25 - ); + expect( + getCompletedPercentage([], currentBlockIds, currentBlockIds[1]) + ).toBe(25); }); it('returns 75 if three out of four challenges are complete', () => { expect( - getCompletedPercent( + getCompletedPercentage( completedChallengesIds, currentBlockIds, completedChallengesIds[0] @@ -27,13 +27,13 @@ describe('', () => { it('returns 100 if all challenges have been completed', () => { expect( - getCompletedPercent(completedChallengesIds, currentBlockIds, id) + getCompletedPercentage(completedChallengesIds, currentBlockIds, id) ).toBe(100); }); it('returns 100 if more challenges have been complete than exist', () => { expect( - getCompletedPercent(fakeCompletedChallengesIds, currentBlockIds, id) + getCompletedPercentage(fakeCompletedChallengesIds, currentBlockIds, id) ).toBe(100); }); }); diff --git a/client/src/templates/Challenges/components/completion-modal.tsx b/client/src/templates/Challenges/components/completion-modal.tsx index 589863317fccca..dcf5ae24650431 100644 --- a/client/src/templates/Challenges/components/completion-modal.tsx +++ b/client/src/templates/Challenges/components/completion-modal.tsx @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ import { Button, Modal } from '@freecodecamp/react-bootstrap'; -import { useStaticQuery, graphql } from 'gatsby'; import { noop } from 'lodash-es'; import React, { Component } from 'react'; import { TFunction, withTranslation } from 'react-i18next'; @@ -10,19 +9,23 @@ import { Dispatch } from 'redux'; import { createSelector } from 'reselect'; import { dasherize } from '../../../../../utils/slugs'; -import { isFinalProject } from '../../../../utils/challenge-types'; import Login from '../../../components/Header/components/Login'; import { executeGA } from '../../../redux/actions'; -import { isSignedInSelector } from '../../../redux/selectors'; -import { AllChallengeNode, ChallengeFiles } from '../../../redux/prop-types'; - +import { + isSignedInSelector, + allChallengesInfoSelector +} from '../../../redux/selectors'; +import { AllChallengesInfo, ChallengeFiles } from '../../../redux/prop-types'; import { closeModal, submitChallenge } from '../redux/actions'; import { - completedChallengesIds, + completedChallengesIdsSelector, isCompletionModalOpenSelector, successMessageSelector, challengeFilesSelector, - challengeMetaSelector + challengeMetaSelector, + completedPercentageSelector, + completedChallengesInBlockSelector, + currentBlockIdsSelector } from '../redux/selectors'; import CompletionModalBody from './completion-modal-body'; @@ -31,10 +34,14 @@ import './completion-modal.css'; const mapStateToProps = createSelector( challengeFilesSelector, challengeMetaSelector, - completedChallengesIds, + completedChallengesIdsSelector, isCompletionModalOpenSelector, isSignedInSelector, + allChallengesInfoSelector, successMessageSelector, + completedPercentageSelector, + completedChallengesInBlockSelector, + currentBlockIdsSelector, ( challengeFiles: ChallengeFiles, { @@ -45,7 +52,11 @@ const mapStateToProps = createSelector( completedChallengesIds: string[], isOpen: boolean, isSignedIn: boolean, - message: string + allChallengesInfo: AllChallengesInfo, + message: string, + completedPercent: number, + completedChallengesInBlock: number, + currentBlockIds: string[] ) => ({ challengeFiles, title, @@ -54,7 +65,11 @@ const mapStateToProps = createSelector( completedChallengesIds, isOpen, isSignedIn, - message + allChallengesInfo, + message, + completedPercent, + completedChallengesInBlock, + currentBlockIds }) ); @@ -69,38 +84,6 @@ const mapDispatchToProps = function (dispatch: Dispatch) { return () => dispatchers; }; -export function getCompletedPercent( - completedChallengesIds: string[] = [], - currentBlockIds: string[] = [], - currentChallengeId: string -): number { - const completedChallengesInBlock = getCompletedChallengesInBlock( - completedChallengesIds, - currentBlockIds, - currentChallengeId - ); - const completedPercent = Math.round( - (completedChallengesInBlock / currentBlockIds.length) * 100 - ); - - return completedPercent > 100 ? 100 : completedPercent; -} - -function getCompletedChallengesInBlock( - completedChallengesIds: string[], - currentBlockChallengeIds: string[], - currentChallengeId: string -) { - const oldCompletionCount = completedChallengesIds.filter(challengeId => - currentBlockChallengeIds.includes(challengeId) - ).length; - - const isAlreadyCompleted = - completedChallengesIds.includes(currentChallengeId); - - return isAlreadyCompleted ? oldCompletionCount : oldCompletionCount + 1; -} - interface CompletionModalsProps { block: string; blockName: string; @@ -108,51 +91,47 @@ interface CompletionModalsProps { challengeType: number; close: () => void; completedChallengesIds: string[]; - currentBlockIds?: string[]; executeGA: () => void; challengeFiles: ChallengeFiles; id: string; isOpen: boolean; isSignedIn: boolean; + allChallengesInfo: AllChallengesInfo; message: string; + completedPercent: number; + completedChallengesInBlock: number; + currentBlockIds: string[]; submitChallenge: () => void; superBlock: string; t: TFunction; title: string; } -interface CompletionModalInnerState { +interface CompletionModalState { downloadURL: null | string; - completedPercent: number; - completedChallengesInBlock: number; } -export class CompletionModalInner extends Component< +class CompletionModal extends Component< CompletionModalsProps, - CompletionModalInnerState + CompletionModalState > { + static displayName: string; constructor(props: CompletionModalsProps) { super(props); - this.handleSubmit = this.handleSubmit.bind(this); this.handleKeypress = this.handleKeypress.bind(this); - this.state = { - downloadURL: null, - completedPercent: 0, - completedChallengesInBlock: 0 + downloadURL: null }; } static getDerivedStateFromProps( - props: CompletionModalsProps, - state: CompletionModalInnerState - ): CompletionModalInnerState { + props: Readonly, + state: CompletionModalState + ): CompletionModalState { const { challengeFiles, isOpen } = props; if (!isOpen) { return { - downloadURL: null, - completedPercent: 0, - completedChallengesInBlock: 0 + downloadURL: null }; } const { downloadURL } = state; @@ -177,25 +156,8 @@ export class CompletionModalInner extends Component< }); newURL = URL.createObjectURL(blob); } - - const { completedChallengesIds, currentBlockIds, id, isSignedIn } = props; - const completedPercent = isSignedIn - ? getCompletedPercent(completedChallengesIds, currentBlockIds, id) - : 0; - - let completedChallengesInBlock = 0; - if (currentBlockIds) { - completedChallengesInBlock = getCompletedChallengesInBlock( - completedChallengesIds, - currentBlockIds, - id - ); - } - return { - downloadURL: newURL, - completedPercent, - completedChallengesInBlock + downloadURL: newURL }; } @@ -205,14 +167,10 @@ export class CompletionModalInner extends Component< // Since Hotkeys also listens to Ctrl + Enter we have to stop this event // getting to it. e.stopPropagation(); - this.handleSubmit(); + this.props.submitChallenge(); } } - handleSubmit(): void { - this.props.submitChallenge(); - } - componentWillUnmount(): void { if (this.state.downloadURL) { URL.revokeObjectURL(this.state.downloadURL); @@ -224,22 +182,23 @@ export class CompletionModalInner extends Component< const { block, close, - currentBlockIds, id, isOpen, isSignedIn, message, superBlock = '', t, - title + title, + completedPercent, + completedChallengesInBlock, + currentBlockIds, + submitChallenge } = this.props; - const { completedPercent, completedChallengesInBlock } = this.state; - - const totalChallengesInBlock = currentBlockIds?.length ?? 0; + const totalChallengesInBlock = currentBlockIds.length; if (isOpen) { - executeGA({ type: 'modal', data: '/completion-modal' }); + executeGA({ event: 'pageview', pagePath: '/completion-modal' }); } // normally dashedName should be graphQL queried and then passed around, // but it's only used to make a nice filename for downloading, so dasherize @@ -282,7 +241,7 @@ export class CompletionModalInner extends Component< block={true} bsSize='large' bsStyle='primary' - onClick={() => this.handleSubmit()} + onClick={() => submitChallenge()} > {isSignedIn ? t('buttons.submit-and-go') : t('buttons.go-to-next')} (Ctrl + Enter) @@ -305,84 +264,6 @@ export class CompletionModalInner extends Component< } } -interface Options { - isFinalProjectBlock: boolean; -} - -interface CertificateNode { - challenge: { - // TODO: use enum - certification: string; - tests: { id: string }[]; - }; -} - -const useCurrentBlockIds = ( - block: string, - certification: string, - options?: Options -) => { - const { - allChallengeNode: { edges: challengeEdges }, - allCertificateNode: { nodes: certificateNodes } - }: { - allChallengeNode: AllChallengeNode; - allCertificateNode: { nodes: CertificateNode[] }; - } = useStaticQuery(graphql` - query getCurrentBlockNodes { - allChallengeNode( - sort: { - fields: [ - challenge___superOrder - challenge___order - challenge___challengeOrder - ] - } - ) { - edges { - node { - challenge { - block - id - } - } - } - } - allCertificateNode { - nodes { - challenge { - certification - tests { - id - } - } - } - } - } - `); - - const currentCertificateIds = certificateNodes - .filter( - node => dasherize(node.challenge.certification) === certification - )[0] - ?.challenge.tests.map(test => test.id); - const currentBlockIds = challengeEdges - .filter(edge => edge.node.challenge.block === block) - .map(edge => edge.node.challenge.id); - - return options?.isFinalProjectBlock ? currentCertificateIds : currentBlockIds; -}; - -const CompletionModal = (props: CompletionModalsProps) => { - const currentBlockIds = useCurrentBlockIds( - props.block || '', - props.certification || '', - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - { isFinalProjectBlock: isFinalProject(props.challengeType) } - ); - return ; -}; - CompletionModal.displayName = 'CompletionModal'; export default connect( diff --git a/client/src/templates/Challenges/components/help-modal.tsx b/client/src/templates/Challenges/components/help-modal.tsx index 66ed57101aa088..15cd27ea7ff1b9 100644 --- a/client/src/templates/Challenges/components/help-modal.tsx +++ b/client/src/templates/Challenges/components/help-modal.tsx @@ -16,7 +16,7 @@ import './help-modal.css'; interface HelpModalProps { closeHelpModal: () => void; createQuestion: () => void; - executeGA: (attributes: { type: string; data: string }) => void; + executeGA: (attributes: { event: string; pagePath: string }) => void; isOpen?: boolean; t: (text: string) => string; challengeTitle: string; @@ -44,7 +44,7 @@ const generateSearchLink = (title: string, block: string) => { return search; }; -export function HelpModal({ +function HelpModal({ closeHelpModal, createQuestion, executeGA, @@ -54,7 +54,7 @@ export function HelpModal({ challengeTitle }: HelpModalProps): JSX.Element { if (isOpen) { - executeGA({ type: 'modal', data: '/help-modal' }); + executeGA({ event: 'pageview', pagePath: '/help-modal' }); } return ( diff --git a/client/src/templates/Challenges/components/preview-portal.tsx b/client/src/templates/Challenges/components/preview-portal.tsx index 4710cf0dc8e16e..366fa68cff28bb 100644 --- a/client/src/templates/Challenges/components/preview-portal.tsx +++ b/client/src/templates/Challenges/components/preview-portal.tsx @@ -2,35 +2,60 @@ import { Component, ReactElement } from 'react'; import ReactDOM from 'react-dom'; import { TFunction, withTranslation } from 'react-i18next'; import { connect } from 'react-redux'; -import { storePortalDocument, removePortalDocument } from '../redux/actions'; +import { createSelector } from 'reselect'; +import { + storePortalWindow, + removePortalWindow, + setShowPreviewPortal, + setIsAdvancing +} from '../redux/actions'; +import { + portalWindowSelector, + isAdvancingToChallengeSelector +} from '../redux/selectors'; interface PreviewPortalProps { children: ReactElement | null; - togglePane: (pane: string) => void; windowTitle: string; t: TFunction; - storePortalDocument: (document: Document | undefined) => void; - removePortalDocument: () => void; + storePortalWindow: (window: Window | null) => void; + removePortalWindow: () => void; + portalWindow: null | Window; + setShowPreviewPortal: (arg: boolean) => void; + setIsAdvancing: (arg: boolean) => void; + isAdvancing: boolean; } const mapDispatchToProps = { - storePortalDocument, - removePortalDocument + storePortalWindow, + removePortalWindow, + setShowPreviewPortal, + setIsAdvancing }; +const mapStateToProps = createSelector( + isAdvancingToChallengeSelector, + portalWindowSelector, + (isAdvancing: boolean, portalWindow: null | Window) => ({ + isAdvancing, + portalWindow + }) +); + class PreviewPortal extends Component { static displayName = 'PreviewPortal'; mainWindow: Window; externalWindow: Window | null = null; + isAdvancing: boolean; containerEl; titleEl; styleEl; constructor(props: PreviewPortalProps) { super(props); - this.mainWindow = window; - this.externalWindow = null; + this.externalWindow = this.props.portalWindow; + this.isAdvancing = this.props.isAdvancing; this.containerEl = document.createElement('div'); this.titleEl = document.createElement('title'); this.styleEl = document.createElement('style'); @@ -39,6 +64,17 @@ class PreviewPortal extends Component { componentDidMount() { const { t, windowTitle } = this.props; + if (!this.externalWindow) { + this.externalWindow = window.open( + '', + '', + 'width=960,height=540,left=100,top=100' + ); + } else { + this.externalWindow.document.head.innerHTML = ''; + this.externalWindow.document.body.innerHTML = ''; + } + this.titleEl.innerText = `${t( 'learn.editor-tabs.preview' )} | ${windowTitle}`; @@ -51,12 +87,6 @@ class PreviewPortal extends Component { } `; - this.externalWindow = window.open( - '', - '', - 'width=960,height=540,left=100,top=100' - ); - this.externalWindow?.document.head.appendChild(this.titleEl); this.externalWindow?.document.head.appendChild(this.styleEl); this.externalWindow?.document.body.setAttribute( @@ -69,19 +99,23 @@ class PreviewPortal extends Component { ); this.externalWindow?.document.body.appendChild(this.containerEl); this.externalWindow?.addEventListener('beforeunload', () => { - this.props.togglePane('showPreviewPortal'); + this.props.setShowPreviewPortal(false); }); - this.props.storePortalDocument(this.externalWindow?.document); + this.props.storePortalWindow(this.externalWindow); + // close the portal if the main window closes this.mainWindow?.addEventListener('beforeunload', () => { this.externalWindow?.close(); }); } componentWillUnmount() { - this.externalWindow?.close(); - this.props.removePortalDocument(); + if (!this.props.isAdvancing) { + this.externalWindow?.close(); + } + this.props.removePortalWindow(); + this.props.setIsAdvancing(false); } render() { @@ -92,6 +126,6 @@ class PreviewPortal extends Component { PreviewPortal.displayName = 'PreviewPortal'; export default connect( - null, + mapStateToProps, mapDispatchToProps )(withTranslation()(PreviewPortal)); diff --git a/client/src/templates/Challenges/components/shortcuts-modal.tsx b/client/src/templates/Challenges/components/shortcuts-modal.tsx index 629a59adff0117..6d882f026444a3 100644 --- a/client/src/templates/Challenges/components/shortcuts-modal.tsx +++ b/client/src/templates/Challenges/components/shortcuts-modal.tsx @@ -37,7 +37,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => dispatch ); -export function ShortcutsModal({ +function ShortcutsModal({ closeShortcutsModal, toggleKeyboardShortcuts, isOpen, diff --git a/client/src/templates/Challenges/components/side-panel.css b/client/src/templates/Challenges/components/side-panel.css index 4e15f7c07015fd..e0347eaaebad5c 100644 --- a/client/src/templates/Challenges/components/side-panel.css +++ b/client/src/templates/Challenges/components/side-panel.css @@ -59,3 +59,9 @@ background: var(--tc-black-5); border-radius: 4px; } + +/* MERGE */ +#mobile-layout-pane-instructions > .instructions-panel { + height: auto; + overflow-y: none; +} diff --git a/client/src/templates/Challenges/components/test-suite.css b/client/src/templates/Challenges/components/test-suite.css index 20753a5aed13ab..51c0151deb92f6 100644 --- a/client/src/templates/Challenges/components/test-suite.css +++ b/client/src/templates/Challenges/components/test-suite.css @@ -4,7 +4,7 @@ flex-direction: column; margin: 6px 0 16px; margin: 15px 0; - padding-left: 0; + padding-inline-start: 0; } .challenge-test-suite-heading { diff --git a/client/src/templates/Challenges/components/tool-panel.tsx b/client/src/templates/Challenges/components/tool-panel.tsx index a07cf61498dc15..412ec93096e568 100644 --- a/client/src/templates/Challenges/components/tool-panel.tsx +++ b/client/src/templates/Challenges/components/tool-panel.tsx @@ -108,8 +108,13 @@ function ToolPanel({ )} {/* {challengeType !== challengeTypes.multifileCertProject && ( - )} */} diff --git a/client/src/templates/Challenges/components/video-modal.tsx b/client/src/templates/Challenges/components/video-modal.tsx index 1b42eeff8c8775..2ceba3ac9db6d1 100644 --- a/client/src/templates/Challenges/components/video-modal.tsx +++ b/client/src/templates/Challenges/components/video-modal.tsx @@ -12,7 +12,7 @@ import './video-modal.css'; interface VideoModalProps { closeVideoModal: () => void; - executeGA: (attributes: { type: string; data: string }) => void; + executeGA: (attributes: { event: string; pagePath: string }) => void; isOpen?: boolean; t: (attribute: string) => string; videoUrl?: string; @@ -28,7 +28,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => dispatch ); -export function VideoModal({ +function VideoModal({ closeVideoModal, executeGA, isOpen, @@ -36,7 +36,7 @@ export function VideoModal({ videoUrl }: VideoModalProps): JSX.Element { if (isOpen) { - executeGA({ type: 'modal', data: '/completion-modal' }); + executeGA({ event: 'pageview', pagePath: '/completion-modal' }); } return ( diff --git a/client/src/templates/Challenges/odin/Show.tsx b/client/src/templates/Challenges/odin/Show.tsx new file mode 100644 index 00000000000000..10e2558c9b1484 --- /dev/null +++ b/client/src/templates/Challenges/odin/Show.tsx @@ -0,0 +1,420 @@ +// Package Utilities +import { Button, Grid, Col, Row } from '@freecodecamp/react-bootstrap'; +import { graphql } from 'gatsby'; +import React, { Component } from 'react'; +import Helmet from 'react-helmet'; +import { ObserveKeys } from 'react-hotkeys'; +import { TFunction, withTranslation } from 'react-i18next'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import type { Dispatch } from 'redux'; +import { createSelector } from 'reselect'; + +// Local Utilities +import Loader from '../../../components/helpers/loader'; +import Spacer from '../../../components/helpers/spacer'; +import LearnLayout from '../../../components/layouts/learn'; +import { ChallengeNode, ChallengeMeta } from '../../../redux/prop-types'; +import Hotkeys from '../components/Hotkeys'; +import VideoPlayer from '../components/VideoPlayer'; +import CompletionModal from '../components/completion-modal'; +import PrismFormatted from '../components/prism-formatted'; +import { + challengeMounted, + updateChallengeMeta, + openModal, + updateSolutionFormValues +} from '../redux/actions'; +import { isChallengeCompletedSelector } from '../redux/selectors'; + +// Styles +import './show.css'; +import '../video.css'; + +// Redux Setup +const mapStateToProps = createSelector( + isChallengeCompletedSelector, + (isChallengeCompleted: boolean) => ({ + isChallengeCompleted + }) +); +const mapDispatchToProps = (dispatch: Dispatch) => + bindActionCreators( + { + updateChallengeMeta, + challengeMounted, + updateSolutionFormValues, + openCompletionModal: () => openModal('completion') + }, + dispatch + ); + +// Types +interface ShowOdinProps { + challengeMounted: (arg0: string) => void; + data: { challengeNode: ChallengeNode }; + description: string; + isChallengeCompleted: boolean; + openCompletionModal: () => void; + pageContext: { + challengeMeta: ChallengeMeta; + }; + t: TFunction; + updateChallengeMeta: (arg0: ChallengeMeta) => void; + updateSolutionFormValues: () => void; +} + +interface ShowOdinState { + subtitles: string; + downloadURL: string | null; + selectedOption: number | null; + answer: number; + isWrongAnswer: boolean; + assignmentsCompleted: number; + allAssignmentsCompleted: boolean; + videoIsLoaded: boolean; +} + +// Component +class ShowOdin extends Component { + static displayName: string; + private _container: HTMLElement | null | undefined; + + constructor(props: ShowOdinProps) { + super(props); + this.state = { + subtitles: '', + downloadURL: null, + selectedOption: null, + answer: 1, + isWrongAnswer: false, + assignmentsCompleted: 0, + allAssignmentsCompleted: false, + videoIsLoaded: false + }; + + this.handleSubmit = this.handleSubmit.bind(this); + } + + componentDidMount(): void { + const { + challengeMounted, + data: { + challengeNode: { + challenge: { title, challengeType, helpCategory } + } + }, + pageContext: { challengeMeta }, + updateChallengeMeta + } = this.props; + updateChallengeMeta({ + ...challengeMeta, + title, + challengeType, + helpCategory + }); + challengeMounted(challengeMeta.id); + this._container?.focus(); + } + + componentDidUpdate(prevProps: ShowOdinProps): void { + const { + data: { + challengeNode: { + challenge: { title: prevTitle } + } + } + } = prevProps; + const { + challengeMounted, + data: { + challengeNode: { + challenge: { title: currentTitle, challengeType, helpCategory } + } + }, + pageContext: { challengeMeta }, + updateChallengeMeta + } = this.props; + if (prevTitle !== currentTitle) { + updateChallengeMeta({ + ...challengeMeta, + title: currentTitle, + challengeType, + helpCategory + }); + challengeMounted(challengeMeta.id); + } + } + + handleSubmit( + solution: number, + openCompletionModal: () => void, + assignments: string[] + ) { + const hasAssignments = assignments.length > 0; + const completed = this.state.allAssignmentsCompleted; + const isCorrect = solution - 1 === this.state.selectedOption; + + if (isCorrect) { + this.setState({ + isWrongAnswer: false + }); + if (!hasAssignments || completed) openCompletionModal(); + } else { + this.setState({ + isWrongAnswer: true + }); + } + } + + handleOptionChange = ( + changeEvent: React.ChangeEvent + ): void => { + this.setState({ + isWrongAnswer: false, + selectedOption: parseInt(changeEvent.target.value, 10) + }); + }; + + handleAssignmentChange = ( + event: React.ChangeEvent, + totalAssignments: number + ): void => { + const assignmentsCompleted = event.target.checked + ? this.state.assignmentsCompleted + 1 + : this.state.assignmentsCompleted - 1; + const allAssignmentsCompleted = totalAssignments === assignmentsCompleted; + + this.setState({ + assignmentsCompleted, + allAssignmentsCompleted + }); + }; + + onVideoLoad = () => { + this.setState({ + videoIsLoaded: true + }); + }; + + render() { + const { + data: { + challengeNode: { + challenge: { + fields: { blockName }, + title, + description, + superBlock, + certification, + block, + videoId, + videoLocaleIds, + bilibiliIds, + question: { text, answers, solution }, + assignments + } + } + }, + openCompletionModal, + pageContext: { + challengeMeta: { nextChallengePath, prevChallengePath } + }, + t + } = this.props; + + const blockNameTitle = `${t( + `intro:${superBlock}.blocks.${block}.title` + )} - ${title}`; + return ( + { + this.handleSubmit(solution, openCompletionModal, assignments); + }} + innerRef={(c: HTMLElement | null) => (this._container = c)} + nextChallengePath={nextChallengePath} + prevChallengePath={prevChallengePath} + > + + + + + {videoId && ( +
    + +
    + {!this.state.videoIsLoaded ? ( +
    + +
    + ) : null} + +
    + + )} +
    + +

    {title}

    + + + + {assignments.length > 0 && ( + <> +

    {t('learn.assignments')}

    +
    + {assignments.map((assignment, index) => ( + + ))} +
    {' '} + + + )} + +

    {t('learn.question')}

    + +
    + {answers.map((option, index) => ( + + ))} +
    +
    + +
    + {this.state.isWrongAnswer && ( + {t('learn.wrong-answer')} + )} + {!this.state.allAssignmentsCompleted && + assignments.length > 0 && ( + <> +
    + {t('learn.assignment-not-complete')} + + )} +
    + + + + + + + + + + ); + } +} + +ShowOdin.displayName = 'ShowOdin'; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(withTranslation()(ShowOdin)); + +export const query = graphql` + query TheOdinProject($slug: String!) { + challengeNode(challenge: { fields: { slug: { eq: $slug } } }) { + challenge { + videoId + videoLocaleIds { + espanol + italian + portuguese + } + bilibiliIds { + aid + bvid + cid + } + title + description + challengeType + helpCategory + superBlock + certification + block + fields { + blockName + slug + } + question { + text + answers + solution + } + translationPending + assignments + } + } + } +`; diff --git a/client/src/templates/Challenges/odin/show.css b/client/src/templates/Challenges/odin/show.css new file mode 100644 index 00000000000000..8db116b549910a --- /dev/null +++ b/client/src/templates/Challenges/odin/show.css @@ -0,0 +1,28 @@ +input[type='checkbox'] { + display: grid; + place-content: center; + -webkit-appearance: none; + appearance: none; + background-color: #fff; + min-width: 1.15em; + min-height: 1.15em; + max-width: 1.15em; + max-height: 1.15em; + margin-inline-end: 15px; + border: 2px solid black; + border-radius: 0.15em; + transform: translateY(-0.075em); +} + +input[type='checkbox']::before { + content: ''; + width: 0.65em; + height: 0.65em; + transform: scale(0); + transition: 120ms transform ease-in-out; + box-shadow: inset 1em 1em black; +} + +input[type='checkbox']:checked::before { + transform: scale(1); +} diff --git a/client/src/templates/Challenges/projects/backend/Show.tsx b/client/src/templates/Challenges/projects/backend/Show.tsx index 6738baeb983a20..2ce24b84c04a9f 100644 --- a/client/src/templates/Challenges/projects/backend/Show.tsx +++ b/client/src/templates/Challenges/projects/backend/Show.tsx @@ -6,7 +6,8 @@ import { Col, Grid, Row } from '@freecodecamp/react-bootstrap'; import { graphql } from 'gatsby'; import React, { Component } from 'react'; import Helmet from 'react-helmet'; -import { TFunction, withTranslation } from 'react-i18next'; +import { withTranslation } from 'react-i18next'; +import type { TFunction } from 'i18next'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; diff --git a/client/src/templates/Challenges/projects/solution-form.tsx b/client/src/templates/Challenges/projects/solution-form.tsx index 0f7a5cc1afda9b..19d554b052541a 100644 --- a/client/src/templates/Challenges/projects/solution-form.tsx +++ b/client/src/templates/Challenges/projects/solution-form.tsx @@ -9,13 +9,16 @@ import { frontEndProject, pythonProject } from '../../../../utils/challenge-types'; -import { Form, ValidatedValues } from '../../../components/formHelpers'; +import { + StrictSolutionForm, + ValidatedValues +} from '../../../components/formHelpers/form'; interface SubmitProps { completed: boolean; } -interface FormProps extends WithTranslation { +interface SolutionFormProps extends WithTranslation { buttonLabel?: string; challengeType: number; description?: string; @@ -23,8 +26,8 @@ interface FormProps extends WithTranslation { updateSolutionForm: (arg0: Record) => void; } -export class SolutionForm extends Component { - constructor(props: FormProps) { +export class SolutionForm extends Component { + constructor(props: SolutionFormProps) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } @@ -116,7 +119,7 @@ export class SolutionForm extends Component { } return ( -
    ({}); const mapDispatchToProps = (dispatch: Dispatch) => @@ -24,13 +22,13 @@ interface ToolPanelProps { t: TFunction; } -export function ToolPanel({ +function ToolPanel({ guideUrl, openHelpModal, t }: ToolPanelProps): JSX.Element { return ( -
    + <> {guideUrl && ( -
    + ); } diff --git a/client/src/templates/Challenges/rechallenge/builders.ts b/client/src/templates/Challenges/rechallenge/builders.ts index 9b0fd91f86e26b..f174c79acb9f78 100644 --- a/client/src/templates/Challenges/rechallenge/builders.ts +++ b/client/src/templates/Challenges/rechallenge/builders.ts @@ -10,7 +10,7 @@ export function concatHtml({ required = [], template, contents -}: ConcatHTMLOptions) { +}: ConcatHTMLOptions): string { const embedSource = template ? _template(template) : ({ source }: { source: ConcatHTMLOptions['contents'] }) => source; diff --git a/client/src/templates/Challenges/rechallenge/transformers.js b/client/src/templates/Challenges/rechallenge/transformers.js index 4abd8943a2eaaa..ddc5ba1f7c1955 100644 --- a/client/src/templates/Challenges/rechallenge/transformers.js +++ b/client/src/templates/Challenges/rechallenge/transformers.js @@ -99,9 +99,8 @@ const testJS = matchesProperty('ext', 'js'); const testJSX = matchesProperty('ext', 'jsx'); const testHTML = matchesProperty('ext', 'html'); const testHTML$JS$JSX = overSome(testHTML, testJS, testJSX); -export const testJS$JSX = overSome(testJS, testJSX); -export const replaceNBSP = cond([ +const replaceNBSP = cond([ [ testHTML$JS$JSX, partial(transformContents, contents => contents.replace(NBSPReg, ' ')) diff --git a/client/src/templates/Challenges/redux/action-types.js b/client/src/templates/Challenges/redux/action-types.js index 2082700138a0ae..62e43ef87b2d29 100644 --- a/client/src/templates/Challenges/redux/action-types.js +++ b/client/src/templates/Challenges/redux/action-types.js @@ -14,7 +14,6 @@ export const actionTypes = createTypes( 'updateConsole', 'updateChallengeMeta', 'updateFile', - 'updateJSEnabled', 'updateSolutionFormValues', 'updateSuccessMessage', 'updateTests', @@ -30,14 +29,16 @@ export const actionTypes = createTypes( 'storedCodeFound', 'noStoredCodeFound', 'saveEditorContent', - + 'setShowPreviewPane', + 'setShowPreviewPortal', 'closeModal', 'openModal', + 'setIsAdvancing', 'previewMounted', 'projectPreviewMounted', - 'storePortalDocument', - 'removePortalDocument', + 'storePortalWindow', + 'removePortalWindow', 'challengeMounted', 'checkChallenge', 'executeChallenge', diff --git a/client/src/templates/Challenges/redux/actions.js b/client/src/templates/Challenges/redux/actions.js index 1f8a5666ac0e0c..73645db188af87 100644 --- a/client/src/templates/Challenges/redux/actions.js +++ b/client/src/templates/Challenges/redux/actions.js @@ -22,7 +22,6 @@ export const createQuestion = createAction(actionTypes.createQuestion); export const initTests = createAction(actionTypes.initTests); export const updateTests = createAction(actionTypes.updateTests); export const cancelTests = createAction(actionTypes.cancelTests); - export const initConsole = createAction(actionTypes.initConsole); export const initLogs = createAction(actionTypes.initLogs); export const updateChallengeMeta = createAction( @@ -31,13 +30,16 @@ export const updateChallengeMeta = createAction( export const updateFile = createAction(actionTypes.updateFile); export const updateConsole = createAction(actionTypes.updateConsole); export const updateLogs = createAction(actionTypes.updateLogs); -export const updateJSEnabled = createAction(actionTypes.updateJSEnabled); export const updateSolutionFormValues = createAction( actionTypes.updateSolutionFormValues ); export const updateSuccessMessage = createAction( actionTypes.updateSuccessMessage ); +export const setShowPreviewPortal = createAction( + actionTypes.setShowPreviewPortal +); +export const setShowPreviewPane = createAction(actionTypes.setShowPreviewPane); export const logsToConsole = createAction(actionTypes.logsToConsole); @@ -49,7 +51,7 @@ export const disableBuildOnError = createAction( export const storedCodeFound = createAction(actionTypes.storedCodeFound); export const noStoredCodeFound = createAction(actionTypes.noStoredCodeFound); export const saveEditorContent = createAction(actionTypes.saveEditorContent); - +export const setIsAdvancing = createAction(actionTypes.setIsAdvancing); export const closeModal = createAction(actionTypes.closeModal); export const openModal = createAction(actionTypes.openModal); @@ -58,12 +60,8 @@ export const projectPreviewMounted = createAction( actionTypes.projectPreviewMounted ); -export const storePortalDocument = createAction( - actionTypes.storePortalDocument -); -export const removePortalDocument = createAction( - actionTypes.removePortalDocument -); +export const storePortalWindow = createAction(actionTypes.storePortalWindow); +export const removePortalWindow = createAction(actionTypes.removePortalWindow); export const challengeMounted = createAction(actionTypes.challengeMounted); export const checkChallenge = createAction(actionTypes.checkChallenge); diff --git a/client/src/templates/Challenges/redux/completion-epic.js b/client/src/templates/Challenges/redux/completion-epic.js index c9a206061f7b6d..373d19f38ac260 100644 --- a/client/src/templates/Challenges/redux/completion-epic.js +++ b/client/src/templates/Challenges/redux/completion-epic.js @@ -3,7 +3,6 @@ import { omit } from 'lodash-es'; import { ofType } from 'redux-observable'; import { empty, of } from 'rxjs'; import { catchError, concat, retry, switchMap, tap } from 'rxjs/operators'; - import { challengeTypes, submitTypes } from '../../../../utils/challenge-types'; import { actionTypes as submitActionTypes } from '../../../redux/action-types'; import { @@ -20,7 +19,7 @@ import { } from '../../../utils/iframe-message'; import postUpdate$ from '../utils/post-update'; import { actionTypes } from './action-types'; -import { closeModal, updateSolutionFormValues } from './actions'; +import { updateSolutionFormValues } from './actions'; import { challengeFilesSelector, challengeMetaSelector, @@ -66,6 +65,7 @@ function submitModern(type, state) { const tests = challengeTestsSelector(state); if ( challengeType === 11 || + challengeType === 15 || (tests.length > 0 && tests.every(test => test.pass && !test.err)) ) { if (type === actionTypes.checkChallenge) { @@ -156,6 +156,7 @@ export default function completionEpic(action$, state$) { switchMap(({ type }) => { const state = state$.value; const meta = challengeMetaSelector(state); + const { nextChallengePath, challengeType, superBlock } = meta; let submitter = () => of({ type: 'no-user-signed-in' }); @@ -168,6 +169,7 @@ export default function completionEpic(action$, state$) { challengeType ); } + if (isSignedInSelector(state)) { submitter = submitters[submitTypes[challengeType]]; } @@ -177,19 +179,20 @@ export default function completionEpic(action$, state$) { }; return submitter(type, state).pipe( - tap(async res => { + tap(res => { if (res.type === submitActionTypes.updateFailed) { return; } + postChallengeCompletedEvent({ meta }); - const nextNavigatePath = await pathToNavigateTo(); + + const nextNavigatePath = pathToNavigateTo(); if (nextNavigatePath) { return navigate(nextNavigatePath); } else { postNavigationLastChallengeEvent({ meta }); } - }), - concat(of(closeModal('completion'))) + }) ); }) ); diff --git a/client/src/templates/Challenges/redux/create-question-epic.js b/client/src/templates/Challenges/redux/create-question-epic.js index e01f001147ad20..51b11eed151add 100644 --- a/client/src/templates/Challenges/redux/create-question-epic.js +++ b/client/src/templates/Challenges/redux/create-question-epic.js @@ -14,7 +14,7 @@ import { const { forumLocation } = envData; -function filesToMarkdown(challengeFiles = {}) { +function filesToMarkdown(challengeFiles = []) { const moreThanOneFile = challengeFiles?.length > 1; return challengeFiles.reduce((fileString, challengeFile) => { if (!challengeFile) { @@ -38,18 +38,46 @@ function filesToMarkdown(challengeFiles = {}) { }, '\n'); } +export function insertEditableRegions(challengeFiles = []) { + if (challengeFiles?.some(file => file.editableRegionBoundaries?.length > 0)) { + const editableRegionStrings = fileExtension => { + const startComment = fileExtension === 'html' ? '' : '*/'; + return `\n${startComment} User Editable Region ${endComment}\n`; + }; + + const filesWithEditableRegions = challengeFiles.map(file => { + const { contents, editableRegionBoundaries, ext } = file; + if (editableRegionBoundaries.length > 0) { + const comment = editableRegionStrings(ext); + const [start, end] = editableRegionBoundaries; + const lines = contents.split('\n'); + lines.splice(start, 0, comment); + lines.splice(end, 0, comment); + return { ...file, contents: lines.join('\n') }; + } + return file; + }); + return filesWithEditableRegions; + } + return challengeFiles; +} + function createQuestionEpic(action$, state$, { window }) { return action$.pipe( ofType(actionTypes.createQuestion), tap(() => { const state = state$.value; - const challengeFiles = challengeFilesSelector(state); + let challengeFiles = challengeFilesSelector(state); const { title: challengeTitle, superBlock, block, helpCategory } = challengeMetaSelector(state); + + challengeFiles = insertEditableRegions(challengeFiles); + const { navigator: { userAgent }, location: { pathname, origin } diff --git a/client/src/templates/Challenges/redux/create-question-epic.test.js b/client/src/templates/Challenges/redux/create-question-epic.test.js index 3e211b0fce896d..6572b0f1b7cd28 100644 --- a/client/src/templates/Challenges/redux/create-question-epic.test.js +++ b/client/src/templates/Challenges/redux/create-question-epic.test.js @@ -1,4 +1,5 @@ import { transformEditorLink } from '../utils'; +import { insertEditableRegions } from './create-question-epic'; describe('create-question-epic', () => { describe('transformEditorLink', () => { @@ -27,4 +28,65 @@ describe('create-question-epic', () => { }); }); }); + describe('insertEditableRegions', () => { + const multiCertChallengeFiles = [ + { + contents: '

    Hello World

    ', + ext: 'html', + fileKey: 'indexhtml', + history: ['index.html'], + head: '', + id: '', + name: 'index', + path: 'index.html', + seed: '', + tail: '' + }, + { + contents: '', + ext: 'css', + fileKey: 'stylescss', + history: ['styles.css'], + head: '', + id: '', + name: 'styles', + path: 'styles.css', + seed: '', + tail: '' + } + ]; + const multiPracticeChallengeFiles = [ + { + contents: + '\n \n

    Hello World

    \n \n', + editableRegionBoundaries: [2, 4], + ext: 'html', + fileKey: 'indexhtml', + history: ['index.html'], + head: '', + id: '', + name: 'index', + path: 'index.html', + seed: '\n \n

    Hello World

    \n \n', + tail: '' + } + ]; + it('should not insert editable regions for certification projects', () => { + const challengeFiles = insertEditableRegions(multiCertChallengeFiles); + challengeFiles.forEach(({ contents }) => { + expect(contents).not.toContain('User Editable Region'); + }); + }); + it('should insert editable regions for multifile practice projects', () => { + const challengeFiles = insertEditableRegions(multiPracticeChallengeFiles); + challengeFiles.forEach(({ contents }) => { + expect(contents).toContain('User Editable Region'); + }); + }); + it('should not throw if editableRegionBoundaries is undefined', () => { + expect(() => + insertEditableRegions(multiCertChallengeFiles) + ).not.toThrow(); + }); + }); }); diff --git a/client/src/templates/Challenges/redux/current-challenge-saga.js b/client/src/templates/Challenges/redux/current-challenge-saga.js index eb78a2f09f4018..9e07be593b7ae0 100644 --- a/client/src/templates/Challenges/redux/current-challenge-saga.js +++ b/client/src/templates/Challenges/redux/current-challenge-saga.js @@ -5,7 +5,7 @@ import { randomCompliment } from '../../../utils/get-words'; import { CURRENT_CHALLENGE_KEY } from './action-types'; import { updateSuccessMessage } from './actions'; -export function* currentChallengeSaga({ payload: id }) { +function* currentChallengeSaga({ payload: id }) { yield store.set(CURRENT_CHALLENGE_KEY, id); // // Temporarily removed to reduce calls to database // // will need to re-import things at the top @@ -26,7 +26,7 @@ export function* currentChallengeSaga({ payload: id }) { // } } -export function* updateSuccessMessageSaga() { +function* updateSuccessMessageSaga() { yield put(updateSuccessMessage(randomCompliment())); } diff --git a/client/src/templates/Challenges/redux/execute-challenge-saga.js b/client/src/templates/Challenges/redux/execute-challenge-saga.js index c3efec31cbe14c..9088ca2330595c 100644 --- a/client/src/templates/Challenges/redux/execute-challenge-saga.js +++ b/client/src/templates/Challenges/redux/execute-challenge-saga.js @@ -57,7 +57,7 @@ import { const previewTimeout = 2500; // when 'run tests' is clicked, do this first -export function* executeCancellableChallengeSaga(payload) { +function* executeCancellableChallengeSaga(payload) { const { challengeType, id } = yield select(challengeMetaSelector); const { challengeFiles } = yield select(challengeDataSelector); @@ -84,7 +84,7 @@ export function* executeCancellableChallengeSaga(payload) { yield cancel(task); } -export function* executeChallengeSaga({ payload }) { +function* executeChallengeSaga({ payload }) { const isBuildEnabled = yield select(isBuildEnabledSelector); if (!isBuildEnabled) { return; diff --git a/client/src/templates/Challenges/redux/index.js b/client/src/templates/Challenges/redux/index.js index 309e889159f704..894d3e94b11f73 100644 --- a/client/src/templates/Challenges/redux/index.js +++ b/client/src/templates/Challenges/redux/index.js @@ -44,9 +44,12 @@ const initialState = { projectPreview: false, shortcuts: false }, - portalDocument: false, + portalWindow: null, + showPreviewPortal: false, + showPreviewPane: true, projectFormValues: {}, - successMessage: 'Happy Coding!' + successMessage: 'Happy Coding!', + isAdvancing: false }; export const epics = [ @@ -187,18 +190,30 @@ export const reducer = handleActions( ...state, isBuildEnabled: false }), - [actionTypes.storePortalDocument]: (state, { payload }) => ({ + [actionTypes.setShowPreviewPortal]: (state, { payload }) => ({ ...state, - portalDocument: payload + showPreviewPortal: payload }), - [actionTypes.removePortalDocument]: state => ({ + [actionTypes.setShowPreviewPane]: (state, { payload }) => ({ ...state, - portalDocument: false + showPreviewPane: payload + }), + [actionTypes.storePortalWindow]: (state, { payload }) => ({ + ...state, + portalWindow: payload + }), + [actionTypes.removePortalWindow]: state => ({ + ...state, + portalWindow: null }), [actionTypes.updateSuccessMessage]: (state, { payload }) => ({ ...state, successMessage: payload }), + [actionTypes.setIsAdvancing]: (state, { payload }) => ({ + ...state, + isAdvancing: payload + }), [actionTypes.closeModal]: (state, { payload }) => ({ ...state, modal: { diff --git a/client/src/templates/Challenges/redux/selectors.js b/client/src/templates/Challenges/redux/selectors.js index 936f08183e2e36..f06d20ce388777 100644 --- a/client/src/templates/Challenges/redux/selectors.js +++ b/client/src/templates/Challenges/redux/selectors.js @@ -1,13 +1,21 @@ import { challengeTypes } from '../../../../utils/challenge-types'; -import { completedChallengesSelector } from '../../../redux/selectors'; +import { + completedChallengesSelector, + allChallengesInfoSelector, + isSignedInSelector +} from '../../../redux/selectors'; +import { + getCurrentBlockIds, + getCompletedChallengesInBlock, + getCompletedPercentage +} from '../../../utils/get-completion-percentage'; import { ns } from './action-types'; -export const currentTabSelector = state => state[ns].currentTab; export const challengeFilesSelector = state => state[ns].challengeFiles; export const challengeMetaSelector = state => state[ns].challengeMeta; export const challengeTestsSelector = state => state[ns].challengeTests; export const consoleOutputSelector = state => state[ns].consoleOut; -export const completedChallengesIds = state => +export const completedChallengesIdsSelector = state => completedChallengesSelector(state).map(node => node.id); export const isChallengeCompletedSelector = state => { const completedChallenges = completedChallengesSelector(state); @@ -30,8 +38,9 @@ export const successMessageSelector = state => state[ns].successMessage; export const projectFormValuesSelector = state => state[ns].projectFormValues || {}; - -export const portalDocumentSelector = state => state[ns].portalDocument; +export const isAdvancingToChallengeSelector = state => state[ns].isAdvancing; +export const portalDocumentSelector = state => state[ns].portalWindow?.document; +export const portalWindowSelector = state => state[ns].portalWindow; export const challengeDataSelector = state => { const { challengeType } = challengeMetaSelector(state); @@ -82,7 +91,55 @@ export const challengeDataSelector = state => { return challengeData; }; +export const currentBlockIdsSelector = state => { + const { block, certification, challengeType } = challengeMetaSelector(state); + const allChallengesInfo = allChallengesInfoSelector(state); + + return getCurrentBlockIds( + allChallengesInfo, + block, + certification, + challengeType + ); +}; + +export const completedChallengesInBlockSelector = state => { + const completedChallengesIds = completedChallengesIdsSelector(state); + const currentBlockIds = currentBlockIdsSelector(state); + const { id } = challengeMetaSelector(state); + + return getCompletedChallengesInBlock( + completedChallengesIds, + currentBlockIds, + id + ); +}; + +export const completedPercentageSelector = state => { + const isSignedIn = isSignedInSelector(state); + if (isSignedIn) { + const completedChallengesIds = completedChallengesIdsSelector(state); + const { id } = challengeMetaSelector(state); + const currentBlockIds = currentBlockIdsSelector(state); + const completedPercentage = getCompletedPercentage( + completedChallengesIds, + currentBlockIds, + id + ); + return completedPercentage; + } else return 0; +}; + +export const isBlockNewlyCompletedSelector = state => { + const completedPercentage = completedPercentageSelector(state); + const completedChallengesIds = completedChallengesIdsSelector(state); + const { id } = challengeMetaSelector(state); + return completedPercentage === 100 && !completedChallengesIds.includes(id); +}; + export const attemptsSelector = state => state[ns].attempts; export const canFocusEditorSelector = state => state[ns].canFocusEditor; export const visibleEditorsSelector = state => state[ns].visibleEditors; export const testsRunningSelector = state => state[ns].testsRunning; +export const showPreviewPortalSelector = state => state[ns].showPreviewPortal; +export const showPreviewPaneSelector = state => state[ns].showPreviewPane; diff --git a/client/src/templates/Challenges/utils/build.ts b/client/src/templates/Challenges/utils/build.ts index b902c8b635d7c9..6951043d988007 100644 --- a/client/src/templates/Challenges/utils/build.ts +++ b/client/src/templates/Challenges/utils/build.ts @@ -107,11 +107,13 @@ const buildFunctions = { [challengeTypes.multifileCertProject]: buildDOMChallenge }; -export function canBuildChallenge(challengeData: BuildChallengeData) { +export function canBuildChallenge(challengeData: BuildChallengeData): boolean { const { challengeType } = challengeData; return Object.prototype.hasOwnProperty.call(buildFunctions, challengeType); } +// TODO: Figure out and (hopefully) simplify the return type. +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export async function buildChallenge( challengeData: BuildChallengeData, options: BuildOptions @@ -131,6 +133,8 @@ const testRunners = { [challengeTypes.pythonProject]: getDOMTestRunner, [challengeTypes.multifileCertProject]: getDOMTestRunner }; +// TODO: Figure out and (hopefully) simplify the return type. +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function getTestRunner( buildData: BuildChallengeData, runnerConfig: TestRunnerConfig, @@ -185,10 +189,16 @@ async function getDOMTestRunner( runTestInTestFrame(document, testString, testTimeout); } +type BuildResult = { + challengeType: number; + build: string; + sources: Source | undefined; +}; + export function buildDOMChallenge( { challengeFiles, required = [], template = '' }: BuildChallengeData, { usesTestRunner } = { usesTestRunner: false } -) { +): Promise | undefined { const finalRequires = [...required]; if (usesTestRunner) finalRequires.push(...frameRunner); @@ -225,7 +235,7 @@ export function buildDOMChallenge( export function buildJSChallenge( { challengeFiles }: { challengeFiles: ChallengeFiles }, options: BuildOptions -) { +): Promise | undefined { const pipeLine = composeFunctions(...getTransformers(options)); const finalFiles = challengeFiles?.map(pipeLine); @@ -250,7 +260,7 @@ export function buildJSChallenge( } } -export function buildBackendChallenge({ url }: BuildChallengeData) { +function buildBackendChallenge({ url }: BuildChallengeData) { return { challengeType: challengeTypes.backend, build: concatHtml({ required: frameRunner }), @@ -262,7 +272,7 @@ export function updatePreview( buildData: BuildChallengeData, document: Document, proxyLogger: ProxyLogger -) { +): void { if ( buildData.challengeType === challengeTypes.html || buildData.challengeType === challengeTypes.multifileCertProject @@ -293,7 +303,7 @@ function getDocumentTitle(buildData: BuildChallengeData) { export function updateProjectPreview( buildData: BuildChallengeData, document: Document -) { +): void { if ( buildData.challengeType === challengeTypes.html || buildData.challengeType === challengeTypes.multifileCertProject @@ -309,7 +319,7 @@ export function updateProjectPreview( } } -export function challengeHasPreview({ challengeType }: ChallengeMeta) { +export function challengeHasPreview({ challengeType }: ChallengeMeta): boolean { return ( challengeType === challengeTypes.html || challengeType === challengeTypes.modern || @@ -317,13 +327,15 @@ export function challengeHasPreview({ challengeType }: ChallengeMeta) { ); } -export function isJavaScriptChallenge({ challengeType }: ChallengeMeta) { +export function isJavaScriptChallenge({ + challengeType +}: ChallengeMeta): boolean { return ( challengeType === challengeTypes.js || challengeType === challengeTypes.jsProject ); } -export function isLoopProtected(challengeMeta: ChallengeMeta) { +export function isLoopProtected(challengeMeta: ChallengeMeta): boolean { return challengeMeta.superBlock !== 'coding-interview-prep'; } diff --git a/client/src/templates/Challenges/utils/frame.ts b/client/src/templates/Challenges/utils/frame.ts index 906df13cc46cc1..32147061c6cda7 100644 --- a/client/src/templates/Challenges/utils/frame.ts +++ b/client/src/templates/Challenges/utils/frame.ts @@ -8,6 +8,9 @@ declare global { interface Window { console: { log: () => void; + info: () => void; + warn: () => void; + error: () => void; }; i18nContent: i18n; } @@ -132,11 +135,15 @@ const createHeader = (id = mainPreviewId) => ` `; +type TestResult = + | { pass: boolean } + | { err: { message: string; stack?: string } }; + export const runTestInTestFrame = async function ( document: Document, test: string, timeout: number -) { +): Promise { const { contentDocument: frame } = document.getElementById( testId ) as HTMLIFrameElement; @@ -195,12 +202,41 @@ const updateProxyConsole = const oldLog = frameContext.window.console.log.bind( frameContext.window.console ); + const oldInfo = frameContext.window.console.info.bind( + frameContext.window.console + ); + + const oldWarn = frameContext.window.console.warn.bind( + frameContext.window.console + ); + + const oldError = frameContext.window.console.error.bind( + frameContext.window.console + ); + frameContext.window.console.log = function proxyConsole( ...args: string[] ) { proxyLogger(args.map((arg: string) => utilsFormat(arg)).join(' ')); return oldLog(...(args as [])); }; + + frameContext.window.console.info = function proxyInfo(...args: string[]) { + proxyLogger(args.map((arg: string) => utilsFormat(arg)).join(' ')); + return oldInfo(...(args as [])); + }; + + frameContext.window.console.warn = function proxyWarn(...args: string[]) { + proxyLogger(args.map((arg: string) => utilsFormat(arg)).join(' ')); + return oldWarn(...(args as [])); + }; + + frameContext.window.console.error = function proxyWarn( + ...args: string[] + ) { + proxyLogger(args.map((arg: string) => utilsFormat(arg)).join(' ')); + return oldError(...(args as [])); + }; } return frameContext; @@ -309,7 +345,7 @@ export const createMainPreviewFramer = ( document: Document, proxyLogger: ProxyLogger, frameTitle: string -) => +): ((args: Context) => void) => createFramer( document, mainPreviewId, @@ -322,7 +358,7 @@ export const createMainPreviewFramer = ( export const createProjectPreviewFramer = ( document: Document, frameTitle: string -) => +): ((args: Context) => void) => createFramer( document, projectPreviewId, @@ -336,7 +372,8 @@ export const createTestFramer = ( document: Document, proxyLogger: ProxyLogger, frameReady: () => void -) => createFramer(document, testId, initTestFrame, proxyLogger, frameReady); +): ((args: Context) => void) => + createFramer(document, testId, initTestFrame, proxyLogger, frameReady); const createFramer = ( document: Document, diff --git a/client/src/templates/Challenges/utils/index.ts b/client/src/templates/Challenges/utils/index.ts index 81f0fb5146b829..f4e3a5aa511e53 100644 --- a/client/src/templates/Challenges/utils/index.ts +++ b/client/src/templates/Challenges/utils/index.ts @@ -35,7 +35,7 @@ export function transformEditorLink(url: string): string { export function enhancePrismAccessibility( prismEnv: Prism.hooks.ElementHighlightedEnvironment -) { +): void { const langs: { [key: string]: string } = { js: 'JavaScript', javascript: 'JavaScript', diff --git a/client/src/templates/Challenges/video/show.css b/client/src/templates/Challenges/video.css similarity index 100% rename from client/src/templates/Challenges/video/show.css rename to client/src/templates/Challenges/video.css diff --git a/client/src/templates/Challenges/video/Show.tsx b/client/src/templates/Challenges/video/Show.tsx index 2cdd509136d58f..743187c246aef9 100644 --- a/client/src/templates/Challenges/video/Show.tsx +++ b/client/src/templates/Challenges/video/Show.tsx @@ -31,7 +31,7 @@ import { import { isChallengeCompletedSelector } from '../redux/selectors'; // Styles -import './show.css'; +import '../video.css'; // Redux Setup const mapStateToProps = createSelector( diff --git a/client/src/templates/Introduction/components/block.tsx b/client/src/templates/Introduction/components/block.tsx index 30e4501ceb1c5e..b1649130bd4c58 100644 --- a/client/src/templates/Introduction/components/block.tsx +++ b/client/src/templates/Introduction/components/block.tsx @@ -13,7 +13,6 @@ import DropDown from '../../../assets/icons/dropdown'; import GreenNotCompleted from '../../../assets/icons/green-not-completed'; import GreenPass from '../../../assets/icons/green-pass'; import { Link, Spacer } from '../../../components/helpers'; -import { executeGA } from '../../../redux/actions'; import { completedChallengesSelector } from '../../../redux/selectors'; import { ChallengeNode, CompletedChallenge } from '../../../redux/prop-types'; import { playTone } from '../../../utils/tone'; @@ -45,20 +44,18 @@ const mapStateToProps = ( }; const mapDispatchToProps = (dispatch: Dispatch) => - bindActionCreators({ toggleBlock, executeGA }, dispatch); + bindActionCreators({ toggleBlock }, dispatch); interface BlockProps { blockDashedName: string; challenges: ChallengeNode[]; completedChallengeIds: string[]; - executeGA: typeof executeGA; isExpanded: boolean; superBlock: SuperBlocks; t: TFunction; toggleBlock: typeof toggleBlock; } - -export class Block extends Component { +class Block extends Component { static displayName: string; constructor(props: BlockProps) { super(props); @@ -67,15 +64,8 @@ export class Block extends Component { } handleBlockClick(): void { - const { blockDashedName, toggleBlock, executeGA } = this.props; + const { blockDashedName, toggleBlock } = this.props; void playTone('block-toggle'); - executeGA({ - type: 'event', - data: { - category: 'Map Block Click', - action: blockDashedName - } - }); toggleBlock(blockDashedName); } diff --git a/client/src/templates/Introduction/components/cert-challenge.tsx b/client/src/templates/Introduction/components/cert-challenge.tsx index 58f57e949eff69..ab5445713c65da 100644 --- a/client/src/templates/Introduction/components/cert-challenge.tsx +++ b/client/src/templates/Introduction/components/cert-challenge.tsx @@ -34,7 +34,7 @@ interface CertChallengeProps { currentCerts: Steps['currentCerts']; superBlock: SuperBlocks; t: TFunction; - title: typeof certMap[number]['title']; + title: (typeof certMap)[number]['title']; user: User; verifyCert: typeof verifyCert; } @@ -130,7 +130,8 @@ const CertChallenge = ({ > {isCertified && userLoaded ? t('buttons.show-cert') - : t('buttons.go-to-settings')} + : t('buttons.go-to-settings')}{' '} + {title} )} @@ -139,8 +140,6 @@ const CertChallenge = ({ CertChallenge.displayName = 'CertChallenge'; -export { CertChallenge }; - export default connect( mapStateToProps, mapDispatchToProps diff --git a/client/src/templates/Introduction/components/challenges.tsx b/client/src/templates/Introduction/components/challenges.tsx index 6686cf863f7a84..0e28ae015296ae 100644 --- a/client/src/templates/Introduction/components/challenges.tsx +++ b/client/src/templates/Introduction/components/challenges.tsx @@ -9,7 +9,6 @@ import GreenNotCompleted from '../../../assets/icons/green-not-completed'; import GreenPass from '../../../assets/icons/green-pass'; import { executeGA } from '../../../redux/actions'; import { SuperBlocks } from '../../../../../config/certification-settings'; -import { ExecuteGaArg } from '../../../pages/donate'; import { ChallengeWithCompletedNode } from '../../../redux/prop-types'; import { isNewJsCert, isNewRespCert } from '../../../utils/is-a-cert'; @@ -18,7 +17,6 @@ const mapDispatchToProps = (dispatch: Dispatch) => interface Challenges { challengesWithCompleted: ChallengeWithCompletedNode[]; - executeGA: (payload: ExecuteGaArg) => void; isProjectBlock: boolean; superBlock: SuperBlocks; blockTitle?: string | null; @@ -26,20 +24,11 @@ interface Challenges { function Challenges({ challengesWithCompleted, - executeGA, isProjectBlock, superBlock, blockTitle }: Challenges): JSX.Element { const { t } = useTranslation(); - const handleChallengeClick = (slug: string) => - executeGA({ - type: 'event', - data: { - category: 'Map Challenge Click', - action: slug - } - }); const renderCheckMark = (isCompleted: boolean) => isCompleted ? : ; @@ -60,9 +49,6 @@ function Challenges({
    - handleChallengeClick(firstIncompleteChallenge.fields.slug) - } to={firstIncompleteChallenge.fields.slug} > {!isChallengeStarted @@ -88,7 +74,6 @@ function Challenges({ > {!isProjectBlock ? ( handleChallengeClick(challenge.fields.slug)} to={challenge.fields.slug} className={`map-grid-item ${ +challenge.isCompleted ? 'challenge-completed' : '' @@ -103,10 +88,7 @@ function Challenges({ ) : ( - handleChallengeClick(challenge.fields.slug)} - to={challenge.fields.slug} - > + {challenge.title} {renderCheckMark(challenge.isCompleted)} @@ -129,20 +111,14 @@ function Challenges({ key={'map-challenge' + challenge.fields.slug} > {!isProjectBlock ? ( - handleChallengeClick(challenge.fields.slug)} - to={challenge.fields.slug} - > + {renderCheckMark(challenge.isCompleted)} {challenge.title} ) : ( - handleChallengeClick(challenge.fields.slug)} - to={challenge.fields.slug} - > + {challenge.title} {renderCheckMark(challenge.isCompleted)} diff --git a/client/src/templates/Introduction/intro.css b/client/src/templates/Introduction/intro.css index 016f53495669a1..615557a8960595 100644 --- a/client/src/templates/Introduction/intro.css +++ b/client/src/templates/Introduction/intro.css @@ -80,7 +80,8 @@ a.cert-tag:active { display: flex; flex-direction: column; justify-content: center; - padding: 25px 15px 10px 0; + padding-block: 10px 25px; + padding-inline: 0 15px; margin: 0 0 0.6rem; flex-grow: 2; flex-basis: 0; @@ -122,7 +123,7 @@ a.cert-tag:active { padding: 18px 0; background: transparent; border: none; - text-align: left; + text-align: start; width: 100%; } @@ -147,7 +148,7 @@ button.map-title { } .map-project-checkmark { - padding-left: 15px; + padding-inline-start: 15px; } .block .map-cert-title { @@ -184,7 +185,8 @@ button.map-title { .map-cert-title > h3 { font-size: 1.17rem; - margin: 0 0 0 15px; + margin-block: 0; + margin-inline: 15px 0; } .map-cert-title > svg { @@ -199,15 +201,15 @@ button.map-title { } .map-title-completed { - margin-left: auto; + margin-inline-start: auto; min-width: 100px; - padding-left: 20px; + padding-inline-start: 20px; } .map-title-completed-big { - margin-left: auto; - padding-right: 15px; - padding-left: 20px; + margin-inline-start: auto; + padding-inline-end: 15px; + padding-inline-start: 20px; position: relative; top: 4px; } @@ -225,7 +227,7 @@ button.map-title { .block-grid .map-title > svg:last-child { transform: rotate(180deg); - margin-left: auto; + margin-inline-start: auto; } .block-grid.open .map-title > svg:last-child { @@ -348,7 +350,7 @@ button.map-title { .map-title-completed { flex-shrink: 0; - padding-left: 15px; + padding-inline-start: 15px; } } @@ -381,7 +383,7 @@ button.map-title { font-size: 1rem; display: block; margin-bottom: 5px; - margin-right: 5px; + margin-inline-end: 5px; padding: 4px 10px; color: var(--highlight-color); background-color: var(--highlight-background); diff --git a/client/src/templates/Introduction/super-block-intro.tsx b/client/src/templates/Introduction/super-block-intro.tsx index 9b82cece7e8e51..d0c84f3e1a5068 100644 --- a/client/src/templates/Introduction/super-block-intro.tsx +++ b/client/src/templates/Introduction/super-block-intro.tsx @@ -205,16 +205,17 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => { /> ))} - {superBlock !== SuperBlocks.CodingInterviewPrep && ( -
    - -
    - )} + {superBlock !== SuperBlocks.CodingInterviewPrep && + superBlock !== SuperBlocks.TheOdinProject && ( +
    + +
    + )}
    {!isSignedIn && !signInLoading && (
    diff --git a/client/src/utils/A-B-tester.test.ts b/client/src/utils/A-B-tester.test.ts deleted file mode 100644 index df932ff6abd3f1..00000000000000 --- a/client/src/utils/A-B-tester.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import faker from 'faker'; -import { emailToABVariant } from './A-B-tester'; - -describe('client/src is-email-variation-a', () => { - it('Consistently returns the same result for the same input', () => { - const preSavedResult = { - hash: '23e3cacb302b0c759531faa8b414b23709c26029', - isVariantA: true, - hashInt: 2 - }; - const result = emailToABVariant('foo@freecodecamp.org'); - expect(result).toEqual(preSavedResult); - }); - it('Distributes A and B variations equaly for 100K random emails', () => { - let A = 0; - let B = 0; - const sampleSize = 100000; - faker.seed(123); - - for (let i = 0; i < sampleSize; i++) { - if (emailToABVariant(faker.internet.email()).isVariantA) A++; - else B++; - } - - const isBucketWellDistributed = (variant: number): boolean => - variant > 0.99 * (sampleSize / 2); - - expect(isBucketWellDistributed(A) && isBucketWellDistributed(B)).toEqual( - true - ); - }); -}); diff --git a/client/src/utils/A-B-tester.ts b/client/src/utils/A-B-tester.ts deleted file mode 100644 index d78141ebad8ea8..00000000000000 --- a/client/src/utils/A-B-tester.ts +++ /dev/null @@ -1,21 +0,0 @@ -import sha1 from 'sha-1'; - -// This function turns an email to a hash and decides if it should be -// an A or B variant for A/B testing - -export function emailToABVariant(email: string): { - hash: string; - isVariantA: boolean; - hashInt: number; -} { - // turn the email into a number - const hash: string = sha1(email); - const hashInt = parseInt(hash.slice(0, 1), 16); - // turn the number to A or B variant - const isVariantA = hashInt % 2 === 0; - return { - hash, - isVariantA, - hashInt - }; -} diff --git a/client/src/utils/ajax.ts b/client/src/utils/ajax.ts index fbf3b19459a183..b284b6924d8916 100644 --- a/client/src/utils/ajax.ts +++ b/client/src/utils/ajax.ts @@ -136,6 +136,8 @@ function parseApiResponseToClientUser(data: ApiUser): UserResponse { }; } +// TODO: this at least needs a few aliases so it's human readable +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function mapFilesToChallengeFiles( fileContainer: ({ files: (File & { key: string })[] } & Rest)[] = [] ) { diff --git a/client/src/utils/analyticsStrings.test.ts b/client/src/utils/analyticsStrings.test.ts new file mode 100644 index 00000000000000..96cf47ce145d8a --- /dev/null +++ b/client/src/utils/analyticsStrings.test.ts @@ -0,0 +1,14 @@ +import { stringifyDonationEvents } from './analyticsStrings'; + +describe('Analytics donation strings', () => { + it('Should return correct string for modal patreon payment', () => { + expect(stringifyDonationEvents('modal', 'patreon')).toEqual( + 'Modal Patreon Payment Redirection' + ); + }); + it('Should return correct string for modal donate page stripe card payment', () => { + expect(stringifyDonationEvents('donate page', 'stripe card')).toEqual( + 'Donate Page Stripe Card Payment Submission' + ); + }); +}); diff --git a/client/src/utils/analyticsStrings.ts b/client/src/utils/analyticsStrings.ts new file mode 100644 index 00000000000000..f5f559c08a9772 --- /dev/null +++ b/client/src/utils/analyticsStrings.ts @@ -0,0 +1,15 @@ +import { PaymentContext, PaymentProvider } from '../components/Donation/types'; + +export function stringifyDonationEvents( + paymentContext: PaymentContext, + paymentProvider: PaymentProvider +): string { + const donationString = `${paymentContext} ${paymentProvider} payment ${ + paymentProvider === 'patreon' ? 'redirection' : 'submission' + }`; + + // return title case + return donationString.replace(/(^\w{1})|(\s+\w{1})/g, letter => + letter.toUpperCase() + ); +} diff --git a/client/src/utils/challenge-request-helpers.ts b/client/src/utils/challenge-request-helpers.ts index 3451f372437902..d4017894beb4d5 100644 --- a/client/src/utils/challenge-request-helpers.ts +++ b/client/src/utils/challenge-request-helpers.ts @@ -13,11 +13,25 @@ interface StandardizeRequestBodyArgs { challengeType: number; } +interface File { + contents: string; + ext: string; + history: string[]; + key: string; + name: string; +} + +interface Body { + id: string; + files?: File[]; + challengeType: number; +} + export function standardizeRequestBody({ id, challengeFiles = [], challengeType -}: StandardizeRequestBodyArgs) { +}: StandardizeRequestBodyArgs): Body { return { id, files: challengeFiles?.map(({ fileKey, contents, ext, name, history }) => { @@ -33,12 +47,12 @@ export function standardizeRequestBody({ }; } -export function getStringSizeInBytes(str = '') { +export function getStringSizeInBytes(str = ''): number { const stringSizeInBytes = new Blob([JSON.stringify(str)]).size; return stringSizeInBytes; } -export function bodySizeFits(bodySizeInBytes: number) { +export function bodySizeFits(bodySizeInBytes: number): boolean { return bodySizeInBytes <= MAX_BODY_SIZE; } diff --git a/client/src/utils/get-completion-percentage.ts b/client/src/utils/get-completion-percentage.ts new file mode 100644 index 00000000000000..392644c48a510c --- /dev/null +++ b/client/src/utils/get-completion-percentage.ts @@ -0,0 +1,57 @@ +import { AllChallengesInfo } from '../redux/prop-types'; +import { dasherize } from '../../../utils/slugs'; +import { isFinalProject } from '../../utils/challenge-types'; + +export function getCompletedPercentage( + completedChallengesIds: string[] = [], + currentBlockIds: string[] = [], + currentChallengeId: string +): number { + const completedChallengesInBlock = getCompletedChallengesInBlock( + completedChallengesIds, + currentBlockIds, + currentChallengeId + ); + const completedPercent = Math.round( + (completedChallengesInBlock / currentBlockIds.length) * 100 + ); + + return completedPercent > 100 ? 100 : completedPercent; +} + +export function getCompletedChallengesInBlock( + completedChallengesIds: string[], + currentBlockIds: string[], + currentChallengeId: string +): number { + const oldCompletionCount = completedChallengesIds.filter(challengeId => + currentBlockIds.includes(challengeId) + ).length; + + const isAlreadyCompleted = + completedChallengesIds.includes(currentChallengeId); + + return isAlreadyCompleted ? oldCompletionCount : oldCompletionCount + 1; +} + +export const getCurrentBlockIds = ( + allChallengesInfo: AllChallengesInfo, + block: string, + certification: string, + challengeType: number +): string[] => { + const { challengeEdges, certificateNodes } = allChallengesInfo; + const currentCertificateIds = + certificateNodes + .filter( + node => dasherize(node.challenge.certification) === certification + )[0] + ?.challenge.tests.map(test => test.id) ?? []; + const currentBlockIds = challengeEdges + .filter(edge => edge.node.challenge.block === block) + .map(edge => edge.node.challenge.id); + + return isFinalProject(challengeType) + ? currentCertificateIds + : currentBlockIds; +}; diff --git a/client/src/utils/path-parsers.ts b/client/src/utils/path-parsers.ts index 587606f409c01d..11f23e452db8ef 100644 --- a/client/src/utils/path-parsers.ts +++ b/client/src/utils/path-parsers.ts @@ -31,6 +31,3 @@ export const isLocationSuperBlock = ( ): boolean => { return /^\/learn\/[\w-]+\/$/.test(location?.pathname ?? ''); }; - -const pathParsers = { isLanding, isChallenge }; -export default pathParsers; diff --git a/client/src/utils/report-error.ts b/client/src/utils/report-error.ts index d58bc024ba5a44..4d4bc6cdc43539 100644 --- a/client/src/utils/report-error.ts +++ b/client/src/utils/report-error.ts @@ -1,4 +1,4 @@ -import * as Sentry from '@sentry/gatsby'; +import { captureException } from '@sentry/gatsby'; import envData from '../../../config/env.json'; const { sentryClientDSN } = envData; @@ -11,5 +11,5 @@ export function reportClientSideError( ): string | void { return sentryClientDSN === null ? console.error(`Client: ${message}`, e) - : Sentry.captureException(e); + : captureException(e); } diff --git a/client/src/utils/solution-display-type.ts b/client/src/utils/solution-display-type.ts index 8c1be9198b3a0b..101553f528624e 100644 --- a/client/src/utils/solution-display-type.ts +++ b/client/src/utils/solution-display-type.ts @@ -2,12 +2,20 @@ import type { CompletedChallenge } from '../redux/prop-types'; import { challengeTypes } from '../../utils/challenge-types'; import { maybeUrlRE } from '.'; +// eslint-disable-next-line @typescript-eslint/naming-convention +type DisplayType = + | 'none' + | 'showMultifileProjectSolution' + | 'showUserCode' + | 'showProjectAndGithubLinks' + | 'showProjectLink'; + export const getSolutionDisplayType = ({ solution, githubLink, challengeFiles, challengeType -}: CompletedChallenge) => { +}: CompletedChallenge): DisplayType => { if (challengeFiles?.length) return challengeType === challengeTypes.multifileCertProject ? 'showMultifileProjectSolution' diff --git a/client/src/utils/superblock-map-titles.ts b/client/src/utils/superblock-map-titles.ts index fa2ec32c994282..dae9af0dcba935 100644 --- a/client/src/utils/superblock-map-titles.ts +++ b/client/src/utils/superblock-map-titles.ts @@ -9,9 +9,12 @@ enum SuperBlockI18nKeys { // the key above is used to create the last word for superBlock titles used on // the map and window. e.g. 'Certification' in Responsive Web Design // Certification -const superBlocksWithoutLastWord = [SuperBlocks.CodingInterviewPrep]; +const superBlocksWithoutLastWord = [ + SuperBlocks.CodingInterviewPrep, + SuperBlocks.TheOdinProject +]; -export function getSuperBlockTitleForMap(superBlock: SuperBlocks) { +export function getSuperBlockTitleForMap(superBlock: SuperBlocks): string { const i18nSuperBlock = i18next.t(`intro:${superBlock}.title`); return superBlocksWithoutLastWord.includes(superBlock) diff --git a/client/src/utils/tone/index.ts b/client/src/utils/tone/index.ts index e146073809e384..103ea6c46d2efe 100644 --- a/client/src/utils/tone/index.ts +++ b/client/src/utils/tone/index.ts @@ -62,20 +62,16 @@ type ToneStates = keyof typeof toneUrls; export async function playTone(state: ToneStates): Promise { const playSound = !!store.get('fcc-sound'); if (playSound && toneUrls[state]) { - const tone = await import('tone'); + const Tone = await import('tone'); - if (tone.context.state !== 'running') { - tone.context.resume().catch(err => { - console.error('Error resuming audio context', err); - }); - } - const player = new tone.Player(toneUrls[state]).toDestination(); + const player = new Tone.Player(toneUrls[state]).toDestination(); const storedVolume = (store.get('soundVolume') as number) ?? 50; const calculateDecibel = -60 * (1 - storedVolume / 100); player.volume.value = calculateDecibel; - player.autostart = true; + await Tone.loaded(); + player.start(); } } diff --git a/client/static/fonts/noto-sans-arabic/NotoSansArabic-Black.woff b/client/static/fonts/noto-sans-arabic/NotoSansArabic-Black.woff new file mode 100644 index 00000000000000..be9dde5af63958 Binary files /dev/null and b/client/static/fonts/noto-sans-arabic/NotoSansArabic-Black.woff differ diff --git a/client/static/fonts/noto-sans-arabic/NotoSansArabic-Bold.woff b/client/static/fonts/noto-sans-arabic/NotoSansArabic-Bold.woff new file mode 100644 index 00000000000000..e574d88730df85 Binary files /dev/null and b/client/static/fonts/noto-sans-arabic/NotoSansArabic-Bold.woff differ diff --git a/client/static/fonts/noto-sans-arabic/NotoSansArabic-Light.woff b/client/static/fonts/noto-sans-arabic/NotoSansArabic-Light.woff new file mode 100644 index 00000000000000..6555b1a146d8ea Binary files /dev/null and b/client/static/fonts/noto-sans-arabic/NotoSansArabic-Light.woff differ diff --git a/client/static/fonts/noto-sans-arabic/NotoSansArabic-Regular.woff b/client/static/fonts/noto-sans-arabic/NotoSansArabic-Regular.woff new file mode 100644 index 00000000000000..08e7d743c7501f Binary files /dev/null and b/client/static/fonts/noto-sans-arabic/NotoSansArabic-Regular.woff differ diff --git a/client/tsconfig.json b/client/tsconfig.json new file mode 100644 index 00000000000000..441cb64d66b301 --- /dev/null +++ b/client/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "lib": ["WebWorker", "DOM", "DOM.Iterable", "ES2020"], + "target": "es2020", + "module": "es2020", + "moduleResolution": "node", + "allowJs": true, + "jsx": "react", + "strict": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "noEmit": true, + "resolveJsonModule": true, + "skipLibCheck": true + }, + "include": ["i18n/**/*", "plugins/**/*", "src/**/*", "utils/**/*"] +} diff --git a/client/utils/build-challenges.js b/client/utils/build-challenges.js index c6e0e4bac9c433..fc091383c64a8d 100644 --- a/client/utils/build-challenges.js +++ b/client/utils/build-challenges.js @@ -9,7 +9,7 @@ const { CHALLENGES_DIR, META_DIR, getChallengesDirForLang -} = require('../../curriculum/getChallenges'); +} = require('../../curriculum/get-challenges'); const { curriculumLocale } = envData; diff --git a/client/utils/challenge-types.js b/client/utils/challenge-types.js index 5cbc1d59f66af2..d0c665e1ade339 100644 --- a/client/utils/challenge-types.js +++ b/client/utils/challenge-types.js @@ -14,6 +14,7 @@ const video = 11; const codeAllyPractice = 12; const codeAllyCert = 13; const multifileCertProject = 14; +const theOdinProject = 15; // individual exports exports.backend = backend; @@ -38,7 +39,8 @@ exports.challengeTypes = { video, codeAllyPractice, codeAllyCert, - multifileCertProject + multifileCertProject, + theOdinProject }; exports.isFinalProject = challengeType => { @@ -60,12 +62,6 @@ exports.isCodeAllyPractice = challengeType => { return challengeType === codeAllyPractice; }; -// turn challengeType to file ext -exports.pathsMap = { - [html]: 'html', - [js]: 'js', - [jsProject]: 'js' -}; // determine the component view for each challenge exports.viewTypes = { [html]: 'classic', @@ -81,7 +77,8 @@ exports.viewTypes = { [video]: 'video', [codeAllyPractice]: 'codeAlly', [codeAllyCert]: 'codeAlly', - [multifileCertProject]: 'classic' + [multifileCertProject]: 'classic', + [theOdinProject]: 'odin' }; // determine the type of submit function to use for the challenge on completion @@ -103,7 +100,8 @@ exports.submitTypes = { [modern]: 'tests', [video]: 'tests', [codeAllyCert]: 'project.frontEnd', - [multifileCertProject]: 'tests' + [multifileCertProject]: 'tests', + [theOdinProject]: 'tests' }; // determine which help forum questions should be posted to diff --git a/client/utils/gatsby/challenge-page-creator.js b/client/utils/gatsby/challenge-page-creator.js index 186fdf9940b3c7..776532c7941692 100644 --- a/client/utils/gatsby/challenge-page-creator.js +++ b/client/utils/gatsby/challenge-page-creator.js @@ -32,16 +32,30 @@ const video = path.resolve( '../../src/templates/Challenges/video/Show.tsx' ); +const odin = path.resolve( + __dirname, + '../../src/templates/Challenges/odin/Show.tsx' +); + const views = { backend, classic, modern: classic, frontend, video, - codeAlly + codeAlly, + odin // quiz: Quiz }; +function getIsFirstStep(_node, index, nodeArray) { + const current = nodeArray[index]; + const previous = nodeArray[index - 1]; + + if (!previous) return true; + return previous.node.challenge.block !== current.node.challenge.block; +} + function getNextChallengePath(_node, index, nodeArray) { const next = nodeArray[index + 1]; return next ? next.node.challenge.fields.slug : '/learn'; @@ -78,6 +92,7 @@ exports.createChallengePages = function (createPage) { certification, superBlock, block, + isFirstStep: getIsFirstStep(challenge, index, allChallengeEdges), template, required, nextChallengePath: getNextChallengePath( diff --git a/client/utils/gatsby/layout-selector.test.tsx b/client/utils/gatsby/layout-selector.test.tsx index ac769f44d1a2ef..f56a25a68fbef9 100644 --- a/client/utils/gatsby/layout-selector.test.tsx +++ b/client/utils/gatsby/layout-selector.test.tsx @@ -6,7 +6,7 @@ import ShallowRenderer from 'react-test-renderer/shallow'; import FourOhFourPage from '../../src/pages/404'; import Certification from '../../src/pages/certification'; import Learn from '../../src/pages/learn'; -import { createStore } from '../../src/redux/createStore'; +import { createStore } from '../../src/redux/create-store'; import layoutSelector from './layout-selector'; jest.mock('../../src/analytics'); diff --git a/client/utils/help-category-map.json b/client/utils/help-category-map.json index 6fa138ac53f9d8..b7e9db89e5ffc5 100644 --- a/client/utils/help-category-map.json +++ b/client/utils/help-category-map.json @@ -42,6 +42,8 @@ "algorithms": "JavaScript", "data-structures": "JavaScript", "take-home-projects": "JavaScript", + "top-learn-html-foundations": "HTML-CSS", + "top-build-a-recipe-project": "HTML-CSS", "rosetta-code": "JavaScript", "project-euler": "JavaScript", "scientific-computing-with-python": "Python", @@ -101,5 +103,6 @@ "build-a-cash-register-project": "JavaScript", "build-a-palindrome-checker-project": "JavaScript", "build-a-roman-numeral-converter-project": "JavaScript", - "build-a-telephone-number-validator-project": "JavaScript" + "build-a-telephone-number-validator-project": "JavaScript", + "learn-advanced-array-methods-by-building-a-statistics-calculator": "JavaScript" } diff --git a/client/webpack-workers.js b/client/webpack-workers.js index 7d6cd9d3b47260..54dea0a70acc91 100644 --- a/client/webpack-workers.js +++ b/client/webpack-workers.js @@ -62,7 +62,7 @@ module.exports = (env = {}) => { }, plugins: [ new CopyWebpackPlugin({ - patterns: ['../node_modules/sass.js/dist/sass.sync.js'] + patterns: ['./node_modules/sass.js/dist/sass.sync.js'] }), new webpack.ProvidePlugin({ process: 'process/browser' diff --git a/config/certification-settings.ts b/config/certification-settings.ts index e3fddaf40aa14f..7172f244a07e59 100644 --- a/config/certification-settings.ts +++ b/config/certification-settings.ts @@ -33,7 +33,8 @@ export enum SuperBlocks { DataAnalysisPy = 'data-analysis-with-python', InfoSec = 'information-security', MachineLearningPy = 'machine-learning-with-python', - CodingInterviewPrep = 'coding-interview-prep' + CodingInterviewPrep = 'coding-interview-prep', + TheOdinProject = 'the-odin-project' } export const certIds = { diff --git a/config/donation-settings.js b/config/donation-settings.ts similarity index 54% rename from config/donation-settings.js rename to config/donation-settings.ts index bdf7886dcd3b2c..0ade9659fc61eb 100644 --- a/config/donation-settings.js +++ b/config/donation-settings.ts @@ -1,26 +1,32 @@ // Configuration for client side -const durationsConfig = { +import { DonationConfig } from '../client/src/components/Donation/types'; + +export const durationsConfig: { + month: 'monthly'; + onetime: 'one-time'; +} = { month: 'monthly', onetime: 'one-time' }; -const amountsConfig = { + +export const amountsConfig = { month: [1000, 2000, 3000, 4000, 5000], onetime: [2500, 5000, 7500, 10000, 15000] }; -const defaultAmount = { +export const defaultAmount: { month: 500; onetime: 7500 } = { month: 500, onetime: 7500 }; -const defaultDonation = { - donationAmount: defaultAmount['month'], +export const defaultDonation: DonationConfig = { + donationAmount: defaultAmount.month, donationDuration: 'month' }; -const modalDefaultDonation = { +export const modalDefaultDonation: DonationConfig = { donationAmount: 500, donationDuration: 'month' }; -const onetimeSKUConfig = { +export const onetimeSKUConfig = { live: [ { amount: '15000', id: 'sku_IElisJHup0nojP' }, { amount: '10000', id: 'sku_IEliodY88lglPk' }, @@ -38,9 +44,9 @@ const onetimeSKUConfig = { }; // Configuration for server side -const durationKeysConfig = ['month', 'onetime']; -const donationOneTimeConfig = [100000, 25000, 6000]; -const donationSubscriptionConfig = { +export const durationKeysConfig = ['month', 'one-time']; +export const donationOneTimeConfig = [100000, 25000, 6000]; +export const donationSubscriptionConfig = { duration: { month: 'Monthly' }, @@ -51,7 +57,7 @@ const donationSubscriptionConfig = { // Shared paypal configuration // keep the 5 dollars for the modal -const paypalConfigTypes = { +export const paypalConfigTypes = { live: { month: { 500: { planId: 'P-1L11422374370240ULZKX3PA' }, @@ -74,42 +80,65 @@ const paypalConfigTypes = { } }; -const paypalConfigurator = (donationAmount, donationDuration, paypalConfig) => { - if (donationDuration === 'onetime') { +type DonationAmount = 500 | 1000 | 2000 | 3000 | 4000 | 5000; + +interface OneTimeConfig { + amount: DonationAmount; + duration: 'one-time'; + planId: null; +} + +interface SubscriptionConfig { + amount: DonationAmount; + duration: 'month'; + planId: string; +} + +export const paypalConfigurator = ( + donationAmount: DonationAmount, + donationDuration: 'one-time' | 'month', + paypalConfig: { + month: { + 500: { planId: string }; + 1000: { planId: string }; + 2000: { planId: string }; + 3000: { planId: string }; + 4000: { planId: string }; + 5000: { planId: string }; + }; + } +): OneTimeConfig | SubscriptionConfig => { + if (donationDuration === 'one-time') { return { amount: donationAmount, duration: donationDuration, planId: null }; } return { amount: donationAmount, duration: donationDuration, - planId: paypalConfig[donationDuration]['' + donationAmount].planId + planId: paypalConfig[donationDuration][donationAmount].planId }; }; -const donationUrls = { +export const donationUrls = { successUrl: 'https://www.freecodecamp.org/news/thank-you-for-donating/', cancelUrl: 'https://freecodecamp.org/donate' }; -const patreonDefaultPledgeAmount = 500; +export const patreonDefaultPledgeAmount = 500; -const aBTestConfig = { +export const aBTestConfig = { isTesting: true, type: 'secureIconButtonOnly' }; -module.exports = { - durationsConfig, - amountsConfig, - defaultAmount, - defaultDonation, - durationKeysConfig, - donationOneTimeConfig, - donationSubscriptionConfig, - modalDefaultDonation, - onetimeSKUConfig, - paypalConfigTypes, - paypalConfigurator, - donationUrls, - patreonDefaultPledgeAmount, - aBTestConfig -}; +export enum PaymentContext { + Modal = 'modal', + DonatePage = 'donate page', + Certificate = 'certificate' +} + +export enum PaymentProvider { + Paypal = 'paypal', + Patreon = 'patreon', + Stripe = 'stripe', + StripeCard = 'stripe card' +} diff --git a/config/i18n.ts b/config/i18n.ts index 9fe7a6311d20cb..786c9a54261d35 100644 --- a/config/i18n.ts +++ b/config/i18n.ts @@ -68,7 +68,7 @@ export const i18nextCodes = { }; // These are for the language selector dropdown menu in the footer -export const LangNames = { +export const LangNames: { [key: string]: string } = { [Languages.English]: 'English', [Languages.Espanol]: 'Español', [Languages.Chinese]: '中文(简体字)', @@ -111,7 +111,7 @@ export const rtlLangs = ['arabic']; // locale is sourced from a JSON file, so we use getLangCode to // find the associated enum values -export function getLangCode(locale: PropertyKey) { +export function getLangCode(locale: PropertyKey): string { if (isPropertyOf(LangCodes, locale)) return LangCodes[locale]; throw new Error(`${String(locale)} is not a valid locale`); } diff --git a/config/knip/knip.dev.json b/config/knip/knip.dev.json deleted file mode 100644 index 7970a93f04711c..00000000000000 --- a/config/knip/knip.dev.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "client":{ - "dev": true, - "exclude": ["dependencies"], - "entryFiles": [ - "gatsby-*.js", - "src/pages/*.tsx", - "src/templates/Challenges/**/{s,S}how.tsx", - "src/templates/Introduction/**/{intro,super-block-intro}.tsx", - "src/**/*.test.{js,ts,tsx}" - ], - "projectFiles": [ - "src/**/*.{js,ts,tsx}", - "!static/misc/*.js", - "!i18n/schema-validation.ts", - "!plugins/**", - "!postcss.config.js", - "!src/client/frame-runner.ts", - "!src/client/workers/**", - "!webpack-workers.js", - "!**/i18n/config-for-tests.ts", - "!**/__mocks__/**", - "!**/__fixtures/**", - "!**/node_modules/**" - ] - } -} diff --git a/config/knip/knip.json b/config/knip/knip.json deleted file mode 100644 index cdb79eb4b6cfae..00000000000000 --- a/config/knip/knip.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "client":{ - "exclude": ["dependencies"], - "entryFiles": [ - "gatsby-*.js", - "src/html.tsx", - "src/pages/*.tsx", - "src/templates/Challenges/**/{s,S}how.tsx", - "src/templates/Introduction/**/{intro,super-block-intro}.tsx" - ], - "projectFiles": [ - "**/*.{js,ts,tsx}", - "!static/misc/*.js", - "!i18n/schema-validation.ts", - "!plugins/**", - "!postcss.config.js", - "!src/client/frame-runner.ts", - "!src/client/workers/**", - "!webpack-workers.js", - "!**/*.test.{js,ts,tsx}", - "!**/i18n/config-for-tests.ts", - "!**/__mocks__/**", - "!**/__fixtures/**", - "!**/node_modules/**", - "!**/*.d.ts" - ] - } -} diff --git a/config/superblock-order.test.ts b/config/superblock-order.test.ts index 233f7c4d60c13b..cf21825a48b493 100644 --- a/config/superblock-order.test.ts +++ b/config/superblock-order.test.ts @@ -150,6 +150,7 @@ describe("'superBlockOrder' helper functions", () => { SuperBlocks.MachineLearningPy, SuperBlocks.CodingInterviewPrep, SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject, SuperBlocks.RespWebDesign ]; expect(learnSuperBlocks).toStrictEqual(test); @@ -188,7 +189,8 @@ describe("'superBlockOrder' helper functions", () => { SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, SuperBlocks.CodingInterviewPrep, - SuperBlocks.JsAlgoDataStructNew + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject ]; expect(notAuditedSuperBlocks).toStrictEqual(test); expect(notAuditedSuperBlocks.length).toEqual(test.length); diff --git a/config/superblock-order.ts b/config/superblock-order.ts index bc4253127d21e4..bfbeb4d83cdb50 100644 --- a/config/superblock-order.ts +++ b/config/superblock-order.ts @@ -79,7 +79,8 @@ export const defaultSuperBlockOrder: SuperBlocks[] = [ SuperBlocks.DataAnalysisPy, SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, - SuperBlocks.CodingInterviewPrep + SuperBlocks.CodingInterviewPrep, + SuperBlocks.TheOdinProject ]; /* @@ -127,7 +128,10 @@ export const superBlockOrder: SuperBlockOrder = { SuperBlocks.CodingInterviewPrep ], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign] }, [TranslationStates.NotAudited]: { @@ -140,7 +144,7 @@ export const superBlockOrder: SuperBlockOrder = { }, [Languages.Espanol]: { [CurriculumMaps.Landing]: [ - SuperBlocks.RespWebDesign, + SuperBlocks.RespWebDesignNew, SuperBlocks.JsAlgoDataStruct, SuperBlocks.FrontEndDevLibs, SuperBlocks.DataVis, @@ -155,7 +159,7 @@ export const superBlockOrder: SuperBlockOrder = { [CurriculumMaps.Learn]: { [TranslationStates.Audited]: { [SuperBlockStates.Current]: [ - SuperBlocks.RespWebDesign, + SuperBlocks.RespWebDesignNew, SuperBlocks.JsAlgoDataStruct, SuperBlocks.FrontEndDevLibs, SuperBlocks.DataVis, @@ -166,19 +170,20 @@ export const superBlockOrder: SuperBlockOrder = { ], [SuperBlockStates.New]: [], [SuperBlockStates.Upcoming]: [], - [SuperBlockStates.Legacy]: [] + [SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign] }, [TranslationStates.NotAudited]: { [SuperBlockStates.Current]: [ - SuperBlocks.RespWebDesignQA, - SuperBlocks.RespWebDesignNew, SuperBlocks.RelationalDb, SuperBlocks.InfoSec, SuperBlocks.MachineLearningPy, SuperBlocks.CodingInterviewPrep ], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [] } } @@ -223,7 +228,10 @@ export const superBlockOrder: SuperBlockOrder = { SuperBlocks.CodingInterviewPrep ], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [] } } @@ -268,7 +276,10 @@ export const superBlockOrder: SuperBlockOrder = { SuperBlocks.CodingInterviewPrep ], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [] } } @@ -312,7 +323,10 @@ export const superBlockOrder: SuperBlockOrder = { [TranslationStates.NotAudited]: { [SuperBlockStates.Current]: [], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [] } } @@ -356,7 +370,10 @@ export const superBlockOrder: SuperBlockOrder = { [TranslationStates.NotAudited]: { [SuperBlockStates.Current]: [], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [] } } @@ -399,7 +416,10 @@ export const superBlockOrder: SuperBlockOrder = { [TranslationStates.NotAudited]: { [SuperBlockStates.Current]: [SuperBlocks.CodingInterviewPrep], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [] } } @@ -444,7 +464,10 @@ export const superBlockOrder: SuperBlockOrder = { [TranslationStates.NotAudited]: { [SuperBlockStates.Current]: [], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [] } } @@ -489,7 +512,10 @@ export const superBlockOrder: SuperBlockOrder = { SuperBlocks.CodingInterviewPrep ], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [] } } @@ -534,7 +560,10 @@ export const superBlockOrder: SuperBlockOrder = { SuperBlocks.CodingInterviewPrep ], [SuperBlockStates.New]: [], - [SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew], + [SuperBlockStates.Upcoming]: [ + SuperBlocks.JsAlgoDataStructNew, + SuperBlocks.TheOdinProject + ], [SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign] } } @@ -565,11 +594,17 @@ function shouldShowSuperblocks({ return true; } +type Config = { + language: string; + showNewCurriculum?: string; + showUpcomingChanges?: string; +}; + export function getLearnSuperBlocks({ language = 'english', showNewCurriculum = 'false', showUpcomingChanges = 'false' -}) { +}: Config): SuperBlocks[] { const learnSuperBlocks: SuperBlocks[] = []; Object.values(TranslationStates).forEach(translationState => { @@ -597,7 +632,7 @@ export function getAuditedSuperBlocks({ language = 'english', showNewCurriculum = 'false', showUpcomingChanges = 'false' -}) { +}: Config): SuperBlocks[] { const auditedSuperBlocks: SuperBlocks[] = []; Object.values(SuperBlockStates).forEach(superBlockState => { @@ -623,7 +658,7 @@ export function getNotAuditedSuperBlocks({ language = 'english', showNewCurriculum = 'false', showUpcomingChanges = 'false' -}) { +}: Config): SuperBlocks[] { const notAuditedSuperBlocks: SuperBlocks[] = []; Object.values(SuperBlockStates).forEach(superBlockState => { diff --git a/curriculum-server/package.json b/curriculum-server/package.json index 12ccb9f6246978..cb8d47b081b1f6 100644 --- a/curriculum-server/package.json +++ b/curriculum-server/package.json @@ -6,7 +6,7 @@ "private": true, "engines": { "node": ">=16", - "npm": ">=8" + "pnpm": "7" }, "repository": { "type": "git", @@ -24,10 +24,10 @@ "source-curriculum": "ts-node source-curriculum.ts" }, "dependencies": { - "json-server": "0.17.1" + "json-server": "0.17.2" }, "devDependencies": { "ts-node": "10.9.1", - "typescript": "4.9.3" + "typescript": "4.9.5" } } diff --git a/curriculum/challenges/_meta/build-a-caesars-cipher-project/meta.json b/curriculum/challenges/_meta/build-a-caesars-cipher-project/meta.json index bde54d0df06c33..e25c4f2c04eaa1 100644 --- a/curriculum/challenges/_meta/build-a-caesars-cipher-project/meta.json +++ b/curriculum/challenges/_meta/build-a-caesars-cipher-project/meta.json @@ -1,6 +1,6 @@ { "name": "Build a Caesars Cipher Project", - "isUpcomingChange": false, + "isUpcomingChange": true, "usesMultifileEditor": false, "order": 17, "time": "30 hours", @@ -13,4 +13,3 @@ "Build a Caesars Cipher" ] ]} - \ No newline at end of file diff --git a/curriculum/challenges/_meta/build-a-cash-register-project/meta.json b/curriculum/challenges/_meta/build-a-cash-register-project/meta.json index ad35924ec72d59..2d1b9a5c0632db 100644 --- a/curriculum/challenges/_meta/build-a-cash-register-project/meta.json +++ b/curriculum/challenges/_meta/build-a-cash-register-project/meta.json @@ -1,6 +1,6 @@ { "name": "Build a Cash Register Project", - "isUpcomingChange": false, + "isUpcomingChange": true, "usesMultifileEditor": false, "order": 14, "time": "30 hours", @@ -13,4 +13,3 @@ "Build a Cash Register" ] ]} - \ No newline at end of file diff --git a/curriculum/challenges/_meta/build-a-palindrome-checker-project/meta.json b/curriculum/challenges/_meta/build-a-palindrome-checker-project/meta.json index 79bfad5d1d1923..eb8d83795df4f8 100644 --- a/curriculum/challenges/_meta/build-a-palindrome-checker-project/meta.json +++ b/curriculum/challenges/_meta/build-a-palindrome-checker-project/meta.json @@ -1,6 +1,6 @@ { "name": "Build a Palindrome Checker Project", - "isUpcomingChange": false, + "isUpcomingChange": true, "usesMultifileEditor": false, "order": 3, "time": "30 hours", @@ -13,4 +13,3 @@ "Build a Palindrome Checker" ] ]} - \ No newline at end of file diff --git a/curriculum/challenges/_meta/build-a-roman-numeral-converter-project/meta.json b/curriculum/challenges/_meta/build-a-roman-numeral-converter-project/meta.json index a87e89b0a10dfa..e8b38ed57735de 100644 --- a/curriculum/challenges/_meta/build-a-roman-numeral-converter-project/meta.json +++ b/curriculum/challenges/_meta/build-a-roman-numeral-converter-project/meta.json @@ -1,6 +1,6 @@ { "name": "Build a Roman Numeral Converter Project", - "isUpcomingChange": false, + "isUpcomingChange": true, "usesMultifileEditor": false, "order": 6, "time": "30 hours", @@ -13,4 +13,3 @@ "Build a Roman Numeral Converter" ] ]} - \ No newline at end of file diff --git a/curriculum/challenges/_meta/build-a-telephone-number-validator-project/meta.json b/curriculum/challenges/_meta/build-a-telephone-number-validator-project/meta.json index d5d6ee8bd999d9..b9857da1fc38f4 100644 --- a/curriculum/challenges/_meta/build-a-telephone-number-validator-project/meta.json +++ b/curriculum/challenges/_meta/build-a-telephone-number-validator-project/meta.json @@ -1,6 +1,6 @@ { "name": "Build a Telephone Number Validator Project", - "isUpcomingChange": false, + "isUpcomingChange": true, "usesMultifileEditor": false, "order": 10, "time": "30 hours", @@ -13,4 +13,3 @@ "Build a Telephone Number Validator" ] ]} - \ No newline at end of file diff --git a/curriculum/challenges/_meta/learn-advanced-array-methods-by-building-a-statistics-calculator/meta.json b/curriculum/challenges/_meta/learn-advanced-array-methods-by-building-a-statistics-calculator/meta.json new file mode 100644 index 00000000000000..b43593f0aa11d8 --- /dev/null +++ b/curriculum/challenges/_meta/learn-advanced-array-methods-by-building-a-statistics-calculator/meta.json @@ -0,0 +1,216 @@ +{ + "name": "Learn Advanced Array Methods by Building a Statistics Calculator", + "isUpcomingChange": true, + "usesMultifileEditor": true, + "hasEditableBoundaries": true, + "dashedName": "learn-advanced-array-methods-by-building-a-statistics-calculator", + "order": 10, + "time": "5 hours", + "template": "", + "required": [], + "superBlock": "2022/javascript-algorithms-and-data-structures", + "superOrder": 4, + "isBeta": true, + "challengeOrder": [ + [ + "635060a5c03c950f46174cb5", + "Step 1" + ], + [ + "63507b5ac8a55134223374c7", + "Step 2" + ], + [ + "63507bcbfe4ede356e624395", + "Step 3" + ], + [ + "63507c19151201368ee3e16c", + "Step 4" + ], + [ + "63507c4b63731437227b0134", + "Step 5" + ], + [ + "63507d810f1a2e38f1908fd8", + "Step 6" + ], + [ + "63507e4562cdde3a28e8de1b", + "Step 7" + ], + [ + "63507ebb0c50ce3b9d669cd9", + "Step 8" + ], + [ + "63507fc6cc29083cc44df2fb", + "Step 9" + ], + [ + "6350805fe0fe283dd347b0dc", + "Step 10" + ], + [ + "635080d80b72803e973841da", + "Step 11" + ], + [ + "6350854411ffb73feb6bb84e", + "Step 12" + ], + [ + "63508577f69f41409275f877", + "Step 13" + ], + [ + "635085da54fc2041e0303e75", + "Step 14" + ], + [ + "635085f80bd9b5429faa40c4", + "Step 15" + ], + [ + "6350866cce4c6d43bdf607c8", + "Step 16" + ], + [ + "63508750f040a348a440a0bf", + "Step 17" + ], + [ + "635089e3bd3e144f2db4094f", + "Step 18" + ], + [ + "63508abbff1c4c5210d68cc5", + "Step 19" + ], + [ + "63508bb4afb069534e81f33b", + "Step 20" + ], + [ + "63508c898d753754757bd5e3", + "Step 21" + ], + [ + "635090f47eb6d9563a6fed05", + "Step 22" + ], + [ + "635091f8dbf554575fb5aa0c", + "Step 23" + ], + [ + "6352e79d15aae30fac58f48e", + "Step 24" + ], + [ + "6352e80e024e89111600edfb", + "Step 25" + ], + [ + "6352e93db104661305c5f658", + "Step 26" + ], + [ + "6352e96d2604f813c656750b", + "Step 27" + ], + [ + "6352ea3a5b79e614ee2282fd", + "Step 28" + ], + [ + "6352ebd3ab962c168a122e85", + "Step 29" + ], + [ + "6352ec8b9c70fd17b8c7ba3f", + "Step 30" + ], + [ + "6352ecef9f045519063da9b3", + "Step 31" + ], + [ + "6352edee8a4de01ad693f0e4", + "Step 32" + ], + [ + "6352ee566a59d31d24bde74b", + "Step 33" + ], + [ + "6352f09b1e53a420e7873344", + "Step 34" + ], + [ + "6352f179bdca23221298a5ba", + "Step 35" + ], + [ + "6352f2526dccb523150b64fb", + "Step 36" + ], + [ + "6352f2a24eb71b24284ca2b6", + "Step 37" + ], + [ + "6352faf71a9db52631864634", + "Step 38" + ], + [ + "6352fbb93a91a8272f838d42", + "Step 39" + ], + [ + "6352fcb156834128001ea945", + "Step 40" + ], + [ + "6352fce75b2d3b2924930f1e", + "Step 41" + ], + [ + "6352fe473d53592a40ae403b", + "Step 42" + ], + [ + "6352fed209792d2b89e92ea1", + "Step 43" + ], + [ + "6352ff27e0e51b2c7dce0010", + "Step 44" + ], + [ + "6352ffe4cfafa72d595a0007", + "Step 45" + ], + [ + "6353004b235d7a2e0b913f2b", + "Step 46" + ], + [ + "6353024f5eab012fa2f57eec", + "Step 47" + ], + [ + "6353028147d3c7309017216a", + "Step 48" + ], + [ + "635302be760d6031d11a06cd", + "Step 49" + ], + [ + "6374249d3fbf2a5b079ba036", + "Step 50" + ] + ] +} \ No newline at end of file diff --git a/curriculum/challenges/_meta/learn-typography-by-building-a-nutrition-label/meta.json b/curriculum/challenges/_meta/learn-typography-by-building-a-nutrition-label/meta.json index cf0d7d963a4f99..a647ab2173068f 100644 --- a/curriculum/challenges/_meta/learn-typography-by-building-a-nutrition-label/meta.json +++ b/curriculum/challenges/_meta/learn-typography-by-building-a-nutrition-label/meta.json @@ -135,144 +135,148 @@ "Step 31" ], [ - "615f5486b8fd4b71633f69b0", + "6395d33ab5d91bf317107c48", "Step 32" ], [ - "615f575b50b91e72af079480", + "615f5486b8fd4b71633f69b0", "Step 33" ], [ - "615f5af373a68e744a3c5a76", + "6396e33fe478dd264ebbf278", "Step 34" ], [ - "615f5c1cb7575c7551ed8a40", + "615f575b50b91e72af079480", "Step 35" ], [ - "615f5fd85d0062761f288364", + "615f5af373a68e744a3c5a76", "Step 36" ], [ - "615f61338c8ca176d6445574", + "615f5fd85d0062761f288364", "Step 37" ], [ - "615f666ac5edea782feb7e75", + "615f61338c8ca176d6445574", "Step 38" ], [ - "615f671b6d1919792745aa5d", + "615f666ac5edea782feb7e75", "Step 39" ], [ - "615f6823d0815b7a991f2a75", + "615f671b6d1919792745aa5d", "Step 40" ], [ - "615f6a7d4ba8037bc086c2c7", + "635bde33c91c80540eae239b", "Step 41" ], [ - "615f6b2d164f81809efd9bdc", + "615f6823d0815b7a991f2a75", "Step 42" ], [ - "615f6cc778f7698258467596", + "615f6b2d164f81809efd9bdc", "Step 43" ], [ - "615f6fddaac1e083502d3e6a", + "615f6cc778f7698258467596", "Step 44" ], [ - "615f70077a4ff98424236c1e", + "615f6fddaac1e083502d3e6a", "Step 45" ], [ - "615f72a872354a850d4f533e", + "615f70077a4ff98424236c1e", "Step 46" ], [ - "615f74a71f1e498619e38ee8", + "615f72a872354a850d4f533e", "Step 47" ], [ - "615f7ad94380408d971d14f6", + "615f74a71f1e498619e38ee8", "Step 48" ], [ - "615f7bc680f7168ea01ebf99", + "615f7ad94380408d971d14f6", "Step 49" ], [ - "615f7c71eab8218f846e4503", + "615f7bc680f7168ea01ebf99", "Step 50" ], [ - "615f7d489a581590d1350288", + "615f7c71eab8218f846e4503", "Step 51" ], [ - "615f7de4487b64919bb4aa5e", + "615f7d489a581590d1350288", "Step 52" ], [ - "615f7e7281626a92bbd62da8", + "615f7de4487b64919bb4aa5e", "Step 53" ], [ - "615f7ecb09de9a938ef94756", + "615f7e7281626a92bbd62da8", "Step 54" ], [ - "615f7fa959ab75948f96a0d6", + "615f7ecb09de9a938ef94756", "Step 55" ], [ - "615f808d85793195b0f53be9", + "615f7fa959ab75948f96a0d6", "Step 56" ], [ - "615f829d07b18f96f6f6684b", + "615f808d85793195b0f53be9", "Step 57" ], [ - "615f83ef928ec9982b785b6a", + "615f829d07b18f96f6f6684b", "Step 58" ], [ - "615f84f246e8ba98e3cd97be", + "615f83ef928ec9982b785b6a", "Step 59" ], [ - "615f887466db4ba14b5342cc", + "615f84f246e8ba98e3cd97be", "Step 60" ], [ - "615f89e055040ba294719d2f", + "615f887466db4ba14b5342cc", "Step 61" ], [ - "615f8bfe0f30a1a3c340356b", + "615f89e055040ba294719d2f", "Step 62" ], [ - "615f8f1223601fa546e93f31", + "615f8bfe0f30a1a3c340356b", "Step 63" ], [ - "615f905fbd1017a65ca224eb", + "615f8f1223601fa546e93f31", "Step 64" ], [ - "615f94786869e1a7fec54375", + "615f905fbd1017a65ca224eb", "Step 65" ], [ - "615f951dff9317a900ef683f", + "615f94786869e1a7fec54375", "Step 66" + ], + [ + "615f951dff9317a900ef683f", + "Step 67" ] ] -} +} \ No newline at end of file diff --git a/curriculum/challenges/_meta/top-build-a-recipe-project/meta.json b/curriculum/challenges/_meta/top-build-a-recipe-project/meta.json new file mode 100644 index 00000000000000..df2b93d2096c34 --- /dev/null +++ b/curriculum/challenges/_meta/top-build-a-recipe-project/meta.json @@ -0,0 +1,15 @@ +{ + "name": "TOP build a recipe project", + "isUpcomingChange": true, + "order": 1, + "time": "", + "template": "", + "required": [], + "superBlock": "the-odin-project", + "challengeOrder": [ + [ + "6391d1a4f7ac71efd0621380", + "Build a Recipe Page Project" + ] + ] +} diff --git a/curriculum/challenges/_meta/top-learn-html-foundations/meta.json b/curriculum/challenges/_meta/top-learn-html-foundations/meta.json new file mode 100644 index 00000000000000..b15490e569cc83 --- /dev/null +++ b/curriculum/challenges/_meta/top-learn-html-foundations/meta.json @@ -0,0 +1,119 @@ +{ + "name": "TOP Learn HTML Foundations", + "isUpcomingChange": true, + "order": 0, + "time": "", + "template": "", + "required": [], + "superBlock": "the-odin-project", + "challengeOrder": [ + [ + "6374f208de18c50e48ba767b", + "Introduction To HTML and CSS Question A" + ], + [ + "6376327e2724a688c04636e3", + "Introduction To HTML and CSS Question B" + ], + [ + "637633162724a688c04636e4", + "Introduction To HTML and CSS Question C" + ], + [ + "637633672724a688c04636e5", + "Introduction To HTML and CSS Question D" + ], + [ + "637f4e0e72c65bc8e73dfe1e", + "Elements and Tags Question A" + ], + [ + "637f4e1672c65bc8e73dfe1f", + "Elements and Tags Question B" + ], + [ + "637f4e1c72c65bc8e73dfe20", + "HTML Boilerplate Question A" + ], + [ + "637f4e2872c65bc8e73dfe21", + "HTML Boilerplate Question B" + ], + [ + "637f4e2f72c65bc8e73dfe22", + "HTML Boilerplate Question C" + ], + [ + "637f4e3672c65bc8e73dfe23", + "HTML Boilerplate Question D" + ], + [ + "637f4e5872c65bc8e73dfe27", + "Working With Text Question A" + ], + [ + "637f4e5f72c65bc8e73dfe28", + "Working With Text Question B" + ], + [ + "637f4e6672c65bc8e73dfe29", + "Working With Text Question C" + ], + [ + "637f4e6e72c65bc8e73dfe2a", + "Working With Text Question D" + ], + [ + "637f4e7972c65bc8e73dfe2b", + "Working With Text Question E" + ], + [ + "637f4e8072c65bc8e73dfe2c", + "Working With Text Question F" + ], + [ + "637f4e8772c65bc8e73dfe2d", + "Working With Text Question G" + ], + [ + "637f4e3e72c65bc8e73dfe24", + "Understand Ordered and Unordered List Question A" + ], + [ + "637f4e4672c65bc8e73dfe25", + "Understand Ordered and Unordered List Question B" + ], + [ + "637f4e5172c65bc8e73dfe26", + "Understand ordered and Unordered List Question C" + ], + [ + "637f704072c65bc8e73dfe36", + "Links and Images Question A" + ], + [ + "637f703572c65bc8e73dfe35", + "Links and Images Question B" + ], + [ + "637f703072c65bc8e73dfe34", + "Links and Images Question C" + ], + [ + "637f702872c65bc8e73dfe33", + "Links and Images Question D" + ], + [ "637f702372c65bc8e73dfe32", + "Links and Images Question E" + ], + [ "637f701c72c65bc8e73dfe31", + "Links and Images Question F" + ], + [ "637f701572c65bc8e73dfe30", + "Links and Images Question G" + ], + [ "637f700b72c65bc8e73dfe2f", + "Links and Images Question D" + ] + ] +} diff --git a/curriculum/challenges/arabic/00-certifications/data-visualization-certification/data-visualization-certification.yml b/curriculum/challenges/arabic/00-certifications/data-visualization-certification/data-visualization-certification.yml index 1a22cbbd33da7c..d77cefc4226fd8 100644 --- a/curriculum/challenges/arabic/00-certifications/data-visualization-certification/data-visualization-certification.yml +++ b/curriculum/challenges/arabic/00-certifications/data-visualization-certification/data-visualization-certification.yml @@ -7,7 +7,7 @@ isPrivate: true tests: - id: bd7168d8c242eddfaeb5bd13 - title: التصوير المرئي للبيانات باستخدام مخطط بياني للأعمدة + title: التصوير المرئي للبيانات باستخدام مخطط الأعمدة - id: bd7178d8c242eddfaeb5bd13 title: التصوير المرئي للبيانات باستخدام مخطط التشتت diff --git a/curriculum/challenges/arabic/00-certifications/front-end-development-libraries-certification/front-end-development-libraries-certification.yml b/curriculum/challenges/arabic/00-certifications/front-end-development-libraries-certification/front-end-development-libraries-certification.yml index e00138af76c4fa..b65e0f5cbfe141 100644 --- a/curriculum/challenges/arabic/00-certifications/front-end-development-libraries-certification/front-end-development-libraries-certification.yml +++ b/curriculum/challenges/arabic/00-certifications/front-end-development-libraries-certification/front-end-development-libraries-certification.yml @@ -13,10 +13,10 @@ tests: title: بناء عارض Markdown - id: 587d7dbc367417b2b2512bae - title: بناء آلة الدرامز + title: أنشئ آلة الطبول - id: bd7158d8c442eddfaeb5bd17 - title: بناء آلة حاسبة بإستخدام JavaScript + title: ابن آلة حاسبة باستخدام JavaScript - id: bd7158d8c442eddfaeb5bd0f title: بناء ساعة 25 + 5 diff --git a/curriculum/challenges/arabic/00-certifications/javascript-algorithms-and-data-structures-certification/javascript-algorithms-and-data-structures-certification.yml b/curriculum/challenges/arabic/00-certifications/javascript-algorithms-and-data-structures-certification/javascript-algorithms-and-data-structures-certification.yml index 3349d7cd478965..dbfa713d1db0b6 100644 --- a/curriculum/challenges/arabic/00-certifications/javascript-algorithms-and-data-structures-certification/javascript-algorithms-and-data-structures-certification.yml +++ b/curriculum/challenges/arabic/00-certifications/javascript-algorithms-and-data-structures-certification/javascript-algorithms-and-data-structures-certification.yml @@ -7,16 +7,16 @@ isPrivate: true tests: - id: aaa48de84e1ecc7c742e1124 - title: فاحص الـ Palindrome + title: مدقق لمعاكس المقطع النصي - id: a7f4d8f2483413a6ce226cac - title: محول الأرقام الرومانية + title: محول للأرقام الرومانية - id: 56533eb9ac21ba0edf2244e2 - title: شفرة قيصر (Caesars Cipher) + title: شفرة قيصر - id: aff0395860f5d3034dc0bfc9 - title: مدقق رقم الهاتف + title: مدقق لرقم الهاتف - id: aa2e6f85cab2ab736c9a9b24 - title: ماكينة تسجيل المدفوعات النقدية + title: مكنة لتسجيل النقود diff --git a/curriculum/challenges/arabic/00-certifications/legacy-data-visualization-certification/legacy-data-visualization-certification.yml b/curriculum/challenges/arabic/00-certifications/legacy-data-visualization-certification/legacy-data-visualization-certification.yml index 04ac3369a4fcce..19885830ef35d5 100644 --- a/curriculum/challenges/arabic/00-certifications/legacy-data-visualization-certification/legacy-data-visualization-certification.yml +++ b/curriculum/challenges/arabic/00-certifications/legacy-data-visualization-certification/legacy-data-visualization-certification.yml @@ -22,7 +22,7 @@ tests: title: بناء لعبة Roguelike Dungeon Crawler - id: bd7168d8c242eddfaeb5bd13 - title: التصوير المرئي للبيانات باستخدام مخطط بياني للأعمدة + title: التصوير المرئي للبيانات باستخدام مخطط الأعمدة - id: bd7178d8c242eddfaeb5bd13 title: التصوير المرئي للبيانات باستخدام مخطط التشتت diff --git a/curriculum/challenges/arabic/00-certifications/legacy-front-end-certification/legacy-front-end-certification.yml b/curriculum/challenges/arabic/00-certifications/legacy-front-end-certification/legacy-front-end-certification.yml index 41c89333ec83d5..25e29896e5d357 100644 --- a/curriculum/challenges/arabic/00-certifications/legacy-front-end-certification/legacy-front-end-certification.yml +++ b/curriculum/challenges/arabic/00-certifications/legacy-front-end-certification/legacy-front-end-certification.yml @@ -1,13 +1,13 @@ --- id: 561add10cb82ac38a17513be -title: شهادة الواجهة الأمامية القديمة +title: شهادة الواجهة الأمامية التراثية certification: legacy-front-end challengeType: 7 isPrivate: true tests: - id: bd7158d8c242eddfaeb5bd13 - title: قم ببناء صفحة ويب لعرض نماذج الأعمال الشخصية + title: أنشئ معرضا لأعمالك الخاصة - id: bd7158d8c442eddfaeb5bd13 title: قم ببناء آلة عرض اقتباسات عشوائية @@ -16,7 +16,7 @@ tests: title: قم ببناء ساعة 25 + 5 - id: bd7158d8c442eddfaeb5bd17 - title: بناء آلة حاسبة بإستخدام JavaScript + title: بناء آلة حاسبة باستخدام JavaScript - id: bd7158d8c442eddfaeb5bd10 title: إظهار الطقس المحلي diff --git a/curriculum/challenges/arabic/00-certifications/legacy-full-stack-certification/legacy-full-stack-certification.yml b/curriculum/challenges/arabic/00-certifications/legacy-full-stack-certification/legacy-full-stack-certification.yml index e9ca568670698e..d22c82b228b4eb 100644 --- a/curriculum/challenges/arabic/00-certifications/legacy-full-stack-certification/legacy-full-stack-certification.yml +++ b/curriculum/challenges/arabic/00-certifications/legacy-full-stack-certification/legacy-full-stack-certification.yml @@ -1,6 +1,6 @@ --- id: 561add10cb82ac38a17213bd -title: شهادة الـ Full Stack القديمة +title: شهادة الـ Full Stack التراثية certification: legacy-full-stack challengeType: 7 isPrivate: true @@ -13,13 +13,13 @@ tests: title: شهادة الخوارزميات وهياكل البيانات في JavaScript - id: 561acd10cb82ac38a17513bc - title: شهادة مكتبات تطوير واجهة المستخدم (Front End Libraries) + title: شهادة مكتبات Front End - id: 5a553ca864b52e1d8bceea14 - title: شهادة Data Visualization + title: شهادة التصور المرئي للبيانات - id: 561add10cb82ac38a17523bc - title: شهادة API's and Microservice + title: شهادة واجهة برمجة التطبيقات (API) والخدمات المصغّرة - id: 561add10cb82ac38a17213bc - title: شهادة أمن المعلومات القديمة وشهادة ضمان الجودة + title: شهادة أمن المعلومات التراثية وشهادة ضمان الجودة diff --git a/curriculum/challenges/arabic/00-certifications/legacy-information-security-and-quality-assurance-certification/legacy-information-security-and-quality-assurance-certification.yml b/curriculum/challenges/arabic/00-certifications/legacy-information-security-and-quality-assurance-certification/legacy-information-security-and-quality-assurance-certification.yml index 66f533142b3e1b..60777ae960738b 100644 --- a/curriculum/challenges/arabic/00-certifications/legacy-information-security-and-quality-assurance-certification/legacy-information-security-and-quality-assurance-certification.yml +++ b/curriculum/challenges/arabic/00-certifications/legacy-information-security-and-quality-assurance-certification/legacy-information-security-and-quality-assurance-certification.yml @@ -1,6 +1,6 @@ --- id: 561add10cb82ac38a17213bc -title: شهادة أمن المعلومات القديمة وشهادة ضمان الجودة +title: شهادة أمن المعلومات التراثية وشهادة ضمان الجودة certification: legacy-information-security-and-quality-assurance challengeType: 7 isPrivate: true diff --git a/curriculum/challenges/arabic/00-certifications/responsive-web-design-certification/responsive-web-design-certification.yml b/curriculum/challenges/arabic/00-certifications/responsive-web-design-certification/responsive-web-design-certification.yml index 341301ba269bf4..e8e2df55dc5621 100644 --- a/curriculum/challenges/arabic/00-certifications/responsive-web-design-certification/responsive-web-design-certification.yml +++ b/curriculum/challenges/arabic/00-certifications/responsive-web-design-certification/responsive-web-design-certification.yml @@ -7,7 +7,7 @@ isPrivate: true tests: - id: bd7158d8c442eddfaeb5bd18 - title: بناء صفحة تحية + title: أنشئ مشروع صفحة الثناء - id: 587d78af367417b2b2512b03 title: بناء نموذج استطلاع رأي @@ -16,7 +16,7 @@ tests: title: بناء الصفحة الرئيسة لمنتج - id: 587d78b0367417b2b2512b05 - title: أنشئ صفحة التوثيق الفني + title: أنشئ صفحة التوثيق التقنية - id: bd7158d8c242eddfaeb5bd13 - title: قم ببناء مشروع صفحة ويب لعرض نماذج الاعمال الشخصية + title: أنشئ معرضا لأعمالك الخاصة diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/add-a-text-alternative-to-images-for-visually-impaired-accessibility.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/add-a-text-alternative-to-images-for-visually-impaired-accessibility.md index 27f9c91bb751f0..a957e919b1aa85 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/add-a-text-alternative-to-images-for-visually-impaired-accessibility.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/add-a-text-alternative-to-images-for-visually-impaired-accessibility.md @@ -21,7 +21,7 @@ dashedName: add-a-text-alternative-to-images-for-visually-impaired-accessibility # --instructions-- -كامبر القط هو نينجا في البرمجة وهو أيضا نينجا حقيقي، يقوم ببناء صفحة ويب لمشاركة معرفتة. الصورة الشخصية التي يريد استخدامها تظهر مهاراته ويجب أن تحظي بتقدير جميع زوار الموقع. أضف خاصية (attribute) `alt` في الوسم (tag) `img` لتظهر أن كامبر القط يجيد لعبة الكاراتية. (خاصية الصورة `src` لا ترتبط بملف فعلي، لذا يجب أن ترى نص `alt` في العرض.) +Camper Cat هو نينجا في البرمجة وهو أيضا نينجا حقيقي، يقوم ببناء صفحة ويب لمشاركة معرفتة. الصورة الشخصية التي يريد استخدامها تظهر مهاراته ويجب أن تحظي بتقدير جميع زوار الموقع. أضف خاصية (attribute) `alt` في الوسم (tag) `img` لتظهر أن Camper Cat يجيد لعبة الكاراتية. (خاصية الصورة `src` لا ترتبط بملف فعلي، لذا يجب أن ترى نص `alt` في العرض.) # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/add-an-accessible-date-picker.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/add-an-accessible-date-picker.md index f54b40bdd31fbe..e434da4f1de91d 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/add-an-accessible-date-picker.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/add-an-accessible-date-picker.md @@ -24,29 +24,29 @@ dashedName: add-an-accessible-date-picker # --instructions-- -يقوم Camper Cat بإعداد بطولة Mortal Kombat ويريد أن يطلب من منافسيه معرفة التاريخ الأفضل. أضف وسم `input` مع سمة `type` من نوع `date` ، وسمة `id` بقيمة `pickdate`، و سمة `name` بقيمة `date`. +يقوم Camper Cat بإعداد بطولة Mortal Kombat ويريد أن يطلب من منافسيه معرفة التاريخ الأفضل. أضف علامة `input` مع سمة `type` من نوع `date`، و مع سمة `id` بقيمة `pickdate`، و أيضا سمة `name` بقيمة `date`. # --hints-- -يجب أن يحتوي الكود علي وسم `input` واحد لحقل محدد التاريخ. +يجب أن يحتوي الكود علي علامة `input` واحد لخانة محدد التاريخ. ```js assert($('input').length == 2); ``` -يجب أن يحتوي وسم `input` على سمة `type` بقيمة `date`. +يجب أن يحتوي علامة `input` على سمة `type` بقيمة `date`. ```js assert($('input').attr('type') == 'date'); ``` -يجب أن يحتوي وسم `input` على سمة `id` بقيمة `pickdate`. +يجب أن يحتوي علامة `input` على سمة `id` بقيمة `pickdate`. ```js assert($('input').attr('id') == 'pickdate'); ``` -يجب أن يحتوي وسم `input` على سمة `name` بقيمة `date`. +يجب أن يحتوي علامة `input` على سمة `name` بقيمة `date`. ```js assert($('input').attr('name') == 'date'); diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-carefully-choosing-colors-that-convey-information.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-carefully-choosing-colors-that-convey-information.md index 2f21941dc92f84..ee510da38e3c68 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-carefully-choosing-colors-that-convey-information.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-carefully-choosing-colors-that-convey-information.md @@ -19,7 +19,7 @@ dashedName: >- # --instructions-- -تختبر Camper Cat أنماطًا مختلفة لزر مهم ، ولكن اللون الأصفر للخلفة (`#FFFF33`) `background-color` و الاخضر (`#33FF33`) `color`لون النص هي درجات مجاورة على عجلة الألوان ولا يمكن تمييزها فعليًا عند بعض المصابين بعمى الألوان. (خفتهم المتشابهة تفشل أيضًا في فحص نسبة التباين). غيّر لون النص `color` إلى اللون الأزرق المظلم (`#003366`) لحل كلتا المشكلتين. +يختبر Camper Cat أنماطًا مختلفة لزر مهم، ولكن اللون الأصفر (`#FFFF33`) للخلفية (`background-color`) و الاخضر (`#33FF33`) للون النص (`color`) هي درجات مجاورة على عجلة الألوان ولا يمكن لبعض المصابين بعمى الألوان التمييز ببنهم. (خفتهم المتشابهة تفشل أيضًا في فحص نسبة التباين). غيّر لون النص `color` إلى اللون الأزرق المظلم (`#003366`) لحل كلتا المشكلتين. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-using-sufficient-contrast.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-using-sufficient-contrast.md index 133f49e990f454..afad525b088327 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-using-sufficient-contrast.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/avoid-colorblindness-issues-by-using-sufficient-contrast.md @@ -19,7 +19,7 @@ dashedName: avoid-colorblindness-issues-by-using-sufficient-contrast # --instructions-- -يقوم Camper Cat بتجربة استخدام الألوان لنص مدونته وخلفيتها ، ولكن دمجة الحالي لللون الأخضر للخلفية `background-color` مع لون النص الماروني `color` له نسبة تباين 2.5:1. يمكنك بسهولة ضبط إضاءة الألوان بما اته عرفها، باستخدام خاصية في الـ CSS و هي `hsl()` (التي تمثل hue بمعني التدرج و saturation بمعني التشبع و lightness بمعني الخفة) بتغيير الوسيطة (argument) الثالثة. زيادة قيمة الخفة lightness للون الخلفية `background-color` من 35% إلى 55%، وتقليل قيمة الخفة لـ `color` من 20% إلى 15%. وهذا ما يحسّن التباين إلى 5.9:1. +يقوم Camper Cat بتجربة استخدام الألوان لنص مدونته وخلفيتها، ولكن دمجة لألون الأخضر للخلفية `background-color` مع لون النص الماروني (maroon) الحالي `color` له نسبة تباين 2.5:1. يمكنك بسهولة ضبط إضاءة الألوان بما اته عرفها، باستخدام خاصية في الـ CSS و هي `hsl()` (التي تمثل hue بمعني التدرج و saturation بمعني التشبع و lightness بمعني الخفة) بتغيير الوسيطة (argument) الثالثة. زيادة قيمة الخفة lightness للون الخلفية `background-color` من 35% إلى 55%، وتقليل قيمة الخفة لـ `color` من 20% إلى 15%. وهذا ما يحسّن التباين إلى 5.9:1. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/give-links-meaning-by-using-descriptive-link-text.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/give-links-meaning-by-using-descriptive-link-text.md index 91ab935f674991..6da59306862ece 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/give-links-meaning-by-using-descriptive-link-text.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/give-links-meaning-by-using-descriptive-link-text.md @@ -11,11 +11,11 @@ dashedName: give-links-meaning-by-using-descriptive-link-text Screen reader users have various options for what type of content their device reads. These options include skipping to (or over) landmark elements, jumping to the main content, or getting a page summary from the headings. Another option is to only hear the links available on a page. -Screen readers do this by reading the link text, or what's between the anchor (`a`) tags. Having a list of "click here" or "read more" links isn't helpful. Instead, use brief but descriptive text within the `a` tags to provide more meaning for these users. +قارئ الشاشة يفعل ذلك بقراءة نص الرابط، أو ما بين علامات الرابط (`a`). Having a list of "click here" or "read more" links isn't helpful. Instead, use brief but descriptive text within the `a` tags to provide more meaning for these users. # --instructions-- -The link text that Camper Cat is using is not very descriptive without the surrounding context. Move the anchor (`a`) tags so they wrap around the text `information about batteries` instead of `Click here`. +نص الرابط الذي يستخدمه Camper Cat ليس وصفياً جداً بدون السياق المحيط. انقل علامات الرابط (`a`) بحيث تلتف حول النص `information about batteries` بدلاً من `Click here`. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-accessibility-of-audio-content-with-the-audio-element.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-accessibility-of-audio-content-with-the-audio-element.md index 8e5ff50fc468d0..0a9674923a445f 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-accessibility-of-audio-content-with-the-audio-element.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-accessibility-of-audio-content-with-the-audio-element.md @@ -26,7 +26,7 @@ Here's an example: # --instructions-- -Time to take a break from Camper Cat and meet fellow camper Zersiax (@zersiax), a champion of accessibility and a screen reader user. To hear a clip of his screen reader in action, add an `audio` element after the `p`. Include the `controls` attribute. Then place a `source` tag inside the `audio` tags with the `src` attribute set to `https://s3.amazonaws.com/freecodecamp/screen-reader.mp3` and `type` attribute set to `"audio/mpeg"`. +حان الوقت لأخذ استراحة من Camper Cat و مقابلة الزميل camper Zersiax (@zersiax), بطل ال accessibility و مستخدم لتقنية قارئ الشاشة (screen reader). To hear a clip of his screen reader in action, add an `audio` element after the `p`. Include the `controls` attribute. Then place a `source` tag inside the `audio` tags with the `src` attribute set to `https://s3.amazonaws.com/freecodecamp/screen-reader.mp3` and `type` attribute set to `"audio/mpeg"`. **Note:** The audio clip may sound fast and be difficult to understand, but that is a normal speed for screen reader users. diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-chart-accessibility-with-the-figure-element.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-chart-accessibility-with-the-figure-element.md index d677e66b94008c..168b6351e7ea02 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-chart-accessibility-with-the-figure-element.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-chart-accessibility-with-the-figure-element.md @@ -27,7 +27,7 @@ Here's an example - note that the `figcaption` goes inside the `figure` tags and # --instructions-- -Camper Cat is hard at work creating a stacked bar chart showing the amount of time per week to spend training in stealth, combat, and weapons. Help him structure his page better by changing the `div` tag he used to a `figure` tag, and the `p` tag that surrounds the caption to a `figcaption` tag. +Camper Cat شاق في العمل لإنشاء مخطط أعمدة مكدسة يبين مقدار الوقت في الأسبوع لقضاء التدريب على السرقة، القتال والأسلحة. Help him structure his page better by changing the `div` tag he used to a `figure` tag, and the `p` tag that surrounds the caption to a `figcaption` tag. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-form-field-accessibility-with-the-label-element.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-form-field-accessibility-with-the-label-element.md index 55492a9a50e968..8348eb4e910183 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-form-field-accessibility-with-the-label-element.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-form-field-accessibility-with-the-label-element.md @@ -26,7 +26,7 @@ The value of the `for` attribute must be the same as the value of the `id` attri # --instructions-- -Camper Cat expects a lot of interest in his thoughtful blog posts and wants to include an email sign up form. Add a `for` attribute on the email `label` that matches the `id` on its `input` field. +تنتظر Camper Cat الكثير من الاهتمام في مشاركاته المدونة المدروسة وترغب في تضمين نموذج تسجيل البريد الإلكتروني. Add a `for` attribute on the email `label` that matches the `id` on its `input` field. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-readability-with-high-contrast-text.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-readability-with-high-contrast-text.md index 8bf9b62cf5731d..b3d9a57f918359 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-readability-with-high-contrast-text.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/improve-readability-with-high-contrast-text.md @@ -15,7 +15,7 @@ The Web Content Accessibility Guidelines (WCAG) recommend at least a 4.5 to 1 co # --instructions-- -Camper Cat's choice of light gray text on a white background for his recent blog post has a 1.5:1 contrast ratio, making it hard to read. Change the `color` of the text from the current gray (`#D3D3D3`) to a darker gray (`#636363`) to improve the contrast ratio to 6:1. +اختيار Camper Cat للنص الرمادي الخفيف على خلفية بيضاء لمشاركته الأخيرة يحتوي على 1.5:1 نسبة التباين، مما يجعل من الصعب قراءتها. Change the `color` of the text from the current gray (`#D3D3D3`) to a darker gray (`#636363`) to improve the contrast ratio to 6:1. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/jump-straight-to-the-content-using-the-main-element.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/jump-straight-to-the-content-using-the-main-element.md index 83031edde59ed2..02ebc2ac766197 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/jump-straight-to-the-content-using-the-main-element.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/jump-straight-to-the-content-using-the-main-element.md @@ -19,7 +19,7 @@ The `main` tag also has an embedded landmark feature that assistive technology c # --instructions-- -Camper Cat has some big ideas for his ninja weapons page. Help him set up his markup by adding opening and closing `main` tags between the `header` and `footer` (covered in other challenges). Keep the `main` tags empty for now. +Camper Cat لديه بعض الأفكار الكبيرة لصفحة أسلحة النينجا. Help him set up his markup by adding opening and closing `main` tags between the `header` and `footer` (covered in other challenges). Keep the `main` tags empty for now. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/know-when-alt-text-should-be-left-blank.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/know-when-alt-text-should-be-left-blank.md index 695445ea37e647..7b46cb25d313bd 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/know-when-alt-text-should-be-left-blank.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/know-when-alt-text-should-be-left-blank.md @@ -23,7 +23,7 @@ Background images usually fall under the 'decorative' label as well. However, th # --instructions-- -Camper Cat has coded a skeleton page for the blog part of his website. He's planning to add a visual break between his two articles with a decorative image of a samurai sword. Add an `alt` attribute to the `img` tag and set it to an empty string. (Note that the image `src` doesn't link to an actual file - don't worry that there are no swords showing in the display.) +قام Camper Cat ببرمجة هيكل الصفحة لمدونة موقعه. He's planning to add a visual break between his two articles with a decorative image of a samurai sword. Add an `alt` attribute to the `img` tag and set it to an empty string. (Note that the image `src` doesn't link to an actual file - don't worry that there are no swords showing in the display.) # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-elements-only-visible-to-a-screen-reader-by-using-custom-css.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-elements-only-visible-to-a-screen-reader-by-using-custom-css.md index 63bfea4b75cc0d..f3c52234204dad 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-elements-only-visible-to-a-screen-reader-by-using-custom-css.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-elements-only-visible-to-a-screen-reader-by-using-custom-css.md @@ -35,7 +35,7 @@ Here's an example of the CSS rules that accomplish this: # --instructions-- -Camper Cat created a really cool stacked bar chart for his training page, and put the data into a table for his visually impaired users. The table already has an `sr-only` class, but the CSS rules aren't filled in yet. Give the `position` an `absolute` value, the `left` a `-10000px` value, and the `width` and `height` both `1px` values. +أنشأ Camper Cat مخطط أعمدة مكدسة رائع جدا لصفحة التدريب، و وضع البيانات في جدول لمستخدميه ذوي الإعاقة البصرية. The table already has an `sr-only` class, but the CSS rules aren't filled in yet. Give the `position` an `absolute` value, the `left` a `-10000px` value, and the `width` and `height` both `1px` values. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-links-navigable-with-html-access-keys.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-links-navigable-with-html-access-keys.md index ba72f6d7976780..a738ee9f87e21e 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-links-navigable-with-html-access-keys.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-links-navigable-with-html-access-keys.md @@ -21,7 +21,7 @@ Here's an example: # --instructions-- -Camper Cat wants the links around the two blog article titles to have keyboard shortcuts so his site's users can quickly navigate to the full story. Add an `accesskey` attribute to both links and set the first one to `g` (for Garfield) and the second one to `c` (for Chuck Norris). +يريد Camper Cat أن يكون للرابطان حول عنوان مقالات المدونة اختصارات لوحة المفاتيح (keyboard shortcuts) حتى يتمكن مستخدمو موقعه من الانتقال بسرعة إلى القصة الكاملة. Add an `accesskey` attribute to both links and set the first one to `g` (for Garfield) and the second one to `c` (for Chuck Norris). # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-footer-landmark.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-footer-landmark.md index 3330ea186d7bf9..f536b53a165e94 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-footer-landmark.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-footer-landmark.md @@ -13,7 +13,7 @@ Similar to `header` and `nav`, the `footer` element has a built-in landmark feat # --instructions-- -Camper Cat's training page is making good progress. Change the `div` he used to wrap his copyright information at the bottom of the page to a `footer` element. +صفحة تدريب Camper Cat تحرز تقدما جيدا. Change the `div` he used to wrap his copyright information at the bottom of the page to a `footer` element. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-header-landmark.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-header-landmark.md index babce0170895de..5c4b08403548fa 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-header-landmark.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-header-landmark.md @@ -9,11 +9,11 @@ dashedName: make-screen-reader-navigation-easier-with-the-header-landmark # --description-- -عنصر الـ HTML5 التالي الذي يضيف المعنى الدلالي ويحسن إمكانية الوصول هو عنصر الـ `header`. يستخدم لإحتواء المعلومات التمهيدية أو روابط التنقل لعنصره الاساسي ويعمل بشكل جيد مع المحتوى المتكرر في الأعلى على الصفحات متعددة. +عنصر الـ HTML5 التالي الذي يضيف المعنى الدلالي ويحسن إمكانية الوصول هو عنصر `header`. يستخدم لاحتواء المعلومات التمهيدية أو روابط التنقل لعنصره آلأساسي ويعمل بشكل جيد مع المحتوى المتكرر في الأعلى على الصفحات متعددة. `header` يشاركك الميزة البارزة المدمجة التي رأيتها مع `main`، مما يسمح للتكنولوجيات المساعدة بالانتقال بسرعة إلى ذلك المحتوى. -**ملاحظة:** عنصر الـ `header` يستخدم في عنصر `body` بمستند HTML الخاص بك. وهذا يختلف عن عن عنصر الـ `head` الذي يحتوي على عنوان الصفحة، معلومات تعريفية، و الخ. +**ملاحظة:** عنصر `header` يستخدم في عنصر `body` بمستند HTML الخاص بك. وهذا يختلف عن عن عنصر الـ `head` الذي يحتوي على عنوان الصفحة، معلومات تعريفية، و الخ. # --instructions-- @@ -21,13 +21,13 @@ dashedName: make-screen-reader-navigation-easier-with-the-header-landmark # --hints-- -يجب أن يحتوي الكود الخاص بك على `header` واحد فقط. +يجب أن يحتوي الكود الخاص بك على علامة `header` واحدة فقط. ```js assert($('header').length == 1); ``` -يجب أن يحتوي عنصر `header` عنصر الـ `h1`. +يجب أن يحتوي عنصر `header` على عنصر `h1`. ```js assert($('header').children('h1').length == 1); diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-nav-landmark.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-nav-landmark.md index 906d7dd5c8348f..f73869217142da 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-nav-landmark.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/make-screen-reader-navigation-easier-with-the-nav-landmark.md @@ -15,7 +15,7 @@ If there are repeated site links at the bottom of the page, it isn't necessary t # --instructions-- -Camper Cat included navigation links at the top of his training page, but wrapped them in a `div`. Change the `div` to a `nav` tag to improve the accessibility on his page. +تضمن Camper Cat وصلات تنقل من الجزء العلوي من صفحة التدريب، لكنه لفها في `div`. Change the `div` to a `nav` tag to improve the accessibility on his page. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/standardize-times-with-the-html5-datetime-attribute.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/standardize-times-with-the-html5-datetime-attribute.md index d9318d50f7bcca..3892d3ff1bc129 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/standardize-times-with-the-html5-datetime-attribute.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/standardize-times-with-the-html5-datetime-attribute.md @@ -19,7 +19,7 @@ Here's an example: # --instructions-- -Camper Cat's Mortal Kombat survey results are in! Wrap a `time` tag around the text `Thursday, September 15th` and add a `datetime` attribute to it set to `2016-09-15`. +صدرت نتائج استقصاء Camper Cat في Mortal Kombat! Wrap a `time` tag around the text `Thursday, September 15th` and add a `datetime` attribute to it set to `2016-09-15`. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/use-headings-to-show-hierarchical-relationships-of-content.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/use-headings-to-show-hierarchical-relationships-of-content.md index fbb95eaf6b164f..4feaf983881252 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/use-headings-to-show-hierarchical-relationships-of-content.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/use-headings-to-show-hierarchical-relationships-of-content.md @@ -23,7 +23,7 @@ One final point, each page should always have one (and only one) `h1` element, w # --instructions-- -Camper Cat wants a page on his site dedicated to becoming a ninja. Help him fix the headings so his markup gives semantic meaning to the content, and shows the proper parent-child relationships of his sections. Change all the `h5` tags to the proper heading level to indicate they are subsections of the `h2` ones. Use `h3` tags for the purpose. +يريد Camper Cat صفحة مخصصة على موقعه الإلكتروني لتعليم النينجا. Help him fix the headings so his markup gives semantic meaning to the content, and shows the proper parent-child relationships of his sections. Change all the `h5` tags to the proper heading level to indicate they are subsections of the `h2` ones. Use `h3` tags for the purpose. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/use-tabindex-to-add-keyboard-focus-to-an-element.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/use-tabindex-to-add-keyboard-focus-to-an-element.md index 0ae730fc94b2d5..cfd48fbd8290e7 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/use-tabindex-to-add-keyboard-focus-to-an-element.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/use-tabindex-to-add-keyboard-focus-to-an-element.md @@ -21,7 +21,7 @@ Certain elements, such as links and form controls, automatically receive keyboar # --instructions-- -Camper Cat created a new survey to collect information about his users. He knows input fields automatically get keyboard focus, but he wants to make sure his keyboard users pause at the instructions while tabbing through the items. Add a `tabindex` attribute to the `p` tag and set its value to `0`. Bonus - using `tabindex` also enables the CSS pseudo-class `:focus` to work on the `p` tag. +أنشأ Camper Cat استبيانا جديدا لجمع المعلومات عن مستخدمي موقعه. He knows input fields automatically get keyboard focus, but he wants to make sure his keyboard users pause at the instructions while tabbing through the items. Add a `tabindex` attribute to the `p` tag and set its value to `0`. Bonus - using `tabindex` also enables the CSS pseudo-class `:focus` to work on the `p` tag. # --hints-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/wrap-content-in-the-article-element.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/wrap-content-in-the-article-element.md index f6eaf6e3697369..0ec49e8d271e50 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/wrap-content-in-the-article-element.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/wrap-content-in-the-article-element.md @@ -9,7 +9,7 @@ dashedName: wrap-content-in-the-article-element # --description-- -`article` هو عنصر آخر من عناصر HTML5 الجديدة التي تضيف المعنى الدلالي الي الـ markup. `article` هو عنصر تقسيم ويستخدم لتغليف المحتوي القائم بذاته. يعمل الوسم بشكل جيد مع إدخالات المدونة أو مشاركات المنتدى أو المقالات الإخبارية. +`article` هو عنصر آخر من عناصر HTML5 الجديدة التي تضيف المعنى الدلالي الي الـ markup. `article` هو عنصر تقسيم ويستخدم لتغليف المحتوي القائم بذاته. يعمل العلامة بشكل جيد مع إدخالات المدونة أو مشاركات المنتدى أو المقالات الإخبارية. تحديد فيما إذا كان المحتوى يستطيع أن يكون مستقلا هو عادة حكم شخصي، ولكن هناك عدة اختبارات بسيطة يمكنك استخدامها. اسأل نفسك إذا كنت قد قمت بإزالة كل السياق المحيط، هل سيظل المحتوى منطقياً؟ وبالمثل بالنسبة للنص، هل سيظل المحتوى صحيحا إذا كان في RSS feed ؟ @@ -21,17 +21,17 @@ dashedName: wrap-content-in-the-article-element # --instructions-- -استخدم Camper Cat وسوم `article` لتغليف المشاركات على صفحة مدونته، لكنه نسي استخدامها حول المشاركة العلوية. قم بتغيير وسم `div` لاستخدام وسم `article` بدلاً منه. +استخدم Camper Cat علامات `article` لتغليف المشاركات على صفحة مدونته، لكنه نسي استخدامها حول المشاركة العلوية. قم بتغيير علامة `div` لاستخدام علامة `article` بدلاً منه. # --hints-- -الكود الخاص بك يجب أن يحتوي على ثلاث وسوم `article`. +الكود الخاص بك يجب أن يحتوي على ثلاث علامات `article`. ```js assert($('article').length == 3); ``` -يجب ألا يحتوي الكود الخاص بك علي اي وسوم `div`. +يجب ألا يحتوي الكود الخاص بك على أي علامة `div`. ```js assert($('div').length == 0); diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/wrap-radio-buttons-in-a-fieldset-element-for-better-accessibility.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/wrap-radio-buttons-in-a-fieldset-element-for-better-accessibility.md index dab2077c2353c5..794a8db4a3d528 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/wrap-radio-buttons-in-a-fieldset-element-for-better-accessibility.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-accessibility/wrap-radio-buttons-in-a-fieldset-element-for-better-accessibility.md @@ -1,6 +1,6 @@ --- id: 587d778b367417b2b2512aa7 -title: Wrap Radio Buttons in a fieldset Element for Better Accessibility +title: تغليف Radio Buttons داخل fieldset لتحسينا لإمكانيه الوصول challengeType: 0 videoUrl: 'https://scrimba.com/c/cVJVefw' forumTopicId: 301030 @@ -9,13 +9,13 @@ dashedName: wrap-radio-buttons-in-a-fieldset-element-for-better-accessibility # --description-- -The next form topic covers the accessibility of radio buttons. Each choice is given a `label` with a `for` attribute tying to the `id` of the corresponding item as covered in the last challenge. Since radio buttons often come in a group where the user must choose one, there's a way to semantically show the choices are part of a set. +يغطي الموضوع التالي إمكانية الوصول إلى أزرار الاختيار في النموذج. كل اختيار يعطى `label` وله سمة `for` مرتبطة بـسمة `id` في العنصر المقابل, كما هو مشمول في التحدي الأخير. نظرًا لأن أزرار الراديو (radio buttons) غالبا ما تأتي في مجموعات حيث يجب على المستخدم أن يختار زر واحد فقط من المجموعة، هناك طريقة لإظهار الخيارات بشكل لُغَوي أنها فعلا جزء من نفس المجموعة. -The `fieldset` tag surrounds the entire grouping of radio buttons to achieve this. It often uses a `legend` tag to provide a description for the grouping, which screen readers read for each choice in the `fieldset` element. +يحيط علامة (tag) `fieldset` بكامل مجموعة الأزرار الراديو ( radio buttons) لتحقيق ذلك. غالبا ما تستخدم علامة (tag) `legend` لتقديم وصف للمجموعة، أي قارئ الشاشة (screen readers) سيقرأ كل اختيار في عنصر `fieldset`. -The `fieldset` wrapper and `legend` tag are not necessary when the choices are self-explanatory, like a gender selection. Using a `label` with the `for` attribute for each radio button is sufficient. +العلامة `fieldset` و `legend` ليست ضرورية عندما تكون الاختيارات غنية عن التفسير، مثل اختيار نوع الجنس. استخدام `label` مع سمة `for` لكل زر راديو هو كاف. -Here's an example: +إليك مثال: ```html @@ -33,17 +33,17 @@ Here's an example: # --instructions-- -Camper Cat wants information about the ninja level of his users when they sign up for his email list. He's added a set of radio buttons and learned from our last lesson to use `label` tags with `for` attributes for each choice. Go Camper Cat! However, his code still needs some help. Change the `div` tag surrounding the radio buttons to a `fieldset` tag, and change the `p` tag inside it to a `legend`. +يريد Camper Cat معلومات عن مستوى النينجا لمستخدميه عند تسجيلهم لقائمة بريده الإلكتروني. لقد أضاف مجموعة من أزرار الراديو وتعلمنا من درسنا الأخير استخدام علامات `label` مع سمات `for` لكل اختيار. اذهب يا Camper Cat! However, his code still needs some help. تغيير علامة `div` الذي يحيط بأزرار الراديو إلى علامة `fieldset`، و قم بتغيير علامة `p` بداخلها إلى `legend`. # --hints-- -Your code should have a `fieldset` tag around the radio button set. +يجب أن يكون الكود الخاص بك فيه علامة `fieldset` حول مجموعة أزرار الراديو. ```js assert($('fieldset').length == 1); ``` -The `fieldset` element should have a closing tag. +يجب أن يكون لعلامة `fieldset` علامة اغلاق أيضا. ```js assert( @@ -52,19 +52,19 @@ assert( ); ``` -Your code should have a `legend` tag around the text asking what level ninja a user is. +يجب أن يحتوي الكود الخاصة بك على علامة `legend` حول النص الذي يسأل عن مستوى النينجا للمستخدم. ```js assert($('legend').length == 1); ``` -Your code should not have any `div` tags. +يجب ألا يحتوي الكود الخاص بك على أي علامة `div`. ```js assert($('div').length == 0); ``` -Your code should no longer have a `p` tag around the text asking what level ninja a user is. +يجب ألا يحتوي الكود الخاصة بك على علامة `p` حول النص الذي يسأل عن مستوى النينجا للمستخدم. ```js assert($('p').length == 4); diff --git a/curriculum/challenges/arabic/01-responsive-web-design/applied-visual-design/adjust-the-hover-state-of-an-anchor-tag.md b/curriculum/challenges/arabic/01-responsive-web-design/applied-visual-design/adjust-the-hover-state-of-an-anchor-tag.md index 308491804b4e68..eba7cc36171be1 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/applied-visual-design/adjust-the-hover-state-of-an-anchor-tag.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/applied-visual-design/adjust-the-hover-state-of-an-anchor-tag.md @@ -1,6 +1,6 @@ --- id: 587d781d367417b2b2512ac8 -title: Adjust the Hover State of an Anchor Tag +title: اضبط حالة التأشير بالحوم في علامة الرابط challengeType: 0 videoUrl: 'https://scrimba.com/c/cakRGcm' forumTopicId: 301035 @@ -11,7 +11,7 @@ dashedName: adjust-the-hover-state-of-an-anchor-tag This challenge will touch on the usage of pseudo-classes. A pseudo-class is a keyword that can be added to selectors, in order to select a specific state of the element. -For example, the styling of an anchor tag can be changed for its hover state using the `:hover` pseudo-class selector. Here's the CSS to change the `color` of the anchor tag to red during its hover state: +على سبيل المثال، يمكن تغيير تصميم علامة الرابط عندما يحوم الماوس فوقها بواسطة فئة زائفة pseudo-class من نوع `:hover`. Here's the CSS to change the `color` of the anchor tag to red during its hover state: ```css a:hover { @@ -25,13 +25,13 @@ The code editor has a CSS rule to style all `a` tags black. Add a rule so that w # --hints-- -The anchor tag `color` should remain black, only add CSS rules for the `:hover` state. +علامة الرابط `color` يجب أن تبقى سوداء. فقط أضف قواعد CSS لدولة `:hover`. ```js assert($('a').css('color') == 'rgb(0, 0, 0)'); ``` -The anchor tag should have a `color` of blue on hover. +يجب أن يتغير قيمة `color` في علامة الرابط (anchor) إلى الأزرق (blue) عندما تحوم عليها (hover). ```js assert( diff --git a/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/create-a-set-of-checkboxes.md b/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/create-a-set-of-checkboxes.md index 43bc88a61693f8..6c0f2f8caeb10c 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/create-a-set-of-checkboxes.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/create-a-set-of-checkboxes.md @@ -43,7 +43,7 @@ Each of your three checkbox elements should be nested in its own `label` element assert($('label > input[type="checkbox"]:only-child').length > 2); ``` -Make sure each of your `label` elements has a closing tag. +تأكد أن كل `label` له علامة إغلاق. ```js assert( diff --git a/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/fill-in-the-blank-with-placeholder-text.md b/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/fill-in-the-blank-with-placeholder-text.md index b9a9509f8ea622..e48285eea70484 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/fill-in-the-blank-with-placeholder-text.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/fill-in-the-blank-with-placeholder-text.md @@ -13,7 +13,7 @@ Web developers traditionally use lorem ipsum text as placeholder text Lorem ipsum text has been used as placeholder text by typesetters since the 16th century, and this tradition continues on the web. -Well, 5 centuries is long enough. Since we're building a CatPhotoApp, let's use something called "kitty ipsum" text. +Well, 5 centuries is long enough. بما أنك تنشئ برنامج CatPhotoApp، استخدم نص "kitty ipsum". # --instructions-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/link-to-external-pages-with-anchor-elements.md b/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/link-to-external-pages-with-anchor-elements.md index 73a3eaed90b8fc..80bdf98afd4c63 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/link-to-external-pages-with-anchor-elements.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/link-to-external-pages-with-anchor-elements.md @@ -1,6 +1,6 @@ --- id: bad87fee1348bd9aedf08816 -title: Link to External Pages with Anchor Elements +title: الربط بصفحات خارجية بواسطة العناصر Anchor challengeType: 0 videoUrl: 'https://scrimba.com/p/pVMPUv/c8EkncB' forumTopicId: 18226 @@ -11,13 +11,13 @@ dashedName: link-to-external-pages-with-anchor-elements You can use `a` (*anchor*) elements to link to content outside of your web page. -`a` elements need a destination web address called an `href` attribute. They also need anchor text. Here's an example: +عناصر `a` تتطلّب عنوان وب للوجهة يسمّى: `href`. وتتطلّب أيضا نصّ رابط anchor. Here's an example: ```html this links to freecodecamp.org ``` -Then your browser will display the text `this links to freecodecamp.org` as a link you can click. And that link will take you to the web address `https://www.freecodecamp.org`. +ثم يعرض متصفّحك نص: `this links to freecodecamp.org` على هيئة رابط يمكنك النقر عليه. And that link will take you to the web address `https://www.freecodecamp.org`. # --instructions-- @@ -31,13 +31,13 @@ Your `a` element should have the anchor text of `cat photos`. assert(/cat photos/gi.test($('a').text())); ``` -You need an `a` element that links to `https://www.freecatphotoapp.com` +تحتاج إلى عنصر `a` يربط بـعنوان `https://www.freecatphotoapp.com` ```js assert(/^https?:\/\/(www\.)?freecatphotoapp\.com\/?$/i.test($('a').attr('href'))); ``` -Your `a` element should have a closing tag. +عنصر `a` الخاص بك لا بد أن يكون له علامة إغلاق (closing tag). ```js assert( diff --git a/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/turn-an-image-into-a-link.md b/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/turn-an-image-into-a-link.md index 94fd61e4930998..5fd409a9ced94b 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/turn-an-image-into-a-link.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/basic-html-and-html5/turn-an-image-into-a-link.md @@ -21,7 +21,7 @@ Remember to use `#` as your `a` element's `href` property in order to turn it in # --instructions-- -Place the existing image element within an `a` (*anchor*) element. +ضع عنصر الصورة داخل عنصر `a` (*anchor*) الحالي. Once you've done this, hover over your image with your cursor. Your cursor's normal pointer should become the link clicking pointer. The photo is now a link. diff --git a/curriculum/challenges/arabic/01-responsive-web-design/css-flexbox/use-the-flex-shrink-property-to-shrink-items.md b/curriculum/challenges/arabic/01-responsive-web-design/css-flexbox/use-the-flex-shrink-property-to-shrink-items.md index fc9b59ab23f18e..5541b9cc8feec0 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/css-flexbox/use-the-flex-shrink-property-to-shrink-items.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/css-flexbox/use-the-flex-shrink-property-to-shrink-items.md @@ -1,6 +1,6 @@ --- id: 587d78ad367417b2b2512afb -title: Use the flex-shrink Property to Shrink Items +title: استعمال خاصية flex-shrink لتقليص الأصناف challengeType: 0 videoUrl: 'https://scrimba.com/p/pVaDAv/cd3PBfr' forumTopicId: 301113 @@ -9,11 +9,11 @@ dashedName: use-the-flex-shrink-property-to-shrink-items # --description-- -So far, all the properties in the challenges apply to the flex container (the parent of the flex items). However, there are several useful properties for the flex items. +وتنطبق حتى الآن جميع الخواص في التحديات على الحاوية المرنة ( flex container وهو أصل الأصناف المرنة). غير أن هناك عدة خصائص مفيدة للأصناف المرنة (flex items). The first is the `flex-shrink` property. When it's used, it allows an item to shrink if the flex container is too small. Items shrink when the width of the parent container is smaller than the combined widths of all the flex items within it. -The `flex-shrink` property takes numbers as values. The higher the number, the more it will shrink compared to the other items in the container. For example, if one item has a `flex-shrink` value of `1` and the other has a `flex-shrink` value of `3`, the one with the value of `3` will shrink three times as much as the other. +الخاصية `flex-shrink` تأخذ الأرقام كقيم. وكلما ارتفع العدد، سيتقلص العدد مقارنة بالاصناف الأخرى في الحاوية. For example, if one item has a `flex-shrink` value of `1` and the other has a `flex-shrink` value of `3`, the one with the value of `3` will shrink three times as much as the other. # --instructions-- diff --git a/curriculum/challenges/arabic/01-responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage.md b/curriculum/challenges/arabic/01-responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage.md index afe98f114e4332..4050a8f54d518c 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage.md @@ -1,6 +1,6 @@ --- id: bd7158d8c242eddfaeb5bd13 -title: Build a Personal Portfolio Webpage +title: أنشئ معرضا لأعمالك الخاصة challengeType: 14 forumTopicId: 301143 dashedName: build-a-personal-portfolio-webpage diff --git a/curriculum/challenges/arabic/01-responsive-web-design/responsive-web-design-projects/build-a-product-landing-page.md b/curriculum/challenges/arabic/01-responsive-web-design/responsive-web-design-projects/build-a-product-landing-page.md index 1dbc840e0bb20c..a36f6c5daf199b 100644 --- a/curriculum/challenges/arabic/01-responsive-web-design/responsive-web-design-projects/build-a-product-landing-page.md +++ b/curriculum/challenges/arabic/01-responsive-web-design/responsive-web-design-projects/build-a-product-landing-page.md @@ -1,6 +1,6 @@ --- id: 587d78af367417b2b2512b04 -title: Build a Product Landing Page +title: أنشئ صفحة لعرض المنتج challengeType: 14 forumTopicId: 301144 dashedName: build-a-product-landing-page diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting/confirm-the-ending.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting/confirm-the-ending.md index 8e44a491f3c7c3..4edfccbb7e3f76 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting/confirm-the-ending.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting/confirm-the-ending.md @@ -8,7 +8,7 @@ dashedName: confirm-the-ending # --description-- -تحقق مما إذا كان string (الحَجَّة الأولى، `str`) أخر string المطلوب (الحَجَّة الثانية، `target`). +تحقق مما إذا كان المقطع النصي (string) (المعطى (argument) الأولى `str`) أخر المقطع النصي المطلوب (المعطى الثاني `target`). *يمكنك* حل هذا التحدي بطريقة `.endsWith()`، التي تم تقديمها في ES2015. لكن لغرض هذا التحدي، نود أن تستخدموا واحدة من طرق subnstrings فى JavaScript بدلاً من ذلك. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting/convert-celsius-to-fahrenheit.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting/convert-celsius-to-fahrenheit.md index a4f5d5ea085718..eb80337ecab2b3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting/convert-celsius-to-fahrenheit.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting/convert-celsius-to-fahrenheit.md @@ -10,7 +10,7 @@ dashedName: convert-celsius-to-fahrenheit معادلة تحويل درجة الحرارة من الدرجة المئوية إلى درجة فهرنهايت هي: درجة الحرارة المئوية مضروبة في `9/5`, مضاف إليها `32`. -لديك المتغير `celsius` ويمثل درجة الحرارة المئوية. استخدم المتغير `fahrenheit` الذي سبق تعريفه وعيّن درجة حرارة فهرنهايت المعادلة لدرجة الحرارة المئوية المعطاة. استخدم المعادلة في السطر الأول، لتحويل درجة الحرارة المئوية إلى فهرنهايت. +لديك المتغير `celsius` ويمثل درجة الحرارة المئوية. استخدم المتغير `fahrenheit` الذي سبق أعلانه وعيّن درجة حرارة فهرنهايت المعادلة لدرجة الحرارة المئوية المعطاة. استخدم المعادلة في السطر الأول، لتحويل درجة الحرارة المئوية إلى فهرنهايت. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/access-an-arrays-contents-using-bracket-notation.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/access-an-arrays-contents-using-bracket-notation.md index 7b6010e120253e..6c2adb2f176ced 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/access-an-arrays-contents-using-bracket-notation.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/access-an-arrays-contents-using-bracket-notation.md @@ -1,6 +1,6 @@ --- id: 5a661e0f1068aca922b3ef17 -title: الوصول إلى محتويات القائمة (Array) باستخدام رمز القوس (Bracket Notation) +title: الوصول إلى محتويات القائمة (Array) باستخدام علامات الأقواس (Bracket Notation) challengeType: 1 forumTopicId: 301149 dashedName: access-an-arrays-contents-using-bracket-notation @@ -16,7 +16,7 @@ dashedName: access-an-arrays-contents-using-bracket-notation let ourArray = ["a", "b", "c"]; ``` -في القائمة، يحتوي كل عنصر على ترتيب index. هذا الترتيب يتضاعف كموقع ذلك العنصر في القائمة، وكيف تشير إليه. ومع ذلك، من المهم ملاحظة أن القائمات JavaScript هي قائمات مترتبة من الصفر، بمعنى أن العنصر الأول للقائمة هو في الواقع في موضع ***صفر*** وليس الأول. من أجل استرجاع عنصر من قائمة يمكننا إرفاق ترتيب بين قوسين وإلحاقه إلى نهاية القائمة، أو أكثر شيوعاً، إلى متغير يشير إلى كائن من نوع قائمة. هذا معروف باسم رمز الاقواس bracket notation. على سبيل المثال، إذا أردنا استرداد `a` من `ourArray`و تعيينه إلى متغير، يمكننا أن نفعل ذلك بواسطة التعليمات البرمجية التالية: +في القائمة، يحتوي كل عنصر على ترتيب index. هذا الترتيب يتضاعف كموقع ذلك العنصر في القائمة، وكيف تشير إليه. ومع ذلك، من المهم ملاحظة أن القائمات JavaScript هي قائمات مترتبة من الصفر، بمعنى أن العنصر الأول للقائمة هو في الواقع في موضع ***صفر*** وليس الأول. من أجل استرجاع عنصر من قائمة يمكننا إرفاق ترتيب بين قوسين وإلحاقه إلى نهاية القائمة، أو أكثر شيوعاً، إلى متغير يشير إلى كائن من نوع قائمة. هذا معروف باسم علامات الأقواس bracket notation. على سبيل المثال، إذا أردنا استرداد `a` من `ourArray`و تعيينه إلى متغير، يمكننا أن نفعل ذلك بواسطة التعليمات البرمجية التالية: ```js let ourVariable = ourArray[0]; @@ -30,7 +30,7 @@ let ourVariable = ourArray[0]; ourArray[1] = "not b anymore"; ``` -باستخدام رمز الأقواس، قمنا الآن بإعادة تعيين العنصر في الترتيب 1 من السلسلة `b`، إلى `not b anymore`. الآن `ourArray` هو `["a", "not b anymore", "c"]`. +باستخدام علامات الأقواس، قمنا الآن بإعادة تعيين العنصر في الترتيب 1 من المقطع النصي `b`، إلى `not b anymore`. الآن `ourArray` هو `["a", "not b anymore", "c"]`. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/access-property-names-with-bracket-notation.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/access-property-names-with-bracket-notation.md index 194fd0634aa1c2..4a3264ba55ab38 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/access-property-names-with-bracket-notation.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/access-property-names-with-bracket-notation.md @@ -8,7 +8,7 @@ dashedName: access-property-names-with-bracket-notation # --description-- -في تحدي الكائن الأول ذكرنا استخدام رمز القوس كوسيلة للوصول إلى قيم الخاصية باستخدام تقييم متغير. على سبيل المثال، تخيل أن كائن `foods` الخاص بنا يتم استخدامه في برنامَج لتسجيل النقود في محل تجارة. لدينا وظيفة ما و التي تعين `selectedFood` ونحن نريد التحقق من كائن `foods` للتأكد من وجود ذلك الطعام. وقد يبدو ذلك كالتالي: +في تحدي الكائن الأول ذكرنا استخدام علامات الأقواس كوسيلة للوصول إلى قيم الخاصية باستخدام تقييم متغير. على سبيل المثال، تخيل أن كائننا `foods` يستخدمه مكنة لتسجيل النقود في محل تجارة. لدينا وظيفة ما و التي تعين `selectedFood` ونحن نريد التحقق من كائن `foods` للتأكد من وجود ذلك الطعام. وقد يبدو ذلك كالتالي: ```js let selectedFood = getCurrentFood(scannedItem); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-items-to-an-array-with-push-and-unshift.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-items-to-an-array-with-push-and-unshift.md index 4a677ecfe2b139..2b4222c49a2d30 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-items-to-an-array-with-push-and-unshift.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-items-to-an-array-with-push-and-unshift.md @@ -10,7 +10,7 @@ dashedName: add-items-to-an-array-with-push-and-unshift طول القائمة، مثل أنواع البيانات التي يمكن أن تحتويها، غير ثابت. ويمكن تعريف القائمات بطول أي عدد من العناصر، ويمكن إضافة العناصر أو إزالتها بمرور الوقت؛ وبعبارة أخرى، القائمات هي قابلة للتغير mutable. في هذا التحدي، سننظر إلى وظيفتين يمكن بهما تعديل القائمة: `Array.push()` و `Array.unshift()`. -تأخذ كلتا الوظيفتين عنصراً واحداً أو أكثر من العناصر كمعلمات وتضيف هذه العناصر إلى القائمة التي تستدعيها الوظيفة؛ وظيفة `push()` تضيف عناصر إلى نهاية القائمة، و `unshift()` تضيف عناصر إلى البداية. انظر ما يلي: +تأخذ كلتا الطريقتان (methods) عنصراً واحداً أو أكثر من العناصر كوسائط (parameters) وتضيف هذه العناصر إلى القائمة (array) التي تنفيذها الطريقة؛ تضيف طريقة `push()` عناصر إلى نهاية القائمة، وتضيف `unshift()` عناصر إلى البداية. انظر ما يلي: ```js let twentyThree = 'XXIII'; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-items-using-splice.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-items-using-splice.md index eb69c8bbac4ff0..9df1e39c140511 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-items-using-splice.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-items-using-splice.md @@ -8,7 +8,7 @@ dashedName: add-items-using-splice # --description-- -تذكر في التحدي الأخير الذي ذكرناه أن `splice()` يمكن أن يأخذ ما يصل إلى ثلاث حجج؟ حسناً، يمكنك استخدام المعلم الثالث، المكون من عنصر واحد أو أكثر، للإضافة إلى القائمة. يمكن أن يكون هذا مفيدًا بشكل لا يصدق للتبديل السريع لعنصر، أو مجموعة من العناصر، بعنصر آخر. +تذكر في التحدي السابق الذي ذكرناه إن `splice()` تمكن أن تأخذ ما يصل إلى ثلاثة وسائط (parameters)؟ حسناً، يمكنك استخدام الوسيط الثالث، المكون من عنصر واحد أو أكثر، للإضافة إلى القائمة (array). يمكن أن يكون هذا مفيدًا بشكل لا يصدق للتبديل السريع لعنصر، أو مجموعة من العناصر، بعنصر آخر. ```js const numbers = [10, 11, 12, 12, 15]; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-key-value-pairs-to-javascript-objects.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-key-value-pairs-to-javascript-objects.md index a7f3d0e66ea2f8..3a5ec8d77c0c7a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-key-value-pairs-to-javascript-objects.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/add-key-value-pairs-to-javascript-objects.md @@ -81,7 +81,7 @@ assert(foods.grapes === 35); assert(foods.strawberries === 27); ``` -يجب تعيين أزواج key-value باستخدام dot او bracket notation. +يجب تعيين أزواج key-value باستخدام dot او علامات الأقواس. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/check-for-the-presence-of-an-element-with-indexof.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/check-for-the-presence-of-an-element-with-indexof.md index f13243529dbe09..85e6117d714f6b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/check-for-the-presence-of-an-element-with-indexof.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/check-for-the-presence-of-an-element-with-indexof.md @@ -8,7 +8,7 @@ dashedName: check-for-the-presence-of-an-element-with-indexof # --description-- -نظرًا لأنه يمكن تغيير القوائم، أو *يتم تحويرها* في أي وقت، لا يوجد ضمان حول مكان وجود جزء معين من البيانات في قائمة معينة، أو حتي إذا كان هذا العنصر لا يزال موجودا. لحسن الحظ، يوفر لنا JavaScript وظيفة مدمجة أخرى، `indexOf()`، وهذه تسمح لنا بالتحقق بسرعة وسهولة من وجود عنصر في القائمة. `indexOf()` تأخذ عنصرا كمعلم, و عندما تستدعي، فإنها ترجع المكان، أو الترتيب (index)، لهذا العنصر، أو `-1` إذا كان العنصر غير موجود في القائمة. +نظرًا لأنه يمكن تغيير القوائم، أو *يتم تحويرها* في أي وقت، لا يوجد ضمان حول مكان وجود جزء معين من البيانات في قائمة معينة، أو حتي إذا كان هذا العنصر لا يزال موجودا. لحسن الحظ، يوفر لنا JavaScript وظيفة مدمجة (built-in method) أخرى تسمى `indexOf()`، وهذه تسمح لنا بالتحقق بسرعة وسهولة من وجود عنصر في القائمة. تأخذ `indexOf()` عنصرا كوسيط عند تفعيلها، فإنها تنتج المكان (position)، أو الترتيب (index)، لهذا العنصر، أو `-1` إذا كان العنصر غير موجود في القائمة (array). على سبيل المثال: @@ -24,7 +24,7 @@ fruits.indexOf('pears'); # --instructions-- -`indexOf()` يمكن أن تكون مفيدة بشكل لا يصدق للتحقق بسرعة من وجود عنصر في القائمة. لقد حددنا الوظيفة `quickCheck`، التي تأخذ القائمة وعناصر كوسيطات (arguments). عدل الوظيفة باستخدام `indexOf()` بحيث تنتج `true` إذا كان العنصر الذي تم تمريره موجود في القائمة، و `false` إذا لم يكن موجود. +`indexOf()` يمكن أن تكون مفيدة بشكل لا يصدق للتحقق بسرعة من وجود عنصر في القائمة. لقد حددنا الوظيفة `quickCheck`، التي تأخذ القائمة وعناصر كمعطيات (arguments). عدل الوظيفة باستخدام `indexOf()` بحيث تنتج `true` إذا كان العنصر الذي تم تمريره موجود في القائمة، و `false` إذا لم يكن موجود. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/copy-array-items-using-slice.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/copy-array-items-using-slice.md index 170d63e5985d50..59b4eec8dda04d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/copy-array-items-using-slice.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/copy-array-items-using-slice.md @@ -8,7 +8,7 @@ dashedName: copy-array-items-using-slice # --description-- -الوظيفة التالية التي سنغطيها هي `slice()`. بدلا من تعديل القائمة، `slice()` تنسخ أو *تستخرج* عدد معين من العناصر إلى قائمة جديدة، دون تغيير للقائمة التي استدعت عليها الوظيفة. تأخذ `slice()` معلمتين فقط - الأولى هي ترتيب الذي يبدأ عنده الاستخراج، والثانية هي الترتيب الذي يتم عنده إيقاف الاستخراج (سيحدث الاستخراج حتى الترتيب، ولكن لا يشمل العنصر في هذا الترتيب). ضع في اعتبارك هذا المثال: +الوظيفة التالية التي سنغطيها هي `slice()`. بدلا من تعديل القائمة، `slice()` تنسخ أو *تستخرج* عدد معين من العناصر إلى قائمة جديدة، دون تغيير للقائمة التي استدعت عليها الوظيفة. تأخذ `slice()` وسيطين (parameters) فقط - يكون الأولى الترتيب الذي يبدأ عنده الاستخراج، ويكون الثاني الترتيب الذي يتم عنده إيقاف الاستخراج (سيحدث الاستخراج حتى الترتيب، ولكن لا يشمل العنصر نهاية الترتيب). ضع في اعتبارك هذا المثال: ```js let weatherConditions = ['rain', 'snow', 'sleet', 'hail', 'clear']; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/create-complex-multi-dimensional-arrays.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/create-complex-multi-dimensional-arrays.md index efc1762b4355d3..af68bb2ae75da1 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/create-complex-multi-dimensional-arrays.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/create-complex-multi-dimensional-arrays.md @@ -1,6 +1,6 @@ --- id: 587d7b7b367417b2b2512b16 -title: إنشاء القوائم معقدة متعددة الأبعاد +title: إنشاء القوائم معقدة متعددة الأبعاد (multi-dimensional arrays) challengeType: 1 forumTopicId: 301159 dashedName: create-complex-multi-dimensional-arrays @@ -8,9 +8,9 @@ dashedName: create-complex-multi-dimensional-arrays # --description-- -رائع! لقد تعلمت للتو طناً من المعلومات عن القوائم! لقد كانت هذه النِّظْرة عامة عالية المستوى إلى حد ما، وهناك الكثير لتتعلمه حول العمل مع القائمات، التي سترى الكثير منها في الأقسام اللاحقة. ولكن قبل الانتقال إلى Objects، دعنا نلقي النِّظْرة أخرى ونرى كيف يمكن أن تصبح القوائم (arrays) أكثر تعقيدًا قليلاً مما رأيناه في التحديات السابقة. +رائع! لقد تعلمت للتو طناً من المعلومات عن القوائم (arrays)! لقد كانت هذه النِّظْرة عامة عالية المستوى إلى حد ما، وهناك الكثير لتتعلمه حول العمل مع القوائم، التي سترى الكثير منها في الأقسام اللاحقة. ولكن قبل الانتقال إلى كائنات (Objects)، دعنا نلقي النِّظْرة أخرى ونرى كيف يمكن أن تصبح القوائم (arrays) أكثر تعقيدًا قليلاً مما رأيناه في التحديات السابقة. -واحدة من أقوى السمات عند التفكير في القوائم كهياكل للبيانات، هو أن القوائم يمكن أن تحتوي، أو حتى إن تكون مكونة بالكامل من قوائم أخرى. ورأيت القوائم التي تحتوي على قوائم في تحديات سابقة، ولكنها بسيطة إلى حد ما. ومع ذلك، فإن القوائم يمكن أن تحتوي على عمق لا حدود له من القوائم التي يمكن أن تحتوي على قوائم أخرى، لكل منها مستويات عشوائية من العمق وما إلى ذلك. بهذه الطريقة، يمكن للقائمة أن تصبح بسرعة هيكل بيانات معقد جداً، يعرف باسم multi-dimensional أو قائمة متداخلة (nested array). انظر إلى المثال التالي: +واحدة من أقوى السمات عند التفكير في القوائم كهياكل للبيانات، هو أن القوائم يمكن أن تحتوي، أو حتى إن تكون مكونة بالكامل من قوائم أخرى. ورأيت القوائم التي تحتوي على قوائم في تحديات سابقة، ولكنها بسيطة إلى حد ما. ومع ذلك، فإن القوائم يمكن أن تحتوي على عمق لا حدود له من القوائم التي يمكن أن تحتوي على قوائم أخرى، لكل منها مستويات عشوائية من العمق وما إلى ذلك. بهذه الطريقة، يمكن للقائمة أن تصبح بسرعة هيكل بيانات معقد جداً، يعرف باسم عديد الأبعاد (multi-dimensional) أو قائمة متداخلة (nested array). انظر إلى المثال التالي: ```js let nestedArray = [ @@ -33,7 +33,7 @@ let nestedArray = [ قائمة `deep` متداخلة على مستويين عميقين. قوائم `deeper` بعمق 3 مستويات. قوائم `deepest` هي 4 مستويات، و `deepest-est?` هي 5 مستويات. -وفي حين أن هذا المثال قد يبدو متشابكا فإن هذا المستوى من التعقيد ليس مستغربا أو غير عادي عند التعامل مع كميات كبيرة من البيانات. ومع ذلك، لا يزال بإمكاننا الوصول بسهولة إلى أعمق مستويات قائمة بهذا التعقيد باستخدام رمز القوس: +وفي حين أن هذا المثال قد يبدو متشابكا فإن هذا المستوى من التعقيد ليس مستغربا أو غير عادي عند التعامل مع كميات كبيرة من البيانات. ومع ذلك، لا يزال بإمكاننا الوصول بسهولة إلى أعمق مستويات قائمة بهذا التعقيد علامات الأقواس: ```js console.log(nestedArray[2][1][0][0][0]); @@ -51,11 +51,11 @@ console.log(nestedArray[2][1][0][0][0]); # --instructions-- -لقد حددنا متغير `myNestedArray`، تم تعيينه مساوياً لقائمة. عدل `myNestedArray` باستخدام أي مجموعة من strings، و numbers، و booleans لعناصر البيانات، بحيث يكون لديها على وجه التحديد خمس مستويات من العمق (تذكر، أن القائمة الخارجية هي المستوى 1). في مكان ما على المستوى الثالث ضف المقطع `deep`, وعلى المستوى الرابع ضف المقطع `deeper`, وعلى المستوى الخامس ضف المقطع `deepest`. +لقد أعلنا متغير `myNestedArray`، مساويا لقائمة. عدل `myNestedArray` باستخدام أي مجموعة من مقاطع نصية (strings)، و أرقام (numbers)، و حالات (booleans) لعناصر البيانات، بحيث يكون لديها على وجه التحديد خمس مستويات من العمق (تذكر، أن القائمة الخارجية هي المستوى 1). في مكان ما على المستوى الثالث ضف المقطع `deep`, وعلى المستوى الرابع ضف المقطع `deeper`, وعلى المستوى الخامس ضف المقطع `deepest`. # --hints-- -`myNestedArray` يجب أن تحتوي فقط على numbers و booleans و strings كعناصر بيانات +`myNestedArray` يجب أن تحتوي فقط على أرقام (numbers) وحالات (booleans) و مقاطع نصية (strings) كعناصر للبيانات ```js assert.strictEqual( @@ -79,7 +79,7 @@ assert.strictEqual( ); ``` -`myNestedArray` يجب أن تحتوي على 5 مستويات بالضبط من العمق +يجب أن تحتوي `myNestedArray` على 5 مستويات من العمق بالضبط ```js assert.strictEqual( @@ -102,7 +102,7 @@ assert.strictEqual( ); ``` -`myNestedArray` يجب أن تحتوي بالضبط على عنصر واحد من المقطع `deep` في قائمة بعمق ثلاث مستويات +يجب أن تحتوي `myNestedArray` على عنصر واحد من المقطع نصي `deep` في قائمة بعمق ثلاث مستويات بالضبط ```js assert( @@ -131,7 +131,7 @@ assert( ); ``` -`myNestedArray` يجب أن تحتوي بالضبط على عنصر واحد من السلسلة `deeper` في قائمة بعمق اربع مستويات +يجب أن تحتوي `myNestedArray` على عنصر واحد من المقطع نصي `deeper` في قائمة بعمق اربع مستويات بالضبط ```js assert( @@ -160,7 +160,7 @@ assert( ); ``` -`myNestedArray` يجب أن تحتوي بالضبط على عنصر واحد من المقطع `deepest` في قائمة بعمق خمس مستويات +يجب أن تحتوي `myNestedArray` على عنصر واحد من المقطع نصي `deepest` في قائمة بعمق خمس مستويات بالضبط ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/modify-an-array-stored-in-an-object.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/modify-an-array-stored-in-an-object.md index 96ff4763bef006..c982bf3829bc3c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/modify-an-array-stored-in-an-object.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/modify-an-array-stored-in-an-object.md @@ -12,7 +12,7 @@ dashedName: modify-an-array-stored-in-an-object # --instructions-- -ألقي النِّظْرة على الكائن الذي قدمناه في محرر التعليمات البرمجية. يحتوي كائن `user` على ثلاث هُوِيَّات. يحتوي هُوِيَّة `data` على خمس هُوِيَّات، يحتوي أحدها على القائمة من `friends`. من هذا، يمكنك أن ترى مدى مرونة الكائنات مثل هياكل البيانات. لقد بدأنا كتابة وظيفة `addFriend`. إنهاء الكتابة بحيث يأخذ كائن `user` ويضيف اسم وسيطة `friend` للقائمة المخزنة في `user.data.friends` وأنشئ تلك القائمة. +ألقي النِّظْرة على الكائن الذي قدمناه في محرر التعليمات البرمجية. يحتوي كائن `user` على ثلاث هُوِيَّات. يحتوي هُوِيَّة `data` على خمس هُوِيَّات، يحتوي أحدها على القائمة من `friends`. من هذا، يمكنك أن ترى مدى مرونة الكائنات مثل هياكل البيانات. لقد بدأنا كتابة وظيفة `addFriend`. إنهاء الكتابة بحيث يأخذ كائن `user` ويضيف اسم المعطى `friend` للقائمة المخزنة في `user.data.friends` وأنشئ تلك القائمة. # --hints-- @@ -22,7 +22,7 @@ dashedName: modify-an-array-stored-in-an-object assert('name' in user && 'age' in user && 'data' in user); ``` -يجب أن تقبل وظيفة (function) مسمى `addFriend` كائن `user` ومقطع نصي `friend` كوسائط و أضف friend إلى قائمة `friends` في كائن `user`. +يجب أن تقبل وظيفة (function) مسمى `addFriend` كائن `user` ومقطع نصي `friend` كمعطيات وأضف friend إلى قائمة `friends` في كائن `user`. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/modify-an-object-nested-within-an-object.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/modify-an-object-nested-within-an-object.md index f3a9f1376c7bb1..8a43399533eba2 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/modify-an-object-nested-within-an-object.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/modify-an-object-nested-within-an-object.md @@ -58,7 +58,7 @@ assert('totalUsers' in userActivity.data && 'online' in userActivity.data); assert(userActivity.data.online === 45); ``` -يجب تعيين خاصية `online` باستخدام dot او bracket notation. +يجب تعيين خاصية `online` باستخدام dot او علامات الأقواس. ```js assert.strictEqual(code.search(/online: 45/), -1); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-from-an-array-with-pop-and-shift.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-from-an-array-with-pop-and-shift.md index 82de3b5f502936..3722097bda1bf5 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-from-an-array-with-pop-and-shift.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-from-an-array-with-pop-and-shift.md @@ -8,7 +8,7 @@ dashedName: remove-items-from-an-array-with-pop-and-shift # --description-- -كلاً من `push()` و `unshift()` لديهما functions معارضة و هما: `pop()` و `shift()`. ربما خمنت الآن انه بدلاً من إضافة بواسطة `pop()` تقوم *بإزالة* عنصر من نهاية array، بينما `shift()` يزيل عنصر من البداية. الفرق الرئيس بين `pop()` و `shift()` وأمثالهم `push()` و `unshift()`, هو أن أيا من الطريقتين لا يأخذ parameters، ويسمح كل منهما فقط بتعديل array بعنصر واحد فقط في كل مرة. +كلاً من `push()` و `unshift()` لديهما functions معارضة و هما: `pop()` و `shift()`. ربما خمنت الآن انه بدلاً من إضافة بواسطة `pop()` تقوم *بإزالة* عنصر من نهاية array، بينما `shift()` يزيل عنصر من البداية. الفرق الرئيس بين `pop()` و `shift()` وأمثالهم `push()` و `unshift()`, هو إن الطريقتين (method) لا تأخذوا وسائط (parameters)، وتسمحوا كل منهم فقط بتعديل قائمة (array) بعنصر واحد فقط في كل مرة. ألقي نَّظْرَة: diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice.md index 147ad02896ef04..cff13ae310ea6b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/remove-items-using-splice.md @@ -10,7 +10,7 @@ dashedName: remove-items-using-splice حسنًا، لقد تعلمنا كيفية إزالة العناصر من بداية ونهاية arrays باستخدام `shift()` و `pop()`، ولكن ماذا لو أردت إزالة عنصر من مكان ما في المنتصف؟ أم إزالة أكثر من عنصر واحد في المرة الواحدة؟ هنا يأتي دور `splice()`. `splice()` تسمح لنا بالقيام بما يلي: **إزالة أي عدد من العناصر المتتالية** من أي مكان في array. -`splice()` يمكن أن يأخذ ما يصل إلى 3 parameters، ولكن في الوقت الحالي، سنركز على أول 2 parameters. أول ٢ parameters في `splice()` هما أعداد صحيحة تمثل indexes، أو أماكن العناصر في array التي تستدعهم `splice()`. وتذكر أن arrays هم *zero-indexed*، بحيث لنشير إلى العنصر الأول في array، سوف تستخدم `0`. يمثل أول parameter في `splice()` الترتيب (index) في array التي تبدأ منها إزالة العناصر، بينما parameter الثاني يشير إلى عدد العناصر المراد حذفها. على سبيل المثال: +يمكن أن يأخذ `splice()` ما يصل من 3 وسائط (parameters)، ولكن في الوقت الحالي، سنركز على أول 2. يكون أول ثاني وسائط في `splice()` أعداد صحيحة تمثل ترتيب (indexes) العناصر، أو أماكن العناصر في قائمة (array) الذي `splice()` تم تفعيلها. وتذكر أن arrays هم *zero-indexed*، بحيث لنشير إلى العنصر الأول في array، سوف تستخدم `0`. يمثل أول وسيط في `splice()` الترتيب (index) في قائمة التي تبدأ منها إزالة العناصر، بينما الوسيط الثاني يشير إلى عدد العناصر المراد حذفها. على سبيل المثال: ```js let array = ['today', 'was', 'not', 'so', 'great']; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/use-an-array-to-store-a-collection-of-data.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/use-an-array-to-store-a-collection-of-data.md index ef3dbe392a7b5c..6c7c2515bec4e1 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/use-an-array-to-store-a-collection-of-data.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-data-structures/use-an-array-to-store-a-collection-of-data.md @@ -46,7 +46,7 @@ let complexArray = [ # --instructions-- -لقد حددنا متغير يسمى `yourArray`. أكمل البيان بتعيين array من 5 عناصر في الأقل في الطول لمتغير `yourArray`. يجب أن تحتوي array على stringواحد علي الأفل و number واحد و boolean واحد. +لقد أعلنا متغير يسمى `yourArray`. أكمل البيان بتعيين array من 5 عناصر في الأقل في الطول لمتغير `yourArray`. يجب أن تحتوي array على stringواحد علي الأفل و number واحد و boolean واحد. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/access-array-data-with-indexes.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/access-array-data-with-indexes.md index f7ec3c9a182a4a..d664e57d896848 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/access-array-data-with-indexes.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/access-array-data-with-indexes.md @@ -1,6 +1,6 @@ --- id: 56bbb991ad1ed5201cd392ca -title: الوصول إلى بيانات القائمة باستخدام الترتيب (Access Array Data with Indexes) +title: الوصول إلى بيانات القائمة باستخدام الترتيب challengeType: 1 videoUrl: 'https://scrimba.com/c/cBZQbTz' forumTopicId: 16158 @@ -11,7 +11,7 @@ dashedName: access-array-data-with-indexes يمكننا الوصول إلى البيانات داخل القائمات باستخدام الترتيب. -Array indexes تكتب بنفس الأقواس التي تستخدم في مقاطع النصية (strings)، باستثناء أنه بدلاً من تحديد رمز، فإنهم يحددون عنصرا في القائمة (array). مثل المقاطع النصية (strings)، فإن القائمات (arrays) تستخدم القائمة تبدأ بالصفر، لذا فإن العنصر الأول في القائمة (array) لديه الترتيب (index) برقم `0`. +array indexes تكتب بنفس الأقواس التي تستخدم في المقاطع النصية (strings)، باستثناء أنه بدلاً من تحديد رمز، فإنهم يحددون عنصرا في القائمة (array). مثل المقاطع النصية، فإن القائمات تستخدم ترتيب من الصفر، لذا فإن رَقَم ترتيب (index) العنصر الأول في القائمة `0`.
    @@ -23,7 +23,7 @@ console.log(array[0]); const data = array[1]; ``` -`console.log(array[0])` تطبع `50` و `data` بقيمة `60`. +`console.log(array[0])` تطبع `50` و `data` قيمتها `60`. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes.md index b0449ba040149e..b8bac4a19edf76 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/access-multi-dimensional-arrays-with-indexes.md @@ -1,6 +1,6 @@ --- id: 56592a60ddddeae28f7aa8e1 -title: الوصول إلى القائمات المتعددة الأبعاد باستخدام الترتيب (Access Multi-Dimensional Arrays With Indexes) +title: الوصول إلى القائمات المتعددة الأبعاد باستخدام الترتيب challengeType: 1 videoUrl: 'https://scrimba.com/c/ckND4Cq' forumTopicId: 16159 @@ -9,7 +9,7 @@ dashedName: access-multi-dimensional-arrays-with-indexes # --description-- -إحدى الطرق للتفكير في قائمة عديده الأبعاد(multi-dimensional) هي تكون *قائمة من قائمات (array of arrays)*. عندما تستخدم أقواس للوصول إلى القائمة (array)، تشير المجموعة الأولى من الأقواس إلى المواد الموجودة في أعلى فئة (المستوى الأول)، ويشير كل زوج إضافي من الأقواس إلى المستوى التالي من الإدخالات في الداخل. +تتمثل إحدى طرق التفكير في القائمة العديدة الأبعاد (multi-dimensional) بأنها *كقائمة قائمات (array of arrays)*. عندما تستخدم أقواس للوصول إلى القائمة (array)، يشير أول زوج من الأقواس إلى العناصر الموجودة في أبعد مستوى (المستوى الأول)، ويشير كل زوج إضافي من الأقواس إلى المستوى التالي من الإدخالات في الداخل. **مثال** @@ -28,11 +28,11 @@ const element = arr[3][0][1]; في هذا المثال، لدي `subarray` قيمة `[[10, 11, 12], 13, 14]`, ولدي `nestedSubarray` قيمة `[10, 11, 12]`, ولدي `element` قيمة `11`. -**ملاحظة:** لا ينبغي أن تكون هناك أي مسافات بين اسم القائمة (array) والأقواس المربعة، مثل `array [0][0]` و حتي ذلك `array [0] [0]` ممنوع أيضاً. مع أنّ JavaScript قادر على معالجة هذا الأمر بشكل صحيح، إلا أن هذا قد يحير المبرمجين الآخرين الذين يقرؤون التعليمات البرمجية الخاص بك. +**ملاحظة:** لا ينبغي أن تكون هناك أي مسافات بين اسم القائمة (array) والأقواس المربعة، مثل `array [0][0]` و حتي ذلك `array [0] [0]` ممنوع أيضاً. مع أنّ JavaScript قادر على معالجة هذا الأمر بشكل صحيح، إلا أن هذا قد يحير المبرمجين الآخرين الذين يقرؤون التعليمات البرمجية الخاصة بك. # --instructions-- -باستخدام bracket notation، اختر عنصرا من `myArray` بحيث أن `myData` يساوي `8`. +اختار عنصرا من `myArray` باستخدام علامات الأقواس بحيث أن `myData` يساوي `8`. # --hints-- @@ -42,7 +42,7 @@ const element = arr[3][0][1]; assert(myData === 8); ``` -يجب أن تستخدم bracket notation لقراءة القيمة الصحيحة من `myArray`. +يجب أن تستخدم علامات الأقواس لقراءة القيمة الصحيحة من `myArray`. ```js assert(/myData=myArray\[2\]\[1\]/.test(__helpers.removeWhiteSpace(code))); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays.md index d1cbafdca3bcc8..622ba4ba131205 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244cd -title: الوصول إلى القائمات المتداخلة (Accessing Nested Arrays) +title: الوصول إلى القائمات المتداخلة challengeType: 1 videoUrl: 'https://scrimba.com/c/cLeGDtZ' forumTopicId: 16160 @@ -11,7 +11,7 @@ dashedName: accessing-nested-arrays وكما رأينا في أمثلة سابقة، يمكن أن تحتوي الكائنات (objects) على كائنات متدخلة (nested objects) و قائمات متداخلة (nested arrays). على غرار الوصول إلى الكائنات متدخلة nested objects، يمكن ربط bracket notation في القائمة للوصول إلى القائمات متداخلة (nested arrays). -وفيما يلي مثال على كيفية الوصول إلى القائمة متداخلة nested) array): +وفيما يلي مثال على كيفية الوصول إلى القائمة متداخلة (nested array): ```js const ourPets = [ @@ -41,7 +41,7 @@ ourPets[1].names[0]; # --instructions-- -باستخدام dot و bracket notation، وعيّن المتغير `secondTree` إلى العنصر الثاني في قائمة `trees` من object باسم `myPlants`. +استخدم dot و علامات الأقواس, لتعيّن المتغير `secondTree` إلى العنصر الثاني في قائمة `trees` من object باسم `myPlants`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-bracket-notation.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-bracket-notation.md index 095d4fe8801f3d..0d152807800263 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-bracket-notation.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-bracket-notation.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244c8 -title: الوصول خصائص (Properties) الكائن (Object) بواسطة Bracket Notation +title: الوصول لخصائص (Properties) الكائن (Object) بواسطة استخدام dot و علامات الأقواس challengeType: 1 videoUrl: 'https://scrimba.com/c/cBvmEHP' forumTopicId: 16163 @@ -9,11 +9,11 @@ dashedName: accessing-object-properties-with-bracket-notation # --description-- -الطريقة الثانية للوصول إلى خصائص الكائن هي القوسان المعكوفان (`[]`). في حال إن خاصية الكائن الذي تحاول الوصول إليه يحتوي على مسافة في اسمه, سوف تحتاج إلى استخدام القوسان المعكوفان (bracket notation). +الطريقة الثانية للوصول إلى خصائص الكائن هي استخدام علامات الأقواس (`[]`). في حال إن خاصية الكائن الذي تحاول الوصول إليه يحتوي على مسافة في اسمه, سوف تحتاج إلى استخدام علامات الأقواس (bracket notation). على أية حال, فانه يمكنك أستخدام bracket notation على خصائص الكائن من دون مسافات. -هذا مثال على استخدام bracket notation لقراءة خاصية الكائن: +هذا مثال على استخدام علامات الأقواس لقراءة خاصية الكائن: ```js const myObj = { @@ -33,7 +33,7 @@ myObj["NoSpace"]; # --instructions-- -أقراء قيم خصائص `an entree` و `the drink` في `testObj` باستخدام القوسان المعكوفان وتعينهم إلى `entreeValue` و `drinkValue` على التوالي. +أقراء قيم خصائص `an entree` و `the drink` في `testObj` باستخدام علامات الأقواس وعينهم إلى `entreeValue` و `drinkValue` على التوالي. # --hints-- @@ -61,7 +61,7 @@ assert(typeof drinkValue === 'string'); assert(drinkValue === 'water'); ``` -يجب عليك أستخدام القوسان المعكوفان مرتين +يجب عليك أستخدام علامات الأقواس مرتين ```js assert(code.match(/testObj\s*?\[('|")[^'"]+\1\]/g).length > 1); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-dot-notation.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-dot-notation.md index 140c7560b18ee7..431232abff18e1 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-dot-notation.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-dot-notation.md @@ -9,7 +9,7 @@ dashedName: accessing-object-properties-with-dot-notation # --description-- -هناك طريقتان للوصول إلى خصائص الكائن: نقطة التأشير (`.`) وتدوين الأقواس (`[]`)، على غرار القائمة. +هناك طريقتان للوصول إلى خصائص الكائن: نقطة التأشير (`.`) و علامات الأقواس (`[]`)، على غرار القائمة. ترميز النقطة هو ما تستخدمه عندما تعرف اسم الخاصية التي تحاول الوصول إليها مسبقاً. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-variables.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-variables.md index 37c8d3ad711e06..53bde20f3e3ba1 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-variables.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/accessing-object-properties-with-variables.md @@ -9,7 +9,7 @@ dashedName: accessing-object-properties-with-variables # --description-- -وثمة استخدام آخر لترميز آلأقواس للوصول إلى الخصائص المخزنة كقيمة للمتغير. يمكن أن يكون هذا مفيداً جداً خلال تكرار خصائص الكائن أو عند الوصول إلى جدول البحث. +وثمة استخدام آخر لعلامات الأقواس للوصول إلى الخصائص المخزنة كقيمة للمتغير. يمكن أن يكون هذا مفيداً جداً خلال تكرار خصائص الكائن أو عند الوصول إلى جدول البحث. فيما يلي, مثال على استخدام متغير للوصول إلى خاصية ما: @@ -53,7 +53,7 @@ assert(typeof player === 'string'); assert(player === 'Montana'); ``` -يجب عليك استخدام ترميز ألأقواس للوصول إلى `testObj` +يجب عليك استخدام علامات الأقواس للوصول إلى `testObj` ```js assert(/testObj\s*?\[.*?\]/.test(code)); @@ -65,7 +65,7 @@ assert(/testObj\s*?\[.*?\]/.test(code)); assert(!code.match(/player\s*=\s*"|\'\s*Montana\s*"|\'\s*;/gi)); ``` -يجب أن تستخدم المتغير `playerNumber` في رمز القوس +يجب أن تستخدم المتغير `playerNumber` في علامات الأقواس ```js assert(/testObj\s*?\[\s*playerNumber\s*\]/.test(code)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/add-two-numbers-with-javascript.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/add-two-numbers-with-javascript.md index 7b572bcb22fce4..e742982039704a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/add-two-numbers-with-javascript.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/add-two-numbers-with-javascript.md @@ -9,11 +9,11 @@ dashedName: add-two-numbers-with-javascript # --description-- -`Number` (رَقَم) هو نوع من أنواع البيانات في لغة JavaScript و هو يمثل بيانات رقمية. +`Number` هو نوع من أنواع البيانات في لغة JavaScript و هو يمثل بيانات رقمية. حاول إضافة رقمين باستخدام JavaScript. -تستخدم JavaScript رمز `+` كمعامل الإضافة عند وضعه بين رقمين. +تستخدم JavaScript رمز `+` كمشغل الإضافة عند وضعه بين رقمين. **مثال:** diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/adding-a-default-option-in-switch-statements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/adding-a-default-option-in-switch-statements.md index d72ac1e7b41c94..c43b833a4fcb07 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/adding-a-default-option-in-switch-statements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/adding-a-default-option-in-switch-statements.md @@ -9,7 +9,7 @@ dashedName: adding-a-default-option-in-switch-statements # --description-- -في عبارة `switch` قد لا تكون قادراً على تحديد جميع القيم المحتملة كعبارات `case`. بدلاً من ذلك، يمكنك إضافة عبارة `default` التي سيتم تنفيذها إذا لم يتم العثور على عبارات `case` مطابقة. فكر بالأمر مثل العبارة `else` في `if/else`. +في عبارة `switch` قد لا تكون قادراً على تحديد جميع القيم المحتملة كعبارات `case`. بدلاً من ذلك، يمكنك إضافة عبارة `default` التي سيتم تنفيذها إذا لم يتم العثور على عبارات `case` مطابقة. وكأنها مثل آخر عبارة `else` في `if/else`. يجب أن تكون عبارة `default` آخر حالة. @@ -38,31 +38,31 @@ switch (num) { # --hints-- -`switchOfStuff("a")` يجب أن يعيد مقطع نصي (string) باسم `apple` +يجب أن ينتج `switchOfStuff("a")` مقطع نصي (string) بقيمة `apple` ```js assert(switchOfStuff('a') === 'apple'); ``` -`switchOfStuff("b")` يجب أن ينتج مقطع نصي (string) باسم `bird` +يجب أن ينتج `switchOfStuff("b")` مقطع نصي بقيمة `bird` ```js assert(switchOfStuff('b') === 'bird'); ``` -`switchOfStuff("c")` يجب أن ينتج مقطع نصي (string) باسم `cat` +يجب أن ينتج `switchOfStuff("c")` مقطع نصي بقيمة `cat` ```js assert(switchOfStuff('c') === 'cat'); ``` -`switchOfStuff("d")` يجب أن ينتج مقطع نصي (string) باسم `stuff` +يجب أن ينتج `switchOfStuff("d")`مقطع نصي بقيمة `stuff` ```js assert(switchOfStuff('d') === 'stuff'); ``` -`switchOfStuff(4)` يجب أن ينتج مقطع نصي (string) باسم `stuff` +يجب أن ينتج `switchOfStuff(4)` مقطع نصي بقيمة `stuff` ```js assert(switchOfStuff(4) === 'stuff'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/appending-variables-to-strings.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/appending-variables-to-strings.md index 1e706f40dccaf3..62b79a4d644085 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/appending-variables-to-strings.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/appending-variables-to-strings.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244ed -title: إلحاق المتغيرات بالمقاطع النصية (Appending Variables to Strings) +title: إلحاق المتغيرات بالمقاطع النصية challengeType: 1 videoUrl: 'https://scrimba.com/c/cbQmZfa' forumTopicId: 16656 @@ -9,7 +9,7 @@ dashedName: appending-variables-to-strings # --description-- -تماما كما يمكننا بناء مقطع نصي (string) مكونة من عدة سطور باستخدام الاحرف مقطع نصي (string literals)، يمكننا أيضا إلحاق المتغيرات في مقطع نصي (string) معينة باستخدام (`+=`). +تماما كما نستطيع أن نبني مقطع نصي (string) مكون من عدة سطور باستخدام مقاطع نصية حرفية (string literals)، يمكننا أيضا إلحاق المتغيرات في مقطع نصي (string) معين باستخدام المشغل (`+=`). على سبيل المثال: @@ -19,11 +19,11 @@ let ourStr = "freeCodeCamp is "; ourStr += anAdjective; ``` -المتغير `ourStr` ستكون قيمته النهائية `freeCodeCamp is awesome!`. +قيمة المتغير `ourStr` النهائية ستكون `freeCodeCamp is awesome!`. # --instructions-- -عرف متغير جديد `someAdjective` بحيث يكون string قيمته مكون من 3 أحرف في الأقل, ثم إلحاقه بمتغير آخر `myStr` باستخدام `+=`. +حدد قيمة المتغير `someAdjective` بحيث يكون مقطع نصي مكون من 3 أحرف في الأقل, ثم ضفه في نهاية المتغير `myStr` باستخدام `+=`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/assigning-the-value-of-one-variable-to-another.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/assigning-the-value-of-one-variable-to-another.md index 8327934880ceae..d757a010d3a7e3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/assigning-the-value-of-one-variable-to-another.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/assigning-the-value-of-one-variable-to-another.md @@ -1,6 +1,6 @@ --- id: 5ee127a03c3b35dd45426493 -title: تعيين قيمة متغير إلى متغير آخر (Assigning the Value of One Variable to Another) +title: تعيين قيمة متغير إلى متغير آخر challengeType: 1 videoUrl: '' forumTopicId: 418265 @@ -9,7 +9,7 @@ dashedName: assigning-the-value-of-one-variable-to-another # --description-- -بعد تعيين قيمة إلى متغير باستخدام عملية تكليف (=)، يمكنك تعيين قيمة هذا المتغير إلى متغير آخر باستخدام عمليةتكليف (=) ذاتها. +بعد تعيين قيمة إلى متغير باستخدام مشغل التعيين (=)، يمكنك تعيين قيمة هذا المتغير إلى متغير آخر باستخدام مشغل التعيين (=) ذاتها. ```js var myVar; @@ -18,7 +18,7 @@ var myNum; myNum = myVar; ``` -ما ورد أعلاه يظهر تعريف المتغير `myVar` دون قيمة، ثم يعين له القيمة `5`. بعد ذلك، يتم تعريف متغير آخر يدعى `myNum` دون قيمة. ثم يتم تعيين قيمة المتغير `myVar` (التي تساوي `5`) إلى المتغير `myNum`. الآن المتغير `myNum` لديه القيمة `5`. +ما ورد أعلى يعلن المتغير `myVar` دون قيمة، ثم يخصص له قيمة `5`. بعد ذلك، يتم إعلان متغير آخر يدعى `myNum` دون قيمة. ثم يتم تعيين قيمة المتغير `myVar` (التي تساوي `5`) إلى المتغير `myNum`. الآن المتغير `myNum` لديه القيمة `5`. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/assignment-with-a-returned-value.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/assignment-with-a-returned-value.md index 1a44bd6728e309..6c39b65533c018 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/assignment-with-a-returned-value.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/assignment-with-a-returned-value.md @@ -9,19 +9,19 @@ dashedName: assignment-with-a-returned-value # --description-- -إذا كنت ستتذكر من مناقشتنا حول تخزين القيم مع مشغل التعيين (=)، يتم عزم كل شيء لحق الإشارة المتساوية قبل تعيين القيمة. وهذا يعني أنه يمكننا أخذ قيمة الناتجة من وظيفة وتعيينها إلى متغير. +إذا كنت تتذكر من مناقشتنا حول تخزين القيم مع مشغل التعيين (=)، يتم عزم كل شيء لاحق لعلامة المساواة قبل تعيين القيمة. وهذا يعني أنه يمكننا أخذ القيمة الناتجة من وظيفة وتعيينها إلى متغير. -افترض أن لدينا وظيفة معرف سلفًا يدعي `sum`، التي تضيف رقمين معا، ثم: +Assume we have defined a function `sum` which adds two numbers together. ```js ourSum = sum(5, 12); ``` -يستعي الوظيفة `sum` التي ترجع قيمة `17` وتعيينها إلى متغير `ourSum`. +Calling the `sum` function with the arguments of `5` and `12` produces a return value of `17`. This return value is assigned to the `ourSum` variable. # --instructions-- -استدعي الوظيفة `processArg` باستخدام حَجَّة بقيمة `7`, وعيّن قيمة إرجاع لوظيفة للمتغير `processed`. +فعِّل الوظيفة `processArg` باستخدام معطى قيمته `7`, وعيّن المنتج من الوظيفة إلى قيمة المتغير `processed`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/chaining-if-else-statements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/chaining-if-else-statements.md index 004466526db711..088a7b14a5a777 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/chaining-if-else-statements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/chaining-if-else-statements.md @@ -9,7 +9,7 @@ dashedName: chaining-if-else-statements # --description-- -يمكن تسلسل -ربط- عدة تعبيرات `if/else` معًا في السياقات المنطقية المعقدة. إليك مثال من pseudocode أو ما يسمى بالتعليمات البرمجية الزائفة -وهن التعليمات الغير مرتبط بلغة برمجة معينة ولكنه قريب من لغة الإنسان- لعدة تعبير `if` و `else if`: +يمكن تسلسل -ربط- عدة تعبيرات `if/else` معًا في السياقات المنطقية المعقدة. إليك pseudocode أو ما يسمى بالتعليمات البرمجية الزائفة -وهن التعليمات الغير مرتبطة بلغة برمجة واحدة ولكنها قريبة من لغة الإنسان- لعدة عبارات `if` و `else if` مسلسلة: ```js if (condition1) { @@ -26,7 +26,7 @@ if (condition1) { # --instructions-- -اكتب تعبيرات متسلسلة `if`/`else if` للتحقق من الشروط التالية: +اكتب تعبيرات متسلسلة `if`/`else if` لتقَّضي الشروط التالية: `num < 5` - تنتج (return) `Tiny` `num < 10` - تنتج (return) `Small` @@ -48,67 +48,67 @@ assert(code.match(/else/g).length > 3); assert(code.match(/if/g).length > 3); ``` -يجب أن يكون لديك في الأقل تعبير `return` +يجب أن يكون لديك في الأقل تعبير واحد `return` ```js assert(code.match(/return/g).length >= 1); ``` -`testSize(0)` يجب ان تنتج (return) المقطع (string) `Tiny` +`testSize(0)` يجب أن تنتج المقطع النصي `Tiny` ```js assert(testSize(0) === 'Tiny'); ``` -`testSize(4)` يجب ان تنتج (return) المقطع (string) `Tiny` +`testSize(4)` يجب أن تنتج المقطع النصي `Tiny` ```js assert(testSize(4) === 'Tiny'); ``` -`testSize(5)` يجب ان تنتج (return) المقطع (string) `Small` +`testSize(5)` يجب أن تنتج المقطع النصي `Small` ```js assert(testSize(5) === 'Small'); ``` -`testSize(8)` يجب ان تنتج (return) المقطع (string) `Small` +`testSize(8)` يجب أن تنتج المقطع النصي `Small` ```js assert(testSize(8) === 'Small'); ``` -`testSize(10)` يجب ان تنتج (return) المقطع (string) `Medium` +`testSize(10)` يجب أن تنتج المقطع النصي `Medium` ```js assert(testSize(10) === 'Medium'); ``` -`testSize(14)` يجب ان تنتج (return) المقطع (string) `Medium` +`testSize(14)` يجب أن تنتج المقطع النصي `Medium` ```js assert(testSize(14) === 'Medium'); ``` -`testSize(15)` يجب ان تنتج (return) المقطع (string) `Large` +`testSize(15)` يجب أن تنتج المقطع النصي `Large` ```js assert(testSize(15) === 'Large'); ``` -`testSize(17)` يجب ان تنتج (return) المقطع (string) `Large` +`testSize(17)` يجب أن تنتج المقطع النصي `Large` ```js assert(testSize(17) === 'Large'); ``` -`testSize(20)` يجب ان تنتج (return) المقطع (string) `Huge` +`testSize(20)` يجب أن تنتج المقطع النصي `Huge` ```js assert(testSize(20) === 'Huge'); ``` -`testSize(25)` يجب ان تنتج (return) المقطع (string) `Huge` +`testSize(25)` يجب أن تنتج المقطع النصي `Huge` ```js assert(testSize(25) === 'Huge'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code.md index 9e9f0282e7e699..99b48c6e4c4407 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comment-your-javascript-code.md @@ -1,6 +1,6 @@ --- id: bd7123c9c441eddfaeb4bdef -title: التعليق علي تعليماتك البرمجية في JavaScript +title: التعليق (Comment) في كودك من JavaScript challengeType: 1 removeComments: false videoUrl: 'https://scrimba.com/c/c7ynnTp' @@ -10,7 +10,7 @@ dashedName: comment-your-javascript-code # --description-- -التعليقات هي أسطر من التعليمات البرمجية التي سيتجاهلها JavaScript عمداً. التعليقات هي طريقة رائعة لترك الملاحظات لنفسك وللأشخاص الآخرين الذين سيحتاجون لاحقاً إلى معرفة ما تفعله تلك التعليمات البرمجية. +إن التعليقات أسطر من الكود التي سيتجاهلها JavaScript عمداً. إن التعليقات طريقة رائعة لترك الملاحظات لنفسك وللأشخاص الآخرين الذين سيحتاجون لاحقاً إلى معرفة ما يفعله ذلك الكود. هناك طريقتان لكتابة التعليقات في JavaScript: @@ -27,7 +27,7 @@ dashedName: comment-your-javascript-code multi-line comment */ ``` -**ملاحظة:** عند كتابة التعليمات البرمجية، يجب عليك إضافة تعليقات بانتظام لتوضيح وظيفة أجزاء من التعليمات البرمجية الخاص بك. التعليق الجيد يمكن أن يساعد على إيصال المغزى من التعليمات البرمجية الخاص بك - للآخرين *و* لنفسك في المستقبل. +**ملاحظة:** عند كتابة الكود، يجب عليك إضافة تعليقات بانتظام لتوضيح وظيفة أجزاء من كودك. التعليق الجيد يمكن أن يساعد على إيصال المغزى من كودك - للآخرين *و* لنفسك في المستقبل. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-equality-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-equality-operator.md index ba99c3632e39e1..d25e6a6b634aa3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-equality-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-equality-operator.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244d0 -title: المقارنات باستخدام عملية المساواة (==) +title: المقارنة باستخدام مشغِّل المساواة (==) challengeType: 1 videoUrl: 'https://scrimba.com/c/cKyVMAL' forumTopicId: 16784 @@ -9,9 +9,9 @@ dashedName: comparison-with-the-equality-operator # --description-- -هناك العديد من عمليات المساواة في JavaScript. كل هذه العمليات يعيدون قيمة boolean منطقية `true` أو `false`. +هناك العديد من مشغلي المقارنة في JavaScript. كل هذه المشغلين ينتجون قيمة منطقية boolean من `true` أو `false`. -ابسط أنواع هذه العمليات هي عملية مقارنة المساواة `==`. تقارن عملية المساواة بين قيمتين وتعيد `true` إذا كانتا القيمتين متساويتين أو `false` إذا لم تكونا متساويتين. لاحظ أن المساواة تختلف عن تعيين (`=`)، التي تعطي القيمة على يمين العملية إلى متغير على يسارها. +ابسط نوع مشغِّل هو مشغِّل المساواة `==`. يقارن مشغِّل المساواة بين قيمتين و ينتج `true` إذا كانتا القيمتين متساويتين أو `false` إذا لم تكونا كذلك. لاحظ أن المساواة تختلف عن التعيين (`=`)، التي تعطي القيمة على يمين المشغِّل إلى متغير على يساره. ```js function equalityTest(myVal) { @@ -22,7 +22,7 @@ function equalityTest(myVal) { } ``` -إذا كانت قيمة `myVal` تساوي `10`، عملية المساواة تعيد `true`، و بهذا سيتم تنفيذ التعليمات البرمجية في الأقواس، وستعيد الدالة `Equal`. وإلا فإن الوظيفة ستعيد `Not Equal`. لكي تقوم JavaScript بمقارنة نوعين مختلفين في ا نوع البيانات (على سبيل المثال، مقارنة بين نوع `numbers` و نوع `strings`)، يجب أن تحول احدمها إلى نوع الآخر. هذا يُعرف بالقسر النوع (Type Coercion). بمجرد فعل ذلك، يتمكن Javascript من المقارنة بين المصطلحات التالية: +إذا كانت قيمة `myVal` تساوي `10`، عملية المساواة تعيد `true`، و بهذا سيتم تنفيذ التعليمات البرمجية المكتوبة بين الأقواس، وستنتج الوظيفة `Equal`. وإلا فإن الوظيفة ستنتج `Not Equal`. لكي تقوم JavaScript بمقارنة بين نوعين مختلفين من أنواع البيانات (على سبيل المثال، نوع `numbers` و نوع `strings`)، يجب أن تحوِّل احدمها إلى النوع الآخر. هذا يُعرف بقسر النوع (Type Coercion). بمجرد فعل ذلك، يتمكن Javascript من المقارنة بين المصطلحات كما يلي: ```js 1 == 1 // true @@ -33,23 +33,23 @@ function equalityTest(myVal) { # --instructions-- -اضف عملية المساواة إلى المكان المشار أليه كي تعيد الوظيفة `Equal` إذا تساوي `val` قيمة `12`. +اضف مشغِّل المساواة إلى المكان المشار أليه كي تنتج الوظيفة `Equal` إذا تساوت `val` بعدد `12`. # --hints-- -يجب أن `testEqual(10)` تعيد `Not Equal` +يجب أن `testEqual(10)` تنتج `Not Equal` ```js assert(testEqual(10) === 'Not Equal'); ``` -يجب أن `testEqual(12)` تعيد `Equal` +يجب أن `testEqual(12)` تنتج `Equal` ```js assert(testEqual(12) === 'Equal'); ``` -يجب أن `testEqual("12")` تعيد `Equal` +يجب أن `testEqual("12")` تنتج `Equal` ```js assert(testEqual('12') === 'Equal'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-operator.md index 2615e15bf79928..7651c79201db74 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-operator.md @@ -9,9 +9,9 @@ dashedName: comparison-with-the-greater-than-operator # --description-- -مشغل أكبر من (`>`) يقارن بين قيم رقمين. إذا كان الرَّقَم إلى اليسار أكبر من الرَّقَم إلى اليمين (لأن التعليمات البرمجية بالإنكليزية)، فإنه ينتج `true`. خلاف ذلك، فإنه ينتج `false`. +مشغل أكبر من (`>`) يقارن بين قيمة رقمين. إذا كان الرَّقَم إلى اليسار أكبر من الرَّقَم إلى اليمين (لأن التعليمات البرمجية بالإنجليزية)، فإنه ينتج `true`. خلاف ذلك، فإنه ينتج `false`. -وعلى غرار المشغل المعني بالمساواة، فإن مشغل أكبر من سيحول أنواع البيانات من القيم عند مقارنتها. +وعلى غرار مشغل المساواة، فإن مشغل أكبر من سيحول أنواع قيم البيانات عند مقارنتها. **على سبيل المثال** diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-or-equal-to-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-or-equal-to-operator.md index 6be5d8971e1d4b..5d56a0661fb2a0 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-or-equal-to-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-greater-than-or-equal-to-operator.md @@ -9,9 +9,9 @@ dashedName: comparison-with-the-greater-than-or-equal-to-operator # --description-- -يقارن مشغل أكبر من أو يساوي (`>=`) بين قيمتين لرقمين. إذا كان الرَّقَم إلى اليسار أكبر من لو يساوي الرَّقَم إلى اليمين، فإنه يرجع `true`. خلاف ذلك، فإنه يرجع `false`. +يقارن مشغل أكبر من أو يساوي (`>=`) بين قيمتين لرقمين. إذا كان الرَّقَم إلى اليسار أكبر من أو يساوي الرَّقَم إلى اليمين، فإنه يرجع `true`. خلاف ذلك، فإنه يرجع `false`. -وعلى غرار المشغل المعني بالمساواة، سيحول مشغل أكبر من أو يساوي أنواع البيانات من القيم عند مقارنتها. +وعلى غرار مشغل المساواة، سيحول مشغل أكبر من أو يساوي نوع البيانات عند مقارنتها. **على سبيل المثال** @@ -24,47 +24,47 @@ dashedName: comparison-with-the-greater-than-or-equal-to-operator # --instructions-- -أضف أكبر من أو يساوي إلى الخطوط المشار إليها بحيث تكون عبارات المراجعة منطقية. +أضف أكبر من أو يساوي إلى الخطوط المشار إليها بحيث تكون عبارات return منطقية. # --hints-- -يجب أن ينتج `testGreaterOrEqual(0)` مقطع `Less than 10` +يجب أن ينتج `testGreaterOrEqual(0)` المقطع النصي `Less than 10` ```js assert(testGreaterOrEqual(0) === 'Less than 10'); ``` -يجب أن ينتج `testGreaterOrEqual(9)` مقطع `Less than 10` +يجب أن ينتج `testGreaterOrEqual(9)` المقطع النصي `Less than 10` ```js assert(testGreaterOrEqual(9) === 'Less than 10'); ``` -يجب أن ينتج `testGreaterOrEqual(10)` مقطع `10 or Over` +يجب أن ينتج `testGreaterOrEqual(10)` المقطع النصي `10 or Over` ```js assert(testGreaterOrEqual(10) === '10 or Over'); ``` -يجب أن ينتج `testGreaterOrEqual(11)` مقطع `10 or Over` +يجب أن ينتج `testGreaterOrEqual(11)` المقطع النصي `10 or Over` ```js assert(testGreaterOrEqual(11) === '10 or Over'); ``` -يجب أن ينتج `testGreaterOrEqual(19)` مقطع `10 or Over` +يجب أن ينتج `testGreaterOrEqual(19)` المقطع النصي `10 or Over` ```js assert(testGreaterOrEqual(19) === '10 or Over'); ``` -يجب أن ينتج `testGreaterOrEqual(100)` مقطع `20 or Over` +يجب أن ينتج `testGreaterOrEqual(100)` المقطع النصي `20 or Over` ```js assert(testGreaterOrEqual(100) === '20 or Over'); ``` -يجب أن ينتج `testGreaterOrEqual(21)` مقطع `20 or Over` +يجب أن ينتج `testGreaterOrEqual(21)` المقطع النصي `20 or Over` ```js assert(testGreaterOrEqual(21) === '20 or Over'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-inequality-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-inequality-operator.md index 2152a1203e1441..1ddb452bc04421 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-inequality-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-inequality-operator.md @@ -9,7 +9,7 @@ dashedName: comparison-with-the-inequality-operator # --description-- -مشغل لا مساواة (`!=`) هو يخالف مشغل المساواة. وهذا يعني لا مساواة يرجع `false` عندما ترجع المساواة `true` و*العكس كذلك*. وعلى غرار المشغل المعني بالمساواة، فإن مشغل لا مساواة سيحول أنواع البيانات من القيم عند مقارنتها. +مشغل لا مساواة (`!=`) هو يخالف مشغل المساواة. وهذا يعني أنَّ لا مساواة يرجع `false` فحين ترجع المساواة `true` و*العكس كذلك*. وعلى غرار مشغل المساواة، فإن مشغل لا مساواة سيحول أنواع قيم البيانات عند مقارنتها. **على سبيل المثال** @@ -23,35 +23,35 @@ dashedName: comparison-with-the-inequality-operator # --instructions-- -أضف مشغل لا مساواة `!=` في `if` بحيث تقوم الوظيفة بإنشاء مقطع الآتي `Not Equal` عندما لا يساوي `val` القيمة `99`. +أضف مشغل لا مساواة `!=` في `if` بحيث تقوم الوظيفة بإنشاء مقطع الآتي `Not Equal` عندما لا يساوي `val` عدد `99`. # --hints-- -يجب أن ينتج `testNotEqual(99)` مقطع `Equal` +يجب أن ينتج `testNotEqual(99)` المقطع النصي `Equal` ```js assert(testNotEqual(99) === 'Equal'); ``` -يجب أن ينتج `testNotEqual("99")` مقطع `Equal` +يجب أن ينتج `testNotEqual("99")` المقطع النصي `Equal` ```js assert(testNotEqual('99') === 'Equal'); ``` -يجب أن ينتج `testNotEqual(12)` مقطع `Not Equal` +يجب أن ينتج `testNotEqual(12)` المقطع النصي `Not Equal` ```js assert(testNotEqual(12) === 'Not Equal'); ``` -يجب أن ينتج `testNotEqual("12")` مقطع `Not Equal` +يجب أن ينتج `testNotEqual("12")` المقطع النصي `Not Equal` ```js assert(testNotEqual('12') === 'Not Equal'); ``` -يجب أن ينتج `testNotEqual("bob")` مقطع `Not Equal` +يجب أن ينتج `testNotEqual("bob")` المقطع `Not Equal` ```js assert(testNotEqual('bob') === 'Not Equal'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-operator.md index c6267e78e2cf18..961d6cd2dd879d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-operator.md @@ -9,7 +9,7 @@ dashedName: comparison-with-the-less-than-operator # --description-- -يقارن مشغل آلأصغر من (`<`) بين قيمتين رقمين. إذا كان الرَّقَم إلى اليسار أصغر من الرَّقَم إلى اليمين، فإنه يرجع `true`. خلاف ذلك، فإنه يرجع `false`. وعلى غرار المشغل المعني بالمساواة، يقوم المشغل أقل من بتحويل أنواع البيانات عند مقارنتها. +يقارن مشغل الأصغر من (`<`) بين قيم رقمين. إذا كان الرَّقَم إلى اليسار أصغر من الرَّقَم إلى اليمين، فإنه يرجع `true`. خلاف ذلك، فإنه يرجع `false`. وعلى غرار مشغل المساواة، يقوم المشغل أقل من بتحويل أنواع البيانات عند مقارنتها. **مثال** @@ -23,41 +23,41 @@ dashedName: comparison-with-the-less-than-operator # --instructions-- -أضف مشغل أقل من إلى الخطوط المشار إليها بحيث تكون تعبيرات مراجعة منطقية. +أضف مشغل أقل من إلى الخطوط المشار إليها بحيث تكون تعبيرات return منطقية. # --hints-- -يجب أن ينتج `testLessThan(0)` مقطع `Under 25` +يجب أن ينتج `testLessThan(0)` المقطع النصي `Under 25` ```js assert(testLessThan(0) === 'Under 25'); ``` -يجب أن ينتج `testLessThan(24)` مقطع `Under 25` +يجب أن ينتج `testLessThan(24)` المقطع النصي `Under 25` ```js assert(testLessThan(24) === 'Under 25'); ``` -يجب أن ينتج `testLessThan(25)` مقطع `Under 55` +يجب أن ينتج `testLessThan(25)` المقطع النصي `Under 55` ```js assert(testLessThan(25) === 'Under 55'); ``` -يجب أن ينتج `testLessThan(54)` مقطع `Under 55` +يجب أن ينتج `testLessThan(54)` المقطع النصي `Under 55` ```js assert(testLessThan(54) === 'Under 55'); ``` -يجب أن ينتج `testLessThan(55)` مقطع `55 or Over` +يجب أن ينتج `testLessThan(55)` المقطع النصي `55 or Over` ```js assert(testLessThan(55) === '55 or Over'); ``` -يجب أن ينتج `testLessThan(99)` مقطع `55 or Over` +يجب أن ينتج `testLessThan(99)` المقطع النصي `55 or Over` ```js assert(testLessThan(99) === '55 or Over'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-or-equal-to-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-or-equal-to-operator.md index 1711aa9696d5a0..de1b05704591c7 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-or-equal-to-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-less-than-or-equal-to-operator.md @@ -9,7 +9,7 @@ dashedName: comparison-with-the-less-than-or-equal-to-operator # --description-- -مشغل اصغر من أو يساوي، (`<=`) يقارن بين قيم رقمين. إذا كان الرَّقَم إلى اليسار أقل من أو يساوي الرَّقَم إلى اليمين، فإنه يعيد `true`. إذا كان الرَّقَم الموجود على اليسار أكبر من الرَّقَم الموجود على اليمين، فإنه يعيد `false`. وعلى غرار المشغل المعني بالمساواة، يحول مشغل اصغر من أو يساوي أنواع البيانات من القيم عند مقارنتها. +مشغل اصغر من أو يساوي، (`<=`) يقارن بين قيم رقمين. إذا كان الرَّقَم إلى اليسار أقل من أو يساوي الرَّقَم إلى اليمين، فإنه يعيد `true`. إذا كان الرَّقَم الموجود على اليسار أكبر من الرَّقَم الموجود على اليمين، فإنه يعيد `false`. وعلى غرار مشغل المساواة، يحول مشغل اصغر من أو يساوي أنواع البيانات عند مقارنتها. **مثال** @@ -23,47 +23,47 @@ dashedName: comparison-with-the-less-than-or-equal-to-operator # --instructions-- -أضف مشغل اصغر من أو يساوي إلى السطور المشار إليها بحيث تكون تعبيرات المراجعة منطقية. +أضف مشغل اصغر من أو يساوي إلى السطور المشار إليها بحيث تكون تعبيرات return منطقية. # --hints-- -يجب أن ينتج `testLessOrEqual(0)` المقطع `Smaller Than or Equal to 12` +يجب أن ينتج `testLessOrEqual(0)` المقطع النصي `Smaller Than or Equal to 12` ```js assert(testLessOrEqual(0) === 'Smaller Than or Equal to 12'); ``` -يجب أن ينتج `testLessOrEqual(11)` مقطع `Smaller Than or Equal to 12` +يجب أن ينتج `testLessOrEqual(11)` المقطع النصي `Smaller Than or Equal to 12` ```js assert(testLessOrEqual(11) === 'Smaller Than or Equal to 12'); ``` -يجب أن ينتج `testLessOrEqual(12)` مقطع `Smaller Than or Equal to 12` +يجب أن ينتج `testLessOrEqual(12)` المقطع النصي `Smaller Than or Equal to 12` ```js assert(testLessOrEqual(12) === 'Smaller Than or Equal to 12'); ``` -يجب أن ينتج `testLessOrEqual(23)` مقطع `Smaller Than or Equal to 24` +يجب أن ينتج `testLessOrEqual(23)` المقطع النصي `Smaller Than or Equal to 24` ```js assert(testLessOrEqual(23) === 'Smaller Than or Equal to 24'); ``` -يجب أن ينتج `testLessOrEqual(24)` مقطع `Smaller Than or Equal to 24` +يجب أن ينتج `testLessOrEqual(24)` المقطع النصي `Smaller Than or Equal to 24` ```js assert(testLessOrEqual(24) === 'Smaller Than or Equal to 24'); ``` -يجب أن ينتج `testLessOrEqual(25)` مقطع `More Than 24` +يجب أن ينتج `testLessOrEqual(25)` المقطع النصي `More Than 24` ```js assert(testLessOrEqual(25) === 'More Than 24'); ``` -يجب أن ينتج `testLessOrEqual(55)` مقطع `More Than 24` +يجب أن ينتج `testLessOrEqual(55)` المقطع النصي `More Than 24` ```js assert(testLessOrEqual(55) === 'More Than 24'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-strict-equality-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-strict-equality-operator.md index 13af72577bc9ed..492efaa3412895 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-strict-equality-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparison-with-the-strict-equality-operator.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244d1 -title: المقارنات باستخدام المساواة الصارمة +title: المقارنات باستخدام مشغِّل المساواة الصارمة challengeType: 1 videoUrl: 'https://scrimba.com/c/cy87atr' forumTopicId: 16790 @@ -11,7 +11,7 @@ dashedName: comparison-with-the-strict-equality-operator يكون مشغل المساواة الصارمة (`===`) نظير مشغل المساواة (`==`). ومع ذلك، وخلافاً لمشغل المساواة، الذي يحاول تحويل القيمتين إلى نوع مشترك، لا يقوم مشغل المساواة الصارمة (strict equality) بإجراء تحويل من نوع إلى آخر. -وإذا كانت القيم التي تجري مقارنتها ذات أنواع مختلفة، فإنها تعدّ غير متساوية، وسيعيد مشغل المساواة الصارمة القيمة false. +وإذا كانت القيم التي تقارن ذات أنواع مختلفة، فإنها تعدّ غير متساوية، وسيعيد مشغل المساواة الصارمة القيمة false. **على سبيل المثال** @@ -24,11 +24,11 @@ dashedName: comparison-with-the-strict-equality-operator # --instructions-- -استخدام مشغل المساواة الصارمة في بيان `if` حتي تنتج الوظيفة مقطع باسم `Equal` عندما يكون `val` مساوية بطريقة صارمة (strictly equal) إلى `7`. +استخدم مشغل المساواة الصارمة في بيان `if` حتي تنتج الوظيفة مقطع نصي قيمته `Equal` عندما يكون `val` مساوي بطريقة صارمة (strictly equal) إلى `7`. # --hints-- -يجب أن ينتج `testStrict(10)` مقطع `Not Equal` +يجب أن ينتج `testStrict(10)` المقطع النصي `Not Equal` ```js assert(testStrict(10) === 'Not Equal'); @@ -40,7 +40,7 @@ assert(testStrict(10) === 'Not Equal'); assert(testStrict(7) === 'Equal'); ``` -يجب أن ينتج `testStrict("7")` مقطع `Not Equal` +يجب أن ينتج `testStrict("7")` المقطع النصي `Not Equal` ```js assert(testStrict('7') === 'Not Equal'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator.md index 76498e5720d428..e0b544b68f9a72 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-and-operator.md @@ -11,7 +11,7 @@ dashedName: comparisons-with-the-logical-and-operator ستحتاج أحيانًا إلى اختبار أكثر من شيء في وقت واحد. مشغل الإضافة المنطقي ورمزه (`&&`) يرجع `true` فقط إذا كان المعاملتين إلى اليسار واليمين صحيحين. -ويمكن تحقيق نفس التأثير عن طريق أدخال if statement داخل if أخري: +ويمكن تحقيق نفس التأثير عن طريق وضع عبارة if داخل if أخري: ```js if (num > 5) { @@ -33,7 +33,7 @@ return "No"; # --instructions-- -استبدل بيانين if إلى if statement واحدة، باستخدام المشغل `&&`، الذي سوف يعيد المقطع `Yes` إذا كان `val` أقل من أو يساوي `50` وأكثر من أو يساوي `25`. خلاف ذلك، سوف يعيد المقطع `No`. +استبدل العبارتان if إلى if واحدة، باستخدام المشغل `&&`، الذي سوف يعيد المقطع `Yes` إذا كان `val` أقل من أو يساوي `50` وأكثر من أو يساوي `25`. خلاف ذلك، سوف يعيد المقطع `No`. # --hints-- @@ -43,55 +43,55 @@ return "No"; assert(code.match(/&&/g).length === 1); ``` -يجب أن يكون لديك بيان `if` واحد فقط +يجب أن يكون لديك عبارة `if` واحد فقط ```js assert(code.match(/if/g).length === 1); ``` -يجب أن ينتج `testLogicalAnd(0)` مقطع `No` +يجب أن ينتج `testLogicalAnd(0)` المقطع النصي `No` ```js assert(testLogicalAnd(0) === 'No'); ``` -يجب أن ينتج `testLogicalAnd(24)` المقطع `No` +يجب أن ينتج `testLogicalAnd(24)` المقطع النصي `No` ```js assert(testLogicalAnd(24) === 'No'); ``` -يجب أن ينتج `testLogicalAnd(25)` المقطع `Yes` +يجب أن ينتج `testLogicalAnd(25)` المقطع النصي `Yes` ```js assert(testLogicalAnd(25) === 'Yes'); ``` -يجب أن ينتج `testLogicalAnd(30)` المقطع `Yes` +يجب أن ينتج `testLogicalAnd(30)` المقطع النصي `Yes` ```js assert(testLogicalAnd(30) === 'Yes'); ``` -يجب أن ينتج `testLogicalAnd(50)` المقطع `Yes` +يجب أن ينتج `testLogicalAnd(50)` المقطع النصي `Yes` ```js assert(testLogicalAnd(50) === 'Yes'); ``` -يجب أن ينتج `testLogicalAnd(51)` المقطع `No` +يجب أن ينتج `testLogicalAnd(51)` المقطع النصي `No` ```js assert(testLogicalAnd(51) === 'No'); ``` -يجب أن ينتج `testLogicalAnd(75)` المقطع `No` +يجب أن ينتج `testLogicalAnd(75)` المقطع النصي `No` ```js assert(testLogicalAnd(75) === 'No'); ``` -يجب أن ينتج `testLogicalAnd(80)` المقطع `No` +يجب أن ينتج `testLogicalAnd(80)` المقطع النصي `No` ```js assert(testLogicalAnd(80) === 'No'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-or-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-or-operator.md index 9560f668cf36ea..edfcdfd35bf3e8 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-or-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/comparisons-with-the-logical-or-operator.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244d9 -title: المقارنات باستخدام مشغل إي من المنطقي +title: المقارنات باستخدام مشغل إي من (or) المنطقي (||) challengeType: 1 videoUrl: 'https://scrimba.com/c/cEPrGTN' forumTopicId: 16800 @@ -9,9 +9,9 @@ dashedName: comparisons-with-the-logical-or-operator # --description-- -يرجع مشغل إي من الآتي (`||`) القيمة `true` إذا كان أي من المعاملتين هما `true`. خلاف ذلك، فإنه يرجع `false`. +يرجع مشغل إي من (logical or) الآتي (`||`) القيمة `true` إذا كان أي من المعاملتين هما `true`. خلاف ذلك، فإنه يرجع `false`. -يتكون مشغل المعاملات من رمزين و هما خطين مستقيمين ألآتيه: (`||`). يمكن العثور على هذا الرمز عادة بين مفاتيح Backspace و Enter. +يتكون مشغل إي من من رمزين و هما خطين مستقيمين كالآتي: (`||`). يمكن العثور على هذا الرمز عادة بين مفاتيح Backspace و Enter. يجب أن يبدو النمط أدناه مألوفًا من الدروس السابقة: @@ -36,7 +36,7 @@ return "Yes"; # --instructions-- -قم بدمج تعبيرات `if` في تعبير واحدة تعيد المقطع `Outside` إذا كان `val` ليس بين `10` و `20` بشمول 10 و 20. خلاف ذلك، ارجع المقطع `Inside`. +قم بدمج تعبيرات `if` في تعبير واحد ينتج المقطع `Outside` إذا كان `val` ليس بين `10` و `20` بشمول 10 و 20. خلاف ذلك، ارجع المقطع `Inside`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-addition.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-addition.md index 919d753d4e1899..dca867620cbedf 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-addition.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-addition.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244af -title: التخصيص المركب مع الجمع المعزز (Compound Assignment With Augmented Addition) +title: التعيين المركب مع الجمع المعزز challengeType: 1 videoUrl: 'https://scrimba.com/c/cDR6LCb' forumTopicId: 16661 @@ -9,13 +9,13 @@ dashedName: compound-assignment-with-augmented-addition # --description-- -في البرمجة، من الشائع استخدام assignments (التعيينات) لتعديل محتوي المتغير. تذكر أن كل شيء إلى يمين علامة المساواة يتم تقييمه أولا، لذلك يمكننا القول: +في البرمجة، من الشائع استخدام assignments (التعيينات) لتعديل محتوي المتغير. تذكر أن كل شيء إلى يمين علامة المساواة يتم تقييمه أولا، لذلك يمكننا أن نقول: ```js myVar = myVar + 5; ``` -لإضافة `5` إلى `myVar`. نظرًا لأن هذا نمط شائع، فهناك مشغلين يقوموا بعملية رياضية وتعيين في خطوة واحدة. +وذلك يضيف `5` إلى `myVar`. نظرًا أن هذا نمط شائع، فهناك مشغلين يقومون بالعملية الرياضية مع عملية التعيين في خطوة واحدة. أحد هؤلاء المشغلين هو مشغل `+=`. @@ -25,11 +25,11 @@ myVar += 5; console.log(myVar); ``` -سوف يتم عرض `6` في وحدة التحكم. +سوف يتم عرض `6` في الكونسول. # --instructions-- -تحويل التعيينات `a`, و `b`, و `c` لتستخدم المشغل `+=`. +حوِّل التعيينات `a` و `b` و `c` لتستخدم المشغل `+=`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-division.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-division.md index 0cb5a2a5c80a2b..f315b7ac7cb16e 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-division.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-division.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b2 -title: التخصيص المركب مع التقسيم المعزز (Compound Assignment With Augmented Division) +title: التعيين المركب مع التقسيم المعزز challengeType: 1 videoUrl: 'https://scrimba.com/c/c2QvKT2' forumTopicId: 16659 diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-multiplication.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-multiplication.md index 050c27a8f25ccc..8a36f3ee17851d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-multiplication.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-multiplication.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b1 -title: التخصيص المركب مع الضرب المعزز (Compound Assignment With Augmented Multiplication) +title: التعيين المركب مع الضرب المعزز challengeType: 1 videoUrl: 'https://scrimba.com/c/c83vrfa' forumTopicId: 16662 @@ -9,13 +9,13 @@ dashedName: compound-assignment-with-augmented-multiplication # --description-- -يقوم المشغل `*=` مضاعفة متغير في عدد. +يقوم المشغل `*=` f بمضاعفة متغير في عدد. ```js myVar = myVar * 5; ``` -سوف تضاعف `myVar` في `5`. ويمكن إعادة كتابة هذا على النحو التالي: +سيتم ضرب `myVar` في `5`. ويمكن إعادة كتابة هذا على النحو التالي: ```js myVar *= 5; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-subtraction.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-subtraction.md index 77ffd07f38d1d4..6b5425dfb4260e 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-subtraction.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/compound-assignment-with-augmented-subtraction.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b0 -title: التخصيص المركب مع الطرح المعزز (Compound Assignment With Augmented Subtraction) +title: التعيين المركب مع الطرح المعزز challengeType: 1 videoUrl: 'https://scrimba.com/c/c2Qv7AV' forumTopicId: 16660 diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-plus-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-plus-operator.md index 2b3549a3d8b1f1..a6153f6d93f5ee 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-plus-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-plus-operator.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b7 -title: ربط المقاطع النصية باستخدام مشغل الجمع (Concatenating Strings with Plus Operator) +title: ربط المقاطع النصية باستخدام مشغل الجمع challengeType: 1 videoUrl: 'https://scrimba.com/c/cNpM8AN' forumTopicId: 16802 @@ -9,7 +9,7 @@ dashedName: concatenating-strings-with-plus-operator # --description-- -في JavaScript، عندما يستخدم مشغل `+` مع `String`، فإنه يسمى مشغل سلسلة. يمكنك بناء مقطع جديد من المقاطع الأخرى من طريق تجميع السلسلة بعضها مع بعض. +في JavaScript، عندما يستخدم مشغل `+` مع `String`، فإنه يسمى مشغل الضم. يمكنك بناء مقطع نصي جديد من المقاطع الأخرى عن طريق ضم بعضها مع بعض. **مثال** @@ -17,7 +17,7 @@ dashedName: concatenating-strings-with-plus-operator 'My name is Alan,' + ' I concatenate.' ``` -**ملاحظة:** احترس من المسافات. لإن ربط السلسلة لا تضيف مسافات بين المقاطع الذي تم جمعها، لذا ستحتاج إلى إضافتها بنفسك. +**ملاحظة:** احترس من المسافات. لإن مشغِّل الضم لا يضيف مسافات بين المقاطع الذي يجمعها، لذا ستحتاج إلى إضافتها بنفسك. مثال: @@ -25,14 +25,14 @@ dashedName: concatenating-strings-with-plus-operator const ourStr = "I come first. " + "I come second."; ``` -المقطع الآتي `I come first. I come second.` سيتم عرضه في وحدة التحكم. +سيعرض الكونسول المقطع الآتي `I come first. I come second.`. # --instructions-- أنشئ `myStr` من المقاطع الآتية `This is the start.` و `This is the end.` باستخدام المشغل `+`. تيقن من تضمين مسافة بين المقاطع. # --hints-- -يجب أن يوجد حرف الفراغ واحد بين المقطعين في `myStr`. +يجب أن يوجد حرف فراغ واحد بين المقطعين في `myStr`. ```js assert(/start\. This/.test(myStr)); @@ -56,7 +56,7 @@ assert(code.match(/(["']).*\1\s*\+\s*(["']).*\2/g)); assert(/const\s+myStr/.test(code)); ``` -يجب عليك تعيين النتيجة إلى متغير `myStr`. +يجب عليك تعيين النتيجة إلى المتغير `myStr`. ```js assert(/myStr\s*=/.test(code)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-the-plus-equals-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-the-plus-equals-operator.md index 17d0739b8002bb..8a5a60ad3d025a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-the-plus-equals-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/concatenating-strings-with-the-plus-equals-operator.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b8 -title: ربط المقاطع النصية باستخدام مشغل =+ (Concatenating Strings with the Plus Equals Operator) +title: ضم المقاطع النصية باستخدام مشغل =+ (Concatenating Strings with the Plus Equals Operator) challengeType: 1 videoUrl: 'https://scrimba.com/c/cbQmmC4' forumTopicId: 16803 @@ -9,9 +9,9 @@ dashedName: concatenating-strings-with-the-plus-equals-operator # --description-- -يمكننا أيضًا استخدام المشغل `+=` لربط مقطع كسلسلة في نهاية متغير مقطع نصي أخر موجود. ويمكن أن يكون ذلك مفيدا جدا لكسر المقطع طويل على عدة اسطر. +يمكننا أيضًا استخدام المشغل `+=` لضم مقطع نصي في نهاية متغير مقطع نصي آخر موجود. ويمكن أن يكون ذلك مفيدا جدا لكسر مقطع نصي طويل على عدة اسطر. -**ملاحظة:** احترس من المسافات. لا يضيف التسلسل مسافات بين مقاطع نصية المتسلسلة التي تم جمعها، لذا ستحتاج إلى إضافتها بنفسك. +**ملاحظة:** احترس من المسافات. لا يضيف المشغِّل مسافات بين المقاطع النصية المتسلسلة عند جمعها، لذا ستحتاج إلى إضافتها بنفسك. مثال: @@ -20,21 +20,21 @@ let ourStr = "I come first. "; ourStr += "I come second."; ``` -يحتوي `ourStr` قيمة مقطع الآتي `I come first. I come second.` الآن. +يحتوي `ourStr` على قيمة المقطع النصي الآتي `I come first. I come second.` الآن. # --instructions-- -أبني `myStr` على عدة اسطر بواسطة عمل سلسلة من المقاطع الآتية: `This is the first sentence.` و `This is the second sentence.` باستخدام المشغل `+=`. استخدم مشغل `+=` بطريقة مشابهة لكيفية عرضه في المثال وتيقن من تضمين مسافة بين المقاطع. ابدأ بتعيين المقطع الأول إلى `myStr`، ثم أضف المقطع الثاني. +ابني `myStr` على عدة اسطر بضم المقاطع الآتية: `This is the first sentence.` و `This is the second sentence.` و استخدم المشغل `+=`. استخدم مشغل `+=` بطريقة مشابهة للمثال وتيقن من تضمين مسافة بين المقاطع. ابدأ بتعيين المقطع الأول إلى `myStr`، ثم أضف المقطع الثاني. # --hints-- -يجب أن يوجد حرف الفراغ واحد بين المقطعين في `myStr`. +يجب أن يوجد حرف فراغ واحد بين المقطعين في `myStr`. ```js assert(/sentence\. This/.test(myStr)); ``` -يجب أن يكون قيمة `myStr` مقطع الآتي `This is the first sentence. This is the second sentence.` +يجب أن يكون قيمة `myStr` المقطع النصي الآتي `This is the first sentence. This is the second sentence.` ```js assert(myStr === 'This is the first sentence. This is the second sentence.'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/constructing-strings-with-variables.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/constructing-strings-with-variables.md index 7283a670b96eea..e80668cde93ff9 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/constructing-strings-with-variables.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/constructing-strings-with-variables.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b9 -title: بناء المقاطع النصية باستخدام المتغيرات (Constructing Strings with Variables) +title: بناء المقاطع النصية باستخدام المتغيرات challengeType: 1 videoUrl: 'https://scrimba.com/c/cqk8rf4' forumTopicId: 16805 @@ -9,7 +9,7 @@ dashedName: constructing-strings-with-variables # --description-- -أحيانا قد تحتاج إلي إنشاء مقطع. في أثناء استخدام مشغل التسلسل الآتي (`+`)، يمكنك إدخال متغير واحد أو أكثر في مقطع الذي تقوم ببنائه. +أحيانا قد تحتاج إلي إنشاء مقطع نصي. باستخدام مشغل الضم الآتي (`+`)، يمكنك إدخال متغير واحد أو أكثر في المقطع الذي تقوم ببنائه. مثال: @@ -22,17 +22,17 @@ const ourStr = "Hello, our name is " + ourName + ", how are you?"; # --instructions-- -عيّن `myName` إلى مقطع مساوي لأسمك وأبني `myStr` بقيمة `myName` بين المقطعين الآتيين `My name is` و `and I am well!` +عيّن `myName` إلى مقطع مساوي لأسمك وأبني `myStr` واضعاً `myName` بين المقطعين الآتيين `My name is` و `and I am well!` # --hints-- -يجب تعيين `myName` كمقطع يحتوي 3 رموز في الأقل. +يجب تعيين `myName` كمقطع نصي يحتوي 3 رموز في الأقل. ```js assert(typeof myName !== 'undefined' && myName.length > 2); ``` -يجب عليك استخدام مشغلين اثنين من `+` لبناء `myStr` يحتوي `myName` داخله. +يجب عليك استخدام `+` مرتين لبناء `myStr` باحتواء `myName` داخله. ```js assert(code.match(/["']\s*\+\s*myName\s*\+\s*["']/g).length > 0); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/count-backwards-with-a-for-loop.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/count-backwards-with-a-for-loop.md index 8640a6e7e2ebda..98eb93fd0cb66d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/count-backwards-with-a-for-loop.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/count-backwards-with-a-for-loop.md @@ -23,7 +23,7 @@ for (let i = 10; i > 0; i -= 2) { } ``` -سوف تحتوي `ourArray` الآن على `[10, 8, 6, 4, 2]`. غير التغيير البادئ (initialization) و التعبير الأخير (final expression) حتى نتمكن من العد إلى الوراء بمقدار اثنين لإنشاء قائمة (array) من الأعداد التنازلية الفردية. +سوف تحتوي `ourArray` الآن على `[10, 8, 6, 4, 2]`. غير التعبير البادئ (initialization) و التعبير الأخير (final expression) حتى نتمكن من العد إلى الوراء بمقدار اثنين لإنشاء قائمة (array) من الأعداد التنازلية الفردية. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/counting-cards.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/counting-cards.md index 5b7d22358c78fb..0a7efac2579b8a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/counting-cards.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/counting-cards.md @@ -1,6 +1,6 @@ --- id: 565bbe00e9cc8ac0725390f4 -title: عدد الأوراق (Counting Cards) +title: عد أوراق اللعب challengeType: 1 videoUrl: 'https://scrimba.com/c/c6KE7ty' forumTopicId: 16809 @@ -9,23 +9,23 @@ dashedName: counting-cards # --description-- -في لُعْبَة النادي بلاك جاك، يمكن للاعب أن يحدد ما إذا كان يتمتع بميزة على المنزل بواسطة تتبع العدد النسبي للبطاقات المرتفعة والمنخفضة المتبقية في مجموعة الورق. هذا يسمى إحصاء الورق (Card Counting). +في لُعْبَة بلاك جاك (blackjack)، يمكن للاعب أن يحدد ما إذا كان يتمتع بميزة على اللاعب الموزِّع بواسطة تتبع العدد النسبي للأوراق المرتفعة والمنخفضة المتبقية في مجموعة الورق. هذا يسمى إحصاء الورق (Card Counting). -يكون وجود المزيد من الورق عالي القيمة المتبقي في المجموعة, أفضل للاعب. يتم تعيين قيمة لكل بطاقة وفقاً للجدول بالأدنى. عندما يكون العد موجبًا، يجب على اللاعب المراهنة بشكل مرتفع. عندما يكون العد صفرًا أو سلبيًا، يجب أن يراهن اللاعب على انخفاض. +يكون وجود المزيد من الورق عالي القيمة المتبقي في المجموعة, أفضل للاعب. يتم تعيين قيمة لكل ورقة لعب وفقاً للجدول بالأدنى. عندما يكون العد موجبًا، يجب على اللاعب المراهنة بشكل مرتفع. عندما يكون العد صفرًا أو سلبيًا، يجب أن يراهن اللاعب بشكل منخفض.
    - {title} + + {t(`certification.project.title.${title}`, title)} + {this.getProjectSolution(id, title)} @@ -283,7 +286,8 @@ export class CertificationSettings extends Component { data-cy={`btn-for-${certSlug}`} onClick={createClickHandler(certSlug)} > - {isCert ? t('buttons.show-cert') : t('buttons.claim-cert')} + {isCert ? t('buttons.show-cert') : t('buttons.claim-cert')}{' '} + {certName}
    تغيير العدالأوراق
    +12, 3, 4, 5, 6
    07, 8, 9
    -110, 'J', 'Q', 'K', 'A'
    -سوف تكتب وظيفة لعد الورق. سوف يتلقى حِجَّة `card`, الذي يمكن أن يكون رقما أو مقطع، ويزيد أو يخفض متغير `count` وفقا لقيمة الورقة (انظر إلى الجدول). ثم ستقوم الوظيفة (function) بإنشاء مقطع (string) يحتوي علي العد الحالي والمقطع `Bet` إذا كان العد إيجابياً، أو `Hold` إذا كان العد صفر أو سلبي. يجب أن يفصل العد الحالي وقرار اللاعب (`Bet` أو `Hold`) بمسافة واحدة. +سوف تكتب وظيفة لعد الورق. سوف تتلقى وسيط (parameter) اسمه `card`, الذي يمكن أن يكون رقما أو مقطع نصي (string)، وسوف تزيد أو تخفض متغير `count` وفقا لقيمة الورقة المعطى (انظر إلى الجدول). ثم ستقوم الوظيفة بإنشاء مقطع نصي يحتوي علي العد الحالي وكلمة `Bet` إذا كان العد إيجابياً، أو `Hold` إذا كان العد صفر أو سلبي. يجب أن يفصل العد الحالي وقرار اللاعب (`Bet` أو `Hold`) بمسافة فارعة واحدة. **مثال على النتائج:** كالآتي `-3 Hold` أو `5 Bet` **تلميح** -لا تعيد تعيين `count` إلى 0 عندما تكون القيمة 7 أو 8 أو 9. لا بإنشاء قائمة. +لا تعيد تعيين `count` إلى 0 عندما تكون القيمة 7 أو 8 أو 9. لا تنتج قائمة (array(. لا تتضمن الاقتباسات (واحدة أو مزدوجة) في الإخراج. # --hints-- -يجب أن تعيد وظيفتك قيمة للعدد والنص (`Bet` أو `Hold`) مع حرف فارغ واحد بينهما. +يجب أن تنتج وظيفتك قيمة العدد والنص (`Bet` أو `Hold`) مع حرف فارغ واحد بينهما. ```js assert(// @@ -38,7 +38,7 @@ assert(// ); ``` -يجب أن ينتج تسلسل الورق 2، 3، 4، 5، 6 المقطع `5 Bet` +إن أعطيَ الورق 2، 3، 4، 5، 6 بالتسلسل، يجب أن تنتج المقطع `5 Bet` ```js assert( @@ -57,7 +57,7 @@ assert( ); ``` -يجب أن ينتج تسلسل الورق 7، 8، 9 المقطع `0 Hold` +إن أعطيَ الورق 7, 8, 9 بالتسلسل، يجب أن تنتج المقطع `0 Hold` ```js assert( @@ -74,7 +74,7 @@ assert( ); ``` -يجب أن ينتج تسلسل الورق 10, J, Q, K, A المقطع `-5 Hold` +إن أعطيَ الورق 10, J, Q, K, A بالتسلسل، يجب أن تنتج المقطع `-5 Hold` ```js assert( @@ -93,7 +93,7 @@ assert( ); ``` -يجب أن ينتج تسلسل الورق 3, 7, Q, 8, A المقطع `-1 Hold` +إن أعطيَ الورق 3, 7, Q, 8, A بالتسلسل، يجب أن تنتج المقطع `-1 Hold` ```js assert( @@ -112,7 +112,7 @@ assert( ); ``` -يجب أن ينتج تسلسل الورق 2, J, 9, 2, 7 المقطع `1 Bet` +إن أعطيَ الورق 2, J, 9, 2, 7 بالتسلسل، يجب أن تنتج المقطع `1 Bet` ```js assert( @@ -131,7 +131,7 @@ assert( ); ``` -يجب أن ينتج تسلسل الورق 2، 2، 10 المقطع `1 Bet` +إن أعطيَ الورق 2، 2، 10 بالتسلسل، يجب أن تنتج المقطع `1 Bet` ```js assert( @@ -148,7 +148,7 @@ assert( ); ``` -يجب أن ينتج تسلسل الورق 3, 2, A, 10, K المقطع `-1 Hold` +إن أعطيَ الورق 3, 2, A, 10, K بالتسلسل، يجب أن تنتج المقطع `-1 Hold` ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/create-decimal-numbers-with-javascript.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/create-decimal-numbers-with-javascript.md index aa074aa8881e4d..20160798630d9c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/create-decimal-numbers-with-javascript.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/create-decimal-numbers-with-javascript.md @@ -11,11 +11,11 @@ dashedName: create-decimal-numbers-with-javascript يمكننا تخزين أرقام عشرية في المتغيرات أيضا. يشار أحياناً إلى الأرقام العشرية على أنها أرقام نُقَط عائمة (floating point) أو عائمات (floats). -**ملاحظة:** عندما حساب الأرقام، يتم حسابها بدقة محدودة. وقد تؤدي العمليات التي تستخدم نُقَط عائمة إلى نتائج مختلفة عن النتائج المرجوة. إذا حصلت على واحدة من هذه النتائج، أفتح موضوع في منتدى freeCodeCamp. +**ملاحظة:** عندما تحسب الأرقام، يتم حسابها بدقة محدودة. وقد تؤدي العمليات التي تستخدم نُقَط عائمة إلى نتائج مختلفة عن النتائج المرغوبة. إذا حصلت على واحدة من هذه النتائج، أفتح موضوع في منتدى freeCodeCamp. # --instructions-- -أنشئ متغير `myDecimal` وإعطائه قيمة عشرية بجزء كسري (على سبيل المثال `5.7`). +أنشئ متغير `myDecimal` واعطه قيمة عشرية بجزء كسري (على سبيل المثال `5.7`). # --hints-- @@ -25,7 +25,7 @@ dashedName: create-decimal-numbers-with-javascript assert(typeof myDecimal === 'number'); ``` -يجب أن يحتوي `myDecimal` على نقطة عشرية +يجب أن يحتوي `myDecimal` على نقطة عشرية (decimal point) ```js assert(myDecimal % 1 != 0); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-a-read-only-variable-with-the-const-keyword.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-a-read-only-variable-with-the-const-keyword.md index 8793f815ee9cad..9e06a459cbbbe5 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-a-read-only-variable-with-the-const-keyword.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-a-read-only-variable-with-the-const-keyword.md @@ -1,6 +1,6 @@ --- id: 587d7b87367417b2b2512b41 -title: تعريف متغير للقراءة ثابت باستخدام كلمة Const +title: إعلان متغير ثابت للقراءة فقط باستخدام مصطلح const challengeType: 1 forumTopicId: 301201 dashedName: declare-a-read-only-variable-with-the-const-keyword @@ -8,24 +8,24 @@ dashedName: declare-a-read-only-variable-with-the-const-keyword # --description-- -لا يكون أستخدام كلمة `let` الطريقة الجديدة الوحيدة لتعريف المتغيرات. في ES6، يمكنك أيضا تعريف المتغيرات باستخدام كلمة `const`. +لا يكون أستخدام مصطلح `let` الطريقة الجديدة الوحيدة لإعلان المتغيرات. في ES6، يمكنك أيضا إعلان المتغيرات باستخدام كلمة `const`. -تحتوي `const` كل الميزات الرائعة الموجودة في `let`، مع المكافأة المضافة و هي أن المتغيرات المعرفة بواسطة `const` ثابته. هي قيمة ثابتة، مما يعني أنه بمجرد تعيين متغير باستخدام `const`، فلا يمكن إعادة تعيينه: +تحتوي `const` كل الميزات الرائعة الموجودة في `let`، مع المكافأة الإضافية و هي أن المتغيرات المعلنة بواسطة `const` تستعمل للقراءة فقط. وإنهم قيم ثابتة، مما يعني أنه بمجرد إعلان المتغير باستخدام `const`، فلا يمكن إعادة تعيينه: ```js const FAV_PET = "Cats"; FAV_PET = "Dogs"; ``` -سيتم عرض خطأ في وحدة التحكم بسبب إعادة تعيين قيمة `FAV_PET`. +ستعرض وحدة التحكم خطأ بسبب إعادة تعيين قيمة `FAV_PET`. -يجب عليك دائماً تسمية المتغيرات التي لا ترد إعادة تعيينها باستخدام كلمة `const`. يساعد هذا عندما تحاول بالخطأ إعادة تعيين متغير من المفترض أن يظل ثابتًا. +يجب عليك دائماً إعلان المتغيرات التي لا تريد إعادة تعيينها باستخدام المصطلح `const`. يساعد هذا عندما تحاول بالخطأ إعادة تعيين متغير من المفترض أن يظل ثابتًا. -**ملاحظة:** من الشائع عند المطورين استخدام معرّفات uppercase للمتغيرات ذات القيم الثابتة و lowercase أو camelCase للقيم القابلة للتغيير (objects و arrays). سوف تتعلم المزيد عن الكائنات والقوائم و القيم الثابتة والقابلة للتغيير في تحديات لاحقة. أيضا في التحديات اللاحقة، سترى أمثلة لمعرِّفات المتغيرات uppercase أو lowercase أو camelCase. +**ملاحظة:** من الشائع عند المطورين استخدام معرّفات بأسلوب uppercase للمتغيرات ذات القيم الثابتة وأسلوب lowercase أو camelCase للقيم القابلة للتغيير ( مثل الكائنات (objects) والقوائم (arrays)). سوف تتعلم المزيد عن الكائنات, والقوائم, و القيم الثابتة, والقيم القابلة للتغيير في تحديات لاحقة. أيضا في التحديات اللاحقة، سترى أمثلة لمعرِّفات المتغيرات uppercase أو lowercase أو camelCase. # --instructions-- -غيّر التعليمات البرمجية بحيث يتم تعريف جميع المتغيرات باستخدام `let` أو `const`. استخدم `let` عندما ترغب بتغير المتغير، و استخدم `const` عندما ترغب ببقي المتغير ثابتاً. كذلك اعد تسمية المتغيرات المعرفة باستخدام `const` لتتوافق مع الممارسات الشائعة. لا تغيير المقاطع المعينة للمتغيرات. +غيّر الكود بحيث يعلن جميع المتغيرات باستعمال `let` أو `const`. استخدم `let` عندما ترغب بتغير المتغير، و استخدم `const` عندما ترغب ببقي المتغير ثابتاً. كذلك اعد تسمية المتغيرات المعلنة باستعمال `const` لتتوافق مع الممارسات الشائعة. لا تغيير المقاطع المعينة للمتغيرات. # --hints-- @@ -42,19 +42,19 @@ assert.match(code, /(FCC)/); assert.notMatch(code, /(fCC)/); ``` -يجب أن يكون متغير `FCC` ثابت تم تعريفه باستخدام `const`. +يجب أن يكون متغير `FCC` ثابت معلن بواسطة `const`. ```js assert.match(code, /const\s+FCC/); ``` -لا ينبغي تغيير المقطع المسندة في المتغير `FCC`. +لا ينبغي تغيير المقطع النصي في المتغير `FCC`. ```js assert.equal(FCC, 'freeCodeCamp'); ``` -يجب أن يتم تعريف `fact` باستخدام `let`. +يجب أن تعلن `fact` بواسطة `let`. ```js assert.match(code, /(let\s+fact)/g); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-javascript-variables.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-javascript-variables.md index 5827e6bece28b4..c72cab264755d0 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-javascript-variables.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-javascript-variables.md @@ -1,6 +1,6 @@ --- id: bd7123c9c443eddfaeb5bdef -title: إنشاء متغيرات في JavaScript +title: أعلان المتغيرات في JavaScript challengeType: 1 videoUrl: 'https://scrimba.com/c/cNanrHq' forumTopicId: 17556 @@ -9,21 +9,21 @@ dashedName: declare-javascript-variables # --description-- -في علوم الحاسب، تكون البيانات أي شيء ذو معني للحواسيب. يوفر JavaScript ثماني أنواع بيانات مختلفة و هي كالآتي `undefined`, و`null`, و`boolean`, و`string`, و`symbol`, و`bigint`, و`number`, و `object`. +في علم الحاسوب (computer science)، تكون البيانات أي شيء ذو معني للحاسوب. يوفر JavaScript ثماني أنواع بيانات مختلفة و هي كالآتي `undefined`, و`null`, و`boolean`, و`string`, و`symbol`, و`bigint`, و`number`, و `object`. -على سبيل المثال، تقوم الحاسوب بالتمييز بين الأرقام، مثل الرَّقَم `12` و `strings` مثل `"12"` و `"dog"` أو `"123 cats"`, وهي مجموعات من الرموز. يمكن للحواسيب عمليات رياضية على الأعداد، ولكن ليس على المقاطع النصية (strings). +على سبيل المثال، يقوم الحاسوب بالتمييز بين الأرقام، مثل الرَّقَم `12` و `strings` مثل `"12"` و `"dog"` أو `"123 cats"`, وهي مجموعات من الرموز. يمكن للحواسيب عمليات رياضية على الأعداد، ولكن ليس على المقاطع النصية (strings). -تسمح المتغيرات للحواسيب بتخزين البيانات ومعالجتها بطريقة ديناميكية. وهم يفعلون ذلك باستخدام "تسمية" للإشارة إلى البيانات بدلاً من استخدام البيانات نفسها. ويمكن تخزين أي نوع من أنواع البيانات الثمانية في متغير. +تسمح المتغيرات للحواسيب بتخزين البيانات ومعالجتها بطريقة ديناميكية. ويفعلوا ذلك باستخدام "المسمى" للإشارة إلى البيانات بدلاً من استخدام البيانات نفسها. ويمكن تخزين أي نوع من أنواع البيانات الثمانية في متغير. المتغيرات مشابهة للمتغيرات x و y التي تستخدمها في الرياضيات، مما يعني أنهم اسم بسيط لتمثيل البيانات التي نريد الرجوع إليها. وتختلف متغيرات الحاسوب عن المتغيرات الرياضية من حيث أنها تستطيع تخزين قيم مختلفة في أوقات مختلفة. -نحن نطلب من JavaScript إنشاء أو تعين متغير عن طريق وضع الكلمة `var` أمامه، مثل ذلك: +نطلب من JavaScript إنشاء أو أعلان متغير عن طريق وضع الكلمة `var` أمامه، مثل ذلك: ```js var ourName; ``` -هذا ينشئ متغير يسمى `ourName`. في JavaScript تنهي التعبيرات باستخدام الفاصلة المنقوطة (;). أسماء المتغيرات يمكن أن تتكون من أرقام وحروف و `$` أو `_`، ولكن قد لا تحتوي على مسافات أو تبدأ برقم. +هذا ينشئ متغير يسمى `ourName`. في JavaScript, تنهي التعبيرات باستخدام الفاصلة المنقوطة (;). يمكن أن تتكون أسماء المتغيرات من أرقام وحروف و `$` أو `_`، ولكن قد لا تحتوي على مسافات أو تبدأ برقم. # --instructions-- @@ -34,7 +34,7 @@ var ourName; # --hints-- -يجب أن تعرف `myName` باستخدام كلمة `var` و تنهي بالفاصلة المنقوطة (;) +يجب أن تعلن `myName` باستخدام كلمة `var` و تنهي بالفاصلة المنقوطة (;) ```js assert(/var\s+myName\s*;/.test(code)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-string-variables.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-string-variables.md index 7a9cc285755c9a..94856f2d23b932 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-string-variables.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/declare-string-variables.md @@ -1,6 +1,6 @@ --- id: bd7123c9c444eddfaeb5bdef -title: أنشاء متغيرات المقاطع نصية (Declare String Variables) +title: إعلان متغيرات المقاطع النصية challengeType: 1 videoUrl: 'https://scrimba.com/c/c2QvWU6' forumTopicId: 17557 @@ -9,27 +9,27 @@ dashedName: declare-string-variables # --description-- -في السابق كنت تستخدم الكود التالي لإنشاء متغير: +في السابق كنت تستخدم الكود التالي لإعلان متغير: ```js var myName; ``` -ولكن يمكنك أيضا أنشاء متغير المقطع بهذه الطريقة: +ولكن يمكنك أيضا إعلان متغير المقطع النصي (string) بهذه الطريقة: ```js var myName = "your name"; ``` -`"your name"` يسمي مقطع حرفي. المقطع النصي أو مقطع هي مقطع تتكون من رمز أو أكثر، مرفقين في علامات اقتباس (Quotes) مفردة أو مزدوجة. +يسمي`"your name"` المقطع موضوعي. يتكون المقطع الموضوعي أو المقطع النصي من رمز أو رموز، مرفقين في علامات اقتباس (quotes) مفردة أو مزدوجة. # --instructions-- -إنشاء متغيرين مقطعين جديدين: `myFirstName` و `myLastName` وعيين قيم الاسم الأول والاسم الأخير على التوالي. +إنشاء متغيرين مقطعين جديدين: وعين `myFirstName` و `myLastName` بقيم اسمك والاسم عائلتك على التوالي. # --hints-- -يجب أن يحتوي مقطع `myFirstName` على حرف واحد في الأقل. +يجب أن يحتوي مقطع `myFirstName` على رمز واحد في الأقل. ```js assert( @@ -47,7 +47,7 @@ assert( ); ``` -يجب أن يحتوي مقطع `myLastName` على حرف واحد في الأقل. +يجب أن يحتوي مقطع `myLastName` على رمز واحد في الأقل. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/decrement-a-number-with-javascript.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/decrement-a-number-with-javascript.md index ea0af524bf3530..b17352c479527b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/decrement-a-number-with-javascript.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/decrement-a-number-with-javascript.md @@ -21,7 +21,7 @@ i--; i = i - 1; ``` -**ملاحظة:** السطر بِرُمَّته يصبح `i--;`، وإلغاء الحاجة إلى علامة المساواة. +**ملاحظة:** السطر بكامله يصبح `i--;`، مما يزيل الحاجة إلى علامة المساواة. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/delete-properties-from-a-javascript-object.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/delete-properties-from-a-javascript-object.md index 5a8b2c45e642dc..1a4f25f7689587 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/delete-properties-from-a-javascript-object.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/delete-properties-from-a-javascript-object.md @@ -42,7 +42,7 @@ delete ourDog.bark; # --instructions-- -احذف خاصية `tails` من `myDog`. يمكنك استخدام النقطة (dot) أو القوسان المعكوفان (bracket notation). +احذف خاصية `tails` من `myDog`. يمكنك استخدام النقطة (dot) أو علامات الأقواس (bracket notation). # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md index 53a1021b42f42c..0d97aebbc562d2 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/escape-sequences-in-strings.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b6 -title: تسلسلات الهروب في المقاطع (Escape Sequences in Strings) +title: تسلسلات الإخراج في المقاطع النصية challengeType: 1 videoUrl: 'https://scrimba.com/c/cvmqRh6' forumTopicId: 17567 @@ -9,26 +9,25 @@ dashedName: escape-sequences-in-strings # --description-- -الاقتباسات (Quotes) ليست الرموز الوحيدة التي يمكن أن تكتب باحتياليه داخل المقطع (string). وهناك سببان لاستخدام رموز احتيالية (escaping characters): - -1. للسماح لك باستخدام الرموز التي قد لا تتمكن من استخدامها، مثل سطر جديد (newline). -2. للسماح لك بتمثيل الاقتباسات (Quotes) متعددة في مقطع دون أن يسيء JavaScript فهم ما تعنيه. - -وقد تعلمنا ذلك في التحدي السابق. +الاقتباسات (quotes) ليست الرموز الوحيدة التي يمكن أن تكتب مخرَّجة (escaped) داخل مقطع نصي (string). تتيح لك escape sequences استخدام الرموز التي لا تمكن استعمالها في مقطع ما بدونهم.
    الكودالناتج
    \'single quote
    \"double quote
    \\backslash
    \nnewline
    \ttab
    \rcarriage return
    \bword boundary
    \fform feed
    -*لاحظ أن يجب أن تكون الخط المائل (backslash) نفسه أحتيالي (escaped) ليتم عرضها كخط مائل backslash.* +*لاحظ أن يجب أن يكون الخط المائل (backslash) نفسه يخرَّج (escaped) ليتم عرضه كخط مائل backslash.* # --instructions-- -عيّن الأسطر الثلاثة التالية من النص في المتغير `myStr` الوحيد باستخدام تسلسل احتيالي (escape sequences). +عيّن المقاطع الثلاثة في السطور التالية في المتغير الوحيد `myStr` باستخدام تسلسلات التخريج (escape sequences). -
    FirstLine
        \SecondLine
    ThirdLine
    +
    +FirstLine
    +    \SecondLine
    +ThirdLine
    +
    -سوف تحتاج إلى استخدام تسلسل احتيالي لإدراج الرموز الخاصة (special characters) بشكل صحيح. ستحتاج أيضًا إلى اتباع التباعد كما هو موضح أعلاه، دون مسافات بين التسلسل الاحتيالي escape sequences أو الكلمات. +سوف تحتاج إلى استخدام تسلسلات التخريج لإدراج الرموز الخاصة (special characters) بشكل صحيح. ستحتاج أيضًا إلى اتباع التباعد كما هو موضح أعلاه، دون مسافات بين تسلسلات التخريج escape sequences أو الكلمات. -**ملاحظة:** يتم الحصول على التباعد (indentation) في `SecondLine` باستخدام رمز التحايل الشريط (tab escape character) وليس المسافة الفارغة (space). +**ملاحظة:** يتم الحصول على التباعد (indentation) في `SecondLine` باستخدام رمز التخريح الشريط (tab escape character) وليس المسافة الفارغة (space). # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/escaping-literal-quotes-in-strings.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/escaping-literal-quotes-in-strings.md index 0e7ff5dcda4ef8..1df4b35efcea17 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/escaping-literal-quotes-in-strings.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/escaping-literal-quotes-in-strings.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b5 -title: الاحتيال على علامات التنصيص في المقاطع النصية +title: إخراج (Escape) علامات التنصيص في المقاطع النصية challengeType: 1 videoUrl: 'https://scrimba.com/c/c2QvgSr' forumTopicId: 17568 @@ -9,15 +9,15 @@ dashedName: escaping-literal-quotes-in-strings # --description-- -عندما تحديد مقطع نصي يجب أن تبدأ وتنتهي علامتا التنصيص واحد ('') أو مزدوج (""). ماذا يحدث عندما تحتاج إلى استخدام علامتا التنصيص مثل: `"` أو `'` داخل مقطع نصي خاص بك؟ +عند تحديد مقطع نصي يجب أن تبدأ وتنتهي بعلامات التنصيص مفردة ('') أو مزدوجة (""). ماذا يحدث عندما تحتاج إلى استخدام علامتا التنصيص مثل: `"` أو `'` داخل مقطعك النصي؟ -في JavaScript، يمكنك عمل خدعة داخل علامتا التنصيص حتي لا تعدّ نهاية للعلامة الأولى في المقطع النصي عن طريق وضع خط مائل بشكل (`\`) أمام علامتا التنصيص. +في JavaScript، يمكنك إخراج علامتا التنصيص حتى لا تعدّ نهاية للمقطع النصي عن طريق وضع خط مائل للشمال بشكل (`\`) أمام علامة التنصيص. ```js const sampleStr = "Alan said, \"Peter is learning JavaScript\"."; ``` -هذا يوضح إلى JavaScript أن علامة التنصيص التالية ليس نهاية للمقطع، بل يجب أن تظهر داخل المقطع. لذا عند طبع هذا إلى وحدة التحكم ستحصل على: +هذا يوضح إلى JavaScript أن علامة التنصيص التالية ليست بنهاية للمقطع، بل يجب أن تظهر داخل المقطع. لذا عند طبع هذا إلى الكونسول (console) ستحصل على: ```js Alan said, "Peter is learning JavaScript". @@ -25,7 +25,7 @@ Alan said, "Peter is learning JavaScript". # --instructions-- -استخدم خطوط مائلة لتعيين مقطع إلى متغير `myStr` بحيث إذا كنت تريد طباعته إلى وحدة التحكم، ستري ما يلي: +استخدم شرطات مائلة للشمال لتعيين مقطع نصي إلى متغير `myStr` بحيث إذا كنت تريد طباعته إلى الكونسول، ستري ما يلي: ```js I am a "double quoted" string inside "double quotes". @@ -33,7 +33,7 @@ I am a "double quoted" string inside "double quotes". # --hints-- -يجب عليك استخدام علامة التنصيص المزدوجة (`"`) وتتحايل على العلامات أربع مرات مثل (`\"`). +يجب عليك استخدام علامة التنصيص المزدوجة (`"`) وتخرج العلامات أربع مرات مثل (`\"`). ```js assert(code.match(/\\"/g).length === 4 && code.match(/[^\\]"/g).length === 2); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/explore-differences-between-the-var-and-let-keywords.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/explore-differences-between-the-var-and-let-keywords.md index 7cfbc07cab4c70..459318b501ebdf 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/explore-differences-between-the-var-and-let-keywords.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/explore-differences-between-the-var-and-let-keywords.md @@ -1,6 +1,6 @@ --- id: 587d7b87367417b2b2512b3f -title: استكشاف الاختلافات بين كلمتين var و let +title: استكشاف الاختلافات بين المصطلحين var و let challengeType: 1 forumTopicId: 301202 dashedName: explore-differences-between-the-var-and-let-keywords @@ -8,7 +8,7 @@ dashedName: explore-differences-between-the-var-and-let-keywords # --description-- -واحدة من أكبر مشكلات إنشاء المتغيرات باستخدام كلمة `var` هي أنه يمكنك بسهولة تغيير تعريفات المتغيرات السابقة: +واحدة من أكبر المشكلات في إعلان المتغيرات بمصطلح `var` هي أنه يمكنك بسهولة استبدال قيم الإعلانات السابقة للمتغيرات: ```js var camper = "James"; @@ -16,11 +16,11 @@ var camper = "David"; console.log(camper); ``` -في الكود أعلاه، تم أنشاء متغير `camper` في الأصل بقيمة `James`، وتم تغيره بعد ذلك ليصبح `David`. ثم يعرض وحدة التحكم المقطع (string) الآتي `David`. +في الكود أعلاه، أعطى متغير `camper` قيمة `James` في الإعلان الأصلي، ثم تستبدل عند إعادة إعلانه ليصبح `David`. ولذلك يعرض وحدة التحكم (console) المقطع النصي (string) الآتي `David`. -في تطبيق صغير، قد لا تواجه هذا النوع من المشاكل. لكن كلما أصبح الكود الخاص بك أكبر، قد تغير المتغير عن طريق الخطأ الذي لم تكن تنوي تغييره. ولأذن هذا السلوك لا يوقع خطأ، يصبح البحث عن الأخطاء وإصلاحها أكثر صعوبة. +في تطبيق صغير، قد لا تواجه هذه المشكلة. لكن إذا أصبح مركزك للكود أكبر، قد تستبدل قيمة متغير دون وعي. ولأن هذا السلوك لا يوقع خطأ، يصبح البحث عن الأخطاء وإصلاحها أكثر صعوبة. -تم تقديم كلمة `let` في ES6، وهو تحديث رئيس JavaScript، لحل هذه المشكلة المحتملة باستخدام `var`. ستتعرف إلى ميزات ES6 الأخرى في التحديات اللاحقة. +قدم مصطلح `let` في ES6، وهو تحديث رئيسي للغة JavaScript، لحل هذه المشكلة المحتملة باستخدام مصطلح `var`. ستتعرف إلى ميزات ES6 الأخرى في التحديات اللاحقة. إذا استبدلت `var` إلى `let` في الكود أعلاه، فإنه يؤدي إلى خطأ: @@ -29,13 +29,13 @@ let camper = "James"; let camper = "David"; ``` -يمكن رؤية الخطأ في وحدة تحكم المتصفح الخاص بك. +يمكن رؤية الخطأ في وحدة التحكم (console) متصفحك. -لذلك على خلاف `var`، عندما تستخدم `let`، يمكن تعريف متغير بنفس الاسم مرة واحدة فقط. +لذلك على خلاف `var`، عندما تستعمل `let`، يمكن إعلان متغير بنفس الاسم مرة واحدة فقط. # --instructions-- -حديث الكود بحيث يستخدم فقط كلمة `let`. +حدّث الكود بحيث يستخدم فقط مصطلح `let`. # --hints-- @@ -45,13 +45,13 @@ let camper = "David"; assert.notMatch(code, /var/g); ``` -يجب أن تساوي `catName` المقطع (string) الآتي `Oliver`. +يجب أن تساوي `catName` المقطع النصي الآتي `Oliver`. ```js assert.equal(catName, 'Oliver'); ``` -يجب أن تساوي `catSound` المقطع (string) الآتي `Meow!` +يجب أن تساوي `catSound` المقطع النصي الآتي `Meow!` ```js assert.equal(catSound, 'Meow!'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/find-the-length-of-a-string.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/find-the-length-of-a-string.md index e91b7bc1c56990..1f5128d8db1516 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/find-the-length-of-a-string.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/find-the-length-of-a-string.md @@ -1,6 +1,6 @@ --- id: bd7123c9c448eddfaeb5bdef -title: العثور على طول مقطع نصي (Find the Length of a String) +title: العثور عن عدد الرموز أو الطول لمقطع نصي challengeType: 1 videoUrl: 'https://scrimba.com/c/cvmqEAd' forumTopicId: 18182 @@ -9,23 +9,23 @@ dashedName: find-the-length-of-a-string # --description-- -يمكنك العثور على قيمة طول `String` بكتابة `.length` بعد متغير المقطع (string) أو المقطع النصي (string literal). +يمكنك العثور على الطول أو عدد الرموز في `String` بكتابة `.length` بعد متغير المقطع النصي أو بعد مقطع حرفي (string literal). ```js console.log("Alan Peter".length); ``` -سوف يتم عرض القيمة `10` في وحدة التحكم. لاحظ أن رمز المسافة بين "Alan" و "Peter" يتم حسابه أيضا. +سوف يتم عرض القيمة `10` في الكونسول. لاحظ أن رمز المسافة بين "Alan" و "Peter" يتم عدُّه أيضا. -على سبيل المثال، إذا أنشئت متغير `const firstName = "Ada"`، يمكننا معرفة طول المقطع (string) الآتي `Ada` باستخدام `firstName.length`. +على سبيل المثال، إذا أنشئت متغير `const firstName = "Ada"`، يمكننا معرفة طول المقطع النصي الآتي `Ada` باستخدام `firstName.length`. # --instructions-- -استخدم خاصية `.length` لتعيين `lastNameLength` إلى عدد الأحرف في `lastName`. +استخدم خاصية `.length` لتعيين `lastNameLength` إلى عدد الرموز في `lastName`. # --hints-- -لا يجب عليك تغيير تعريفات المتغيرات في قسم `// Setup`. +لا يجب عليك تغيير إعلانات المتغيرات في قسم `// Setup`. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/finding-a-remainder-in-javascript.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/finding-a-remainder-in-javascript.md index f95f97cd5b56bb..d4b9449fd10043 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/finding-a-remainder-in-javascript.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/finding-a-remainder-in-javascript.md @@ -13,12 +13,20 @@ dashedName: finding-a-remainder-in-javascript **مثال** -
    5 % 2 = 1 لأن
    Math.floor(5 / 2) = 2 (الناتج)
    2 * 2 = 4
    5 - 4 = 1 (المتبقي)
    +
    +5 % 2 = 1
    +5 / 2 = 2 remainder 1
    +2 * 2 = 4
    +5 - 4 = 1
    +
    -**الاستخدام** -في الرياضيات، يمكن التحقق من أن الرَّقَم زوجي أو فردي عن طريق التحقق من بقية قسمة العدد على `2`. +**Usage** +In mathematics, a number can be checked to be even or odd by checking the remainder of the division of the number by `2`. Even numbers have a remainder of `0`, while odd numbers a remainder of `1`. -
    17 % 2 = 1 (17 فردي)
    48 % 2 = 0 (48 زوجي)
    +
    +17 % 2 = 1
    +48 % 2 = 0
    +
    **ملاحظة:** مشغل المتبقي يشار إليه أحياناً بشكل غير صحيح على أنه مشغل بالمائة (modulus operator). إنه شبيه جداً بالـمائه (modulus)، ولكنه لا يعمل بشكل صحيح مع الأعداد السالبة. @@ -28,7 +36,7 @@ dashedName: finding-a-remainder-in-javascript # --hints-- -يجب تهيئة المتغير `remainder` بمعني أخر يجب أن يكون initialized +يجب تهيئة المتغير `remainder`. بمعنى آخر، يجب أن يكون initialized ```js assert(/(const|let|var)\s+?remainder/.test(code)); @@ -51,7 +59,9 @@ assert(/\s+?remainder\s*?=\s*?.*%.*;?/.test(code)); ## --after-user-code-- ```js -(function(y){return 'remainder = '+y;})(remainder); +(function (y) { + return 'remainder = ' + y; +})(remainder); ``` ## --seed-contents-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/global-scope-and-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/global-scope-and-functions.md index aa077efae03f69..ac950cf101661b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/global-scope-and-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/global-scope-and-functions.md @@ -9,13 +9,13 @@ dashedName: global-scope-and-functions # --description-- -في JavaScript، يشير النطاق إلى رؤية المتغيرات. يكون إلى المتغيرات التي تم تعريفها خارج الوظيفة نطاق يسمي شامل. وهذا يعني أنه يمكن رؤيتها في كل مكان في التعليمات البرمجية JavaScript الخاص بك. +في JavaScript، يشير النطاق إلى ظهور المتغيرات. يكون إلى المتغيرات التي تم تعريفها خارج الوظيفة مجال شامل (Global scope). وهذا يعني أنه يمكن رؤيتها في كل مكان في التعليمات البرمجية JavaScript الخاص بك. -يتم تعريف المتغيرات دون استخدام الكلمات الآتية `let` أو `const` يتم إنشاؤها تلقائيًا في نطاق `global`. هذا يمكن أن يؤدي إلى عواقب غير مقصودة في مكان آخر من التعليمات البرمجية الخاص بك أو عند تشغيل الوظيفة مرة أخرى. يجب عليك دائماً تعريف المتغيرات الخاصة بك باستخدام `let` أو `const`. +تكون المتغيرات التي أعلنت دون إستخدام المصطلحات `let` أو `const` تنشئ تلقائيًا في مجال شامل `global`. و هذا يمكن أن يؤدي إلى عواقب غير مقصودة في مكان آخر من الكود الخاص بك أو عند تشغيل الوظيفة مرة أخرى. يجب عليك دائماً إعلان متغيراتك باستخدام `let` أو `const`. # --instructions-- -باستخدام `let` أو `const`، عرف متغير شامل يسمى `myGlobal` خارج الوظيفة ما. قم بتهيئته بقيمة `10`. +باستخدام `let` أو `const`، أعلن متغير شامل يسمى `myGlobal` خارج كل الوظائف. قم بتهيئته بقيمة `10`. داخل الوظيفة `fun1`، عيّّن `5` إلى `oopsGlobal` ولكن ***دون*** استخدام `var`, أو `let`, أو `const`. @@ -33,13 +33,13 @@ assert(typeof myGlobal != 'undefined'); assert(myGlobal === 10); ``` -يجب تعريف `myGlobal` باستخدام `let` أو `const` +يجب إعلان `myGlobal` باستعمال `let` أو `const` ```js assert(/(let|const)\s+myGlobal/.test(code)); ``` -يجب أن يكون متغير `oopsGlobal` شامل وأن يساوي `5` +يجب أن يكون `oopsGlobal` متغير شامل وأن يساوي `5` ```js assert(typeof oopsGlobal != 'undefined' && oopsGlobal === 5); @@ -88,7 +88,7 @@ uncapture(); function fun1() { - // Assign 5 to oopsGlobal Here + // Assign 5 to oopsGlobal here } diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/global-vs.-local-scope-in-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/global-vs.-local-scope-in-functions.md index efc9557e8b7389..939e2deb7920ed 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/global-vs.-local-scope-in-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/global-vs.-local-scope-in-functions.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244c0 -title: النطاق العام مقابل النطاق المحلي في الوظائف (Global vs. Local Scope in Functions) +title: المجال الشامل مقابل النطاق المحدد في الوظائف challengeType: 1 videoUrl: 'https://scrimba.com/c/c2QwKH2' forumTopicId: 18194 @@ -9,7 +9,7 @@ dashedName: global-vs--local-scope-in-functions # --description-- -من الممكن الحصول على متغيرات محالية (Local) و عامة (Global) بنفس الاسم. عندما تقوم ذلك، يكون المتغير المحالي (local) له الأسبقية على المتغير العام (global). +من الممكن الحصول على متغيرات محدودة (local) و شاملة (global) بنفس الاسم. عندما تفعل ذلك، يكون المتغير المحدود (local) له الأسبقية على المتغير الشامل (global). وفي هذا المثال: @@ -22,15 +22,15 @@ function myFun() { } ``` -سوف تنتج الوظيفة `myFun` السلسلة `Head` لأن النسخة المحالية (local) من المتغير موجودة. +سوف تنتج الوظيفة `myFun` المقطع النصي `Head` لأن النسخة المحدودة (local) من المتغير موجودة. # --instructions-- -أضف متغير محالي (local) إلى وظيفة `myOutfit` لتجاوز قيمة `outerWear` بالمقطع `sweater`. +أضف متغير محدود (local) إلى وظيفة `myOutfit` لتجاوز قيمة `outerWear` الحالية بالمقطع النصي التالي `sweater`. # --hints-- -لا يجب عليك تغيير قيمة العام (global) الآتي `outerWear`. +لا يجب عليك تغيير قيمة المتغير الشامل (global) الآتي `outerWear`. ```js assert(outerWear === 'T-Shirt'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/golf-code.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/golf-code.md index 53255c079726af..afed8331492ea3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/golf-code.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/golf-code.md @@ -11,75 +11,75 @@ dashedName: golf-code في لُعْبَة الجولف، كل ثقب لديه `par`، التي تصف متوسط عدد الضربات `strokes` المتوقعة من اللاعب من أجل أدخال الكرة في الثَّقب لإكمال اللعب. اعتمادًا على مدى بعد `strokes` من `par` سواء البعد كان فوق أو تحت، يوجد اسم مستعار مختلف لكل منهم. -سيتم تمرير `par` و `strokes` كوسائط (arguments) لوظائفك (function). أرجع المقطع الصحيح وفقًا لهذا الجدول الذي يسرد strokes حسب الأولوية؛ من الأعلى إلى الأسفل: +سيمرر `par` و `strokes` كمعطيات (arguments) لوظيفتك (function). أرجع المقطع الصحيح وفقًا لهذا الجدول الذي يسرد strokes حسب الأولوية؛ من الأعلى إلى الأسفل:
    StrokesReturn
    1"Hole-in-one!"
    <= par - 2"Eagle"
    par - 1"Birdie"
    par"Par"
    par + 1"Bogey"
    par + 2"Double Bogey"
    >= par + 3"Go Home!"
    -يكونان `par` و `strokes` دائما من نوع رَقْم أيحابى. لقد أضفنا القائمة من جميع الأسماء لمساعدتك. +يكونان `par` و `strokes` دائما من نوع رَقم إيجابي. لقد أضفنا القائمة من جميع الأسماء لمساعدتك. # --hints-- -يجب أن ينتج `golfScore(4, 1)` المقطع `Hole-in-one!` +يجب أن ينتج `golfScore(4, 1)` المقطع النصي `Hole-in-one!` ```js assert(golfScore(4, 1) === 'Hole-in-one!'); ``` -يجب أن ينتج `golfScore(4, 2)` المقطع `Eagle` +يجب أن ينتج `golfScore(4, 2)` المقطع النصي `Eagle` ```js assert(golfScore(4, 2) === 'Eagle'); ``` -يجب أن ينتج `golfScore(5, 2)` المقطع `Eagle` +يجب أن ينتج `golfScore(5, 2)` المقطع النصي `Eagle` ```js assert(golfScore(5, 2) === 'Eagle'); ``` -يجب أن ينشئ `golfScore(4, 3)` المقطع `Birdie` +يجب أن ينتج `golfScore(4, 3)` المقطع النصي `Birdie` ```js assert(golfScore(4, 3) === 'Birdie'); ``` -يجب أن ينشئ `golfScore(4, 4)` المقطع `Par` +يجب أن ينتج `golfScore(4, 4)` المقطع النصي `Par` ```js assert(golfScore(4, 4) === 'Par'); ``` -يجب أن ينشئ `golfScore(1, 1)` المقطع `Hole-in-one!` +يجب أن ينتج `golfScore(1, 1)` المقطع النصي `Hole-in-one!` ```js assert(golfScore(1, 1) === 'Hole-in-one!'); ``` -يجب أن ينشئ `golfScore(5, 5)` المقطع `Par` +يجب أن ينتج `golfScore(5, 5)` المقطع النصي `Par` ```js assert(golfScore(5, 5) === 'Par'); ``` -يجب أن ينشئ `golfScore(4, 5)` المقطع `Bogey` +يجب أن ينتج `golfScore(4, 5)` المقطع النصي `Bogey` ```js assert(golfScore(4, 5) === 'Bogey'); ``` -يجب أن ينشئ `golfScore(4, 6)` المقطع `Double Bogey` +يجب أن ينتج `golfScore(4, 6)` المقطع النصي`Double Bogey` ```js assert(golfScore(4, 6) === 'Double Bogey'); ``` -يجب أن ينشئ `golfScore(4, 7)` المقطع `Go Home!` +يجب أن ينتج `golfScore(4, 7)` المقطع النصي`Go Home!` ```js assert(golfScore(4, 7) === 'Go Home!'); ``` -يجب أن ينشئ `golfScore(5, 9)` المقطع `Go Home!` +يجب أن ينتج `golfScore(5, 9)` المقطع النصي`Go Home!` ```js assert(golfScore(5, 9) === 'Go Home!'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/increment-a-number-with-javascript.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/increment-a-number-with-javascript.md index 58c323c61a52e8..d5cea9e9c23056 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/increment-a-number-with-javascript.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/increment-a-number-with-javascript.md @@ -9,7 +9,7 @@ dashedName: increment-a-number-with-javascript # --description-- -يمكنك بسهولة زيادة أو إضافة واحد إلى متغير مع مشغل `+ +`. +يمكنك بسهولة زيادة أو إضافة واحد إلى متغير مع مشغل `++`. ```js i++; @@ -21,7 +21,7 @@ i++; i = i + 1; ``` -**ملاحظة:** السطر بِرُمَّته يصبح `i++;`، مما يزيل الحاجة إلى علامة يساوي (equal sign). +**ملاحظة:** السطر بالأكمل يصبح `i++;`، مما يزيل الحاجة إلى علامة المساواة (equal sign). # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator.md index a6fc9d7dc047ee..6a1b80fc4f9a21 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/initializing-variables-with-the-assignment-operator.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244a9 -title: تهيئة المتغيرات باستخدام مشغل التعيين (Initializing Variables with the Assignment Operator) +title: تهيئة المتغيرات باستخدام مشغل التعيين challengeType: 1 videoUrl: 'https://scrimba.com/c/cWJ4Bfb' forumTopicId: 301171 @@ -9,7 +9,7 @@ dashedName: initializing-variables-with-the-assignment-operator # --description-- -من الشائع تعيين للمتغير قيمة أولية في نفس السطر المعلن عنه. +من الشائع تهيئة قيمة أولية للمتغير في نفس السطر المعلن عنه. ```js var myVar = 0; @@ -19,7 +19,7 @@ var myVar = 0; # --instructions-- -عرّف متغير `a` باستخدام `var` و عيّن له قيمة `9`. +أعلن متغير `a` باستخدام `var` و هيئ له قيمة `9`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/introducing-else-if-statements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/introducing-else-if-statements.md index b9e62828b9d3d0..17a806de84da1f 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/introducing-else-if-statements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/introducing-else-if-statements.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244db -title: مقدمة ألى تعبيرات Else/If +title: مقدمة إلى تعبيرات Else/If challengeType: 1 videoUrl: 'https://scrimba.com/c/caeJ2hm' forumTopicId: 18206 @@ -9,7 +9,7 @@ dashedName: introducing-else-if-statements # --description-- -إذا كان لديك شروط متعددة تحتاج التعامل معها، يمكنك استخدام `if` بالإضافة مع `else if`. +إذا كان لديك شروط متعددة تحتاج التعامل معها، يمكنك استخدام `if` بالإضافة مع `else if` في تسلسل. ```js if (num > 15) { @@ -39,7 +39,7 @@ assert(code.match(/else/g).length > 1); assert(code.match(/if/g).length > 1); ``` -يجب أن يكون لديك قوسين منحين (curly braces) لكل `if else` لكتابه الكود بداخلها. +يجب أن يكون لديك قوسين مقرونتين (curly braces) لكل `if else` لكتابه الكود بداخلها. ```js assert( @@ -49,31 +49,31 @@ assert( ); ``` -يجب أن تنتج `testElseIf(0)` المقطع `Smaller than 5` +يجب أن تنتج `testElseIf(0)` المقطع النصي `Smaller than 5` ```js assert(testElseIf(0) === 'Smaller than 5'); ``` -يجب أن تنتج `testElseIf(5)` مقطع `Between 5 and 10` +يجب أن تنتج `testElseIf(5)` المقطع النصي `Between 5 and 10` ```js assert(testElseIf(5) === 'Between 5 and 10'); ``` -يجب أن تنتج `testElseIf(7)` مقطع `Between 5 and 10` +يجب أن تنتج `testElseIf(7)` المقطع النصي `Between 5 and 10` ```js assert(testElseIf(7) === 'Between 5 and 10'); ``` -يجب أن تنتج `testElseIf(10)` مقطع `Between 5 and 10` +يجب أن تنتج `testElseIf(10)` المقطع النصي `Between 5 and 10` ```js assert(testElseIf(10) === 'Between 5 and 10'); ``` -يجب أن تنتج `testElseIf(12)` مقطع `Greater than 10` +يجب أن تنتج `testElseIf(12)` المقطع النصي `Greater than 10` ```js assert(testElseIf(12) === 'Greater than 10'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/introducing-else-statements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/introducing-else-statements.md index 476ae2c66ef24c..a3aed65e18a77e 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/introducing-else-statements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/introducing-else-statements.md @@ -9,7 +9,7 @@ dashedName: introducing-else-statements # --description-- -عندما يكون شرط العبارة `if` صحيحًا، يتم تنفيذ كتلة التعليمات البرمجية التي تليها. ماذا عن عندما يكون هذا الشرط خطأ؟ عادة لن يحدث شيء. باستخدام عبارة `else`، يمكن تنفيذ كتلة بديلة من التعليمات البرمجية. +عندما يكون شرط العبارة `if` صحيحًا، يتم تنفيذ كتلة التعليمات البرمجية التي تليها. ماذا عن عندما يكون هذا الشرط خطأ؟ عادة لن يحدث شيء. ولكن باستخدام عبارة `else`، يمكن تنفيذ مجموعة مختلفة من الكود. ```js if (num > 10) { @@ -37,25 +37,25 @@ assert(code.match(/if/g).length === 1); assert(/else/g.test(code)); ``` -يجب أن تنتج `testElse(4)` مقطع `5 or Smaller` +يجب أن تنتج `testElse(4)` المقطع النصي `5 or Smaller` ```js assert(testElse(4) === '5 or Smaller'); ``` -يجب أن تنتج `testElse(5)` مقطع `5 or Smaller` +يجب أن تنتج `testElse(5)` المقطع النصي `5 or Smaller` ```js assert(testElse(5) === '5 or Smaller'); ``` -يجب أن تنتج `testElse(6)` مقطع `Bigger than 5` +يجب أن تنتج `testElse(6)` المقطع النصي`Bigger than 5` ```js assert(testElse(6) === 'Bigger than 5'); ``` -يجب أن تنتج `testElse(10)` مقطع `Bigger than 5` +يجب أن تنتج `testElse(10)` المقطع النصي`Bigger than 5` ```js assert(testElse(10) === 'Bigger than 5'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop.md index 26f1a4db6485a1..052d3c437e756d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-through-an-array-with-a-for-loop.md @@ -19,7 +19,7 @@ for (let i = 0; i < arr.length; i++) { } ``` -تذكر أن القوائم (arrays) لديها ترتيب (index) قائم على الصفر، مما يعني أن ترتيب الأخير في القائمة (array) هو `length - 1`. يكون شرطك لهذه الحلقة (loop) هو `i < arr.length`، الذي يوقف الحلقة (loop) عندما `i` يساوي `length`. في هذه الحالة يكون آخر تكرار `i === 4`, بمعنى عندما تصبح `i` مساوي `arr.length - 1` وتنتج `6` ألى وحدة التحكم. ثم `i` يزيد إلى `5`، وتنتهي الحلقة (loop) لأن `i < arr.length` يكون `false`. +تذكر أن القوائم (arrays) لديها ترتيب (index) من الصفر، مما يعني أن ترتيب الأخير في القائمة (array) هو `length - 1`. يكون شرطك لهذه الحلقة (loop) هو `i < arr.length`، الذي يوقف الحلقة (loop) عندما `i` يساوي `length`. في هذه الحالة يكون آخر تكرار `i === 4`, بمعنى عندما تصبح `i` مساوي `arr.length - 1` وتنتج `6` ألى وحدة التحكم. ثم `i` يزيد إلى `5`، وتنتهي الحلقة (loop) لأن `i < arr.length` يكون `false`. # --instructions-- @@ -27,7 +27,7 @@ for (let i = 0; i < arr.length; i++) { # --hints-- -يجب تعريف وتهيئة `total` إلى 0. +يجب إعلان وتهيئة `total` بقيمة 0. ```js assert(code.match(/(var|let|const)\s*?total\s*=\s*0.*?;?/)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-with-javascript-for-loops.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-with-javascript-for-loops.md index bce01c3e9efa9f..6f9323f4a62de9 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-with-javascript-for-loops.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/iterate-with-javascript-for-loops.md @@ -15,9 +15,9 @@ dashedName: iterate-with-javascript-for-loops تعريف حلَقات For مع ثلاث عبارات اختيارية تفصل بينها الفاصلات المنقوطة (semicolons): -`for (a; b; c)`، حيث ان `a` هي عبارة التهيئة، `b` هي عبارة الشرط، و `c` هي العبارة النهائية. +`for (a; b; c)`، حيث ان `a` هي تعبير التهيئة، `b` هي تعبير الشرط، و `c` هي العبارة النهائية. -يتم تنفيذ عبارة التهيئة مرة واحدة فقط قبل بَدْء الحلقة. يستخدم عادة لتحديد وإعداد متغير الحلقة الخاص بك. +يتم تنفيذ عبارة التهيئة مرة واحدة فقط قبل بَدْء الحلقة. يستخدم عادة لإعلان وإعداد متغير الحلقة الخاص بك. يتم تقييم عبارة الشرط في بداية كل حلقة وسوف يستمر مادام أنه يقيّم إلى `true`. عندما يكون الشرط `false` في بداية الحلقة سوف تتوقف الحلقة عن التنفيذ. هذا يعني أن إذا بدأ الشرط كزائف (false)، لن تنفذ الحلقة (loop) الخاصة بك أبدا. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions.md index bf3b3880efddca..582c74d59bcbaf 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/local-scope-and-functions.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244bf -title: النطاق المحلي والوظائف (Local Scope and Functions) +title: النطاق المحدود والوظائف challengeType: 1 videoUrl: 'https://scrimba.com/c/cd62NhM' forumTopicId: 18227 @@ -9,9 +9,9 @@ dashedName: local-scope-and-functions # --description-- -المتغيرات التي يتم تعريفها داخل وظيفة، وكذلك الحجج الوظيفة لديها نطاق و يكون محلي. وهذا يعني أنها لا تبد مرئية إلا في إطار الوظيفة. +المتغيرات التي أعلنت داخل وظيفة (function)، وكذلك الوسائط (parameters) للوظيفة لديها مجال محدود (local). وهذا يعني أنها لا تكون ظاهرة (أو معروفة) إلا في نطاق الوظيفة. -هذه وظيفة `myTest` مع متغير محلي يسمى `loc`. +هذه وظيفة `myTest` مع متغير محدود يسمى `loc`. ```js function myTest() { @@ -23,17 +23,17 @@ myTest(); console.log(loc); ``` -استدعاء الوظيفة `myTest()` ستعرض المقطع `foo` في وحدة التحكم. سيؤدي سطر `console.log(loc)` (خارج وظيفة `myTest`) إلى ظهور خطأ، حيث إن `loc` لم يتم تعريفها خارج الوظيفة. +تفعيل وظيفة `myTest()` سيعرض مقطع `foo` في الكونسول. سيؤدي سطر `console.log(loc)` (خارج وظيفة `myTest`) إلى ظهور خطأ، حيث إن `loc` لم يتم تعريفها خارج الوظيفة. # --instructions-- -يحتوي المحرر على اثنين `console.log` لمساعدتك على رؤية ما يحدث. تحقق من وحدة التحكم خلال كتابة الكود لترى كيف يتغير. عرف متغير محلي اسمه `myVar` داخل `myLocalScope` وشغل الاختبارات. +يحتوي المحرر على سطرين `console.log` لمساعدتك على رؤية ما يحدث. تحقق على الكونسول خلال كتابة الكود لترى كيف يتغير. اعلن متغير محدود اسمه `myVar` داخل `myLocalScope` وشغِّل الاختبارات. -**ملاحظة:** وحدة التحكم ستظل تعرض `ReferenceError: myVar is not defined`، ولكن هذا لن يتسبب في فشل الاختبارات. +**ملاحظة:** الكونسول سيظل بعرض `ReferenceError: myVar is not defined`، ولكن هذا لن يتسبب في فشل الاختبارات. # --hints-- -لا ينبغي أن يحتوي الكود على متغير عام يدعي `myVar`. +لا ينبغي أن يحتوي الكود على متغير شامل يدعى `myVar`. ```js function declared() { @@ -43,7 +43,7 @@ function declared() { assert.throws(declared, ReferenceError); ``` -يجب عليك إضافة متغير محلي يدعي `myVar`. +يجب عليك إضافة متغير محدود يدعى `myVar`. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/logical-order-in-if-else-statements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/logical-order-in-if-else-statements.md index e95e04569e7696..c9ba2c6e16dfac 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/logical-order-in-if-else-statements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/logical-order-in-if-else-statements.md @@ -13,7 +13,7 @@ dashedName: logical-order-in-if-else-statements يتم تنفيذ الوظيفة (function) من الأعلى إلى الأسفل، لذا سترغب في توخي الحذر بشأن العبارة التي تأتي أولاً. -ولنأخذ هاتين الوظيفتين (functions) كمثال. +ولنأخذ هاتين الوظيفتين كمثال. إليك الأول: @@ -29,7 +29,7 @@ function foo(x) { } ``` -أما الثاني فيغير ترتيب العبارات فقط: +أما الثاني فقد غير ترتيب العبارات فقط: ```js function bar(x) { @@ -43,7 +43,7 @@ function bar(x) { } ``` -بينما تبدو هاتان الوظيفتان (functions) متطابقتان تقريباً، إذا مررنا رَقْم إلى كليهما نحصل على نواتج مختلفة. +بينما تبدو هاتان الوظيفتان متطابقتان تقريباً، إذا اعطينا رَقم إلى كليهما نحصل على نواتج مختلفة. ```js foo(0) diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-pop.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-pop.md index 96021be6e80efc..e4daa7c561567b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-pop.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-pop.md @@ -1,6 +1,6 @@ --- id: 56bbb991ad1ed5201cd392cc -title: تغيير القوائم (Arrays) باستخدام pop() +title: تغيير القوائم (Arrays) باستخدام طريقة pop challengeType: 1 videoUrl: 'https://scrimba.com/c/cRbVZAB' forumTopicId: 18236 @@ -9,9 +9,9 @@ dashedName: manipulate-arrays-with-pop # --description-- -طريقة أخرى لتغيير البيانات في قائمة (Array) هي باستخدام الوظيفة `.pop()`. +طريقة أخرى لتغيير البيانات في القائمة (array) هي استخدام الوظيفة `.pop()`. -تستخدم الوظيفة `.pop()` لإزالة قيمة من نهاية القائمة. يمكننا تخزين هذه القيمة المستخرجة عن طريق تعيينها إلى متغير. بعبارة أخرى، تزيل الوظيفة `.pop()` العنصر الأخير من قائمة وتنتج ذلك العنصر. +تستخدم الوظيفة `.pop()` لإزالة (أو قفز pop) قيمة من نهاية القائمة. يمكننا تخزين هذه القيمة المستخرجة عن طريق تعيينها إلى متغير. بعبارة أخرى، تزيل الوظيفة `.pop()` العنصر الأخير من قائمة وتنتج ذلك العنصر. أي نوع من البيانات يمكن أن تستخرج من القائمة - الأرقام، المقاطع، حتى القوائم المتداخلة. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-push.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-push.md index e23d53c49e72d0..7ff03fec4cb2f3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-push.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-push.md @@ -1,6 +1,6 @@ --- id: 56bbb991ad1ed5201cd392cb -title: تغيير القوائم (Arrays) باستخدام push() +title: تغيير القوائم باستخدام طريقة push challengeType: 1 videoUrl: 'https://scrimba.com/c/cnqmVtJ' forumTopicId: 18237 @@ -9,9 +9,9 @@ dashedName: manipulate-arrays-with-push # --description-- -طريقة سهلة لإضافة البيانات إلى نهاية القائمة هي عن طريق وظيفة `push()`. +يوجد طريقة سهلة لإضافة البيانات إلى نهاية القائمة و هي عن طريق وظيفة `push()`. -يأخذ `.push()` واحد أو أكثر من الحجج و "يدفعها" إلى نهاية القائمة. +تأخذ `.push()` واحد أو أكثر من الوسائط و "تدفعها" إلى نهاية القائمة. على سبيل المثال: @@ -23,11 +23,11 @@ const arr2 = ["Stimpson", "J", "cat"]; arr2.push(["happy", "joy"]); ``` -لدي `arr1` قيمة `[1, 2, 3, 4]` الآن ولدي `arr2` قيمة `["Stimpson", "J", "cat", ["happy", "joy"]]`. +ألأن `arr1` لديه قيمة `[1, 2, 3, 4]` ولدي `arr2` قيمة `["Stimpson", "J", "cat", ["happy", "joy"]]`. # --instructions-- -اضف `["dog", 3]` إلي نهاية المتغير `myArray`. +ضف `["dog", 3]` إلي نهاية المتغير `myArray`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-shift.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-shift.md index 60cf7a9381a5fe..a328777af4df48 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-shift.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-shift.md @@ -1,6 +1,6 @@ --- id: 56bbb991ad1ed5201cd392cd -title: تغيير القوائم (Arrays) باستخدام shift() +title: تغيير القوائم باستخدام طريقة shift challengeType: 1 videoUrl: 'https://scrimba.com/c/cRbVETW' forumTopicId: 18238 @@ -9,9 +9,9 @@ dashedName: manipulate-arrays-with-shift # --description-- -يزيل `pop()` العنصر الأخير من القائمة دائما. ماذا لو كنت تريد إزالة الأول؟ +يزيل `pop()` العنصر الأخير من القائمة دائما. ولكن ماذا لو كنت تريد إزالة الأول؟ -هنا يأتي دور `.shift()`. يعمل تماما مثل `.pop()`، ولكنه يزيل العنصر الأول بدلا من العنصر الأخير. +هنا يأتي دور `.shift()`. يعمل تماما مثل `.pop()`، ولكنه يزيل (أو يزيح - shift) العنصر الأول بدلا من العنصر الأخير. مثال: @@ -20,11 +20,11 @@ const ourArray = ["Stimpson", "J", ["cat"]]; const removedFromOurArray = ourArray.shift(); ``` -سيحتوي `removedFromOurArray` قيمة المقطع `Stimpson`، وسيحتوي `ourArray` على `["J", ["cat"]]`. +ستحتوي `removedFromOurArray` قيمة المقطع `Stimpson`، وستحتوي `ourArray` على `["J", ["cat"]]`. # --instructions-- -استخدم الوظيفة `.shift()` لإزالة العنصر الأول من `myArray` وعيّن القيمة التي "تم نقلها" إلى متغير جديد `removedFromMyArray`. +استخدم الوظيفة `.shift()` لإزالة العنصر الأول من `myArray` وعيّن القيمة التي "أزيحت للخارج" إلى متغير جديد `removedFromMyArray`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-unshift.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-unshift.md index 2a4c9aaa4fb084..ff977abb896385 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-unshift.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/manipulate-arrays-with-unshift.md @@ -1,6 +1,6 @@ --- id: 56bbb991ad1ed5201cd392ce -title: تغيير القوائم (Arrays) باستخدام unshift() +title: تغيير القوائم باستخدام طريقة unshift challengeType: 1 videoUrl: 'https://scrimba.com/c/ckNDESv' forumTopicId: 18239 @@ -9,7 +9,7 @@ dashedName: manipulate-arrays-with-unshift # --description-- -ليس من ممكن استخدام `shift` في عناصر من بداية القائمة فقط، ولكن يمكنك استخدام `unshift` في عناصر في بداية القائمة أيضًا، أي يمكن أن تضيف عناصر ألى بداية القائمة. +ليس فقط تسطيع أن تستخدم `shift` لتزيح العناصر من بداية قائمة إلى خارجها، ولكن أيضاً يمكنك استخدام `unshift` لتزيح عناصر إلى بداية القائمة أيضًا، أي يمكنك أن تضيف عناصر في بداية القائمة. يعمل `.unshift()` تماما مثل `.push()`، ولكن بدلا من إضافة العنصر في نهاية القائمة، يضيف `unshift()` العنصر إلى بداية القائمة. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/modify-array-data-with-indexes.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/modify-array-data-with-indexes.md index dfa6cf54e9b3fb..1a08e71c6faf6a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/modify-array-data-with-indexes.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/modify-array-data-with-indexes.md @@ -1,6 +1,6 @@ --- id: cf1111c1c11feddfaeb8bdef -title: تعديل بيانات القوائم بالترتيب (Modify Array Data With Indexes) +title: تعديل بيانات القوائم برقم الترتيب challengeType: 1 videoUrl: 'https://scrimba.com/c/czQM4A8' forumTopicId: 18241 @@ -9,7 +9,7 @@ dashedName: modify-array-data-with-indexes # --description-- -على عكس المقاطع، عناصر القائمة هي قابلة للتغيير ويمكن تغييرها بحرية، حتى لو تم تعريف القائمة بواسطة `const`. +على عكس المقاطع النصية، عناصر القائمة هي قابلة للتغيير (mutable) ويمكن تغييرها بحرية، حتى لو تم تعريف القائمة بواسطة `const`. **مثال** @@ -24,7 +24,7 @@ ourArray[0] = 15; # --instructions-- -عدل البيانات المخزنة في الترتيب `0` من `myArray` إلى قيمة `45`. +عدل البيانات المخزنة في موقع الترتيب رَقَم `0` من `myArray` إلى قيمة `45`. # --hints-- @@ -47,7 +47,7 @@ assert( ); ``` -يجب عليك استخدام الترتيب الصحيح لتعديل القيمة في `myArray`. +يجب عليك استخدام رقم الترتيب الصحيح لتعديل القيمة في `myArray`. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiple-identical-options-in-switch-statements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiple-identical-options-in-switch-statements.md index 2d4e56080b126c..206ad63798b459 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiple-identical-options-in-switch-statements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiple-identical-options-in-switch-statements.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244df -title: خيرات عدّة متشابهة في تعبيرات Switch +title: عدّة خيرات متشابهة في تعبيرات switch challengeType: 1 videoUrl: 'https://scrimba.com/c/cdBKWCV' forumTopicId: 18242 @@ -9,7 +9,7 @@ dashedName: multiple-identical-options-in-switch-statements # --description-- -إذا تم حذف عبارات `break` من عبارات `switch` لكل `case`، سيتم تنفيذ عبارات `case` التالية حتى تقابلهم عبارة `break`. إذا كان لديك مدخلات متعددة بنفس المخرج، يمكنك تمثيلها في عبارة `switch`, أليك مثال: +إذا تم حذف عبارة `break` من عبارة `switch` في أي `case`، سيتم تنفيذ عبارات `case` التالية حتى مقابلة عبارة `break`. إذا كان لديك مدخلات متعددة بنفس المخرج، يمكنك تمثيلها في عبارة `switch`, أليك مثال: ```js let result = ""; @@ -97,7 +97,7 @@ assert(sequentialSizes(9) === 'High'); assert(!/else/g.test(code) || !/if/g.test(code)); ``` -يجب أن يكون لديك تسع `case` +يجب أن يكون لديك تسع عبارات `case` ```js assert(code.match(/case/g).length === 9); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiply-two-decimals-with-javascript.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiply-two-decimals-with-javascript.md index a79323144c7895..3ae00f4a9c98be 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiply-two-decimals-with-javascript.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiply-two-decimals-with-javascript.md @@ -11,7 +11,7 @@ dashedName: multiply-two-decimals-with-javascript في JavaScript، يمكنك أيضًا إجراء حسابات بأرقام عشرية، تماما مثل الأرقام صحيحة. -لنضرب عددين عشريين معًا لنحصل على حاصل ضربهما. +دعونا نضرب عددين عشريين معًا لنحصل على حاصل ضربهما. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiply-two-numbers-with-javascript.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiply-two-numbers-with-javascript.md index 01b5aea176ea59..56eca97df15202 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiply-two-numbers-with-javascript.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/multiply-two-numbers-with-javascript.md @@ -23,7 +23,7 @@ const myVar = 13 * 13; # --instructions-- -غيّر `0` بحيث يساوي الناتج `80`. +غيّر `0` بحيث يساوي الناتج (product) `80`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/nest-one-array-within-another-array.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/nest-one-array-within-another-array.md index f023c235b75ba8..c02a0a3f5c301d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/nest-one-array-within-another-array.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/nest-one-array-within-another-array.md @@ -1,6 +1,6 @@ --- id: cf1111c1c11feddfaeb7bdef -title: أدخال قائمة في قائمة اخري +title: إدخال قائمة في قائمة اخرى challengeType: 1 videoUrl: 'https://scrimba.com/c/crZQZf8' forumTopicId: 18247 @@ -9,21 +9,21 @@ dashedName: nest-one-array-within-another-array # --description-- -يمكنك أيضًا ادخال قوائم داخل القوائم الأخرى، مثل أدناه: +يمكنك أيضًا إدخال قوائم داخل قوائم أخرى، مثل أدناه: ```js const teams = [["Bulls", 23], ["White Sox", 45]]; ``` -هذا يسمى أيضا قوائم متعددة الأبعاد. +هذا يسمى أيضا قوائم متعددة الأبعاد (multi-dimensional array). # --instructions-- -أنشئ قوائم متداخلة تسمى `myArray`. +أنشئ قائمة متداخلة تسمى `myArray`. # --hints-- -يجب أن تحتوي `myArray` على الأقل علي قائمة واحدة متداخلة داخل قائمة أخرى. +يجب أن تحتوي `myArray` على الأقل علي قائمة واحدة متداخلة في قائمة أخرى. ```js assert(Array.isArray(myArray) && myArray.some(Array.isArray)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/passing-values-to-functions-with-arguments.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/passing-values-to-functions-with-arguments.md index a22959f3fae8ed..b8ff73b450e52a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/passing-values-to-functions-with-arguments.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/passing-values-to-functions-with-arguments.md @@ -9,9 +9,9 @@ dashedName: passing-values-to-functions-with-arguments # --description-- -الحجج هي متغيرات تعمل كعناصر ناقلة للقيم الذي يجب أن تكون مدخلة للوظيفة عند استدعائها. عندما يتم تعريف الوظيفة، فإنها تُعرَّف عادة مع واحد أو أكثر من الحجج. القيم الفعلية التي تدخل (أو "تمرر") إلى وظيفة عند استدعائها هي معروفة باسم الحجج (arguments). +إن الوسائط (parameters) متغيرات تعمل كعناصر ناقلة للقيم الذي تعطى لوظيفة (function) عند تفعيلها. عندما يتم تعريف وظيفة، فإنها تُعرَّف عادة مع واحد أو أكثر من الوسائط. القيم الفعلية التي تدخل (أو "تمرر") إلى وظيفة عند استدعائها هي معروفة باسم المعطيات (arguments). -إليك وظيفة ذات حجتين، `param1` و `param2`: +إليك وظيفة ذات وسيطين، `param1` و `param2`: ```js function testFun(param1, param2) { @@ -19,11 +19,11 @@ function testFun(param1, param2) { } ``` -ثم يمكننا استدعاء `testFun` مثل: `testFun("Hello", "World");`. لقد تمريرنا حجج من نوع مقطع, `Hello` و `World`. داخل الحجة، `param1` سيتساوى مع المقطع `Hello` و `param2` سيتساوى مع المقطع `World`. لاحظ أنه يمكنك استدعاء `testFun` مرة أخرى مع حجج مختلفة والمعلمات سوف تأخذ قيمة الحجج الجديدة. +ثم يمكننا تفعيل `testFun` مثل: `testFun("Hello", "World");`. لقد مرَّرنا معطيين من نوع مقطع نصي، `Hello` و `World`. داخل الوظيفة، `param1` سيتساوى مع المقطع `Hello` و `param2` سيتساوى مع المقطع `World`. لاحظ أنه يمكنك تنفيذ `testFun` مرة أخرى مع معطيات (arguments) مختلفة ووسائط (parameters) لتأخذ قيمة المعطيات الجديدة. # --instructions-- -
    1. أنشاء وظيفة تسمى functionWithArgs تقبل حجج وتخرج المجموع الخاص بهم إلى وحدة التحكم.
    2. استدعي الوظيفة برقمين كحجتين.
    +
    1. أنشئ وظيفة تسمى functionWithArgs تقبل معطييّن وتخرج المجموع الخاص بهم إلى الكونسول.
    2. استدعي الوظيفة برقمين كحجتين.
    # --hints-- @@ -55,7 +55,7 @@ if (typeof functionWithArgs === 'function') { assert(logOutput == 16); ``` -يجب عليك استدعاء `functionWithArgs` برقمين بعد تعريفه. +يجب عليك استدعاء `functionWithArgs` برقمين بعد تعريفها. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/practice-comparing-different-values.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/practice-comparing-different-values.md index 5df8a9bd80a50e..1dbeb107e21381 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/practice-comparing-different-values.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/practice-comparing-different-values.md @@ -1,6 +1,6 @@ --- id: 599a789b454f2bbd91a3ff4d -title: التدريب على مقارنة القيم المختلفة (Practice comparing different values) +title: التدريب على مقارنة القيم المختلفة challengeType: 1 videoUrl: 'https://scrimba.com/c/cm8PqCa' forumTopicId: 301174 @@ -9,15 +9,15 @@ dashedName: practice-comparing-different-values # --description-- -في التحديين الأخيرين، لقد تعلمنا عن مشغل المساواة (`==`) ومشغل المساواة الصارمة (`===`). راجع بسريعة وتتدرب باستخدام هؤلاء المشغلين. +في التحديين الأخيرين، لقد تعلمنا عن مشغل المساواة (`==`) ومشغل المساواة الصارمة (`===`). راجع سريعا وتدرب على استخدام هؤلاء المشغلين. -إذا لم تكن القيم الذي يجري مقارنتهم من نفس النوع، يقوم المشغل المعني بالمساواة بإجراء تحويل نوعي، ثم يقوم بتقييم القيم. ومع ذلك، فإن عامل المساواة الصارمة (strict equality operator) سيقارن بين نوع البيانات والقيمة كما هي، دون تحويل نوع إلى آخر. +إذا لم تكن القيم الذي تقارن من نفس النوع، سيقوم مشغل المساواة بإجراء تحويل نوعي (type conversion)، ثم يقوم بمقارنة القيم. ومع ذلك، إن مشغل المساواة الصارمة (strict equality operator) سيقارن بين نوع البيانات والقيمة كما هي، دون تحويل نوع إلى آخر. **على سبيل المثال** `3 == '3'` يرجع `true` لأن JavaScript تحويل المقطع إلى رَقْم. يرجع `3 === '3'` حالة `false` لأن الأنواع مختلفة ولا يتم إجراء تحويل. -**ملاحظة:** في JavaScript، يمكنك تحديد نوع متغير أو قيمة باستخدام مشغل `typeof` على النحو التالي: +**ملاحظة:** في JavaScript، يمكنك أن تكتشف نوع متغير أو قيمة باستخدام مشغل `typeof` على النحو التالي: ```js typeof 3 @@ -32,13 +32,13 @@ typeof '3' # --hints-- -يجب أن ينتج `compareEquality(10, "10")` مقطع `Not Equal` +يجب أن ينتج `compareEquality(10, "10")` مقطع نصي `Not Equal` ```js assert(compareEquality(10, '10') === 'Not Equal'); ``` -يجب أن ينتج `compareEquality("20", 20)` مقطع `Not Equal` +يجب أن ينتج `compareEquality("20", 20)` مقطع نصي `Not Equal` ```js assert(compareEquality('20', 20) === 'Not Equal'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes.md index fc86bbac9ec546..58e825469e9e5e 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/quoting-strings-with-single-quotes.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244b4 -title: اقتباس مقاطع بعلامات اقتباس منفردة (Quoting Strings with Single Quotes) +title: اقتباس المقاطع النصية بعلامات اقتباس منفردة challengeType: 1 videoUrl: 'https://scrimba.com/c/cbQmnhM' forumTopicId: 18260 @@ -9,14 +9,14 @@ dashedName: quoting-strings-with-single-quotes # --description-- -قيم مقطع في JavaScript يمكن كتابتها بعلامات اقتباس فردية أو مزدوجة، مادام تبدأ وتنتهي بنفس النوع من العلامات. وخلافا لبعض لغات البرمجة الأخرى، يفعل الاقتباس المنفرد والاقتباس المزدوج الشيء نفسه في JavaScript. +المقاطع النصية (string values) في JavaScript يمكن كتابتها بعلامات اقتباس فردية أو مزدوجة، ما زالت العلمات في البَدْء نفس النوع في النهاية. وخلافا لبعض لغات البرمجة الأخرى، علمات الاقتباس المنفردة والاقتباس المزدوجة يفعلان الشيء نفسه في JavaScript. ```js const doubleQuoteStr = "This is a string"; const singleQuoteStr = 'This is also a string'; ``` -السبب في رغبتك في استخدام نوع من الاقتباس فوق الآخر هو إذا كنت ترغب في استخدام كلا النوعين في المقطع. قد يحدث هذا إذا كنت ترغب في حفظ محادثة في المقطع ووضع المحادثة بين علامات الاقتباس. استخدام آخر له هو حفظ علامة `` مع سمات مختلفة في علامات الاقتباس، كل ذلك ضمن مقطع. +السبب في رغبتك في استخدام نوع اقتباس فوق النوع الآخر هو إذا رغبت في استخدام كلا النوعين في المقطع. قد يحدث هذا إذا رغبت في حفظ محادثة في مقطع نصي ووضع المحادثة بين علامات الاقتباس. استخدام آخر له هو حفظ علامة `` مع سمات مختلفة في علامات الاقتباس، كل ذلك ضمن مقطع نصي. ```js const conversation = 'Finn exclaims to Jake, "Algebraic!"'; @@ -29,17 +29,17 @@ const goodStr = 'Jake asks Finn, "Hey, let\'s go on an adventure?"'; const badStr = 'Finn responds, "Let's go!"'; ``` -هنا `badStr` سوف تسبب بخطأ. +هنا `badStr` سوف تسبب خطأ. -في goodStr أعلاه، يمكنك استخدام أي من علامات الاقتباس بأمان باستخدام الخط المائل (backslash) الآتية `\` كرمز متحايل (escape character). +في goodStr أعلاه، يمكنك استخدام أي من علامات الاقتباس بأمان باستخدام الخط المائل (backslash) الآتية `\` كرمز التخريج (escape character). -**ملاحظة:** يجب عدم الخلط بين الخط المائل (blackslash) الآتية `\` والخط المائل للأمام (forward slash) الآتية `/`. إنهم لا يفعلون الشيء نفسه. +**ملاحظة:** يجب عدم الخلط بين الخط المائل (blackslash) للشمال `\` والخط المائل (forward slash) لليمين `/`. إنهم لا يفعلون الشيء نفسه. # --instructions-- -غيّر المقطع المقدم إلى مقطع مع اقتباسات فردية في البداية والنهاية وبدون رموز متحايلة (escape characters). +غيّر المقطع النصي المقدم إلى مقطع مع اقتباسات فردية في البداية والنهاية وبدون رموز التخريج (escape characters). -الآن، العلامة `` في المقطع تستخدم اقتباسات مزدوجة في كل مكان. سوف تحتاج إلى تغيير الاقتباسات الخارجية إلى اقتباسات فردية حتى تتمكن من إزالة الرموز متحايلة (escape characters). +الآن، العلامة `` في المقطع تستخدم اقتباسات مزدوجة في كل مكان. سوف تحتاج إلى تغيير الاقتباسات الخارجية إلى اقتباسات فردية حتى تتمكن من إزالة رموز التخريج (escape characters). # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md index d305f50923e062..5c5aa16eb7cd83 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/record-collection.md @@ -8,9 +8,9 @@ dashedName: record-collection # --description-- -لديك object literal يمثل جزءا من مجموعة سجلات موسيقية الخاصة بك. يحتوي كل سجل على رقم معرف فريد يعدّ الهُوِيَّة والعديد من الخصائص الأخرى. ليست كل السجلات لديها معلومات كاملة. +لديك حروف الكائن التي تمثل جزء من مجموعة سجلاتك الموسيقية. يحتوي كل سجل على رقم معرف فريد يعدّ الهُوِيَّة والعديد من الخصائص الأخرى. ليست كل السجلات لديها معلومات كاملة. -أنت تبدأ بالوظيفة `updateRecords` التي تأخذ object literal يدعي `records`، يحتوي على مجموعة ألبومات موسيقية. و `id`, و `prop` (مثل `artist` أو `tracks`)، و `value`. أكمل الوظيفة باستخدام القواعد أدناه لتعديل الكائن الممرر إلى الوظيفة. +أنت تبدأ بالوظيفة `updateRecords` التي تأخذ الكائن حرفي يدعي `records`، يحتوي على مجموعة ألبومات موسيقية. و `id`, و `prop` (مثل `artist` أو `tracks`)، و `value`. أكمل الوظيفة باستخدام القواعد أدناه لتعديل الكائن الممرر إلى الوظيفة. - الوظيفة الخاص بك يجب أن يرجع دائما كائن مجموعة السجلات بِرُمَّته. - إذا كان `prop` ليس `tracks` و `value` ليس مقطع فارغ، حديث أو تعيين `prop` السجلات إلى `value`. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/replacing-if-else-chains-with-switch.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/replacing-if-else-chains-with-switch.md index 6b117f568ad7d5..217fd1f8388032 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/replacing-if-else-chains-with-switch.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/replacing-if-else-chains-with-switch.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244e0 -title: استبدال If Else Chains بـ Switch +title: استبدال عبارات if/else المتسلسلة بعبارة switch challengeType: 1 videoUrl: 'https://scrimba.com/c/c3JE8fy' forumTopicId: 18266 @@ -9,7 +9,7 @@ dashedName: replacing-if-else-chains-with-switch # --description-- -إذا كان لديك العديد من الخيارات للاختيار منها، `switch` يمكن أن يكون أسهل في الكتابة من الكثير من `if`/`else if`. ما يلي: +إذا كان لديك العديد من الخيارات التي يجب الاختيار بينها، عبارة `switch` قد تكون أسهل في الكتابة من سلسلة طويلة من عبارات `if`/`else if`. التالي: ```js if (val === 1) { @@ -60,43 +60,43 @@ assert(!/if/g.test(code)); assert(code.match(/break/g).length >= 4); ``` -`chainToSwitch("bob")` يجب أن تساوي الـ string الآتي `Marley` +`chainToSwitch("bob")` should return the string `Marley` ```js assert(chainToSwitch('bob') === 'Marley'); ``` -`chainToSwitch(42)` يجب أن تساوي الـ string الآتي `The Answer` +`chainToSwitch(42)` should return the string `The Answer` ```js assert(chainToSwitch(42) === 'The Answer'); ``` -`chainToSwitch(1)` يجب أن تساوي الـ string الآتي `There is no #1` +`chainToSwitch(1)` should return the string `There is no #1` ```js assert(chainToSwitch(1) === 'There is no #1'); ``` -`chainToSwitch(99)` يجب أن تساوي الـ string الآتي `Missed me by this much!` +`chainToSwitch(99)` should return the string `Missed me by this much!` ```js assert(chainToSwitch(99) === 'Missed me by this much!'); ``` -`chainToSwitch(7)` يجب أن تساوي الـ string الآتي `Ate Nine` +`chainToSwitch(7)` should return the string `Ate Nine` ```js assert(chainToSwitch(7) === 'Ate Nine'); ``` -`chainToSwitch("John")` يجب أن يكون `""` (string فارغ) +`chainToSwitch("John")` should return `""` (empty string) ```js assert(chainToSwitch('John') === ''); ``` -`chainToSwitch(156)` يجب أن يكون `""` (string فارغ) +`chainToSwitch(156)` should return `""` (empty string) ```js assert(chainToSwitch(156) === ''); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/return-a-value-from-a-function-with-return.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/return-a-value-from-a-function-with-return.md index 418da705952e17..21dae1b5bec562 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/return-a-value-from-a-function-with-return.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/return-a-value-from-a-function-with-return.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244c2 -title: إرجاع قيمة من وظيفة (Return a Value from a Function with Return) +title: إنتاج قيمة من وظيفة (Function) challengeType: 1 videoUrl: 'https://scrimba.com/c/cy87wue' forumTopicId: 18271 @@ -9,7 +9,7 @@ dashedName: return-a-value-from-a-function-with-return # --description-- -يمكننا نقل القيم إلى وظيفة باستخدام حجج. يمكنك استخدام `return` لإرسال قيمة إلى خارج الوظيفة. +يمكننا نقل القيم إلى وظيفة باستخدام معطيات (arguments). يمكنك استخدام تعبير `return` للحصول على قيمة من وظيفة (function). **مثال** @@ -21,13 +21,13 @@ function plusThree(num) { const answer = plusThree(5); ``` -لدي `answer` القيمة `8` الآن. +يحتوي `answer` على قيمة `8`. -يأخذ `plusThree` من الحجج ما يقابل `num` وينتج قيمة تساوي `num + 3`. +تأخذ `plusThree` قيمة من المعطى `num` وتنتج قيمة تساوي `num + 3`. # --instructions-- -أنشئ وظيفة `timesFive` التي تقبل حجة واحد، وتضربه في `5`، وترجع القيمة الجديدة. +أنشئ الوظيفة `timesFive` التي تقبل معطى واحد، وتضربه في `5`، وتنتج (returns) قيمة جديدة. # --hints-- @@ -37,19 +37,19 @@ const answer = plusThree(5); assert(typeof timesFive === 'function'); ``` -يجب أن ينتج `timesFive(5)` قيمة `25` +يجب أن تنتج `timesFive(5)` قيمة `25` ```js assert(timesFive(5) === 25); ``` -يجب أن ينتج `timesFive(2)` قيمة `10` +يجب أن تنتج `timesFive(2)` قيمة `10` ```js assert(timesFive(2) === 10); ``` -يجب أن ينتج `timesFive(0)` قيمة `0` +يجب أن تنتج `timesFive(0)` قيمة `0` ```js assert(timesFive(0) === 0); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/return-early-pattern-for-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/return-early-pattern-for-functions.md index 83f0157139c1ca..539f83d2e529e5 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/return-early-pattern-for-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/return-early-pattern-for-functions.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244c4 -title: نمط الإنشاء المبكر للوظائف (Return Early Pattern for Functions) +title: نمط return المبكر للوظائف challengeType: 1 videoUrl: 'https://scrimba.com/c/cQe39Sq' forumTopicId: 18272 @@ -9,7 +9,7 @@ dashedName: return-early-pattern-for-functions # --description-- -عندما يتم الوصول إلى `return`، يتوقف تنفيذ الوظيفة الحالي ويعود التحكم إلى مكان الاستدعاء. +عندما يتم الوصول إلى عبارة `return`، يتوقف تنفيذ الوظيفة الحالية ويعود التحكم إلى مكان الاستدعاء. **مثال** @@ -22,14 +22,14 @@ function myFun() { myFun(); ``` -سيتم عرض مقطع `Hello` في وحدة التحكم، وإنشاء مقطع `World`. لن يعرض مقطع `byebye` في وحدة التحكم أبدا، لأن الوظيفة تنتج عند `return`. +سيتم عرض مقطع `Hello` في وحدة التحكم، وإنشاء مقطع `World`. لن يعرض المقطع `byebye` في وحدة التحكم أبدا، لأن الوظيفة تنتهي عند عبارة `return`. # --instructions-- -عدّل الوظيفة `abTest` بحيث إذا كان `a` أو `b` أقل من `0` ستنتج الوظيفة قيمة `undefined` فوراً. +عدّل الوظيفة `abTest` بحيث إذا كان `a` أو `b` أقل من `0` ستنتهي الوظيفة مع إنتاج قيمة `undefined` فوراً. **تلميح** -تذكر أن تكون undefined كلمة وليست مقتطع. +تذكر أن undefined مصطلح وليست مقطع نصي. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/returning-boolean-values-from-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/returning-boolean-values-from-functions.md index ade4664fcdc16d..54bde0002200ae 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/returning-boolean-values-from-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/returning-boolean-values-from-functions.md @@ -1,6 +1,6 @@ --- id: 5679ceb97cbaa8c51670a16b -title: عودة القيم المنطقية من الوظيفة (Returning Boolean Values from Functions) +title: إنتاج القيم المنطقية من الوظائف challengeType: 1 videoUrl: 'https://scrimba.com/c/cp62qAQ' forumTopicId: 18273 @@ -9,7 +9,7 @@ dashedName: returning-boolean-values-from-functions # --description-- -قد تتذكر من المقارنات باستخدام عملية المساواة (==) أن جميع مشغلي المقارنات يرجعون حالة منطقية (boolean) سواء `true` أو `false`. +قد تتذكر من المقارنة باستخدام مشغِّل المساواة (==) أن جميع مشغلي المقارنات ينتجون قيمة منطقية (boolean) سواء `true` أو `false`. في بعض الأحيان يستخدم الناس `if/else` لإجراء المقارنة، مثلا: @@ -37,13 +37,13 @@ function isEqual(a, b) { # --hints-- -يجب أن يرجع `isLess(10, 15)` حالة `true` +يجب أن ينتج `isLess(10, 15)` حالة `true` ```js assert(isLess(10, 15) === true); ``` -يجب أن يرجع `isLess(15, 10)` حالة `false` +يجب أن ينتج `isLess(15, 10)` حالة `false` ```js assert(isLess(15, 10) === false); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements.md index d81cc2da545b8a..5157fd380d34d6 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/selecting-from-many-options-with-switch-statements.md @@ -9,26 +9,26 @@ dashedName: selecting-from-many-options-with-switch-statements # --description-- -إذا كان لديك العديد من الخيارات للاختيار من بينهما، استخدم عبارة switch. تختبر عبارة `switch` قيمة ويمكن أن تحتوي على العديد من عبارات case التي تحدد القيم المختلفة الممكنة. يتم تنفيذ العبارات من أول قيمة `case` متطابقة حتى يتم العثور على `break`. +إن كنت تريد الاختيار بين خيارات كثيرة، استخدم عبارة switch. تختبر عبارة `switch` قيمة، ومن الأمكن أن تحتوي على عديد من عبارات case التي تحدد قيم مختلفة ممكنة. يتم تنفيذ العبارات من أول قيمة `case` متطابقة حتى يتم العثور على `break`. فيما يلي مثال على عبارة `switch`: ```js -switch (lowercaseLetter) { - case "a": - console.log("A"); +switch (fruit) { + case "apple": + console.log("The fruit is an apple"); break; - case "b": - console.log("B"); + case "orange": + console.log("The fruit is an orange"); break; } ``` -يتم اختبار قيم `case` مساواة تامة strict equality (`===`). كلمة `break` تخبر JavaScript بالتوقف عن تنفيذ العبارات. إذا تم حذف كلمة `break`, سيتم تنفيذ العبارة التالية. +تستخدم اختبارات القيم في `case` المساواة الصارمة (`===`). كلمة `break` تخبر JavaScript بالتوقف عن تنفيذ العبارات. إذا تم حذف كلمة `break`, سيتم تنفيذ العبارة التالية. # --instructions-- -اكتب عبارة switch تختبر `val` وتعين `answer` للشروط التالية: +اكتب عبارة switch لتختبر قيمة `val` وتعين المتغير `answer` للشروط التالية: `1` - `alpha` `2` - `beta` `3` - `gamma` @@ -36,25 +36,25 @@ switch (lowercaseLetter) { # --hints-- -`caseInSwitch(1)` يجب أن يكون له قيمة السلسلة (string) النصية `alpha` +`caseInSwitch(1)` يجب أن يكون له قيمة المقطع النصي (string) `alpha` ```js assert(caseInSwitch(1) === 'alpha'); ``` -`caseInSwitch(2)` يجب أن يكون له قيمة السلسلة (string) النصية `beta` +`caseInSwitch(2)` يجب أن يكون له قيمة المقطع النصي `beta` ```js assert(caseInSwitch(2) === 'beta'); ``` -`caseInSwitch(3)` يجب أن يكون له قيمة السلسلة (string) النصية `gamma` +`caseInSwitch(3)` يجب أن يكون له قيمة المقطع النصي `gamma` ```js assert(caseInSwitch(3) === 'gamma'); ``` -`caseInSwitch(4)` يجب أن يكون له قيمة السلسلة (string) النصية `delta` +`caseInSwitch(4)` يجب أن يكون له قيمة المقطع النصي `delta` ```js assert(caseInSwitch(4) === 'delta'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/shopping-list.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/shopping-list.md index 1bcd107cda438e..8571ce739ab26d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/shopping-list.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/shopping-list.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244bc -title: قائمة التسوق (Shopping List) +title: قائمة التسوق challengeType: 1 videoUrl: 'https://scrimba.com/c/c9MEKHZ' forumTopicId: 18280 @@ -9,37 +9,37 @@ dashedName: shopping-list # --description-- -قم إنشاء قائمة تسوق في المتغير `myList`. وينبغي أن تكون القائمة multi-dimensional array (مصفوفة متعددة الأبعاد) تحتوي على عدة sub-arrays (مصفوفات فرعية). +أنشئ قائمة تسوُّق في المتغير `myList`. وينبغي أن تكون القائمة متعددة الأبعاد (multi-dimensional array) تحتوي على عدة قائمات فرعية (sub-arrays). -يجب أن يحتوي العنصر الأول في كل sub-array على string يحمل اسم الصنف. أما العنصر الثاني فيجب أن يكون رقماً يمثل الكمية مثل. +يجب أن يحتوي العنصر الأول في كل قائمة فرعية (sub-array) على مقطع نصي (string) يحمل اسم الصنف. أما العنصر الثاني فيجب أن يكون رقماً يمثل الكمية، مثلا ```js ["Chocolate Bar", 15] ``` -وينبغي أن يكون في القائمة خمسة sub-arrays على الأقل. +وينبغي أن يكون في القائمة خمسة قائمات فرعية (sub-arrays) على الأقل. # --hints-- -`myList` يجب أن تكون array. +يجب أن تكون `myList` قائمة (array). ```js assert(isArray); ``` -العناصر الأولى في كل الـ sub-arrays الخاصة بك يجب أن تكون كلها strings. +يجب أن تكون كلِّ العناصر الأولى في كل قوائمك الفرعية (sub-arrays) مقاطع نصية (strings). ```js assert(hasString); ``` -العناصر الثانية في كل الـ sub-arrays الخاصة بك يجب أن تكون كلها numbers. +يجب أن تكون كل العناصر الثانية في كل قوائمك الفرعية (sub-arrays) أرقام. ```js assert(hasNumber); ``` -يجب أن يكون لديك 5 عناصر على الأقل في قائمتك. +يجب أن يكون لديك 5 أصناف على الأقل في قائمتك. ```js assert(count > 4); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/stand-in-line.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/stand-in-line.md index 3b14387ec79602..edf2403a2b44c7 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/stand-in-line.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/stand-in-line.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244c6 -title: قف في الصف (Stand in Line) +title: قف في الصف challengeType: 1 videoUrl: 'https://scrimba.com/c/ca8Q8tP' forumTopicId: 18307 @@ -9,11 +9,11 @@ dashedName: stand-in-line # --description-- -في علوم الحاسب الصف هو هيكل بيانات مجرد، حيث يتم حفظ العناصر بالترتيب. يمكن إضافة عناصر جديدة في الجزء الخلفي من الصف ويتم إزالة العناصر القديمة من مقدمة الصف. +في علوم الحاسب (Computer Science) الصف أو queue هو هيكل بيانات (Data Structure) مجرد، حيث يتم حفظ العناصر بالترتيب. يمكن إضافة عناصر جديدة في الجزء الخلفي من الصف ويتم إزالة العناصر القديمة من مقدمة الصف. # --instructions-- -اكتب الوظيفة `nextInLine` و التي تأخذ القائمة الآتية (`arr`) ورَقْم (`item`) كحجج. +اكتب الوظيفة `nextInLine` و التي تأخذ القائمة الآتية (`arr`) ورَقْم (`item`) كمعطيات. أضف الرَقْم إلى نهاية القائمة، ثم أزل العنصر الأول من القائمة. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/store-multiple-values-in-one-variable-using-javascript-arrays.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/store-multiple-values-in-one-variable-using-javascript-arrays.md index a800d8f6b142ca..a3f7520bd17b91 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/store-multiple-values-in-one-variable-using-javascript-arrays.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/store-multiple-values-in-one-variable-using-javascript-arrays.md @@ -1,6 +1,6 @@ --- id: bd7993c9c69feddfaeb8bdef -title: تخزين قيم متعددة في متغير واحد باستخدام مصفوفات جافا سكريبت (Store Multiple Values in one Variable using JavaScript Arrays) +title: تخزين قيم متعددة في متغير واحد باستخدام قائمات JavaScript challengeType: 1 videoUrl: 'https://scrimba.com/c/crZQWAm' forumTopicId: 18309 @@ -9,9 +9,9 @@ dashedName: store-multiple-values-in-one-variable-using-javascript-arrays # --description-- -مع متغير جافا سكريبت الـ `array`، يمكننا تخزين عدة قطع من البيانات في مكان واحد. +بواسطة المتغيرات من نوع `array` في JavaScript، يمكننا تخزين عدة قطع من البيانات في مكان واحد. -تبدأ تعريف الـ array بأقواس مربعه (square bracke) وتنهيها بأقواس مربعه، ووضع فاصلة بين كل إدخال، مثال: +تبدأ إعلان القائمة (array) بأقواس مربعه (square bracke) وتنهيها بأقواس مربعه، ووضع فاصلة بين كل إدخال، مثال: ```js const sandwich = ["peanut butter", "jelly", "bread"]; @@ -19,7 +19,7 @@ const sandwich = ["peanut butter", "jelly", "bread"]; # --instructions-- -قم بتعديل الـ array الجديدة `myArray` بحيث تحتوي على string ورقم في نفس الوقت (بهذا الترتيب). +عدِّل الـقائمة الجديدة `myArray` بحيث تحتوي على string ورقم في نفس الوقت (بهذا الترتيب). # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/storing-values-with-the-assignment-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/storing-values-with-the-assignment-operator.md index e0180d01f20157..2502ed5accbc58 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/storing-values-with-the-assignment-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/storing-values-with-the-assignment-operator.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244a8 -title: تخزين القيم مع مشغل التعيين (Storing Values with the Assignment Operator) +title: تخزين القيم مع مشغل التعيين (=) challengeType: 1 videoUrl: 'https://scrimba.com/c/cEanysE' forumTopicId: 18310 @@ -17,7 +17,7 @@ myVariable = 5; هذا يعين `Number` بقيمة `5` إلى `myVariable`. -إذا كانت هناك أي حسابات إلى يمين مشغل `=`، يتم أداء هذه حسابات قبل تعيين القيمة إلى المتغير الموجود على يسار المشغل. +إذا كانت هناك أي حسابات إلى يمين مشغل `=`، يتم أداء هذه الحسابات قبل تعيين القيمة إلى المتغير الموجود على يسار المشغل. ```js var myVar; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript.md index 9614b3609dbb72..08a01e03ac0954 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/subtract-one-number-from-another-with-javascript.md @@ -1,6 +1,6 @@ --- id: cf1111c1c11feddfaeb4bdef -title: طرح رقم من الآخر باستخدام JavaScript +title: طرح رَقَم من رَقَم آخر باستخدام JavaScript challengeType: 1 videoUrl: 'https://scrimba.com/c/cP3yQtk' forumTopicId: 18314 @@ -9,7 +9,7 @@ dashedName: subtract-one-number-from-another-with-javascript # --description-- -يمكننا أيضا أن نطرح رقما من الآخر. +يمكننا أيضا أن نطرح رقما من رقما آخر. يستخدم JavaScript رمز `-` للطرح. @@ -22,17 +22,17 @@ const myVar = 12 - 6; لدي `myVar` قيمة `6` الآن. # --instructions-- -غيّر `0` بحيث يكون الفرق `12`. +غيّر `0` بحيث يكون الفرق (difference) `12`. # --hints-- -يجب أن يساوي `difference` قيمة 12. +يجب أن يساوي المتغير `difference` قيمة `12`. ```js assert(difference === 12); ``` -يجب عليك طرح رَقَم واحد فقط من 45. +يجب أن تطرح رَقَم واحد فقط من `45`. ```js assert(/difference=45-33;?/.test(__helpers.removeWhiteSpace(code))); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understand-string-immutability.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understand-string-immutability.md index 0479edcfc8111e..06234850a2306e 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understand-string-immutability.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understand-string-immutability.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244ba -title: فهم عدم قابلية المقطع على التغيير (Understand String Immutability) +title: فهم عدم قابلية المقطع على التغيير (String Immutability) challengeType: 1 videoUrl: 'https://scrimba.com/c/cWPVaUR' forumTopicId: 18331 @@ -9,16 +9,16 @@ dashedName: understand-string-immutability # --description-- -في JavaScript، قيم `String` هي قيم قابلة للتغيير، مما يعني أنه لا يمكن تغييرها بمجرد إنشائها. +في JavaScript، قيم `String` هي قيم غير قابلة للتغيير، (immutable) مما يعني أنه لا يمكن تغييرها بعد إنشائها. -على سبيل المثال الكود التالي سيحدث خطأ لأن الحرف `B` في المقطع `Bob` لا يمكن تغييره إلى الحرف `J`: +على سبيل المثال الكود التالي سينتج خطأ لأن الحرف `B` في المقطع النصي `Bob` لا يمكن تغييره إلى حرف `J`: ```js let myStr = "Bob"; myStr[0] = "J"; ``` -لاحظ أن هذا *لا* يعني أنه لا يمكن إعادة تعيين `myStr`. الطريقة الوحيدة لتغيير `myStr` هي تعيينه بمقطع جديدة، هكذا: +لاحظ أن هذا *لا* يعني أنه لا يمكن إعادة تعيين `myStr`. الطريقة الوحيدة لتغيير `myStr` هي تعيينه بمقطع جديد، هكذا: ```js let myStr = "Bob"; @@ -27,7 +27,7 @@ myStr = "Job"; # --instructions-- -صحّ تعيين `myStr` بحيث يحتوي على قيمة المقطع `Hello World` باستخدام النهج الموضح في المثال أعلاه. +صحّح تعيين `myStr` بحيث يحتوي على قيمة المقطع النصي `Hello World` باستخدام الطريقة الموضحة في المثال أعلاه. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-boolean-values.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-boolean-values.md index 5df0a28bef384a..b91ac0d6171520 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-boolean-values.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-boolean-values.md @@ -1,6 +1,6 @@ --- id: bd7123c9c441eddfaeb5bdef -title: فهم الحالات المنطقية (Understanding Boolean Values) +title: فهم القيم المنطقية challengeType: 1 videoUrl: 'https://scrimba.com/c/c9Me8t4' forumTopicId: 301176 @@ -9,23 +9,23 @@ dashedName: understanding-boolean-values # --description-- -نوع آخر من البيانات هو حالة المنطقية. يمكن أن يكون للحالات المنطقية حالة واحدة فقط من حالتين: `true` أو `false`. إنها في الأساس كمفاتيح تشغيل صغيرة لإيقاف وبدء التشغيل، حيث إن `true` يبدأ التشغيل و `false` يوقفه. وهاتان الحالتان تستبعد إحداهما الأخرى. +نوع آخر من البيانات هو القيم المنطقية المطلق عليها إسم Boolean. يمكن أن يكون للقيم المنطقية (booleans) حالة واحدة فقط من حالتين: `true` أو `false`. إنهم في الأساس كمفاتيح تشغيل صغيرة لبدء أو إيقاف التشغيل، حيث إن `true` يبدأ التشغيل و `false` يوقفه. والحالتان يستبعدان بعضهن البعض (mutually-exclusive). -**ملاحظة:** القيم الحالة المنطقية لا تكتب أبدا باستخدام علامات الاقتباس. المقطعين `"true"` و `"false"` ليست حالتي منطقية وليس لها معنى خاص في JavaScript. +**ملاحظة:** القيم المنطقية لا تكتب أبدا باستخدام علامات الاقتباس. المقطعين `"true"` و `"false"` ليسوا بقيم منطقية وليس لهم معنى خاص في JavaScript. # --instructions-- -عدّل الوظيفة `welcomeToBooleans` بحيث ترجع `true` بدلاً من `false` عند النقر على زر التشغيل. +Modify the `welcomeToBooleans` function so that it returns `true` instead of `false`. # --hints-- -يجب أن تقوم الوظيفة `welcomeToBooleans()` بإرجاع حالة منطقية (`true`, أو `false`). +يجب أن تقوم الوظيفة `welcomeToBooleans()` بإنتاج قيمة منطقية (`true`, أو `false`). ```js assert(typeof welcomeToBooleans() === 'boolean'); ``` -يجب أن يرجع `welcomeToBooleans()` حالة `true`. +`welcomeToBooleans()` يجب أن ينتج `true`. ```js assert(welcomeToBooleans() === true); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-case-sensitivity-in-variables.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-case-sensitivity-in-variables.md index f0747b19f17b0a..29ec1dd48705b3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-case-sensitivity-in-variables.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-case-sensitivity-in-variables.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244ab -title: فهم حساسية الحالة الحروف في المتغيرات (Understanding Case Sensitivity in Variables) +title: فهم حساسية الحالة الحروف في المتغيرات challengeType: 1 videoUrl: 'https://scrimba.com/c/cd6GDcD' forumTopicId: 18334 @@ -27,7 +27,7 @@ var thisVariableNameIsSoLong; # --instructions-- -عدّل التعريفات والتخصيصات الحالية بحيث تستخدم أسماؤها camelCase. +عدّل الإعلانات والتخصيصات الحالية بحيث تستخدم أسماؤها camelCase. لا تنشئ أي متغيرات جديدة. @@ -39,7 +39,7 @@ var thisVariableNameIsSoLong; assert(typeof studlyCapVar !== 'undefined' && studlyCapVar === 10); ``` -يجب أن يتم تعريف`properCamelCase` وأن تكون له قيمة `A String` بنوع مقطع. +يجب أن يتم تعريف`properCamelCase` وأن تكون له قيمة المقطع النصي `A String`. ```js assert( @@ -53,7 +53,7 @@ assert( assert(typeof titleCaseOver !== 'undefined' && titleCaseOver === 9000); ``` -يجب أن يستخدم `studlyCapVar` حالة camelCase في كل من أقسام التعريف والتخصيص. +يجب أن يستخدم `studlyCapVar` حالة camelCase في كل من أقسام الإعلان والتخصيص. ```js assert(code.match(/studlyCapVar/g).length === 2); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function.md index bb19d74f0ba401..8ecf981fc51b8b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-undefined-value-returned-from-a-function.md @@ -1,6 +1,6 @@ --- id: 598e8944f009e646fc236146 -title: فهم القيم غير المحددة المرتجعة من الوظيفة (Understanding Undefined Value returned from a Function) +title: فهم القيم غير المحددة المنتجة من وظيفة challengeType: 1 videoUrl: 'https://scrimba.com/c/ce2p7cL' forumTopicId: 301177 @@ -9,7 +9,7 @@ dashedName: understanding-undefined-value-returned-from-a-function # --description-- -يمكن أن يتضمن الوظيفة عبارة `return` ولكن ليس عليه أن يفعل ذلك. في حالة أن الوظيفة لا يحتوي على عبارة `return` عندما يتم استدعائه، تتم معالجة الكود الداخلي في الوظيفة ولكن القيمة التي يتم إرجاعها هي `undefined`. +تستطيع الوظيفة أن تتضمن عبارة `return` ولكن ليست ملزمة بفعل ذلك. في حالة أن الوظيفة لا تحتوي على عبارة `return`، عند تفعيلها، يتم معالجة الكود الداخلي في الوظيفة، ولكن القيمة المنتجة تكون `undefined`. **مثال** @@ -23,11 +23,11 @@ function addSum(num) { addSum(3); ``` -تكون `addSum` وظيفة دون `return`. سيغير وظيفة المتغير `sum` العالمي الآتي, ولكن تكون القيمة المرتجعة للوظيفة `undefined`. +الوظيفة `addSum` بدون `return`. ستغير الوظيفة قيمة المتغير الشامل `sum`، ولكن تكون القيمة المنتجة للوظيفة هي `undefined`. # --instructions-- -أنشئ وظيفة `addFive` دون أي حجج. تضيف الوظيفة 5 إلى متغير `sum` ولكن تكون قيمته المرتجعة `undefined`. +أنشئ وظيفة `addFive` دون أي معطيات. تضيف الوظيفة 5 إلى متغير `sum` ولكن تكون القيمة المنتجة `undefined`. # --hints-- @@ -37,19 +37,19 @@ addSum(3); assert(typeof addFive === 'function'); ``` -بمجرد تشغيل كلتا الوظيفتين، يجب أن يكون `sum` يساوي `8`. +بمجرد تشغيل كلا الوظيفتين، يجب أن يكون `sum` يساوي `8`. ```js assert(sum === 8); ``` -يجب أن تنتج `addFive` القيمة المرتجعة `undefined`. +يجب أن تنتج `addFive` القيمة `undefined`. ```js assert(addFive() === undefined); ``` -داخل وظيفة `addFive`، يجب عليك إضافة `5` إلى متغير `sum`. +داخل وظيفة `addFive`، يجب عليك إضافة `5` إلى المتغير `sum`. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-uninitialized-variables.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-uninitialized-variables.md index c0754503ba84ce..d29ad8efa7016a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-uninitialized-variables.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/understanding-uninitialized-variables.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244aa -title: فهم المتغيرات غير المهيأة (Understanding Uninitialized Variables) +title: فهم المتغيرات غير المهيأة challengeType: 1 videoUrl: 'https://scrimba.com/c/cBa2JAL' forumTopicId: 18335 @@ -9,7 +9,7 @@ dashedName: understanding-uninitialized-variables # --description-- -عند تعريف متغيرات JavaScript، يكون لها قيمة أولية وهي `undefined`. إذا قمت بعملية رياضية على متغير `undefined` ستكون نتيجتك `NaN` مما يعني "Not a Number" إي "ليس رقما". إذا ربط مقطع مع متغير `undefined`، فستحصل على مقطع بقيمة `undefined`. +عند إعلان المتغيرات في JavaScript، يكون لها قيمة أولية وهي `undefined`. إذا قمت بعملية رياضية على متغير قيمته `undefined` ستكون نتيجتك `NaN` مما يعني "Not a Number" إي "ليس رقما". إذا ربط مقطع نصي مع متغير `undefined`، فستحصل على مقطع نصي بقيمة `undefined`. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/updating-object-properties.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/updating-object-properties.md index 4bd3ae7b1704d2..9c4f3faf51783f 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/updating-object-properties.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/updating-object-properties.md @@ -9,7 +9,7 @@ dashedName: updating-object-properties # --description-- -بعد إنشاء كائن JavaScript، يمكنك تحديث خصائصه في أي وقت كما يمكنك تحديث أي متغير آخر. يمكنك استخدام أي من تدوين النِّقَاط أو تدوين الأقواس المعكوفان (dot or bracket notation). +بعد إنشاء كائن JavaScript، يمكنك تحديث خصائصه في أي وقت كما يمكنك تحديث أي متغير آخر. يمكنك استخدام أي من رمز النقطة أو علامات الأقواس (dot or bracket notation). على سبيل المثال، دعونا ننظر إلى `ourDog`: @@ -26,7 +26,7 @@ const ourDog = { # --instructions-- -حدث خاصية اسم الكائن `myDog`. غيّر اسمه من `Coder` إلى `Happy Coder`. يمكنك استخدام أي من تدوين النِّقَاط أو تدوين الأقواس المعكوفان (dot or bracket notation). +حدث خاصية اسم الكائن `myDog`. غيّر اسمه من `Coder` إلى `Happy Coder`. يمكنك استخدام أي من رمز النقطة أو علامات الأقواس (dot or bracket notation). # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-first-character-in-a-string.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-first-character-in-a-string.md index a28608ed66466b..2f4ce5fd581d97 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-first-character-in-a-string.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-first-character-in-a-string.md @@ -1,6 +1,6 @@ --- id: bd7123c9c549eddfaeb5bdef -title: استخدم رمز الاقواس للعثور على اول حرف في مقطع (Use Bracket Notation to Find the First Character in a String) +title: استخدم علامات الأقواس للعثور على اول حرف في مقطع challengeType: 1 videoUrl: 'https://scrimba.com/c/ca8JwhW' forumTopicId: 18341 @@ -9,11 +9,11 @@ dashedName: use-bracket-notation-to-find-the-first-character-in-a-string # --description-- -القوسان المعكوفان هي طريقة للحصول على رمز في ترتيب معين داخل المقطع. +القوسان المربعان هما طريقة للحصول على رمز في ترتيب (index) معين داخل مقطع نصي. -معظم لغات البرمجة الحديثة، مثل JavaScript، لا تبدأ في العد من 1 كما يفعل البشر. إنهم يبدؤون عند الصفر. يشار إلى هذا بالترتيب مبني على الصفر. +معظم لغات البرمجة الحديثة، مثل JavaScript، لا تبدأ في العد من 1 كما يفعل البشر. إنهم يبدؤون عند الصفر. يشار إلى هذا بالترتيب من الصفر zero-based indexing. -على سبيل المثال، رمز ترتيب 0 في كلمة `Charles` هو `C`. إذن إذا `const firstName = "Charles"`، يمكنك الحصول على قيمة الرمز الأول من المقطع باستخدام `firstName[0]`. +على سبيل المثال، الرمز في ترتيب 0 في كلمة `Charles` هو `C`. إذن إذا `const firstName = "Charles"`، يمكنك الحصول على قيمة الرمز الأول من المقطع باستخدام `firstName[0]`. مثال: @@ -26,7 +26,7 @@ const firstLetter = firstName[0]; # --instructions-- -استخدم رمز الأقواس للعثور على الرمز الأول في متغير `lastName` وتعيينه إلى `firstLetterOfLastName`. +استخدم علامات الأقواس المربعة للعثور على الرمز الأول في متغير `lastName` وتعيينه إلى `firstLetterOfLastName`. **تلميح:** حاول النظر إلى المثال أعلاه إذا كنت عالق. @@ -38,7 +38,7 @@ const firstLetter = firstName[0]; assert(firstLetterOfLastName === 'L'); ``` -يجب عليك استخدام رمز الأقواس المعكوفان. +يجب عليك استخدام علامات الأقواس. ```js assert(code.match(/firstLetterOfLastName\s*=\s*lastName\s*\[\s*\d\s*\]/)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-last-character-in-a-string.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-last-character-in-a-string.md index 12d33734835b8a..858985a08642c4 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-last-character-in-a-string.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-last-character-in-a-string.md @@ -1,6 +1,6 @@ --- id: bd7123c9c451eddfaeb5bdef -title: استخدم رمز آلأقواس (Bracket Notation) للعثور على آخر حرف في سلسلة (String) +title: استخدم علامات الأقواس (Bracket Notation) للعثور على آخر حرف في مقطع نصي (String) challengeType: 1 videoUrl: 'https://scrimba.com/c/cBZQGcv' forumTopicId: 18342 @@ -9,9 +9,9 @@ dashedName: use-bracket-notation-to-find-the-last-character-in-a-string # --description-- -للحصول على آخر حرف من سلسلة (String)، يمكنك طرح واحد من طول السلسلة (String). +للحصول على آخر حرف من المقطع النصي (String)، يمكنك طرح واحد من طوله. -على سبيل المثال، إذا `const firstName = "Ada"`، يمكنك الحصول على قيمة الحرف الأخير من السلسلة باستخدام `firstName[firstName.length - 1]`. +على سبيل المثال، إذا `const firstName = "Ada"`، يمكنك الحصول على قيمة الحرف الأخير من المقطع باستخدام `firstName[firstName.length - 1]`. مثال: @@ -20,17 +20,17 @@ const firstName = "Ada"; const lastLetter = firstName[firstName.length - 1]; ``` -`lastLetter` سيكون لها قيمة تساوي السلسلة `a`. +سيكون قيمة `lastLetter` تساوي المقطع النصي `a`. # --instructions-- -استخدم رمز الأقواس للعثور على الحرف الأخير في المتغير `lastName`. +استخدم علامات الأقواس للعثور على الحرف الأخير في المتغير `lastName`. **تلميح:** حاول النظر إلى المثال أعلاه إذا كنت عالق. # --hints-- -`lastLetterOfLastName` يجب أن يكون الحرف `e`. +يجب أن يكون `lastLetterOfLastName` الحرف `e`. ```js assert(lastLetterOfLastName === 'e'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-character-in-a-string.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-character-in-a-string.md index df2d282fa5019b..db775becfc8c51 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-character-in-a-string.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-character-in-a-string.md @@ -1,6 +1,6 @@ --- id: bd7123c9c450eddfaeb5bdef -title: استخدم رمز آلأقواس المعكوفان للعثور على حرف معين في مقطع +title: استخدم علامات الأقواس للعثور على حرف معين في مقطع challengeType: 1 videoUrl: 'https://scrimba.com/c/cWPVJua' forumTopicId: 18343 @@ -9,9 +9,9 @@ dashedName: use-bracket-notation-to-find-the-nth-character-in-a-string # --description-- -يمكنك أيضًا استخدام رمز الأقواس المعكوفان للحصول على الحرف في مواقع أخرى داخل مقطع. +يمكنك أيضًا استخدام علامات الأقواس للحصول على حرف في مواقع أخرى داخل مقطع. -تذكر أن أجهزة الكمبيوتر تبدأ في العد في `0`، لذا فإن الحرف الأول هو في الواقع الحرف صفر. +تذكر أن أجهزة الكمبيوتر تبدأ في العد من `0`، لذا فإن الحرف الأول هو في الواقع الحرف الصفر. مثال: @@ -24,7 +24,7 @@ const secondLetterOfFirstName = firstName[1]; # --instructions-- -دعونا نحاول تعيين `thirdLetterOfLastName` مساوية للحرف الثالث من متغير `lastName` باستخدام رمز آلأقواس المعكوفان. +دعونا نحاول تعيين `thirdLetterOfLastName` مساوية للحرف الثالث من متغير `lastName` باستخدام علامات الأقواس. **تلميح:** حاول النظر إلى المثال أعلاه إذا كنت عالق. @@ -36,7 +36,7 @@ const secondLetterOfFirstName = firstName[1]; assert(thirdLetterOfLastName === 'v'); ``` -يجب عليك استخدام رمز آلأقواس المعكوفان. +يجب عليك استخدام علامات الأقواس. ```js assert(code.match(/thirdLetterOfLastName\s*=\s*lastName\s*\[\s*\d\s*\]/)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-to-last-character-in-a-string.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-to-last-character-in-a-string.md index d1054668e310f8..06ccc4f2a878fd 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-to-last-character-in-a-string.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-bracket-notation-to-find-the-nth-to-last-character-in-a-string.md @@ -1,6 +1,6 @@ --- id: bd7123c9c452eddfaeb5bdef -title: استخدم رمز آلأقواس المعكوفان للعثور على حرف معين قبل الأخر في مقطع +title: استخدم علامات الأقواس للعثور على رمز معين قبل الأخير في المقطع النصي challengeType: 1 videoUrl: 'https://scrimba.com/c/cw4vkh9' forumTopicId: 18344 @@ -9,7 +9,7 @@ dashedName: use-bracket-notation-to-find-the-nth-to-last-character-in-a-string # --description-- -يمكنك استخدام نفس المبدأ الذي استخدمناه للتو لاسترداد الحرف الأخير في مقطع لاسترداد الحرف ما قبل أخر حرف. +يمكنك استخدام نفس المبدأ الذي استخدمناه لاسترداد آخر حرف في مقطع نصي لتسترد أي حرف ما قبل الحرف الأخير. على سبيل المثال يمكنك الحصول على قيمة الحرف الثالث إلى الأخير من مقطع `const firstName = "Augusta"` باستخدام `firstName[firstName.length - 3]` @@ -20,11 +20,11 @@ const firstName = "Augusta"; const thirdToLastLetter = firstName[firstName.length - 3]; ``` -سيحتوي `thirdToLastLetter` قيمة من المقطع `s`. +سيحتوي `thirdToLastLetter` قيمة `s` من المقطع النصي. # --instructions-- -استخدم رمز آلأقواس المعكوفان للعثور على الحرف الثاني إلى الأخير في مقطع `lastName`. +استخدم علامات الأقواس للعثور على الحرف الثاني إلى الأخير في مقطع `lastName`. **تلميح:** حاول النظر إلى المثال أعلاه إذا كنت عالق. @@ -36,7 +36,7 @@ const thirdToLastLetter = firstName[firstName.length - 3]; assert(secondToLastLetterOfLastName === 'c'); ``` -يجب عليك استخدام `.length` للحصول على الحرف الثاني الأخير. +يجب عليك استخدام `.length` للحصول على الحرف الثاني إلى الأخير. ```js assert(code.match(/\.length/g).length > 0); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-conditional-logic-with-if-statements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-conditional-logic-with-if-statements.md index 0d2d17c3e8bde9..36fb438bb3f73b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-conditional-logic-with-if-statements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-conditional-logic-with-if-statements.md @@ -9,9 +9,9 @@ dashedName: use-conditional-logic-with-if-statements # --description-- -تستخدم تعبيرات `if` لإخذ القرارات في الكود البرمجي. تخبر كلمة `if` لغة JavaScript بتنفيذ التعليمات البرمجية داخل الأقواس المتعرجة (curly braces) تحت شروط معينة, تكون معرفة في الأقواس (parentheses). تعرف هذه الشروط بالشروط المنطقية `Boolean` ويمكن أن تكون فقط صحيحة `true` أو خاطئة `false`. +تستخدم تعبيرات `if` لإخذ القرارات في الكود. تخبر كلمة `if` لغة JavaScript بتنفيذ التعليمات البرمجية داخل الأقواس المقرونة (curly braces) تحت شروط معينة معرفة في أقواس دائرية (parentheses). تعرف هذه الشروط بالشروط المنطقية `Boolean` ويمكن أن تكون قيمتها فقط صحيحة `true` أو خاطئة `false`. -عندما يتم تقييم الشرط إلى صحيح `true`، يقوم البرنامج بتنفيذ التعبيرات البرمجية داخل الأقواس المتعرجة (curly braces). عندما يتم تقييم الشرط إلى خطأ `false`، التعليمات البرمجية داخل الأقواس المتعرجة (curly braces) لن تنفذ. +عندما يتم تقييم الشرط المنطقي إلى صحيح `true`، يقوم البرنامج بتنفيذ التعبيرات البرمجية داخل الأقواس المقرونة (curly braces). عندما يتم تقييم الشرط المنطقي إلى خطأ `false`، التعليمات البرمجية داخل الأقواس المقرونة (curly braces) لن تنفذ. **كود زائف (Pseudocode)** @@ -33,11 +33,11 @@ test(false); ينتج `test(true)` مقطع `It was true`، وينتج `test(false)` مقطع `It was false`. -عندما يتم استدعاء `test` بقيمة `true`، ويكون تعبير `if` يقيّم `myCondition` لتتيقن من أنها `true` أو لا. نظرًا لأنه `true`، فإن الوظيفة تنتج `It was true`. عندما تتصل ب `test` بقيمة `false`، يكون `myCondition` بقيمة *غير* `true` ولم يتم تنفيذ العبارة الواردة في الأقواس المنحنية وتنتج الوظيفة `It was false`. +عندما تفعَّل `test` بقيمة `true`، سيقوم تعبير `if` بتقييم `myCondition` لتتيقن من أنها `true` أو لا. نظرًا لأنه `true`، فإن الوظيفة تنتج `It was true`. عندما تفعَّل `test` بقيمة `false`، يكون `myCondition` قيمته *ليست* `true` ولم يتم تنفيذ العبارة الواردة في الأقواس المدورة وتنتج الوظيفة `It was false`. # --instructions-- -أنشئ تعبير `if` داخل الوظيفة لينتج `Yes, that was true` إذا حالة الحجة `wasThatTrue` تكون `true` وتنتج `No, that was false` خلافا لذلك. +أنشئ تعبير `if` داخل الوظيفة لينتج `Yes, that was true` إذا حالة الوسيط `wasThatTrue` تكون `true` وينتج `No, that was false` خلافا لذلك. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-multiple-conditional-ternary-operators.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-multiple-conditional-ternary-operators.md index 4253e56fa1aa98..c092d0dc54d636 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-multiple-conditional-ternary-operators.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-multiple-conditional-ternary-operators.md @@ -37,7 +37,7 @@ function findGreaterOrEqual(a, b) { } ``` -ويعدّ من أفضل الممارسات تشكيل متعهدين شرطيين متعددين، بحيث يكون كل شرط على خط منفصل، كما هو مبين أعلاه. استخدام عدة مشغلين مشروطين دون إهدار مناسب قد يجعل من الصعب قراءة التعليمات البرمجية الخاصة بك. على سبيل المثال: +ويعدّ من أفضل الممارسات تشكيل متعهدين شرطيين متعددين، بحيث يكون كل شرط على خط منفصل، كما هو مبين أعلاه. استخدام عدة مشغلين مشروطين دون إهدار مناسب قد يجعل من الصعب قراءة الكود الخاص بك. على سبيل المثال: ```js function findGreaterOrEqual(a, b) { diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown.md index 4fe4ea0c029368..83e94e1dbc660c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown.md @@ -33,7 +33,7 @@ console.log(countup(5)); # --instructions-- -لقد عرفنا وظيفة تسمى `countdown` مع حجة واحدة (`n`). يجب أن تستخدم الوظيفة التكرار لإعادة قائمة تحتوي على الأعداد من `n` إلى `1` استنادًا إلى حجة وهي `n`. إذا تم تفعيل الوظيفة بعدد أقل من 1، يجب أن تنتج قائمة فارغة. على سبيل المثال، استدعاء هذه الوظيفة مع `n = 5` يجب أن تنتج القائمة التالية `[5, 4, 3, 2, 1]`. يجب أن تستخدم الوظيفة التكرار بواسطة تفعيل نفسها، ويجب ألا تستخدم الحلقات من أي نوع. +لقد عرفنا وظيفة تسمى `countdown` مع وسيط (parameter) واحدة (`n`). يجب أن تستخدم الوظيفة التكرار (recursion) لتنتج قائمة (array) تحتوي على الأعداد من `n` إلى `1` استنادًا إلى وسيط (parameter) مسمى `n`. إذا تم تفعيل الوظيفة بعدد أقل من 1، يجب أن تنتج قائمة فارغة. على سبيل المثال، استدعاء هذه الوظيفة مع `n = 5` يجب أن تنتج القائمة التالية `[5, 4, 3, 2, 1]`. يجب أن تستخدم الوظيفة التكرار بواسطة تفعيل نفسها، ويجب ألا تستخدم الحلقات من أي نوع. # --hints-- @@ -71,7 +71,7 @@ assert( ); ``` -لا ينبغي استخدام المتغيرات العالمية (Global variables) للتخزين المؤقت القائمة (array). +لا ينبغي استخدام المتغيرات الشاملة (Global variables) للتخزين المؤقت للقائمة (array). ```js countdown(1) diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers.md index 1f582ecbcfa7f6..833632939dbd1f 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-range-of-numbers.md @@ -12,7 +12,7 @@ dashedName: use-recursion-to-create-a-range-of-numbers # --instructions-- -لقد عرفنا وظيفة تسمى `rangeOfNumbers` مع اثنين من الحجج. يجب أن تنتج الوظيفة قيمة القائمة من الأعداد الصحيحة التي تبدأ بعدد يمثله حجة وهي `startNum` وتنتهي بعدد يمثله حجة آخرة وهي `endNum`. سيكون رقم البداية دائماً أقل من أو يساوي رقم النهاية. يجب أن تستخدم الوظيفة التكرار بواسطة تفعيل نفسها، ويجب ألا تستخدم الحلَقات من أي نوع. يجب أن تعمل أيضا في الحالات التي يكون فيها كل من `startNum` و `endNum` متماثلين. +لقد حددنا وظيفة (function) تسمى `rangeOfNumbers` مع اثنين من الوسائط (parameters). يجب أن تنتج الوظيفة قائمة من الأعداد الصحيحة التي تبدأ بعدد يمثله وسيط `startNum` وتنتهي بعدد يمثله وسيط `endNum` الآخرة. سيكون رقم البداية دائماً أقل من أو يساوي رقم النهاية. يجب أن تستخدم الوظيفة التكرار بواسطة تفعيل نفسها، ويجب ألا تستخدم الحلَقات من أي نوع. يجب أن تعمل أيضا في الحالات التي يكون فيها كل من `startNum` و `endNum` متماثلين. # --hints-- @@ -56,7 +56,7 @@ assert.deepStrictEqual(rangeOfNumbers(6, 9), [6, 7, 8, 9]); assert.deepStrictEqual(rangeOfNumbers(4, 4), [4]); ``` -لا ينبغي استخدام المتغيرات العالمية (Global variables) للتخزين المؤقت القائمة (array). +لا ينبغي استخدام المتغيرات الشاملة (Global variables) للتخزين المؤقت للقائمة (array). ```js rangeOfNumbers(1, 3) diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-the-parseint-function.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-the-parseint-function.md index b94905c0c00782..0cd44b5cfa043c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-the-parseint-function.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/use-the-parseint-function.md @@ -19,7 +19,7 @@ const a = parseInt("007"); # --instructions-- -استخدم `parseInt()` في وظيفة اسمها `convertToInteger` تقبل حجة اسمها `str` هي مقطع، تحوله إلى عدد صحيح وترجعه. +استخدم `parseInt()` في وظيفة اسمها `convertToInteger` لتخول قيمة المقطع النصي `str` إلى عدد صحيح, وتنتجه. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/word-blanks.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/word-blanks.md index 7fcd7baa7d7d7f..d184b0ddd19696 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/word-blanks.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/word-blanks.md @@ -9,7 +9,7 @@ dashedName: word-blanks # --description-- -لقد تم تزويدك بجمل مع بعض الكلمات الناقصة، مثل الأسماء و الأفعال و النعوت و الظروف. ثم تملأ القطع المفقودة بكلمات من اختيارك بطريقة تجعل الجملة المكتملة منطقية. +تم تزويدك بجمل ناقصة بعض الكلمات، مثل الأسماء و الأفعال و النعوت و الظروف. ثم أملأ القطع المفقودة بكلمات من اختيارك بطريقة تجعل الجملة المكتملة منطقية. فكر في هذه الجملة - كانت حقاً **\_\_\_\_\_**، ونحن **\_\_\_\_** أيضا **\_\_\_\_\_**. هذه الجملة لها ثلاث قطع مفقودة - نعمة و فعل و ظرف، ويمكنك إضافة كلمات من اختيارك لإكمالها. ويمكن بعد ذلك أن نحيل الجملة المستكملة إلى متغير (variable) على النحو التالي: @@ -21,13 +21,13 @@ const sentence = "It was really " + "hot" + ", and we " + "laughed" + " ourselve في هذا التحدي، نقدم لكم اسماً وفعلاً ووصفاً وظرفاً. تحتاج إلى تشكيل جملة كاملة باستخدام كلمات من اختيارك، إلى جانب الكلمات التي نقدمها. -سوف تحتاج إلى استخدام مشغل يربط المقاطع (string concatenation operator) `+` لبناء مقطع (string) جديدة، باستخدام المتغيرات المتاحة: `myNoun`، و `myAdjective`، و `myVerb`، و `myAdverb`. بعد ذلك عيين مقطع الذي تم تشكيلها إلى متغير `wordBlanks`. لا يجب عليك تغيير الكلمات المسندة إلى متغيرات. +سوف تحتاج إلى استخدام مشغل ضم المقاطع (string concatenation operator) `+` لبناء مقطع نصي جديد، باستخدام المتغيرات المتاحة: `myNoun`، و `myAdjective`، و `myVerb`، و `myAdverb`. بعد ذلك عيين المقطع النصي الذي تم تشكيله إلى متغير `wordBlanks`. لا يجب عليك تغيير الكلمات المسندة إلى متغيرات. -سوف تحتاج أيضا إلى حساب المسافات الموجودة في مقطع، بحيث تحتوي الجملة الأخيرة على مسافات بين جميع الكلمات. ينبغي أن تكون النتيجة الجملة الكاملة. +سوف تحتاج أيضا إلى حساب المسافات الموجودة في مقطعك، بحيث أن تحتوي الجملة الأخيرة على مسافات بين جميع الكلمات. ينبغي أن تكون النتيجة جملة كاملة. # --hints-- -يجب أن تكون `wordBlanks` مقطع. +يجب أن تكون `wordBlanks` مقطع نصي. ```js assert(typeof wordBlanks === 'string'); @@ -44,7 +44,7 @@ assert( ); ``` -يجب ألا تستخدم القيم `dog` أو `ran`, أو `big`, أو `quickly` لإنشاء `wordBlanks`. +يجب ألا تستخدم القيم `dog` أو `ran`, أو `big`, أو `quickly` مباشرةً لإنشاء `wordBlanks`. ```js const newCode = removeAssignments(code); @@ -56,7 +56,7 @@ assert( ); ``` -يجب أن يحتوي `wordBlanks` على جميع الكلمات المخصصة للمتغيرات `myNoun`, و `myVerb`, و `myAdjective`, و `myAdverb` المفصولة برموز ليست بكلمات (و أي كلمات إضافية من اختيارك). +يجب أن يحتوي `wordBlanks` على جميع الكلمات المخصصة للمتغيرات `myNoun`, و `myVerb`, و `myAdjective`, و `myAdverb` المفصولة برموز ليست بكلمات (مع أي كلمات إضافية من اختيارك). ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/write-reusable-javascript-with-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/write-reusable-javascript-with-functions.md index b5c0f3a7d9dd37..f8cc559c288c86 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/write-reusable-javascript-with-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/basic-javascript/write-reusable-javascript-with-functions.md @@ -1,6 +1,6 @@ --- id: 56bbb991ad1ed5201cd392cf -title: كتابة JavaScript قابل لإعادة الاستخدام مع الوظائف (Write Reusable JavaScript with Functions) +title: كتابة JavaScript قابلة لإعادة الاستخدام بواسطة الوظائف (Functions) challengeType: 1 videoUrl: 'https://scrimba.com/c/cL6dqfy' forumTopicId: 18378 @@ -9,7 +9,7 @@ dashedName: write-reusable-javascript-with-functions # --description-- -في JavaScript، يمكننا تقسيم الكود إلى أجزاء قابلة لإعادة الاستخدام تسمى وظائف. +في JavaScript، يمكننا تقسيم الكود إلى أجزاء قابلة لإعادة الاستخدام تسمى وظائف (functions). إليك مثال لوظيفة: @@ -19,16 +19,16 @@ function functionName() { } ``` -يمكنك استدعاء أو تفعيل هذه الوظيفة باستخدام اسمه متبوعا بقوسين، هكذا: `functionName();` في كل مرة يستدعي الوظيفة، ستطبع الرسالة `Hello World` في وحدة التحكم. سيتم تنفيذ الكود بين الأقواس المتعرجة في كل مرة يستدعي الوظيفة. +يمكنك تنفيذ أو تفعيل هذه الوظيفة باستخدام اسمها متبوعا بقوسين، هكذا: `functionName();`. في كل مرة تفعَّل الوظيفة، ستطبع الرسالة `Hello World` في الكونسول (console). سيتم تنفيذ الكود بين الأقواس المقرونة في كل مرة تفعَّل الوظيفة. # --instructions--
    1. - أنشئ وظيفة تسمى reusableFunction الذي يطبع مقطع Hi World إلى وحدة التحكم. + أنشئ وظيفة تسمى reusableFunction التي تطبع مقطع Hi World في الكونسول.
    2. - أستدعي الوظيفة. + فعِّل الوظيفة.
    @@ -40,13 +40,13 @@ function functionName() { assert(typeof reusableFunction === 'function'); ``` -إذا تم استدعاء `reusableFunction`، فيجب طباعة مقطع `Hi World` علي وحدة التحكم. +إذا تم تفعيل `reusableFunction`، فيجب طباعة مقطع `Hi World` في الكونسول. ```js assert(testConsole()); ``` -يجب عليك استدعاء `reusableFunction` بمجرد تعريفها. +يجب عليك تفعيل `reusableFunction` بمجرد تعريفها. ```js const functionStr = reusableFunction && __helpers.removeWhiteSpace(reusableFunction.toString()); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-arguments-passed-in-the-wrong-order-when-calling-a-function.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-arguments-passed-in-the-wrong-order-when-calling-a-function.md index f20e1d24e3de02..d112945a53d37c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-arguments-passed-in-the-wrong-order-when-calling-a-function.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-arguments-passed-in-the-wrong-order-when-calling-a-function.md @@ -1,6 +1,6 @@ --- id: 587d7b85367417b2b2512b3a -title: إدراك الوسائط (Arguments) المارة بترتيب خاطئ عند تفعيل وظيفة +title: إدراك المعطيات (Arguments) المارة بترتيب خاطئ عند تفعيل وظيفة challengeType: 1 forumTopicId: 301184 dashedName: catch-arguments-passed-in-the-wrong-order-when-calling-a-function @@ -8,7 +8,7 @@ dashedName: catch-arguments-passed-in-the-wrong-order-when-calling-a-function # --description-- -متابعة للمناقشة حول تفعيل الوظائف (functions)، الخطأ التالي الذي يجب مراقبته هو عندما يتم تقديم الوسائط الوظيفة (function's arguments) بالترتيب غير الصحيح. إذا كانت الوسائط (arguments) مختلفة الأنواع، مثل الوظيفة (function) التي تتوقع قائمة (array) وعدد صحيح، فمن المرجح أن يؤدي ذلك إلى خطأ في وقت التشغيل. إذا كانت الـ arguments هي من نفس النوع (كلها أعداد، على سبيل المثال)، فلن يكون لمنطق الكود أي معنى. تأكد من تقديم جميع الـ arguments المطلوبة، بالترتيب الصحيح لتجنب هذه المشاكل. +متابعة للمناقشة حول تفعيل الوظائف (functions)، الخطأ التالي الذي يجب مراقبته هو عندما يقدم الوسائط (arguments) الوظيفة بالترتيب غير الصحيح. إذا كانت المعطيات (arguments) مختلفة الأنواع، مثل الوظيفة (function) التي تتوقع قائمة (array) وعدد صحيح، فمن المرجح أن يؤدي ذلك إلى خطأ في وقت التفعيل. إذا كانت المعطيات (arguments) من نفس النوع (كلها أعداد، على سبيل المثال)، فلن يكون لمنطق الكود أي معنى. تأكد من تقديم جميع المعطيات (arguments) المطلوبة، بالترتيب الصحيح لتجنب هذه المشاكل. # --instructions-- @@ -22,7 +22,7 @@ dashedName: catch-arguments-passed-in-the-wrong-order-when-calling-a-function assert(power == 8); ``` -يجب أن يستخدم كودك الترتيب الصحيح لوسائط (arguments) لتفعيل الوظيفة (funciton) مسمى `raiseToPower`. +يجب أن يستخدم كودك الترتيب الصحيح لمعطيات (arguments) لتفعيل الوظيفة (funciton) المسمى `raiseToPower`. ```js assert(code.match(/raiseToPower\(\s*?base\s*?,\s*?exp\s*?\);/g)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-missing-open-and-closing-parenthesis-after-a-function-call.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-missing-open-and-closing-parenthesis-after-a-function-call.md index 949c1485a9dcca..29385b2317add7 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-missing-open-and-closing-parenthesis-after-a-function-call.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-missing-open-and-closing-parenthesis-after-a-function-call.md @@ -8,7 +8,7 @@ dashedName: catch-missing-open-and-closing-parenthesis-after-a-function-call # --description-- -عندما لا تأخذ الوظيفة (function) أو الطريقة (method) أي وسائط (arguments)، قد تنسى إدراج أقواس الفتح والإغلاق (فارغة) عند تفعيلها. غالباً ما يتم حفظ نتيجة تفعيل وظيفة (function) في متغير (variable) لاستخدام آخر في كودك. يمكن اكتشاف هذا الخطأ عن طريق تسجيل قيم المتغيرات (variables) (أو أنواعها) إلى الوحدة (console) وملاحظة أن القيمة المعينة للمتغير (variable) هي مرجع وظيفة (function reference)، بدلاً من القيمة المتوقعة وهي ناتج تنفيذ الوظيفة (function). +عندما لا تأخذ الوظيفة (function) أو الطريقة (method) أي معطيات (arguments)، قد تنسى إدراج أقواس الفتح والإغلاق (فارغة) عند تفعيلها. غالباً ما يتم حفظ نتيجة تفعيل وظيفة (function) في متغير (variable) لاستخدام آخر في كودك. يمكن اكتشاف هذا الخطأ عن طريق تسجيل قيم المتغيرات (variables) (أو أنواعها) إلى الوحدة (console) وملاحظة أن القيمة المعينة للمتغير (variable) هي مرجع وظيفة (function reference)، بدلاً من القيمة المتوقعة وهي ناتج تنفيذ الوظيفة (function). فتختلف المتغيرات الواردة في المثال التالي: diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-misspelled-variable-and-function-names.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-misspelled-variable-and-function-names.md index 5a4692222eb530..5cae5df96ed1b9 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-misspelled-variable-and-function-names.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-misspelled-variable-and-function-names.md @@ -30,7 +30,7 @@ assert(netWorkingCapital === 2); assert(!code.match(/recievables/g)); ``` -يجب تعريف متغير باسم `receivables` واستخدامه بشكل صحيح في الكود. +يجب إعلان متغير باسم `receivables` واستخدامه بشكل صحيح في الكود. ```js assert(code.match(/receivables/g).length == 2); @@ -42,7 +42,7 @@ assert(code.match(/receivables/g).length == 2); assert(!code.match(/payable;/g)); ``` -يجب تعريف متغير باسم `payables` واستخدامه بشكل صحيح في الكود. +يجب إعلان متغير باسم `payables` واستخدامه بشكل صحيح في الكود. ```js assert(code.match(/payables/g).length == 2); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-mixed-usage-of-single-and-double-quotes.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-mixed-usage-of-single-and-double-quotes.md index 2fe24359cce32d..d465c87026535d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-mixed-usage-of-single-and-double-quotes.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-mixed-usage-of-single-and-double-quotes.md @@ -1,6 +1,6 @@ --- id: 587d7b84367417b2b2512b37 -title: إدراك الاستخدام المختلط لعلامات التنصيص الفردية والزوجية (Catch Mixed Usage of Single and Double Quotes) +title: إدراك الاستخدام المختلط لعلامات التنصيص الفردية والزوجية challengeType: 1 forumTopicId: 301188 dashedName: catch-mixed-usage-of-single-and-double-quotes @@ -8,9 +8,9 @@ dashedName: catch-mixed-usage-of-single-and-double-quotes # --description-- -يسمح JavaScript باستخدام كلا علامات التنصيص، الفردية (`'`) والزوجية (`"`) لتعريف مقطع. انتقاء أحد الخيارين هو تفضيل شخصي، مع بعض الاستثناءات. +يسمح JavaScript باستخدام كلا علامات التنصيص، الفردية (`'`) والزوجية (`"`) لإعلان المقطع النصي (string). انتقاء أحد الخيارين هو تفضيل شخصي، مع بعض الاستثناءات. -وجدود الخيارين مجدٍ عندما يحوي المقطع اختصارات أو نص آخر داخل علامات تنصيص. فقط كن حذراً من إغلاق المقطع مبكراً، مما يسبب خطأ في تركيب الجملة. +وجدود الخيارين مجدٍ عندما يحوي المقطع النصي اختصارات أو نص آخر داخل علامات تنصيص. فقط كن حذراً من إغلاق المقطع مبكراً، مما يسبب خطأ في تركيب الجملة. فيما يلي بعض الأمثلة على خلط علامات التنصيص: @@ -22,7 +22,7 @@ const uhOhGroucho = 'I've had a perfectly wonderful evening, but this wasn't it. أما الاثنان الأولان فهما صحيحان، ولكن الثالث غير صحيح. -وبطبيعة الحال، لا بأس من الاستمرار على نوع واحد من علامات التنصيص. يمكنك التعامل مع علامات التنصيص داخل المقطع باستخدام رمز التحايل (`\`): +وبطبيعة الحال، لا بأس من الاستمرار على نوع واحد من علامات التنصيص. يمكنك التعامل مع علامات التنصيص داخل المقطع النصي باستخدام رمز التخريج (`\`): ```js const allSameQuotes = 'I\'ve had a perfectly wonderful evening, but this wasn\'t it.'; @@ -30,11 +30,11 @@ const allSameQuotes = 'I\'ve had a perfectly wonderful evening, but this wasn\'t # --instructions-- -أصلح المقطع بحيث يستخدم علامات تنصيص مختلفة لقيمة `href` أو تحايل على علامات التنصيص الموجودة. حافظ على علامات التنصيص المزدوجة حول المقطع كُلََّه. +أصلح المقطع النصي بحيث يستخدم علامات تنصيص مختلفة لقيمة `href` أو أخرج علامات التنصيص الموجودة. حافظ على علامات التنصيص المزدوجة حول المقطع كُلََّه. # --hints-- -يجب أن يصلح الكود الخاص بك علامات التنصيص حول قيمة `href` وهي `#Home` إما بتغييرها أو معالجتها برمز التحايل (\). +يجب أن يصلح الكود الخاص بك علامات التنصيص حول قيمة `href` وهي `#Home` إما بتغييرها أو معالجتها برمز التخريج (\). ```js assert(code.match(//g)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-unclosed-parentheses-brackets-braces-and-quotes.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-unclosed-parentheses-brackets-braces-and-quotes.md index 78f9424726d690..5f122ece22fc81 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-unclosed-parentheses-brackets-braces-and-quotes.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-unclosed-parentheses-brackets-braces-and-quotes.md @@ -1,6 +1,6 @@ --- id: 587d7b84367417b2b2512b36 -title: 'التقاط الاقواس و الاقتباسات الغير مغلقة (Catch Unclosed Parentheses, Brackets, Braces and Quotes)' +title: 'التقاط الاقواس و الاقتباسات الغير مغلقة' challengeType: 1 forumTopicId: 301190 dashedName: catch-unclosed-parentheses-brackets-braces-and-quotes @@ -8,7 +8,7 @@ dashedName: catch-unclosed-parentheses-brackets-braces-and-quotes # --description-- -يجب أن تكون على علم بخطأ آخر في بناء الجملة, هو أن جميع الأقواس الافتتاحية، والأقواس المعقوفة، والاقتباسات تحتوي على زوج إقفال. يحدث نسيان قطعة ما عندما تحرير كود موجود وإدخال عناصر بأحد أنواع الأزواج. أيضًا، كن حذرًا عند دمج مجموعة الكود في أخري، مثل إضافة وظيفة تعيد التفعيل كحجة إلى طريقة. +يجب أن تكون على علم بخطأ آخر في بناء الجملة, هو أن جميع الأقواس الافتتاحية، والأقواس المعكوفة، والاقتباسات تحتوي على زوج إقفال. يحدث نسيان قطعة ما عندما تحرير كود موجود وإدخال عناصر بأحد أنواع الأزواج. أيضًا، كن حذرًا عند دمج مجموعة الكود في أخري، مثل إضافة وظيفة تعيد التفعيل كحجة إلى طريقة. إحدى الطرق لتجنب هذا الخطأ هي بمجرد كتابة الرمز الافتتاحي، قم على الفور بكتابة رمز الإغلاق، ثم قم بتحريك المؤشر مرة أخرى بينهما، ثم استمر في البرمجة. لحسن الحظ، فإن معظم برامج تحرير الكود الحديثة تولد النصف الثاني من الزوج تلقائيًا. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-use-of-assignment-operator-instead-of-equality-operator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-use-of-assignment-operator-instead-of-equality-operator.md index ca6cc699cf2f8f..b5237232346032 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-use-of-assignment-operator-instead-of-equality-operator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/catch-use-of-assignment-operator-instead-of-equality-operator.md @@ -10,7 +10,7 @@ dashedName: catch-use-of-assignment-operator-instead-of-equality-operator البرامج المتفرعة، أي تلك الذي تقوم بأشياء مختلفة إذا تم الوفاء بشروط معينة، تعتمد على بيانات `if`, و `else if`, و `else` في JavaScript. يأخذ الشرط أحيانًا شكل اختبار ما إذا كانت النتيجة مساوية لقيمة. -هذا المنطق ينطق (باللغة الإنجليزية، على الأقل) كـ "... if x equals y, then" الذي يمكن ترجمته حرفيا إلى كود باستخدام `=` أو مشغل التعيين. هذا يؤدي إلى جعل برنامجك يعمل بشكل غير متوقع. +هذا المنطق ينطق (باللغة الإنجليزية، على الأقل) كـ "... if x equals y, then" الذي يمكن ترجمته حرفية إلى كود باستخدام `=` أو مشغل التعيين. هذا يؤدي إلى جعل برنامجك يعمل بشكل غير متوقع. كما تم تغطيته في التحديات السابقة، يقوم مشغل التعيين (`=`) في JavaScript بإسناد قيمة إلى اسم متغير. و يقوم المشغلون `==` و `===` بالتحقق من المساواة (الثلاثية `===` تتحقق من المساواة الصارمة بمعنى أن كل من القيمة والنوع يطبقان). diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/prevent-infinite-loops-with-a-valid-terminal-condition.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/prevent-infinite-loops-with-a-valid-terminal-condition.md index 153f9c94a4a92f..5bb8e3e75f0660 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/prevent-infinite-loops-with-a-valid-terminal-condition.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/debugging/prevent-infinite-loops-with-a-valid-terminal-condition.md @@ -10,7 +10,7 @@ dashedName: prevent-infinite-loops-with-a-valid-terminal-condition الموضوع الأخير هو الحلقة اللانهائية المخيفة (dreaded infinite loop). الحلقات التكرارية (loops) هي أدوات رائعة عندما يحتاج برنامجك لتشغيل كتلة الكود عدد معين من المرات أو حتى يتم الوفاء بشرط ما، ولكنها تحتاج إلى حالة نهائية تنهي التكرار. الحلقات اللانهائية (Infinite loops) من المحتمل أن تجمد أو تعطل المتصفح، وقد تسبب في فشل تنفيذ البرامج، وهو ما لا يريده أحد. -كان هناك مثال لحلقة لانهائية في مقدمة هذا القسم - لم يكن لديها أي شرط نهائي للخروج من حلقة `while` داخل `loopy()`. لا تستدعي هذه الوظيفة! +كان هناك مثال لحلقة لانهائية في مقدمة هذا القسم - لم يكن لديها أي شرط نهائي للخروج من حلقة `while` داخل `loopy()`. لا تفعيل تلك الوظيفة (function)! ```js function loopy() { @@ -24,7 +24,7 @@ function loopy() { # --instructions-- -تحتوي وظيفة `myFunc()` على حلقة لانهائية لأن حالة الشرط الانتهائي `i != 4` لن تقيّم أبدا إلى `false` (وتخرج من التكرار) - `i` سوف يزداد بمقدار 2 في كل تكرار، ويقفز فوق 4 حيث إن `i` عدد فردي من البداية. أصلح مشغل المقارنة (comparison operator) في حالة الشرط الانتهائي بحيث تعمل الحلقة فقط ل `i` بقيمة أقل من أو يساوي 4. +تحتوي وظيفة `myFunc()` على حلقة لانهائية لإن حالة الشرط الانتهائي `i != 4` لن تصبح `false` أبدا (وتخرج من التكرار) - سوف يزداد `i` بمقدار 2 في كل تكرار، ويقفز فوق 4 حيث إن `i` عدد فردي من البداية. أصلح مشغل المقارنة (comparison operator) في حالة الشرط الانتهائي بحيث تعمل الحلقة فقط ل `i` بقيمة أقل من أو يساوي 4. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords.md index e05082d8e40a15..42c9c370f03d59 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/compare-scopes-of-the-var-and-let-keywords.md @@ -10,9 +10,9 @@ dashedName: compare-scopes-of-the-var-and-let-keywords إذا كانت `let` غير مألوف، تحقق هذا التحدي عن أختلاف بين كلمة (let) وكلمة (var). -عندما تعلن متغير باستخدام كلمة `var`، يتم الإعلان عنه عالميًا (declared globally)، أو محليًا (locally) إذا تم الإعلان عنه داخل وظيفة. +عندما تعلن متغير باستخدام مصطلح `var`، يكون للمتغير مجال شامل (global scope)، أو إذا اعلن عنه داخل وظيفة (function) فمجاله محدد (local scope). -كلمة `let` تتصرف بالمثل، ولكن مع بعض الميزات الإضافية. عندما تعلن متغير باستخدام `let` داخل الكتلة أو تعبير أو عبارة، فنطاق المتغير يقتصر على تلك الكتلة (block) أو التعبير (statement) أو العبارة (expression). +يتصرف مصطلح `let` بالمثل، ولكن مع بعض الميزات الإضافية. عندما تعلن متغير باستخدام `let` داخل الكتلة أو تعبير أو عبارة، فنطاق المتغير يقتصر على تلك الكتلة (block) أو التعبير (statement) أو العبارة (expression). على سبيل المثال: @@ -27,7 +27,7 @@ console.log(i); هنا ستعرض وحدة التحكم القيم `[0, 1, 2]` و `3`. -مع كلمة `var`، يتم الإعلان عن `i` عالميا. لذلك عندما يتم تنفيذ `i++`، فإنه يحدث المتغير العالمي. وهذا الكود مماثل لما يلي: +مع مصطلح `var`، يعلن `i` بشكل شامل. لذلك عندما ينفذ `i++`، فإنه يحدث المتغير الشامل. وهذا الكود مماثل لما يلي: ```js var numArray = []; @@ -41,7 +41,7 @@ console.log(i); هنا ستعرض وحدة التحكم القيم `[0, 1, 2]` و `3`. -هذا السلوك سوف يسبب مشكلات إذا كنت تريد إنشاء وظيفة وتخزينها لاستخدامها لاحقاً داخل حلقة `for` تستخدم متغير `i`. هذا لأن الوظيفة المخزنة سوف تشير دائما إلى قيمة متغير `i` العالمي المحدث. +هذا السلوك سوف يسبب مشكلات إذا كنت تريد إنشاء وظيفة وتخزينها لاستخدامها لاحقاً داخل حلقة `for` تستخدم متغير `i`. هذا لأن الوظيفة المخزنة سوف تشير دائما إلى قيمة متغير `i` الشامل المحدث. ```js var printNumTwo; @@ -57,7 +57,7 @@ console.log(printNumTwo()); هنا ستعرض وحدة التحكم القيمة `3`. -كما تري، `printNumTwo()` يطبع 3 وليس 2. هذا لأن القيمة التي تم تعيينها إلى `i` تم تحديثها و `printNumTwo()` يرجع القيمة `i` العالمية وليس القيمة التي احتواها `i` عندما تم إنشاء الوظيفة في حلقة التكرار. لا تتبع كلمة `let` هذا السلوك: +كما تري، `printNumTwo()` يطبع 3 وليس 2. هذا لأن القيمة التي عينت إلى `i` تُحدث, وتنتج `printNumTwo()` القيمة الشاملة `i` وليس القيمة التي احتواها `i` عندما أنشئت الوظيفة في حلقة التكرار. لا تتبع مصطلح `let` هذا السلوك: ```js let printNumTwo; @@ -74,13 +74,13 @@ console.log(i); هنا ستعرض وحدة التحكم القيمة `2`، وخطأ `i is not defined`. -`i` غير معرف لأنه لم يتم إعلانه في النطاق العالمي (global scope). تم الإعلان عنه فقط ضمن حلقة `for`. أنتج `printNumTwo()` القيمة الصحيحة لأن ثلاث متغيرات `i` مختلفة مع قيم فريدة (0, 1, و 2) تم إنشاؤها بواسطة `let` داخل كود الحلقة التكرارية. +`i` غير معروف لأنه لم يعلن في المجال الشامل (global scope). اعلن عنه فقط ضمن حلقة `for`. أنتج `printNumTwo()` القيمة الصحيحة لأن ثلاث متغيرات `i` مختلفة مع قيم فريدة (0, 1, و 2) أنشئت بواسطة `let` داخل كود الحلقة التكرارية. # --instructions-- -أصلح الكود بحيث أن `i` المعلن عنها في `if` تصبح متغير منفصل عن `i` المعلن عنها في السطر الأول من الوظيفة. كن متأكدا من عدم استخدام كلمة `var` في أي مكان في الكود الخاص بك. +أصلح الكود بحيث إن `i` المعلن عنها في `if` تصبح متغير منفصل من `i` المعلن عنها في السطر الأول من الوظيفة. كن متيقن من عدم استخدام مصطلح `var` في أي مكان في كودك. -تم تصميم هذا التمرين لتوضيح الفرق بين كيفية تعيين الكلمات `var` و `let` نطاقًا للمتغير المعلن. عند برمجة وظيفة مماثلة لتلك المستخدمة في هذه الممارسة، كثيرا ما يكون من الأفضل استخدام أسماء مختلفة للمتغيرات لتجنب الخلط. +تم تصميم هذا التمرين لتوضيح الفرق بين كيفية تعيين المصطلحات `var` و `let` نطاقًا للمتغير المعلن. عند برمجة وظيفة مماثلة لتلك المستخدمة في هذه الممارسة، كثيرا ما يكون من الأفضل استخدام أسماء مختلفة للمتغيرات لتجنب الخلط. # --hints-- @@ -90,7 +90,7 @@ console.log(i); assert(!code.match(/var/g)); ``` -المتغير `i` المعلن عنه في `if` يجب أن يساوي المقطع `block scope`. +يجب أن يساوي المتغير `i` المعلن عنه في `if` المقطع النصي `block scope`. ```js assert(code.match(/(i\s*=\s*).*\s*.*\s*.*\1('|")block\s*scope\2/g)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject.md index 24b7297917bdc4..489ce5d455253f 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/complete-a-promise-with-resolve-and-reject.md @@ -8,7 +8,7 @@ dashedName: complete-a-promise-with-resolve-and-reject # --description-- -يكون للوعد (promise) ثلاث حالات: `pending`, و `fulfilled`, و `rejected`. كائن Promise الذي قمت بإنشائه في التحدي السابق معلق إلى الأبد في حالة `pending` لأنك لم تضف طريقة لإكمال كائن Promise. حجج `resolve` و `reject` المعطاة لوظفية الكائن promise تستخدم لفعل ذلك. تستخدم `resolve` عندما تريد أن ينجح الكائن promise وتستخدم `reject` عندما تريد أن يفشل الكائن promise. هذا الطرق تستقبل حَجَّة (argument)، كما هو مبين بالإدانة. +يكون للوعد (promise) ثلاث حالات: `pending`, و `fulfilled`, و `rejected`. كائن Promise الذي قمت بإنشائه في التحدي السابق معلق إلى الأبد في حالة `pending` لأنك لم تضف طريقة لإكمال كائن Promise. تستخدم الوسائط `resolve` و `reject` المعطى promise لفعل ذلك. تستخدم `resolve` عندما تريد أن ينجح الكائن promise وتستخدم `reject` عندما تريد أن يفشل الكائن promise. هذا الطرق تستقبل معطى (argument)، كما هو مبين بالإدانة. ```js const myPromise = new Promise((resolve, reject) => { @@ -20,11 +20,11 @@ const myPromise = new Promise((resolve, reject) => { }); ``` -المثال الوارد أعلاه يستخدم مقاطع (strings) نصية كحَجَّة (argument) لهذه الوظائف (functions)، ولكن يمكن أن تكون أي شيء حقا. في كثير من الأحيان، قد يكون كائناً، يمكنك استخدام البيانات منه، لوضع البيانات على موقعك أو في أي مكان آخر. +المثال الوارد أعلاه يستخدم مقاطع (strings) نصية كمعطى (argument) لهذه الوظائف (functions)، ولكن يمكن أن تكون أي شيء حقا. في كثير من الأحيان، قد يكون كائناً، يمكنك استخدام البيانات منه، لوضع البيانات على موقعك أو في أي مكان آخر. # --instructions-- -اجعل كائن promise يتعامل مع النجاح والفشل. إذا كان `responseFromServer` صحيحاً `true`، فاستدعي طريقة `resolve` لإكمال كائن promisie بنجاح. مرر `resolve` إلى سلسلة (string) نصية بقيمة `We got the data`. إذا كان `responseFromServer` بـ `false`، استخدم دالة `reject` كبديل و مرر اليها الـ string الآتي: `Data not received`. +اجعل كائن promise يتعامل مع النجاح والفشل. إذا كان `responseFromServer` صحيحاً `true`، ففعيل طريقة `resolve` لإكمال كائن promise بنجاح. مرر `resolve` مقطع نصي بقيمة `We got the data`. إذا كانت حالة `responseFromServer` بقيمة `false`، استخدم طريقة `reject` كبديل و مررها المقطع النصي (string) الآتي: `Data not received`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-a-javascript-promise.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-a-javascript-promise.md index 730db3bdcdaa98..f0d03e09830a32 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-a-javascript-promise.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-a-javascript-promise.md @@ -8,7 +8,7 @@ dashedName: create-a-javascript-promise # --description-- -الوعد (promise) في لغة JavaScript هو التوعد بالقيام بشيء ما، عادة بشكل غير متزامن. وعندما تنتهي المهمة، إما أن تفي بالوعد أو أن تخفق في ذلك. يكون `Promise` منشئ للوظيفة، لذا تحتاج إلى استخدام كلمة `new` لإنشاء واحد. إنه يأخذ وظيفة (كحجة) مع حجتين - `resolve` و `reject`. وهذه هي الطرق المستخدمة لتحديد نتيجة الوعد. يبدو بناء الجملة كهذا: +الوعد (promise) في لغة JavaScript هو التوعد بالقيام بشيء ما، عادة بشكل غير متزامن. وعندما تنتهي المهمة، إما أن تفي بالوعد أو أن تخفق في ذلك. يكون `Promise` منشئ للوظيفة، لذا تحتاج إلى استخدام كلمة `new` لإنشاء واحد. إنه يأخذ وظيفة (function) كمعطى, مع وسيطين (parameters) يسمان - `resolve` و `reject`. وهذه هي الطرق المستخدمة لتحديد نتيجة الوعد. يبدو بناء الجملة كهذا: ```js const myPromise = new Promise((resolve, reject) => { @@ -18,17 +18,17 @@ const myPromise = new Promise((resolve, reject) => { # --instructions-- -قم بإنشاء وعد جديد يسمى `makeServerRequest`. قم بتمرير وظيفة بحجج `resolve` و `reject` ألى المنشئ (constructor). +قم بإنشاء وعد جديد يسمى `makeServerRequest`. اعطي وظيفة مع الوسائط `resolve` و `reject` إلى المنشئ (constructor). # --hints-- -يجب عليك تعيين وعد إلى متغير معرف اسمه `makeServerRequest`. +يجب عليك تخصص وعد (promise) إلى متغير المعلن اسمه `makeServerRequest`. ```js assert(makeServerRequest instanceof Promise); ``` -يجب أن يتلقى الوعد الخاص بك الوظيفة مع `resolve` و `reject` كحجج. +يجب أن يتلقى وعدك (promise) وظيفة مع `resolve` و `reject` كوسائط. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default.md index 017f682dad29e7..dbe392ddf582c1 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-an-export-fallback-with-export-default.md @@ -26,11 +26,11 @@ export default function(x, y) { الأول هو named function، والثاني هو anonymous function. -بما أن `export default` يستخدم لتعريف قيمة احتياطية لـ module أو ملف، يمكن أن يكون لديك قيمة واحدة فقط هي الـ default export في كل module أو ملف. بالإضافة إلى ذلك، لا يمكنك استخدام `export default` مع `var` أو `let` أو `const` +لما كان `export default` يستخدم لإعلان القيمة الاحتياطية لـ module أو ملف، يمكن أن يكون لديك قيمة واحدة فقط هي الـ default export في كل module أو ملف. بالإضافة إلى ذلك، لا يمكنك استخدام `export default` مع `var` أو `let` أو `const` # --instructions-- -الدالة التالية يجب أن تكون القيمة الاحتياطية للـ module. الرجاء إضافة الكود اللازم للقيام بذلك. +الوظيفة التالية يجب أن تكون القيمة الاحتياطية للـ module. الرجاء إضافة الكود اللازم للقيام بذلك. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-strings-using-template-literals.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-strings-using-template-literals.md index 8231fc497e44df..7888fc820cc37b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-strings-using-template-literals.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/create-strings-using-template-literals.md @@ -1,6 +1,6 @@ --- id: 587d7b8a367417b2b2512b4e -title: Create Strings using Template Literals +title: إنشاء المقاطع النصية باستخدام قوالب النصوص challengeType: 1 forumTopicId: 301200 dashedName: create-strings-using-template-literals @@ -28,7 +28,7 @@ console.log(greeting); ستعرض وحدة التحكم السلاسل `Hello, my name is Zodiac Hasbro!` و `I am 56 years old.`. -لقد حدث الكثير من الأشياء هنا. أولاً، يستخدم المثال الـ backticks الآتية (`` ` ``)، وليس علامات الاقتباس (`'` أو `"`) لاحتواء الـ string. ثانياً، لاحظ أن الـ string متعدد الأسطر في كل من الكود والناتج. هذا يوفر من إدخال `\n` داخل الـ strings. بناء الجملة `${variable}` المستخدم أعلاه هو placeholder. بشكل أساسي، لن تضطر إلى استخدام التسلسل مع عامل التشغيل `+` بعد الآن. لإضافة متغيرات إلى الـ strings، فقط قم بإسقاط المتغير في template string و حاوطه بـ `${` و `}`. وبالمثل، يمكنك تضمين عبارات أخرى في الـ string literal، على سبيل المثال `${a + b}`. هذه الطريقة الجديدة لإنشاء الـ strings تمنحك المزيد من المرونة لإنشاء strings قوية. +لقد حدث الكثير من الأشياء هنا. أولاً، يستخدم المثال الـ backticks الآتية (`` ` ``)، وليس علامات الاقتباس (`'` أو `"`) لاحتواء المقطع النصي. ثانياً، لاحظ أن الـ string متعدد الأسطر في كل من الكود والناتج. هذا يوفر من إدخال `\n` داخل الـ strings. بناء الجملة `${variable}` المستخدم أعلاه هو placeholder. بشكل أساسي، لن تضطر إلى استخدام التسلسل مع عامل التشغيل `+` بعد الآن. لإضافة متغيرات إلى الـ strings، فقط قم بإسقاط المتغير في template string و حاوطه بـ `${` و `}`. وبالمثل، يمكنك تضمين عبارات أخرى في الـ string literal، على سبيل المثال `${a + b}`. هذه الطريقة الجديدة لإنشاء الـ strings تمنحك المزيد من المرونة لإنشاء strings قوية. # --instructions-- @@ -66,7 +66,7 @@ assert( ); ``` -وينبغي استخدام Template strings و expression interpolation. +وينبغي استخدام template strings و expression interpolation. ```js (getUserInput) => assert(getUserInput('index').match(/(`.*\${.*}.*`)/)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then.md index 79d390ccb4af83..bde0d10a5cff38 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/handle-a-fulfilled-promise-with-then.md @@ -20,7 +20,7 @@ myPromise.then(result => { # --instructions-- -أضف method الـ `then` إلى الـ promise الخاص بك. استخدم `result` كمعلمة لـ callback function واخرج الـ `result` إلى وحدة التحكم. +أضف method الـ `then` إلى الـ promise الخاص بك. استخدم `result` كوسيط لوظيفة تعيد تفعيلها وسجل قيمة `result` في وحدة التحكم (console). # --hints-- @@ -32,7 +32,7 @@ assert( ); ``` -يجب أن تكون لـ method الـ `then` الـ callback function مع `result` كمعلمتها (parameter). +يجب أن تكون لطريقة (method) المسمى `then` الوظيفة تعيد تفعيلها (callback function) مع `result` كوسيط (parameter). ```js assert(resultIsParameter); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.md index 1a668f8e2ee093..33cf40190b7280 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/handle-a-rejected-promise-with-catch.md @@ -20,7 +20,7 @@ myPromise.catch(error => { # --instructions-- -أضف method الـ `catch` إلى الـ promise الخاص بك. استخدم `error` كمعلمة لـ callback function واخرج الـ `error` إلى وحدة التحكم. +أضف method الـ `catch` إلى الـ promise الخاص بك. استخدم `error` كوسيط لوظيفة تعيد تفعيلها وسجل `error` في وحدة التحكم (console). # --hints-- @@ -32,7 +32,7 @@ assert( ); ``` -يجب أن تكون لـ method الـ `catch` الـ callback function مع `error` كمعلمتها (parameter). +يجب أن تكون لطريقة (method) المسمى `catch` الوظيفة تعيد تفعيلها (callback function) مع `error` كوسيطها (parameter). ```js assert(errorIsParameter); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const.md index 5fac37f460b143..0b0b0eb506376a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/mutate-an-array-declared-with-const.md @@ -1,6 +1,6 @@ --- id: 587d7b87367417b2b2512b42 -title: Mutate an Array Declared with const +title: تغير القائمة (array) المعلنة عند استخدام const challengeType: 1 forumTopicId: 301206 dashedName: mutate-an-array-declared-with-const @@ -8,13 +8,13 @@ dashedName: mutate-an-array-declared-with-const # --description-- -إذا كنت غير مألوفة مع `const`، تحقق من هذا التحدي حول كلمة const الثابتة. +إذا كنت غير مألوفة مع `const`، تحقق من هذا التحدي حول مصطلح const. -يحتوي تعريف `const` على العديد من حالات الاستخدام في JavaScript الحديثة. +يحتوي إعلان `const` على العديد من حالات الاستخدام في JavaScript الحديثة. بعض المطورين يفضلون تعيين جميع متغيراتهم باستخدام `const` بشكل افتراضي، ما لم يعلموا أنهم سيحتاجون إلى إعادة تعيين القيمة. فقط في تلك الحالة، يستخدمون `let`. -ومع ذلك، من المهم أن نفهم أن الـ objects (بما في ذلك arrays و functions) المخصصة للمتغير باستخدام `const` لا تزال قابلة للتغيير. استخدام تعريف `const` يمنع فقط إعادة تعيين معرف المتغير. +ومع ذلك، من المهم أن نفهم أن الـ objects (بما في ذلك arrays و functions) المخصصة للمتغير باستخدام `const` لا تزال قابلة للتغيير. استخدام إعلان `const` يمنع فقط إعادة تخصص هوية للمتغير. ```js const s = [5, 6, 7]; @@ -29,7 +29,7 @@ console.log(s); # --instructions-- -الـ array معرفة كـ `const s = [5, 7, 2]`. قم بتغيير الـ array إلى `[2, 5, 7]` باستخدام تعيينات العناصر المتنوعة. +تعلن القائمة (array) كالآتي `const s = [5, 7, 2]`. قم بتغيير الـ array إلى `[2, 5, 7]` باستخدام تعيينات العناصر المتنوعة. # --hints-- @@ -45,7 +45,7 @@ console.log(s); (getUserInput) => assert(getUserInput('index').match(/const\s+s/g)); ``` -لا يجب عليك تغيير تعريف الـ array الأصلي. +لا يجب عليك تغيير إعلان القائمة (array) الأصلي. ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/prevent-object-mutation.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/prevent-object-mutation.md index 098e5c5a3c338a..18fbae41e4a35e 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/prevent-object-mutation.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/prevent-object-mutation.md @@ -8,7 +8,7 @@ dashedName: prevent-object-mutation # --description-- -كما رأينا في التحدي السابق، استخدام `const` وحده لا يحمي بياناتك من امكانية تغييرها. لضمان عدم تغيير بياناتك، توفر JavaScript وظيفة `Object.freeze` لمنع تغيير البيانات. +كما رأينا في التحدي السابق، إعلان `const` وحده لا يحمي بياناتك من إمكانية تغييرها. لضمان عدم تغيير بياناتك، توفر JavaScript وظيفة `Object.freeze` لمنع تغيير البيانات. سيتم رفض أي محاولة لتغيير الـ object، مع اظهار خطأ إذا كان السكريبت يعمل في strict mode. @@ -44,7 +44,7 @@ console.log(obj); assert(getUserInput('index').match(/const\s+MATH_CONSTANTS/g)); ``` -لا يجب عليك تغيير التعريف الأصلي لـ `MATH_CONSTANTS`. +لا يجب عليك تغيير الإعلان الأصلي لـ `MATH_CONSTANTS`. ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/reuse-javascript-code-using-import.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/reuse-javascript-code-using-import.md index b82f70a7ae6f25..9736be2f19e545 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/reuse-javascript-code-using-import.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/reuse-javascript-code-using-import.md @@ -14,7 +14,7 @@ dashedName: reuse-javascript-code-using-import import { add } from './math_functions.js'; ``` -هنا ، `import` سوف تجد `add` في `math_functions.js`، قم باستيراد هذه الدالة فقط لاستخدامها، وتجاهل البقية. الكود `./` يخبر الـ import بالبحث عن ملف `math_functions.js` في نفس المجلد مثل الملف الحالي. مسار الملف النسبي (`./`) وملحق الملف (`.js`) مطلوبين عند استخدام الاستيراد بهذه الطريقة. +هنا ، `import` سوف تجد `add` في `math_functions.js`، قم باستيراد هذه الوظيفة فقط لاستخدامها، وتجاهل البقية. الكود `./` يخبر الـ import بالبحث عن ملف `math_functions.js` في نفس المجلد مثل الملف الحالي. مسار الملف النسبي (`./`) وملحق الملف (`.js`) مطلوبين عند استخدام الاستيراد بهذه الطريقة. يمكنك استيراد أكثر من عنصر واحد من الملف عن طريق إضافته في بيان `import` مثل هذا: @@ -24,7 +24,7 @@ import { add, subtract } from './math_functions.js'; # --instructions-- -أضف بيان `import` المناسب الذي سيسمح للملف الحالي باستخدام الدوال `uppercaseString` و `lowercaseString` التي قمت بتصديرها في الدرس السابق. هذه الدوال موجودة في ملف يسمى `string_functions.js`، وهو في نفس المجلد مثل الملف الحالي. +أضف بيان `import` المناسب الذي سيسمح للملف الحالي باستخدام الوظائف `uppercaseString` و `lowercaseString` التي قمت بتصديرها في الدرس السابق. هذه الوظائف موجودة في ملف يسمى `string_functions.js`، وهو في نفس المجلد مثل الملف الحالي. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/set-default-parameters-for-your-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/set-default-parameters-for-your-functions.md index 910ecfb02ef6fb..62bf54416df70c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/set-default-parameters-for-your-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/set-default-parameters-for-your-functions.md @@ -21,7 +21,7 @@ console.log(greeting()); ستعرض وحدة التحكم الـ strings الآتية `Hello John` و `Hello Anonymous`. -يبدأ الـ default parameter في العمل عندما لا يتم تحديد الـ argument (عندما تكون undefined). كما ترون في المثال أعلاه، الـ parameter الآتي `name` سوف يتلقى القيمة الافتراضية `Anonymous` ، عندما لا تقدم قيمة للـ parameter. يمكنك إضافة القيم الافتراضية لاي عدد من الـ parameters كما تريد. +يبدأ الوسيط الافتراضي (default parameter) في العمل عندما لا يتم تحديد المعطى argument (عندما تكون undefined). كما ترون في المثال أعلاه، سوف يتلقى الوسيط (parameter) المسمى `name` الآتي القيمة الافتراضية `Anonymous`، عندما لا تقدم قيمة للوسيط. يمكنك إضافة القيم الافتراضية لأي عدد من الوسائط (parameters) كما تريد. # --instructions-- @@ -41,7 +41,7 @@ assert(increment(5, 2) === 7); assert(increment(5) === 6); ``` -قيمة الـ default parameter لـ `1` يجب استخدامها لـ `value`. +يجب استخدام قيمة `1` للوسائط الافتراضية (default parameter) في `value`. ```js assert(code.match(/value\s*=\s*1/g)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-arrow-functions-to-write-concise-anonymous-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-arrow-functions-to-write-concise-anonymous-functions.md index 0f42e31706bbd7..09e37c61eaa750 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-arrow-functions-to-write-concise-anonymous-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-arrow-functions-to-write-concise-anonymous-functions.md @@ -1,6 +1,6 @@ --- id: 587d7b87367417b2b2512b43 -title: استخدام Arrow Functions لكتابة الدوال المجهولة الموجزة (Use Arrow Functions to Write Concise Anonymous Functions) +title: استخدام Arrow Functions لكتابة الوظائف المجهولة الموجزة challengeType: 1 forumTopicId: 301211 dashedName: use-arrow-functions-to-write-concise-anonymous-functions diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-class-syntax-to-define-a-constructor-function.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-class-syntax-to-define-a-constructor-function.md index 2228503d757a53..9dba2c45ed46f9 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-class-syntax-to-define-a-constructor-function.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-class-syntax-to-define-a-constructor-function.md @@ -10,11 +10,9 @@ dashedName: use-class-syntax-to-define-a-constructor-function يوفر ES6 طريقة syntax جديدة لإنشاء objects، باستخدام كلمة class. -وتجدر الإشارة إلى أن syntax الـ `class` هو مجرد syntax وليس تنفيذًا كاملًا للـ class لنموذج البرمجة الشيئية (object-oriented)، على عكس لغات مثل Java و Python و Ruby ، إلخ. +في ES5، ينشئ كائن (object) عند تحدد وظيفة (function) يسمى `constructor` واستخدام مصطلح `new` لتمثيل كائن. -في ES5، ينشئ كائن (object) عند تحدد وظيفة (function) يسمى `constructor` واستخدام مصطلح `new` لتمثيل كائن (object). - -في ES6، يحتوي إعلان `class` على طريقة `constructor` التي يتم استدعاؤها مع مصطلح `new` جديدة. إذا لم يتم تعريف طريقة `constructor` بوضوح، فعندها يتم تعريفها ضمنيا دون أي حجج (arguments). +في ES6، يحتوي إعلان `class` على طريقة `constructor` التي تنفذ مع مصطلح `new` جديدة. إذا لم يتم تعريف طريقة `constructor` بوضوح، فعندها تعرّف ضمنيا دون أي معطيات (arguments). ```js // Explicit constructor @@ -43,21 +41,21 @@ const atlas = new Rocket(); atlas.launch(); ``` -وتجدر الإشارة إلى أن كلمة `class` تعرف function جديد، تمت إضافة الـ constructor إليه. يتم استدعاء هذا الـ constructor عندما يتم استدعاء `new` لإنشاء object جديد. +وتجدر الإشارة إلى أن كلمة `class` تعرف وظيفة جديد، تضاف المنشئ إليها. يستدعى هذا المنشئ عندما تنفيذ `new` لإنشاء كائن جديد. -**ملاحظة:** يجب أن تستخدم UpperCamelCase لاسماء الـ class في ES6، كما في `SpaceShuttle` المستخدمة أعلاه. +**ملاحظة:** يجب أن تستخدم UpperCamelCase لاسماء الفئات في ES6، كما في `SpaceShuttle` المستخدمة أعلاه. -Method الـ `constructor` هي method خاصة لإنشاء وتهيئة object تم إنشاؤه عن طريق class. سوف تتعلم المزيد عنها في قسم البرمجة الشيئية في شهادة خوارزميات جافا سكريبت وهياكل البيانات. +إن طريقة `constructor` خاصة لإنشاء وتهيئة كائن منشئ بواسطة فئة. سوف تتعلم المزيد عنها في قسم البرمجة الكائنية في شهادة خوارزميات JavaScript وهياكل البيانات. # --instructions-- -استخدم كلمة `class` واكتب `constructor` لإنشاء class الـ `Vegetable`. +استخدم مصطلح `class` واكتب `constructor` لإنشاء فئة `Vegetable`. -Class الـ `Vegetable` يتيح لك إنشاء vegetable object مع خاصية `name` والتي يتم تمريرها إلى الـ `constructor`. +تتيح فئة `Vegetable` لك إنشاء كائن vegetable مع خاصية `name` التي تمرر إلى الـ `constructor`. # --hints-- -`Vegetable` يجب أن تكون `class` مع method معرفة للـ `constructor`. +يجب أن تكون`Vegetable` بنوع `class` مع وظيفة `constructor` محددة. ```js assert( @@ -65,13 +63,13 @@ assert( ); ``` -يجب استخدام كلمة `class`. +يجب استخدام مصطلح `class`. ```js assert(code.match(/class/g)); ``` -`Vegetable` يجب أن يتم انشاء مثيل له. +يجب أن يمثل `Vegetable`. ```js assert(() => { @@ -80,7 +78,7 @@ assert(() => { }); ``` -`carrot.name` يجب أن يرجع `carrot`. +يجب أن ينتج `carrot.name` قيمة `carrot`. ```js assert(carrot.name == 'carrot'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters.md index e4d9dba87662bf..d07fda10ba0265 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters.md @@ -1,6 +1,6 @@ --- id: 587d7b8a367417b2b2512b4d -title: Use Destructuring Assignment to Pass an Object as a Function's Parameters +title: استخدام التعيين التركيبي (Destructuring Assignment) لإعطاء كائن كوسيط للوظائف challengeType: 1 forumTopicId: 301217 dashedName: use-destructuring-assignment-to-pass-an-object-as-a-functions-parameters @@ -27,7 +27,7 @@ const profileUpdate = ({ name, age, nationality, location }) => { } ``` -عندما يتم تمرير `profileData` إلى الـ function أعلاه، يتم تفصيص القيم من معلمة (parameter) الـ function لاستخدامها داخل الـ function. +عندما يتم تمرير `profileData` إلى الوظيفة (function) أعلاه، تفكيك القيم من وسيط (parameter) الوظيفة لاستخدامها داخل الوظيفة. # --instructions-- @@ -53,7 +53,7 @@ assert(half(stats) === 28.015); assert(__helpers.removeWhiteSpace(code).match(/half=\({\w+,\w+}\)/)); ``` -وينبغي استخدام Destructured parameter. +ينبغي استخدام وسيط التركيبي (Destructured parameter). ```js assert(!code.match(/stats\.max|stats\.min/)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements.md index 0881854a94975b..c6feacdc09443d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-destructuring-assignment-with-the-rest-parameter-to-reassign-array-elements.md @@ -1,7 +1,7 @@ --- id: 587d7b8a367417b2b2512b4c title: >- - Use Destructuring Assignment with the Rest Parameter to Reassign Array Elements + التفكيك عن طريق عناصر rest challengeType: 1 forumTopicId: 301218 dashedName: >- @@ -22,11 +22,11 @@ console.log(arr); ستعرض وحدة التحكم القيم `1, 2` و `[3, 4, 5, 7]`. -المتغيرات `a` و `b` تأخذ القيم الأولى والثانية من الـ array. بعد ذلك، بسبب وجود rest parameter، الـ `arr` يحصل على بقية القيم في شكل array. يعمل العنصر rest بشكل صحيح فقط كآخر متغير في القائمة. بمعني انه لا يمكنك استخدام rest parameter لالتقاط subarray (اي array فرعية) تترك العنصر الأخير من الـ array الأصلية. +المتغيرات `a` و `b` تأخذ القيم الأولى والثانية من الـ array. بعد ذلك، بسبب وجود الثلاثة نقاط التي تدعى rest، سوف يحصل المتغير `arr` على بقية القيم في شكل قائمة (array). يعمل العنصر rest بشكل صحيح فقط كآخر متغير في القائمة. بمعني، انه لا يمكنك استخدام rest للحصول على قائمة فرعية (subarray) التي لا تحتوي غلى العنصر الأخير من القائمة الأصلية. # --instructions-- -استخدام تشكيل مخرج للمعلومات (destructuring assignment) مع الحجة (parameter) الباقية لمحاكاة سلوك `Array.prototype.slice()`. يجب أن ينتج `removeFirstTwo()` قائمة فرعية (sub-array) من قائمة `list` الأصلية دون العنصرين الأولين. +استخدم تشكيل rest لتعيين التركبي (destructuring assignment) لمحاكاة سلوك `Array.prototype.slice()`. يجب أن ينتج `removeFirstTwo()` قائمة فرعية (sub-array) من قائمة `list` الأصلية دون العنصرين الأولين. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-export-to-share-a-code-block.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-export-to-share-a-code-block.md index 57b763166ed59c..97b51e624165e7 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-export-to-share-a-code-block.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-export-to-share-a-code-block.md @@ -8,7 +8,7 @@ dashedName: use-export-to-share-a-code-block # --description-- -تخيل مِلَفّ يسمى `math_functions.js` يحتوي على عدة وظائف (functions) ذات صلة بالعمليات الرياضية. واحد منها مخزن في متغير، `add`، والذي يأخذ رقمين ويعيد مجموعهم. تريد استخدام هذه الوظيفة في عدة ملفات من JavaScript المختلفة. من أجل مشاركتها مع هذه الملفات الأخرى، تحتاج أولاً الي ان تصدرها باستخدام `export`. +تخيل مِلَفّ يسمى `math_functions.js` يحتوي على عدة وظائف (functions) ذات صلة بالعمليات الرياضية. واحد منها مخزن في متغير، `add`، والذي يأخذ رقمين ويعيد مجموعهم. تريد أن تستخدم الوظيفة (function) في عدة ملفات JavaScript المختلفة. من أجل مشاركتها مع هذه الملفات الأخرى، تحتاج أولاً الي ان تصدرها باستخدام `export`. ```js export const add = (x, y) => { diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-getters-and-setters-to-control-access-to-an-object.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-getters-and-setters-to-control-access-to-an-object.md index aecb02a34bddc0..bfa407a3156589 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-getters-and-setters-to-control-access-to-an-object.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-getters-and-setters-to-control-access-to-an-object.md @@ -38,7 +38,7 @@ console.log(novel.writer); ستعرض وحدة التحكم السلسلتين strings باسم `anonymous` و `newAuthor`. -لاحظ الصيغة المستخدمة لاستدعاء getter و setter. حتى أنها لا تشبه الوظائف العادية. تعتبر الـ Getters و Setters مهمة لأنها تخفي تفاصيل التنفيذ الداخلية. +لاحظ الصيغة المستخدمة لاستدعاء getter و setter. حتى أنها لا تشبه الوظائف (functions) العادية. تعتبر الـ Getters و Setters مهمة لأنها تخفي تفاصيل التنفيذ الداخلية. **ملاحظة:** من المألوف أن يسبق اسم المتغير الخاص برمز underscore هيئته (`_`). ومع ذلك، فإن الرمز نفسه لا يجعل المتغير خاصًا. @@ -58,7 +58,7 @@ console.log(novel.writer); # --hints-- -`Thermostat` يجب أن يكون `class` مع وظيفة `constructor` محددة. +يجب أن يكون `Thermostat` بنوع `class` مع طريقة `constructor` محددة. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters.md index 2f8b50dcff908b..35f80e2f6c1462 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-the-rest-parameter-with-function-parameters.md @@ -1,6 +1,6 @@ --- id: 587d7b88367417b2b2512b47 -title: Use the Rest Parameter with Function Parameters +title: استخدام وسائط Rest مع وسائط الوظيفة challengeType: 1 forumTopicId: 301221 dashedName: use-the-rest-parameter-with-function-parameters @@ -8,7 +8,7 @@ dashedName: use-the-rest-parameter-with-function-parameters # --description-- -من أجل مساعدتنا في إنشاء functions أكثر مرونة، يوفر ES6 الـ rest parameters للـ function parameters. مع rest parameter، يمكنك إنشاء functions تأخذ عددا متغيرا من الـ arguments. يتم تخزين هذه الـ arguments في array يمكن الوصول إليها في وقت لاحق من داخل الـ function. +من أجل مساعدتنا في إنشاء وظائف (functions) أكثر مرونة، يوفر ES6 الوسائط rest للوسائط (parameters) الوظيفة. مع وسيط rest، يمكنك إنشاء وظائف تأخذ عددا متغيرا من المعطيات (arguments). يتم تخزين هذه الـ arguments في array يمكن الوصول إليها في وقت لاحق من داخل الـ function. تحقق من هذا الكود: @@ -22,11 +22,11 @@ console.log(howMany("string", null, [1, 2, 3], { })); ستعرض وحدة التحكم السلاسل `You have passed 3 arguments.` و `You have passed 4 arguments.`. -الـ rest parameter تزيل الحاجة إلى التحقق من array الـ `args` وتسمح لنا بتطبيق `map()` و `filter()` و `reduce()` على array المعلمات (parameters). +يزيل وسيط rest الحاجة إلى التحقق من القائمة (array) المسمى `args` وتسمح لك باستعمال `map()` و `filter()` و `reduce()` في وسائط القائمة. # --instructions-- -قم بتعديل الدالة `sum` باستخدام rest parameter بطريقة تجعل الدالة `sum` قادرة على أخذ أي عدد من الـ arguments وإرجاع مجموعها. +عدل وظيفة `sum` باستخدام وسيط rest بطريقة تجعل الوظيفة `sum` قادرة على أخذ أي عدد من المعطيات وإنتاج مجموعها. # --hints-- @@ -54,7 +54,7 @@ assert(sum(5) === 5); assert(sum() === 0); ``` -`sum` يجب أن يكون arrow function يستخدم rest parameter syntax الآتي (`...`) على معلمة `args`. +يجب أن تكون `sum` وظيفة السهم, التي تستخدم تشكيل وسيط rest الآتي (`...`) على وسيط `args`. ```js assert(__helpers.removeWhiteSpace(code).match(/sum=\(\.\.\.args\)=>/)); @@ -67,7 +67,11 @@ assert(__helpers.removeWhiteSpace(code).match(/sum=\(\.\.\.args\)=>/)); ```js const sum = (x, y, z) => { const args = [x, y, z]; - return args.reduce((a, b) => a + b, 0); + let total = 0; + for (let i = 0; i < args.length; i++) { + total += args[i]; + } + return total; } ``` @@ -75,6 +79,10 @@ const sum = (x, y, z) => { ```js const sum = (...args) => { - return args.reduce((a, b) => a + b, 0); + let total = 0; + for (let i = 0; i < args.length; i++) { + total += args[i]; + } + return total; } ``` diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-the-spread-operator-to-evaluate-arrays-in-place.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-the-spread-operator-to-evaluate-arrays-in-place.md index 373f3c0d440217..8fb930aa580c84 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-the-spread-operator-to-evaluate-arrays-in-place.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/use-the-spread-operator-to-evaluate-arrays-in-place.md @@ -8,7 +8,7 @@ dashedName: use-the-spread-operator-to-evaluate-arrays-in-place # --description-- -ES6 يقدم spread operator، والذي يسمح لنا بتوسيع الـ arrays وغيرها من التعبيرات في الأماكن التي يتوقع أن تكون فيها معلمات أو عناصر متعددة. +يقدم ES6 مشغل الانتشار (spread operator)، الذي يسمح لنا بتوسيع القوائم (arrays) وغيرها من العبارات في الأماكن التي يتوقع أن تكون فيها وسائط (parameters) أو عناصر متعددة. كود ES5 أدناه يستخدم `apply()` لحساب القيمة القصوى في الـ array: diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-arrow-functions-with-parameters.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-arrow-functions-with-parameters.md index c05c3287a32897..dccae5e24404b8 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-arrow-functions-with-parameters.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-arrow-functions-with-parameters.md @@ -1,6 +1,6 @@ --- id: 587d7b88367417b2b2512b44 -title: Write Arrow Functions with Parameters +title: أنشاء وظائف السهم (Arrow Functions) مع الوسائط challengeType: 1 forumTopicId: 301223 dashedName: write-arrow-functions-with-parameters @@ -17,7 +17,7 @@ doubler(4); `doubler(4)` سوف يعيد القيمة `8`. -إذا كان للـ arrow function معلمة واحدة، يمكن حذف الأقواس المرفقة بالمعلمة. +إذا كان للوظيفة السهم وسيط واحدة، يمكن حذف الأقواس المرفقة للوسيط. ```js const doubler = item => item * 2; @@ -41,16 +41,16 @@ multiplier(4, 2); يجب عليك استبدال كلمة `var`. ```js -(getUserInput) => assert(!getUserInput('index').match(/var/g)); +assert.notMatch(code, /var/g); ``` `myConcat` يجب أن يكون متغير ثابت (باستخدام `const`). ```js -(getUserInput) => assert(getUserInput('index').match(/const\s+myConcat/g)); +assert.match(code, /const\s+myConcat/g); ``` -`myConcat` يجب أن تكون arrow function مع معلمين (two parameters) +يجب أن تكون `myConcat` وظيفة السهم (arrow function) مع وسيطين (parameters) ```js assert( @@ -68,7 +68,7 @@ assert.deepEqual(myConcat([1, 2], [3, 4, 5]), [1, 2, 3, 4, 5]); لا ينبغي استخدام كلمة `function`. ```js -(getUserInput) => assert(!getUserInput('index').match(/function/g)); +assert.notMatch(code, /function/g); ``` # --seed-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.md index 8c7482db72450b..e89ca4ec57dab2 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-concise-declarative-functions-with-es6.md @@ -1,6 +1,6 @@ --- id: 587d7b8b367417b2b2512b50 -title: Write Concise Declarative Functions with ES6 +title: أكتب وظائف تعلين (Declarative Functions) واضحة في ES6 challengeType: 1 forumTopicId: 301224 dashedName: write-concise-declarative-functions-with-es6 @@ -42,7 +42,7 @@ const person = { (getUserInput) => assert(!code.match(/function/)); ``` -`setGear` يجب أن تكون declarative function. +يجب أن تكون `setGear` وظيفة معلنا (declarative function). ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-concise-object-literal-declarations-using-object-property-shorthand.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-concise-object-literal-declarations-using-object-property-shorthand.md index f1e88439605307..34f8eb6c31b0f5 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-concise-object-literal-declarations-using-object-property-shorthand.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/es6/write-concise-object-literal-declarations-using-object-property-shorthand.md @@ -1,6 +1,6 @@ --- id: 587d7b8a367417b2b2512b4f -title: Write Concise Object Literal Declarations Using Object Property Shorthand +title: أكتب إعلانات واضح للكائن (Object) باستعمال خاصية تختصر الكائن challengeType: 1 forumTopicId: 301225 dashedName: write-concise-object-literal-declarations-using-object-property-shorthand @@ -8,7 +8,7 @@ dashedName: write-concise-object-literal-declarations-using-object-property-shor # --description-- -يضيف ES6 بعض الدعم اللطيف لتعريف الـ objects بسهولة. +يضيف ES6 بعض الدعم اللطيف لتعريف الكائنات بسهولة. ضع في اعتبارك الكود التالي: @@ -27,7 +27,7 @@ const getMousePosition = (x, y) => ({ x, y }); # --instructions-- -قم باستخدام خاصية الـ object القصير مع object literals لإنشاء وإرجاع object بخصائص `name` و `age` و `gender`. +استخدم خاصية الكائن المختصرة مع حروف الكائن لإنشاء كائن بخصائص `name`, و `age`, و `gender`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.md index fd23d3ecfdb712..f4ecfcd7f327ca 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/avoid-mutations-and-side-effects-using-functional-programming.md @@ -8,13 +8,13 @@ dashedName: avoid-mutations-and-side-effects-using-functional-programming # --description-- -إذا لم تكتشف ذلك سلفًا، المشكلة في التحدي السابق كانت مع استدعاء `splice` في وظيفة `tabClose()`. لسوء الحظ، `splice` يغير القائمة (array) الأصلية التي تم استدعاء الوظيفة عليها، لذا ففي الاستدعاء الثاني لها استخدمت قائمة (array) معدلة، وأعطت نتائج غير متوقعة. +إذا لم تكتشف ذلك سلفًا، المشكلة في التحدي السابق كانت مع استدعاء `splice` في وظيفة `tabClose()`. لسوء الحظ، `splice` يغير القائمة (array) الأصلية التي فُعِل عليها، لذا التفعيل الثاني له استخدم القائمة (array) المعدلة، وأعطى نتائج غير متوقعة. -هذا مثال صغير لنمط أكبر بكثير- يمكنك استدعاء وظيفة (function) على متغير (variable)، قائمة (array)، أو كائن(object)، والوظيفة تغير المتغير أو شيء ما في الكائن. +هذا مثال صغير لنمط أكبر بكثير- يمكنك تفعيل وظيفة (function) للتأثير على متغير (variable)، أو قائمة (array)، أو كائن (object). وتغير الوظيفة المتغير أو شيء ما في الكائن. -وأحد المبادئ الأساسية للبرمجة الوظيفية هو عدم تغيير الأشياء. التغييرات تؤدي إلى أعطال. من الأسهل منع الأعطال علما بأن وظائفك (functions) لا تغير أي شيء، بما في ذلك حجج (arguments) الوظيفة أو أي متغير (variable) عام. +وأحد المبادئ الأساسية للبرمجة الوظيفية هو عدم تغيير الأشياء. التغييرات تؤدي إلى أعطال. من الأسهل منع الأعطال علما بأن وظائفك (functions) لا تغير أي شيء، بما في ذلك معطيات (arguments) الوظيفة أو أي متغير (variable) شامل. -المثال السابق لم يكن به أي عمليات معقدة ولكن دالة `splice` غيرت القائمة الأصلية، وأسفرت عن حدوث خطأ. +المثال السابق لم يكن به أي عمليات معقدة ولكن `splice` غيرت القائمة (array) الأصلية، وأسفرت عن حدوث خطأ. تذكر أنه في البرمجة الوظيفية، تغيير الأشياء يسمى طفرة mutation، وتسمى النتيجة تأثير جانبي side effect. من الناحية المثالية، يجب أن تكون الوظيفة خالصة (pure function)، مما يعني أنها لا تسبب أي تأثيرات جانبية. @@ -22,11 +22,11 @@ dashedName: avoid-mutations-and-side-effects-using-functional-programming # --instructions-- -اكتب التعليمات البرمجية للوظيفة `incrementer` حتي ترجع قيمة المتغير العام `fixedValue` بعد زيادة قيمته بواحد. +اكتب الكود للوظيفة `incrementer` حتي تنتج قيمة المتغير الشامل `fixedValue` بعد زيادة قيمته بواحد. # --hints-- -لا ينبغي للوظيفة `incrementer` أن تغير قيمة `fixedValue` (التي هي `4`). +لا ينبغي للوظيفة (function) مسمى `incrementer` أن تغير قيمة `fixedValue` (التي هي `4`). ```js incrementer(); @@ -40,7 +40,7 @@ const __newValue = incrementer(); assert(__newValue === 5); ``` -يجب أن تنتج الوظيفة `incrementer` قيمة استناداً إلى قيمة المتغير العام `fixedValue`. +يجب أن تنتج الوظيفة `incrementer` قيمة استناداً إلى قيمة المتغير الشامل `fixedValue`. ```js (function () { diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method.md index d51e0e10a2d753..c4730c8e76e7de 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/combine-an-array-into-a-string-using-the-join-method.md @@ -1,6 +1,6 @@ --- id: 587d7daa367417b2b2512b6c -title: Combine an Array into a String Using the join Method +title: دمج قائمة لإنتاج مقطع نصي باستخدام طريقة join challengeType: 1 forumTopicId: 18221 dashedName: combine-an-array-into-a-string-using-the-join-method diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype.md index 0f8981ffebfa39..824a00172da85f 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/implement-map-on-a-prototype.md @@ -1,6 +1,6 @@ --- id: 587d7b8f367417b2b2512b62 -title: تنفيذ دالة map على Prototype +title: تنفيذ طريقة map في Prototype challengeType: 1 forumTopicId: 301230 dashedName: implement-map-on-a-prototype @@ -8,22 +8,22 @@ dashedName: implement-map-on-a-prototype # --description-- -كما رأيتم من تطبيق `Array.prototype.map()`، أو `map()` من قبل، فدالة `map` ترجع array من نفس طول الـ array التي استُدعت الدالة عليها. وهي إلى ذلك لا تغير القائمة (array) الأصلية، مادام أن وظيفتها لإعادة التفعيل (callback function) لا تفعل ذلك. +كما رأيتم من تطبيق `Array.prototype.map()`، أو `map()` من قبل، فطريقة `map` تنتج قائمة (array) من نفس طول القائمة (array) التي تم تفعيل الطريقة (method) عليها. وهي إلى ذلك لا تغير القائمة (array) الأصلية، مادام أن وظيفتها لإعادة التفعيل (callback function) لا تفعل ذلك. -بمعنى آخر، `map` هي وظيفة خالصة (pure function)، ومخرجها يعتمد فقط على مدخلاتها. إضافةً إلى ذلك، فإنها تأخذ وظيفة أخرى كحجة (argument) لها. +بمعنى آخر، `map` هي وظيفة خالصة (pure function)، ومخرجها يعتمد فقط على مدخلاتها. إضافةً إلى ذلك، فإنها تأخذ وظيفة أخرى كمعطى (argument) لها. -قد تتعلم الكثير عن دالة `map` إذا قمت بتنفيذ الإصدار الخاص بك منها. من المستحسن أن تستخدم حلقات `for` التكرارية أو `Array.prototype.forEach()`. +قد تتعلم الكثير عن طريقة `map` إذا مارست نسختك منها. من المستحسن أن تستخدم حلقات `for` التكرارية أو `Array.prototype.forEach()`. # --instructions-- -اكتب `Array.prototype.myMap()` الخاص بك، والذي يجب أن يتصرف مثل `Array.prototype.map()`. يجب ألا تستخدم دالة `map` المدمجة. يمكن الوصول إلى مثيل (instance) `Array` في دالة `myMap` باستخدام `this`. +اكتب `Array.prototype.myMap()` الخاص بك، الذي يجب أن يقلد مثل `Array.prototype.map()`. يجب ألا تستخدم طريقة `map` مبنية داخلياً (built-in method). يمكن الوصول إلى مثيل (instance) `Array` في طريقة `myMap` باستخدام `this`. # --hints-- يجب أن يساوي `[23, 65, 98, 5, 13].myMap(item => item * 2)` قيمة `[46, 130, 196, 10, 26]`. ```js -const _test_s = [46, 130, 196, 10, 13]; +const _test_s = [23, 65, 98, 5, 13]; const _callback = item => item * 2; assert(JSON.stringify(_test_s.map(_callback)) === JSON.stringify(_test_s.myMap(_callback))); ``` @@ -36,7 +36,7 @@ const _callback = element => element.toUpperCase(); assert(JSON.stringify(_test_s.map(_callback)) === JSON.stringify(_test_s.myMap(_callback))); ``` -يجب أن ينتج `[1, 1, 2, 5, 2].myMap((element, index, array) => array[i + 1] || array[0])` قائمة `[1, 2, 5, 2, 1]`. +يجب أن ينتج `[1, 1, 2, 5, 2].myMap((element, index, array) => array[index + 1] || array[0])` قائمة `[1, 2, 5, 2, 1]`. ```js const _test_s = [1, 1, 2, 5, 2]; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application.md index e0b2991144190d..e642e513ccd642 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/introduction-to-currying-and-partial-application.md @@ -52,7 +52,7 @@ partialFn(10); // 13 # --instructions-- -املأ نص الدالة `add` بحيث تستخدم خاصية curry لإضافة المعلمات `x` و `y` و `z`. +املأ نص الوظيفة (function) المسمى `add` بحيث تستخدم خاصية curry لإضافة الوسائط (parameters) المسمى `x`, و `y`, و `z`. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming.md index 67c15cc66804db..cb50314acba5be 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/learn-about-functional-programming.md @@ -12,7 +12,7 @@ dashedName: learn-about-functional-programming تتعلق البرمجة الوظيفية (Functional) بما يلي: -1) وظائف منعزلة (Isolated functions) - لا تعتمد على حالة البرنامَج، الذي يشمل المتغيرات العامة (global) القابلة للتغيير +1) وظائف منعزلة (Isolated functions) - لا تعتمد على حالة البرنامَج، الذي يشمل المتغيرات الشاملة (global) القابلة للتغيير 2) الوظائف الخالصة (Pure functions) - نفس الإدخال يعطي دائمًا نفس الإخراج diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function.md index a5fc5dda0850b2..2ac83581024c20 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/pass-arguments-to-avoid-external-dependence-in-a-function.md @@ -10,9 +10,9 @@ dashedName: pass-arguments-to-avoid-external-dependence-in-a-function التحدي الأخير كان يقترب خطوة من مبادئ الـ functional programming، ولكن لا يزال هناك شيء مفقود. -لم نقم بتغيير قيمة المتغير الـ global، ولكن الدالة `incrementer` لن تعمل بدون وجود المتغير الـ global و هو `fixedValue`، هناك. +لم نقم بتغيير قيمة المتغير الشامل (global)، ولكن الوظيفة `incrementer` لن تعمل بدون وجود المتغير الـشامل و هو `fixedValue`، هناك. -وهناك مبدأ آخر للـ functional programming وهو تعريف تبعياتك بشكل صريح. هذا يعني إذا كان الـ function يعتمد على متغير أو object موجود، قم بتمرير هذا المتغير أو الـ object مباشرة إلى الـ function كـ argument. +وهناك مبدأ آخر للبرمجة الوظيفية (functional programming) وهو إعلان تبعياتك (dependencies) بشكل صريح. هذا يعني إذا كان الـ function يعتمد على متغير أو object موجود، قم بتمرير هذا المتغير أو الـ object مباشرة إلى الـ function كـ argument. وهناك عدة نتائج جيدة لهذا المبدأ. الـ function يصبح أسهل لاختباره، فأنت تعرف بالضبط المدخلات التي يتطلبها، ولن يعتمد على أي شيء آخر في برنامجك. @@ -22,7 +22,7 @@ dashedName: pass-arguments-to-avoid-external-dependence-in-a-function # --instructions-- -دعونا نقوم بتحديث دالة `incrementer` لنعرف بوضوح تبعياتها. +حدث وظيفة `incrementer` لتعلن بوضوح تبعياتها. اكتب دالة `incrementer` بحيث أنها تأخذ arguments، ثم ترجع نتيجة بعد زيادة القيمة بواحد. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions.md index 0a4d977b7cd86f..eb8a48ed65b64d 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions.md @@ -1,6 +1,6 @@ --- id: 587d7b8f367417b2b2512b60 -title: تعديل المتغيرات العالمية (Global Variables) لأخراجهم من الوظائف (Functions) +title: تعديل المتغيرات الشاملة (Global Variables) لأخراجهم من الوظائف (Functions) challengeType: 1 forumTopicId: 301235 dashedName: refactor-global-variables-out-of-functions @@ -12,7 +12,7 @@ dashedName: refactor-global-variables-out-of-functions 1) لا تغير متغير (variable) أو كائن (object) - أنشئ متغيرات و كائنات (objects) جديدة و منشئا من الوظيفة (function) إذا لزم الأمر. تلميح: باستخدام شيء مثل `const newArr = arrVar`، حيث `arrVar` هو array، سوف يقوم ببساطة بإنشاء مرجع إلى المتغير الحالي وليس نسخة. لذا فإن تغيير قيمة في `newArr` سيغير القيمة في `arrVar`. -2) تعريف وسائط الوظيفة (function parameters) - يعتمد حسابات داخل الوظيفة (function) فقط على الوسائط (arguments) التي تمر إلى الوظيفة (function)، ولاا تعتمد على أي كائن (object) أو متغير (variable) عام (global). +2) أعلن وسائط الوظيفة (function parameters) - تعتمد الحسابات داخل الوظيفة (function) فقط على المعطيات (arguments) التي تعطى إلى الوظيفة (function)، ولا تعتمد على أي كائن (object) أو متغير (variable) شامل (global). إن إضافة واحد إلى رقما ليس مثيراً جداً، ولكن يمكننا تطبيق هذه المبادئ عند العمل مع arrays أو objects أكثر تعقيداً. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice.md index ba53bbddab3b82..39f2c35a806c61 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/remove-elements-from-an-array-using-slice-instead-of-splice.md @@ -8,7 +8,7 @@ dashedName: remove-elements-from-an-array-using-slice-instead-of-splice # --description-- -من الانماط الشائعة أثناء العمل مع ال arrays هو عندما تريد إزالة العناصر والحفاظ على بقية الـ array. يقدم JavaScript طريقة `splice` للقيام بذلك، والتي تأخذ arguments لفهرس مكان بدء إزالة العناصر، ثم عدد العناصر المراد إزالتها. إذا لم يتم تقديم الـ argument الثانية، فالافتراضي هو إزالة العناصر حتي النهاية. ومع ذلك، فإن طريقة `splice` تغير الـ array الأصلية التي يتم استدعاؤها عليها. إليك مثال: +من الانماط الشائعة أثناء العمل مع ال arrays هو عندما تريد إزالة العناصر والحفاظ على بقية الـ array. يقدم JavaScript طريقة `splice` للقيام بذلك، التي تأخذ معطيات (arguments) رقم الترتيب المكان الذي تبدأ منه بإزالة العناصر، ثم عدد العناصر المراد إزالتها. إذا لم يقدم المعطي الثاني، فالافتراضي هو إزالة العناصر حتي النهاية. ومع ذلك، فإن طريقة `splice` تغير الـ array الأصلية التي يتم استدعاؤها عليها. إليك مثال: ```js const cities = ["Chicago", "Delhi", "Islamabad", "London", "Berlin"]; @@ -17,23 +17,23 @@ cities.splice(3, 1); هنا `splice` ترجع السلسلة `London` وتحذفها من cities array. `cities` سيكون لها القيمة `["Chicago", "Delhi", "Islamabad", "Berlin"]`. -وكما رأينا في التحدي الأخير، فإن طريقة `slice` لا تغير الـ array الأصلية، ولكن ترجع واحدة جديدة يمكن حفظها في متغير. تذكر أن طريقة `slice` تأخذ وسيطين (arguments) للفهارس لبدء الـ slice وإنهائه (النهاية غير مشمولة) ، وإرجاع هذه العناصر في array جديدة. ويساعد استخدام طريقة `slice` بدلاً من `splice` على تجنب أي تأثيرات جانبية تغير في الـ array. +وكما رأينا في التحدي الأخير، فإن طريقة `slice` لا تغير الـ array الأصلية، ولكن ترجع واحدة جديدة يمكن حفظها في متغير. تذكر أن طريقة `slice` تأخذ معطين لرقم الترتيب لبدء بتقسيم (slice) وإنهائه (النهاية غير مشمولة)، وأنتاج هذه العناصر في قائمة (array) جديدة. ويساعد استخدام طريقة `slice` بدلاً من `splice` على تجنب أي تأثيرات جانبية تغير في الـ array. # --instructions-- -أعّد كتابة الوظيفة `nonMutatingSplice` باستخدام `slice` بدلاً من `splice`. يجب أن يقصر طول مصفوفة `cities` المقدمة على 3، ويعيد array جديدة تحتوي على العناصر الثلاثة الأولى فقط. +أعّد كتابة الوظيفة `nonMutatingSplice` باستخدام `slice` بدلاً من `splice`. يجب أن يقصر طول القائمة `cities` المقدمة على 3، ويعيد array جديدة تحتوي على العناصر الثلاثة الأولى فقط. لا تغيّر القائمة (array) الأصلية المقدمة للوظيفة (function). # --hints-- -يجب أن يستخدم الكود الخاص بك دالة `slice`. +يجب أن يستخدم كودك طريقة `slice`. ```js assert(code.match(/\.slice/g)); ``` -يجب ألا يستخدم الكود الخاص بك دالة `splice`. +يجب ألا يستخدم كودك طريقة `splice`. ```js assert(!code.match(/\.?[\s\S]*?splice/g)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array.md index cc07df5eb51ffe..5be68a28d7674c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/return-a-sorted-array-without-changing-the-original-array.md @@ -1,6 +1,6 @@ --- id: 587d7da9367417b2b2512b6a -title: Return a Sorted Array Without Changing the Original Array +title: أرجع قائمة مفرزة دون تغير القائمة الأصلية challengeType: 1 forumTopicId: 301237 dashedName: return-a-sorted-array-without-changing-the-original-array @@ -8,15 +8,15 @@ dashedName: return-a-sorted-array-without-changing-the-original-array # --description-- -التأثير الجانبي لـ `sort` هو أنه يغير ترتيب العناصر في ال array الأصلية. وبعبارة أخرى، فإنه يغير ال array في مكانها. إحدى الطرق لتجنب ذلك هي أن تقوم أولاً بلزق array فارغة إلى ال array التي يتم فرزها (تذكر أن `slice` و `concat` تعيد array جديدة)، ثم قم بتشغيل `sort`. +التأثير الجانبي لطريقة `sort` هو أنخها تغير ترتيب العناصر في القائمة (array) الأصلية. وبعبارة أخرى، فإنه يغير ال array في مكانها. إحدى الطرق لتجنب ذلك هي أن تقوم أولاً بلزق array فارغة إلى ال array التي يتم فرزها (تذكر أن `slice` و `concat` تعيد array جديدة)، ثم قم بتشغيل `sort`. # --instructions-- -استخدم `sort` في الدالة `nonMutatingSort` لفرز عناصر array بالترتيب التصاعدي. يجب أن تعيد الدالة array جديدا، وليس تغيير متغير `globalArray`. +استخدم `sort` في الوظيفة `nonMutatingSort` لفرز عناصر array بالترتيب التصاعدي. يجب أن تعيد الوظيفة array جديدا، وليس تغيِّر متغير `globalArray`. # --hints-- -يجب أن يستخدم الكود الخاص بك دالة `sort`. +يجب أن يستخدم الكود الخاص بك طريقة `sort`. ```js assert(nonMutatingSort.toString().match(/\.sort/g)); @@ -37,26 +37,26 @@ assert( ); ``` -`nonMutatingSort(globalArray)` لا ينبغي أن تكون hard coded. +`nonMutatingSort(globalArray)` لا ينبغي أن تكون قيمها مثبتة (hard-coded). ```js assert(!nonMutatingSort.toString().match(/\[.*?[23569].*?\]/gs)); ``` -وينبغي أن تعيد الدالة array جديدا، وليس ال array التي تمرر إليها. +وينبغي أن تعيد الوظيفة array جديدا، وليس ال array التي أعطت ها. ```js assert(nonMutatingSort(globalArray) !== globalArray); ``` -`nonMutatingSort([1, 30, 4, 21, 100000])` يجب ان يعيد `[1, 4, 21, 30, 100000]`. +`nonMutatingSort([1, 30, 4, 21, 100000])` يجب ان تعيد `[1, 4, 21, 30, 100000]`. ```js assert(JSON.stringify(nonMutatingSort([1, 30, 4, 21, 100000])) === JSON.stringify([1, 4, 21, 30, 100000])) ``` -`nonMutatingSort([140000, 104, 99])` يجب ان يعيد `[99, 104, 140000]`. +`nonMutatingSort([140000, 104, 99])` يجب ان تعيد `[99, 104, 140000]`. ```js assert(JSON.stringify(nonMutatingSort([140000, 104, 99])) === diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/return-part-of-an-array-using-the-slice-method.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/return-part-of-an-array-using-the-slice-method.md index 8880fc4cc50c63..e4377dd2e60445 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/return-part-of-an-array-using-the-slice-method.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/return-part-of-an-array-using-the-slice-method.md @@ -21,7 +21,7 @@ const newArray = arr.slice(1, 3); # --instructions-- -استخدم طريقة `slice` في `sliceArray` لإرجاع جزء من مصفوفة `anim` بالنظر إلى مؤشري `beginSlice` و `endSlice`. يجب أن تعيد الدالة array. +استخدم طريقة `slice` في `sliceArray` لإرجاع جزء من مصفوفة `anim` بالنظر إلى مؤشري `beginSlice` و `endSlice`. يجب أن تعيد الوظيفة array. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology.md index 5fd8006a04a87e..9f665c14c610d9 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/understand-functional-programming-terminology.md @@ -10,7 +10,7 @@ dashedName: understand-functional-programming-terminology كان لدى فريق FCC تقلبات مزاجية ويريد الآن نوعين من الشاي: الشاي الأخضر والشاي الأسود. حقائق عامة: تقلبات مزاج العميل شائعة جدًا. -بهذه المعلومات، سنحتاج إلى مراجعة دالة `getTea` من التحدي الأخير للتعامل مع مختلف طلبات الشاي. يمكننا تعديل `getTea` لقبول function كمعلمة (parameter) لتكون قادرة على تغيير نوع الشاي الذي تعيده. هذا يجعل `getTea` أكثر مرونة، ويعطي المبرمج المزيد من التحكم عندما يطلب العميل التغيير. +بهذه المعلومات، سنحتاج إلى مراجعة دالة `getTea` من التحدي الأخير للتعامل مع مختلف طلبات الشاي. يمكنك تعديل `getTea` لقبول وظيفة (function) كوسيط (parameter) لتكون قادرة على تغيير نوع الشاي الذي تعيده. هذا يجعل `getTea` أكثر مرونة، ويعطي المبرمج المزيد من التحكم عندما يطلب العميل التغيير. ولكن أولاً، دعونا نغطي بعض المصطلحات المتعلقة بالـ functions: diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/understand-the-hazards-of-using-imperative-code.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/understand-the-hazards-of-using-imperative-code.md index e7240dc2c7433f..ae98f8e66c9acb 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/understand-the-hazards-of-using-imperative-code.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/understand-the-hazards-of-using-imperative-code.md @@ -12,9 +12,9 @@ Functional programming هي عادة جيدة. إنها تجعل الكود ال في اللغة الإنجليزية (والعديد من اللغات الأخرى) ، يتم استخدام صيغة الأمر لإعطاء الأوامر. وبالمثل ، فإن أسلوب الأمر في البرمجة هو الذي يعطي الكمبيوتر مجموعة من العبارات لأداء مهمة ما. -غالبًا ما تغير البيانات حالة البرنامج ، مثل تحديث المتغيرات العالمية(global variables). المثال الكلاسيكي هو كتابة حلقة `for` تعطي توجيهات دقيقة للتكرار على فهارس ال array. +غالبًا ما تغير البيانات حالة البرنامج ، مثل تحديث المتغيرات الشاملة (global variables). المثال الكلاسيكي هو كتابة حلقة `for` تعطي توجيهات دقيقة للتكرار على فهارس ال array. -في المقابل ، ال functional programming هي شكل من أشكال البرمجة التصريحية (declarative programming). أنت تخبر الكمبيوتر بما تريد فعله عن طريق استدعاء method أو function. +في المقابل، تكون البرمجة الوظيفية (functional programming) من أشكال البرمجة المعلنة (declarative programming). أنت تخبر الكمبيوتر بما تريد فعله عن طريق استدعاء method أو function. يقدم جافا سكريبت العديد من ال methods المحددة مسبقاً التي تتعامل مع المهام الشائعة حتى لا تحتاج إلى كتابة كيفية قيام الكمبيوتر بتنفيذها. على سبيل المثال، بدلا من استخدام حلقة `for` المذكورة أعلاه، يمكنك استدعاء `map` التي تتعامل مع تفاصيل التكرار علي array. يساعد هذا في تجنب الأخطاء الدلالية ، مثل "Off By One Errors" التي تمت تغطيتها في قسم ال Debugging. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem.md index ffe3a3b75f2582..d28d5081e35bb8 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-higher-order-functions-map-filter-or-reduce-to-solve-a-complex-problem.md @@ -41,7 +41,7 @@ assert( ); ``` -يجب أن تعيد وظيفتك `array`. +يجب أن تنتج وظيفتك `array`. ```js assert(Array.isArray(squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2]))); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array.md index e9f557ab118a74..788d4ee7593b21 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-the-map-method-to-extract-data-from-an-array.md @@ -12,7 +12,7 @@ dashedName: use-the-map-method-to-extract-data-from-an-array هذه هي البداية فقط. وكما يوحي اسمها، فإن ال functional programming تتمحور حول نظرية ال functions. -سيكون من المنطقي أن تكون قادرًا على تمريرها كـ arguments ل functions أخرى ، وإرجاع function من function أخر. تعتبر الدوال first class objects في جافا سكريبت، مما يعني أنه يمكن استخدامها مثل أي object آخر. يمكن حفظها في المتغيرات، أو تخزينها في object ما، أو تمريرها كـ function arguments. +سيكون من المنطقي أن تكون قادرًا على تمريرها كـ arguments ل functions أخرى ، وإرجاع function من function أخر. تعتبر الوظائف first class objects في جافا سكريبت، مما يعني أنه يمكن استخدامها مثل أي object آخر. يمكن حفظها في المتغيرات، أو تخزينها في object ما، أو تمريرها كـ function arguments. دعونا نبدأ ببعض الـ array functions البسيطة، التي هي methods على ال array object prototype. في هذا التمرين نحن ننظر إلى `Array.prototype.map()`أو ببساطة `map`. @@ -33,7 +33,7 @@ const names = users.map(user => user.name); console.log(names); ``` -ستعرض وحدة التحكم القيمة `[ 'John', 'Amy', 'camperCat' ]`. +سيعرض الكونسول القيمة `[ 'John', 'Amy', 'camperCat' ]`. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data.md index 95865d47f0cb1f..7d563d8038c831 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/functional-programming/use-the-reduce-method-to-analyze-data.md @@ -14,7 +14,7 @@ dashedName: use-the-reduce-method-to-analyze-data الـ callback function تقبل اربعة arguments. وتعرف ال argument الأولى بأنها المجمع الذي يعين قيمة إرجاع الـ callback function من التكرار السابق، والـ argument الثاني هو العنصر الحالي الذي يجري معالجته، وال argument الثالث هو فهرس ذلك العنصر والرابع هو ال array التي يستدعي عليها `reduce`. -بالإضافة إلى الـ callback function فـ `reduce` لديه معلمة إضافية تأخذ قيمة أولية للمجمع. إذا لم يتم استخدام هذا المعامل الثاني، يتم تخطي التكرار الأول ويتم تمرير التكرار الثاني العنصر الأول من ال array كالمجمع. +فضلاً على ذلك, لدي الوظيفة تعيد تفعيلها (callback function) المسمى `reduce` وسيط (parameter) إضافية التي تأخذ قيمة أولية للمجمع. إذا لم يتم استخدام هذا الوسيط الثاني، يتم تخطي التكرار الأول ويتم تمرير التكرار الثاني العنصر الأول من القائمة (array) كالمجمع. انظر أدناه للحصول على مثال يستخدم `reduce` على مصفوفة `users` لإرجاع مجموع أعمار المستخدمين. ومن أجل البساطة، لا يستخدم المثال سوى ال arguments الأولى والثانية. @@ -47,7 +47,7 @@ const usersObj = users.reduce((obj, user) => { console.log(usersObj); ``` -ستعرض وحدة التحكم القيمة `{ John: 34, Amy: 20, camperCat: 10 }`. +سيعرض الكونسول القيمة `{ John: 34, Amy: 20, camperCat: 10 }`. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/drop-it.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/drop-it.md index 06b9b57d7db3d8..399c4bd1bac067 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/drop-it.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/drop-it.md @@ -8,7 +8,7 @@ dashedName: drop-it # --description-- -بالنظر إلى المصفوفة `arr` ، كرر وأزل كل عنصر بدءًا من العنصر الأول (الفهرس 0) حتى تعرض الدالة `func` القيمة `true` عندما يتم تمرير العنصر المتكرر من خلالها. +بالنظر إلى المصفوفة `arr` ، كرر وأزل كل عنصر بدءًا من العنصر الأول (الفهرس 0) حتى تعرض الوظيفة `func` القيمة `true` عندما يتم تمرير العنصر المتكرر من خلالها. ثم ارجع بقية ال array بمجرد استيفاء الشرط، وإلا ، يجب إرجاع `arr` كـ array فارغة. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true.md index 45513e2d8af833..7bea1ab1008291 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/everything-be-true.md @@ -8,9 +8,9 @@ dashedName: everything-be-true # --description-- -تحقق مما إذا كان الـ argument الثاني صحيح truthy على جميع عناصر المجموعة (الـ argument الأول). +تحقق مما إذا كان المعطى (argument) الثاني صحيح (truthy) على جميع عناصر المجموعة (المعطى الأول). -بمعنى آخر ، يتم إعطاؤك array لمجموعة من الـ objects. سيكون المسند `pre` خاصية للـ object وتحتاج إلى إرجاع `true` إذا كانت قيمته `truthy`. خلاف ذلك، قم بإرجاع `false`. +بمعنى آخر، يتم إعطاؤك قائمة (array) لمجموعة من الكائنات (objects). سيكون المسند `pre` خاصية للـ object وتحتاج إلى إرجاع `true` إذا كانت قيمته `truthy`. خلاف ذلك، قم بإرجاع `false`. في Javascript، القيم `truthy` هي القيم التي تترجم إلى `true` عند تقييمها في سياق منطقي (Boolean). diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/search-and-replace.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/search-and-replace.md index 08bf9f2447e9f9..095966de95da98 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/search-and-replace.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/search-and-replace.md @@ -8,19 +8,19 @@ dashedName: search-and-replace # --description-- -قم بإجراء بحث واستبدال علي الجملة باستخدام الوسيطات المقدمة و ارجع الجملة الجديدة. +اجري بحث واستبدال علي الجملة باستخدام المعطيات (arguments) المقدمة وأنتج الجملة الجديدة. -الوسيطة الأولى هي الجملة التي سيجري البحث والاستبدال عليها. +إن المعطى الأولى جملة التي سيجري البحث والاستبدال عليها. -الوسيطة الثانية هي الكلمة التي سيتم استبدالها. +إن المعطى الثانية كلمة التي استبدلتها (سابقا). -أما الوسيطة الثالثة فهي ما ستحل محل الوسيطة الثانية. +أما المعطى الثالث ما سيحل محل المعطى الثاني (سلفا). **ملاحظة:** احتفظ بحالة الحرف الأول في الكلمة الأصلية عند استبدالها. على سبيل المثال إذا كنت تقصد استبدال كلمة `Book` بكلمة `dog`، ينبغي استبدالها كـ `Dog` # --hints-- -`myReplace("Let us go to the store", "store", "mall")` يجب أن يعيد السلسلة النصية `Let us go to the mall`. +`myReplace("Let us go to the store", "store", "mall")` يجب أن يعيد المقطع النصي `Let us go to the mall`. ```js assert.deepEqual( @@ -29,7 +29,7 @@ assert.deepEqual( ); ``` -`myReplace("He is Sleeping on the couch", "Sleeping", "sitting")` يجب أن يعيد السلسلة النصية `He is Sitting on the couch`. +`myReplace("He is Sleeping on the couch", "Sleeping", "sitting")` يجب أن يعيد المقطع النصي `He is Sitting on the couch`. ```js assert.deepEqual( @@ -38,7 +38,7 @@ assert.deepEqual( ); ``` -`myReplace("I think we should look up there", "up", "Down")` يجب أن يعيد السلسلة النصية `I think we should look down there`. +`myReplace("I think we should look up there", "up", "Down")` يجب أن يعيد المقطع النصي `I think we should look down there`. ```js assert.deepEqual( @@ -47,7 +47,7 @@ assert.deepEqual( ); ``` -`myReplace("This has a spellngi error", "spellngi", "spelling")` يجب أن يعيد السلسلة النصية `This has a spelling error`. +`myReplace("This has a spellngi error", "spellngi", "spelling")` يجب أن يعيد المقطع النصي `This has a spelling error`. ```js assert.deepEqual( @@ -56,7 +56,7 @@ assert.deepEqual( ); ``` -`myReplace("His name is Tom", "Tom", "john")` يجب أن يعيد السلسلة النصية `His name is John`. +`myReplace("His name is Tom", "Tom", "john")` يجب أن يعيد المقطع النصي `His name is John`. ```js assert.deepEqual( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple.md index 1edd5fb892345e..d8ff892d8be652 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/smallest-common-multiple.md @@ -8,7 +8,7 @@ dashedName: smallest-common-multiple # --description-- -اعثر عن أصغر مضاعف مشترك للمعلمات المتوفرة والتي يمكن تقسيمها بالتساوي على كليهما ، وكذلك على جميع الأرقام المتسلسلة في النطاق بين هذه المعلمات. +اعثر عن أصغر مضاعف مشترك للوسائط (parameters) المتوفرة التي يمكن تقسيمها بالتساوي على كليهما، وكذلك على جميع الأرقام المتسلسلة في النطاق بين هذه الوسائط. سيكون النطاق عبارة عن مصفوفة من رقمين لن يكونا بالضرورة بالترتيب العددي. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sorted-union.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sorted-union.md index 55d2496f405eb5..2fcefeaed8c8e5 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sorted-union.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sorted-union.md @@ -8,7 +8,7 @@ dashedName: sorted-union # --description-- -أكتب وظيفة (function) تأخذ قائمتين أو أكثر وتعيد مجموعة جديدة من القيم الفريدة حسب ترتيب القوائم (arrays) الأصلية المقدمة. +أكتب وظيفة (function) تأخذ قائمتين أو أكثر وتنتج مجموعة جديدة من القيم الفريدة حسب ترتيب القوائم (arrays) الأصلية المقدمة. بعبارة أخرى، ينبغي إدراج جميع القيم الموجودة من جميع القوائم (arrays) بترتيبها الأصلي، ولكن دون تكرار لها في القائمة (array) النهائية. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/steamroller.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/steamroller.md index 47943c19594a37..8dd6d0dcc28894 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/steamroller.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/steamroller.md @@ -36,7 +36,7 @@ assert.deepEqual(steamrollArray([1, [], [3, [[4]]]]), [1, 3, 4]); assert.deepEqual(steamrollArray([1, {}, [3, [[4]]]]), [1, {}, 3, 4]); ``` -يجب ألا يستخدم الحل الخاص بك الدوال `Array.prototype.flat()` أو `Array.prototype.flatMap()`. +يجب ألا يستخدم الحل الخاص بك الوظائف `Array.prototype.flat()` أو `Array.prototype.flatMap()`. ```js assert(!code.match(/\.\s*flat\s*\(/) && !code.match(/\.\s*flatMap\s*\(/)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers.md index 8c7c5178e4369a..b4cd9ce7b1900c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/sum-all-odd-fibonacci-numbers.md @@ -10,7 +10,7 @@ dashedName: sum-all-odd-fibonacci-numbers بإعطائك عدد صحيح موجب `num` ، قم بإرجاع مجموع كل أرقام فيبوناتشي الفردية الأقل من أو تساوي `num`. -الرقمان الأولان في تسلسل فيبوناتشي هما 1 و 1. وكل رقم إضافي في التسلسل هو مجموع الرقمين السابقين. والأرقام الستة الأولى من سلسلة فيبوناتشي هي 1 و 1 و 2 و 3 و 5 و 8. +The first two numbers in the Fibonacci sequence are 0 and 1. وكل رقم إضافي في التسلسل هو مجموع الرقمين السابقين. The first seven numbers of the Fibonacci sequence are 0, 1, 1, 2, 3, 5 and 8. على سبيل المثال `sumFibs(10)` يجب أن يرجع `10` لأن جميع أرقام فيبوناتشي الفردية التي هي أقل من أو تساوي `10` هي 1 و 1 و 3 و 5. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou.md index 12f7da9ce9b43f..22f945a44f1e09 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/wherefore-art-thou.md @@ -8,7 +8,7 @@ dashedName: wherefore-art-thou # --description-- -قم بإنشاء function يبحث في array من الـ objects (الـ argument الأولى) ويرجع array من جميع الـ objects التي لديها أزواج مطابقة من name و value (الـ argument الثانية). يجب أن يكون كل name و value من الـ object المصدر، موجودا في الـ object من الـ collection، إذا كان يراد إدراجه في الـ array التي تم ارجاعها. +أنشئ وظيفة (function) يبحث في قائمة (array) من الكائنات (objects) (المعطى (argument) الأولى) وينتج قائمة من جميع الكائنات التي لديها أزواج مطابقة من name و value (المعطى الثانية). يجب أن يكون كل name و value من الـ object المصدر، موجودا في الـ object من الـ collection، إذا كان يراد إدراجه في الـ array التي تم ارجاعها. على سبيل المثال، إذا كانت الـ argument الأولى هي `[{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }]`, والـ argument الثانية هي `{ last: "Capulet" }`، يجب عليك إعادة الـ object الثالث من الـ array (الـ argument الأولى)، لأنه يحتوي على الاسم وقيمته، وهذا ما تم إرساله كـ argument ثانية. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/caesars-cipher.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/caesars-cipher.md index 16df5dfdf00f3d..92b5a944b3da74 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/caesars-cipher.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/caesars-cipher.md @@ -1,6 +1,6 @@ --- id: 56533eb9ac21ba0edf2244e2 -title: Caesars Cipher +title: شفرة قيصر challengeType: 5 forumTopicId: 16003 dashedName: caesars-cipher @@ -12,7 +12,7 @@ dashedName: caesars-cipher من الاستخدامات الحديثة الشائعة تشفير ROT13 ، حيث يتم تبديل قيم الحروف بمقدار 13 مكانًا. وهكذا `A ↔ N`، `B ↔ O` وما إلى ذلك. -اكتب وظيفة تأخذ مقطع نصي مشفر من نوع ROT13 كمدخل وتنتج مقطع نصي غير مشفر. +اكتب وظيفة (function) تأخذ مقطع نصي (string) مشفر من نوع ROT13 كمدخل وتنتج مقطع نصي غير مشفر. جميع الحروف ستكون كبيرة (uppercase). لا تغير أي حرف غير أبجدي (مثل المسافات وعلامات الترقيم)، ولكن مررها. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register.md index b0b6a4a3b6d0c2..e1bee22eedd772 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/cash-register.md @@ -1,6 +1,6 @@ --- id: aa2e6f85cab2ab736c9a9b24 -title: Cash Register +title: مكنة لتسجيل النقود challengeType: 5 forumTopicId: 16012 dashedName: cash-register @@ -8,11 +8,11 @@ dashedName: cash-register # --description-- -قم بتصميم دالة درج تسجيل المدفوعات `checkCashRegister()` التي تقبل سعر الشراء كـ argument أولى (`price`)، و الدفع كـ argument ثانية (`cash`) ، و cash-in-drawer اي النقود في الدرج (`cid`) كـ argument ثالثة. +صمم وظيفة درج لتسجيل النقود `checkCashRegister()` التي تقبل سعر الشراء كمعطى أولى (`price`)، و الدفع كمعطى ثاني (`cash`)، و cash-in-drawer أي النقود في الدرج (`cid`) كمعطى ثالث. `cid` عبارة عن array ثنائية الأبعاد للعملة المتاحة. -يجب أن تقوم دالة `checkCashRegister()` دائما بإرجاع object يحتوي على key الـ `status` و key الـ `change`. +يجب أن تقوم وظيفة `checkCashRegister()` دائما بإنتاج كائن يحتوي على الهوية (key) المسمى `status` و الهوية `change`. قم بإرجاع `{status: "INSUFFICIENT_FUNDS", change: []}` إذا كان cash-in-drawer أقل من الباقي المستحق، أو إذا كنت لا تستطيع إرجاع الباقي بالضبط. @@ -40,7 +40,7 @@ dashedName: cash-register # --hints-- -`checkCashRegister(19.5, 20, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])` يجب ان يرجع object. +يجب أن ينتج `checkCashRegister(19.5, 20, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])` كائن. ```js assert.deepEqual( @@ -61,7 +61,7 @@ assert.deepEqual( ); ``` -`checkCashRegister(19.5, 20, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])` يجب ان يرجع `{status: "OPEN", change: [["QUARTER", 0.5]]}`. +يجب أن ينتج `checkCashRegister(19.5, 20, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])` كائن `{status: "OPEN", change: [["QUARTER", 0.5]]}`. ```js assert.deepEqual( @@ -80,7 +80,7 @@ assert.deepEqual( ); ``` -`checkCashRegister(3.26, 100, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])` يجب ان يرجع `{status: "OPEN", change: [["TWENTY", 60], ["TEN", 20], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.5], ["DIME", 0.2], ["PENNY", 0.04]]}`. +يجب أن ينتج `checkCashRegister(3.26, 100, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]])` كائن `{status: "OPEN", change: [["TWENTY", 60], ["TEN", 20], ["FIVE", 15], ["ONE", 1], ["QUARTER", 0.5], ["DIME", 0.2], ["PENNY", 0.04]]}`. ```js assert.deepEqual( @@ -110,7 +110,7 @@ assert.deepEqual( ); ``` -`checkCashRegister(19.5, 20, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])` يجب ان يرجع `{status: "INSUFFICIENT_FUNDS", change: []}`. +يجب أن ينتج `checkCashRegister(19.5, 20, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])` كائن `{status: "INSUFFICIENT_FUNDS", change: []}`. ```js assert.deepEqual( @@ -129,7 +129,7 @@ assert.deepEqual( ); ``` -`checkCashRegister(19.5, 20, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])` يجب ان يرجع `{status: "INSUFFICIENT_FUNDS", change: []}`. +يجب أن ينتج `checkCashRegister(19.5, 20, [["PENNY", 0.01], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 1], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])` كائن `{status: "INSUFFICIENT_FUNDS", change: []}`. ```js assert.deepEqual( @@ -148,7 +148,7 @@ assert.deepEqual( ); ``` -`checkCashRegister(19.5, 20, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])` يجب ان يرجع `{status: "CLOSED", change: [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]}`. +يجب أن ينتج `checkCashRegister(19.5, 20, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]])` كائن `{status: "CLOSED", change: [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]}`. ```js assert.deepEqual( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker.md index 6d07135f341c56..3fd98aeadf16ee 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/palindrome-checker.md @@ -1,6 +1,6 @@ --- id: aaa48de84e1ecc7c742e1124 -title: Palindrome Checker +title: مدقق لمعاكس المقطع النصي challengeType: 5 forumTopicId: 16004 dashedName: palindrome-checker diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/roman-numeral-converter.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/roman-numeral-converter.md index cae6e0220741c7..425b47c65b7127 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/roman-numeral-converter.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/roman-numeral-converter.md @@ -1,6 +1,6 @@ --- id: a7f4d8f2483413a6ce226cac -title: Roman Numeral Converter +title: محول للأرقام الرومانية challengeType: 5 forumTopicId: 16044 dashedName: roman-numeral-converter diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator.md index 2101560a4500a0..a744f7215c4d33 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/telephone-number-validator.md @@ -1,6 +1,6 @@ --- id: aff0395860f5d3034dc0bfc9 -title: Telephone Number Validator +title: مدقق الأرقام الهواتف challengeType: 5 forumTopicId: 16090 dashedName: telephone-number-validator diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.md index 960c65a0459b7e..c37ada50d003dc 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.md @@ -1,6 +1,6 @@ --- id: 587d7db1367417b2b2512b87 -title: إضافة الدوال بعد الميراث (Add Methods After Inheritance) +title: إضافة الطرق (Methods) بعد الميراث (Inheritance) challengeType: 1 forumTopicId: 301315 dashedName: add-methods-after-inheritance @@ -8,9 +8,9 @@ dashedName: add-methods-after-inheritance # --description-- -الـ constructor function الذي يرث `prototype` الـ object الخاص به من الـ supertype constructor function يمكن أن يكون له الـ methods الخاصة به بالإضافة إلى الـ methods الموروثة. +الوظيفة المنشئة (constructor function) التي ترث كائنها (object) تسمى `prototype` من وظيفة منشئة كبرى (supertype), يمكن أن تحتوي على طرقها (methods) بالإضافة إلى الطرق الموروثة. -على سبيل المثال، `Bird` هو constructor يرث `prototype` من `Animal`: +على سبيل المثال، يكون `Bird` منشئ (constructor) الذي يرث `prototype` من `Animal`: ```js function Animal() { } @@ -22,7 +22,7 @@ Bird.prototype = Object.create(Animal.prototype); Bird.prototype.constructor = Bird; ``` -بالإضافة إلى ما هو موروث من `Animal`، تريد إضافة سلوك فريد إلى objects الـ `Bird`. هنا ، `Bird` سيحصل على دالة `fly()`. يتم إضافة الدوال إلى `prototype` ال `Bird's` بنفس الطريقة مثل أي constructor function: +بالإضافة إلى ما موروث من `Animal`، تريد إضافة سلوك فريد إلى كائنات (objects) المسمى `Bird`. هنا، سيحصل `Bird` على وظيفة (function) مسمى `fly()`. تضاف الوظائف إلى `prototype` في `Bird's` بنفس الطريقة مثل أي وظيفة منشئا (constructor function): ```js Bird.prototype.fly = function() { @@ -30,7 +30,7 @@ Bird.prototype.fly = function() { }; ``` -الآن سيكون لمثيلات `Bird` الـ methods الاتية `eat()` و `fly()`: +الآن سيكون لمثيلات `Bird` الطرق الآتية `eat()` و `fly()`: ```js let duck = new Bird(); @@ -38,45 +38,45 @@ duck.eat(); duck.fly(); ``` -`duck.eat()` يعرض السلسلة `nom nom nom` في وحدة التحكم و `duck.fly()` سيعرض السلسلة `I'm flying!`. +يعرض `duck.eat()` مقطع نصي (string) بقيمة `nom nom nom` في وحدة التحكم ويعرض `duck.fly()` مقطع نصي `I'm flying!`. # --instructions-- -أضف كل الكود الضروري حتى يرث كائن `Dog` من `Animal` و الـ constructor الخاص بـ `prototype` الـ `Dog` تم تعيينه إلى `Dog`. ثم أضف `bark()` إلى الكائن `Dog` بحيث أن `beagle` يمكن أن يفعل `eat()` و `bark()`. يجب أن تطبع method الـ `bark()` الكلمة `Woof!` إلى وحدة التحكم. +أضف كل الكود الضروري حتى يرث كائن `Dog` من `Animal` و عيّن المنشئ الخاص بـ `prototype` من `Dog` بقيمة `Dog`. ثم أضف طريقة `bark()` إلى الكائن `Dog` بحيث أن `beagle` يمكن أن ينفذ `eat()` و `bark()`. يجب أن تطبع طريقة `bark()` كلمة `Woof!` إلى وحدة التحكم (console). # --hints-- -`Animal` لا يجب أن يستجيب لـ `bark()`. +يجب ألا `Animal` يستجيب إلى طريقة `bark()`. ```js assert(typeof Animal.prototype.bark == 'undefined'); ``` -`Dog` يجب أن يرث `eat()` من `Animal`. +يجب أن يرث `Dog` طريقة `eat()` من `Animal`. ```js assert(typeof Dog.prototype.eat == 'function'); ``` -يجب أن يحتوي prototype الـ `Dog` على `bark()`. +يجب أن يحتوي prototype داخل `Dog` على `bark()`. ```js assert('bark' in Dog.prototype); ``` -`beagle` يجب أن يكون `instanceof` من `Animal`. +يجب أن يكون `beagle` جزء (`instanceof`) من `Animal`. ```js assert(beagle instanceof Animal); ``` -يجب تعيين constructor الـ `beagle` إلى `Dog`. +يجب أن يكون منشئ `beagle` بقيمة `Dog`. ```js assert(beagle.constructor === Dog); ``` -`beagle.eat()` يجب أن يطبع السلسلة `nom nom nom` +يجب أن يطبع `beagle.eat()` مقطع نصي `nom nom nom` ```js capture(); @@ -85,7 +85,7 @@ uncapture(); assert(logOutput == 'nom nom nom'); ``` -`beagle.bark()` يجب ان يطبع السلسلة `Woof!` +يجب أن يطبع `beagle.bark()` مقطع نصي `Woof!` ```js capture(); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object.md index 5dc31a813eab7d..959675d6173d89 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object.md @@ -1,6 +1,6 @@ --- id: 587d7dad367417b2b2512b75 -title: إنشاء method في الكائن +title: إنشاء طريقة (Method) في الكائن challengeType: 1 forumTopicId: 301318 dashedName: create-a-method-on-an-object @@ -8,9 +8,9 @@ dashedName: create-a-method-on-an-object # --description-- -يمكن أن يكون لل objects نوع خاص من الخواص، يسمى method. +يمكن أن يكون للكائنات objects نوع خاص من الخواص، تسمى الطريقة (method). -الـ methods نوع من الخصائص عبارة عن functions. هذا يضيف سلوكا مختلفا إلى الـ object. فيما يلي مثال `duck` مع method: +إن الطرق methods الخصائص التي تكون وظائف (functions). هذا يضيف سلوكا مختلفا إلى الكائن (object). فيما يلي مثال `duck` بها طريقة (method): ```js let duck = { @@ -21,21 +21,21 @@ let duck = { duck.sayName(); ``` -المثال يضيف `sayName` ، التي هي function ترجع جملة تعطي اسم الـ `duck`. لاحظ أن الـ method وصلت إلى خاصية `name` في الـ return statement باستخدام `duck.name`. والتحدي التالي سيغطي طريقة أخرى للقيام بذلك. +يضيف المثال طريقة (method) تسمى `sayName`، إنها وظيفة (function) تنتج جملة باستخدام الاسم في `duck`. لاحظ أن الطريقة method وصلت إلى خاصية `name` في التعبير المنتج (return statement) باستخدام `duck.name`. والتحدي التالي سيغطي طريقة أخرى للقيام بذلك. # --instructions-- -باستخدام كائن `dog` ، أعطه method تسمى `sayLegs`. الـ method يجب ان تعيد الجملة `This dog has 4 legs.` +باستخدام كائن `dog`، أعطه طريقة (method) تسمى `sayLegs`. يجب أن تنتج الطريقة الجملة `This dog has 4 legs.` # --hints-- -`dog.sayLegs()` يجب أن تكون function. +يجب أن تكون `dog.sayLegs()` وظيفة (function). ```js assert(typeof dog.sayLegs === 'function'); ``` -يجب أن تعيد `dog.sayLegs()` السلسلة المحددة - لاحظ أن علامات الترقيم والتباعد مهمان. +يجب أن تنتج `dog.sayLegs()` المقطع النصي المحددة - لاحظ أن علامات الترقيم والتباعد مهمان. ```js assert(dog.sayLegs() === 'This dog has 4 legs.'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments.md index 70600f84216d24..4f93752ead5649 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments.md @@ -1,6 +1,6 @@ --- id: 587d7dae367417b2b2512b79 -title: Extend Constructors to Receive Arguments +title: تمديد المنشئات (Constructors) لتلقي المعطيات (Arguments) challengeType: 1 forumTopicId: 18235 dashedName: extend-constructors-to-receive-arguments @@ -16,7 +16,7 @@ swan.name = "Carlos"; swan.color = "white"; ``` -لنفترض أنك كنت تكتب برنامجاً لتعقب مئات أو حتى آلاف الطيور المختلفة في مطير. سوف يستغرق الأمر الكثير من الوقت لإنشاء كل الطيور، ثم تغيير الخصائص إلى قيم مختلفة لكل منها. من أجل إنشاء objects الـ `Bird` المختلفة بسهولة، يمكنك تصميم constructor الطيور الخاص بك بحيث يقبل الـ parameters: +لنفترض أنك كنت تكتب برنامجاً لتعقب مئات أو حتى آلاف الطيور المختلفة في مطير. سوف يستغرق الأمر الكثير من الوقت لإنشاء كل الطيور، ثم تغيير الخصائص إلى قيم مختلفة لكل منها. من أجل إنشاء كائنات الـ `Bird` المختلفة بسهولة، يمكنك تصميم منشئك (constructor) مسمى Bird بحيث يقبل الوسائط (parameters): ```js function Bird(name, color) { @@ -26,7 +26,7 @@ function Bird(name, color) { } ``` -ثم مرر القيم كحجج (arguments) لتعريف كل طائر فريد إلى constructor باسم `Bird`: التعليمات البرمجية `let cardinal = new Bird("Bruce", "red");` ينشئ مثيل جديد من `Bird` بخصائص `name` و `color` بقيم `Bruce` و `red` علي التوالي. مازالت خاصية `numLegs` بقيمة 2. يحتوي `cardinal` على هذه الخواص: +ثم مرر القيم كمعطيات (arguments) لتحديد كل طائر فريد في منشئ (constructor) باسم `Bird`: ينشئ `let cardinal = new Bird("Bruce", "red");` مثيل (instance) جديد من `Bird` بخصائص `name` و `color` بقيم `Bruce` و `red` علي التوالي. مازالت خاصية `numLegs` بقيمة 2. يحتوي `cardinal` على هذه الخواص: ```js cardinal.name @@ -38,17 +38,17 @@ cardinal.numLegs # --instructions-- -إنشاء constructor آخر باسم `Dog`. هذه المرة، اضبطه لأخذ حجج (Parameters) الآتية `name` و `color`، و اجعل الخاصية `numLegs` ثابتة عند 4. ثم قم بإنشاء `Dog` جديد محفوظ في متغير اسمه `terrier`. مرر اليه اثنان strings كـ arguments للخصائص `name` و `color`. +إنشاء constructor آخر باسم `Dog`. هذه المرة، اضبطه لأخذ وسائط (Parameters) الآتية `name` و `color`، واجعل الخاصية `numLegs` ثابتة عند 4. ثم قم بإنشاء `Dog` جديد محفوظ في متغير اسمه `terrier`. مرر له مقطعان نصيان (strings) كمعطيات للخصائص `name` و `color`. # --hints-- -`Dog` يجب أن يتلقى argument لـ `name`. +يجب أن يتلقى `Dog` معطى `name`. ```js assert(new Dog('Clifford').name === 'Clifford'); ``` -`Dog` يجب أن يتلقى argument لـ `color`. +يجب أن يتلقى `Dog` معطى `color`. ```js assert(new Dog('Clifford', 'yellow').color === 'yellow'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype.md index 56250f9b54486a..65e3159bfb7742 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype.md @@ -36,7 +36,7 @@ animal.eat(); animal instanceof Animal; ``` -دالة `instanceof` هنا، ستعيد `true`. +ستعيد طريقة `instanceof` حالة `true` هنا. # --instructions-- @@ -44,13 +44,13 @@ animal instanceof Animal; # --hints-- -يجب تعريف متغير `duck`. +يجب إعلان متغير `duck`. ```js assert(typeof duck !== 'undefined'); ``` -يجب تعريف متغير `beagle`. +يجب إعلان متغير `beagle`. ```js assert(typeof beagle !== 'undefined'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties.md index 23edd5b7dcc1a6..90230752779339 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties.md @@ -58,7 +58,7 @@ assert.deepEqual(ownProps, ['name']); assert.deepEqual(prototypeProps, ['numLegs']); ``` -يجب عليك حل هذا التحدي دون استخدام الدالة المدمجة في `Object.keys()`. +يجب عليك حل هذا التحدي دون استخدام الوظيفة المدمجة في `Object.keys()`. ```js assert(!/\Object.keys/.test(code)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype.md index 4b39fb9b64d557..5d8ca6f86bed76 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype.md @@ -8,7 +8,7 @@ dashedName: remember-to-set-the-constructor-property-when-changing-the-prototype # --description-- -هناك تأثير جانبي مهم لضبط prototype يدويًا إلى كائن (object) جديد. إنه يمحو خاصية `constructor`! يمكن استخدام هذه الخاصية لمعرفة إي وظيفة منشئ (constructor) هي التي أنشأت نموذج (instance)، ولكن بما انه تم التعديل علي الخاصية (property)، فإنها تعطي الآن نتائج خاطئة: +هناك تأثير جانبي مهم لضبط prototype يدويًا إلى كائن (object) جديد. إنه يمحو خاصية `constructor`! يمكن استخدام هذه الخاصية لمعرفة إي وظيفة منشئ (constructor function) هي التي أنشأت نموذج (instance)، ولكن بما انه تم التعديل علي الخاصية (property)، فإنها تعطي الآن نتائج خاطئة: ```js duck.constructor === Bird; @@ -16,7 +16,7 @@ duck.constructor === Object; duck instanceof Bird; ``` -بالترتيب، سيتم تقييم هذه التعبيرات إلى `false`، و `true`، و `true`. +بالترتيب، سيتم تقييم هذه العبارات إلى `false`، و `true`، و `true`. لإصلاح هذا، عندما يتم تعيين prototype يدوياً إلى كائن جديد، تذكر أن تحدد خاصية `constructor`: diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property.md index 4cc528aec6daba..d74a6e690eb7ca 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property.md @@ -1,6 +1,6 @@ --- id: 587d7db1367417b2b2512b86 -title: إعادة تعيين خاصية موروثة (Reset an Inherited Constructor Property) +title: إعادة تعيين خاصية موروثة challengeType: 1 forumTopicId: 301324 dashedName: reset-an-inherited-constructor-property diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties.md index 007005a13736f2..5a49dc2ece64fb 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties.md @@ -54,7 +54,7 @@ assert(ownProps.indexOf('name') !== -1 && ownProps.indexOf('numLegs') !== -1); assert(!/Object(\.keys|\[(['"`])keys\2\])/.test(code)); ``` -يجب عليك حل هذا التحدي بدون hardcoding مصفوفة `ownProps`. +يجب عليك حل هذا التحدي بدون إدخال قيم مثبتة (hard-coding) في قائمة `ownProps`. ```js assert( diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property.md index a188f882d81f7a..cf3376c4723944 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property.md @@ -36,7 +36,7 @@ function joinBirdFraternity(candidate) { # --instructions-- -اكتب دالة `joinDogFraternity` التي تأخذ معلمة `candidate` و باستخدام الـ `constructor` ،قم بإرجاع `true` إذا كان المرشح `Dog`، وإلا أرجع `false`. +اكتب وظيفة `joinDogFraternity` التي تأخذ وسيط `candidate`, وتستخدم خاصية `constructor`, لتنتج `true` عندما يكون قيمة candidate تساوي `Dog`، وتنتح `false` عندما لا يكون كذلك. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife.md index 364153abf986d2..71e6d45c26ffc3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife.md @@ -1,6 +1,6 @@ --- id: 587d7db2367417b2b2512b8b -title: Understand the Immediately Invoked Function Expression (IIFE) +title: أدراك الوظائف المنفذة عند إعلانهم (Immediately Invoked Function Expression (IIFE)) challengeType: 1 forumTopicId: 301328 dashedName: understand-the-immediately-invoked-function-expression-iife @@ -8,7 +8,7 @@ dashedName: understand-the-immediately-invoked-function-expression-iife # --description-- -النمط الشائع في جافا سكريبت هو تنفيذ الـ function بمجرد إعلانه: +النمط الشائع في JavaScript هو تنفيذ الوظيفة (function) بمجرد إعلانه: ```js (function () { @@ -16,13 +16,13 @@ dashedName: understand-the-immediately-invoked-function-expression-iife })(); ``` -هذا اسمه anonymous function expression الذي ينفذ على الفور، ويخرج `Chirp, chirp!` على الفور. +هذا اسمه تعبير غامض للوظيفة (anonymous function expression) الذي ينفذ على الفور، وينتج `Chirp, chirp!` على الفور. -لاحظ أن ال function ليس له اسم وليس مخزن في متغير. ويؤدي القوسان () الواردان في نهاية ال function expression إلى تنفيذه أو استدعاءه على الفور. هذا النمط يعرف بـ immediately invoked function expression او IIFE. +لاحظ إن الوظيفة ليس لها اسم وليست مخزنة في متغير. ويؤدي القوسان () الواردان في نهاية ال function expression إلى تنفيذه أو استدعاءه على الفور. هذا النمط يعرف بـ immediately invoked function expression او IIFE. # --instructions-- -أعد كتابة الدالة `makeNest` وأزيل استدعائها بحيث أنها تصبح anonymous immediately invoked function expression (IIFE). +أعد كتابة الوظيفة `makeNest` وأزيل استدعائها بحيث أنها تصبح anonymous immediately invoked function expression (IIFE). # --hints-- @@ -32,7 +32,7 @@ dashedName: understand-the-immediately-invoked-function-expression-iife assert(/\((function|\(\))(=>|\(\)){?/.test(code.replace(/\s/g, ''))); ``` -يجب أن يكون ال function الخاص بك بين قوسين في نهاية التعبير لاستدعائه على الفور. +يجب أن يكون ال function الخاص بك بين قوسين في نهاية العبارة لاستدعائه على الفور. ```js assert(/\(.*(\)\(|\}\(\))\)/.test(code.replace(/[\s;]/g, ''))); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects.md index 9c4f8a0459895c..d04a3d37b62f87 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects.md @@ -54,7 +54,7 @@ plane.fly(); # --hints-- -يجب أن يعرف الكود الخاص بك عن متغير `glideMixin` وهو function. +يجب أن يعلن كودك إن متغير `glideMixin` وظيفة (function). ```js assert(typeof glideMixin === 'function'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally.md index 83935b14b5ba5b..29c1ceb7889031 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally.md @@ -18,7 +18,7 @@ bird.name = "Duffy"; لذلك، يمكن لأي جزء من الكود الخاص بك تغيير اسم `bird` بسهولة إلى أي قيمة. فكروا في أشياء مثل كلمات المرور والحسابات المصرفية التي يسهل تغييرها من قبل أي جزء من الكود الخاص بك. وهذا يمكن أن يسبب الكثير من المشاكل. -وأبسط طريقة لجعل هذه الخاصية العامة، خاصة، هي عن طريق إنشاء متغير داخل الـ constructor function. وهذا يغير نطاق ذلك المتغير بحيث يكون ضمن الـ constructor function علي عكس أن يكون متاحا بشكل global. وبهذه الطريقة، لا يمكن الوصول إلى المتغير وتغييره إلا بواسطة method تكون أيضا ضمن الـ constructor function. +وأبسط طريقة لجعل هذه الخاصية العامة، خاصة، هي عن طريق إنشاء متغير داخل الـ constructor function. وهذا يغير مجال ذلك المتغير بحيث يكون ضمن الـ constructor function علي عكس أن يكون متاحا بشكل شامل (global). وبهذه الطريقة، لا يمكن الوصول إلى المتغير وتغييره إلا بواسطة method تكون أيضا ضمن الـ constructor function. ```js function Bird() { @@ -32,11 +32,11 @@ let ducky = new Bird(); ducky.getHatchedEggCount(); ``` -هنا `getHatchedEggCount` هي method مميزة، لأنها لديها حق الوصول إلى المتغير الخاص `hatchedEgg`. هذا ممكن لأن `hatchedEgg` تم تعريفها في نفس السياق مثل `getHatchedEggCount`. في جافا سكريبت، الدالة دائما لها حق الوصول إلى السياق الذي تم إنشاؤها فيه. هذا يسمى `closure`. +هنا `getHatchedEggCount` هي method مميزة، لأنها لديها حق الوصول إلى المتغير الخاص `hatchedEgg`. هذا ممكن لإن `hatchedEgg` أعلنت في نفس السياق مثل `getHatchedEggCount`. في جافا سكريبت، الوظيفة دائما لها حق الوصول إلى السياق الذي تم إنشاؤها فيه. هذا يسمى `closure`. # --instructions-- -قم بتغيير كيفية تعريف `weight` في دالة `Bird` بحيث يصبح متغير خاص. ثم قم بإنشاء `getWeight` لإرجاع قيمة `weight` والتي هي 15. +غير كيفية تعلن `weight` في وظيفة `Bird` بحيث يصبح متغير خاص. ثم قم بإنشاء `getWeight` لإرجاع قيمة `weight` والتي هي 15. # --hints-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object.md index 16d268fdd75218..b79ace14daa99b 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object.md @@ -1,6 +1,6 @@ --- id: 587d7dac367417b2b2512b74 -title: Use Dot Notation to Access the Properties of an Object +title: استخدام رمز النقطة (Dot Notation) للحصول على خصائص الكائن (Object) challengeType: 1 forumTopicId: 301333 dashedName: use-dot-notation-to-access-the-properties-of-an-object @@ -8,7 +8,7 @@ dashedName: use-dot-notation-to-access-the-properties-of-an-object # --description-- -أحدث التحدي الأخير object ذو خصائص مختلفة. الآن سترى كيفية الوصول إلى قيم هذه الخواص. إليك مثال: +أنشئ التحدي السابق كائن (object) ذو خصائص (properties) مختلفة. الآن سترى كيف تصل إلى قيم تلك الخصائص. إليك مثال: ```js let duck = { @@ -18,21 +18,21 @@ let duck = { console.log(duck.name); ``` -يتم استخدام تدوين Dot على اسم الكائن، `duck`، يليها اسم الخاصية، `name`، للوصول إلى قيمة `Aflac`. +تستخدم رمز النقطة (dot notation) على اسم الكائن `duck`، يليها اسم الخاصية `name`، للوصول إلى قيمة `Aflac`. # --instructions-- -قم بطباعة خواص كائن `dog` إلى وحدة التحكم الخاصة بك. +أطبع خواص كائن `dog` إلى وحدتك التحكم (console). # --hints-- -يجب أن يستخدم الكود الخاص بك `console.log` لطباعة قيمة خاصية `name` لكائن `dog`. +يجب أن يستخدم كودك `console.log` لطباعة قيمة خاصية `name` لكائن `dog`. ```js assert(/console.log\(.*dog\.name.*\)/g.test(code)); ``` -يجب أن يستخدم الكود الخاص بك `console.log` لطباعة قيمة خاصية `numLegs` لكائن `dog`. +يجب أن يستخدم كودك `console.log` لطباعة قيمة خاصية `numLegs` لكائن `dog`. ```js assert(/console.log\(.*dog\.numLegs.*\)/g.test(code)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself.md index 6445636bf59e10..9e6df4bc411812 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself.md @@ -1,6 +1,6 @@ --- id: 587d7db0367417b2b2512b83 -title: Use Inheritance So You Don't Repeat Yourself +title: استخدام التوريث (Inheritance) حتى لا تعيد تكرار نفسك (DRY) challengeType: 1 forumTopicId: 301334 dashedName: use-inheritance-so-you-dont-repeat-yourself @@ -8,9 +8,9 @@ dashedName: use-inheritance-so-you-dont-repeat-yourself # --description-- -هناك مبدأ في البرمجة يسمى Don't Repeat Yourself (DRY). السبب في أن الكود المتكرر مشكلة هو أن أي تغيير يتطلب إصلاح الكود في أماكن متعددة. وهذا يعني عادة المزيد من العمل للمبرمجين والمزيد من الحيز للأخطاء. +هناك مبدأ في البرمجة يسمى لا تكرر نقسك (Don't Repeat Yourself (DRY)). إن السبب وراء ضرر تكرار الكود هو أحتياج تعديل الكود في أماكن متعددة تغيير عند الرغبة بذلك. وعادة يضع هذا المزيد من العمل للمبرمجين ويزيد من احتمال وجود أخطاء. -لاحظ في المثال أدناه أن `describe` مشتركة من قبل `Bird` و `Dog`: +لاحظ في المثال أدناه إن `describe` مشتركة من قبل `Bird` و `Dog`: ```js Bird.prototype = { @@ -28,7 +28,7 @@ Dog.prototype = { }; ``` -يتم تكرار `describe` في مكانين. يمكن تعديل الكود لاتباع مبدأ DRY عن طريق إنشاء `supertype` (أو الاب) يسمى `Animal`: +يتم تكرار طريقة (method) المسمى `describe` في مكانين. يمكن تعديل الكود لاتباع مبدأ DRY عن طريق إنشاء `supertype` (أو حاوي (parent)) يسمى `Animal`: ```js function Animal() { }; @@ -41,7 +41,7 @@ Animal.prototype = { }; ``` -بما أن `Animal` يتضمن method الـ `describe` ، يمكنك إزالته من `Bird` و `Dog`: +عند أحتواء `Animal` على طريقة `describe`، يمكنك إزالتها من `Bird` و `Dog`: ```js Bird.prototype = { @@ -55,23 +55,23 @@ Dog.prototype = { # --instructions-- -يتم تكرار method الـ `eat` في كل من `Cat` و `Bear`. قم بتعديل الكود بروح DRY عن طريق نقل method الـ `eat` إلى `supertype` الـ `Animal`. +يتم تكرار طريقة `eat` في كل من `Cat` و `Bear`. عدل كود بهدف عدم تكرار نفسك (DRY) عن طريق نقل طريقة `eat` داخل `Animal` الذي يكون `supertype`. # --hints-- -`Animal.prototype` يجب أن تحتوي على خاصية `eat`. +يجب أن تحتوي `Animal.prototype` على خاصية `eat`. ```js assert(Animal.prototype.hasOwnProperty('eat')); ``` -`Bear.prototype` يجب ألا يحتوي على خاصية `eat`. +يجب ألا يحتوي `Bear.prototype` على خاصية `eat`. ```js assert(!Bear.prototype.hasOwnProperty('eat')); ``` -`Cat.prototype` يجب ألا تحتوي على خاصية `eat`. +يجب ألا تحتوي `Cat.prototype` على خاصية `eat`. ```js assert(!Cat.prototype.hasOwnProperty('eat')); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code.md index 8a20ad3779263a..901ca5d06ca7f9 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code.md @@ -25,7 +25,7 @@ console.log(duck.numLegs); console.log(canary.numLegs); ``` -بما أن جميع ال instances تحتوي تلقائياً على الخصائص في الـ `prototype`، فكر في `prototype` كـ "وصفة" لإنشاء الـ objects. لاحظ أن الـ `prototype` لـ `duck` و `canary` هو جزء من constructor الـ`Bird` كـ `Bird.prototype`. كل object تقريبا في جافا سكريبت لديه خاصية `prototype` التي هي جزء من الـ constructor function التي أنشأتها. +بما أن جميع ال instances تحتوي تلقائياً على الخصائص في الـ `prototype`، فكر في `prototype` كـ "وصفة" لإنشاء الـ objects. لاحظ أن الـ `prototype` لـ `duck` و `canary` هو جزء من constructor الـ`Bird` كـ `Bird.prototype`. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/check-for-all-or-none.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/check-for-all-or-none.md index 27dbf007db2d28..def0348be7f8b3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/check-for-all-or-none.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/check-for-all-or-none.md @@ -22,7 +22,7 @@ rainbowRegex.test(american); rainbowRegex.test(british); ``` -كل من استدعائات دالة `test` سيرجعان `true`. +كل من استدعاءات طريقة (method) مسمى `test` سيرجعان `true`. # --instructions-- diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/check-for-mixed-grouping-of-characters.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/check-for-mixed-grouping-of-characters.md index bcf70e204b5f7e..6df8bfbbed6819 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/check-for-mixed-grouping-of-characters.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/check-for-mixed-grouping-of-characters.md @@ -12,7 +12,7 @@ dashedName: check-for-mixed-grouping-of-characters إذا كنت ترغب في العثور على `Penguin` او `Pumpkin` في string، يمكنك استخدام Regular Expression التالي: `/P(engu|umpk)in/g` -ثم تحقق مما إذا كانت مجموعات الـ string المطلوبة موجودة في الـ test string باستخدام دالة `test()`. +ثم تحقق مما إذا كانت مجموعات من مقطع النصي (string) المطلوبة موجودة في مقطع test النصي باستخدام طريقة (method) تسمى `test()`. ```js let testStr = "Pumpkin"; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/extract-matches.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/extract-matches.md index 1c3342759910bc..0d4377c890d112 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/extract-matches.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/extract-matches.md @@ -10,7 +10,7 @@ dashedName: extract-matches حتى الآن، كنت تتحقق فقط من وجود أو عدم وجود نمط داخل string. يمكنك أيضا استخراج المطابقات الفعلية التي وجدتها باستخدام دالة `.match()`. -لاستخدام دالة `.match()` ، قم بتطبيق الدالة على string ومرر بداخلها الـ regex في الأقواس. +لاستخدام وظيفة `.match()` ، قم بتطبيق الوظيفة على string ومرر بداخلها الـ regex في الأقواس. إليك مثال: diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/ignore-case-while-matching.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/ignore-case-while-matching.md index 2569210eee0e2c..8e323e3c892d5c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/ignore-case-while-matching.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/ignore-case-while-matching.md @@ -8,7 +8,7 @@ dashedName: ignore-case-while-matching # --description-- -حتى الآن، لقد نظرتم إلى regex للقيام بمطابقة حرفية من الـ strings. ولكن في بعض الأحيان قد ترغب في مطابقة الاختلافات في الحالة. +حتى الآن، لقد نظرت إلى regex للتطابق المقاطع النصية حرفيًا. ولكن في بعض الأحيان قد ترغب في مطابقة الاختلافات في الحالة. Case و هي الحالة (او في بعض الاحيان letter case) هي الفرق بين uppercase letters و lowercase letters اي الاحرف الكبيرة و الاحرف الصغيرة. أمثلة للحروف الكبيرة هي `A` و `B` و `C`. أمثلة للحروف الصغيرة هي `a` و `b` و `c`. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-a-literal-string-with-different-possibilities.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-a-literal-string-with-different-possibilities.md index 2ea80cd2c00545..1bf8d52fc8e9e2 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-a-literal-string-with-different-possibilities.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-a-literal-string-with-different-possibilities.md @@ -1,6 +1,6 @@ --- id: 587d7db4367417b2b2512b90 -title: طابق سلسلة حرفية (Literal String) مع احتمالات مختلفة +title: طابق مقطع نصي حرفي (Literal String) مع احتمالات مختلفة challengeType: 1 forumTopicId: 301345 dashedName: match-a-literal-string-with-different-possibilities @@ -8,9 +8,9 @@ dashedName: match-a-literal-string-with-different-possibilities # --description-- -باستخدام regexes مثل `/coding/`، يمكنك البحث عن النمط `coding` في سلسلة (string) أخرى. +باستخدام regexes مثل `/coding/`، يمكنك البحث عن النمط `coding` في مقطع نصي أخر. -هذا جيد للبحث عن سلسلة (string) واحدة، لكنه يقتصر على نمط واحد فقط. يمكنك البحث عن أنماط متعددة باستخدام `alternation` أو رمز `OR` التالي: `|`. +هذا جيد للبحث في مقطع نصي (string) واحد، لكنه يقتصر على نمط واحد فقط. يمكنك البحث عن أنماط متعددة باستخدام `alternation` أو رمز `OR` التالي: `|`. هذا المشغل يطابق الأنماط قبله أو بعده. على سبيل المثال، إذا كنت ترغب في مطابقة السلاسل (strings) باسم `yes` أو `no`، تريد regex إن يكون `/yes|no/`. @@ -22,49 +22,49 @@ dashedName: match-a-literal-string-with-different-possibilities # --hints-- -الـ regex الآتي `petRegex` يجب أن يرجع `true` للسلسلة `John has a pet dog.` +نمطـ regex الآتي `petRegex` يجب أن يرجع `true` للمقطع النصي `John has a pet dog.` ```js petRegex.lastIndex = 0; assert(petRegex.test('John has a pet dog.')); ``` -الـ regexا لآتي `petRegex` يجب أن يرجع `false` للسلسلة `Emma has a pet rock.` +نمط regex الآتي `petRegex` يجب أن يرجع `false` للمقطع النصي `Emma has a pet rock.` ```js petRegex.lastIndex = 0; assert(!petRegex.test('Emma has a pet rock.')); ``` -الـ regex الآتي `petRegex` يجب أن يرجع `true` للسلسلة `Emma has a pet bird.` +نمط regex الآتي `petRegex` يجب أن يرجع `true` للمقطع النصي `Emma has a pet bird.` ```js petRegex.lastIndex = 0; assert(petRegex.test('Emma has a pet bird.')); ``` -الـ regex الآتي `petRegex` يجب أن يرجع `true` للسلسلة `Liz has a pet cat.` +نمطـ regex الآتي `petRegex` يجب أن يرجع `true` للمقطع النصي `Liz has a pet cat.` ```js petRegex.lastIndex = 0; assert(petRegex.test('Liz has a pet cat.')); ``` -الـ regex الآتي `petRegex` يجب أن يرجع `false` للسلسلة `Kara has a pet dolphin.` +نمط regex الآتي `petRegex` يجب أن يرجع `false` للمقطع النصي `Kara has a pet dolphin.` ```js petRegex.lastIndex = 0; assert(!petRegex.test('Kara has a pet dolphin.')); ``` -الـ regex الآتي `petRegex` يجب أن يرجع `true` للسلسلة `Alice has a pet fish.` +نمط regex الآتي `petRegex` يجب أن يرجع `true` للمقطع النصي `Alice has a pet fish.` ```js petRegex.lastIndex = 0; assert(petRegex.test('Alice has a pet fish.')); ``` -الـ regex الآتي `petRegex` يجب أن يرجع `false` للسلسلة `Jimmy has a pet computer.` +نمط regex الآتي `petRegex` يجب أن يرجع `false` للمقطع النصي `Jimmy has a pet computer.` ```js petRegex.lastIndex = 0; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-ending-string-patterns.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-ending-string-patterns.md index 097801f8194346..4d927880c4d623 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-ending-string-patterns.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-ending-string-patterns.md @@ -24,11 +24,11 @@ storyRegex.test(noEnding); # --instructions-- -استخدم رمز الدولار (`$`) لمطابقة السلسلة `caboose` في نهاية السلسة `caboose`. +استخدم رمز الدولار (`$`) لمطابقة المقطع النصي `caboose` في نهاية `caboose`. # --hints-- -يجب عليك البحث عن `caboose` باستخدام علامة الدولار `$` في الـ regex. +يجب عليك البحث عن `caboose` باستخدام علامة الدولار `$` في نمط regex. ```js assert(lastRegex.source == 'caboose$'); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-literal-strings.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-literal-strings.md index 12e588224205c4..fb762fe43fc52a 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-literal-strings.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-literal-strings.md @@ -1,6 +1,6 @@ --- id: 587d7db3367417b2b2512b8f -title: مطابقة السلاسل النصية (Match Literal Strings) +title: مطابقة النصوص الحرفية challengeType: 1 forumTopicId: 301355 dashedName: match-literal-strings @@ -8,7 +8,7 @@ dashedName: match-literal-strings # --description-- -في التحدي الأخير، بحثت عن كلمة `Hello` باستخدام regular expression الاتي `/Hello/`. هذا regex يبحث عن مطابقة حرفية في string الآتي `Hello`. إليك مثال آخر يبحث عن مطابقة حرفية في string الآتي `Kevin`: +في التحدي الأخير، بحثت عن كلمة `Hello` باستخدام regular expression الاتي `/Hello/`. هذا regex يبحث عن مطابقة حرفية في المقطع النصي الآتي `Hello`. إليك مثال آخر يبحث عن مطابقة حرفية في المقطع النصي الآتي `Kevin`: ```js let testStr = "Hello, my name is Kevin."; @@ -31,11 +31,11 @@ wrongRegex.test(testStr); # --instructions-- -أكمل regex الأتي `waldoRegex` للعثور على `"Waldo"` في السلسلة (string) النصية `waldoIsHiding` مع مطابقة حرفية. +أكمل regex الأتي `waldoRegex` للعثور على `"Waldo"` في المقطع (string) النصية `waldoIsHiding` مع مطابقة حرفية. # --hints-- -إن regex الخاص بك `waldoRegex` يجب أن يجد string الآتي `Waldo` +إن regex الخاص بك `waldoRegex` يجب أن يجد المقطع النصي الآتي `Waldo` ```js waldoRegex.lastIndex = 0; @@ -49,7 +49,7 @@ waldoRegex.lastIndex = 0; assert(!waldoRegex.test('Somewhere is hiding in this text.')); ``` -يجب عليك إجراء مطابقة حرفية للسلسلة (string) النصية باستخدام regex الخاص بك. +يجب عليك إجراء مطابقة حرفية للمقطع النصية (string) باستخدام regex الخاص بك. ```js assert(!/\/.*\/i/.test(code)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-single-character-with-multiple-possibilities.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-single-character-with-multiple-possibilities.md index b8c50b627d7e19..cf5d9ef796c04c 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-single-character-with-multiple-possibilities.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/match-single-character-with-multiple-possibilities.md @@ -8,7 +8,7 @@ dashedName: match-single-character-with-multiple-possibilities # --description-- -تعلمت كيفية مطابقة الأنماط الحرفية (`/literal/`) و wildcard character (`/./`). هذه هي أقصى درجات التعبيرات النمطية، حيث يجد احدهم التطابقات الدقيقة والآخر يطابق كل شيء. وهناك خيارات تمثل توازنا بين الطرفين. +تعلمت كيفية مطابقة الأنماط الحرفية (`/literal/`) و wildcard character (`/./`). هذه هي أقصى درجات العبارات النمطية، حيث يجد احدهم التطابقات الدقيقة والآخر يطابق كل شيء. وهناك خيارات تمثل توازنا بين الطرفين. يمكنك البحث عن نمط حرفي مع بعض المرونة باستخدام character classes. تتيح لك Character classes تعريف مجموعة من الأحرف التي ترغب في تطابقها عن طريق وضعها داخل الأقواس المربعة (`[` و `]`). @@ -30,7 +30,7 @@ bogStr.match(bgRegex); # --instructions-- -استخدم character class مع حروف (`a`, `e`, `i`, `o`, `u`) في regex الخاص بك `vowelRegex` للعثور على جميع الـ vowels في السلسلة `quoteSample`. +استخدم character class مع حروف (`a`, `e`, `i`, `o`, `u`) في regex الخاص بك `vowelRegex` للعثور على جميع الـ vowels في المقطع النصي `quoteSample`. **ملاحظة**: تأكد من مطابقة الـ vowels الكبيرة و الصغيرة. diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/remove-whitespace-from-start-and-end.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/remove-whitespace-from-start-and-end.md index d25e5f3bb03c96..a3430ef252ea47 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/remove-whitespace-from-start-and-end.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/remove-whitespace-from-start-and-end.md @@ -14,7 +14,7 @@ dashedName: remove-whitespace-from-start-and-end اكتب regex و استخدم الطرق المناسبة لإزالة الـ whitespace في بداية و نهاية الـ strings. -**ملاحظة:** دالة `String.prototype.trim()` ستعمل هنا، ولكن ستحتاج إلى إكمال هذا التحدي باستخدام regular expressions. +**ملاحظة:** طريقة `String.prototype.trim()` ستعمل هنا، ولكن ستحتاج إلى إكمال هذا التحدي باستخدام regular expressions. # --hints-- @@ -24,7 +24,7 @@ dashedName: remove-whitespace-from-start-and-end assert(result === 'Hello, World!'); ``` -يجب ألا يستخدم الحل الخاص بك دالة `String.prototype.trim()`. +يجب ألا يستخدم حلك طريقة `String.prototype.trim()`. ```js assert(!code.match(/\.?[\s\S]*?trim/)); diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/reuse-patterns-using-capture-groups.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/reuse-patterns-using-capture-groups.md index 255d756788bab5..2d58694ec92671 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/reuse-patterns-using-capture-groups.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/reuse-patterns-using-capture-groups.md @@ -28,7 +28,7 @@ repeatRegex.test(repeatStr); // Returns true repeatStr.match(repeatRegex); // Returns ["row row row", "row"] ``` -سيؤدي استخدام دالة `.match()` على string إلى ارجاع array بداخله الـ substring المطابق، جنبا إلى جنب مع الـ captured groups الخاصين به. +سيؤدي استخدام طريقة `.match()` على مقطع (string) إلى أنتاج قائمة (array) بداخلها مقطع فرعي (substring) المطابق، جنبا إلى جنب مع المجموعات المستخدمة الخاصين بها. # --instructions-- @@ -96,6 +96,20 @@ reRegex.lastIndex = 0; assert(reRegex.test('10 10 10')); ``` +Your regex should not match the string `42\t42\t42`. + +```js +reRegex.lastIndex = 0; +assert(!reRegex.test('42\t42\t42')); +``` + +Your regex should not match the string `42 42 42`. + +```js +reRegex.lastIndex = 0; +assert(!reRegex.test('42 42 42')); +``` + # --seed-- ## --seed-contents-- @@ -110,6 +124,6 @@ let result = reRegex.test(repeatNum); ```js let repeatNum = "42 42 42"; -let reRegex = /^(\d+)\s\1\s\1$/; +let reRegex = /^(\d+) \1 \1$/; let result = reRegex.test(repeatNum); ``` diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/use-capture-groups-to-search-and-replace.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/use-capture-groups-to-search-and-replace.md index 6a42887571d907..cd0a8f778e35a3 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/use-capture-groups-to-search-and-replace.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/use-capture-groups-to-search-and-replace.md @@ -10,7 +10,7 @@ dashedName: use-capture-groups-to-search-and-replace البحث أمر مفيد. ومع ذلك ، يمكنك جعل البحث أكثر قوة عندما يغير أيضًا (أو يستبدل) النص الذي تطابقه. -يمكنك البحث عن النص واستبداله في سلسلة باستخدام `.replace()` على string. المدخلات لـ `.replace()` هي أولا نمط الـ regex الذي تريد البحث عنه. المعلمة الثانية هي الـ string الذي يحل محل المطابقة أو function للقيام بشيء ما. +يمكنك البحث عن النص واستبداله في سلسلة باستخدام `.replace()` على string. المدخلات لـ `.replace()` هي أولا نمط الـ regex الذي تريد البحث عنه. إن الوسيط (parameter) الثاني مقطع نصي (string) الذي يحل محل المطابقة أو وظيفة (function) للقيام بشيء ما. ```js let wrongText = "The sky is silver."; diff --git a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/using-the-test-method.md b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/using-the-test-method.md index 8090e071b36c14..51b4814993e0f4 100644 --- a/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/using-the-test-method.md +++ b/curriculum/challenges/arabic/02-javascript-algorithms-and-data-structures/regular-expressions/using-the-test-method.md @@ -1,6 +1,6 @@ --- id: 587d7db3367417b2b2512b8e -title: Using the Test Method +title: استخدام طريقة Test challengeType: 1 forumTopicId: 301369 dashedName: using-the-test-method @@ -8,11 +8,11 @@ dashedName: using-the-test-method # --description-- -تستخدم الـ Regular expressions في لغات البرمجة لمطابقة أجزاء من الـ strings. أنت تنشئ أنماطا لمساعدتك على القيام بهذه المطابقة. +تستخدم Regular expressions في لغات البرمجة لمطابقة أجزاء من المقاطع النصية (strings). أنت تنشئ أنماطا لمساعدتك على القيام بهذه المطابقة. -إذا كنت ترغب في العثور على كلمة `the` في السلسلة `The dog chased the cat`، يمكنك استخدام الـ regular expression التالي: `/the/`. لاحظ أن علامات الاقتباس غير مطلوبة في ال regular expression. +إذا كنت ترغب في العثور على كلمة `the` في مقطع `The dog chased the cat`، يمكنك استخدام regular expression التالي: `/the/`. لاحظ أن علامات الاقتباس غير مطلوبة في regular expression. -لدى جافا سكريبت طرق متعددة لاستخدام regexes. إحدى الطرق لاختبار regex هي استخدام `.test()`. `.test()` تأخذ regex، وتطبقه على سلسلة (توضع داخل الأقواس)، وتعيد `true` أو `false` إذا عثر النمط الخاص بك على شيء أو لا. +لدى JavaScript طرق متعددة لاستخدام regexes. إحدى الطرق لاختبار regex هي استخدام طريقة (method) تسمى `.test()`. يوضع regex في طريقة `.test()`، وتطبقه على مقطع نصي (توضع داخل الأقواس)، وتنتج `true` أو `false` إذا عثر نمطك على شيء أو لا. ```js let testStr = "freeCodeCamp"; @@ -20,11 +20,11 @@ let testRegex = /Code/; testRegex.test(testStr); ``` -دالة `test` هنا، ستعيد `true`. +ستنتج طريقة `test` حالة `true` هنا. # --instructions-- -طبق `myRegex` على السلسلة `myString` باستخدام `.test()`. +طبق regex يسمى `myRegex` على مقطع `myString` باستخدام طريقة `.test()`. # --hints-- @@ -34,7 +34,7 @@ testRegex.test(testStr); assert(code.match(/myRegex.test\(\s*myString\s*\)/)); ``` -يجب أن ترجع نتيجتك `true`. +يجب أن تنتج `true`. ```js assert(result === true); diff --git a/curriculum/challenges/arabic/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine.md b/curriculum/challenges/arabic/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine.md index 9047a6825469d9..d113b307ab59f2 100644 --- a/curriculum/challenges/arabic/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine.md +++ b/curriculum/challenges/arabic/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-drum-machine.md @@ -1,6 +1,6 @@ --- id: 587d7dbc367417b2b2512bae -title: أنشئ Drum Machine +title: أنشئ آلة الطبول challengeType: 3 forumTopicId: 301370 dashedName: build-a-drum-machine diff --git a/curriculum/challenges/arabic/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator.md b/curriculum/challenges/arabic/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator.md index 97c68f2113b55a..119c29cdf6c4fa 100644 --- a/curriculum/challenges/arabic/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator.md +++ b/curriculum/challenges/arabic/03-front-end-development-libraries/front-end-development-libraries-projects/build-a-javascript-calculator.md @@ -1,6 +1,6 @@ --- id: bd7158d8c442eddfaeb5bd17 -title: أنشئ حاسبة باستخدام JavaScript +title: بناء آلة حاسبة باستخدام JavaScript challengeType: 3 forumTopicId: 301371 dashedName: build-a-javascript-calculator diff --git a/curriculum/challenges/arabic/03-front-end-development-libraries/jquery/target-even-elements-using-jquery.md b/curriculum/challenges/arabic/03-front-end-development-libraries/jquery/target-even-elements-using-jquery.md index 2a831ae794fe3d..43def3859d527d 100644 --- a/curriculum/challenges/arabic/03-front-end-development-libraries/jquery/target-even-elements-using-jquery.md +++ b/curriculum/challenges/arabic/03-front-end-development-libraries/jquery/target-even-elements-using-jquery.md @@ -21,7 +21,7 @@ dashedName: target-even-elements-using-jquery $(".target:odd").addClass("animated shake"); ``` -حاول تحديد جميع العناصر الزوجية `target` وإعطائها فئات `animated` و `shake`. تذكر أن **الأرقام الزوجية** تشير إلى موضع العناصر التي لها نظام قائم على الصفر. +حاول تحديد جميع العناصر الزوجية `target` وإعطائها فئات `animated` و `shake`. تذكر أن **الأرقام الزوجية** تشير إلى موقع العناصر التي لها نظام ترتيب من الصفر. # --hints-- diff --git a/curriculum/challenges/arabic/03-front-end-development-libraries/react/create-a-controlled-input.md b/curriculum/challenges/arabic/03-front-end-development-libraries/react/create-a-controlled-input.md index cf8973cd285cc6..8b895c3e1c07b3 100644 --- a/curriculum/challenges/arabic/03-front-end-development-libraries/react/create-a-controlled-input.md +++ b/curriculum/challenges/arabic/03-front-end-development-libraries/react/create-a-controlled-input.md @@ -14,7 +14,7 @@ dashedName: create-a-controlled-input يحتوي محرر التعليمات البرمجية على الهيكل العظمي لمكون يسمى `ControlledInput` لإنشاء عنصر `input` المتحكم بيه. تم فعلًا تهيئة `state` للمكون (component) مع خاصية (property) تسمى `input` التي تحتوي على مقطع نصي (string) فارغة. هذه القيمة تمثل نوع النص المستخدم في حقل `input`. -أولا، إنشاء طريقة تسمى `handleChange()` تحتوي على الوسيطة تسمى `event`. عندما يتم تسمية الطريقة، فإنها تتلقى كائن `event` يحتوي على سلسلة من النص من عنصر `input`. يمكنك الوصول إلى هذه السلسلة باستخدام `event.target.value` داخل الطريقة. حديث خاصية (property) تسمى `input` في `state` للمكون (component) مع هذا المقطع النصي (string) الجديدة. +أولا، إنشاء طريقة تسمى `handleChange()` تحتوي على وسيط يسمى `event`. عندما يتم تسمية الطريقة، فإنها تتلقى كائن `event` يحتوي على سلسلة من النص من عنصر `input`. يمكنك الوصول إلى هذه السلسلة باستخدام `event.target.value` داخل الطريقة. حديث خاصية (property) تسمى `input` في `state` للمكون (component) مع هذا المقطع النصي (string) الجديدة. في طريقة `render`، أنشئ عنصر `input` فوق علامة `h4`. أضف سمة (attribute) تسمى `value` تساوي خاصية (property) تسمى `input` في `state` للمكون (component). ثم أضف معالج الحدث `onChange()` إلى طريقة `handleChange()`. diff --git a/curriculum/challenges/arabic/03-front-end-development-libraries/react/render-a-class-component-to-the-dom.md b/curriculum/challenges/arabic/03-front-end-development-libraries/react/render-a-class-component-to-the-dom.md index d34c6fdd95385d..5a74017ecd39cd 100644 --- a/curriculum/challenges/arabic/03-front-end-development-libraries/react/render-a-class-component-to-the-dom.md +++ b/curriculum/challenges/arabic/03-front-end-development-libraries/react/render-a-class-component-to-the-dom.md @@ -10,7 +10,7 @@ dashedName: render-a-class-component-to-the-dom يمكنك تذكر استخدام API ReactDOM في تحدي سابق لإضافة عناصر JSX إلى DOM. وستبدو عملية تقديم مكونات React متشابهة جدا. لقد ركزت التحديات القليلة الماضية على المكونات (components) والتكوين (composition)، لذلك تم التقديم لك خلف الكواليس. ومع ذلك، لن يقدم أي من رمز React الذي تكتبه إلى DOM دون أستدعاء API ReactDOM. -إليك تذكير بكفية كتابة الصيغة: `ReactDOM.render(componentToRender, targetNode)`. الحَجَّة الأولى هي عنصر React الذي تريد أنتاجه. الحجة الثانية هي نقطة التواصل DOM التي تريد أن تجعل ذلك المكون داخلها. +إليك تذكير بكفية كتابة الصيغة: `ReactDOM.render(componentToRender, targetNode)`. الحَجَّة الأولى هي عنصر React الذي تريد أنتاجه. الحجة الثانية هي DOM node التي تريد أن تجعل ذلك المكون داخلها. يتم تمرير مكونات React إلى `ReactDOM.render()` بشكل مختلف قليلا عن عناصر JSX. بالنسبة لعناصر JSX ، يمكنك تمرير اسم العنصر الذي تريد أنتاجه. لكن، بالنسبة لمكونات React، تحتاج إلى استخدام نفس الجملة كما لو كنت تقدم مكوناً متداخلاً، على سبيل المثال `ReactDOM.render(, targetNode)`. أنت تستخدم هذه الجملة لكل من مكونات فئة ES6 والمكونات الوظيفية ES6. diff --git a/curriculum/challenges/arabic/03-front-end-development-libraries/react/render-html-elements-to-the-dom.md b/curriculum/challenges/arabic/03-front-end-development-libraries/react/render-html-elements-to-the-dom.md index 092b3ab720829a..80f52e03146c14 100644 --- a/curriculum/challenges/arabic/03-front-end-development-libraries/react/render-html-elements-to-the-dom.md +++ b/curriculum/challenges/arabic/03-front-end-development-libraries/react/render-html-elements-to-the-dom.md @@ -10,13 +10,13 @@ dashedName: render-html-elements-to-the-dom حتى الآن، تعلمت أن JSX أداة مناسبة لكتابة HTML مقروءة داخل JavaScript. مع React، يمكننا تقديم JSX قاصدًا إلى HTML DOM باستخدام React الذي يقدم API المعروف باسم ReactDOM. -ReactDOM يوفر طريقة بسيطة لتقديم عناصر React إلى DOM التي تبدو مثل: `ReactDOM.render(componentToRender, targetNode)`, حيث الحَجَّة الأولى هي عنصر React أو المكون الذي تريد أن تنتجه، والحجة الثانية هي نقطة التواصل DOM التي تريد تقديم المكون إليها. +ReactDOM يوفر طريقة بسيطة لتقديم عناصر React إلى DOM التي تبدو مثل: `ReactDOM.render(componentToRender, targetNode)`, حيث الحَجَّة الأولى هي عنصر React أو المكون الذي تريد أن تنتجه، والحجة الثانية هي node DOM التي تريد تقديم المكون إليها. كما تتوقع، `ReactDOM.render()` يجب أن يستدعى بعد إعلانات عناصر JSX، تماما مثل كيفية الإعلان عن المتغيرات قبل استخدامها. # --instructions-- -يحتوي محرر التعليمات البرمجية على مكون JSX بسيط. استخدم طريقة `ReactDOM.render()` لإضافة هذا المكون إلى الصفحة. يمكنك تمرير عناصر JSX المحددة قاصدًا كالحجة الأولى واستخدام `document.getElementById()` لتحديد نقطة التواصل DOM لتقديمها إليها. هناك `div` مع `id='challenge-node'` متاح لك للاستخدام. تيقن من عدم تغيير ثابت `JSX`. +يحتوي محرر التعليمات البرمجية على مكون JSX بسيط. استخدم طريقة `ReactDOM.render()` لإضافة هذا المكون إلى الصفحة. يمكنك تمرير عناصر JSX المحددة قاصدًا كالحجة الأولى واستخدام `document.getElementById()` لتحديد DOM node لتقديمها إليها. هناك `div` مع `id='challenge-node'` متاح لك للاستخدام. تيقن من عدم تغيير ثابت `JSX`. # --hints-- @@ -38,7 +38,7 @@ assert(JSX.props.children[0].type === 'h1'); assert(JSX.props.children[1].type === 'p'); ``` -يجب أن ينتج عنصر JSX المقدم إلى نقطة التواصل DOM مع معرف `challenge-node`. +يجب أن ينتج عنصر JSX المقدم إلى DOM node مع معرف `challenge-node`. ```js assert( diff --git a/curriculum/challenges/arabic/03-front-end-development-libraries/redux/create-a-redux-store.md b/curriculum/challenges/arabic/03-front-end-development-libraries/redux/create-a-redux-store.md index ac656a51b82cd4..17ef90c6f3c84a 100644 --- a/curriculum/challenges/arabic/03-front-end-development-libraries/redux/create-a-redux-store.md +++ b/curriculum/challenges/arabic/03-front-end-development-libraries/redux/create-a-redux-store.md @@ -20,7 +20,7 @@ Redux هو framework لإدارة الحالة (state) التي يمكن است إعلان متغير `store` عيينه إلى طريقة `createStore()`، مرورا في `reducer` كحجة. -**ملاحظة:** الكود في المحرر يستخدم بناء الجملة الافتراضي في ES6 لتهيئة هذه الحالة (reducer) للاحتفاظ بقيمة `5`. إذا لم تكن على دراية بالحجج الافتراضية (default arguments)، يمكنك الرجوع إلى قسم ES6 في المنهج الدراسي الذي يغطي هذا الموضوع. +**ملاحظة:** الكود في المحرر يستخدم بناء الجملة الافتراضي في ES6 لتهيئة هذه الحالة (reducer) للاحتفاظ بقيمة `5`. إذا لم تكن على دراية بالمعطيات الافتراضية (default arguments)، يمكنك الرجوع إلى قسم ES6 في المنهج الدراسي الذي يغطي هذا الموضوع. # --hints-- diff --git a/curriculum/challenges/arabic/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md b/curriculum/challenges/arabic/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md index 4e5032dafaafbf..863b906b94afb1 100644 --- a/curriculum/challenges/arabic/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md +++ b/curriculum/challenges/arabic/03-front-end-development-libraries/sass/use-if-and-else-to-add-logic-to-your-styles.md @@ -39,7 +39,7 @@ dashedName: use-if-and-else-to-add-logic-to-your-styles # --instructions-- -إنشاء mixin يسمى `border-stroke` التي تأخذ حَجَّة `$val`. يجب على mixin التحقق من الشروط التالية باستخدام `@if`، و `@else if`، و `@else`: +إنشاء mixin يسمى `border-stroke` التي تأخذ وسيط `$val`. يجب على mixin التحقق من الشروط التالية باستخدام `@if`، و `@else if`، و `@else`: ```scss light - 1px solid black @@ -51,7 +51,7 @@ heavy - 6px solid black # --hints-- -يجب أن تعلن التعليمات البرمجية الخاصة بك mixin اسمه `border-stroke` يحتوي على حِجَّة اسمها `$val`. +يجب أن يعلن الكود الخاص بك mixin اسمه `border-stroke` يحتوي على وسيط اسمه `$val`. ```js assert(code.match(/@mixin\s+?border-stroke\s*?\(\s*?\$val\s*?\)\s*?{/gi)); diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-bar-chart.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-bar-chart.md index 4e648ec9b72daa..5a09db11fe9005 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-bar-chart.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-bar-chart.md @@ -1,6 +1,6 @@ --- id: bd7168d8c242eddfaeb5bd13 -title: Visualize Data with a Bar Chart +title: التمثيل البياني باستخدام مخطط الأعمدة challengeType: 3 forumTopicId: 301464 dashedName: visualize-data-with-a-bar-chart @@ -8,33 +8,33 @@ dashedName: visualize-data-with-a-bar-chart # --description-- -**Objective:** Build an app that is functionally similar to this: https://bar-chart.freecodecamp.rocks. +**متطلبات:** قم ببناء تطبيق يُشبه في وظيفته https://bar-chart.freecodecamp.rocks. Fulfill the below user stories and get all of the tests to pass. Use whichever libraries or APIs you need. Give it your own personal style. -You can use HTML, JavaScript, CSS, and the D3 svg-based visualization library. The tests require axes to be generated using the D3 axis property, which automatically generates ticks along the axis. These ticks are required for passing the D3 tests because their positions are used to determine alignment of graphed elements. You will find information about generating axes at . Required (non-virtual) DOM elements are queried on the moment of each test. If you use a frontend framework (like Vue for example), the test results may be inaccurate for dynamic content. We hope to accommodate them eventually, but these frameworks are not currently supported for D3 projects. +You can use HTML, JavaScript, CSS, and the D3 svg-based visualization library. The tests require axes to be generated using the D3 axis property, which automatically generates ticks along the axis. These ticks are required for passing the D3 tests because their positions are used to determine alignment of graphed elements. You will find information about generating axes at . Required DOM elements are queried on the moment of each test. If you use a frontend framework (like Vue for example), the test results may be inaccurate for dynamic content. We hope to accommodate them eventually, but these frameworks are not currently supported for D3 projects. **User Story #1:** My chart should have a title with a corresponding `id="title"`. -**User Story #2:** My chart should have a `g` element x-axis with a corresponding `id="x-axis"`. +**قصة المستخدم الثانية 2#:**: يجب أن يحتوي المخطط علي عنصر `g` علي المحور x (الأفقي) مع `id="x-axis"`. -**User Story #3:** My chart should have a `g` element y-axis with a corresponding `id="y-axis"`. +**قصة المُستخدم الثالثة 3#:** يجب أن يحتوى المخطط علي عُنصر `g` علي المحور y (العمودي) مع `id="y-axis"`. **User Story #4:** Both axes should contain multiple tick labels, each with a corresponding `class="tick"`. -**User Story #5:** My chart should have a `rect` element for each data point with a corresponding `class="bar"` displaying the data. +**قصة المٌستخدم الخامسة 5#:** يَجب أن يحتوي المخطط على عُنصر من نوع `rect` لكل معلومة مع عرض للبيانات بواسطة سمة `class="bar"`. -**User Story #6:** Each bar should have the properties `data-date` and `data-gdp` containing `date` and `GDP` values. +**User Story #6:** Each `.bar` should have the properties `data-date` and `data-gdp` containing `date` and `GDP` values. -**User Story #7:** The bar elements' `data-date` properties should match the order of the provided data. +**User Story #7:** The `.bar` elements' `data-date` properties should match the order of the provided data. -**User Story #8:** The bar elements' `data-gdp` properties should match the order of the provided data. +**User Story #8:** The `.bar` elements' `data-gdp` properties should match the order of the provided data. -**User Story #9:** Each bar element's height should accurately represent the data's corresponding `GDP`. +**User Story #9:** Each `.bar` element's height should accurately represent the data's corresponding `GDP`. -**User Story #10:** The `data-date` attribute and its corresponding bar element should align with the corresponding value on the x-axis. +**User Story #10:** The `data-date` attribute and its corresponding `.bar` element should align with the corresponding value on the x-axis. -**User Story #11:** The `data-gdp` attribute and its corresponding bar element should align with the corresponding value on the y-axis. +**User Story #11:** The `data-gdp` attribute and its corresponding `.bar` element should align with the corresponding value on the y-axis. **User Story #12:** I can mouse over an area and see a tooltip with a corresponding `id="tooltip"` which displays more information about the area. diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-choropleth-map.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-choropleth-map.md index 7d17875db0535c..1770327c9ca1f0 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-choropleth-map.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-choropleth-map.md @@ -12,7 +12,7 @@ dashedName: visualize-data-with-a-choropleth-map Fulfill the below user stories and get all of the tests to pass. Use whichever libraries or APIs you need. Give it your own personal style. -You can use HTML, JavaScript, CSS, and the D3 svg-based visualization library. Required (non-virtual) DOM elements are queried on the moment of each test. If you use a frontend framework (like Vue for example), the test results may be inaccurate for dynamic content. We hope to accommodate them eventually, but these frameworks are not currently supported for D3 projects. +You can use HTML, JavaScript, CSS, and the D3 svg-based visualization library. Required DOM elements are queried on the moment of each test. If you use a frontend framework (like Vue for example), the test results may be inaccurate for dynamic content. We hope to accommodate them eventually, but these frameworks are not currently supported for D3 projects. **User Story #1:** My choropleth should have a title with a corresponding `id="title"`. diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-heat-map.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-heat-map.md index cd7e5632a5dd97..8cf5bc2bf8c9b9 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-heat-map.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-heat-map.md @@ -12,7 +12,7 @@ dashedName: visualize-data-with-a-heat-map Fulfill the below user stories and get all of the tests to pass. Use whichever libraries or APIs you need. Give it your own personal style. -You can use HTML, JavaScript, CSS, and the D3 svg-based visualization library. Required (non-virtual) DOM elements are queried on the moment of each test. If you use a frontend framework (like Vue for example), the test results may be inaccurate for dynamic content. We hope to accommodate them eventually, but these frameworks are not currently supported for D3 projects. +You can use HTML, JavaScript, CSS, and the D3 svg-based visualization library. Required DOM elements are queried on the moment of each test. If you use a frontend framework (like Vue for example), the test results may be inaccurate for dynamic content. We hope to accommodate them eventually, but these frameworks are not currently supported for D3 projects. **User Story #1:** My heat map should have a title with a corresponding `id="title"`. diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-scatterplot-graph.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-scatterplot-graph.md index 7f1d00bb3d0711..1d62ae7bd03a20 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-scatterplot-graph.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-scatterplot-graph.md @@ -8,19 +8,19 @@ dashedName: visualize-data-with-a-scatterplot-graph # --description-- -**Objective:** Build an app that is functionally similar to this: https://scatterplot-graph.freecodecamp.rocks. +**متطلبات:** كم ببناء تطبيق يشبه في وظيفته https://scatterplot-graph.freecodecamp.rocks. Fulfill the below user stories and get all of the tests to pass. Use whichever libraries or APIs you need. Give it your own personal style. -يمكنك استخدام HTML و JavaScript و CSS و مكتبة التصوير المستندة D3. تطلب الاختبارات إنشاء محاور (axes) باستخدام خاصية المحور في D3، الذي يؤدي تِلْقائيًا إلى وضع علامات على طول المحور. وهذه العلامات لازمة لاجتياز اختبارات D3, لأن تُستخدم مواقعها لتحديد محاذاة العناصر المرسومة بيانيٍ. ستجد معلومات حول إنشاء محاور في . يتم الاستفسار عن العناصر المطلوبة DOM (غير متغيرة) في لحظة إجراء كل اختبار. إذا كنت تستخدم framework (مثل Vue على سبيل المثال)، قد تكون نتائج الاختبار غير دقيقة للمحتوى الديناميكي. ونأمل أن نستوعبها في المستقبل، ولكن هذه frameworks غير مدعومة حاليا لمشاريع D3. +يمكنك استخدام HTML و JavaScript و CSS و مكتبة التصوير المستندة D3. تطلب الاختبارات إنشاء المحاور (axes) باستخدام خاصية axis في D3، الذي يؤدي تِلْقائيًا إلى وضع علامات (ticks) على طول المحور. وهذه العلامات لازمة لاجتياز اختبارات D3, لأن مواقعها تُستخدم لتحديد محاذاة العناصر المرسومة بيانيٍ. ستجد معلومات حول إنشاء المحاور في . Required DOM elements are queried on the moment of each test. إذا كنت تستخدم framework (مثل Vue على سبيل المثال)، قد تكون نتائج الاختبار غير دقيقة للمحتوى الديناميكي. ونأمل أن نستوعبها في المستقبل، ولكن هذه frameworks غير مدعومة حاليا لمشاريع D3. **قصة المستخدم 1:** يمكنني أن أرى عنصر title مع موافقه `id="title"`. -**قصة المستخدم 2:** يمكنني رؤية محور أفقي (x-axis) يوافق بمتغير يحتوي على `id="x-axis"`. +**قصة المستخدم 2:** يمكنني رؤية محور أفقي (x-axis) يحتوي على سمة `id="x-axis"`. -**قصة المستخدم 3:** يمكنني رؤية محور رئسي (y-axis) يوافق بمتغير يحتوي على `id="y-axis"`. +**قصة المستخدم 3:** يمكنني رؤية محور رئسي (y-axis) يحتوي على `id="y-axis"`. -**قصة المستخدم 4:** يمكنني أن أرى نقاط (dots) ولكل منها فئة (class) يسمى `dot`، التي تمثل البيانات التي يتم تخطيطها. +**قصة المستخدم 4:** يمكنني أن أرى نقاط (dots) ولكل منها فئة (class) `dot`، التي تمثل البيانات التي يتم رسمها. **قصة المستخدم 5:** كل نقطة يجب أن تحتوي على الخصائص `data-xvalue` و `data-yvalue` التي توافق القيم `x` و `y`. @@ -30,25 +30,25 @@ Fulfill the below user stories and get all of the tests to pass. Use whichever l **قصة المستخدم 8:** يجب أن توافق `data-yvalue` ونقطتها الموافقة مع النقطة/القيمة الموافقة على محور أفقي (y-axis). -**قصة المستخدم 9:** يمكننك رأيه تسميات علامة (tick) متعددة على المحور الرأسي (y-axis) مع تنسيق الوقت `%M:%S`. +**قصة المستخدم 9:** يمكننك رؤية تسميات علامة (tick) متعددة على المحور الرأسي (y-axis) مع تنسيق الوقت `%M:%S`. -**قصة المستخدم 10:** يمكننك رأيه تسميات علامة (tick) متعددة على المحور الأفقي (x-axis) الذي يظهر السنة. +**قصة المستخدم 10:** يمكننك رؤية تسميات علامة (tick) متعددة على المحور الأفقي (x-axis) الذي يظهر السنة. -**قصة المستخدم 11:** يمكننك رأيه نطاق (range) تسميات (labels) المحور الأفقي (x-axis) يقع ضمن نطاق بيانات المحور الأفقي (x-axis) فعلاً. +**قصة المستخدم 11:** يمكننك رؤية نطاق (range) تسميات (labels) المحور الأفقي (x-axis) يقع ضمن نطاق بيانات المحور الأفقي (x-axis) فعلاً. -**قصة المستخدم 12:** يمكننك رأيه نطاق (range) تسميات (labels) المحور الرأسي (y-axis) تقع ضمن نطاق بيانات المحور الرأسي (y-axis) فعلاً. +**قصة المستخدم 12:** يمكننك رؤية نطاق (range) تسميات (labels) المحور الرأسي (y-axis) تقع ضمن نطاق بيانات المحور الرأسي (y-axis) فعلاً. -**قصة المستخدم 13:** يمكننك رؤية legend تحتوي على نص وصفي يحتوي على `id="legend"`. +**قصة المستخدم 13:** يمكننك رؤية legend تحتوي على نص وصفي وله سمة `id="legend"`. -**قصة المستخدم 14:** يمكننك تحريك الفأرة (mouse) فوق منطقة ورأيه أدوات نصيحة (tooltip) موافق `id="tooltip"`، التي تعرض المزيد من المعلومات حول المنطقة. +**قصة المستخدم 14:** عند تحريك الفأر (mouse) فوق منطقة سترى أدوات نصيحة (tooltip) لها سمة `id="tooltip"`، وهي تعرض المزيد من المعلومات عن المنطقة. **قصة المستخدم 15:** يجب أن تحتوي تلميح أدواتك (tooltip) على خاصية `data-year` التي تتوافق مع `data-xvalue` في المنطقة النشطة. -إليك مجموعة البيانات التي ستحتاج إلى إكمال هذا المشروع: `https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/cyclist-data.json` +إليك مجموعة البيانات التي ستحتاج لإكمال هذا المشروع: `https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/cyclist-data.json` -You can build your project by using this CodePen template and clicking `Save` to create your own pen. Or you can use this CDN link to run the tests in any environment you like: `https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js` +يمكنك بناء مشروعك عن طريق استخدام هذا نموذج CodePen والنقر على `Save` لإنشاء pen خاص بك. Or you can use this CDN link to run the tests in any environment you like: `https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js` -Once you're done, submit the URL to your working project with all its tests passing. +بمجرد أن تنتهي، ارسل عنوان URL لمشروعك مع اجتياز جميع الاختبارات. # --solutions-- diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-treemap-diagram.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-treemap-diagram.md index 3e26785b9ecef2..bfa9e7321a01ad 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-treemap-diagram.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-projects/visualize-data-with-a-treemap-diagram.md @@ -12,7 +12,7 @@ dashedName: visualize-data-with-a-treemap-diagram Fulfill the below user stories and get all of the tests to pass. Use whichever libraries or APIs you need. Give it your own personal style. -You can use HTML, JavaScript, CSS, and the D3 svg-based visualization library. The tests require axes to be generated using the D3 axis property, which automatically generates ticks along the axis. These ticks are required for passing the D3 tests because their positions are used to determine alignment of graphed elements. You will find information about generating axes at . Required (non-virtual) DOM elements are queried on the moment of each test. If you use a frontend framework (like Vue for example), the test results may be inaccurate for dynamic content. We hope to accommodate them eventually, but these frameworks are not currently supported for D3 projects. +You can use HTML, JavaScript, CSS, and the D3 svg-based visualization library. The tests require axes to be generated using the D3 axis property, which automatically generates ticks along the axis. These ticks are required for passing the D3 tests because their positions are used to determine alignment of graphed elements. You will find information about generating axes at . Required DOM elements are queried on the moment of each test. If you use a frontend framework (like Vue for example), the test results may be inaccurate for dynamic content. We hope to accommodate them eventually, but these frameworks are not currently supported for D3 projects. **User Story #1:** My tree map should have a title with a corresponding `id="title"`. diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-a-hover-effect-to-a-d3-element.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-a-hover-effect-to-a-d3-element.md index 5e51c08ff0397b..2162ce835316b7 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-a-hover-effect-to-a-d3-element.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-a-hover-effect-to-a-d3-element.md @@ -1,6 +1,6 @@ --- id: 587d7faa367417b2b2512bd4 -title: أضف تأثير عند تحرك المستخدم فوق عنصر (Hover Effect) إلى عنصر D3 +title: أضف تأثير عندما يحوم الماوس فوق عنصر (Hover Effect) D3 challengeType: 6 forumTopicId: 301469 dashedName: add-a-hover-effect-to-a-d3-element @@ -8,7 +8,7 @@ dashedName: add-a-hover-effect-to-a-d3-element # --description-- -من الممكن إضافة التأثيرات (effects) التي توضح العمود (bar) عندما يتحرك المستخدم فوقه (hovers) بالفأرة. حتى الآن، طبقت تصميم (style) لمستطيلات بواسطة طرق (methods) في D3 و SVG الموجودة داخلهم، ولكن يمكنك استعمال CSS أيضا. +من الممكن إضافة التأثيرات (effects) التي توضح العمود (bar) عندما يحوم الماوس فوقه (hovers). حتى الآن، طبقت تصميم (style) المستطيلات بواسطة طرق مدمجة (built-in methods) في D3 و SVG، ولكن يمكنك استعمال CSS أيضا. يمكنك تعيين فئة (class) من CSS إلى عناصر SVG مع طريقة (method) تسمى `attr()`. ثم تحتوي فئة الزائفة (pseudo-class) المسمى `:hover` على قواعد التصميم (style) الجديدة لأي تأثيرات عند تحرك المستخدم فوق عنصر (hover). diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-a-tooltip-to-a-d3-element.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-a-tooltip-to-a-d3-element.md index 4cca0a103d8aaf..cbb631c208f32c 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-a-tooltip-to-a-d3-element.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-a-tooltip-to-a-d3-element.md @@ -8,13 +8,13 @@ dashedName: add-a-tooltip-to-a-d3-element # --description-- -يظهر أداة لتلميح (tooltip) المزيد من معلومات العنصر في صفحة عندما ينتقل المستخدم فوق (hovers) هذا العنصر. هناك عدة طرق لإضافة أداة لتلميح (tooltip) لعرض بيانات، هذا التحدي يستخدم عنصر `title` في SVG. +يظهر أداة لتلميح (tooltip) المزيد من معلومات العنصر في صفحة عندما ينتقل المستخدم فوق (hovers) هذا العنصر. There are several ways to add a tooltip to a visualization. This challenge uses the SVG `title` element. يرافق `title` الطريقة (method) المسمى `text()` لإضافة البيانات بشكل ديناميكي إلى الأعمدة (bars). # --instructions-- -أربط عنصر `title` تحت كل نقطة التواصل (node) المسمى `rect`. ثم فعّيل الطريقة (method) المسمى `text()` مع وظيفة تعيد تفعيل (callback function) بحيث يعرض النص قيمة البيانات. +أربط عنصر `title` تحت كل node المسمى `rect`. ثم فعّيل الطريقة (method) المسمى `text()` مع وظيفة تعيد تفعيل (callback function) بحيث يعرض النص قيمة البيانات. # --hints-- @@ -24,55 +24,55 @@ dashedName: add-a-tooltip-to-a-d3-element assert($('title').length == 9); ``` -يجب أن يحتوي أول عنصر `title` على أداة لتلميح (tooltip) بنص `12`. +يجب أن يحتوي أول عنصر `title` على تلميح بنص `12`. ```js assert($('title').eq(0).text() == '12'); ``` -يجب أن يحتوي ثاني عنصر `title` على أداة لتلميح (tooltip) بنص `31`. +يجب أن يحتوي ثاني عنصر `title` على تلميح بنص `31`. ```js assert($('title').eq(1).text() == '31'); ``` -يجب أن يحتوي ثالث عنصر `title` على أداة لتلميح (tooltip) بنص `22`. +يجب أن يحتوي ثالث عنصر `title` على تلميح بنص `22`. ```js assert($('title').eq(2).text() == '22'); ``` -يجب أن يحتوي رابع عنصر `title` على أداة لتلميح (tooltip) بنص `17`. +يجب أن يحتوي رابع عنصر `title` على تلميح بنص `17`. ```js assert($('title').eq(3).text() == '17'); ``` -يجب أن يحتوي خامس عنصر `title` على أداة لتلميح (tooltip) بنص `25`. +يجب أن يحتوي خامس عنصر `title` على تلميح بنص `25`. ```js assert($('title').eq(4).text() == '25'); ``` -يجب أن يحتوي سادس عنصر `title` على أداة لتلميح (tooltip) بنص `18`. +يجب أن يحتوي سادس عنصر `title` على تلميح بنص `18`. ```js assert($('title').eq(5).text() == '18'); ``` -يجب أن يحتوي سابع عنصر `title` على أداة لتلميح (tooltip) بنص `29`. +يجب أن يحتوي سابع عنصر `title` على تلميح بنص `29`. ```js assert($('title').eq(6).text() == '29'); ``` -يجب أن يحتوي ثامن عنصر `title` على أداة لتلميح (tooltip) بنص `14`. +يجب أن يحتوي ثامن عنصر `title` على تلميح بنص `14`. ```js assert($('title').eq(7).text() == '14'); ``` -يجب أن يحتوي تاسع عنصر `title` على أداة لتلميح (tooltip) بنص `9`. +يجب أن يحتوي تاسع عنصر `title` على تلميح بنص `9`. ```js assert($('title').eq(8).text() == '9'); diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-attributes-to-the-circle-elements.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-attributes-to-the-circle-elements.md index 0412b2cc61906f..7b7468c32a489a 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-attributes-to-the-circle-elements.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-attributes-to-the-circle-elements.md @@ -8,17 +8,17 @@ dashedName: add-attributes-to-the-circle-elements # --description-- -أنشئت في التحدي السابق عناصر `circle` لكل نقطة في `dataset`، وربطهم بلوحة (canvas) في SVG. لكن D3 يحتاج إلى مزيد من المعلومات حول موضع (position) وحجم (size) كل `circle` لعرضها بشكل صحيح. +أنشئت في التحدي السابق عناصر `circle` لكل نقطة في `dataset`، وأضفتهم بلوحة (canvas) SVG. لكن D3 يحتاج إلى مزيد من المعلومات حول موقع (position) وحجم (size) كل `circle` لعرضها بشكل صحيح. -لدي `circle` في SVG ثلاث سمات (attributes) رئيسية. تكون السمات (attributes) المسمى `cx` و `cy` إحداثيات. ويخبروا D3 أين يضع (position) *مركز (center)* للشكل على اللوحة (canvas) من SVG. تغير سمة (attribute) نصف قطر (radius) (تكتب مثل: `r`) يأثر على حجم `circle`. +لدي `circle` في SVG ثلاث سمات (attributes) رئيسية. تكون السمات (attributes) المسمى `cx` و `cy` إحداثيات. ويخبروا D3 أين تضع *وَسَط (center)* الشكل على لوحة SVG. تحدد سمة نصف قطر (radius) (وتكتب: `r`) حجم الدائرة (`circle`). -مثل مقياس الإحداثيات `y` داخل `rect`، تقاس `cy` داخل `circle` من الجزء العلوي للوحة (canvas) في SVG، ليس من الأسفل. +مثل مقياس الإحداثيات `rect` داخل `y`، تقاس `cy` داخل `circle` من الجزء العلوي للوحة (canvas) SVG، ليس من الأسفل. -تقدر السمات (attributes) الثلاث جميعها استخدام وظيفة تعيد تفعيل (callback function) لتحديد قيمها بشكل ديناميكي. تذكر أن جميع الطرق (methods) مرتبطة بوظيفة `data(dataset)` تفعّل مرة واحدة لكل عنصر في `dataset`. The `d` parameter in the callback function refers to the current item in `dataset`, which is an array for each point. You use bracket notation, like `d[0]`, to access the values in that array. +تستطيع جميع السمات (attributes) الثلاث باستخدام وظيفة لإعادة التفعيل (callback function) لتحديد قيمها بشكل ديناميكي. تذكر أن جميع الطرق (methods) المسلسلة بعد وظيفة `data(dataset)` تفعّل مرة واحدة لكل عنصر في `dataset`. يشير الوسيط `d` في وظيفة إعادة التفعيل إلى العنصر الحالي في `dataset`، وهو قائمة لكل نقطة. استخدم رمز الأقواس، مثل `d[0]`، للوصول إلى القيم في تلك القائمة. # --instructions-- -Add `cx`, `cy`, and `r` attributes to the `circle` elements. The `cx` value should be the first number in the array for each item in `dataset`. The `cy` value should be based off the second number in the array, but make sure to show the chart right-side-up and not inverted. The `r` value should be `5` for all circles. +أضف السمات `cx` و `cy` و `r` إلى العناصر المسمى `circle`. The `cx` value should be the first number in the array for each item in `dataset`. The `cy` value should be based off the second number in the array, but make sure to show the chart right-side-up and not inverted. The `r` value should be `5` for all circles. # --hints-- diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-document-elements-with-d3.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-document-elements-with-d3.md index 56bcac531c57d9..2cf381b4368ad1 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-document-elements-with-d3.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/add-document-elements-with-d3.md @@ -10,13 +10,13 @@ dashedName: add-document-elements-with-d3 يحتوي D3 على عدة طرق (methods) التي تسمح لك بإضافة وتغيير العناصر في وثيقتك. -تختار طريقة (method) تسمى `select()` عنصراً واحداً من الوثيقة. إنها تأخذ وسيط (argument) كاسم العنصر الذي تريده وتنتج نقطة لتواصل (node) من HTML للعنصر الأول في المستند الذي يطابق الاسم. Here's an example: +تختار طريقة (method) `select()` عنصراً واحداً من الوثيقة. إنها تأخذ اسم العنصر الذي تريده كمعطى (argument)، وتنتج HTML node لأول عنصر في المستند يطابق الاسم. Here's an example: ```js const anchor = d3.select("a"); ``` -يجد المثال السابق أول علامة رابط (anchor) في الصفحة ويحفظ نقطتها لتواصل (node) من HTML في المتغير `anchor`. يمكنك استخدام طريقة الاختيار (select) مع الطرق (methods) أخرى. The `d3` part of the example is a reference to the D3 object, which is how you access D3 methods. +يجد المثال السابق أول علامة رابط (anchor) في الصفحة ويحفظ HTML node لها في المتغير `anchor`. يمكنك استخدام طريقة الاختيار (selection) مع طرق (methods) أخرى. The `d3` part of the example is a reference to the D3 object, which is how you access D3 methods. Two other useful methods are `append()` and `text()`. diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/change-styles-based-on-data.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/change-styles-based-on-data.md index 1ed6ae7d5e2051..a78a59348cd62d 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/change-styles-based-on-data.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/change-styles-based-on-data.md @@ -8,9 +8,7 @@ dashedName: change-styles-based-on-data # --description-- -D3 is about visualization and presentation of data. It's likely you'll want to change the styling of elements based on the data. You can use a callback function in the `style()` method to change the styling for different elements. - -For example, you may want to color a data point blue if it has a value less than 20, and red otherwise. You can use a callback function in the `style()` method and include the conditional logic. The callback function uses the `d` parameter to represent the data point: +D3 is about visualization and presentation of data. It's likely you'll want to change the styling of elements based on the data. For example, you may want to color a data point blue if it has a value less than 20, and red otherwise. You can use a callback function in the `style()` method and include the conditional logic. تستخدم وظيفة إعادة التفعيل على الوسيط `d` لتمثيل نقطة البيانات: ```js selection.style("color", (d) => { diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/change-the-presentation-of-a-bar-chart.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/change-the-presentation-of-a-bar-chart.md index dd3fa7ae7aae35..28e459bccdf5f0 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/change-the-presentation-of-a-bar-chart.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/change-the-presentation-of-a-bar-chart.md @@ -1,6 +1,6 @@ --- id: 587d7fa8367417b2b2512bca -title: تغيير مخطط بياني شريطي (Bar Chart) +title: تغيير التقديم لمخطط الأعمدة (Bar Chart) challengeType: 6 forumTopicId: 301481 dashedName: change-the-presentation-of-a-bar-chart @@ -8,17 +8,17 @@ dashedName: change-the-presentation-of-a-bar-chart # --description-- -وأنشأ التحدي السابق مخطط بياني شريطي (bar chart)، ولكن هناك بعض التغييرات في التنسيق الذي يمكن أن تحسن: +وأنشأ التحدي السابق مخطط أعمدة (bar chart)، ولكن هناك بعض التغييرات في التنسيق الذي يمكن أن تحسنه: -1) إضافة مساحة بين كل شريط لفصله بصرياً، عن طريق إضافة هامش (margin) إلى CSS لفئة تسمى `bar` +1) إضافة مساحة بين كل عمود لفصله بصرياً، عن طريق إضافة هامش (margin) إلى CSS لفئة `bar` -2) زيادة ارتفاع (height) الأشرطة لإظهار الفرق في القيم بشكل أفضل، عن طريق ضرب (multiplying) القيمة في عدد لزيادة الارتفاع +2) زيادة ارتفاع (height) الأعمدة لإظهار الفرق في القيم بشكل أفضل، عن طريق ضرب (multiplying) القيمة في عدد لزيادة الارتفاع # --instructions-- -أولاً، أضف `margin` بقيمة `2px` إلى قئة `bar` في علامة `style`. بعد ذلك، غيّر وظيفة تعيد تفعيل في `style()` بحيث تنتج `10` أضعاف قيمة البيانات الأصلية (بالإضافة إلى `px`). +أولاً، أضف `margin` بقيمة `2px` إلى فئة `bar` في علامة `style`. بعد ذلك، غيّر وظيفة إعادة التفعيل في طريقة `style()` بحيث تنتج `10` أضعاف قيمة البيانات الأصلية (بالإضافة إلى نص `px`). -**ملاحظة:** ضرب كل نقطة بيانات *بنفس* الثابت فقط يغيّر الحجم. إنه مثل تكبير الصورة، الذي لا يغير المقصود من البيانات الأساسية. +**ملاحظة:** ضرب كل نقطة بيانات *بنفس* الرَّقَم الثابت يغيّر المقياس فقط. إنه مثل تكبير الصورة، الذي لا يغير المقصود من البيانات الأساسية. # --hints-- diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/create-a-linear-scale-with-d3.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/create-a-linear-scale-with-d3.md index a5f0ad3b6745d7..8430009c519577 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/create-a-linear-scale-with-d3.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/create-a-linear-scale-with-d3.md @@ -8,13 +8,13 @@ dashedName: create-a-linear-scale-with-d3 # --description-- -يملأ البيانات المرسومة كل من مخطط بياني شريطي وانسياب (النِّقَاط المبعثرة) على لوحة SVG قاصدًا. بيد أنه إذا كان ارتفاع الشريط أو إحدى نِقَاط البيانات أكبر من الارتفاع أو العرض SVG، ستذهب خارج نطاق SVG. +رَسَم البيانات كلا من المخطوطان, أعمدة وانسياب (النِّقَاط المبعثرة), مباشرا على لوحة SVG. ولكن إذا كان ارتفاع العمود أو إحدى نِقَاط البيانات أكبر من ارتفاع أو عرض مساحة SVG، سيقع خارج نطاق منطقة SVG. -في D3، هناك مقاييس للمساعدة في ملأ البيانات. تكون `scales` وظائف (functions) تخبر البرنامَج كيفية ملأ مجموعة من نِقَاط البيانات الخام على البكسلات (px) في لوحة SVG. +في D3، هناك مقاييس (scales) للمساعدة في تخطيط البيانات. تكون `scales` وظائف (functions) تخبر البرنامَج كيفية ملأ مجموعة من نِقَاط البيانات الخام على عدد البكسلس (pixels) في لوحة SVG. -على سبيل المثال، قل أن لديك لوحة SVG بحجم 100x500، وأنت تريد ملأ الناتج إجمال المحلي (Gross Domestic Product) لعدد من الدول. ومجموعة الأعداد ستكون في حدود المليار أو تريليون دولار. يمكنك توفير D3 من المقياس لمعرفة كيفية وضع قيم الناتج المحلي الإجمالي الكبيرة في تلك المساحة 100x500. +على سبيل المثال، قل أن لديك لوحة SVG بحجم 100x500، وتريد رسم الناتج المحلي الإجمالي (Gross Domestic Product) لعدد من الدول. ومجموعة الأعداد ستكون في حدود المليار أو تريليون دولار. يمكنك توفير D3 من مقياس (scale) لمعرفة كيف توضع قيم الناتج المحلي الإجمالي (GDP) الكبيرة في تلك المساحة 100x500. -من غير المحتمل أن تملأ البيانات الخام كما هي. قبل الملأ، عيّن المقياس لكامل مجموعتك للبيانات. بحيث أن قيم `x` و `y` تتناسب مع عرض وطول اللوحة. +من غير المحتمل أن ترسم البيانات الخام كما هي. قبل الرسم، عيّن المقياس لكامل مجموعة البيانات. بحيث أن قيم `x` و `y` تتناسب مع عرض وطول اللوحة. ولدى D3 عدة أنواع من المقاييس. للحصول على مقياس خطي (linear scale) (يستخدم عادة مع البيانات الكمية (quantitative data))، هناك طريقة في D3 تسمى `scaleLinear()`: @@ -22,11 +22,11 @@ dashedName: create-a-linear-scale-with-d3 const scale = d3.scaleLinear() ``` -بشكل افتراضي، يستخدم المقياس عَلاقة الهُوِيَّة (identity relationship). تطابق قيمة المدخل (Input) قيمة المخرج (output). يشمل تحد أخر كيفية تغيير ذلك. +بشكل افتراضي، يستخدم المقياس عَلاقة الهُوِيَّة (identity relationship). تطابق قيمة المدخل (input) قيمة المخرج (output). يشمل تحدي أخر كيفية تغيير ذلك. # --instructions-- -تغيير متغير (variable) مسمى `scale` لإنشاء مقياس خطي (linear scale). ثم عيّن متغير (variable) مسمى `output` إلى scale, الذي فعلته بالإدخال وسيط بقيمة `50`. +غيّر المتغير `scale` لإنشاء مقياس خطي (linear scale). ثم عيّن متغير `output` إلى وظيفة scale, الذي فعَِلت بإدخال معطى بقيمة `50`. # --hints-- @@ -36,13 +36,13 @@ const scale = d3.scaleLinear() assert($('h2').text() == '50'); ``` -يجب أن يستخدم كودك طريقة (method) تسمى `scaleLinear()`. +يجب أن يستخدم كودك طريقة `scaleLinear()`. ```js assert(code.match(/\.scaleLinear/g)); ``` -يجب أن يُفاعِل متغير `output` وظيفة `scale` مع وسيط `50`. +يجب أن يُفعَِل متغير `output` وظيفة `scale` مع معطى `50`. ```js assert(output == 50 && code.match(/scale\(\s*?50\s*?\)/g)); diff --git a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/dynamically-set-the-coordinates-for-each-bar.md b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/dynamically-set-the-coordinates-for-each-bar.md index 01bdb04afa2913..aea916fbe201ef 100644 --- a/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/dynamically-set-the-coordinates-for-each-bar.md +++ b/curriculum/challenges/arabic/04-data-visualization/data-visualization-with-d3/dynamically-set-the-coordinates-for-each-bar.md @@ -1,6 +1,6 @@ --- id: 587d7fa9367417b2b2512bce -title: تعيين الإحداثيات ديناميكيا لكل شريط +title: تعيين الإحداثيات ديناميكيا لكل عمود challengeType: 6 forumTopicId: 301487 dashedName: dynamically-set-the-coordinates-for-each-bar @@ -8,13 +8,13 @@ dashedName: dynamically-set-the-coordinates-for-each-bar # --description-- -التحدي السابق أنشئت وألحقت مستطيل بعنصر `svg` لكل نقطة في `dataset` لتستعرض شريط. لسوء الحظ، كانوا مكدسين بعضَهم فوق بعض. +The last challenge created and appended a rectangle to the `svg` element for each point in `dataset` to represent a bar. لسوء الحظ، كانوا مكدسين بعضَهم فوق بعض. -يمكنك تحكم في موضع المستطيل بواسطة أستخدام سمات (attributes) تسمى `x` و `y`. لتخبر D3 أين يبدأ في رسم الشكل في منطقة `svg`. قام التحدي السابق بتحديدهم إلى صفر، لذلك تم وضع كل عمود (bar) في الزاوية العلوية اليسرى. +التحكم في موقع المستطيل يكون بواسطة سمات (attributes) `x` و `y`. فانهم يخبرون D3 أين يبدأ في رسم الشكل في منطقة `svg`. قام التحدي السابق بتحديدهم إلى صفر، لذلك تم وضع كل عمود (bar) في الزاوية العلوية اليسرى. -للحصول على مخطط بياني شريطي (bar chart)، يجب أن تجلس جميع الشريط على نفس المستوى العمودي، مما يعني أن قيمة `y` تبقى هي نفسها (عند 0) لجميع الأشرطة. ومع ذلك، تحتاج قيمة `x` إلى التغيير عند إضافة الشريط جديد. تذكر أن أكبر قيم من `x` تدفع العناصر إلى أقصى اليمين. عندما تمر عبر عناصر القائمة في `dataset`، يجب أن تزيد قيمة `x`. +للحصول على مخطط أعمدة (bar chart)، يجب أن تجلس جميع الأعمدة على نفس المستوى العمودي، مما يعني أن قيمة `y` تبقى هي نفسها (عند 0) لجميع الأعمدة. أما قيمة `x` عليها أن نتغير عندما تضيف أعمدة جديدة. تذكر أن القيم الأكبر في `x` تدفع العناصر أبعد إلى اليمين. عندما تمر عبر عناصر القائمة في `dataset`، يجب أن تزيد قيمة `x`. -تقبل طريقة (method) تسمى `attr()` في D3 الوظيفة تعيد تفعيل (callback functon) التي تعيين تلك السمة ديناميكيا. وظيفة تعيد تفعيل (callback functon) تأخذ حجيتين (arguments)، واحد لنقطة البيانات نفسها (عادة `d`) وواحد لترتيب نقطة البيانات في القائمة (array). أما الحِجَّة (argument) الثانية تدل على الترتيب فهي حِجَّة اختيارية. إليك التنسيق: +تقبل طريقة (method) `attr()` في D3 وظيفة إعادة التفعيل (callback functon) التي تعيين تلك السمة ديناميكيا. تأخذ وظيفة إعادة التفعيل (callback functon) معطيين (arguments)، واحد لنقطة البيانات نفسها (عادة `d`) وواحد لرقم ترتيب (index) نقطة البيانات في القائمة (array). أما المعطى (argument) الثاني لرقم الترتيب فهو معطى اختياري. إليك التنسيق: ```js selection.attr("property", (d, i) => { @@ -22,13 +22,13 @@ selection.attr("property", (d, i) => { }) ``` -من المهم مُراعاةٌ أنك لا تحتاج إلى كتابة حلقة (loop) نوعها `for` أو استخدام `forEach()` لتكرار العناصر في مجموعة البيانات (data set). تذكر أن طريقة `data()` تحلل مجموعة البيانات (data set), وأي طريقة تتبع `data()` يتم تشغيلها مرة واحدة لكل عنصر في مجموعة البيانات. +من المهم ملاحظة أنك لن تحتاج إلى كتابة حلقة (loop) نوعها `for` أو `forEach()` لتعيد على العناصر في مجموعة البيانات (data set). تذكر أن طريقة `data()` تحلل مجموعة البيانات (data set), وأي طريقة مسلسة تتبع `data()` سيتم تشغيلها مرة واحدة لكل عنصر في مجموعة البيانات. # --instructions-- -غيّر سمة `x` في وظيفة تعيد تفعيل بحيث ترجع الترتيب 30 مرة. +غيّر وظيفة إعادة التفعيل لسمة `x` بحيث تنتج رَقَم الترتيب 30 مرة. -**ملاحظة:** كل عمود له عرض (width) بقيمة 25، لذا زيادة كل قيمة `x` بمقدار 30 تضيف بعض المساحة بين الأشرطة. أي قيمة أكبر من 25 ستنجح في هذا المثال. +**ملاحظة:** كل عمود له عرض (width) بقيمة 25، لذا زيادة كل قيمة `x` بمقدار 30 ستضيف بعض المساحة بين الأشرطة. أي قيمة أكبر من 25 ستنجح في هذا المثال. # --hints-- diff --git a/curriculum/challenges/arabic/04-data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method.md b/curriculum/challenges/arabic/04-data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method.md index b13644c2473d0e..d5701854b74700 100644 --- a/curriculum/challenges/arabic/04-data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method.md +++ b/curriculum/challenges/arabic/04-data-visualization/json-apis-and-ajax/get-json-with-the-javascript-fetch-method.md @@ -38,6 +38,30 @@ Update the code to create and send a `GET` request to the freeCodeCamp Cat Photo # --hints-- + +Your code should use the fetched data to replace the inner HTML + +```js +const catData = "dummy data"; +const ref = fetch; +fetch = () => Promise.resolve({ json: () => catData }); +async () => { + try { + document.getElementById("getMessage").click(); + await new Promise((resolve, reject) => setTimeout(() => resolve(), 250)); + } catch (error) { + console.log(error); + } finally { + fetch = ref; + assert.equal( + document.getElementById("message").textContent, + JSON.stringify(catData) + ); + } +}; +``` + + Your code should make a `GET` request with `fetch`. ```js diff --git a/curriculum/challenges/arabic/04-data-visualization/json-apis-and-ajax/handle-click-events-with-javascript-using-the-onclick-property.md b/curriculum/challenges/arabic/04-data-visualization/json-apis-and-ajax/handle-click-events-with-javascript-using-the-onclick-property.md index b2bf1b3f2de492..479f38446756db 100644 --- a/curriculum/challenges/arabic/04-data-visualization/json-apis-and-ajax/handle-click-events-with-javascript-using-the-onclick-property.md +++ b/curriculum/challenges/arabic/04-data-visualization/json-apis-and-ajax/handle-click-events-with-javascript-using-the-onclick-property.md @@ -1,6 +1,6 @@ --- id: 587d7fad367417b2b2512be1 -title: التعامل مع أحداث النقر (Handle Click Events) مع JavaScript باستخدام خاصية عند النقر (onclick) +title: التعامل مع أحداث النقر (Handle Click Events) مع JavaScript باستخدام خاصية onclick عند النقر challengeType: 6 forumTopicId: 301503 dashedName: handle-click-events-with-javascript-using-the-onclick-property @@ -8,7 +8,7 @@ dashedName: handle-click-events-with-javascript-using-the-onclick-property # --description-- -تريد تنفذ كودك بمجرد الانتهاء من تحميل الصفحة, مرة واحدة فقط. لهذا الغرض، يمكنك إرفاق حدث (event) من JavaScript لمستند مسمى `DOMContentLoaded`. إليك كود الذي يفعل ذلك: +تريد أن ينفذ كودك فقط عندما ينتهي تحميل الصفحة. لهذا الغرض، يمكنك إرفاق حدث (event) من JavaScript لمستند مسمى `DOMContentLoaded`. إليك الكود الذي يفعل ذلك: ```js document.addEventListener('DOMContentLoaded', function() { @@ -24,11 +24,11 @@ document.getElementById('getMessage').onclick = function(){}; # --instructions-- -أضف معالج أحداث النقر داخل وظيفة `DOMContentLoaded` للعنصر مع معرف `getMessage`. +أضف معالج الأحداث (event handler) داخل وظيفة `DOMContentLoaded` للعنصر الذي له id قيمته `getMessage`. # --hints-- -يجب أن تستخدم كودك طريقة `document.getElementById` لتحديد عنصر `getMessage`. +يجب أن يستخدم كودك طريقة `document.getElementById` لتحديد عنصر `getMessage`. ```js assert(code.match(/document\s*\.getElementById\(\s*?('|")getMessage\1\s*?\)/g)); diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md index 8f25970f37af9c..e706395eb64a57 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- @@ -411,7 +411,7 @@ The `description` property of any object in the `log` array that is returned fro ```js async(getUserInput) => { const url = getUserInput('url'); - const res = await fetch(url + '/api/users/', { + const res = await fetch(url + '/api/users', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', @@ -458,7 +458,7 @@ The `duration` property of any object in the `log` array that is returned from ` ```js async(getUserInput) => { const url = getUserInput('url'); - const res = await fetch(url + '/api/users/', { + const res = await fetch(url + '/api/users', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', @@ -505,7 +505,7 @@ The `date` property of any object in the `log` array that is returned from `GET ```js async(getUserInput) => { const url = getUserInput('url'); - const res = await fetch(url + '/api/users/', { + const res = await fetch(url + '/api/users', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/file-metadata-microservice.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/file-metadata-microservice.md index e4a5775b2d2deb..dc47c463bb3e8c 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/file-metadata-microservice.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/file-metadata-microservice.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/request-header-parser-microservice.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/request-header-parser-microservice.md index 5e4903c1937b8f..9fcfc56b3ef7e9 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/request-header-parser-microservice.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/request-header-parser-microservice.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --hints-- diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/timestamp-microservice.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/timestamp-microservice.md index 6554ee0ff4b91c..053c4671344787 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/timestamp-microservice.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/timestamp-microservice.md @@ -8,25 +8,25 @@ dashedName: timestamp-microservice # --description-- -Build a full stack JavaScript app that is functionally similar to this: https://timestamp-microservice.freecodecamp.rocks. Working on this project will involve you writing your code using one of the following methods: +Build a full stack JavaScript app that is functionally similar to this: https://timestamp-microservice.freecodecamp.rocks. سوف يقوم يلزمك العمل على هذا المشروع بكتابة كود باستخدام إحدى الطرق التالية: -- Clone this GitHub repo and complete your project locally. -- Use our Replit starter project to complete your project. -- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo. +- أستنسخ هذا مستودع من GitHub واكمل مشروعك محلياً. +- استخدم مشروعنا المبدئي في Replit لإكمال مشروعك. +- استخدم أي منشئ لموقع لإكمال المشروع. تأكد من دمج جميع الملفات من مستودعنا في GitHub في مشروعك. -If you use Replit, follow these steps to set up the project: +إذا كنت تستخدم Replit، اتبع هذه الخطوات لإعداد المشروع: -- Start by importing the project on Replit. -- Next, you will see a `.replit` window. -- Select `Use run command` and click the `Done` button. +- ابدأ باستيراد (import) المشروع على Replit. +- بعد ذلك، سترى نافذة `.replit`. +- اختار `Use run command` وانقر على زر `Done`. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. ثم أرسل عنوان (URL) إليه في خانة "رابط الحل". وإن أردت تستطيع أيضًا إرسال رابط لكود المصدر لمشروعك في الخانة "رابط Github". -**Note:** Time zones conversion is not a purpose of this project, so assume all sent valid dates will be parsed with `new Date()` as GMT dates. +**ملاحظة:** ليس الغرض من هذا المشروع تحويل المناطق الزمنية، لذلك افترض إن جميع التواريخ الصحيحة المرسلة ستحلل بواسطة `new Date()` كتواريخ GMT. # --hints-- -You should provide your own project, not the example URL. +يجب عليك تقديم URL لمشروعك، وليس عنوان المثال. ```js (getUserInput) => { @@ -36,7 +36,7 @@ You should provide your own project, not the example URL. }; ``` -A request to `/api/:date?` with a valid date should return a JSON object with a `unix` key that is a Unix timestamp of the input date in milliseconds (as type Number) +يجب أن ينتج كائن JSON عند طلب `/api/:date?` التاريخ الصحيح بهوية (key) المسمى `unix` الذي يكون طابع زمني Unix من تاريخ المدخل بالمللي ثانية (كرقم) ```js (getUserInput) => @@ -54,7 +54,7 @@ A request to `/api/:date?` with a valid date should return a JSON object with a ); ``` -A request to `/api/:date?` with a valid date should return a JSON object with a `utc` key that is a string of the input date in the format: `Thu, 01 Jan 1970 00:00:00 GMT` +يجب أن ينتج عند كائن JSON طلب `/api/:date?` مع تاريخ صحيح مع هوية `utc` وتكون قيمته مقطع نصي من تاريخ المدخل. وينسق مثل: `Thu, 01 Jan 1970 00:00:00 GMT` ```js (getUserInput) => @@ -106,7 +106,7 @@ Your project can handle dates that can be successfully parsed by `new Date(date_ ); ``` -If the input date string is invalid, the api returns an object having the structure `{ error : "Invalid Date" }` +If the input date string is invalid, the API returns an object having the structure `{ error : "Invalid Date" }` ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/url-shortener-microservice.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/url-shortener-microservice.md index b3531c2adde458..58cf09e170ee81 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/url-shortener-microservice.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/back-end-development-and-apis-projects/url-shortener-microservice.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/meet-the-node-console.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/meet-the-node-console.md index d8e1f79e3a21a1..f64541beb2fb23 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/meet-the-node-console.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/meet-the-node-console.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. During the development process, it is important to be able to check what’s going on in your code. diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/serve-an-html-file.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/serve-an-html-file.md index 1d618673227afa..8b6a2b6a92b23c 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/serve-an-html-file.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/serve-an-html-file.md @@ -8,10 +8,10 @@ dashedName: serve-an-html-file # --description-- -You can respond to requests with a file using the `res.sendFile(path)` method. You can put it inside the `app.get('/', ...)` route handler. Behind the scenes, this method will set the appropriate headers to instruct your browser on how to handle the file you want to send, according to its type. Then it will read and send the file. This method needs an absolute file path. We recommend you to use the Node global variable `__dirname` to calculate the path like this: +You can respond to requests with a file using the `res.sendFile(path)` method. You can put it inside the `app.get('/', ...)` route handler. خلف الكواليس، ستضبط تلك الطريقة العناوين المناسبة لترشد متصفحك عن كيفية التعامل مع الملف الذي تريد إرساله، وفقًا لنوعه. Then it will read and send the file. This method needs an absolute file path. We recommend you to use the Node global variable `__dirname` to calculate the path like this: ```js -absolutePath = __dirname + relativePath/file.ext +absolutePath = __dirname + '/relativePath/file.ext' ``` # --instructions-- diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/serve-json-on-a-specific-route.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/serve-json-on-a-specific-route.md index 1e977061c7c0fc..91adaf364a0977 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/serve-json-on-a-specific-route.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/serve-json-on-a-specific-route.md @@ -18,7 +18,7 @@ Serve the object `{"message": "Hello json"}` as a response, in JSON format, to G # --hints-- -The endpoint `/json` should serve the json object `{"message": "Hello json"}` +The endpoint `/json` should serve the JSON object `{"message": "Hello json"}` ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/start-a-working-express-server.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/start-a-working-express-server.md index e8e3e82fc5a637..edb616ecedac97 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/start-a-working-express-server.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/start-a-working-express-server.md @@ -1,6 +1,6 @@ --- id: 587d7fb0367417b2b2512bee -title: Start a Working Express Server +title: بدء سيرفر Express مُفعل challengeType: 2 forumTopicId: 301519 dashedName: start-a-working-express-server @@ -8,9 +8,9 @@ dashedName: start-a-working-express-server # --description-- -In the first two lines of the file `myApp.js`, you can see how easy it is to create an Express app object. This object has several methods, and you will learn many of them in these challenges. One fundamental method is `app.listen(port)`. It tells your server to listen on a given port, putting it in running state. For testing reasons, we need the app to be running in the background so we added this method in the `server.js` file for you. +في السطر الأول من الملف `myApp.js`، يمكنك أن ترى مدى سهولة إنشاء كائن تطبيق Express. هذا الكائن لديه العديد من الطرق، وسوف تتعلم الكثير منها في هذه التحديات. إحدى الطرق الأساسية هي `app.listen(port)`. إنه يخبر سيرفرك أن يستمع إلى منفذ (port) معين، وأن يضعه في حالة تشغيل. لأسباب الاختبار، نحن بحاجة إلى أن يكون التطبيق قيد التشغيل في الخلفية لذلك أضفنا لك هذه الطريقة في ملف `server.js`. -Let’s serve our first string! In Express, routes takes the following structure: `app.METHOD(PATH, HANDLER)`. METHOD is an http method in lowercase. PATH is a relative path on the server (it can be a string, or even a regular expression). HANDLER is a function that Express calls when the route is matched. Handlers take the form `function(req, res) {...}`, where req is the request object, and res is the response object. For example, the handler +هيا نمدد المقطع النصي الأول! في Express، تأخذ المسارات البنية التالية: `app.METHOD(PATH, HANDLER)`. إن METHOD طريقة http مكتوبة بحروف صغيرة. إن PATH المنفذ نسبي في السيرفر (يمكن أن يكون مقطع نصي أو حتى عبارة (expression) عادية). إن HANDLER وظيفة معالجة ينفذها Express عند مطابقة ال route. تكتب تلك الوظائف المعالجة مثل `function(req, res) {...}`، حيث req هو كائن الطلب، و res هو كائن الاستجابة. على سبيل المثال المعالج ```js function(req, res) { @@ -18,17 +18,17 @@ function(req, res) { } ``` -will serve the string 'Response String'. +سوف يمدد المقطع النصي 'Response String'. # --instructions-- -Use the `app.get()` method to serve the string "Hello Express" to GET requests matching the `/` (root) path. Be sure that your code works by looking at the logs, then see the results in the preview if you are using Replit. +استخدم طريقة `app.get()` لتمديد المقطع "Hello Express" إلى طلبات GET المطابقة للمسار `/` (منفذ المصدر). أنظر إلى السجلات لتتأكد من أن الكود يعمل، ثم شاهد النتائج في علامة تبويب preview إذا كنت تستخدم Replit. -**Note:** All the code for these lessons should be added in between the few lines of code we have started you off with. +**ملاحظة:** يجب إضافة كل الكود لهذه الدروس بين سطور الكود التي بدأنا بها. # --hints-- -Your app should serve the string 'Hello Express' +يجب أن يخدم تطبيقك المقطع النصي 'Hello Express' ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/use-the-.env-file.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/use-the-.env-file.md index 80708e3fdb91c3..18ecaf24375b0b 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/use-the-.env-file.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/basic-node-and-express/use-the-.env-file.md @@ -18,11 +18,11 @@ Let's add an environment variable as a configuration option. Create a `.env` file in the root of your project directory, and store the variable `MESSAGE_STYLE=uppercase` in it. -Then, in the `/json` GET route handler you created in the last challenge access `process.env.MESSAGE_STYLE` and transform the response object's `message` to uppercase if the variable equals `uppercase`. The response object should either be `{"message": "Hello json"}` or `{"message": "HELLO JSON"}`, depending on the `MESSAGE_STYLE` value. +Then, in the `/json` GET route handler you created in the last challenge access `process.env.MESSAGE_STYLE` and transform the response object's `message` to uppercase if the variable equals `uppercase`. The response object should either be `{"message": "Hello json"}` or `{"message": "HELLO JSON"}`, depending on the `MESSAGE_STYLE` value. Note that you must read the value of `process.env.MESSAGE_STYLE` **inside** the route handler, not outside of it, due to the way our tests run. **Note:** If you are using Replit, you cannot create a `.env` file. Instead, use the built-in SECRETS tab to add the variable. -If you are working locally, you will need the `dotenv` package. It loads environment variables from your `.env` file into `process.env`. The `dotenv` package has already been installed, and is in your project's `package.json` file. At the top of your `myApp.js` file, import and load the variables with `require('dotenv').config()`. +If you are working locally, you will need the `dotenv` package. It loads environment variables from your `.env` file into `process.env`. The `dotenv` package has already been installed, and is in your project's `package.json` file. At the top of your `myApp.js` file, add `require('dotenv').config()` to load the environment variables. # --hints-- diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-description-to-your-package.json.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-description-to-your-package.json.md index b9cf761fd990cb..ba0971f39472e4 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-description-to-your-package.json.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-description-to-your-package.json.md @@ -1,6 +1,6 @@ --- id: 587d7fb3367417b2b2512bfc -title: Add a Description to Your package.json +title: إضافة وصف (Description) إلى package.json challengeType: 2 forumTopicId: 301522 dashedName: add-a-description-to-your-package-json @@ -8,11 +8,11 @@ dashedName: add-a-description-to-your-package-json # --description-- -The next part of a good package.json file is the `description` field; where a short, but informative description about your project belongs. +إن الجزء التالي من ملف package.json الجيد يكون خانة `description`؛ حيث يوجد وصف قصير ولكن زاخر بالمعلومات حول مشروعك. -If some day you plan to publish a package to npm, this is the string that should sell your idea to the user when they decide whether to install your package or not. However, that’s not the only use case for the description, it’s a great way to summarize what a project does. It’s just as important in any Node.js project to help other developers, future maintainers or even your future self understand the project quickly. +إذا خطط في يوم ما أن تنشر حزمة إلى npm، فهذا هو المقطع النصي الذي يشرح فكرتك للمستخدمون عندما يقررون تثبيت حزمتك أو لا. بالإضافة هذا ليس الاستخدام الوحيد لذلك الوصف. إنه طريقة رائعة لتلخيص وظيفة المشروع. وأيضا في أي مشروع Node.js فهو مهما بنفس القدر لمساعدة المطورين الآخرين، أو المشرفين في المستقبل، أو حتى لفهمك الخاص للمشروع بسرعة. -Regardless of what you plan for your project, a description is definitely recommended. Here's an example: +بغض النظر عن ما تخطط لمشروعك، فإن الوصف موصى به بكل تأكيد. إليك مثال: ```json "description": "A project that does something awesome", @@ -20,13 +20,13 @@ Regardless of what you plan for your project, a description is definitely recomm # --instructions-- -Add a `description` to the package.json file of your project. +أضف خانة الوصف `description` إلى ملف package.json لمشروعك. -**Note:** Remember to use double-quotes for field-names (") and commas (,) to separate fields. +**ملاحظة:** تذكر أن تستخدم علامات الاقتباس المزدوجة لأسماء الخانات، (") والفواصل (,) للفصل ما بينهم. # --hints-- -package.json should have a valid "description" key +يجب أن يحتوي package.json على هوية "description" صحيحة ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-license-to-your-package.json.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-license-to-your-package.json.md index d97b0134019fd0..59eba529efdbc6 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-license-to-your-package.json.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-license-to-your-package.json.md @@ -1,6 +1,6 @@ --- id: 587d7fb4367417b2b2512bfe -title: Add a License to Your package.json +title: إضافة ترخيص (License) إلى package.json challengeType: 2 forumTopicId: 301523 dashedName: add-a-license-to-your-package-json @@ -8,9 +8,9 @@ dashedName: add-a-license-to-your-package-json # --description-- -The `license` field is where you inform users of what they are allowed to do with your project. +إن خانة `license` المكان الذي تقوم فيه بإبلاغ المستخدمين بما يسمح لهم بفعله بمشروعك. -Some common licenses for open source projects include MIT and BSD. License information is not required, and copyright laws in most countries will give you ownership of what you create by default. However, it’s always a good practice to explicitly state what users can and can’t do. Here's an example of the license field: +وتشمل بعض التراخيص الشائعة للمشاريع المفتوحة المصدر (open source) ترخيص معهد ماساتشوستس للتكنولوجيا (MIT) وبرنامج بي اس دي (BSD). معلومات الترخيص غير مطلوبة، وقوانين حقوق التأليف والنشر (copyright laws) في معظم البلدان ستعطيك ملكية لما تنشئه بشكل افتراضي. ولكن يستحسن دائما أن نذكر صراحة ما يمكن للمستخدمين القيام به وما لا يمكنهم القيام به. إليك مثال لخانة الترخيص: ```json "license": "MIT", @@ -18,11 +18,11 @@ Some common licenses for open source projects include MIT and BSD. License infor # --instructions-- -Fill the `license` field in the package.json file of your project as you find suitable. +املأ خانة `license` في ملف package.json لمشروعك بما تجده مناسبا. # --hints-- -package.json should have a valid "license" key +يجب أن يحتوي package.json على هوية "license" صحيحة ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-version-to-your-package.json.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-version-to-your-package.json.md index a5b3b8b2453893..32242fc63aaf33 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-version-to-your-package.json.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-a-version-to-your-package.json.md @@ -1,6 +1,6 @@ --- id: 587d7fb4367417b2b2512bff -title: Add a Version to Your package.json +title: إضافة رقم الإصدار (Version) إلى package.json challengeType: 2 forumTopicId: 301525 dashedName: add-a-version-to-your-package-json @@ -8,7 +8,7 @@ dashedName: add-a-version-to-your-package-json # --description-- -A `version` is one of the required fields of your package.json file. This field describes the current version of your project. Here's an example: +إن `version` أحد الخانات المطلوبة في ملفك package.json. هذه الخانة تصف الإصدار الحالي من مشروعك. إليك مثال: ```json "version": "1.2.0", @@ -16,11 +16,11 @@ A `version` is one of the required fields of your package.json file. This field # --instructions-- -Add a `version` to the package.json file of your project. +أضف `version` إلى ملف package.json لمشروعك. # --hints-- -package.json should have a valid "version" key +يجب أن يحتوي package.json على هوية "version" صحيحة ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-keywords-to-your-package.json.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-keywords-to-your-package.json.md index 33c9742e8bc559..4d61cbc45cd54e 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-keywords-to-your-package.json.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/add-keywords-to-your-package.json.md @@ -1,6 +1,6 @@ --- id: 587d7fb4367417b2b2512bfd -title: Add Keywords to Your package.json +title: إضافة المصطلحات (keywords) إلى package.json challengeType: 2 forumTopicId: 301526 dashedName: add-keywords-to-your-package-json @@ -8,23 +8,23 @@ dashedName: add-keywords-to-your-package-json # --description-- -The `keywords` field is where you can describe your project using related keywords. Here's an example: +يمكنك الإضافة في خانة `keywords` وصف لمشروعك باستخدام مصطلحات مرتبطة. إليك مثال: ```json "keywords": [ "descriptive", "related", "words" ], ``` -As you can see, this field is structured as an array of double-quoted strings. +كما ترون، هذه الخانة منظمة مثل قائمة من النصوص المزدوجة الاقتباس. # --instructions-- -Add an array of suitable strings to the `keywords` field in the package.json file of your project. +أضف قائمة من النصوص المقطعية المناسبة إلى خانة `keywords` في ملف package.json الخاص بمشروعك. -One of the keywords should be "freecodecamp". +وينبغي أن تكون إحدى المصطلحات "freecodecamp". # --hints-- -package.json should have a valid "keywords" key +يجب أن يحتوي package.json على هوية "keywords" صحيحة ```js (getUserInput) => @@ -39,7 +39,7 @@ package.json should have a valid "keywords" key ); ``` -"keywords" field should be an Array +يجب أن تكون خانة "keywords" قائمة ```js (getUserInput) => @@ -54,7 +54,7 @@ package.json should have a valid "keywords" key ); ``` -"keywords" should include "freecodecamp" +يجب أن تحتوي "keywords" على "freecodecamp" ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/expand-your-project-with-external-packages-from-npm.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/expand-your-project-with-external-packages-from-npm.md index fa9056e09925b6..d8fa616339a60e 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/expand-your-project-with-external-packages-from-npm.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/expand-your-project-with-external-packages-from-npm.md @@ -1,6 +1,6 @@ --- id: 587d7fb4367417b2b2512c00 -title: Expand Your Project with External Packages from npm +title: توسيع مشروعك مع الحزم الخارجية من npm challengeType: 2 forumTopicId: 301527 dashedName: expand-your-project-with-external-packages-from-npm @@ -8,9 +8,9 @@ dashedName: expand-your-project-with-external-packages-from-npm # --description-- -One of the biggest reasons to use a package manager, is their powerful dependency management. Instead of manually having to make sure that you get all dependencies whenever you set up a project on a new computer, npm automatically installs everything for you. But how can npm know exactly what your project needs? Meet the `dependencies` section of your package.json file. +إحدى الأسباب الأكبر لاستخدام مدير الحزم هي إدارة تبعياتك القوية. بدلاً من أن تتأكد يدوياً أنك حصلت على جميع التبعيات كلما أعددت مشروع على جهاز كمبيوتر جديد، npm يقوم بتثبيت كل شيء لك تلقائياً. ولكن كيف يعرف npm احتياجات مشروعك بالضبط؟ تعرَّف إلى قسم التبعيات `dependencies` من ملف package.json الخاص بك. -In this section, packages your project requires are stored using the following format: +في هذا القسم، يخزن اسم الحزم الذي يتطلبها مشروعك باستخدام التنسيق التالي: ```json "dependencies": { @@ -22,13 +22,13 @@ In this section, packages your project requires are stored using the following f # --instructions-- -Add version "1.1.0" of the `@freecodecamp/example` package to the `dependencies` field of your `package.json` file. +Add version `1.1.0` of the `@freecodecamp/example` package to the `dependencies` field of your `package.json` file. -**Note:** `@freecodecamp/example` is a faux package used as a learning tool. +**ملاحظة:** إن `@freecodecamp/example` حزمة زائفة تستخدم كأداة للتعلم. # --hints-- -`"dependencies"` should include `"@freecodecamp/example"`. +`"dependencies"` يجب أن تتضمن `"@freecodecamp/example"`. ```js (getUserInput) => @@ -47,7 +47,7 @@ Add version "1.1.0" of the `@freecodecamp/example` package to the `dependencies` ); ``` -`"@freecodecamp/example"` version should be `"1.1.0"`. +يجب أن يكون إصدار `"@freecodecamp/example"` بقيمة `"1.1.0"`. ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/how-to-use-package.json-the-core-of-any-node.js-project-or-npm-package.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/how-to-use-package.json-the-core-of-any-node.js-project-or-npm-package.md index 0af728e6739a54..89aa13da227e88 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/how-to-use-package.json-the-core-of-any-node.js-project-or-npm-package.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/how-to-use-package.json-the-core-of-any-node.js-project-or-npm-package.md @@ -1,6 +1,6 @@ --- id: 587d7fb3367417b2b2512bfb -title: 'How to Use package.json, the Core of Any Node.js Project or npm Package' +title: 'استخدام package.json، مركز أي مشروع Node.js أو حزمة npm' challengeType: 2 forumTopicId: 301528 dashedName: how-to-use-package-json-the-core-of-any-node-js-project-or-npm-package @@ -8,25 +8,25 @@ dashedName: how-to-use-package-json-the-core-of-any-node-js-project-or-npm-packa # --description-- -Working on these challenges will involve you writing your code using one of the following methods: +العمل على هذه التحديات سوف ينطوي على كتابة كودك باستخدام إحدى الطرق التالية: -- Clone this GitHub repo and complete these challenges locally. -- Use our Replit starter project to complete these challenges. -- Use a site builder of your choice to complete the project. Be sure to incorporate all the files from our GitHub repo. +- انسخ هذا المستودع من GitHub واكمل مشروعك محلياً. +- استخدم مشروعنا المبدئي على Replit لإكمال هذه التحديات. +- استخدم أي منشئ موقع لإكمال المشروع. تحقق انك أضفت جميع الملفات من مستودعنا في GitHub في مشروعك. -If you use Replit, follow these steps to set up the project: +إذا استخدمت Replit، اتبع هذه الخطوات لإعداد المشروع: -- Start by importing the project on Replit. -- Next, you will see a `.replit` window. -- Select `Use run command` and click the `Done` button. +- ابدأ باستيراد (import) المشروع إلى Replit. +- بعد ذلك، سترى نافذة `.replit`. +- اختار `Use run command` وانقر على زر `Done`. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. +عند الانتهاء، تأكد من استضافة ديمو لمشروعك في مكان عام. ثم أرسل عنوانه (URL) في خانة "رابط الحل". -The `package.json` file is the center of any Node.js project or npm package. It stores information about your project, similar to how the <head> section of an HTML document describes the content of a webpage. It consists of a single JSON object where information is stored in key-value pairs. There are only two required fields; "name" and "version", but it’s good practice to provide additional information about your project that could be useful to future users or maintainers. +إن ملف `package.json` مركز أي مشروع Node.js أو حزمة npm. It stores information about your project, similar to how the `head` section of an HTML document describes the content of a webpage. ويتكون من كائن JSON واحد حيث يتم تخزين المعلومات في أزواج key-value. There are only two required fields; `name` and `version`, but it’s good practice to provide additional information about your project that could be useful to future users or maintainers. -If you look at the file tree of your project, you will find the package.json file on the top level of the tree. This is the file that you will be improving in the next couple of challenges. +If you look at the file tree of your project, you will find the `package.json` file on the top level of the tree. هذا هو الملف الذي سوف تحسنه في التحديات القادمة. -One of the most common pieces of information in this file is the `author` field. It specifies who created the project, and can consist of a string or an object with contact or other details. An object is recommended for bigger projects, but a simple string like the following example will do for this project. +واحدة من أكثر المعلومات شيوعا في هذا الملف هي خانة `author`. تحدد اسم منشئ المشروع، وممكن أن يتكون من مقطع نصي أو كائن مع جهة اتصال أو تفاصيل أخرى. يوصى باستخدام كائن لمشاريع أكبر، ولكن مقطع نصي بسيط مثل المثال التالي ينفع لهذا المشروع. ```json "author": "Jane Doe", @@ -34,13 +34,13 @@ One of the most common pieces of information in this file is the `author` field. # --instructions-- -Add your name as the `author` of the project in the package.json file. +Add your name as the `author` of the project in the `package.json` file. -**Note:** Remember that you’re writing JSON, so all field names must use double-quotes (") and be separated with a comma (,). +**ملاحظة:** تذكر أنك تكتب JSON، لذلك يجب أن تستخدم جميع أسماء الخانات علامات اقتباس مزدوجة (") وأن تكون مفصولة بفاصلة (,). # --hints-- -package.json should have a valid "author" key +`package.json` should have a valid "author" key ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/manage-npm-dependencies-by-understanding-semantic-versioning.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/manage-npm-dependencies-by-understanding-semantic-versioning.md index fa43e78268a1c4..232a102f930b60 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/manage-npm-dependencies-by-understanding-semantic-versioning.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/manage-npm-dependencies-by-understanding-semantic-versioning.md @@ -1,6 +1,6 @@ --- id: 587d7fb5367417b2b2512c01 -title: Manage npm Dependencies By Understanding Semantic Versioning +title: إدارة اعتمادات npm بفهم بالإصدار الدلالي لنُسخ البرمجيات (Semantic Versioning) challengeType: 2 forumTopicId: 301529 dashedName: manage-npm-dependencies-by-understanding-semantic-versioning @@ -8,23 +8,23 @@ dashedName: manage-npm-dependencies-by-understanding-semantic-versioning # --description-- -`Versions` of the npm packages in the dependencies section of your package.json file follow what’s called Semantic Versioning (SemVer), an industry standard for software versioning aiming to make it easier to manage dependencies. Libraries, frameworks or other tools published on npm should use SemVer in order to clearly communicate what kind of changes projects can expect if they update. +تتبع القيم في `Versions` من حزم npm في قسم التبعيات من الحُزْمَة الخاصة بك. النظام الذي يسمى بالإصدار الدلالي لنُسخ البرمجيات Semantic Versioning (SemVer)، وهو نمط صناعي لإصدار البرامج يهدف إلى تيسير إدارة الاعتمادات. كل من المكتبات، أو الأطر أو الأدوات الأخرى المنشورة على npm ينبغي أن تستخدم SemVer من أجل الإبلاغ بوضوح عن نوع التغييرات التي يمكن أن تتوقعها المشروعات إذا تم تحديثها. -Knowing SemVer can be useful when you develop software that uses external dependencies (which you almost always do). One day, your understanding of these numbers will save you from accidentally introducing breaking changes to your project without understanding why things that worked yesterday suddenly don’t work today. This is how Semantic Versioning works according to the official website: +معرفة SemVer مفيدة عند تطوير البرامج التي تستخدم التبعية الخارجية (التي تكاد تقوم بها دائما). يوما ما، فهمك لهذه الأرقام سوف يحفظك من إدخال تغييرات على مشروعك عن طريق الخطأ دون تفهم لماذا لا تعمل فجأة اليوم الأشياء التي عملت بالأمس. هذه هي الطريقة التي تعمل بها Semantic Versioning وفقا للموقع الرسمي على الإنترنت: ```json "package": "MAJOR.MINOR.PATCH" ``` -The MAJOR version should increment when you make incompatible API changes. The MINOR version should increment when you add functionality in a backwards-compatible manner. The PATCH version should increment when you make backwards-compatible bug fixes. This means that PATCHes are bug fixes and MINORs add new features but neither of them break what worked before. Finally, MAJORs add changes that won’t work with earlier versions. +يجب أن يزداد رَقَم الإصدار MAJOR عند إجراء تغييرات API غير متوافقة. يجب أن يزداد رَقَم إصدار MINOR عند إضافة وظيفة بطريقة متوافقة رجعياً. يجب أن يزداد رَقَم الإصدار PATCH عند إجراء تصليحات للأخطاء متوافقة رجعيا. وهذا يعني أن PATCHES هي إصلاحات للأخطاء و MINORs تضيف ميزات جديدة ولكن كلا منهما لا يكسر ما كان يعمل من قبل. وأخيراً، يضيف MAJORs تغييرات لن تعمل مع الإصدارات السابقة. # --instructions-- -In the dependencies section of your `package.json` file, change the version of `@freecodecamp/example` to match MAJOR version 1, MINOR version 2 and PATCH version 13 +في قسم التبعيات من ملف الحزمة `package.json`، غيّر إصدار `@freecodecamp/example` لمطابقة قيمة إصدار 1 بنوع MAJOR وإصدار 2 بنوع MINOR وإصدار 13 بنوع PATCH # --hints-- -`"dependencies"` should include `"@freecodecamp/example"`. +يجب أن تتضمن `"dependencies"` مقطع `"@freecodecamp/example"`. ```js (getUserInput) => @@ -43,7 +43,7 @@ In the dependencies section of your `package.json` file, change the version of ` ); ``` -`"@freecodecamp/example"` version should be `"1.2.13"`. +يجب أن يكون إصدار `"@freecodecamp/example"` بقيمة `"1.2.13"`. ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/remove-a-package-from-your-dependencies.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/remove-a-package-from-your-dependencies.md index 2d05d271d17add..f4b2265e7e42ee 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/remove-a-package-from-your-dependencies.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/remove-a-package-from-your-dependencies.md @@ -1,6 +1,6 @@ --- id: 587d7fb5367417b2b2512c04 -title: Remove a Package from Your Dependencies +title: إزالة حزمة (Package) من تبعياتك (Dependency) challengeType: 2 forumTopicId: 301530 dashedName: remove-a-package-from-your-dependencies @@ -8,21 +8,21 @@ dashedName: remove-a-package-from-your-dependencies # --description-- -You have now tested a few ways you can manage dependencies of your project by using the package.json's dependencies section. You have also included external packages by adding them to the file and even told npm what types of versions you want, by using special characters such as the tilde or the caret. +لقد اختبرت الآن بعض الطرق الذي يمكنك بها إدارة التبعيات لمشروعك باستخدام قسم التبعيات في package.json. لقد قمت أيضا بإدراج حزم خارجية عن طريق إضافتها إلى الملف وأخبرت npm ما هي أنواع الإصدارات التي تريدها، باستخدام أحرف خاصة مثل tilde (~) أو caret (^). -But what if you want to remove an external package that you no longer need? You might already have guessed it, just remove the corresponding key-value pair for that package from your dependencies. +ولكن ماذا لو أردت إزالة حزمة خارجية لم تعد بحاجة إليها؟ ربما قد خمنتها فعلًا، عليك فقط أن تزيل زوج key-value المقابل لتلك الحزمة من تبعياتك (dependencies). -This same method applies to removing other fields in your package.json as well. +تنطبق نفس الطريقة على إزالة الخانات الأخرى في package.json أيضا. # --instructions-- -Remove the `@freecodecamp/example` package from your dependencies. +أزل حزمة `@freecodecamp/example` من تبعياتك. -**Note:** Make sure you have the right amount of commas after removing it. +**ملاحظة:** تأكد من أن لديك العدد الصحيح من الفواصل بعد إزالتها. # --hints-- -`"dependencies"` should not include `"@freecodecamp/example"`. +يجب ألا تتضمن `"dependencies"` مقطع `"@freecodecamp/example"`. ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency.md index 84b47b8d7b71f7..9200624155a4c6 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency.md @@ -1,6 +1,6 @@ --- id: 587d7fb5367417b2b2512c03 -title: Use the Caret-Character to Use the Latest Minor Version of a Dependency +title: استخدم رمز Caret لاستخدام أحدث نسخة ثانوي من التبعية challengeType: 2 forumTopicId: 301531 dashedName: use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency @@ -8,25 +8,25 @@ dashedName: use-the-caret-character-to-use-the-latest-minor-version-of-a-depende # --description-- -Similar to how the tilde we learned about in the last challenge allows npm to install the latest PATCH for a dependency, the caret (`^`) allows npm to install future updates as well. The difference is that the caret will allow both MINOR updates and PATCHes. +شبيهة بالطريقة التي تعلمنا بها عن tilde في التحدي الأخير وكيف يسمح لـ npm بتثبيت أحدث PATCH للاعتماد، يسمح رمز caret (`^`) إلى npm تثبيت التحديثات المستقبلية أيضًا. إن الفرق سيسمح رمز caret لكل من التحديثات من MINOR و PATCH. -Your current version of `@freecodecamp/example` should be "~1.2.13" which allows npm to install to the latest 1.2.x version. If you were to use the caret (^) as a version prefix instead, npm would be allowed to update to any 1.x.x version. +Your current version of `@freecodecamp/example` should be `~1.2.13` which allows npm to install to the latest `1.2.x` version. If you were to use the caret (^) as a version prefix instead, npm would be allowed to update to any `1.x.x` version. ```json "package": "^1.3.8" ``` -This would allow updates to any 1.x.x version of the package. +This would allow updates to any `1.x.x` version of the package. # --instructions-- -Use the caret (`^`) to prefix the version of `@freecodecamp/example` in your dependencies and allow npm to update it to any new MINOR release. +استخدم رمز (`^`) لبادئة رَقَم إصدار `@freecodecamp/example` في تبعياتك (dependencies). ذلك يسمح ل npm بتحديثها إلى أي إصدار جديد نوع MINOR. -**Note:** The version numbers themselves should not be changed. +**ملاحظة:** لا تغيير أرقام الإصدار نفسها. # --hints-- -`"dependencies"` should include `"@freecodecamp/example"`. +يجب أن تتضمن `"dependencies"` مقطع `"@freecodecamp/example"`. ```js (getUserInput) => @@ -45,7 +45,7 @@ Use the caret (`^`) to prefix the version of `@freecodecamp/example` in your dep ); ``` -`"@freecodecamp/example"` version should match `"^1.x.x"`. +يجب أن تطابق `"@freecodecamp/example"` إصدارها `"^1.x.x"`. ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency.md index 0ef31ff5846b7c..b4b4c9003d699b 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/managing-packages-with-npm/use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency.md @@ -1,6 +1,6 @@ --- id: 587d7fb5367417b2b2512c02 -title: Use the Tilde-Character to Always Use the Latest Patch Version of a Dependency +title: استخدم رمز Tilde لاستخدام أحدث نسخة patch من التبعية دائما challengeType: 2 forumTopicId: 301532 dashedName: use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency @@ -8,9 +8,9 @@ dashedName: use-the-tilde-character-to-always-use-the-latest-patch-version-of-a- # --description-- -In the last challenge, you told npm to only include a specific version of a package. That’s a useful way to freeze your dependencies if you need to make sure that different parts of your project stay compatible with each other. But in most use cases, you don’t want to miss bug fixes since they often include important security patches and (hopefully) don’t break things in doing so. +في التحدي الأخير، أخبرت npm أن يتضمن نسخة محددة فقط من الحزمة. هذه طريقة مفيدة لتجميد التبعية إذا كنت بحاجة إلى التأكد من أن أجزاء مختلفة من مشروعك تبقى متوافقة مع بعضها البعض. ولكن في معظم حالات الاستخدام، لا ترد أن تفوتك إصلاحات الأخطاء لأنها غالباً ما تتضمن التصحيحات الأمنية الهامة ومن الآمل أنها لا تتسبب لتخريب تطبيقك بذلك. -To allow an npm dependency to update to the latest PATCH version, you can prefix the dependency’s version with the tilde (`~`) character. Here's an example of how to allow updates to any 1.3.x version. +للسماح للتبعية npm للتحديث إلى أحدث إصدار PATCH، يمكنك أن تضيف رمز (`~`) في بداية الإصدار للتبعية. Here's an example of how to allow updates to any `1.3.x` version. ```json "package": "~1.3.8" @@ -18,15 +18,15 @@ To allow an npm dependency to update to the latest PATCH version, you can prefix # --instructions-- -In the package.json file, your current rule for how npm may upgrade `@freecodecamp/example` is to use a specific version (1.2.13). But now, you want to allow the latest 1.2.x version. +In the package.json file, your current rule for how npm may upgrade `@freecodecamp/example` is to use a specific version (`1.2.13`). But now, you want to allow the latest `1.2.x` version. -Use the tilde (`~`) character to prefix the version of `@freecodecamp/example` in your dependencies, and allow npm to update it to any new _patch_ release. +استخدم رمز (`~`) لبادئة رقم إصدار `@freecodecamp/example` في تبعياتك (dependencies). ذلك يسمح ل npm بتحديثها إلى أي إصدار _patch_ جديد. -**Note:** The version numbers themselves should not be changed. +**ملاحظة:** لا تغيير أرقام الإصدار نفسها. # --hints-- -`"dependencies"` should include `"@freecodecamp/example"`. +يجب أن تتضمن `"dependencies"` مقطع `"@freecodecamp/example"`. ```js (getUserInput) => @@ -45,7 +45,7 @@ Use the tilde (`~`) character to prefix the version of `@freecodecamp/example` i ); ``` -`"@freecodecamp/example"` version should match `"~1.2.13"`. +يجب أن تطابق `"@freecodecamp/example"` إصدارها `"~1.2.13"`. ```js (getUserInput) => diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/mongodb-and-mongoose/create-a-model.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/mongodb-and-mongoose/create-a-model.md index 443db8e5930a11..b31049d5b75f87 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/mongodb-and-mongoose/create-a-model.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/mongodb-and-mongoose/create-a-model.md @@ -28,19 +28,15 @@ const someFunc = function(done) { # --instructions-- -Create a person schema called `personSchema` having this prototype: - -```markup -- Person Prototype - --------------------- -name : string [required] -age : number -favoriteFoods : array of strings (*) -``` +Create a person schema called `personSchema` with the following shape: + +* A required `name` field of type `String` +* An `age` field of type `Number` +* A `favoriteFoods` field of type `[String]` Use the Mongoose basic schema types. If you want you can also add more fields, use simple validators like required or unique, and set default values. See our Mongoose article. -Now, create a model called `Person` from the `personSchema`. +Now, create a model from the `personSchema` and assign it to the existing variable `Person`. # --hints-- diff --git a/curriculum/challenges/arabic/05-back-end-development-and-apis/mongodb-and-mongoose/install-and-set-up-mongoose.md b/curriculum/challenges/arabic/05-back-end-development-and-apis/mongodb-and-mongoose/install-and-set-up-mongoose.md index b67d25a5c370aa..0ac7d7aa075fce 100644 --- a/curriculum/challenges/arabic/05-back-end-development-and-apis/mongodb-and-mongoose/install-and-set-up-mongoose.md +++ b/curriculum/challenges/arabic/05-back-end-development-and-apis/mongodb-and-mongoose/install-and-set-up-mongoose.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. In this challenge, you will set up a MongoDB Atlas database and import the required packages to connect to it. diff --git a/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/implementation-of-social-authentication-iii.md b/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/implementation-of-social-authentication-iii.md index aef68751990080..10be5ceeb4888e 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/implementation-of-social-authentication-iii.md +++ b/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/implementation-of-social-authentication-iii.md @@ -61,7 +61,7 @@ async (getUserInput) => { ); assert.match( data, - /GitHubStrategy[^]*return cb/gi, + /GitHubStrategy[^]*cb/gi, 'Strategy should return the callback function "cb"' ); } diff --git a/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/serialization-of-a-user-object.md b/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/serialization-of-a-user-object.md index 405d8c9a127ae1..da9040a8c85848 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/serialization-of-a-user-object.md +++ b/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/serialization-of-a-user-object.md @@ -50,7 +50,7 @@ Submit your page when you think you've got it right. If you're running into erro # --hints-- -You should serialize user function correctly. +You should serialize the user object correctly. ```js async (getUserInput) => { @@ -70,7 +70,7 @@ async (getUserInput) => { } ``` -You should deserialize user function correctly. +You should deserialize the user object correctly. ```js async (getUserInput) => { diff --git a/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/set-up-a-template-engine.md b/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/set-up-a-template-engine.md index 7a5224577d700a..4df625ea8a126c 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/set-up-a-template-engine.md +++ b/curriculum/challenges/arabic/06-quality-assurance/advanced-node-and-express/set-up-a-template-engine.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. A template engine enables you to use static template files (such as those written in *Pug*) in your app. At runtime, the template engine replaces variables in a template file with actual values which can be supplied by your server. Then it transforms the template into a static HTML file that is sent to the client. This approach makes it easier to design an HTML page and allows for displaying variables on the page without needing to make an API call from the client. diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work.md index 59f3e918cc8738..89d3a804db2a89 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work.md +++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-and-testing-with-chai/learn-how-javascript-assertions-work.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/american-british-translator.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/american-british-translator.md index 70d83bf2b6ec27..ef14b99aa5d530 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/american-british-translator.md +++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/american-british-translator.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- @@ -69,7 +69,7 @@ Write the following tests in `tests/2_functional-tests.js`: # --hints-- -I can provide my own project, not the example URL. +You should provide your own project, not the example URL. ```js (getUserInput) => { @@ -282,7 +282,7 @@ async (getUserInput) => { }; ``` -All 24 unit tests are complete and passing. See `/tests/1_unit-tests.js` for the expected behavior you should write tests for. +All 24 unit tests are complete and passing. ```js async (getUserInput) => { @@ -307,7 +307,7 @@ async (getUserInput) => { }; ``` -All 6 functional tests are complete and passing. See `/tests/2_functional-tests.js` for the functionality you should write tests for. +All 6 functional tests are complete and passing. ```js async (getUserInput) => { diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/issue-tracker.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/issue-tracker.md index 58acba6187662a..15d2437574f941 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/issue-tracker.md +++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/issue-tracker.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/metric-imperial-converter.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/metric-imperial-converter.md index f847638bba40f1..90e2329e195dfb 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/metric-imperial-converter.md +++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/metric-imperial-converter.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/personal-library.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/personal-library.md index 31b48ccb37b0bf..a6abf77e231160 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/personal-library.md +++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/personal-library.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/sudoku-solver.md b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/sudoku-solver.md index 096971fa4d1939..fce5f5592f1530 100644 --- a/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/sudoku-solver.md +++ b/curriculum/challenges/arabic/06-quality-assurance/quality-assurance-projects/sudoku-solver.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- @@ -352,7 +352,7 @@ async (getUserInput) => { }; ``` -All 12 unit tests are complete and passing. See `/tests/1_unit-tests.js` for the expected behavior you should write tests for. +All 12 unit tests are complete and passing. ```js async (getUserInput) => { @@ -377,7 +377,7 @@ async (getUserInput) => { }; ``` -All 14 functional tests are complete and passing. See `/tests/2_functional-tests.js` for the expected functionality you should write tests for. +All 14 functional tests are complete and passing. ```js async (getUserInput) => { diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md index e93d9128f27ec1..a233fad342e6a3 100644 --- a/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md +++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/scientific-computing-with-python-projects/budget-app.md @@ -19,7 +19,7 @@ You will be Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks على GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-analysis-example-b.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-analysis-example-b.md index 19441c3cd45673..68d4726de009a1 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-analysis-example-b.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-analysis-example-b.md @@ -16,8 +16,8 @@ dashedName: data-analysis-example-b More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks على GitHub +- كيفية فتح Notebook من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-cleaning-and-visualizations.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-cleaning-and-visualizations.md index 340cd5351d6906..3d0c996789fd42 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-cleaning-and-visualizations.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-cleaning-and-visualizations.md @@ -16,8 +16,8 @@ dashedName: data-cleaning-and-visualizations More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks على GitHub +- كيفية فتح Notebook من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-cleaning-with-dataframes.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-cleaning-with-dataframes.md index e1a58cfd19c54d..3f009dadd5a56c 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-cleaning-with-dataframes.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/data-cleaning-with-dataframes.md @@ -16,8 +16,8 @@ dashedName: data-cleaning-with-dataframes More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks على GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-cells.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-cells.md index d266151844dbdb..869c74f4398008 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-cells.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-cells.md @@ -16,8 +16,8 @@ dashedName: jupyter-notebooks-cells More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح (Notebook) من (GitHub) باستخدام (Google Colab). # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-importing-and-exporting-data.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-importing-and-exporting-data.md index be927727e87f36..343133d911e57b 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-importing-and-exporting-data.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/jupyter-notebooks-importing-and-exporting-data.md @@ -16,8 +16,8 @@ dashedName: jupyter-notebooks-importing-and-exporting-data More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebook من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-algebra-and-size.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-algebra-and-size.md index d6292da8d5cdf2..a68eef03d86d43 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-algebra-and-size.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-algebra-and-size.md @@ -16,8 +16,8 @@ dashedName: numpy-algebra-and-size More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-a.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-a.md index d9f980b8ae1a61..9f450d3f069af1 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-a.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-a.md @@ -16,8 +16,8 @@ dashedName: numpy-introduction-a More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-b.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-b.md index f76d5bf6d1cfd2..f0fc8bcb21b6dd 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-b.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-introduction-b.md @@ -16,8 +16,8 @@ dashedName: numpy-introduction-b More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-operations.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-operations.md index 166ee7c6d0535e..c5132c8e50774b 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-operations.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/numpy-operations.md @@ -16,8 +16,8 @@ dashedName: numpy-operations More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/pandas-conditional-selection-and-modifying-dataframes.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/pandas-conditional-selection-and-modifying-dataframes.md index d16b2a8235fdc4..5c358d257b890d 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/pandas-conditional-selection-and-modifying-dataframes.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/pandas-conditional-selection-and-modifying-dataframes.md @@ -16,8 +16,8 @@ dashedName: pandas-conditional-selection-and-modifying-dataframes More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebook من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/pandas-creating-columns.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/pandas-creating-columns.md index c9bd03fcb63a59..0c78b59b512c27 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/pandas-creating-columns.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/pandas-creating-columns.md @@ -16,8 +16,8 @@ dashedName: pandas-creating-columns More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح (Notebook) من (GitHub) باستخدام (Google Colab). # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-functions-and-collections.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-functions-and-collections.md index fdce91d05f7ec5..0ce305f71c109a 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-functions-and-collections.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-functions-and-collections.md @@ -16,8 +16,8 @@ dashedName: python-functions-and-collections More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-introduction.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-introduction.md index 8bd079a0a4f906..7b932c803e378a 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-introduction.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-introduction.md @@ -16,8 +16,8 @@ dashedName: python-introduction More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-iteration-and-modules.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-iteration-and-modules.md index fddbd3b10c9f9a..0fc48fb2801131 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-iteration-and-modules.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/python-iteration-and-modules.md @@ -16,8 +16,8 @@ dashedName: python-iteration-and-modules More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-csv-and-txt.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-csv-and-txt.md index 0291043e71501e..4c84ec0dc7494c 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-csv-and-txt.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-csv-and-txt.md @@ -16,8 +16,8 @@ dashedName: reading-data-csv-and-txt More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-from-databases.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-from-databases.md index 21186179430bef..f6578128629c2f 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-from-databases.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-from-databases.md @@ -16,8 +16,8 @@ dashedName: reading-data-from-databases More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-introduction.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-introduction.md index 2822287ab61cdb..1c067111e1bc1f 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-introduction.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-course/reading-data-introduction.md @@ -16,8 +16,8 @@ dashedName: reading-data-introduction More resources: -- Notebooks on GitHub -- How to open Notebooks from GitHub using Google Colab. +- Notebooks في GitHub +- كيفية فتح Notebooks من GitHub باستخدام Google Colab. # --question-- diff --git a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor.md b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor.md index 6e50f9b861a555..3b3ad3a4b1f610 100644 --- a/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor.md +++ b/curriculum/challenges/arabic/08-data-analysis-with-python/data-analysis-with-python-projects/sea-level-predictor.md @@ -28,7 +28,7 @@ You will analyze a dataset of the global average sea level change since 1880. Yo Use the data to complete the following tasks: - Use Pandas to import the data from `epa-sea-level.csv`. -- Use matplotlib to create a scatter plot using the `Year` column as the x-axis and the `CSIRO Adjusted Sea Level` column as the y-axix. +- Use matplotlib to create a scatter plot using the `Year` column as the x-axis and the `CSIRO Adjusted Sea Level` column as the y-axis. - Use the `linregress` function from `scipy.stats` to get the slope and y-intercept of the line of best fit. Plot the line of best fit over the top of the scatter plot. Make the line go through the year 2050 to predict the sea level rise in 2050. - Plot a new line of best fit just using the data from year 2000 through the most recent year in the dataset. Make the line also go through the year 2050 to predict the sea level rise in 2050 if the rate of rise continues as it has since the year 2000. - The x label should be `Year`, the y label should be `Sea Level (inches)`, and the title should be `Rise in Sea Level`. diff --git a/curriculum/challenges/arabic/09-information-security/information-security-projects/anonymous-message-board.md b/curriculum/challenges/arabic/09-information-security/information-security-projects/anonymous-message-board.md index b34a819caaa935..f219e784a77fac 100644 --- a/curriculum/challenges/arabic/09-information-security/information-security-projects/anonymous-message-board.md +++ b/curriculum/challenges/arabic/09-information-security/information-security-projects/anonymous-message-board.md @@ -22,7 +22,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/09-information-security/information-security-projects/secure-real-time-multiplayer-game.md b/curriculum/challenges/arabic/09-information-security/information-security-projects/secure-real-time-multiplayer-game.md index ae8a2cc7f90a58..361ebe837ea970 100644 --- a/curriculum/challenges/arabic/09-information-security/information-security-projects/secure-real-time-multiplayer-game.md +++ b/curriculum/challenges/arabic/09-information-security/information-security-projects/secure-real-time-multiplayer-game.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/09-information-security/information-security-projects/stock-price-checker.md b/curriculum/challenges/arabic/09-information-security/information-security-projects/stock-price-checker.md index afa2e0cb78c0ed..08b61006de702d 100644 --- a/curriculum/challenges/arabic/09-information-security/information-security-projects/stock-price-checker.md +++ b/curriculum/challenges/arabic/09-information-security/information-security-projects/stock-price-checker.md @@ -24,7 +24,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --instructions-- diff --git a/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/install-and-require-helmet.md b/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/install-and-require-helmet.md index 984f65d28ad5f2..f3e8ce6c1266d5 100644 --- a/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/install-and-require-helmet.md +++ b/curriculum/challenges/arabic/09-information-security/information-security-with-helmetjs/install-and-require-helmet.md @@ -20,7 +20,7 @@ If you use Replit, follow these steps to set up the project: - Next, you will see a `.replit` window. - Select `Use run command` and click the `Done` button. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Helmet helps you secure your Express apps by setting various HTTP headers. diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/algorithms/implement-binary-search.md b/curriculum/challenges/arabic/10-coding-interview-prep/algorithms/implement-binary-search.md index bd2e8306ee113e..caa2c40514c961 100644 --- a/curriculum/challenges/arabic/10-coding-interview-prep/algorithms/implement-binary-search.md +++ b/curriculum/challenges/arabic/10-coding-interview-prep/algorithms/implement-binary-search.md @@ -10,9 +10,10 @@ dashedName: implement-binary-search Binary search is an **O(log(n))** efficiency algorithm for searching a sorted array to find an element. It operates using the following steps: -1. Find the middle `value` of a sorted array. If `value == target` return (found it!). +1. Find the middle `value` of a sorted array. If `value == target` return `true` (The value has been found and the search is complete). 1. If middle `value < target`, search right half of array in next compare. 1. If middle `value > target`, search left half of array in next compare. +1. If after searching the whole array the value is not present, return `false` (The array has been searched and the value is not in the array). As you can see, you are successively halving an array, which gives you the log(n) efficiency. For this challenge, we want you to show your work - how you got to the target value... the path you took! @@ -20,7 +21,7 @@ As you can see, you are successively halving an array, which gives you the log(n Write a function `binarySearch` that implements the binary search algorithm on an array, returning the path you took (each middle value comparison) to find the target in an array. -The function takes a sorted array of integers and a target value as input. It returns an array containing (in-order) the middle value you found at each halving of the original array until you found the target value. The target value should be the last element of the returned array. If value not is found, return the string `Value Not Found`. +The function takes a sorted array of integers and a target value as input. It returns an array containing (in-order) the middle value you found at each halving of the original array until you found the target value. The target value should be the last element of the returned array. If the value is not found, return the string `Value Not Found`. For example, `binarySearch([1,2,3,4,5,6,7], 5)` would return `[4,6,5]`. diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/rosetta-code/farey-sequence.md b/curriculum/challenges/arabic/10-coding-interview-prep/rosetta-code/farey-sequence.md index f549221deb38c4..71962b17362c24 100644 --- a/curriculum/challenges/arabic/10-coding-interview-prep/rosetta-code/farey-sequence.md +++ b/curriculum/challenges/arabic/10-coding-interview-prep/rosetta-code/farey-sequence.md @@ -47,32 +47,33 @@ assert(typeof farey === 'function'); assert(Array.isArray(farey(3))); ``` -`farey(3)` should return `["1/3","1/2","2/3"]` +`farey(3)` should return `['0/1','1/3','1/2','2/3','1/1']` ```js -assert.deepEqual(farey(3), ['1/3', '1/2', '2/3']); +assert.deepEqual(farey(3),['0/1', '1/3', '1/2', '2/3', '1/1']); ``` -`farey(4)` should return `["1/4","1/3","1/2","2/4","2/3","3/4"]` +`farey(4)` should return `['0/1','1/4','1/3','1/2','2/3','3/4','1/1']` ```js -assert.deepEqual(farey(4), ['1/4', '1/3', '1/2', '2/4', '2/3', '3/4']); +assert.deepEqual(farey(4), ['0/1', '1/4', '1/3', '1/2', '2/3', '3/4', '1/1']); ``` -`farey(5)` should return `["1/5","1/4","1/3","2/5","1/2","2/4","3/5","2/3","3/4","4/5"]` +`farey(5)` should return `['0/1','1/5','1/4','1/3','2/5','1/2','3/5','2/3','3/4','4/5','1/1']` ```js assert.deepEqual(farey(5), [ + '0/1', '1/5', '1/4', '1/3', '2/5', '1/2', - '2/4', '3/5', '2/3', '3/4', - '4/5' + '4/5', + '1/1' ]); ``` @@ -89,21 +90,17 @@ function farey(n) { # --solutions-- ```js -function farey(n){ - let farSeq=[]; - for(let den = 1; den <= n; den++){ - for(let num = 1; num < den; num++){ - farSeq.push({ - str:num+"/"+den, - val:num/den}); - } +function farey(n) { + const sequence = [{ string: "0/1", float: 0.0 }]; + for (let i = 1; i < n; i++) { + for (let j = n; j >= i; j--) { + if (i === 1 || j % i > 0) { + sequence.push({ string: `${i}/${j}`, float: i / j }); + } } - farSeq.sort(function(a,b){ - return a.val-b.val; - }); - farSeq=farSeq.map(function(a){ - return a.str; - }); - return farSeq; + } + return sequence + .sort((a, b) => a.float - b.float) + .map(e => e.string) } ``` diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-a-nightlife-coordination-app.md b/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-a-nightlife-coordination-app.md index 8dd028cc0c28ca..c75478c71afd43 100644 --- a/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-a-nightlife-coordination-app.md +++ b/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-a-nightlife-coordination-app.md @@ -22,7 +22,7 @@ Here are the specific user stories you should implement for this project: **Hint:** Try using the Yelp API to find venues in the cities your users search for. If you use Yelp's API, be sure to mention so in your app. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --solutions-- diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-a-voting-app.md b/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-a-voting-app.md index c5e1f8c05ddd92..e70b3566764d2a 100644 --- a/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-a-voting-app.md +++ b/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-a-voting-app.md @@ -28,7 +28,7 @@ Here are the specific user stories you should implement for this project: **User Story:** As an authenticated user, if you don't like the options on a poll, you can create a new option. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --solutions-- diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-an-image-search-abstraction-layer.md b/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-an-image-search-abstraction-layer.md index 47cee2ababe259..4c4540d7fce084 100644 --- a/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-an-image-search-abstraction-layer.md +++ b/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/build-an-image-search-abstraction-layer.md @@ -18,7 +18,7 @@ Here are the specific user stories you should implement for this project: **User Story:** You can get a list of the most recently submitted search strings. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --solutions-- diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/chart-the-stock-market.md b/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/chart-the-stock-market.md index a5562365284724..c43de0dbaef3f9 100644 --- a/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/chart-the-stock-market.md +++ b/curriculum/challenges/arabic/10-coding-interview-prep/take-home-projects/chart-the-stock-market.md @@ -20,7 +20,7 @@ Here are the specific user stories you should implement for this project: **User Story:** You can see changes in real-time when any other user adds or removes a stock. For this you will need to use Web Sockets. -When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the `Solution Link` field. Optionally, also submit a link to your project's source code in the `GitHub Link` field. +When you are done, make sure a working demo of your project is hosted somewhere public. Then submit the URL to it in the Solution Link field. Optionally, also submit a link to your project's source code in the GitHub Link field. # --solutions-- diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project-projects/project-create-a-recipe-page.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project-projects/project-create-a-recipe-page.md new file mode 100644 index 00000000000000..657a3f6e32dfb7 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project-projects/project-create-a-recipe-page.md @@ -0,0 +1,204 @@ +--- +id: 6391d1a4f7ac71efd0621380 +title: Build a Recipe Page Project +challengeType: 14 +dashedName: project-create-a-recipe-page +--- + +# --description-- + +The website will consist of a main index page which will have links to a few recipes. The website won’t look very pretty by the time you’ve finished. + +**User Stories:** + +1. Your recipe page should contain a `DOCTYPE` tag. +1. Your recipe page should include an `html` element with a `head` and `body` element as children. +1. You should have a `title` element within the `head` element with the text `The Odin Recipes`. +1. You should see an `h1` element that has the text `Creamy Chocolate Fudge`. +1. You should see an image with the url `*placeholder-fcc-cdn*` with a fitting `alt` text. +1. There should be an `h2` element with the text `Description` under the image. +1. You should see a couple of paragraphs under `Description` that describe the recipe. +1. There should be an `h2` element with the text `Ingredients` +1. Under the `Ingredients` heading there should be an unordered list with the ingredients needed for the recipe. +1. Under the list of ingredients add another heading called `Steps`. +1. You should see an ordered list with a couple of steps needed to complete the recipe. +1. Under the steps there should be an `h2` element with the text `More Recipes` +1. You should see a couple of links to other recipes inside an unordered list which has a couple of list items with anchor elements within. +1. These anchor elements should have `href` attribute with the value set to `#` + +# --hints-- + +You should have a `DOCTYPE` tag. + +```js +assert(code.match(//gi)); +``` + +You should have a `html` element with `head` and `body` element. + +```js +const html = document.querySelectorAll('html')[0]; +const head = document.querySelectorAll('html > head')[0]; +const body = document.querySelectorAll('html > body')[0]; + +assert(html && head && body); +``` + +You should have a `title` element within the `head` element that contains the text `The Odin Recipes`. + +```js +assert(document.querySelectorAll('HEAD > TITLE')[0].innerText == 'The Odin Recipes'); +``` + +You should have a `h1` element within your `body` element that contains the text `Creamy Chocolate Fudge`. + +```js +assert(document.querySelectorAll('BODY > H1')[0].innerText == 'Creamy Chocolate Fudge'); +``` + +You should have an image with the url `*placeholder-fcc-cdn*` with an `alt` attribute that has a fitting text. + +```js +const img = document.querySelectorAll('IMG')[0]; + +assert(img && img.alt !='' && img.src === 'https://i.imgur.com/p0J5baJ.jpg') +``` + +You should have an `h2` element with the text `Description`. + +```js +const h2 = document.querySelectorAll('H2')[0]; + +assert(h2.innerText == 'Description'); +``` + +You should have at least two `p` elements describing the recipe. + +```js +const paragraphs = document.querySelectorAll('P'); + +assert(paragraphs.length > 1); +``` + +You should have an `h2` element with the text `Ingredients`. + +```js +const h2 = document.querySelectorAll('H2')[1]; + +assert(h2.innerText == 'Ingredients'); +``` + +You should have an unordered list `
      ` with some ingredients as the list items `
    • `. + +```js +const unorderedList = document.querySelectorAll('UL')[0]; +const listItems = document.querySelectorAll('UL > LI'); + +assert(unorderedList && listItems && listItems.length > 1); +``` + +You should have an `h2` element with the text `Steps`. + +```js +const h2 = document.querySelectorAll('H2')[2]; + +assert(h2.innerText == 'Steps'); +``` + +You should have a `
        ` with the the steps as the list items `
      1. `. + +```js +const orderedList = document.querySelectorAll('OL')[0]; +const listItems = document.querySelectorAll('OL > LI'); + +assert(orderedList && listItems && listItems.length > 1); +``` + +You should have an `h2` element with the text `More Recipes`. + +```js +const h2 = document.querySelectorAll('H2')[3]; + +assert(h2.innerText == 'More Recipes'); +``` + +You should have an unordered list `
          ` element with list items `
        • ` that contain `` tags which lead to other recipes. + +```js +const unorderedList = document.querySelectorAll('UL')[1]; +const listItems = unorderedList.querySelectorAll('LI'); + +const allAreListItems = unorderedList.children.length == listItems.length; + +const containsAnchors = [...listItems].every(function(listItem) { + return listItem.querySelector("a") !== null; +}); + +assert(unorderedList && allAreListItems && containsAnchors && listItems.length > 1); +``` + +Your anchor tags linking to the recipes should have a `href` attribute with the value set to `#` + +```js +const anchorTags = document.querySelectorAll("a"); + +const allAnchorsHaveHrefHash = [...anchorTags].every(function(anchorTag) { + return anchorTag.hasAttribute("href") && anchorTag.getAttribute("href") === "#"; +}); + +assert(allAnchorsHaveHrefHash && anchorTags.length > 0); +``` + +# --seed-- + +## --seed-contents-- + +```html + +``` + +```css + +``` + +## --solutions-- + +```html + + + + The Odin Recipes + + +

          Creamy Chocolate Fudge

          + A delicious chocolate fudge dessert +

          Description

          +

          This recipe is for a rich and creamy chocolate fudge that is sure to satisfy your sweet tooth. It's perfect for a special occasion or as a tasty treat for any time of the year.

          +

          This recipe is easy to follow and only requires a few simple ingredients. With just a few steps, you'll be able to create a delicious dessert that everyone will love.

          +

          Ingredients

          +
            +
          • 1 cup sugar
          • +
          • 1/2 cup unsalted butter
          • +
          • 1/4 cup milk
          • +
          • 1/4 cup cocoa powder
          • +
          • 1/4 cup chocolate chips
          • +
          • 1/4 tsp salt
          • +
          • 1 tsp vanilla extract
          • +
          +

          Steps

          +
            +
          1. In a medium saucepan, melt the butter over medium heat.
          2. +
          3. Add the sugar, milk, cocoa powder, and salt to the saucepan and stir until well combined.
          4. +
          5. Bring the mixture to a boil, stirring constantly, and then reduce the heat to low and simmer for 5 minutes.
          6. +
          7. Remove the saucepan from the heat and stir in the chocolate chips and vanilla extract until the chocolate is melted and the mixture is smooth.
          8. +
          9. Pour the fudge into a greased 8-inch square pan and let it cool completely before cutting into squares.
          10. +
          +

          More Recipes

          +
          + + +``` diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/elements-and-tags-question-a.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/elements-and-tags-question-a.md new file mode 100644 index 00000000000000..f4b05b12871c94 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/elements-and-tags-question-a.md @@ -0,0 +1,54 @@ +--- +id: 637f4e0e72c65bc8e73dfe1e +videoId: LGQuIIv2RVA +title: Elements and Tags Question A +challengeType: 15 +dashedName: elements-and-tags-question-a +--- + +# --description-- + +Almost all elements on an HTML page are just pieces of content wrapped in opening and closing HTML tags. + +Opening tags tell the browser this is the start of an HTML element. They are comprised of a keyword enclosed in angle brackets `<>`. For example, an opening paragraph tag looks like this: `

          `. + +Closing tags tell the browser where an element ends. They are almost the same as opening tags; the only difference is that they have a forward slash before the keyword. For example, a closing paragraph tag looks like this: `

          `. + +A full paragraph element looks like this: + +element diagram + +You can think of elements as containers for content. The opening and closing tags tell the browser what content the element contains. The browser can then use that information to determine how it should interpret and format the content. + +There are some HTML elements that do not have a closing tag. These elements often look like this: `
          ` or ``, but some can also be used without the closing forward slash such as `
          ` or ``. These are known as self-closing tags or empty elements because they don’t wrap any content. You will encounter a few of these in later lessons, but for the most part, elements will have both opening and closing tags. + +HTML has a vast list of predefined tags that you can use to create all kinds of different elements. It is important to use the correct tags for content. Using the correct tags can have a big impact on two aspects of your sites: how they are ranked in search engines; and how accessible they are to users who rely on assistive technologies, like screen readers, to use the internet. + +Using the correct elements for content is called semantic HTML. You will explore this in much more depth later on in the curriculum. + +# --question-- + +## --assignment-- + +Watch Kevin Powell’s [Introduction to HTML video](https://www.youtube.com/watch?v=LGQuIIv2RVA&list=PL4-IK0AVhVjM0xE0K2uZRvsM7LkIhsPT-) + +## --text-- + +What are HTML tags? + +## --answers-- + +HTML tags tell the browser what content an element contains. + +--- + +HTML tags tell the browser when to load its content. + +--- + +HTML tags tell the browser what content the next element contains. + + +## --video-solution-- + +1 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/elements-and-tags-question-b.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/elements-and-tags-question-b.md new file mode 100644 index 00000000000000..9e8720616fb4f2 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/elements-and-tags-question-b.md @@ -0,0 +1,50 @@ +--- +id: 637f4e1672c65bc8e73dfe1f +videoId: LGQuIIv2RVA +title: Elements and Tags Question B +challengeType: 15 +dashedName: elements-and-tags-question-b +--- + +# --description-- + +Almost all elements on an HTML page are just pieces of content wrapped in opening and closing HTML tags. + +Opening tags tell the browser this is the start of an HTML element. They are comprised of a keyword enclosed in angle brackets <>. For example, an opening paragraph tag looks like this: `

          `. + +Closing tags tell the browser where an element ends. They are almost the same as opening tags; the only difference is that they have a forward slash before the keyword. For example, a closing paragraph tag looks like this: `

          `. + +A full paragraph element looks like this: + +element diagram + +You can think of elements as containers for content. The opening and closing tags tell the browser what content the element contains. The browser can then use that information to determine how it should interpret and format the content. + +There are some HTML elements that do not have a closing tag. These elements often look like this: `
          ` or ``, but some can also be used without the closing forward slash such as `
          ` or ``. These are known as self-closing tags or empty elements because they don’t wrap any content. You will encounter a few of these in later lessons, but for the most part, elements will have both opening and closing tags. + +HTML has a vast list of predefined tags that you can use to create all kinds of different elements. It is important to use the correct tags for content. Using the correct tags can have a big impact on two aspects of your sites: how they are ranked in search engines; and how accessible they are to users who rely on assistive technologies, like screen readers, to use the internet. + +Using the correct elements for content is called semantic HTML. You will explore this in much more depth later on in the curriculum. + +# --question-- + +## --text-- + +What are the three parts of most HTML elements? + +## --answers-- + +An opening tag, self closing tag, and content. + +--- + +An opening tag, closing tag, and content. + +--- + +An opening tag, closing tag, and attribute. + + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-a.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-a.md new file mode 100644 index 00000000000000..d563ebf0ac3064 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-a.md @@ -0,0 +1,55 @@ +--- +id: 637f4e1c72c65bc8e73dfe20 +videoId: V8UAEoOvqFg +title: HTML Boilerplate Question A +challengeType: 15 +dashedName: html-boilerplate-question-a +--- + +# --description-- + +To demonstrate an HTML boilerplate, you first need an HTML file to work with. + +Create a new folder on your computer and name it `html-boilerplate`. Within that folder create a new file and name it `index.html`. + +You’re probably already familiar with a lot of different types of files, for example doc, pdf, and image files. + +To let the computer know you want to create an HTML file, you need to append the filename with the `.html` extension as you have done when creating the `index.html` file. + +It is worth noting that you named your HTML file index. You should always name the HTML file that will contain the homepage of your websites `index.html`. This is because web servers will by default look for an index.html page when users land on your websites - and not having one will cause big problems. + +## The DOCTYPE + +Every HTML page starts with a doctype declaration. The doctype’s purpose is to tell the browser what version of HTML it should use to render the document. The latest version of HTML is HTML5, and the doctype for that version is simply ``. + +The doctypes for older versions of HTML were a bit more complicated. For example, this is the doctype declaration for HTML4: + +```html + +``` + +However, you probably won’t ever want to be using an older version of HTML, and so you’ll always use ``. + +Open the `index.html` file created earlier in your text editor and add `` to the very first line. + +# --question-- +## --text-- + +What is the purpose of the `DOCTYPE` declaration? + +## --answers-- + +It tells the browser which version of HTML to use to render the document. + +--- + +It tells the browser that this document uses JavaScript. + +--- + +It tells the browser the title of the document. + + +## --video-solution-- + +1 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-b.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-b.md new file mode 100644 index 00000000000000..7a5284322397ba --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-b.md @@ -0,0 +1,47 @@ +--- +id: 637f4e2872c65bc8e73dfe21 +videoId: V8UAEoOvqFg +title: HTML Boilerplate Question B +challengeType: 15 +dashedName: html-boilerplate-question-b +--- + +# --description-- + +After you declare the doctype, you need to provide an `` element. This is what’s known as the root element of the document, meaning that every other element in the document will be a descendant of it. + +This becomes more important later on when you learn about manipulating HTML with JavaScript. For now, just know that the `html` element should be included on every HTML document. + +Back in the `index.html` file, let’s add the `` element by typing out its opening and closing tags, like so: + +```html + + + +``` + +## What is the lang attribute? +`lang` specifies the language of the text content in that element. This attribute is primarily used for improving accessibility of the webpage. It allows assistive technologies, for example screen readers, to adapt according to the language and invoke correct pronunciation. + +# --question-- + +## --text-- + +What is the `html` element? + +## --answers-- + +It is the root element in the document and tells the browser which version of HTML it should use. + +--- + +It is the root element in the document and all other elements should descend from it. + +--- + +It is the root element in the document and all other elements should come after it. + + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-c.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-c.md new file mode 100644 index 00000000000000..76ceb2841e5e2d --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-c.md @@ -0,0 +1,66 @@ +--- +id: 637f4e2f72c65bc8e73dfe22 +videoId: LGQuIIv2RVA +title: HTML Boilerplate Question C +challengeType: 15 +dashedName: html-boilerplate-question-c +--- + +# --description-- + +The `` element is where you put important meta-information about your webpages, and stuff required for your webpages to render correctly in the browser. Inside the ``, you should not use any element that displays content on the webpage. + +## The Charset Meta Element +You should always have the `meta` tag for the charset encoding of the webpage in the head element: ``. + +Setting the encoding is very important because it ensures that the webpage will display special symbols and characters from different languages correctly in the browser. + +## Title Element +Another element you should always include in the head of an HTML document is the `title` element: + +```html +My First Webpage +``` + +The `title` element is used to give webpages a human-readable title which is displayed in your webpage’s browser tab. + +If you didn’t include a `title` element, the webpage’s title would default to its file name. In your case that would be `index.html`, which isn’t very meaningful for users; this would make it very difficult to find your webpage if the user has many browser tabs open. + +There are many more elements that can go within the `head` of an HTML document. However, for now it’s only crucial to know about the two elements you have covered here. You will introduce more elements that go into the `head` throughout the rest of the curriculum. + +Back in `index.html` file, let’s add a `head` element with a `charset` `meta` element and a `title` within it. The head element goes within the HTML element and should always be the first element under the opening `` tag: + + +```html + + + + + + My First Webpage + + +``` + +# --question-- + +## --text-- + +What is the purpose of the `head` element? + +## --answers-- + +The `head` element is used to display all elements that are displayed on the webpage. + +--- + +The `head` element is used to display important information about your webpage and is used to render web pages correctly with `meta` elements. + +--- + +The `head` element is used to display the header content on top of the webpage. + + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-d.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-d.md new file mode 100644 index 00000000000000..302b6a95d449e5 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/html-boilerplate-question-d.md @@ -0,0 +1,48 @@ +--- +id: 637f4e3672c65bc8e73dfe23 +videoId: V8UAEoOvqFg +title: HTML Boilerplate Question D +challengeType: 15 +dashedName: html-boilerplate-question-d +--- + +# --description-- + +The final element needed to complete the HTML boilerplate is the `` element. This is where all the content that will be displayed to users will go - the text, images, lists, links, and so on. + +To complete the boilerplate, add a `body` element to the `index.html` file. The `body` element also goes within the `html` element and is always below the `head` element, like so: + +# --question-- + +## --assignment-- + +Watch and follow along to Kevin Powell’s brilliant Building your first web page video above. + +--- + +Build some muscle memory by deleting the contents of the `index.html` file and trying to write out all the boilerplate again from memory. Don’t worry if you have to peek at the lesson content the first few times if you get stuck. Just keep going until you can do it a couple of times from memory. + +--- + +Run your boilerplate through this [HTML validator](https://www.freeformatter.com/html-validator.html). Validators ensure your markup is correct and are an excellent learning tool, as they provide feedback on syntax errors you may be making often and aren’t aware of, such as missing closing tags and extra spaces in your HTML. + +## --text-- + +What is the purpose of the `body` element? + +## --answers-- + +This is where all important information about the webpage is displayed such as the `title` and `meta` tags. + +--- + +This is where you tell the browser how to render the webpage correctly. + +--- + +This is where all content will be displayed on the page such images, text, and links. + + +## --video-solution-- + +3 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-a.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-a.md new file mode 100644 index 00000000000000..aa20f137e8955b --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-a.md @@ -0,0 +1,42 @@ +--- +id: 6374f208de18c50e48ba767b +videoId: LGQuIIv2RVA +title: Introduction To HTML and CSS Question A +challengeType: 15 +dashedName: introduction-to-html-and-css-question-a +--- + +# --description-- + +HTML and CSS are two languages that work together to create everything that you see when you look at something on the internet. HTML is the raw data that a webpage is built out of. All the text, links, cards, lists, and buttons are created in HTML. CSS is what adds style to those plain elements. HTML puts information on a webpage, and CSS positions that information, gives it color, changes the font, and makes it look great! + +Many helpful resources out there keep referring to HTML and CSS as programming languages, but if you want to get technical, labeling them as such is not quite accurate. This is because they are only concerned with presenting information. They are not used to program logic. JavaScript, which you will learn in the next section, is a programming language because it’s used to make webpages do things. Yet, there is quite a lot you can do with just HTML and CSS, and you will definitely need them both. Throughout our curriculum, the following lessons focus on giving you the tools you need to succeed once you reach JavaScript content. + +# --question-- + +## --assignment-- + +Read the HTML vs CSS vs JavaScript article. It is a quick overview of the relationships between HTML, CSS, and JavaScript. + +## --text-- + +Which of the following statements is true? + +## --answers-- + +CSS is used to create the basic structure of a webpage, and HTML is used to add style. + +--- + +HTML is used to create the basic structure of a webpage, and CSS is used to add style. + +--- + +HTML and CSS are used to add style to a webpage, and JavaScript is used to create the basic structure. + + +## --video-solution-- + +2 + + diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-b.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-b.md new file mode 100644 index 00000000000000..cd9cf900330f27 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-b.md @@ -0,0 +1,37 @@ +--- +id: 6376327e2724a688c04636e3 +videoId: LGQuIIv2RVA +title: Introduction To HTML and CSS Question B +challengeType: 15 +dashedName: introduction-to-html-and-css-question-b +--- + +# --description-- + + +HTML and CSS are two languages that work together to create everything that you see when you look at something on the internet. HTML is the raw data that a webpage is built out of. All the text, links, cards, lists, and buttons are created in HTML. CSS is what adds style to those plain elements. HTML puts information on a webpage, and CSS positions that information, gives it color, changes the font, and makes it look great! + +Many helpful resources out there keep referring to HTML and CSS as programming languages, but if you want to get technical, labeling them as such is not quite accurate. This is because they are only concerned with presenting information. They are not used to program logic. JavaScript, which you will learn in the next section, is a programming language because it’s used to make webpages do things. Yet, there is quite a lot you can do with just HTML and CSS, and you will definitely need them both. Throughout our curriculum, the following lessons focus on giving you the tools you need to succeed once you reach JavaScript content. + +# --question-- + +## --text-- + +Between HTML and CSS, which should you use to add paragraphs of text on a webpage? + +## --answers-- + +CSS + +--- + +JavaScript + +--- + +HTML + + +## --video-solution-- + +3 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-c.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-c.md new file mode 100644 index 00000000000000..eb759394680d6a --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-c.md @@ -0,0 +1,34 @@ +--- +id: 637633162724a688c04636e4 +videoId: LGQuIIv2RVA +title: Introduction To HTML and CSS Question C +challengeType: 15 +dashedName: introduction-to-html-and-css-question-c +--- + +# --description-- + +HTML and CSS are two languages that work together to create everything that you see when you look at something on the internet. HTML is the raw data that a webpage is built out of. All the text, links, cards, lists, and buttons are created in HTML. CSS is what adds style to those plain elements. HTML puts information on a webpage, and CSS positions that information, gives it color, changes the font, and makes it look great! + +Many helpful resources out there keep referring to HTML and CSS as programming languages, but if you want to get technical, labeling them as such is not quite accurate. This is because they are only concerned with presenting information. They are not used to program logic. JavaScript, which you will learn in the next section, is a programming language because it’s used to make webpages do things. Yet, there is quite a lot you can do with just HTML and CSS, and you will definitely need them both. Throughout our curriculum, the following lessons focus on giving you the tools you need to succeed once you reach JavaScript content. +# --question-- + +## --text-- + +Between HTML and CSS, which should you use to change the font and background color of a button? + +## --answers-- + +You should use CSS to change the background color and font of a button. + +--- + +You should use JavaScript to change the background color and font of a button. + +--- + +You should use HTML to change the background color and font of a button. + +## --video-solution-- + +1 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-d.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-d.md new file mode 100644 index 00000000000000..9e9ee049b7559e --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/introduction-to-html-css-question-d.md @@ -0,0 +1,35 @@ +--- +id: 637633672724a688c04636e5 +videoId: LGQuIIv2RVA +title: Introduction To HTML and CSS Question D +challengeType: 15 +dashedName: introduction-to-html-and-css-question-d +--- + +# --description-- + +HTML and CSS are two languages that work together to create everything that you see when you look at something on the internet. HTML is the raw data that a webpage is built out of. All the text, links, cards, lists, and buttons are created in HTML. CSS is what adds style to those plain elements. HTML puts information on a webpage, and CSS positions that information, gives it color, changes the font, and makes it look great! + +Many helpful resources out there keep referring to HTML and CSS as programming languages, but if you want to get technical, labeling them as such is not quite accurate. This is because they are only concerned with presenting information. They are not used to program logic. JavaScript, which you will learn in the next section, is a programming language because it’s used to make webpages do things. Yet, there is quite a lot you can do with just HTML and CSS, and you will definitely need them both. Throughout our curriculum, the following lessons focus on giving you the tools you need to succeed once you reach JavaScript content. + +# --question-- + +## --text-- + +What is the difference between HTML, CSS, and JavaScript? + +## --answers-- + +HTML is for creating interactive elements, CSS is for the look and feel, and JavaScript is for creating the structure of a webpage. + +--- + +CSS is for the look and feel, JavaScript is for creating interactive elements, and HTML is for creating the structure of a webpage. + +--- + +JavaScript is for the look and feel, CSS is for creating the structure, and HTML is for creating interactive elements of a webpage. + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-a.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-a.md new file mode 100644 index 00000000000000..b4d237448f3245 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-a.md @@ -0,0 +1,66 @@ +--- +id: 637f704072c65bc8e73dfe36 +videoId: tsEQgGjSmkM +title: Links and Images Question A +challengeType: 15 +dashedName: links-and-images-question-a +--- + +# --description-- + +To get some practice using links and images throughout this lesson you need an HTML project to work with. + +- Create a new directory named `odin-links-and-images`. + +- Within that directory, create a new file named `index.html`. + +- Fill in the usual HTML boilerplate. + +- Finally, add the following `h1` to the `body`: `

          Homepage

          ` + +## Anchor Elements +To create a link in HTML, you use the anchor element. An anchor element is defined by wrapping the text or another HTML element you want to be a link with an `` tag. Add the following to the `body` of the `index.html` page you created and open it in the browser: + +```html +click me +``` + +You may have noticed that clicking this link doesn’t do anything. This is because an anchor tag on its own won’t know where you want to link to. You have to tell it a destination to go to. You do this by using an HTML attribute. + +An HTML attribute gives additional information to an HTML element and always goes in the element’s opening tag. An attribute is usually made up of two parts: a name, and a value; however, not all attributes require a value. In your case, you need to add a `href` (hyperlink reference) attribute to the opening anchor tag. The value of the `href` attribute is the destination you want your link to go to. + +Add the following `href` attribute to the anchor element you created previously and try clicking it again, don’t forget to refresh the browser so the new changes can be applied. + +```html +click me +``` + +By default, any text wrapped with an anchor tag without a `href` attribute will look like plain text. If the `href` attribute is present, the browser will give the text a blue color and underline it to signify it is a link. + +It’s worth noting you can use anchor tags to link to any kind of resource on the internet, not just other HTML documents. You can link to videos, pdf files, images, and so on, but for the most part, you will be linking to other HTML documents. + +# --question-- + +## --assignment-- + +Watch Kevin Powell’s HTML Links video above. + +## --text-- + +What HTML tag is used to create a link? + +## --answers-- + +`` + +--- + +`

          ` + +--- + +`

            ` + +## --video-solution-- + +1 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-b.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-b.md new file mode 100644 index 00000000000000..164fb01214f86b --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-b.md @@ -0,0 +1,55 @@ +--- +id: 637f703572c65bc8e73dfe35 +videoId: tsEQgGjSmkM +title: Links and Images Question B +challengeType: 15 +dashedName: links-and-images-question-b +--- + +# --description-- + +To get some practice using links and images throughout this lesson you need an HTML project to work with. + +- Create a new directory named odin-links-and-images. + +- Within that directory, create a new file named index.html. + +- Fill in the usual HTML boilerplate. + +- finally, add the following h1 to the body: `

            Homepage

            ` + +## Anchor Elements +To create a link in HTML, you use the anchor element. An anchor element is defined by wrapping the text or another HTML element you want to be a link with an `
            ` tag. Add the following to the body of the index.html page you created and open it in the browser: + +```html +click me +``` + +You may have noticed that clicking this link doesn’t do anything. This is because an anchor tag on its own won’t know where you want to link to. You have to tell it a destination to go to. You do this by using an HTML attribute. An HTML attribute gives additional information to an HTML element and always goes in the element’s opening tag. An attribute is usually made up of two parts: a name, and a value; however, not all attributes require a value. In your case, you need to add a href (hyperlink reference) attribute to the opening anchor tag. The value of the href attribute is the destination you want your link to go to. Add the following href attribute to the anchor element you created previously and try clicking it again, don’t forget to refresh the browser so the new changes can be applied. + +```html +click me +``` + +By default, any text wrapped with an anchor tag without a `href` attribute will look like plain text. If the `href` attribute is present, the browser will give the text a blue color and underline it to signify it is a link. It’s worth noting you can use anchor tags to link to any kind of resource on the internet, not just other HTML documents. You can link to videos, pdf files, images, and so on, but for the most part, you will be linking to other HTML documents. + +# --question-- +## --text-- + +What is an attribute? +## --answers-- + +An HTML attribute gives additional information to an HTML element and always goes in the element’s closing tag. + +--- + +An HTML attribute is used to tell the browser what the element contains. + +--- + +An HTML attribute gives additional information to an HTML element and always goes in the element’s opening tag. + + +## --video-solution-- + +3 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-c.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-c.md new file mode 100644 index 00000000000000..c8a3913d77eeaf --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-c.md @@ -0,0 +1,56 @@ +--- +id: 637f703072c65bc8e73dfe34 +videoId: tsEQgGjSmkM +title: Links and Images Question C +challengeType: 15 +dashedName: links-and-images-question-c +--- + +# --description-- + +To get some practice using links and images throughout this lesson you need an HTML project to work with. + +- Create a new directory named odin-links-and-images. + +- Within that directory, create a new file named index.html. + +- Fill in the usual HTML boilerplate. + +- finally, add the following h1 to the body: `

            Homepage

            ` + +## Anchor Elements +To create a link in HTML, you use the anchor element. An anchor element is defined by wrapping the text or another HTML element you want to be a link with an `` tag. Add the following to the body of the index.html page you created and open it in the browser: + +```html +click me +``` + +You may have noticed that clicking this link doesn’t do anything. This is because an anchor tag on its own won’t know where you want to link to. You have to tell it a destination to go to. You do this by using an HTML attribute. An HTML attribute gives additional information to an HTML element and always goes in the element’s opening tag. An attribute is usually made up of two parts: a name, and a value; however, not all attributes require a value. In your case, you need to add a href (hyperlink reference) attribute to the opening anchor tag. The value of the href attribute is the destination you want your link to go to. Add the following href attribute to the anchor element you created previously and try clicking it again, don’t forget to refresh the browser so the new changes can be applied. + +```html +click me +``` + +By default, any text wrapped with an anchor tag without a `href` attribute will look like plain text. If the `href` attribute is present, the browser will give the text a blue color and underline it to signify it is a link. It’s worth noting you can use anchor tags to link to any kind of resource on the internet, not just other HTML documents. You can link to videos, pdf files, images, and so on, but for the most part, you will be linking to other HTML documents. + +# --question-- + +## --text-- + +What attribute tells links where to go to? + +## --answers-- + +`src` + +--- + +`href` + +--- + +`link` + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-d.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-d.md new file mode 100644 index 00000000000000..2b6a665eb87887 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-d.md @@ -0,0 +1,112 @@ +--- +id: 637f702872c65bc8e73dfe33 +videoId: ta3Oxx7Yqbo +title: Links and Images Question D +challengeType: 15 +dashedName: links-and-images-question-d +--- + +# --description-- + + +Generally, there are two kinds of links you will create: + +- Links to pages on other websites on the internet + +- Links to pages located on your own websites + + +## Absolute Links +Links to pages on other websites on the internet are called absolute links. A typical absolute link will be made up of the following parts: `protocol://domain/path`. An absolute link will always contain the protocol and domain of the destination. + +You’ve already seen an absolute link in action. The link you created to The Odin Project’s About page earlier was an absolute link as it contains the protocol and domain. + +`https://www.theodinproject.com/about` + +## Relative Links +Links to other pages within your own website are called relative links. Relative links do not include the domain name, since it is another page on the same site, it assumes the domain name will be the same as the page you created the link on. + +Relative links only include the file path to the other page, relative to the page you are creating the link on. This is quite abstract, let’s see this in action using an example. + +Within the `odin-links-and-images` directory, create another HTML file named `about.html` and paste the following code into it: + +```html + + + + + Odin Links and Images + + + +

            About Page

            + + +``` + +Back in the index page, add the following anchor element to create a link to the about page: + +```html + +

            Homepage

            + click me + + About + +``` + +Open the index file in a browser and click on the about link to make sure it is all wired together correctly. Clicking the link should go to the about page you just created. + +This works because the index and about page are in the same directory. That means you can simply use its name (`about.html`) as the link’s href value. + +But you will usually want to organize your website directories a little better. Normally you would only have the `index.html` at the root directory and all other HTML files in their own directory. + +Create a directory named `pages` within the `odin-links-and-images` directory and move the `about.html` file into this new directory. + +Refresh the index page in the browser and then click on the about link. It will now be broken. This is because the location of the about page file has changed. + +To fix this, you just need to update the about link `href` value to include the `pages/` directory since that is the new location of the about file relative to the index file. + +```html + +

            Homepage

            + About + +``` + +Refresh the index page in the browser and try clicking the about link again, it should now be back in working order. + +In many cases, this will work just fine; however, you can still run into unexpected issues with this approach. Prepending `./` before the link will in most cases prevent such issues. By adding `./` you are specifying to your code that it should start looking for the file/directory relative to the **current** directory. + +```html + +

            Homepage

            + About + +``` + +# --question-- + +## --assignment-- + +Watch Kevin Powell’s HTML File Structure video above. + +## --text-- + +What is the difference between an absolute and a relative link? + +## --answers-- + +An absolute link is a link to another page on the current website. A relative link is a link to another website. + +--- + +An absolute link is a link to another website. A relative link is a link another page on the current website. + +--- + +There is no difference between absolute and relative links. + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-e.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-e.md new file mode 100644 index 00000000000000..a935ae3262a399 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-e.md @@ -0,0 +1,98 @@ +--- +id: 637f702372c65bc8e73dfe32 +videoId: 0xoztJCHpbQ +title: Links and Images Question E +challengeType: 15 +dashedName: links-and-images-question-e +--- + +# --description-- + +Websites would be fairly boring if they could only display text. Luckily HTML provides a wide variety of elements for displaying all sorts of different media. The most widely used of these is the image element. + +To display an image in HTML you use the `` element. Unlike the other elements you have encountered, the `` element is self-closing. Empty, self-closing HTML elements do not need a closing tag. + +Instead of wrapping content with an opening and closing tag, it embeds an image into the page using a `src` attribute which tells the browser where the image file is located. The `src` attribute works much like the `href` attribute for anchor tags. It can embed an image using both absolute and relative paths. + +For example, using an absolute path you can display an image located on The Odin Project site: + + + +To use images that you have on your own websites, you can use a relative path. + +- Create a new directory named `images` within the `odin-links-and-images` project. + +- Next, download [this image](https://unsplash.com/photos/Mv9hjnEUHR4/download?force=true&w=640) and move it into the `images` directory you just created. + +- Rename the image to `dog.jpg`. + +Finally add the image to the `index.html` file: + +```html + +

            Homepage

            + click me + + About + + + +``` + +Save the `index.html` file and open it in a browser to view Charles in all his glory. + + +## Parent Directories + +What if you want to use the dog image in the about page? You would first have to go up one level out of the pages directory into its parent directory so you could then access the images directory. + +To go to the parent directory you need to use two dots in the relative filepath like this: `../.` Let’s see this in action, within the body of the `about.html` file, add the following image below the heading you added earlier: + +```html + +``` + +To break this down: + +- First, you are going to the parent directory of the pages directory which is `odin-links-and-images`. + +- Then, from the parent directory, you can go into the `images` directory. + +- Finally, you can access the `dog.jpg` file. + +Using the metaphor we used earlier, using `../` in a filepath is kind of like stepping out from the room you are currently in to the main hallway so you can go to another room. + +## `Alt` attribute + +Besides the `src` attribute, every image element should also have an `alt` (alternative text) attribute. + +The `alt` attribute is used to describe an image. It will be used in place of the image if it cannot be loaded. It is also used with screen readers to describe what the image is to visually impaired users. + +This is how the The Odin Project logo example you used earlier looks with an `alt` attribute included: + + +# --question-- + +## --assignment-- + +Watch Kevin Powell’s HTML Images Video above. + +## --text-- + +Which tag is used to display an image? + +## --answers-- + +`` + +--- + +`` + +--- + +`` + +## --video-solution-- + +3 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-f.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-f.md new file mode 100644 index 00000000000000..ba4eb809e5d54c --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-f.md @@ -0,0 +1,94 @@ +--- +id: 637f701c72c65bc8e73dfe31 +videoId: 0xoztJCHpbQ +title: Links and Images Question F +challengeType: 15 +dashedName: links-and-images-question-f +--- + +# --description-- + +Websites would be fairly boring if they could only display text. Luckily HTML provides a wide variety of elements for displaying all sorts of different media. The most widely used of these is the image element. + +To display an image in HTML you use the `` element. Unlike the other elements you have encountered, the `` element is self-closing. Empty, self-closing HTML elements do not need a closing tag. + +Instead of wrapping content with an opening and closing tag, it embeds an image into the page using a src attribute which tells the browser where the image file is located. The src attribute works much like the href attribute for anchor tags. It can embed an image using both absolute and relative paths. + +For example, using an absolute path you can display an image located on The Odin Project site: + + + +To use images that you have on your own websites, you can use a relative path. + +- Create a new directory named `images` within the `odin-links-and-images` project. + +- Next, download [this image](https://unsplash.com/photos/Mv9hjnEUHR4/download?force=true&w=640) and move it into the images directory you just created. + +- Rename the image to `dog.jpg`. + +Finally add the image to the `index.html` file: + +```html + +

            Homepage

            +
            click me + + About + + + +``` + +Save the `index.html` file and open it in a browser to view Charles in all his glory. + + +## Parent Directories + +What if you want to use the dog image in the about page? You would first have to go up one level out of the pages directory into its parent directory so you could then access the images directory. + +To go to the parent directory you need to use two dots in the relative filepath like this: `../.` Let’s see this in action, within the body of the `about.html` file, add the following image below the heading you added earlier: + +```html + +``` + +To break this down: + +- First, you are going to the parent directory of the pages directory which is `odin-links-and-images`. + +- Then, from the parent directory, you can go into the `images` directory. + +- Finally, you can access the `dog.jpg` file. + +Using the metaphor we used earlier, using `../` in a filepath is kind of like stepping out from the room you are currently in to the main hallway so you can go to another room. + +## Alt attribute + +Besides the src attribute, every image element should also have an alt (alternative text) attribute. + +The alt attribute is used to describe an image. It will be used in place of the image if it cannot be loaded. It is also used with screen readers to describe what the image is to visually impaired users. + +This is how the The Odin Project logo example you used earlier looks with an alt attribute included: + + +# --question-- + +## --text-- + +What two attributes do images always need to have? + +## --answers-- + +`href` and `alt` + +--- + +`name` and `href` + +--- + +`alt` and `src` + +## --video-solution-- + +3 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-g.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-g.md new file mode 100644 index 00000000000000..d1a6fcd44064f7 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-g.md @@ -0,0 +1,94 @@ +--- +id: 637f701572c65bc8e73dfe30 +videoId: 0xoztJCHpbQ +title: Links and Images Question G +challengeType: 15 +dashedName: links-and-images-question-g +--- + +# --description-- + +Websites would be fairly boring if they could only display text. Luckily HTML provides a wide variety of elements for displaying all sorts of different media. The most widely used of these is the image element. + +To display an image in HTML you use the `` element. Unlike the other elements you have encountered, the `` element is self-closing. Empty, self-closing HTML elements do not need a closing tag. + +Instead of wrapping content with an opening and closing tag, it embeds an image into the page using a src attribute which tells the browser where the image file is located. The src attribute works much like the href attribute for anchor tags. It can embed an image using both absolute and relative paths. + +For example, using an absolute path you can display an image located on The Odin Project site: + + + +To use images that you have on your own websites, you can use a relative path. + +- Create a new directory named `images` within the `odin-links-and-images` project. + +- Next, download [this image](https://unsplash.com/photos/Mv9hjnEUHR4/download?force=true&w=640) and move it into the images directory you just created. + +- Rename the image to `dog.jpg`. + +Finally add the image to the `index.html` file: + +```html + +

            Homepage

            + click me + + About + + + +``` + +Save the `index.html` file and open it in a browser to view Charles in all his glory. + + +## Parent Directories + +What if you want to use the dog image in the about page? You would first have to go up one level out of the pages directory into its parent directory so you could then access the images directory. + +To go to the parent directory you need to use two dots in the relative filepath like this: `../.` Let’s see this in action, within the body of the `about.html` file, add the following image below the heading you added earlier: + +```html + +``` + +To break this down: + +- First, you are going to the parent directory of the pages directory which is `odin-links-and-images`. + +- Then, from the parent directory, you can go into the `images` directory. + +- Finally, you can access the `dog.jpg` file. + +Using the metaphor we used earlier, using `../` in a filepath is kind of like stepping out from the room you are currently in to the main hallway so you can go to another room. + +## Alt attribute + +Besides the src attribute, every image element should also have an alt (alternative text) attribute. + +The alt attribute is used to describe an image. It will be used in place of the image if it cannot be loaded. It is also used with screen readers to describe what the image is to visually impaired users. + +This is how the The Odin Project logo example you used earlier looks with an alt attribute included: + + +# --question-- + +## --text-- + +How do you access a parent directory in a filepath? + +## --answers-- + +`../` + +--- + +`./` + +--- + +`.../` + +## --video-solution-- + +1 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-h.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-h.md new file mode 100644 index 00000000000000..cfd73fcfbc1dfe --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/links-and-images-question-h.md @@ -0,0 +1,98 @@ +--- +id: 637f700b72c65bc8e73dfe2f +videoId: 0xoztJCHpbQ +title: Links and Images Question H +challengeType: 15 +dashedName: links-and-images-question-h +--- + +# --description-- + +Websites would be fairly boring if they could only display text. Luckily HTML provides a wide variety of elements for displaying all sorts of different media. The most widely used of these is the image element. + +To display an image in HTML you use the `` element. Unlike the other elements you have encountered, the `` element is self-closing. Empty, self-closing HTML elements do not need a closing tag. + +Instead of wrapping content with an opening and closing tag, it embeds an image into the page using a src attribute which tells the browser where the image file is located. The src attribute works much like the href attribute for anchor tags. It can embed an image using both absolute and relative paths. + +For example, using an absolute path you can display an image located on The Odin Project site: + + + +To use images that you have on your own websites, you can use a relative path. + +- Create a new directory named `images` within the `odin-links-and-images` project. + +- Next, download [this image](https://unsplash.com/photos/Mv9hjnEUHR4/download?force=true&w=640) and move it into the images directory you just created. + +- Rename the image to `dog.jpg`. + +Finally add the image to the `index.html` file: + +```html + +

            Homepage

            + click me + + About + + + +``` + +Save the `index.html` file and open it in a browser to view Charles in all his glory. + + +## Parent Directories + +What if you want to use the dog image in the about page? You would first have to go up one level out of the pages directory into its parent directory so you could then access the images directory. + +To go to the parent directory you need to use two dots in the relative filepath like this: `../.` Let’s see this in action, within the body of the `about.html` file, add the following image below the heading you added earlier: + +```html + +``` + +To break this down: + +- First, you are going to the parent directory of the pages directory which is `odin-links-and-images`. + +- Then, from the parent directory, you can go into the `images` directory. + +- Finally, you can access the `dog.jpg` file. + +Using the metaphor we used earlier, using `../` in a filepath is kind of like stepping out from the room you are currently in to the main hallway so you can go to another room. + +## Alt attribute + +Besides the src attribute, every image element should also have an alt (alternative text) attribute. + +The alt attribute is used to describe an image. It will be used in place of the image if it cannot be loaded. It is also used with screen readers to describe what the image is to visually impaired users. + +This is how the The Odin Project logo example you used earlier looks with an alt attribute included: + + +# --question-- + +## --assignment-- + +Read about the four main image formats that can be used on the web. + +## --text-- + +What are the four main image formats that you can use for images on the web? + +## --answers-- + +TIFF, GIF, PNG, and SVG. + +--- + +JPG, PNG, GIF, and SVG. + +--- + +JPG, PDF, SVG, and GIF. + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/project-create-a-recipe-page.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/project-create-a-recipe-page.md new file mode 100644 index 00000000000000..657a3f6e32dfb7 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/project-create-a-recipe-page.md @@ -0,0 +1,204 @@ +--- +id: 6391d1a4f7ac71efd0621380 +title: Build a Recipe Page Project +challengeType: 14 +dashedName: project-create-a-recipe-page +--- + +# --description-- + +The website will consist of a main index page which will have links to a few recipes. The website won’t look very pretty by the time you’ve finished. + +**User Stories:** + +1. Your recipe page should contain a `DOCTYPE` tag. +1. Your recipe page should include an `html` element with a `head` and `body` element as children. +1. You should have a `title` element within the `head` element with the text `The Odin Recipes`. +1. You should see an `h1` element that has the text `Creamy Chocolate Fudge`. +1. You should see an image with the url `*placeholder-fcc-cdn*` with a fitting `alt` text. +1. There should be an `h2` element with the text `Description` under the image. +1. You should see a couple of paragraphs under `Description` that describe the recipe. +1. There should be an `h2` element with the text `Ingredients` +1. Under the `Ingredients` heading there should be an unordered list with the ingredients needed for the recipe. +1. Under the list of ingredients add another heading called `Steps`. +1. You should see an ordered list with a couple of steps needed to complete the recipe. +1. Under the steps there should be an `h2` element with the text `More Recipes` +1. You should see a couple of links to other recipes inside an unordered list which has a couple of list items with anchor elements within. +1. These anchor elements should have `href` attribute with the value set to `#` + +# --hints-- + +You should have a `DOCTYPE` tag. + +```js +assert(code.match(//gi)); +``` + +You should have a `html` element with `head` and `body` element. + +```js +const html = document.querySelectorAll('html')[0]; +const head = document.querySelectorAll('html > head')[0]; +const body = document.querySelectorAll('html > body')[0]; + +assert(html && head && body); +``` + +You should have a `title` element within the `head` element that contains the text `The Odin Recipes`. + +```js +assert(document.querySelectorAll('HEAD > TITLE')[0].innerText == 'The Odin Recipes'); +``` + +You should have a `h1` element within your `body` element that contains the text `Creamy Chocolate Fudge`. + +```js +assert(document.querySelectorAll('BODY > H1')[0].innerText == 'Creamy Chocolate Fudge'); +``` + +You should have an image with the url `*placeholder-fcc-cdn*` with an `alt` attribute that has a fitting text. + +```js +const img = document.querySelectorAll('IMG')[0]; + +assert(img && img.alt !='' && img.src === 'https://i.imgur.com/p0J5baJ.jpg') +``` + +You should have an `h2` element with the text `Description`. + +```js +const h2 = document.querySelectorAll('H2')[0]; + +assert(h2.innerText == 'Description'); +``` + +You should have at least two `p` elements describing the recipe. + +```js +const paragraphs = document.querySelectorAll('P'); + +assert(paragraphs.length > 1); +``` + +You should have an `h2` element with the text `Ingredients`. + +```js +const h2 = document.querySelectorAll('H2')[1]; + +assert(h2.innerText == 'Ingredients'); +``` + +You should have an unordered list `
              ` with some ingredients as the list items `
            • `. + +```js +const unorderedList = document.querySelectorAll('UL')[0]; +const listItems = document.querySelectorAll('UL > LI'); + +assert(unorderedList && listItems && listItems.length > 1); +``` + +You should have an `h2` element with the text `Steps`. + +```js +const h2 = document.querySelectorAll('H2')[2]; + +assert(h2.innerText == 'Steps'); +``` + +You should have a `
                ` with the the steps as the list items `
              1. `. + +```js +const orderedList = document.querySelectorAll('OL')[0]; +const listItems = document.querySelectorAll('OL > LI'); + +assert(orderedList && listItems && listItems.length > 1); +``` + +You should have an `h2` element with the text `More Recipes`. + +```js +const h2 = document.querySelectorAll('H2')[3]; + +assert(h2.innerText == 'More Recipes'); +``` + +You should have an unordered list `
                  ` element with list items `
                • ` that contain `` tags which lead to other recipes. + +```js +const unorderedList = document.querySelectorAll('UL')[1]; +const listItems = unorderedList.querySelectorAll('LI'); + +const allAreListItems = unorderedList.children.length == listItems.length; + +const containsAnchors = [...listItems].every(function(listItem) { + return listItem.querySelector("a") !== null; +}); + +assert(unorderedList && allAreListItems && containsAnchors && listItems.length > 1); +``` + +Your anchor tags linking to the recipes should have a `href` attribute with the value set to `#` + +```js +const anchorTags = document.querySelectorAll("a"); + +const allAnchorsHaveHrefHash = [...anchorTags].every(function(anchorTag) { + return anchorTag.hasAttribute("href") && anchorTag.getAttribute("href") === "#"; +}); + +assert(allAnchorsHaveHrefHash && anchorTags.length > 0); +``` + +# --seed-- + +## --seed-contents-- + +```html + +``` + +```css + +``` + +## --solutions-- + +```html + + + + The Odin Recipes + + +

                  Creamy Chocolate Fudge

                  + A delicious chocolate fudge dessert +

                  Description

                  +

                  This recipe is for a rich and creamy chocolate fudge that is sure to satisfy your sweet tooth. It's perfect for a special occasion or as a tasty treat for any time of the year.

                  +

                  This recipe is easy to follow and only requires a few simple ingredients. With just a few steps, you'll be able to create a delicious dessert that everyone will love.

                  +

                  Ingredients

                  +
                    +
                  • 1 cup sugar
                  • +
                  • 1/2 cup unsalted butter
                  • +
                  • 1/4 cup milk
                  • +
                  • 1/4 cup cocoa powder
                  • +
                  • 1/4 cup chocolate chips
                  • +
                  • 1/4 tsp salt
                  • +
                  • 1 tsp vanilla extract
                  • +
                  +

                  Steps

                  +
                    +
                  1. In a medium saucepan, melt the butter over medium heat.
                  2. +
                  3. Add the sugar, milk, cocoa powder, and salt to the saucepan and stir until well combined.
                  4. +
                  5. Bring the mixture to a boil, stirring constantly, and then reduce the heat to low and simmer for 5 minutes.
                  6. +
                  7. Remove the saucepan from the heat and stir in the chocolate chips and vanilla extract until the chocolate is melted and the mixture is smooth.
                  8. +
                  9. Pour the fudge into a greased 8-inch square pan and let it cool completely before cutting into squares.
                  10. +
                  +

                  More Recipes

                  +
                  + + +``` diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-a.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-a.md new file mode 100644 index 00000000000000..f4625eb7e31d54 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-a.md @@ -0,0 +1,65 @@ +--- +id: 637f4e3e72c65bc8e73dfe24 +videoId: kcHKFZBVtf4 +title: Understand Ordered and Unordered List Question A +challengeType: 15 +dashedName: understand-ordered-and-unordered-list-question-a +--- + +# --description-- + +If you want to have a list of items where the order doesn’t matter, like a shopping list of items that can be bought in any order, then you can use an unordered list. + +Unordered lists are created using the `
                    ` element, and each item within the list is created using the list item element `
                  • `. + +Each list item in an unordered list begins with a bullet point: + + + +If you instead want to create a list of items where the order does matter, like step-by-step instructions for a recipe, or your top 10 favorite TV shows, then you can use an ordered list. + +Ordered lists are created using the `
                      ` element. Each individual item in them is again created using the list item element `
                    1. `. However, each list item in an ordered list begins with a number instead: + + + +# --question-- + +## --assignment-- + +Watch the first three minutes of Kevin Powell's video on Ordered and Unordered lists above. + +--- + +Make an unordered shopping list of your favorite foods. + +--- + +Make an ordered list of todo’s you need to get done today. + +--- + +Make an unordered list of places you’d like to visit someday. + +--- + +Make an ordered list of your all time top 5 favorite video games or movies. + +## --text-- + +What HTML tag is used to create an unordered list? + +## --answers-- + +`
                    2. ` + +--- + +`
                        ` + +--- + +`
                          ` + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-b.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-b.md new file mode 100644 index 00000000000000..4c6822fc504163 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-b.md @@ -0,0 +1,45 @@ +--- +id: 637f4e4672c65bc8e73dfe25 +videoId: LGQuIIv2RVA +title: Understand Ordered and Unordered List Question B +challengeType: 15 +dashedName: understand-ordered-and-unordered-list-question-b +--- + +# --description-- + +If you want to have a list of items where the order doesn’t matter, like a shopping list of items that can be bought in any order, then you can use an unordered list. + +Unordered lists are created using the `
                            ` element, and each item within the list is created using the list item element `
                          • `. + +Each list item in an unordered list begins with a bullet point: + + + +If you instead want to create a list of items where the order does matter, like step-by-step instructions for a recipe, or your top 10 favorite TV shows, then you can use an ordered list. + +Ordered lists are created using the `
                              ` element. Each individual item in them is again created using the list item element `
                            1. `. However, each list item in an ordered list begins with a number instead: + + + +# --question-- + +## --text-- + +What HTML tag is used to create an ordered list? + +## --answers-- + +`
                                ` + +--- + +`
                              1. ` + +--- + +`
                                  ` + +## --video-solution-- + +1 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-c.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-c.md new file mode 100644 index 00000000000000..c766990ca220a9 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/understand-ordered-and-unordered-list-question-c.md @@ -0,0 +1,45 @@ +--- +id: 637f4e5172c65bc8e73dfe26 +videoId: LGQuIIv2RVA +title: Understand Ordered and Unordered List Question C +challengeType: 15 +dashedName: understand-ordered-and-unordered-list-question-c +--- + +# --description-- + +If you want to have a list of items where the order doesn’t matter, like a shopping list of items that can be bought in any order, then you can use an unordered list. + +Unordered lists are created using the `
                                    ` element, and each item within the list is created using the list item element `
                                  • `. + +Each list item in an unordered list begins with a bullet point: + + + +If you instead want to create a list of items where the order does matter, like step-by-step instructions for a recipe, or your top 10 favorite TV shows, then you can use an ordered list. + +Ordered lists are created using the `
                                      ` element. Each individual item in them is again created using the list item element `
                                    1. `. However, each list item in an ordered list begins with a number instead: + + + +# --question-- + +## --text-- + +What HTML tag is used to create list items within both unordered and ordered lists? + +## --answers-- + +`
                                        ` + +--- + +`
                                      1. ` + +--- + +`
                                          ` + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-a.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-a.md new file mode 100644 index 00000000000000..8698b62aca812a --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-a.md @@ -0,0 +1,60 @@ +--- +id: 637f4e5872c65bc8e73dfe27 +videoId: yqcd-XkxZNM +title: Working With Text Question A +challengeType: 15 +dashedName: working-with-text-question-a +--- + +# --description-- + +What would you expect the following text to output on an HTML page? + +```html + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. + + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. + +``` + +It looks like two paragraphs of text, and so you might expect it to display in that way. However that is not the case, as you can see in the output below: + + + +When the browser encounters new lines like this in your HTML, it will compress them down into one single space. The result of this compression is that all of the text is clumped together into one long line. + +If you want to create paragraphs in HTML, you need to use the paragraph element, which will add a newline after each of your paragraphs. A paragraph element is defined by wrapping text content with a `

                                          ` tag. + +Changing our example from before to use paragraph elements fixes the issue: + + + +# --question-- + +## --assignment-- + +Watch and follow along to Kevin Powell’s HTML Paragraph and Headings Video above. + +## --text-- + +How do you create a paragraph in HTML? + +## --answers-- + +`

                                          This is a paragraph

                                          ` + +--- + +`

                                          This is a paragraph

                                          ` + +--- + +`This is a paragraph` + + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-b.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-b.md new file mode 100644 index 00000000000000..a74d8d11452fcb --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-b.md @@ -0,0 +1,40 @@ +--- +id: 637f4e5f72c65bc8e73dfe28 +videoId: yqcd-XkxZNM +title: Working With Text Question B +challengeType: 15 +dashedName: working-with-text-question-b +--- + +# --description-- + +Headings are different from other HTML text elements: they are displayed larger and bolder than other text to signify that they are headings. + +There are 6 different levels of headings starting from `

                                          ` to `

                                          `. The number within a heading tag represents that heading’s level. The largest and most important heading is `h1`, while `h6` is the tiniest heading at the lowest level. + +Headings are defined much like paragraphs. For example, to create an `h1` heading, we wrap our heading text in a `

                                          ` tag. + + + +Using the correct level of heading is important as levels provide a hierarchy to the content. An `h1` heading should always be used for the heading of the overall page, and the lower level headings should be used as the headings for content in smaller sections of the page. + +# --question-- +## --text-- + +How many different levels of headings are there and what is the difference between them? + +## --answers-- + +There are 5 different levels of headings. `h5` is the smallest and least important heading, and `h1` is the largest and most important heading. + +--- + +There are 6 different levels of headings. `h6` is the largest and most important heading, and `h1` is the smallest and least important heading. + +--- + +There are 6 different levels of headings. `h1` is the largest and most important heading, and `h6` is the smallest and least important heading. + +## --video-solution-- + +3 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-c.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-c.md new file mode 100644 index 00000000000000..6ccf0e06658591 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-c.md @@ -0,0 +1,47 @@ +--- +id: 637f4e6672c65bc8e73dfe29 +videoId: gW6cBZLUk6M +title: Working With Text Question C +challengeType: 15 +dashedName: working-with-text-question-c +--- + +# --description-- + +The `` element makes text bold. It also semantically marks text as important; this affects tools, like screen readers, that users with visual impairments will rely on to use your website. The tone of voice on some screen readers will change to communicate the importance of the text within a `strong` element. To define a `strong` element you wrap text content in a `` tag. + +You can use `strong` on its own: + + + +But you will probably find yourself using the `strong` element much more in combination with other text elements, like this: + + + +Sometimes you will want to make text bold without giving it an important meaning. You’ll learn how to do that in the CSS lessons later in the curriculum. + +# --question-- + +## --assignment-- + +Watch Kevin Powell’s HTML Bold and Italic Text Video above. + +## --text-- + +What element should you use to make text bold and important? + +## --answers-- + +`This is an important message` + +--- + +`

                                          This is an important message

                                          ` + +--- + +`This is an important message` + +## --video-solution-- + +3 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-d.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-d.md new file mode 100644 index 00000000000000..d6647f9a7eabf2 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-d.md @@ -0,0 +1,39 @@ +--- +id: 637f4e6e72c65bc8e73dfe2a +videoId: gW6cBZLUk6M +title: Working With Text Question D +challengeType: 15 +dashedName: working-with-text-question-d +--- + +# --description-- + +The `em` element makes text italic. It also semantically places emphasis on the text, which again may affect things like screen readers. To define an emphasized element you wrap text content in a `` tag. + +To use `em` on its own: + + +Again, like the `strong` element, you will find yourself mostly using the `em` element with other text elements: + + + +# --question-- +## --text-- + +What element should you use to make text italicized to add emphasis? + +## --answers-- + +`This is an italic message` + +--- + +`This is an italic message` + +--- + +`This is an italic message` + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-e.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-e.md new file mode 100644 index 00000000000000..d022a6331e9b99 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-e.md @@ -0,0 +1,66 @@ +--- +id: 637f4e7972c65bc8e73dfe2b +videoId: gW6cBZLUk6M +title: Working With Text Question E +challengeType: 15 +dashedName: working-with-text-question-e +--- + +# --description-- + +You may have noticed that in all the examples in this lesson you indent any elements that are within other elements. This is known as nesting elements. + +When you nest elements within other elements, you create a parent and child relationship between them. The nested elements are the children and the element they are nested within is the parent. + +In the following example, the `body` element is the parent and the `p` is the child: + +```html + + + + +

                                          Lorem ipsum dolor sit amet.

                                          + + +``` + +Just as in human relationships, HTML parent elements can have many children. Elements at the same level of nesting are considered to be siblings. + +For example, the two `p` elements in the following code are siblings, since they are both children of the `body` tag and are at the same level of nesting as each other: + +```html + + + + +

                                          Lorem ipsum dolor sit amet.

                                          +

                                          Ut enim ad minim veniam.

                                          + + +``` + +You use indentation to make the level of nesting clear and readable for yourselves and other developers who will work with your HTML in the future. It is recommended to indent any child elements by two spaces. + +The parent, child, and sibling relationships between elements will become much more important later when you start styling your HTML with CSS and adding behavior with JavaScript. For now, however, it is just important to know the distinction between how elements are related and the terminology used to describe their relationships. + +# --question-- + +## --text-- + +What relationship do two elements have if they are at the same level of nesting? + +## --answers-- + +The elements are each other's parents. + +--- + +The elements are each other's children. + +--- + +The elements are siblings. + +## --video-solution-- + +3 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-f.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-f.md new file mode 100644 index 00000000000000..2ace3f4e36d435 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-f.md @@ -0,0 +1,67 @@ +--- +id: 637f4e8072c65bc8e73dfe2c +videoId: gW6cBZLUk6M +title: Working With Text Question F +challengeType: 15 +dashedName: working-with-text-question-f +--- + +# --description-- + +You may have noticed that in all the examples in this lesson you indent any elements that are within other elements. This is known as nesting elements. + +When you nest elements within other elements, you create a parent and child relationship between them. The nested elements are the children and the element they are nested within is the parent. + +In the following example, the body element is the parent and the paragraph is the child: + +```html + + + + +

                                          Lorem ipsum dolor sit amet.

                                          + + +``` + +Just as in human relationships, HTML parent elements can have many children. Elements at the same level of nesting are considered to be siblings. + +For example, the two paragraphs in the following code are siblings, since they are both children of the body tag and are at the same level of nesting as each other: + +```html + + + + +

                                          Lorem ipsum dolor sit amet.

                                          +

                                          Ut enim ad minim veniam.

                                          + + +``` + +You use indentation to make the level of nesting clear and readable for yourselves and other developers who will work with your HTML in the future. It is recommended to indent any child elements by two spaces. + +The parent, child, and sibling relationships between elements will become much more important later when you start styling your HTML with CSS and adding behavior with JavaScript. For now, however, it is just important to know the distinction between how elements are related and the terminology used to describe their relationships. + +# --question-- + +## --text-- + +What relationship does an element have with any nested element within it? + +## --answers-- + +The element within the other element is called the parent element. + +--- + +The element within the other element is called the child element. + +--- + +The element within the other element is called the sibling element. + + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-g.md b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-g.md new file mode 100644 index 00000000000000..fe83f0ef0624e3 --- /dev/null +++ b/curriculum/challenges/arabic/10-coding-interview-prep/the-odin-project/working-with-text-question-g.md @@ -0,0 +1,49 @@ +--- +id: 637f4e8772c65bc8e73dfe2d +videoId: gW6cBZLUk6M +title: Working With Text Question G +challengeType: 15 +dashedName: working-with-text-question-g +--- + +# --description-- + +HTML comments are not visible to the browser; they allow us to comment on your code so that other developers or your future selves can read them and get some context about something that might not be clear in the code. + +Writing an HTML comment is simple: You just enclose the comment with ``tags. For example: + +```html +

                                          View the html to see the hidden comments

                                          + + + +

                                          Some paragraph text

                                          + + +``` + +# --question-- + +## --assignment-- + +To get some practice working with text in HTML, create a plain blog article page which uses different headings, uses paragraphs, and has some text in the paragraphs bolded and italicized. You can use [Lorem Ipsum](https://loremipsum.io) to generate dummy text, in place of real text as you build your sites. + +## --text-- + +How do you create HTML comments? + +## --answers-- + +`/* This is an HTML comment */` + +--- + +`` + +--- + +`<-- This is an HTML comment --!>` + +## --video-solution-- + +2 diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-personal-portfolio-webpage-project/build-a-personal-portfolio-webpage.md b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-personal-portfolio-webpage-project/build-a-personal-portfolio-webpage.md index b851538a51dffb..dee380a33ced93 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-personal-portfolio-webpage-project/build-a-personal-portfolio-webpage.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-personal-portfolio-webpage-project/build-a-personal-portfolio-webpage.md @@ -1,6 +1,6 @@ --- id: bd7158d8c242eddfaeb5bd13 -title: ابن معرضا لأعمالك الخاصة +title: أنشئ معرضا لأعمالك الخاصة challengeType: 14 forumTopicId: 301143 dashedName: build-a-personal-portfolio-webpage diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-product-landing-page-project/build-a-product-landing-page.md b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-product-landing-page-project/build-a-product-landing-page.md index 0dbd9f3ead7f9b..9d0477c5bd01ea 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-product-landing-page-project/build-a-product-landing-page.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-product-landing-page-project/build-a-product-landing-page.md @@ -1,6 +1,6 @@ --- id: 587d78af367417b2b2512b04 -title: بناء صفحة هبوط لمنتج +title: أنشئ صفحة لعرض لمنتج challengeType: 14 forumTopicId: 301144 dashedName: build-a-product-landing-page diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md index bf05e94470b8ec..72ec9a0ed1ceac 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-survey-form-project/build-a-survey-form.md @@ -1,6 +1,6 @@ --- id: 587d78af367417b2b2512b03 -title: بناء نموذج استطلاع رأي +title: أنشئ نموذج استطلاع رأي challengeType: 14 forumTopicId: 301145 dashedName: build-a-survey-form @@ -8,7 +8,7 @@ dashedName: build-a-survey-form # --description-- -**Objective:** كم ببناء تطبيق يشبه وظيفيا إلي https://survey-form.freecodecamp.rocks +**Objective:** أنشئ تطبيق يشبه وظيفيا إلي https://survey-form.freecodecamp.rocks **المطلبيات:** @@ -259,7 +259,7 @@ const els = document.querySelectorAll('#dropdown option:not([disabled])') assert(els.length >= 2) ``` -`#dropdown` الخاص بك يجب أن يكون تابعا لـ `#survey-form`. +يجب أن يكون `#dropdown` الخاص بك فرع من `#survey-form`. ```js const el = document.querySelector('#survey-form #dropdown') diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-technical-documentation-page-project/build-a-technical-documentation-page.md b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-technical-documentation-page-project/build-a-technical-documentation-page.md index da785d6f332f35..b5617bd6a758cd 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-technical-documentation-page-project/build-a-technical-documentation-page.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-technical-documentation-page-project/build-a-technical-documentation-page.md @@ -1,6 +1,6 @@ --- id: 587d78b0367417b2b2512b05 -title: مشروع بناء صفحة التوثيق التقني +title: أنشئ صفحة التوثيق التقنية challengeType: 14 forumTopicId: 301146 dashedName: build-a-technical-documentation-page @@ -8,11 +8,11 @@ dashedName: build-a-technical-documentation-page # --description-- -**Objective:** قم ببناء تطبيق يشبه وظيفيا إلى https://technical-documentation-page.freecodecamp.rocks +**Objective:** أنشئ تطبيق يشبه وظيفيا إلى https://technical-documentation-page.freecodecamp.rocks **المتطلبات:** -1. يمكنك مشاهدة عنصر `main` مع `id="main-doc"`، والذي يحتوي على المحتوى الرئيسي للصفحة (الوثائق التقنية) +1. يمكنك مشاهدة عنصر `main` مع `id="main-doc"`، الذي يحتوي على المحتوى الرئيسي للصفحة (الوثائق التقنية) 1. ضمن عنصر `#main-doc` ، يمكنك رؤية عدة عناصر `section`، كل منها مع class بقيمة `main-section`. وينبغي أن يكون هناك خمسة على الأقل 1. العنصر الأول في كل `.main-section` يجب أن يكون عنصر `header`، والذي يحتوي على نص يصف موضوع ذلك القسم. 1. كل عنصر من عناصر `section` مع class بقيمة `main-section` يجب أن يكون لديه `id` يتوافق مع نص كل `header` موجود داخله. يجب استبدال أي مسافات بتسطير سفلي (underscore) (على سبيل المثال القسم الذي يحتوي على header "JavaScript and Java" يجب أن يكون لديه `id="JavaScript_and_Java"`) @@ -203,7 +203,7 @@ const remainder = headerText.filter(str => linkText.indexOf(str) === -1) assert(headerText.length > 0 && headerText.length > 0 && remainder.length === 0) ``` -يجب أن يكون لكل `.nav-link` سمة `href` التي تربط مع `.main-section` (على سبيل المثال ، إذا نقرت على العنصر `.nav-link` الذي يحتوي على النص "Hello world" ، تنتقل الصفحة إلى عنصر `section` بهذا الـ id). +يجب أن يكون لكل `.nav-link` سمة `href` التي تربط مع `.main-section` (على سبيل المثال، إذا نقرت على العنصر `.nav-link` الذي يحتوي على النص "Hello world"، تنتقل الصفحة إلى عنصر `section` بهذا المعرف (id)). ```js const hrefValues = Array.from(document.querySelectorAll('.nav-link')).map(el => el.getAttribute('href')) diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-tribute-page-project/build-a-tribute-page.md b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-tribute-page-project/build-a-tribute-page.md index 4c99b97f034e3a..7fdd0c7fad65fe 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-tribute-page-project/build-a-tribute-page.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/build-a-tribute-page-project/build-a-tribute-page.md @@ -1,6 +1,6 @@ --- id: bd7158d8c442eddfaeb5bd18 -title: بناء مشروع صفحة الثناء +title: أنشئ مشروع صفحة الثناء challengeType: 14 forumTopicId: 301147 dashedName: build-a-tribute-page @@ -8,12 +8,12 @@ dashedName: build-a-tribute-page # --description-- -**Objective:** قم ببناء تطبيق يشبه وظيفيا إلى https://tribute-page.freecodecamp.rocks +**Objective:** ابني تطبيق يشابه وظيفيا إلي https://tribute-page.freecodecamp.rocks **المتطلبات:** -1. يجب أن يكون لصفحة الثناء الخاصة بك عنصر `main` مع `id` بقيمة `main`، والذي يحتوي على جميع العناصر الأخرى -1. يجب أن ترى عنصرا مع `id` بقيمة `title`، الذي يحتوي على string (اي نص) ،يصف موضوع صفحة الثناء (مثل "الدكتور نورمان بورلاوغ") +1. يجب أن يكون لصفحتك الثناء عنصر `main` مع `id` بقيمة `main`، الذي يحتوي على جميع العناصر الأخرى +1. يجب أن ترى عنصرا مع `id` بقيمة `title`، الذي يحتوي على مقطع نصي (string)، يصف موضوع صفحة الثناء (مثل "الدكتور نورمان بورلاوغ") 1. يجب أن ترى إما عنصر `figure` أو `div` مع `id` بقيمة `img-div` 1. داخل عنصر `#img-div` يمكنك رؤية عنصر `img` مع `id="image"` 1. داخل عنصر `#img-div` ، يجب أن ترى عنصرا مع `id="img-caption"` يحتوي على محتوى نصي يصف الصورة المعروضة في `#img-div` diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61329b210dac0b08047fd6ab.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61329b210dac0b08047fd6ab.md index f7f79efd9f24f3..f8d918d56f0e7c 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61329b210dac0b08047fd6ab.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/61329b210dac0b08047fd6ab.md @@ -7,7 +7,7 @@ dashedName: step-3 # --description-- -بالمتابعة مع عناصر `meta`، يخبر تعريف `viewport` المتصفح كيفية عرض الصفحة. بما في ذلك تحسين الوصول البصري (visual accessibility) على المحمول، وتحسين _SEO_ كفاءه محرك البحث (seach engine optimization). +بالمتابعة مع عناصر `meta`، يخبر تعريف `viewport` المتصفح كيفية عرض الصفحة. بما في ذلك تسهيل البصري (visual accessibility) على المحمول، وتحسين كفاءه محرك البحث _SEO_ أو (seach engine optimization). قم بإضافة تعريف `viewport` مع سمة `content` مع تفاصيل `width` و `initial-scale` للصفحة. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133d11ef548f51f876149e3.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133d11ef548f51f876149e3.md index 2ef7947512dc97..856a6946c04975 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133d11ef548f51f876149e3.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6133d11ef548f51f876149e3.md @@ -7,7 +7,7 @@ dashedName: step-6 # --description-- -التنقل (Navigation) هو جزء أساسي من إمكانية الوصول (accessibility)، ويعتمد قارئ الشاشة (screen readers) عليك لتوفير بنية الصفحة الخاصة بك. ويتم ذلك باستخدام عناصر semantic HTML. +التنقل (Navigation) هو جزء أساسي من تسهيل المنال (accessibility)، ويعتمد قارئ الشاشة (screen readers) عليك لتوفير بنية صفحتك. ويتم ذلك باستخدام عناصر semantic HTML. أضف `header` و `main` إلى صفحتك. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fabd6f75610664e908fd.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fabd6f75610664e908fd.md index 9a3b8519bf0d93..0581a978dd732f 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fabd6f75610664e908fd.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fabd6f75610664e908fd.md @@ -9,7 +9,7 @@ dashedName: step-14 بما أن هذا اختبار، ستحتاج إلى نموذج (form) للمستخدمين لتقديم إجابات. يمكنك فصل المحتوى بشكل لغوي (semantically) داخل النموذج (form) باستخدام عناصر `section`. -ضمن عنصر `main`، أنشئ نموذج (form) مع ثلاث عناصر `section` متداخلة. بعد ذلك، قم بإرسال النموذج (submit form) إلى `https://freecodecamp.org/practice-project/accessibility-quiz`، باستخدام الطريقة الصحيحة. +ضمن عنصر `main`، أنشئ نموذج (form) مع ثلاث عناصر `section` متداخلة. بعد ذلك، أجعل النموذج (submit form) يرسل إلى `https://freecodecamp.org/practice-project/accessibility-quiz`، باستخدام الطريقة الصحيحة. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fed65b61320743da5894.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fed65b61320743da5894.md index f2fc524bf70116..48138bfc51295c 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fed65b61320743da5894.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6141fed65b61320743da5894.md @@ -7,7 +7,7 @@ dashedName: step-15 # --description-- -لزيادة إمكانية الوصول إلى الصفحة، يمكن استخدام سمة `role` للإشارة إلى الغرض وراء عنصر في الصفحة للتكنولوجيات المساعدة. سمة `role` هي جزء من _Web Accessibility Initiative_ او (WAI)، وتقبل قيم الإعداد المسبق. +لزيادة تسهيل منال (accessibility) في الصفحة، يمكن استخدام سمة `role` للإشارة إلى الغرض وراء عنصر في الصفحة للتكنولوجيات المساعدة. سمة `role` هي جزء من _Web Accessibility Initiative_ أو (WAI)، وتقبل قيم الإعداد المسبق. اعطي كل عنصر من عناصر `section` الـ role بقيمة `region`. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614202874ca576084fca625f.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614202874ca576084fca625f.md index 14a22bb7136df7..5ea067901bbb88 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614202874ca576084fca625f.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614202874ca576084fca625f.md @@ -7,9 +7,9 @@ dashedName: step-16 # --description-- -يتطلب كل role من `region` تسمية مرئية، والتي يجب الإشارة إليها بواسطة السمة `aria-labelledby`. +كل دور `region` يتطلب وصف، مما يساعد مستخدمي قارئ الشاشة على فهم غرضها. إحدى الطرق لإضافة وصف هي أن تضيف عنصر العنوان داخل المنطقة ثم الإشارة إليه مع السمة `aria-labelledby`. -إلى عناصر `section` ، أعطي سمات `aria-labelledby` التالية: +أضف `aria-labelledby` التالي إلى عناصر `section`: - `student-info` - `html-questions` diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614206033d366c090ca7dd42.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614206033d366c090ca7dd42.md index 38bca467f6f5d8..b8f7422ccbaa0e 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614206033d366c090ca7dd42.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614206033d366c090ca7dd42.md @@ -7,7 +7,7 @@ dashedName: step-17 # --description-- -يؤدي Typeface دورا هاما في إمكانية الوصول إلى الصفحة. بعض الخطوط أسهل من غيرها، وهذا صحيح بشكل خاص على الشاشات ذات الدقة المنخفضة (low-resolution). +يؤدي Typeface دورا هاما في تسهيل المنال (accessibility) في الصفحة. بعض الخطوط أسهل من غيرها، وهذا صحيح بشكل خاص على الشاشات ذات الدقة المنخفضة (low-resolution). قم بتغيير الخط لعناصر `h1` و `h2` إلى `Verdana`، واستخدم خط ويب آمنًا آخر في مجموعة sans-serif كخط احتياطي. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143920c8eafb00b735746ce.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143920c8eafb00b735746ce.md index 4c76d78f016eec..223e908386dfdd 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143920c8eafb00b735746ce.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6143920c8eafb00b735746ce.md @@ -7,7 +7,7 @@ dashedName: step-22 # --description-- -مع أنّ أنك أضفت `placeholder` إلى العنصر `input` الأول في الدرس السابق، هذه الممارسة ليست في الواقع أفضل ممارسة لتيسير الوصول؛ في كثير من الأحيان، يخلط المستخدمون بين النص النائب (placeholder text) وقيمة الإدخال الفعلية - و يعتقدون أن هناك قيمة فعلًا في حقل الإدخال. +مع أنّ أنك أضفت `placeholder` إلى العنصر `input` الأول في الدرس السابق، هذه الممارسة ليست في الواقع أفضل ممارسة لتسهيل المنال (accessibility)؛ في كثير من الأحيان، يخلط المستخدمون بين النص النائب (placeholder text) وقيمة الإدخال الفعلية - و يعتقدون أن هناك قيمة فعلًا في حقل الإدخال. أزل placeholder text من عنصر `input` الأول، معتمدا على `label` باعتبارها أفضل الممارسات. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f685797bd30df9784e8c.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f685797bd30df9784e8c.md index 6efdb63b87e498..a3c5851e9fc95f 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f685797bd30df9784e8c.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6145f685797bd30df9784e8c.md @@ -7,7 +7,7 @@ dashedName: step-41 # --description-- -لا تنس إعطاء `form` زر submit. +Do not forget to give your `form` a submit button with the text `Send`. # --hints-- @@ -17,25 +17,25 @@ dashedName: step-41 assert.exists(document.querySelector('button') || document.querySelector('main > input') || document.querySelector('form > input')); ``` -يجب عليك وضع submit ضمن عنصر `form`. +You should place the submit button within the `form` element. ```js assert.exists(document.querySelector('form > button') || document.querySelector('form > input')); ``` -يجب عليك وضع submitt بعد آخر عنصر `section`. +You should place the submit button after the last `section` element. ```js assert.exists(document.querySelector('section:last-of-type + button') || document.querySelector('section:last-of-type + input')); ``` -يجب عليك إعطاء submit سمة `type` بقيمة `submit`. +You should give the submit button a `type` of `submit`. ```js assert.exists(document.querySelector('button[type="submit"]') || document.querySelector('form > input[type="submit"]')); ``` -يجب أن يعرض زر الإرسال (submit) نص `Send`. +The submit button should display the text `Send`. ```js assert.equal(document.querySelector('button[type="submit"]')?.textContent ?? document.querySelector('input[type="submit"]')?.value, 'Send'); diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614796cb8086be482d60e0ac.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614796cb8086be482d60e0ac.md index e31b1c4094de51..bb7f0f666e29d8 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614796cb8086be482d60e0ac.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614796cb8086be482d60e0ac.md @@ -7,7 +7,7 @@ dashedName: step-46 # --description-- -وفيما يتعلق بموضوع إمكانية الوصول البصري (visual accessibility,)، فإن التباين (contrast) بين العناصر عامل رئيسي. فعلى سبيل المثال، ينبغي أن يكون التباين بين النص وخلفية العنوان 4.5:1 على الأقل. +وفيما يتعلق بموضوع تسهيل البصري (visual accessibility)، فإن التباين (contrast) بين العناصر عامل رئيسي. فعلى سبيل المثال، ينبغي أن يكون التباين بين النص وخلفية العنوان 4.5:1 على الأقل. غير لون الخط (font color) لجميع عناصر الروابط (anchor elements) داخل عناصر list إلى شيء به نسبة تباين (contrast ratio) لا تقل عن 7:1. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6148da157cc0bd0d06df5c0a.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6148da157cc0bd0d06df5c0a.md index bf6502a65adcea..50fed0f3166fca 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6148da157cc0bd0d06df5c0a.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6148da157cc0bd0d06df5c0a.md @@ -7,7 +7,7 @@ dashedName: step-57 # --description-- -لمحاذاة مربعات `input` مع بعضها البعض، قم بتعيين خاصية `display` إلى `inline-block` لجميع عناصر `input` و `label` داخل عناصر `.info`. +لمواءمة صناديق الإدخال مع بعضها البعض، أنشئ مجموعة قواعد جديدة تستهدف جميع عناصر `input` و `label` داخل `.info` وتعيين خاصية `display` إلى `inline-block`. أيضًا، بمحاذي (align) نص عنصر `label` إلى اليمين. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6148e5aeb102e3142de026a2.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6148e5aeb102e3142de026a2.md index 00f2af7474ac13..71389b540b4424 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6148e5aeb102e3142de026a2.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/6148e5aeb102e3142de026a2.md @@ -7,7 +7,7 @@ dashedName: step-68 # --description-- -أخيرًا ، يمكن تحسين إمكانية استيعاب التنقل (navigation accessibility) عن طريق توفير اختصارات لوحة المفاتيح. +أخيرًا، يمكن تسهيل التنقل (navigation accessibility) عن طريق توفير اختصارات للوحة المفاتيح. السمة `accesskey` تقبل قائمة مفصولة بمسافة من مفاتيح الوصول (access keys). على سبيل المثال: @@ -19,7 +19,7 @@ dashedName: step-68 _ملاحظة: لا ينصح دائما باستخدام مفاتيح الوصول، ولكن يمكن أن تكون مفيدة_ -أحسنت صنعا. لقد أكملت مشروع تدريب _اختبار إمكانية الوصول_. +أحسنت صنعا. لقد أكملت مشروع تدريب _ اختبار تسهيل المنال (Accessibility Quiz)_. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614ccc21ea91ef1736b9b578.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614ccc21ea91ef1736b9b578.md index 26232f417ff70a..5a1a835458c76a 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614ccc21ea91ef1736b9b578.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-accessibility-by-building-a-quiz/614ccc21ea91ef1736b9b578.md @@ -7,9 +7,9 @@ dashedName: step-1 # --description-- -مرحبا بكم في الجزء الأول من اختبار إمكانية الوصول (Accessibility Quiz). بما انك تسعي أن تكون متمرسًا في HTML و CSS، فقد بدأنا باستخدام النموذج الأساسي. +مرحبا بكم في الجزء الأول من اختبار تسهيل المنال (Accessibility Quiz). بما انك تسعي أن تكون متمرسًا في HTML و CSS، فقد بدأنا باستخدام النموذج الأساسي. -ابدأ رحلة الوصول هذه، عن طريق توفير سمة (attribute) تسمي `lang` إلى `html` الخاص بك. هذا سيساعد قارئ الشاشة (screen readers) على تحديد لغة الصفحة. +ابدأ رحلة التسهيل، عن طريق توفير سمة (attribute) تسمي `lang` إلى `html` الخاص بك. هذا سيساعد قارئ الشاشة (screen readers) على تحديد لغة الصفحة. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f33071498eb2472b87ddee4.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f33071498eb2472b87ddee4.md index 6b6a15ebbf5cc9..0d95ad824674de 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f33071498eb2472b87ddee4.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f33071498eb2472b87ddee4.md @@ -9,7 +9,7 @@ dashedName: step-1 كما تعلمت في الخطوات القليلة الأخيرة من Cat App Photo، هناك بنية أساسية مطلوبة لبدء بناء صفحة الويب الخاصة بك. -قك بإضافة الـ tag الآتي ``، وعنصر `html` مع سمة `lang` بقيمة `en`. +أضف العلامة (tag) الآتي ``، وعنصر `html` مع سمة (attribute) تسمى `lang` بقيمة `en`. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f3c866d0fc037f7311b4ac8.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f3c866d0fc037f7311b4ac8.md index 5a95269381f2da..2016471c741604 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f3c866d0fc037f7311b4ac8.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f3c866d0fc037f7311b4ac8.md @@ -7,18 +7,18 @@ dashedName: step-38 # --description-- -هذا اقرب، لكن الثمن لم يبقى على اليمين. هذا لأن عناصر `inline-block` تأخذ فقط عرض محتوياتها. لنشرها، أضف خاصية `width` إلى منتقيات class تسمي `flavor` و `price` التي تبلغ قيمتها `50%` لكل منهم. +هذا اقرب، لكن الثمن لم يبقى على اليمين. هذا لأن عناصر `inline-block` تأخذ فقط عرض (width) محتوياتها. لنشرها، أضف خاصية (property) تسمى `width` إلى منتقيات فئة (class selectors) تسمي `flavor` و `price` التي تبلغ قيمتها `50%` لكل منهم. # --hints-- -يجب عليك تعيين خاصية `width` إلى `50%` في منتقي `.flavor` الخاص بك. +يجب عليك تعيين خاصية `width` بقيمة `50%` في منتقيك `.flavor`. ```js const flavorWidth = new __helpers.CSSHelp(document).getStyle('.flavor')?.getPropertyValue('width'); assert(flavorWidth === '50%'); ``` -يجب عليك تعيين خاصية `width` إلى `50%` في منتقي `.price` الخاص بك. +يجب عليك تعيين خاصية `width` بقيمة `50%` في منتقيك `.price`. ```js const priceWidth = new __helpers.CSSHelp(document).getStyle('.price')?.getPropertyValue('width'); diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f46e36e745ead58487aabf2.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f46e36e745ead58487aabf2.md index ff7ca706f3ffb2..fc7b2861c08135 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f46e36e745ead58487aabf2.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f46e36e745ead58487aabf2.md @@ -9,7 +9,7 @@ dashedName: step-86 الآن تبدو المسافة العلوية جيدة. المساحة أسفل العنوان في أسفل القائمة أكبر قليلا من المساحة في الجزء العلوي من القائمة وعنصر `h1`. -لتقليل مساحة margin الافتراضية تحت عنوان عنصر `p`، قم بإنشاء class selector يسمى `address` واستخدم القيمة `5px` للخاصية `margin-bottom`. +لتقليل مساحة margin الافتراضية تحت عنوان عنصر `p`، أنشئ منتقي الفئة (class selector) تسمى `address` واستخدم القيمة `5px` للخاصية `margin-bottom`. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f7b88d37b1f98386f04edc0.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f7b88d37b1f98386f04edc0.md index 91066c9cdc7d5a..f16b8ca5dd3f49 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f7b88d37b1f98386f04edc0.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-basic-css-by-building-a-cafe-menu/5f7b88d37b1f98386f04edc0.md @@ -9,7 +9,7 @@ dashedName: step-51 شيء ما لا يبدو صحيحا. لقد أضفت قيمة سمة `class` الصحيحة إلى عنصر `p` مع `Donut` كنص له، لكنك لم تحدد منتقي (selector) له. -لما كان منتقي class مسمى `flavor` لديه فعلًا الخصائص التي تريدها، أضف class باسم `dessert` إليه. +The CSS rule for the `flavor` class already sets the properties you want. Add the `dessert` class as an additional selector for this CSS rule. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61695c4aad56f95497c19583.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61695c4aad56f95497c19583.md index f5b2bd714aed56..328b99cc0d8c3f 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61695c4aad56f95497c19583.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61695c4aad56f95497c19583.md @@ -7,7 +7,10 @@ dashedName: step-3 # --description-- -تذكر أن عنصر `title` يعطي محركات البحث معلومات إضافية عن الصفحة. كما أنه يخبر المتصفحات ما هو النص الذي سيتم عرضه في شريط العنوان عندما تكون الصفحة مفتوحة، وعلى علامة التبويب للصفحة. +تذكر أن عنصر `title` يعطي محركات البحث معلومات إضافية عن الصفحة. It also displays the content of that `title` element in two more ways: + +* in the title bar when the page is open +* in the browser tab for the page when you hover on it. Even if that tab is not active, once you hover on the tab, the `title` text is displayed. داخل عنصر `head`، قم بدمج عنصر `title` مع النص `Colored Markers`. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616965351e74d4689eb6de30.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616965351e74d4689eb6de30.md index 2350e4c29bd8e1..e8d19089cf2f52 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616965351e74d4689eb6de30.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616965351e74d4689eb6de30.md @@ -7,24 +7,26 @@ dashedName: step-5 # --description-- -ضف عنصر `meta` ذاتي الأغلاق داخل `head`. أعطيه سمة `name` بقيمة `viewport` و سمة `content` بقيمة `width=device-width, initial-scale=1.0` حتى تطابق مظهر صحفتك في كل الأجهزة. +You can have multiple self-closing `meta` elements on a web page. What distinguishes one `meta` element from the other is the attribute. You should add a new meta element for each attribute you want to specify. + +Add another self-closing `meta` element within the `head`. Give it a `name` attribute set to `viewport` and a `content` attribute set to `width=device-width, initial-scale=1.0` so your page looks the same on all devices. # --hints-- -يجب أن يكون لديك عنصران `meta`. +You should have two `meta` elements. ```js const meta = document.querySelectorAll('meta'); assert(meta?.length === 2); ``` -يجب أن يكون عنصر `meta` مغلق ذاتيا (self-closing). +Your new `meta` element should be a self-closing element. ```js assert(code.match(/<\/meta>/i) === null); ``` -يجب أن يحتوي عنصر `meta` الجديد على السمة `name` بقيمة `viewport`، و السمة `content` بقيمة `width=device-width, initial-scale=1.0`. +Your new `meta` element should have a `name` attribute set to `viewport`, and a `content` attribute set to `width=device-width, initial-scale=1.0`. ```js const meta = [...document.querySelectorAll('meta')]; diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61696ef7ac756c829f9e4048.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61696ef7ac756c829f9e4048.md index 0cc3f2701ce0e7..5958ab19c38146 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61696ef7ac756c829f9e4048.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61696ef7ac756c829f9e4048.md @@ -9,7 +9,7 @@ dashedName: step-7 في هذا المشروع ستعمل مع ملف CSS خارجي لتصميم الصفحة. لقد قمنا بالفعل بإنشاء ملف `styles.css` لك. ولكن قبل أن تتمكن من استخدامه، ستحتاج إلى ربطه بالصفحة. -قم بدمج عنصر `link` داخل `head`. اعطيها سمة `rel` بقيمة `stylesheet` و `href` بقيمة `styles.css`. +Nest a `link` element within the `head` element. اعطيها سمة `rel` بقيمة `stylesheet` و `href` بقيمة `styles.css`. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d3a67ccf800ad94ec89ae.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d3a67ccf800ad94ec89ae.md index b39be3af236db4..2455e5adafb92b 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d3a67ccf800ad94ec89ae.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d3a67ccf800ad94ec89ae.md @@ -9,7 +9,7 @@ dashedName: step-9 الآن ستضيف بعض العناصر التي ستصممها في نهاية المطاف لتكون لون markers. -أولا، داخل `body`، أضف عنصر `div` وقم بتعيين سمة `class` إلى `container`. تأكد من أن عنصر `div` تحت عنصر `h1`. +First, within the `body` element, add a `div` element and set its `class` attribute to `container`. تأكد من أن عنصر `div` تحت عنصر `h1`. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d47bc9eedc4bc7f621bec.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d47bc9eedc4bc7f621bec.md index f70dcf9cb00a38..0b44696ec24edb 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d47bc9eedc4bc7f621bec.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d47bc9eedc4bc7f621bec.md @@ -7,7 +7,7 @@ dashedName: step-10 # --description-- -بعد ذلك، ضمن عنصر `div`، أضف عنصر `div` آخر وأعطيه class من `marker`. +Next, within the `div` element, add another `div` element and give it a class of `marker`. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d50b93ba424d6282c99cf.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d50b93ba424d6282c99cf.md index 47ca0439f7993d..c4ce04cdc7ab73 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d50b93ba424d6282c99cf.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/616d50b93ba424d6282c99cf.md @@ -7,7 +7,7 @@ dashedName: step-12 # --description-- -تم تطبيق لون الخلفية، ولكن لما كان عنصر `div` من marker فارغ، فليس لديه أي ارتفاع افتراضي. +The background color was applied, but since the marker `div` element has no content in it, it doesn't have any height by default. في قاعدتك من CSS المسمى `.marker`، عيّن خصائص `height` إلى `25px` و `width` إلى `200px` diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61764c602bee6974e7790f35.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61764c602bee6974e7790f35.md index 68369bffdf3948..0a3dd275ad3f92 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61764c602bee6974e7790f35.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61764c602bee6974e7790f35.md @@ -13,19 +13,21 @@ dashedName: step-16
                                          ``` -يجب عليك إضافة class يسمى `one` إلى العنصر `div` الأول ألى marker. +If you add multiple classes to an HTML element, the styles of the first classes you list may be overridden by later classes. + +To begin, add the class `one` to the first marker `div` element. # --hints-- -يجب عليك إضافة class يسمى `one` إلى العنصر `div` الأول ألى marker. +You should add the class `one` to the first marker `div` element. ```js const containerFirstChild = [...document.querySelector('.container')?.children][0]; assert(containerFirstChild?.classList?.contains('one')); ``` -يجب أن يحتوي عنصر الأول `div` من marker على class تسمى `marker` و `one`. +Your first marker `div` should have the classes `marker` and `one`. ```js const containerFirstChild = [...document.querySelector('.container')?.children][0]; diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61764fdda535587e1fefb3aa.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61764fdda535587e1fefb3aa.md index 5485d9fffac854..57d4d17406ddce 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61764fdda535587e1fefb3aa.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61764fdda535587e1fefb3aa.md @@ -7,7 +7,7 @@ dashedName: step-19 # --description-- -أضف class يسمي `two` إلى marker الـ `div` الثاني، و class الـ `three` إلى marker الـ `div` الثالث. +Add the class `two` to the second marker `div`, and add the class `three` to the third marker `div`. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/617bd6ec666b1da2587e4e37.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/617bd6ec666b1da2587e4e37.md index b386bcf53c9e8a..a3b585a08b992e 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/617bd6ec666b1da2587e4e37.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/617bd6ec666b1da2587e4e37.md @@ -9,11 +9,11 @@ dashedName: step-34 وهناك ثلاثة ألوان أخرى ثلاثية: chartreuse green (الأخضر + الأصفر)، azure (الأزرق + cyan)، و rose (الأحمر + magenta). -لإنشاء chartreuse green، قم بتحديث دالة `rgb` في قاعدة `.one` بحيث يكون الأحمر بقيمة `127`، و قيمة الأخضر بالحد الأقصى. +To create chartreuse green, update the `rgb` function in the `.one` CSS rule so that red is at `127`, and set green to the max value. -لإنشاء azure، قم بتحديث دالة `rgb` في قاعدة `.two` بحيث يكون الاخضر بقيمة `127`، و قيمة الازرق بالحد الأقصى. +For azure, update the `rgb` function in the `.two` CSS rule so that green is at `127` and blue is at the max value. -ولإنشاء rose، قم بتحديث دالة `rgb` في قاعدة `.three` بحيث يكون الازرق بقيمة `127`، و قيمة الاحمر بالحد الأقصى. +And for rose, which is sometimes called bright pink, update the `rgb` function in the `.three` CSS rule so that blue is at `127` and red is at the max value. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a00ed1ca871a2b3aca0cb.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a00ed1ca871a2b3aca0cb.md index c755fcb889e7c6..016f9f14a67af5 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a00ed1ca871a2b3aca0cb.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a00ed1ca871a2b3aca0cb.md @@ -9,7 +9,7 @@ dashedName: step-35 الآن بعد أن مررت بجميع الألوان الابتدائية والثانوية والثلاثية على عجلة الألوان، سيكون من الأسهل فهم مفاهيم نظرية الألوان الأخرى وكيف تؤثر على التصميم. -أولا، في القواعد `.one`و `.two`و `.three`، ضبط القيم في الدالة `rgb` بحيث يتم تعيين `background-color` لكل عنصر إلى اسود نقي. تذكر أن دالة `rgb` تستخدم نموذج اللون المضاف (additive color model)، حيث تبدأ الألوان باللون الأسود وتتغير كقيم اللون الأحمر والأخضر والأزرق. +First, in the CSS rules `.one`, `.two`, and `.three`, adjust the values in the `rgb` function so that the `background-color` of each element is set to pure black. تذكر أن دالة `rgb` تستخدم نموذج اللون المضاف (additive color model)، حيث تبدأ الألوان باللون الأسود وتتغير كقيم اللون الأحمر والأخضر والأزرق. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a0b2befb143baefab632b.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a0b2befb143baefab632b.md index c1f5bd285a8f77..c12f8148b0382f 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a0b2befb143baefab632b.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a0b2befb143baefab632b.md @@ -11,7 +11,7 @@ dashedName: step-37 من الأفضل اختيار لون واحد باعتباره اللون السائد، واستخدام لونه التكميلي كلكنة للفت الانتباه إلى محتوى معين على الصفحة. -أولاً، في قاعدة `h1`، استخدم الدالة `rgb` لتعيين لون الخلفية الخاص بها إلى cyan. +First, in the `h1` rule, use the `rgb` function to set its `background-color` to cyan. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a1275e873dcc803c2d1aa.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a1275e873dcc803c2d1aa.md index 50687262fb870d..e817cf0ed3b46d 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a1275e873dcc803c2d1aa.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a1275e873dcc803c2d1aa.md @@ -7,7 +7,7 @@ dashedName: step-38 # --description-- -بعد ذلك، في قاعدة `.one` ، استخدم الدالة `rgb` لتعيين `background-color` إلى الأسود. وفي قاعدة `.two` ، استخدم الدالة `rgb` لتعيين `background-color` إلى اللون الأحمر. +Next, in the `.one` CSS rule, use the `rgb` function to set the `background-color` to black. And in the `.two` CSS rule, use the `rgb` function to set the `background-color` to red. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a132676346ac9f7fd59dd.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a132676346ac9f7fd59dd.md index 4051c4281c07d3..6dc6377a87c206 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a132676346ac9f7fd59dd.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a132676346ac9f7fd59dd.md @@ -11,7 +11,7 @@ dashedName: step-39 هناك العديد من مجموعات الألوان الهامة الأخرى خارج الألوان التكميلية (complementary colors)، لكنك ستتعلم هذه في وقت لاحق. -في الوقت الحالي، استخدم دالة `rgb` في قاعدة `.two` لتعيين `background-color` إلى أسود. +For now, use the `rgb` function in the `.two` CSS rule to set the `background-color` to black. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a16873520a8d088ffdf44.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a16873520a8d088ffdf44.md index b8bb853c31c59b..e1dffddc945022 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a16873520a8d088ffdf44.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a16873520a8d088ffdf44.md @@ -7,7 +7,7 @@ dashedName: step-40 # --description-- -وفي قاعدة `h1` ، قم بإزالة خاصية `background-color` والقيمة للعودة إلى اللون الأبيض الافتراضي. +And in the `h1` CSS rule, remove the `background-color` property and value to go back to the default white color. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b72a0db211f1c29afb906.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b72a0db211f1c29afb906.md index a506de1e7f5221..6fe8330e5c54e5 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b72a0db211f1c29afb906.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b72a0db211f1c29afb906.md @@ -7,7 +7,7 @@ dashedName: step-42 # --description-- -قم بتحديثclass selector الـ `.one` لاستهداف class الـ `red` الجديد. +Update the `.one` CSS rule to target the new `red` class. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7396e57b771f903be90d.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7396e57b771f903be90d.md index 33f98a1548ed5b..cad8ea4a1a9430 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7396e57b771f903be90d.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7396e57b771f903be90d.md @@ -7,7 +7,7 @@ dashedName: step-43 # --description-- -و قم بتحديث دالة `rgb` في قاعدة `.red` بحيث تكون القيمة الحمراء عند الحد الأقصى. +And update the `rgb` function in the `.red` CSS rule so that the red value is at the max. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b74fa777a2b2473c94f82.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b74fa777a2b2473c94f82.md index 75b1846b3bde2d..bbb7e259e788f0 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b74fa777a2b2473c94f82.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b74fa777a2b2473c94f82.md @@ -7,7 +7,7 @@ dashedName: step-45 # --description-- -قم بتحديث CSS class selector الـ `.two` بحيث أنه يستهدف class الـ `green` الجديد. وقم بتحديث منتقي `.three` بحيث يستهدف class الـ `blue` الجديد. +قم بتحديث CSS class selector الـ `.two` بحيث أنه يستهدف class الـ `green` الجديد. And update the `.three` class selector so it targets the new `blue` class. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b761916dac02643940022.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b761916dac02643940022.md index b32b383abac100..00324ab4579597 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b761916dac02643940022.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b761916dac02643940022.md @@ -11,7 +11,7 @@ dashedName: step-46 تبدأ قيم اللون hex برمز `#` وتأخذ ستة رموز من 0-9 و A-F. الزوج الأول من الرموز يمثل الأحمر، والزوج الثاني يمثل الأخضر، والزوج الثالث يمثل الأزرق. على سبيل المثال، `#4B5320`. -في قاعدة CSS لـ `.green`، قم بتعيين خاصية `background-color` إلى رمز لون hex مع القيم `00` للأحمر، `FF` للأخضر و `00` للأزرق. +In the `.green` class selector, set the `background-color` property to a hex color code with the values `00` for red, `FF` for green, and `00` blue. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7c3c83de403126b69c1e.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7c3c83de403126b69c1e.md index c45bf14d8839e6..612efd6c7cc303 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7c3c83de403126b69c1e.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7c3c83de403126b69c1e.md @@ -15,7 +15,7 @@ dashedName: step-47 مع ألوان hex الـ `00` هو 0% من هذا اللون، و `FF` هو 100%. إذن `#00FF00` يترجم إلى 0% أحمر و 100% أخضر و 0% أزرق، و هو نفس `rgb(0, 255, 0)`. -قم بتقليل كثافة اللون الأخضر عن طريق تعيين القيمة الخضراء للون hex إلى `7F`. +Lower the intensity of green by setting the green value of the hex color to `7F`. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7fd56aa2253778bcf5f7.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7fd56aa2253778bcf5f7.md index d8d9d32e6ed006..ef90de1d757a59 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7fd56aa2253778bcf5f7.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b7fd56aa2253778bcf5f7.md @@ -9,11 +9,11 @@ dashedName: step-48 نموذج الألوان HSL أو hue و saturation و lightness، طريقة أخرى لتمثيل الألوان. -تقبل دالة `hsl` ثلاثة قيم: عدد من 0 إلى 360 للـ hue، نسبة مئوية من 0 إلى 100 للـ saturation، ونسبة مئوية من 0 إلى 100 للـ lightness. +The CSS hsl function accepts 3 values: a number from 0 to 360 for hue, a percentage from 0 to 100 for saturation, and a percentage from 0 to 100 for lightness. إذا تخيلتم عجلة لون، فاللون الأحمر هو عند الدرجة صفر، والأخضر عند 120 درجة، والأزرق عند 240 درجة. -Saturation (التشبع) هو كثافة اللون من 0%، أو رمادي، إلى 100% للون النقي. +Saturation is the intensity of a color from 0%, or gray, to 100% for pure color. You must add the percent sign `%` to the saturation and lightness values. Lightness (الضوء) هي مدى سطوع اللون الذي يظهر، من 0٪ أو أسود بالكامل، إلى 100٪ أبيض بالكامل و 50٪ حيادي. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61a5d7ef1cfcf45764df07a2.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61a5d7ef1cfcf45764df07a2.md index 95b37fc9d0fa0d..cc269bf9323294 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61a5d7ef1cfcf45764df07a2.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61a5d7ef1cfcf45764df07a2.md @@ -9,7 +9,7 @@ dashedName: step-70 الآن بعد أن أصبح الألوان markers الصحيحة، حان الوقت لبناء marker sleeves. ابدأ من marker الأحمر. -داخل `div` في marker الأحمر، قم بإنشاء `div` جديد وإعطائه class تسمى `sleeve`. +Inside the red marker `div` element, create a new `div` element and give it a class of `sleeve`. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b093329e7fc020b43b1bb5.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b093329e7fc020b43b1bb5.md index 93e45e168d687c..34a7005cc19655 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b093329e7fc020b43b1bb5.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b093329e7fc020b43b1bb5.md @@ -15,11 +15,13 @@ dashedName: step-75 rgba(redValue, greenValue, blueValue, alphaValue); ``` -في قاعدة `.sleeve`، استخدم وظيفة `rgba` لتعيين خاصية `background-color` للأبيض النقي مع شفافية (opacity) 50%. +You can also use an alpha channel with `hsl` and `hex` colors. You will see how to do that soon. + +In the `.sleeve` rule, use the `rgba` function to set the `background-color` property to pure white with 50% opacity. # --hints-- -يجب أن يكون لقاعدة CSS مسمى `.sleeve` الخاصية `background-color` بقيمة `rgba(255, 255, 255, 0.5)`. +Your `.sleeve` CSS rule should have a `background-color` property set to `rgba(255, 255, 255, 0.5)`. ```js assert(new __helpers.CSSHelp(document).getStyle('.sleeve')?.backgroundColor === 'rgba(255, 255, 255, 0.5)'); diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b0a44a6b865738ba49b9fb.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b0a44a6b865738ba49b9fb.md index 884a631bed66ab..8d08083f4eca96 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b0a44a6b865738ba49b9fb.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b0a44a6b865738ba49b9fb.md @@ -15,13 +15,22 @@ dashedName: step-86 box-shadow: offsetX offsetY color; ``` -ابدأ بإضافة ظل بسيط إلى marker الأحمر. +Here's how the `offsetX` and `offsetY` values work: -في قاعدة CSS مسمى `.red`، قم بإضافة خاصية `box-shadow` مع القيم `5px` ألى `offsetX` و `5px` ألى `offsetY` و `red` ألى `color`. +* both `offsetX` and `offsetY` accept number values in `px` and other CSS units +* a positive `offsetX` value moves the shadow right and a negative value moves it left +* a positive `offsetY` value moves the shadow down and a negative value moves it up +* if you want a value of zero (`0`) for any or both `offsetX` and `offsetY`, you don't need to add a unit. Every browser understands that zero means no change. + +The height and width of the shadow is determined by the height and width of the element it's applied to. You can also use an optional `spreadRadius` value to spread out the reach of the shadow. More on that later. + +Start by adding a simple shadow to the red marker. + +In the `.red` CSS rule, add the `box-shadow` property with the values `5px` for `offsetX`, `5px` for `offsetY`, and `red` for `color`. # --hints-- -قاعدة CSS مسمى `.red`، يجب أن تحتوي علي خاصية `box-shadow` مع القيمة `5px 5px red`. +Your `.red` CSS rule should have a `box-shadow` shorthand property and with the value `5px 5px red`. ```js assert(new __helpers.CSSHelp(document).getStyle('.red')?.boxShadow === 'red 5px 5px'); diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b31287fb580ae75a486047.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b31287fb580ae75a486047.md index 969ccf6e0f7381..4f856c6a80a59d 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b31287fb580ae75a486047.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b31287fb580ae75a486047.md @@ -9,7 +9,7 @@ dashedName: step-90 الآن بعد أن أصبحت على دراية بخاصية `box-shadow` يمكنك وضع اللمسات الأخيرة على الظل، بدءاً بالخاصية في marker الأحمر. -في قاعدة CSS مسمى `.red`، قم بتحديث القيم لخاصية `box-shadow` حتي يصبح `offsetX` بقيمة `0` و `offsetY` بقيمة `0` و `blurRadius` بقيمة `20px` و `spreadRadius` بقيمة `0` و `color` بقيمة `red`. +In the `.red` CSS rule, update the values for the `box-shadow` property so `offsetX` is `0`,`offsetY` is `0`, `blurRadius` is `20px`, `spreadRadius` is `0`, and `color` is `red`. Remember that you don't need to add units to a zero value. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-grid-by-building-a-magazine/6148ceaf5d897d4d8b3554b3.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-grid-by-building-a-magazine/6148ceaf5d897d4d8b3554b3.md index 2fbae74beb8fd1..34f1d7c087e1d8 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-grid-by-building-a-magazine/6148ceaf5d897d4d8b3554b3.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-grid-by-building-a-magazine/6148ceaf5d897d4d8b3554b3.md @@ -7,7 +7,7 @@ dashedName: step-57 # --description-- -وكثيرا ما تستخدم المجلات نصا justified في محتوياتها المطبوعة لهيكلة تصميمها والتحكم في تدفق محتوياتها. بينما يعمل ذلك في الطباعة، يمكن أن يكون النص الـ justified على مواقع الويب مصدر قلق بشأن إمكانية الوصول، على سبيل المثال، صعوبات للأشخاص الذين يعانون من عسر القراءة. +وكثيرا ما تستخدم المجلات نصا justified في محتوياتها المطبوعة لهيكلة تصميمها والتحكم في تدفق محتوياتها. بينما يعمل ذلك في الطباعة، يمكن أن يكون النص المتباعد (justified) على مواقع الويب مصدر قلق بشأن تسهيل منال (accessibility)، ويضيف صعوبات للأشخاص الذين يعانون عسر القراءة على سبيل المثال. لجعل مشروعك يبدو وكأنه مجلة مطبوعة، أعط منتقي `.text` خاصية `text-align` بقيمة `justify`. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-grid-by-building-a-magazine/6148d3fff5186b57123d97e2.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-grid-by-building-a-magazine/6148d3fff5186b57123d97e2.md index b2ed0a4385a82b..7b874bba2ec0b5 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-grid-by-building-a-magazine/6148d3fff5186b57123d97e2.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-grid-by-building-a-magazine/6148d3fff5186b57123d97e2.md @@ -9,9 +9,9 @@ dashedName: step-64 الاقتباس (quote) ليس في الحقيقة اقتباسا بدون علامات اقتباس صحيحة. يمكنك إضافة هذه باستخدام CSS pseudo selectors. -قم بإنشاء منتقي `.quote::before` وقم بتعيين خاصية `content` إلى `"` بمسافة تليها. +أنشئ منتقي `.quote::before` وعين خاصية `content` بقيمة `"` وتليها مسافة. -وأيضا، قم بإنشاء `.quote::after` وقم بتعيين خاصية `content` إلى `"`بمسافة تسبقها. +وأيضا، أنشئ `.quote::after` وعين خاصية `content` بقيمة `"` وتسبقها مسافة. # --hints-- @@ -24,7 +24,7 @@ assert(new __helpers.CSSHelp(document).getStyle('.quote::before')); يجب أن يحتوي منتقي `.quote::before` على خاصية `content` بقيمة `'" '`. ```js -assert(new __helpers.CSSHelp(document).getStyle('.quote::before')?.content?.match(/\\?\"\s/)); +assert(new __helpers.CSSHelp(document).getStyle('.quote::before')?.content?.match(/\"\\"\s\"/)); ``` يجب أن يكون لديك منتقي `.quote::after`. @@ -36,7 +36,7 @@ assert(new __helpers.CSSHelp(document).getStyle('.quote::after')); يجب أن يحتوي منتقي `.quote::after` على خاصية `content` بقيمة `' "'`. ```js -assert(new __helpers.CSSHelp(document).getStyle('.quote::after')?.content?.match(/\s\\?\"/)); +assert(new __helpers.CSSHelp(document).getStyle('.quote::before')?.content?.match(/\"\\"\s\"/)); ``` # --seed-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/61967e74a8e3690ab6292daa.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/61967e74a8e3690ab6292daa.md index a08e8ae7d23125..8fc42781409ff0 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/61967e74a8e3690ab6292daa.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/61967e74a8e3690ab6292daa.md @@ -14,7 +14,7 @@ dashedName: step-2 يجب عليك استخدام منتقي العنصر `body`. ```js -assert.match(code, /body\s*\{/); +assert.exists(new __helpers.CSSHelp(document).getStyle('body')); ``` يجب عليك إضافة `background` داخل منتقي العنصر `body`. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/6196d1ac33c68d27dcda5796.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/6196d1ac33c68d27dcda5796.md index 988069c04070c3..e08ae4dbe2384b 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/6196d1ac33c68d27dcda5796.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/6196d1ac33c68d27dcda5796.md @@ -14,13 +14,25 @@ dashedName: step-23 يجب عليك استخدام خاصية `transform` لدوران العنصر. ```js -assert.notEmpty(new __helpers.CSSHelp(document).getStyle('.back-mountain')?.transform); +const backMountain = new __helpers.CSSHelp(document).getStyle('.back-mountain'); + +if (backMountain?.transform) { + assert.notEmpty(backMountain?.transform); +} else { + assert.notEmpty(backMountain?.rotate); +} ``` يجب أعطاء منقي `.back-mountain` خاصية `transform` بقيمة `--fcc-expected--`, ولكن وجدت بقيمة `--fcc-actual--`. ```js -assert.equal(new __helpers.CSSHelp(document).getStyle('.back-mountain')?.transform, 'rotate(45deg)'); +const backMountain = new __helpers.CSSHelp(document).getStyle('.back-mountain'); + +if (backMountain?.transform) { + assert.equal(backMountain?.transform, 'rotate(45deg)'); +} else { + assert.equal(backMountain?.rotate, '45deg'); +} ``` يجب عليك إعطاء عنصر `.back-mountain` خاصية `left`. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d1c5fc9f8941a400955da.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d1c5fc9f8941a400955da.md index 2e99f487bdb05d..35e1fcb167ff3c 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d1c5fc9f8941a400955da.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d1c5fc9f8941a400955da.md @@ -7,7 +7,7 @@ dashedName: step-75 # --description-- -In some browsers, the _heart_ emoji may look slightly different from the previous step. هذا لأن بعض خصائص الشخصية قد تم تجاوزها بواسطة نمط `font-weight` من `bold`. +في بعض المتصفحات، قد يبدو رمز تعبيري _heart_ مختلفاً قليلاً عن الخطوة السابقة. هذا لأن بعض خصائص الشخصية قد تم تجاوزها بواسطة نمط `font-weight` من `bold`. قم بإصلاح هذا، بواسطة استهداف `div` مع الرموز التعبيرية للقلب، وتعيين `font-weight` لقيمتها الأصلية. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d229b0e542520cd91c685.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d229b0e542520cd91c685.md index e876bcf81c91c1..671517feff1105 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d229b0e542520cd91c685.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d229b0e542520cd91c685.md @@ -14,13 +14,25 @@ dashedName: step-84 يجب عليك إعطاء `.foot.left` خاصية `transform` بقيمة `rotate(80deg)`. ```js -assert.equal(new __helpers.CSSHelp(document).getStyle('.foot.left').getPropVal('transform', true), 'rotate(80deg)'); +const leftFoot = new __helpers.CSSHelp(document).getStyle('.foot.left'); + +if (leftFoot?.transform) { + assert.equal(leftFoot.getPropVal('transform', true), 'rotate(80deg)'); +} else { + assert.equal(leftFoot.getPropVal('rotate', true), '80deg'); +} ``` يجب عليك إعطاء `.foot.right` خاصية `transform` بقيمة `rotate(-80deg)`. ```js -assert.equal(new __helpers.CSSHelp(document).getStyle('.foot.right').getPropVal('transform', true), 'rotate(-80deg)'); +const rightFoot = new __helpers.CSSHelp(document).getStyle('.foot.right'); + +if (rightFoot?.transform) { + assert.equal(rightFoot.getPropVal('transform', true), 'rotate(-80deg)'); +} else { + assert.equal(rightFoot.getPropVal('rotate', true), '-80deg'); +} ``` # --seed-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d2d4e80400325ff89664a.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d2d4e80400325ff89664a.md index 93b822cb7a8ab3..1aa5ab966c2836 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d2d4e80400325ff89664a.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d2d4e80400325ff89664a.md @@ -14,7 +14,14 @@ dashedName: step-91 يجب عليك إعطاء `.arm.left` خاصية `transform` بقيمة `rotate(130deg) scaleX(-1)`. ```js -assert.equal(new __helpers.CSSHelp(document).getStyle('.arm.left').getPropVal('transform', true), 'rotate(130deg)scaleX(-1)'); +const leftArm = new __helpers.CSSHelp(document).getStyle('.arm.left'); + +if (leftArm?.rotate && leftArm?.transform) { + assert.equal(leftArm.getPropVal('rotate', true), '130deg'); + assert.equal(leftArm.getPropVal('transform', true), 'scaleX(-1)'); +} else { + assert.equal(leftArm.getPropVal('transform', true), 'rotate(130deg)scaleX(-1)'); +} ``` # --seed-- @@ -281,7 +288,6 @@ body { top: 35%; left: 5%; transform-origin: top left; - } --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d2ebc81ba81271460850d.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d2ebc81ba81271460850d.md index 35e8dddb42abc2..6f050be3ac1c10 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d2ebc81ba81271460850d.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d2ebc81ba81271460850d.md @@ -14,7 +14,13 @@ dashedName: step-92 يجب عليك إعطاء `.arm.right` خاصية `transform` بقيمة `rotate(-45deg)`. ```js -assert.equal(new __helpers.CSSHelp(document).getStyle('.arm.right')?.getPropVal('transform', true), 'rotate(-45deg)'); +const rightArm = new __helpers.CSSHelp(document).getStyle('.arm.right'); + +if (rightArm?.transform) { + assert.equal(rightArm?.getPropVal('transform', true), 'rotate(-45deg)'); +} else { + assert.equal(rightArm?.getPropVal('rotate', true), '-45deg'); +} ``` # --seed-- @@ -287,7 +293,6 @@ body { .arm.right { top: 0%; right: -5%; - } --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d32c7fa21f32aaa91d499.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d32c7fa21f32aaa91d499.md index b99f65941efc9e..6cd75f86d08f39 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d32c7fa21f32aaa91d499.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d32c7fa21f32aaa91d499.md @@ -14,7 +14,16 @@ dashedName: step-97 يجب عليك إعطاء `10%` إلى خاصية `transform` بقيمة `rotate(110deg) scaleX(-1)`. ```js -assert([...[...new __helpers.CSSHelp(document).getCSSRules('keyframes')].find(rule => rule?.name === 'wave')?.cssRules].find(css => css?.keyText === '10%')?.style?.transform?.replace(/\s+/g, '') === 'rotate(110deg)scaleX(-1)'); +const wave10Percent = [...[...new __helpers.CSSHelp(document).getCSSRules('keyframes')].find(rule => rule?.name === 'wave')?.cssRules].find(css => css?.keyText === '10%'); +const rotateProp = wave10Percent?.style?.rotate?.replace(/\s+/g, ''); +const transformProp = wave10Percent?.style?.transform?.replace(/\s+/g, ''); + +if (rotateProp && transformProp) { + assert(rotateProp === '110deg'); + assert(transformProp === 'scaleX(-1)'); +} else { + assert(transformProp === 'rotate(110deg)scaleX(-1)'); +} ``` # --seed-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d333b738e3c2b5d58b095.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d333b738e3c2b5d58b095.md index 6b143b466c9e40..80143e773e3836 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d333b738e3c2b5d58b095.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d333b738e3c2b5d58b095.md @@ -14,7 +14,16 @@ dashedName: step-98 يجب عليك إعطاء أحداثية `20%` خاصية `transform` بقيمة `rotate(130deg) scaleX(-1)`. ```js -assert([...[...new __helpers.CSSHelp(document).getCSSRules('keyframes')].find(rule => rule?.name === 'wave')?.cssRules].find(css => css?.keyText === '20%')?.style?.transform?.replace(/\s+/g, '') === 'rotate(130deg)scaleX(-1)'); +const wave20Percent = [...[...new __helpers.CSSHelp(document).getCSSRules('keyframes')].find(rule => rule?.name === 'wave')?.cssRules].find(css => css?.keyText === '20%'); +const transformProp = wave20Percent?.style?.transform?.replace(/\s+/g, ''); +const rotateProp = wave20Percent?.style?.rotate?.replace(/\s+/g, ''); + +if (rotateProp && transformProp) { + assert(rotateProp === '130deg'); + assert(transformProp === 'scaleX(-1)'); +} else { + assert(transformProp === 'rotate(130deg)scaleX(-1)'); +} ``` # --seed-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d337765b9f02c10e93722.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d337765b9f02c10e93722.md index 2d8f943f309be2..f06e0e747ce290 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d337765b9f02c10e93722.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-transforms-by-building-a-penguin/619d337765b9f02c10e93722.md @@ -14,13 +14,31 @@ dashedName: step-99 يجب عليك إعطاء نقطة الطريق `30%` خاصية `transform` بقيمة `rotate(110deg) scaleX(-1)`. ```js -assert([...[...new __helpers.CSSHelp(document).getCSSRules('keyframes')].find(rule => rule?.name === 'wave')?.cssRules].find(css => css?.keyText === '30%')?.style?.transform?.replace(/\s+/g, '') === 'rotate(110deg)scaleX(-1)'); +const wave30Percent = [...[...new __helpers.CSSHelp(document).getCSSRules('keyframes')].find(rule => rule?.name === 'wave')?.cssRules].find(css => css?.keyText === '30%'); +const transformProp = wave30Percent?.style?.transform?.replace(/\s+/g, ''); +const rotateProp = wave30Percent?.style?.rotate?.replace(/\s+/g, ''); + +if (rotateProp && transformProp) { + assert(rotateProp === '110deg'); + assert(transformProp === 'scaleX(-1)'); +} else { + assert(transformProp === 'rotate(110deg)scaleX(-1)'); +} ``` يجب عليك إعطاء نقطة الطريق `40%` خاصية `transform` بقيمة `rotate(130deg) scaleX(-1)`. ```js -assert([...[...new __helpers.CSSHelp(document).getCSSRules('keyframes')].find(rule => rule?.name === 'wave')?.cssRules].find(css => css?.keyText === '40%')?.style?.transform?.replace(/\s+/g, '') === 'rotate(130deg)scaleX(-1)'); +const wave40Percent = [...[...new __helpers.CSSHelp(document).getCSSRules('keyframes')].find(rule => rule?.name === 'wave')?.cssRules].find(css => css?.keyText === '40%'); +const transformProp = wave40Percent?.style?.transform?.replace(/\s+/g, ''); +const rotateProp = wave40Percent?.style?.rotate?.replace(/\s+/g, ''); + +if (rotateProp && transformProp) { + assert(rotateProp === '130deg'); + assert(transformProp === 'scaleX(-1)'); +} else { + assert(transformProp === 'rotate(130deg)scaleX(-1)'); +} ``` # --seed-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-variables-by-building-a-city-skyline/5d822fd413a79914d39e98f0.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-variables-by-building-a-city-skyline/5d822fd413a79914d39e98f0.md index c4515339280679..f022b5ae5e0a3c 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-variables-by-building-a-city-skyline/5d822fd413a79914d39e98f0.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-css-variables-by-building-a-city-skyline/5d822fd413a79914d39e98f0.md @@ -16,11 +16,11 @@ gradient-type( ); ``` -في المثال، `color1` صُلْب في الأعلى، `color2` صُلْب في الأسفل، وفي ما بينها ينتقل بالتساوي من واحد إلى آخر. في `.bb1a`، إضافة عنصر تدرج من نوع `linear-gradient` إلى خاصية `background` مع `--building-color1` كاللون الأول و `--window-color1` كالثاني. +في المثال، `color1` صُلْب في الأعلى، `color2` صُلْب في الأسفل، وفي ما بينها ينتقل بالتساوي من واحد إلى آخر. في `.bb1a`، أضف خاصية `background` أسفل خاصية `background-color`. عيّنه كتدرج من نوع `linear-gradient` الذي يستخدم `--building-color1` كاللون الأول و `--window-color1` كالثاني. # --hints-- -يجب عليك تطبيق `background` على `.bb1a`. +يجب عليك تطبيق `background` على `.bb1a` بعد `background-color` مباشرة. ```js assert(new __helpers.CSSHelp(document).getStyle('.bb1a')?.background); @@ -32,13 +32,13 @@ assert(new __helpers.CSSHelp(document).getStyle('.bb1a')?.background); assert.include(new __helpers.CSSHelp(document).getStyle('.bb1a')?.background, 'linear-gradient'); ``` -يجب عليك إعطاء `background` بنوع `linear-gradient` بدءاً من `--building-color1`. +You should give the `background` a `linear-gradient` starting from `var(--building-color1)`. ```js assert.include(new __helpers.CSSHelp(document).getStyle('.bb1a')?.getPropVal('background', true), 'linear-gradient(var(--building-color1'); ``` -يجب عليك إعطاء `background` بنوع `linear-gradient` بدءاً من `--window-color1`. +You should give the `background` a `linear-gradient` ending at `var(--window-color1)`. ```js assert.include(new __helpers.CSSHelp(document).getStyle('.bb1a')?.getPropVal('background', true), 'linear-gradient(var(--building-color1),var(--window-color1))'); diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc17d3bf86c76b9248c6eb4.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc17d3bf86c76b9248c6eb4.md index f455f9f12db410..ef401b326fa4da 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc17d3bf86c76b9248c6eb4.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc17d3bf86c76b9248c6eb4.md @@ -9,7 +9,7 @@ dashedName: step-3 يتم استخدام عنصر `p` لإنشاء فقرة من النصوص على مواقع الويب. قم بإنشاء عنصر `p` تحت عنصر `h2` الخاص بك وقم بإعطائه النص التالي: -`Click here to view more cat photos.` +`See more cat photos in our gallery.` # --hints-- @@ -25,13 +25,13 @@ assert(document.querySelector('p')); assert(code.match(/<\/p\>/)); ``` -يجب أن يكون نص العنصر الخاص بك `p` هو `Click here to view more cat photos.` إما أنك حذفت النص أو لديك خطأ إملائي. +يجب أن يكون نص عنصرك `p` بقيمة `See more cat photos in our gallery.` إما أنك حذفت النص أو لديك خطأ إملائي. ```js const extraSpacesRemoved = document .querySelector('p') .innerText.replace(/\s+/g, ' '); -assert(extraSpacesRemoved.match(/click here to view more cat photos\.?$/i)); +assert(extraSpacesRemoved.match(/see more cat photos in our gallery\.?$/i)); ``` يجب أن يكون عنصر `p` الخاص بك تحت عنصر `h2`. لقد وضعتهم بترتيب خاطئ. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc17dc8f86c76b9248c6eb5.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc17dc8f86c76b9248c6eb5.md index 8e56512f217acb..8456cd9ac997ca 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc17dc8f86c76b9248c6eb5.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc17dc8f86c76b9248c6eb5.md @@ -47,7 +47,7 @@ assert( code .replace(/\s/g, '') .match( - /

                                          clickheretoviewmorecatphotos\.?<\/p>/i + /

                                          seemorecatphotosinourgallery\.?<\/p>/i ) ); ``` @@ -63,7 +63,7 @@ assert(

                                          Cat Photos

                                          --fcc-editable-region-- -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc2385ff86c76b9248c6eb7.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc2385ff86c76b9248c6eb7.md index 89cb818d0924fc..a67c6be9ec1ae0 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc2385ff86c76b9248c6eb7.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc2385ff86c76b9248c6eb7.md @@ -7,7 +7,7 @@ dashedName: step-5 # --description-- -يحتوي HTML5 على بعض العناصر التي تحدد مناطق المحتوى المختلفة. هذه العناصر تجعل HTML الخاص بك أسهل للقراءة وتساعدة في تحسين محرك البحث (SEO) وإمكانية الوصول (accessibility). +يحتوي HTML5 على بعض العناصر التي تحدد مناطق المحتوى المختلفة. هذه العناصر تجعل HTML الخاص بك أسهل للقراءة وتساعد في تحسين محرك البحث (SEO) وتسهيل المنال (accessibility). حدد القسم الرئيس من هذه الصفحة بإضافة علامة فتح `
                                          ` بعد عنصر `h1`، و علامة إغلاق `
                                          ` بعد عنصر `p`. @@ -48,7 +48,7 @@ const mainNode = document.querySelector('main'); const pNode = document.querySelector('p'); assert( mainNode.contains(pNode) && - pNode.textContent.toLowerCase().match(/click here to view more cat photos/) + pNode.textContent.toLowerCase().match(/see more cat photos in our gallery/) ); ``` @@ -64,7 +64,7 @@ assert(

                                          CatPhotoApp

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc23991f86c76b9248c6eb8.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc23991f86c76b9248c6eb8.md index 03ca010df573cc..1c40d212dfeb77 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc23991f86c76b9248c6eb8.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc23991f86c76b9248c6eb8.md @@ -65,14 +65,14 @@ assert( assert(document.querySelector('p')); ``` -نص عنصر `p` يجب أن يكون `Click here to view more cat photos.` لا تقم بتغيير النص أو المسافات أو علامات الترقيم لعنصر `p`. +يجب أن يكون نص عنصر `p` بقيمة `See more cat photos in our gallery.` لا تقم بتغيير النص أو المسافات أو علامات الترقيم لعنصر `p`. ```js assert( document .querySelector('p') .innerText.toLowerCase() - .match(/click\s+here\s+to\s+view\s+more\s+cat\s+photos\.?$/) + .match(/see\s+more\s+cat\s+photos\s+in\s+our\s+gallery\.?$/) ); ``` @@ -94,7 +94,7 @@ assert(code.toLowerCase().match(/-->\s*\n\s{6}

                                          /));

                                          CatPhotoApp

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc23f9bf86c76b9248c6eba.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc23f9bf86c76b9248c6eba.md index 395f2243ed6c4d..4ac96b253638dc 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc23f9bf86c76b9248c6eba.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc23f9bf86c76b9248c6eba.md @@ -52,7 +52,7 @@ assert(collection.indexOf('P') < collection.indexOf('IMG'));

                                          Cat Photos

                                          --fcc-editable-region-- -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24073f86c76b9248c6ebb.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24073f86c76b9248c6ebb.md index ccb7ac7be6a0bc..601bd52955bcb1 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24073f86c76b9248c6ebb.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24073f86c76b9248c6ebb.md @@ -50,7 +50,7 @@ assert(!/\CatPhotoApp

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24165f86c76b9248c6ebc.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24165f86c76b9248c6ebc.md index 8f1eafa3ae6ff3..bea9154902c1f9 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24165f86c76b9248c6ebc.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24165f86c76b9248c6ebc.md @@ -7,7 +7,7 @@ dashedName: step-9 # --description-- -يجب أن تحتوي جميع عناصر `img` على سمة `alt`. يتم استخدام نص السمة `alt` لقراء الشاشة (screen readers) لتحسين إمكانية الوصول ويتم عرضه إذا فشل تحميل الصورة. على سبيل المثال، `A cat` يحتوي على سمة `alt` مع النص `A cat`. +يجب أن تحتوي جميع عناصر `img` على سمة `alt`. يتم استخدام نص السمة `alt` لقراء الشاشة (screen readers) لتسهيل الوصول (accessibility) ويتم عرضه إذا فشل تحميل الصورة. على سبيل المثال، `A cat` يحتوي على سمة `alt` مع النص `A cat`. داخل عنصر `img` ، أضف سمة `alt` مع هذا النص: @@ -48,7 +48,7 @@ assert(altText.match(/A cute orange cat lying on its back\.?$/i));

                                          CatPhotoApp

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24614f86c76b9248c6ebd.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24614f86c76b9248c6ebd.md index 8f1bfd8f552101..f3fadb00026d55 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24614f86c76b9248c6ebd.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dc24614f86c76b9248c6ebd.md @@ -69,7 +69,7 @@ assert(

                                          Cat Photos

                                          --fcc-editable-region-- -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- A cute orange cat lying on its back. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ddbd81294d8ddc1510a8e56.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ddbd81294d8ddc1510a8e56.md index fb2d5c9a181b7d..b1558d23e1ab6e 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ddbd81294d8ddc1510a8e56.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ddbd81294d8ddc1510a8e56.md @@ -45,7 +45,7 @@ assert(

                                          CatPhotoApp

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa22d1b521be39a3de7be0.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa22d1b521be39a3de7be0.md index 13e42936e1655b..8cd17cab9a91f2 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa22d1b521be39a3de7be0.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa22d1b521be39a3de7be0.md @@ -38,14 +38,14 @@ assert( ); ``` -بعد دمج عنصر الرابط (`a`)، محتوى العنصر `p` الوحيد المرئي في المتصفح يجب أن يكون `Click here to view more cat photos.` تحقق مرتين من النص أو المسافات أو علامات الترقيم لكل من `p` وعنصر الرابط المدمج. +بعد إدخال عنصر الرابط (`a`)، يجب أن يكون محتوى العنصر `p` الوحيد المرئي في المتصفح `See more cat photos in our gallery.` أعد التحقق من النص أو المسافات أو علامات الترقيم لكل من `p` وعنصر الرابط داخله. ```js const pText = document .querySelector('p') .innerText.toLowerCase() .replace(/\s+/g, ' '); -assert(pText.match(/click here to view more cat photos\.?$/)); +assert(pText.match(/see more cat photos in our gallery\.?$/)); ``` # --seed-- @@ -60,7 +60,7 @@ assert(pText.match(/click here to view more cat photos\.?$/));

                                          Cat Photos

                                          --fcc-editable-region-- -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          link to cat pictures --fcc-editable-region-- A cute orange cat lying on its back. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa2407b521be39a3de7be1.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa2407b521be39a3de7be1.md index 14b6b8cc56da2e..edbb0356ef859d 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa2407b521be39a3de7be1.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa2407b521be39a3de7be1.md @@ -45,7 +45,7 @@ assert(document.querySelector('a').getAttribute('target') === '_blank');

                                          Cat Photos

                                          --fcc-editable-region-- -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- A cute orange cat lying on its back. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa30b9eacea3f48c6300ad.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa30b9eacea3f48c6300ad.md index 738739528b235e..07e756d178892b 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa30b9eacea3f48c6300ad.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa30b9eacea3f48c6300ad.md @@ -7,11 +7,13 @@ dashedName: step-15 # --description-- -قم بتحويل الصورة إلى رابط عن طريق احاطتها بـ tags العنصر الضرورية. استخدم `https://freecatphotoapp.com` كقيمة السمة `href`. +في الخطوات السابقة كنت تستخدم عنصر الرابط لتحويل النص إلى رابط. ويمكن أيضا تحويل أنواع أخرى من المحتوى إلى رابط عن طريق وضعه بداخل عنصر الرابط. + +حول الصورة إلى رابط عن طريق إحاطتها بعلامات العنصر المناسب. استخدم `https://freecatphotoapp.com` كقيمة السمة `href`. # --hints-- -يجب أن يكون لديك عنصر `img` بقيمة `src` من `https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg`. ربما قمت بحذفها عن طريق الخطأ. +يجب أن يكون لديك عنصر `img` بقيمة `src` من `https://cdn.freecodecamp.org/curriculum/cat-photo-app/relaxing-cat.jpg`. ربما حذفتها عن طريق الخطأ. ```js assert( @@ -21,37 +23,37 @@ assert( ); ``` -يجب أن يحتوي العنصر (`a`) على opening tag. Opening tags تكتب هكذا: ``. +يجب أن يحتوي العنصر (`a`) على علامة الفتح. تكتب علامات الفتح هكذا: ``. ```js assert(document.querySelectorAll('a').length >= 2); ``` -يجب عليك إضافة opening tag واحد فقط للـ (`a`). الرجاء إزالة أي زيادات. +يجب عليك إضافة علامة فتح واحد فقط لـ (`a`). الرجاء إزالة أي زيادات. ```js assert(document.querySelectorAll('a').length === 2); ``` -يجب أن يحتوي العنصر (`a`) على closing tag. Closing tags لها `/` مباشرة بعد رمز `<`. +يجب أن يحتوي العنصر (`a`) على علامة غلق. يجب أن تأتي علامات الغلق بـ `/` بعد رمز `<` مباشرة. ```js assert(code.match(/<\/a>/g).length >= 2); ``` -يجب عليك إضافة closing tag واحد فقط للـ (`a`). الرجاء إزالة أي زيادات. +يجب عليك إضافة علامة غلق واحد فقط لـ (`a`). الرجاء إزالة أي زيادات. ```js assert(code.match(/<\/a>/g).length === 2); ``` -عنصر (`a`) الخاص بك ليس لديه سمة `href`. تحقق من وجود مسافة بعد اسم الـ opening tag و/أو ان هناك مسافات قبل جميع أسماء السمات. +ليس لدي عنصرك (`a`) سمة `href`. تيقن من وجود مسافة بعد اسم علامة الفتح و/أو أن هناك مسافات قبل جميع أسماء السمات. ```js assert(document.querySelector('a').hasAttribute('href')); ``` -(`a`) الخاص بك يجب أن يحيل الي `https://freecatphotoapp.com`. إما أنك حذفت الـ URL أو لديك خطأ إملائي. +يجب أن يربط عنصرك (`a`) إلى `https://freecatphotoapp.com`. إما أنك حذفت الرابط (URL) أو لديك خطأ إملائي. ```js assert( @@ -60,7 +62,7 @@ assert( ); ``` -يجب أن يكون عنصر `img` الخاص بك متداخلا داخل عنصر الرابط (`a`). يجب أن يكون عنصر `img` بأكمله داخل الـ opening و الـ closing tags لعنصر الرابط (`a`). +يجب أن يدخل عنصرك `img` داخل عنصر الرابط (`a`). يجب أن يكون عنصر `img` كله داخل العلامات فتح و العلامات غلق لعنصر الرابط (`a`). ```js assert(document.querySelector('img').parentNode.nodeName === 'A'); @@ -77,7 +79,7 @@ assert(document.querySelector('img').parentNode.nodeName === 'A');

                                          CatPhotoApp

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          --fcc-editable-region-- A cute orange cat lying on its back. --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa3589eacea3f48c6300ae.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa3589eacea3f48c6300ae.md index a8400fd4edf8b9..1d4cf1ce3a2839 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa3589eacea3f48c6300ae.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa3589eacea3f48c6300ae.md @@ -61,7 +61,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa371beacea3f48c6300af.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa371beacea3f48c6300af.md index d37e0aff47973a..d078791bb42862 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa371beacea3f48c6300af.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa371beacea3f48c6300af.md @@ -69,7 +69,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa37b9eacea3f48c6300b0.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa37b9eacea3f48c6300b0.md index b177ce9b02e8cc..20d11d05af3f97 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa37b9eacea3f48c6300b0.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfa37b9eacea3f48c6300b0.md @@ -42,7 +42,7 @@ assert(secondSectionLastElemNode.nodeName === 'UL');

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb5ecbeacea3f48c6300b1.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb5ecbeacea3f48c6300b1.md index f043ae66c4c79b..9c8ff836838dcf 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb5ecbeacea3f48c6300b1.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb5ecbeacea3f48c6300b1.md @@ -61,7 +61,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb6250eacea3f48c6300b2.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb6250eacea3f48c6300b2.md index 9650e8f26b2fd6..808e74805c5f78 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb6250eacea3f48c6300b2.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb6250eacea3f48c6300b2.md @@ -73,7 +73,7 @@ assert(!/\

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb655eeacea3f48c6300b3.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb655eeacea3f48c6300b3.md index cafbe116e6f22f..5dfd36a67e0d93 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb655eeacea3f48c6300b3.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb655eeacea3f48c6300b3.md @@ -53,7 +53,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb6a35eacea3f48c6300b4.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb6a35eacea3f48c6300b4.md index 80407b98d587cf..a67aa0fca1d809 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb6a35eacea3f48c6300b4.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5dfb6a35eacea3f48c6300b4.md @@ -74,7 +74,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d0.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d0.md index ec673fe8e40606..0b5a1542531b6f 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d0.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d0.md @@ -60,7 +60,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d1.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d1.md index fc459f4eed3c0f..ff0395e7ff1718 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d1.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d1.md @@ -56,7 +56,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d2.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d2.md index 1464310624fdc1..e43c148527ee96 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d2.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d2.md @@ -55,6 +55,12 @@ assert.deepStrictEqual( ); ``` +يجب أن يكون لديك عنصر `ol` واحد فقط. + +```js +assert([...document.querySelectorAll('ol')].length == 1); +``` + # --seed-- ## --seed-contents-- @@ -67,7 +73,7 @@ assert.deepStrictEqual(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d3.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d3.md index b4b568f39933fb..250044dc81da76 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d3.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d3.md @@ -41,7 +41,7 @@ assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d4.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d4.md index fcf0cd63d43b5b..5605616ee80083 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d4.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d4.md @@ -61,7 +61,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d5.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d5.md index 53b2c041433747..680ee2d544293a 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d5.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d5.md @@ -68,7 +68,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d6.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d6.md index 4808b6583e3de6..40a7dccdc6dfcf 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d6.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d6.md @@ -50,7 +50,7 @@ assert($('form')[0].innerHTML.trim().length === 0);

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d7.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d7.md index c6f1b12adcec6c..3bbdbaf837e644 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d7.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d7.md @@ -76,7 +76,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d8.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d8.md index e275d98efc98ed..72b3d39f2be3af 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d8.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d8.md @@ -69,7 +69,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d9.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d9.md index 0335e84f7317b4..f360f478d738d3 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d9.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804d9.md @@ -63,7 +63,7 @@ assert(!/\<\s*input\s+placeholder\s*=\s*cat\s+photo\s+url/i.test(code));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804da.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804da.md index 896fa392f4dd7e..c741bc43b7dba7 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804da.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804da.md @@ -52,7 +52,7 @@ assert(collection.indexOf('INPUT') < collection.indexOf('BUTTON'));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804db.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804db.md index 91d9c859288ec5..46c3ea50f52f8c 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804db.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804db.md @@ -50,7 +50,7 @@ assert($('input')[0].getAttribute('required') === '');

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804dc.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804dc.md index 2c89ed071b1f39..a72c9b9c31734c 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804dc.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804dc.md @@ -105,7 +105,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804dd.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804dd.md index b3516c34492b67..bbcba7f76e4a31 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804dd.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804dd.md @@ -61,7 +61,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804de.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804de.md index 1eb89d2edaf76a..37b567c2b7d650 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804de.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804de.md @@ -62,7 +62,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.

                                          Cat Lists

                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804df.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804df.md index f25319f85a968e..908bc26c9b6fe4 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804df.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804df.md @@ -52,7 +52,7 @@ assert($('input')[0].id.match(/^indoor$/));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e1.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e1.md index 1b244f4274f842..c930760281d64f 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e1.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e1.md @@ -58,7 +58,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e2.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e2.md index dd5484687b0e2a..92f5c1a7ea2885 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e2.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e2.md @@ -80,7 +80,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e3.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e3.md index d121beddf9dab9..fb655f625a1fe1 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e3.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e3.md @@ -71,7 +71,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e5.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e5.md index 95846c2fc3b08e..f648de78ef94d3 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e5.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e5.md @@ -22,7 +22,7 @@ assert( ); ``` -زر الراديو الأول مفتقد لسمة `checked`. +زرك الراديو الأول، مع `id` بقيمة `indoor`، يجب أن يكون `checked`. ```js assert($('input[type="radio"]')[0].hasAttribute('checked')); @@ -64,7 +64,7 @@ assert(!$('input[type="checkbox"]')[2].hasAttribute('checked'));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e7.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e7.md index f412aa92b33545..bc2bffdfc54c35 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e7.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e7.md @@ -49,7 +49,7 @@ assert(document.querySelector('main').nextElementSibling.nodeName === 'FOOTER');

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e8.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e8.md index 6362f3743f8bf6..c20f60be263131 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e8.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e8.md @@ -49,7 +49,7 @@ assert(extraSpacesRemoved.match(/No Copyright - freeCodeCamp\.org$/i));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e9.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e9.md index 12b194ab0224f7..3380d361bb18e0 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e9.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804e9.md @@ -60,7 +60,7 @@ assert(pText.match(/^no copyright - freecodecamp.org$/));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          @@ -106,11 +106,9 @@ assert(pText.match(/^no copyright - freecodecamp.org$/));
                                          -

                                          --fcc-editable-region-- - No Copyright - freeCodeCamp.org +

                                          No Copyright - freeCodeCamp.org

                                          --fcc-editable-region-- -

                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ea.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ea.md index e3d163fbf944f0..9595deaef53658 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ea.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ea.md @@ -53,7 +53,7 @@ assert(noSpaces.match(/\<\/head\>\/));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804eb.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804eb.md index e0ca005ef4f1f7..c0ad92f4afbc0d 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804eb.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804eb.md @@ -57,7 +57,7 @@ assert(document.title && document.title.toLowerCase() === 'catphotoapp');

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ec.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ec.md index a40e314ec0d318..ef4cce1ea4dcbd 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ec.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ec.md @@ -49,7 +49,7 @@ assert(code.match(//gi));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ee.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ee.md index 9293b4d0977941..56b82644daa51d 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ee.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5ef9b03c81a63668521804ee.md @@ -44,7 +44,7 @@ assert(noSpaces.match(/^\<\!DOCTYPEhtml\>\

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efada803cbd2bbdab94e332.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efada803cbd2bbdab94e332.md index 8ea7412e4f88e7..90c89a4b1a65ba 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efada803cbd2bbdab94e332.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efada803cbd2bbdab94e332.md @@ -66,7 +66,7 @@ assert(!/\

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efae0543cbd2bbdab94e333.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efae0543cbd2bbdab94e333.md index b861c631d3c65a..44020989b2bb51 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efae0543cbd2bbdab94e333.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efae0543cbd2bbdab94e333.md @@ -7,7 +7,7 @@ dashedName: step-30 # --description-- -لتحسين إمكانية الوصول (accessibility) إلى الصورة التي أضفتها، أضف خاصية `alt` مع النص: +لتسهيل المنال (accessibility) في الصورة التي أضفتها، أضف خاصية `alt` مع النص: `Five cats looking around a field.` @@ -65,7 +65,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efae16e3cbd2bbdab94e334.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efae16e3cbd2bbdab94e334.md index 641c36a63ecc68..a9591826f6f983 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efae16e3cbd2bbdab94e334.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efae16e3cbd2bbdab94e334.md @@ -89,7 +89,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efb23e70dc218d6c85f89b1.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efb23e70dc218d6c85f89b1.md index 728790ca53744b..539c82e2790ac4 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efb23e70dc218d6c85f89b1.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efb23e70dc218d6c85f89b1.md @@ -63,7 +63,7 @@ assert(!/\

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efb2c990dc218d6c85f89b2.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efb2c990dc218d6c85f89b2.md index 166ddf0e1ad4bb..649178dff02797 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efb2c990dc218d6c85f89b2.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efb2c990dc218d6c85f89b2.md @@ -59,7 +59,7 @@ assert(!/\<\s*button\s+type\s*=\s*submit/i.test(code));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc4f528d6a74d05e68af74.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc4f528d6a74d05e68af74.md index 4c3df1173dc53a..7042c4ca854fb6 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc4f528d6a74d05e68af74.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc4f528d6a74d05e68af74.md @@ -9,7 +9,7 @@ dashedName: step-56 هناك طريقة أخرى لربط نص عنصر `input` بالعنصر نفسه. يمكنك دمج النص ضمن عنصر `label` وإضافة سمة `for` بنفس القيمة كسمة `id` لعنصر `input`. -قم بربط النص `Loving` مع مربع الاختيار (checkbox) من خلال إدخال فقط النص `Loving` في عنصر `label` ووضعه على الجانب الأيمن من مربع الاختيار لعنصر `input`. +اربط النص `Loving` مع checkbox بواسطة إدخال النص `Loving` فقط في عنصر `label` وإعطائه السمة `for`. # --hints-- @@ -85,7 +85,7 @@ assert(labelElem.textContent.replace(/\s/g, '').match(/Loving/i));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc518e8d6a74d05e68af75.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc518e8d6a74d05e68af75.md index c2bab9277b3ccf..b40f8c3e36c4fa 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc518e8d6a74d05e68af75.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc518e8d6a74d05e68af75.md @@ -47,7 +47,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc54138d6a74d05e68af76.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc54138d6a74d05e68af76.md index f5be4e60140ecb..3c5669d4892687 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc54138d6a74d05e68af76.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc54138d6a74d05e68af76.md @@ -35,7 +35,7 @@ assert($('input[type="checkbox"]')[0].id.match(/^loving$/));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc575c8d6a74d05e68af77.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc575c8d6a74d05e68af77.md index c259edc6e59647..8448e5dcbf0d78 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc575c8d6a74d05e68af77.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5efc575c8d6a74d05e68af77.md @@ -72,7 +72,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f05a1d8e233dff4a68508d8.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f05a1d8e233dff4a68508d8.md index 06c073b0079329..3294ee47bebdbd 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f05a1d8e233dff4a68508d8.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f05a1d8e233dff4a68508d8.md @@ -93,7 +93,7 @@ assert(code.match(/<\/label>\s*\s*]+>\s*Outdoor/i));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07be6ef7412fbad0c5626b.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07be6ef7412fbad0c5626b.md index fc1525b6fbde80..117c453813f677 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07be6ef7412fbad0c5626b.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07be6ef7412fbad0c5626b.md @@ -22,7 +22,7 @@ assert(document.querySelector('section')); يجب أن يحتوي العنصر `section` على closing tag. Closing tags لها `/` مباشرة بعد رمز `<`. ```js -assert(code.match(/<\/section\>/)); +assert(code.match(/<\/section\s*>/i)); ``` يجب أن يكون عنصر `section` بأكمله بين علامات فتح وإغلاق عنصر `main`. @@ -57,15 +57,15 @@ assert.isFalse(includesH1); --fcc-editable-region-- -

                                          CatPhotoApp

                                          +

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back. -
                                          + --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07c98cdb9413cbd4b16750.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07c98cdb9413cbd4b16750.md index 8178eb6926131a..6c3f6b34aa8be8 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07c98cdb9413cbd4b16750.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07c98cdb9413cbd4b16750.md @@ -70,7 +70,7 @@ assert(foundElems.length === 2);

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07fb1579dc934717801375.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07fb1579dc934717801375.md index 6e000b5f2a072a..4565aecc6b761c 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07fb1579dc934717801375.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f07fb1579dc934717801375.md @@ -63,7 +63,7 @@ assert($('main > section')[2].children.length === 0);

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          --fcc-editable-region-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d48e7b435f13ab6550051.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d48e7b435f13ab6550051.md index bcb1cfb005dbde..535f4eabcb017c 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d48e7b435f13ab6550051.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d48e7b435f13ab6550051.md @@ -59,7 +59,7 @@ assert(extraSpacesRemoved.match(/Is your cat an indoor or outdoor cat\??$/i));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d4ab1b435f13ab6550052.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d4ab1b435f13ab6550052.md index cc0f08f7eaf8bd..ff46469cfa1892 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d4ab1b435f13ab6550052.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d4ab1b435f13ab6550052.md @@ -81,7 +81,7 @@ assert(fieldsetChildren[0].length > fieldsetChildren[1].length);

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d4d04b435f13ab6550053.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d4d04b435f13ab6550053.md index 606043b40e92e6..cc6d109376fbfa 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d4d04b435f13ab6550053.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f0d4d04b435f13ab6550053.md @@ -65,7 +65,7 @@ assert(

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f1a80975fc4bcae0edb3497.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f1a80975fc4bcae0edb3497.md index c1143257512e18..870c3cac6c5cce 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f1a80975fc4bcae0edb3497.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f1a80975fc4bcae0edb3497.md @@ -65,7 +65,7 @@ assert(outdoorRadioButton.getAttribute('value').match(/^outdoor$/));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.

                                          Cat Lists

                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f1a89f1190aff21ae42105a.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f1a89f1190aff21ae42105a.md index b8b7f8b362b04b..0016f429a90ed9 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f1a89f1190aff21ae42105a.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/5f1a89f1190aff21ae42105a.md @@ -53,7 +53,7 @@ assert(energeticCheckbox.getAttribute('value').match(/^energetic$/));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/62bb4009e3458a128ff57d5d.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/62bb4009e3458a128ff57d5d.md index ca1eac1b69f00b..5364ebdea7cd0b 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/62bb4009e3458a128ff57d5d.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/62bb4009e3458a128ff57d5d.md @@ -55,7 +55,7 @@ assert.notMatch(code, /<\/meta\s*>?/i);

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          @@ -124,7 +124,7 @@ assert.notMatch(code, /<\/meta\s*>?/i);

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/62dabe2ef403a12d5d295273.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/62dabe2ef403a12d5d295273.md index f406df6c95aca1..ad37772915fc43 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/62dabe2ef403a12d5d295273.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/62dabe2ef403a12d5d295273.md @@ -41,14 +41,14 @@ assert( ); ``` -يجب أن يكون محتوى عنصر `p` المرئي في المتصفح `Click here to view more cat photos.` تحقق مرتين من النص أو المسافات أو علامات الترقيم لكل من `p` وعنصر الرابط المدمج. +يجب أن يكون محتوى العنصر `p` المرئي في المتصفح `See more cat photos in our gallery.` أعد التحقق من النص أو المسافات أو علامات الترقيم لكل من `p` وعنصر الرابط داخله. ```js const pText = document .querySelector('p') .innerText.toLowerCase() .replace(/\s+/g, ' '); -assert(pText.match(/click here to view more cat photos\.?$/)); +assert(pText.match(/see more cat photos in our gallery\.?$/)); ``` لا ينبغي أن يكون هناك `cat photos` نص تحت عنصر `p`. @@ -74,7 +74,7 @@ assert(

                                          Cat Photos

                                          --fcc-editable-region-- -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          link to cat pictures --fcc-editable-region-- A cute orange cat lying on its back. diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/7cf9b03d81a65668421804c3.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/7cf9b03d81a65668421804c3.md index 5dbb7fe67f5dc7..d09ea1e3cb4d2e 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/7cf9b03d81a65668421804c3.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-by-building-a-cat-photo-app/7cf9b03d81a65668421804c3.md @@ -62,7 +62,7 @@ assert(!/\<\s*input\s+.*\s*=\s*catphotourl/.test(code));

                                          Cat Photos

                                          -

                                          Click here to view more cat photos.

                                          +

                                          See more cat photos in our gallery.

                                          A cute orange cat lying on its back.
                                          diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60fab9f17fa294054b74228c.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60fab9f17fa294054b74228c.md index 01357b212b3cc6..dc6ed8e31f1ce6 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60fab9f17fa294054b74228c.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60fab9f17fa294054b74228c.md @@ -9,7 +9,7 @@ dashedName: step-31 لننتقل إلى `fieldset` الأخيرة. ماذا لو كنت ترغب في السماح للمستخدم بتحميل صورة الملف الشخصي؟ -حسنًا، `input` من نوع `file` يسمح بذلك. قم بإضافة `label` مع النص `Upload a profile picture:`، وإضافة `input` يقبل تحميل الملف. +حسنًا، `input` من نوع `file` يسمح بذلك. أضف `label` مع النص `Upload a profile picture:`، وإدخال `input` الذي يقبل تحميل الملف. # --hints-- diff --git a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60fad1cafcde010995e15306.md b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60fad1cafcde010995e15306.md index 1312bb86596ca1..094695578c208e 100644 --- a/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60fad1cafcde010995e15306.md +++ b/curriculum/challenges/arabic/14-responsive-web-design-22/learn-html-forms-by-building-a-registration-form/60fad1cafcde010995e15306.md @@ -103,23 +103,23 @@ assert.isNotEmpty(document.querySelector('textarea')?.name); --fcc-editable-region--
                                          - - - - + + + +
                                          -