[
  {
    "path": ".editorconfig",
    "content": "# http://editorconfig.org\nroot = true\n\n[*]\nindent_style = spaces\ntab_width = 2\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[*.js]\nindent_style = spaces\ntab_width = 2\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# Contributing to gitmoji\n\nHello!\n\nThanks for contributing on [gitmoji](https://github.com/carloscuesta/gitmoji). Before implementing new features and changes, please [submit an issue](https://github.com/carloscuesta/gitmoji/issues/new). We will discuss here! :stuck_out_tongue_winking_eye:.\n\nIf you would like to add a new emoji to gitmoji, fill the provided `ISSUE_TEMPLATE` when creating an issue and take a look at the contributing section.\n\n## How to submit a pull request?\n\n1. Fork [this repository](https://github.com/carloscuesta/gitmoji/fork).\n2. Create a new branch with the feature name. (Eg: add-emoji-deploy, fix-website-header)\n3. Make your changes.\n4. Test you changes by running `pnpm turbo test`\n   - 4.1. If the snapshots are failing run `pnpm turbo test -- -u` and be sure that the new snapshots match your changes\n5. Commit your changes. Don't forget to add a commit title with an emoji and a description.\n6. Push your changes.\n7. Submit your pull request.\n\n## How to add a gitmoji\n\n1. Open the **gitmojis.json** file located at `packages/gitmojis/src/gitmojis.json`.\n2. Add your emoji using the following code inside of the `gitmojis array []`:\n3. Add a new color to [the emojiColorsMap.js](https://github.com/carloscuesta/gitmoji/blob/master/packages/website/src/components/GitmojiList/emojiColorsMap.js) file. Matching the name you added at the JSON file.\n4. Save the file and create a pull request.\n\n```json\n{\n  \"emoji\": \"\",\n  \"entity\": \"entity (Ex: &#x1F440)\",\n  \"code\": \":code:\",\n  \"description\": \"Enter the description for the gitmoji. Use present form for verbs.\",\n  \"name\": \"code (same as code but without ':' replace underscores for dashes _ => - )\",\n  \"semver\": \"The semantic versioning effect (can be `'major'`, `'minor'`, `'patch'` or `null` if the commit has no effect on the version)\"\n}\n```\n\nIf you want to find the hexadecimal entity of icon, search for it in this site: <a>http://graphemica.com/</a>\n\nEvery suggestion will be reviewed carefully, ⚠️ take into account that not every suggestion will be accepted!\n\n## How to start the website\n\nIf you want to make changes to the site, follow the next steps:\n\n1. Clone gitmoji\n\n```bash\n$ git clone https://github.com/carloscuesta/gitmoji.git\n$ cd gitmoji\n```\n\n2. Install the dependencies and start the development server.\n\n```bash\n$ pnpm install && pnpm run dev\n```\n\nThe project is built with [Next.js](http://nextjs.org)\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: ['carloscuesta']\ncustom: ['https://paypal.me/carloscuesta']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "content": "name: 🐛 Bug report\ndescription: Report an issue\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report!\n  - type: textarea\n    id: bug-description\n    attributes:\n      label: Describe the bug\n      description: A clear description the bug. If you want to contribute to fix this issue, tell us in the description.\n      placeholder: Description\n    validations:\n      required: true\n  - type: textarea\n    id: reproduction\n    attributes:\n      label: Reproduction\n      description: A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is **required**, otherwise the issue might be closed without further notice.\n      placeholder: Reproduction\n    validations:\n      required: true\n  - type: textarea\n    id: system-info\n    attributes:\n      label: System Info\n      description: Output of `npx envinfo --system --binaries --browsers`\n      render: Shell\n      placeholder: Paste the output of the following command \n    validations:\n      required: true\n  - type: checkboxes\n    id: validations\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Follow our [Code of Conduct](https://github.com/carloscuesta/.github/blob/master/.github/CODE_OF_CONDUCT.md)\n          required: true\n        - label: Read the [Contributing Guide](https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md).\n          required: true\n        - label: Check that there isn't already an issue that reports the same bug to avoid creating duplicates.\n          required: true\n        - label: Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.\n          required: true\n        - label: The provided reproduction is a [minimal reproducible](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: 😍 Contribution Guide\n    url: https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md#contributing-to-gitmoji\n    about: Please read through before making any contribution."
  },
  {
    "path": ".github/ISSUE_TEMPLATE/discussion.yml",
    "content": "name: ⁉️ Discussion\ndescription: Want to discuss something? Use this template\nlabels: [discussion]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for your interest in the project and taking the time to fill out this discussion report!\n  - type: textarea\n    id: discussion-description\n    attributes:\n      label: Discussion\n      description: 'Explain the matter here!'\n    validations:\n      required: true\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Follow our [Code of Conduct](https://github.com/carloscuesta/.github/blob/master/.github/CODE_OF_CONDUCT.md)\n          required: true\n        - label: Read the [Contributing Guide](https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md).\n          required: true\n        - label: Check that there isn't already an issue requesting the same feature.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "content": "name: 🚀 Feature proposal\ndescription: Propose a new feature\nlabels: [feature]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for your interest in the project and taking the time to fill out this feature report!\n  - type: textarea\n    id: feature-description\n    attributes:\n      label: Description of the problem\n      description: 'As a user I want [goal] so that [benefit]. If you want to contribute with a PR, tell us in the description. Thanks!'\n    validations:\n      required: true\n  - type: textarea\n    id: suggested-solution\n    attributes:\n      label: Solution\n      description: 'In module [xy] we could provide following implementation...'\n    validations:\n      required: true\n  - type: textarea\n    id: alternative\n    attributes:\n      label: Alternatives\n      description: Explain any alternative solutions or features you've considered.\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: Additional context\n      description: Any other context or screenshots about the feature.\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Follow our [Code of Conduct](https://github.com/carloscuesta/.github/blob/master/.github/CODE_OF_CONDUCT.md)\n          required: true\n        - label: Read the [Contributing Guide](https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md).\n          required: true\n        - label: Check that there isn't already an issue requesting the same feature.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/gitmoji-proposal.yml",
    "content": "name: 😜 Gitmoji proposal\ndescription: Suggest a new gitmoji!\nlabels: [emoji]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for your interest in the project and taking the time to fill out this gitmoji suggestion!\n  - type: input\n    id: emoji-symbol\n    attributes:\n      label: Emoji symbol\n      description: The emoji symbol you want to suggest.\n      placeholder: \"🚀\"\n    validations:\n      required: true\n  - type: input\n    id: emoji-shortcode\n    attributes:\n      label: Emoji code\n      description: The \":shortcode:\" of the emoji on GitHub.\n      placeholder: \":rocket:\"\n    validations:\n      required: true\n  - type: input\n    id: emoji-description\n    attributes:\n      label: Emoji description\n      description: A short description of the emoji.\n      placeholder: What this emoji should be used for?\n    validations:\n      required: true\n  - type: textarea\n    id: emoji-use-case\n    attributes:\n      label: Describe the use case of your emoji\n      description: Explain the creation of this emoji, what this is and when it should be used\n      placeholder: Use case\n    validations:\n      required: true\n  - type: dropdown\n    id: emoji-use-case-covered\n    attributes:\n      label: Is this use case covered by an existing emoji?\n      options:\n        - \"Yes ✅\"\n        - \"No ❌\"\n    validations:\n      required: true\n  - type: checkboxes\n    id: emoji-what-how\n    attributes:\n      label: Does this emoji fall into the \"how\" or the \"what\" category?\n      description: |\n        We are trying to always describe/categorize \"what\" has been done in a particular commit, not the \"how\" it was done (the exceptions being :poop: and :beers:).\n\n        Notice here that, by the descriptions on the \"how\" category, you can't know what has been achieved in the commit.\n\n        | Examples of \"what\" commits                    | Examples of \"how\" commits                         |\n        | --------------------------                    | -------------------------                         |\n        | :white_check_mark: Add, update, or pass tests | :hankey: Write bad code that needs to be improved |\n        | :lock: Fix security or privacy issues         | :beers: Write code drunkenly                      |\n        | :zap: Improve performance                     | :robot: Write an automated commit by a script     |\n      options:\n        - label: This proposal do **not** describe \"how\" a commit was made, but does in fact describe \"what\" is the contents of the commit about.\n          required: true\n    validations:\n      required: true\n  - type: textarea\n    id: emoji-examples\n    attributes:\n      label: Examples\n      description: Include some examples using this emoji.\n      placeholder: Examples\n    validations:\n      required: true\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Follow our [Code of Conduct](https://github.com/carloscuesta/.github/blob/master/.github/CODE_OF_CONDUCT.md)\n          required: true\n        - label: Read the [Contributing Guide](https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md).\n          required: true\n        - label: Check that there isn't already an issue requesting the emoji.\n          required: true\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nPlease, before opening a PR, first open an issue as stated in the [contributing guidelines][1],\nso we can talk about features and discuss implementations.\n\n[1]: https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md#contributing-to-gitmoji\n-->\n\n## Description\n\n<!-- Explanation about your pull request, what changes you've made -->\n\n## Linked issues\n\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: npm\n  directory: \"/\"\n  schedule:\n    interval: monthly\n    time: \"04:00\"\n  open-pull-requests-limit: 10\n  labels:\n      - \"dependencies\"\n  versioning-strategy: increase\n\n- package-ecosystem: \"github-actions\"\n  directory: \"/\"\n  schedule:\n    interval: monthly\n    time: \"04:00\"\n  labels:\n      - \"dependencies\"\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non:\n  push:\n    branches: [master]\n  pull_request:\n    branches: [master]\njobs:\n  ci:\n    runs-on: ubuntu-latest\n    env:\n      TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}\n      TURBO_TEAM: ${{ secrets.TURBO_TEAM }}\n    steps:\n      - uses: actions/checkout@v6\n      - uses: pnpm/action-setup@v4\n      - name: Install Node.js\n        uses: actions/setup-node@v6\n        with:\n          cache: \"pnpm\"\n          node-version-file: \".node-version\"\n      - name: Install dependencies 📦\n        run: pnpm install\n      - name: Lint 🎨\n        run: pnpm turbo lint\n      - name: TypeScript check 🏷\n        run: pnpm turbo tscheck\n      - name: Tests ✅\n        run: pnpm turbo test\n"
  },
  {
    "path": ".github/workflows/lock.yml",
    "content": "name: Lock Issues and PRs\non:\n  schedule:\n    - cron: '0 0 * * *'\njobs:\n  lock:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: dessant/lock-threads@v6\n        with:\n          github-token: ${{ github.token }}\n          issue-inactive-days: '1'\n          pr-inactive-days: '1'\n"
  },
  {
    "path": ".github/workflows/npm-publish.yml",
    "content": "name: NPM Publish\non:\n  push:\n    tags:\n      - \"v*\"\npermissions:\n  id-token: write\n  contents: write\njobs:\n  npm-publish:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: pnpm/action-setup@v4\n      - uses: actions/setup-node@v6\n        with:\n          cache: \"pnpm\"\n          node-version-file: \".node-version\"\n      - name: Install dependencies 📦\n        run: pnpm install\n      - name: Build 👷‍♂️\n        run: pnpm turbo run build --filter=gitmojis\n      - name: Publish package to NPM 🚀\n        run: pnpm turbo publishPackage\n      - name: Publish GitHub Release 📝\n        uses: softprops/action-gh-release@v2\n        with:\n          name: gitmoji ${{github.ref_name}}\n          generate_release_notes: true\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\ndist/\nnode_modules/\n.publish/\n.next\nout/\ncoverage/\n.eslintcache\n*.log\n.pnp.*\n\n# next-pwa\npackages/website/public/workbox-*.js\npackages/website/public/workbox-*.js\npackages/website/public/sw.js\npackages/website/public/sw.js\npackages/website/public/*.map\n\n# next-sitemap\npackages/website/public/robots.txt\npackages/website/public/sitemap.xml\npackages/website/public/sitemap-*.xml\n\n# gitmojis\npackages/website/public/api/\n\n# TS\n*.tsbuildinfo\n\n# Turbo\n.turbo\n"
  },
  {
    "path": ".husky/.gitignore",
    "content": "_\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "pnpm exec lint-staged\n"
  },
  {
    "path": ".husky/pre-push",
    "content": "pnpm turbo tscheck && pnpm turbo test\n"
  },
  {
    "path": ".lintstagedrc.json",
    "content": "{\n  \"*.json\": [\"prettier --write\"],\n  \"*.md\": [\"prettier --write\"],\n  \"*.yml\": [\"prettier --write\"]\n}\n"
  },
  {
    "path": ".node-version",
    "content": "24\n"
  },
  {
    "path": "AGENTS.md",
    "content": "# Gitmoji Guide for AI Assistants\n\n## Purpose\n\nThis guide helps AI assistants understand and use gitmoji convention when creating commits. Using emojis on commit messages provides an easy way of identifying the purpose or intention of a commit with only looking at the emojis used. Gitmoji use emojis to make commit messages more expressive and easier to understand at a glance.\n\n## Official Specification\n\nA gitmoji commit message is composed using the following pieces:\n\n- **intention**: The intention you want to express with the commit, using an emoji from the gitmoji list. Either in the `:shortcode:` or unicode format.\n- **scope**: An optional string that adds contextual information for the scope of the change.\n- **message**: A brief explanation of the change.\n\n### Format\n\n```\n<intention> [scope?][:?] <message>\n\n[optional body]\n```\n\n## Gitmoji reference\n\nFetch all available gitmojis from: https://gitmoji.dev/api/gitmojis.\n\n## Usage Guidelines for AI\n\n### Selecting the correct emoji\n\n1. **Identify the primary purpose** of the commit\n2. **Choose the most specific emoji** that matches the change\n3. **Use only one emoji** per commit for clarity\n4. **Prioritize by impact**: Breaking changes (💥) > Features (✨) > Fixes (🐛) > Refactoring (♻️)\n\n### Examples\n\n```\n✨ feat: Add user authentication system\n\nImplement JWT-based authentication with login and registration endpoints.\nCloses #123\n```\n\n```\n🐛 Resolve null pointer exception in user service\n\nAdded null check before accessing user properties to prevent crashes.\n```\n\n```\n📝 docs: Update installation instructions\n\nAdded step-by-step guide for setting up the development environment.\n```\n\n```\n⚡️ Optimize user query with indexing\n\nReduced query time from 500ms to 50ms by adding composite index.\n```\n\n```\n💥 Update API response format to REST specification\n\nAll API endpoints now return data in a standardized envelope format.\nClients must update their response parsing logic.\n```\n\n## Best Practices\n\n1. **Be atomic**: One emoji, one purpose, one commit\n2. **Write clear subjects**: Keep under 60 characters, imperative mood\n3. **Use the body**: Explain \"why\" not \"what\" for complex changes\n4. **Reference issues**: Include issue numbers when applicable\n5. **Indicate breaking changes**: Use 💥 `:boom:`.\n\n## Resources\n\n- Gitmojis list: https://gitmoji.dev/api/gitmojis\n- Gitmoji website: https://gitmoji.dev/\n- Gitmoji specification: https://gitmoji.dev/specification\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016-2022 Carlos Cuesta\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n\t<a href=\"https://gitmoji.dev\">\n\t\t<img src=\"https://cloud.githubusercontent.com/assets/7629661/20073135/4e3db2c2-a52b-11e6-85e1-661a8212045a.gif\" width=\"456\" alt=\"gitmoji\">\n\t</a>\n</p>\n<p align=\"center\">\n\t<a href=\"https://github.com/carloscuesta/gitmoji/actions?query=workflow%3ACI+branch%3Amaster\">\n\t\t<img src=\"https://img.shields.io/github/actions/workflow/status/carloscuesta/gitmoji/ci.yml?branch=master&style=flat-square\"\n\t\t\t alt=\"Build Status\">\n\t</a>\n\t<a href=\"https://gitmoji.dev\">\n\t\t<img src=\"https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square\"\n\t\t\t alt=\"Gitmoji\">\n\t</a>\n</p>\n\n## About\n\n[Gitmoji](https://gitmoji.dev) is an initiative to standardize and explain **the use of emojis on GitHub commit messages**.\n\n**Using emojis** on **commit messages** provides an **easy way** of **identifying the purpose or intention of a commit** with only looking at the emojis used. As there are a lot of different emojis I found the need of creating a guide that can help to use emojis easier.\n\nThe gitmojis are published on the [following package](https://www.npmjs.com/package/gitmojis) in order to be used as a dependency 📦.\n\n## Using [gitmoji-cli](https://github.com/carloscuesta/gitmoji-cli)\n\nTo use gitmojis from your command line install [gitmoji-cli](https://github.com/carloscuesta/gitmoji-cli). A gitmoji interactive client for using emojis on commit messages.\n\n```bash\nnpm i -g gitmoji-cli\n```\n\n## Example of usage\n\nIn case you need some ideas to integrate gitmoji in your project, here's a practical way to use it:\n\n```\n<intention> [scope?][:?] <message>\n```\n\n- `intention`: An emoji from the list.\n- `scope`: An optional string that adds contextual information for the scope of the change.\n- `message`: A brief explanation of the change.\n\n## Contributing to gitmoji\n\nContributing to gitmoji is a piece of :cake:, read the [contributing guidelines](https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md). You can discuss emojis using the [issues section](https://github.com/carloscuesta/gitmoji/issues/new). To add a new emoji to the list create an issue and send a pull request, see [how to send a pull request and add a gitmoji](https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md#how-to-add-a-gitmoji).\n\n## Spread the word\n\nAre you using Gitmoji on your project? Set the Gitmoji badge on top of your readme using this code:\n\n```html\n<a href=\"https://gitmoji.dev\">\n  <img\n    src=\"https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square\"\n    alt=\"Gitmoji\"\n  />\n</a>\n```\n\n## License\n\nThe code is available under the [MIT](https://github.com/carloscuesta/gitmoji/blob/master/LICENSE) license.\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"gitmoji\",\n  \"private\": true,\n  \"engines\": {\n    \"node\": \"22\",\n    \"pnpm\": \">=8\"\n  },\n  \"scripts\": {\n    \"prepare\": \"husky install\",\n    \"dev\": \"pnpm turbo --parallel dev\"\n  },\n  \"devDependencies\": {\n    \"husky\": \"^9.1.7\",\n    \"lint-staged\": \"^16.2.7\",\n    \"prettier\": \"3.8.1\",\n    \"turbo\": \"2.8.16\"\n  },\n  \"packageManager\": \"pnpm@8.6.2\"\n}\n"
  },
  {
    "path": "packages/gitmojis/.lintstagedrc.json",
    "content": "{\n  \"./src/*.json\": [\"prettier --write ./src/*.json\"],\n  \"./src/*.ts\": [\"prettier --write ./src/*.ts\"],\n  \"./src/*.js\": [\"prettier --write ./src/*.js\"]\n}\n"
  },
  {
    "path": "packages/gitmojis/README.md",
    "content": "<p align=\"center\">\n\t<a href=\"https://gitmoji.dev\">\n\t\t<img src=\"https://cloud.githubusercontent.com/assets/7629661/20073135/4e3db2c2-a52b-11e6-85e1-661a8212045a.gif\" width=\"456\" alt=\"gitmoji\">\n\t</a>\n</p>\n<p align=\"center\">\n\t<a href=\"https://github.com/carloscuesta/gitmoji/actions?query=workflow%3ACI+branch%3Amaster\">\n\t\t<img src=\"https://img.shields.io/github/actions/workflow/status/carloscuesta/gitmoji/ci.yml?branch=master&style=flat-square\"\n\t\t\t alt=\"Build Status\">\n\t</a>\n\t<a href=\"https://gitmoji.dev\">\n\t\t<img src=\"https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square\"\n\t\t\t alt=\"Gitmoji\">\n\t</a>\n</p>\n\n## About\n\nThe emojis from the [gitmoji](https://gitmoji.dev) convention **bundled** into a **node module**.\n\n## Install\n\n```bash\nnpm i gitmojis\n```\n\n## Usage\n\n```js\nimport { gitmojis } from 'gitmojis'\n\nconsole.log(gitmojis)\n\n/*\n[\n  {\n    emoji: '🎨',\n    entity: '&#x1f3a8;',\n    code: ':art:',\n    description: 'Improve structure / format of the code.',\n    name: 'art',\n    semver: null\n  },\n  {\n    emoji: '⚡️',\n    entity: '&#x26a1;',\n    code: ':zap:',\n    description: 'Improve performance.',\n    name: 'zap',\n    semver: null\n  },\n  ...\n]\n*/\n```\n\n## API\n\nAlternatively you can also consume this as through HTTP using the API:\n  \n```bash\ncurl https://gitmoji.dev/api/gitmojis\n```\n\n## Spread the word\n\nAre you using Gitmoji on your project? Set the Gitmoji badge on top of your readme using this code:\n\n```html\n<a href=\"https://gitmoji.dev\">\n  <img\n    src=\"https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square\"\n    alt=\"Gitmoji\"\n  />\n</a>\n```\n"
  },
  {
    "path": "packages/gitmojis/package.json",
    "content": "{\n  \"name\": \"gitmojis\",\n  \"type\": \"module\",\n  \"version\": \"3.15.0\",\n  \"description\": \"An emoji guide for your commit messages.\",\n  \"main\": \"./dist/index.cjs\",\n  \"types\": \"./dist/index.d.ts\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/index.mjs\",\n      \"require\": \"./dist/index.cjs\"\n    }\n  },\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"dev\": \"nodemon --exec 'pnpm run build' --watch ./src\",\n    \"build\": \"unbuild\",\n    \"lint:json\": \"ajv --spec=draft2020 validate -s ./src/schema.json -d ./src/gitmojis.json\",\n    \"lint\": \"pnpm run lint:json && prettier --check ./src/**/*.{js,json,ts}\",\n    \"publishPackage\": \"npm publish\"\n  },\n  \"devDependencies\": {\n    \"ajv-cli\": \"^5.0.0\",\n    \"lint-staged\": \"^16.2.7\",\n    \"nodemon\": \"^3.1.14\",\n    \"prettier\": \"3.8.1\",\n    \"unbuild\": \"^3.6.1\"\n  },\n  \"author\": {\n    \"name\": \"carloscuesta\",\n    \"email\": \"hi@carloscuesta.me\",\n    \"url\": \"https://carloscuesta.me\"\n  },\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/carloscuesta/gitmoji/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/carloscuesta/gitmoji.git\"\n  },\n  \"homepage\": \"https://gitmoji.dev\",\n  \"keywords\": [\n    \"gitmoji\",\n    \"emoji\",\n    \"carloscuesta\",\n    \"commit\"\n  ],\n  \"prettier\": {\n    \"semi\": false,\n    \"singleQuote\": true,\n    \"arrowParens\": \"always\"\n  }\n}\n"
  },
  {
    "path": "packages/gitmojis/src/gitmojis.json",
    "content": "{\n  \"$schema\": \"https://gitmoji.dev/api/gitmojis/schema\",\n  \"gitmojis\": [\n    {\n      \"emoji\": \"🎨\",\n      \"entity\": \"&#x1f3a8;\",\n      \"code\": \":art:\",\n      \"description\": \"Improve structure / format of the code.\",\n      \"name\": \"art\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"⚡️\",\n      \"entity\": \"&#x26a1;\",\n      \"code\": \":zap:\",\n      \"description\": \"Improve performance.\",\n      \"name\": \"zap\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🔥\",\n      \"entity\": \"&#x1f525;\",\n      \"code\": \":fire:\",\n      \"description\": \"Remove code or files.\",\n      \"name\": \"fire\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🐛\",\n      \"entity\": \"&#x1f41b;\",\n      \"code\": \":bug:\",\n      \"description\": \"Fix a bug.\",\n      \"name\": \"bug\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🚑️\",\n      \"entity\": \"&#128657;\",\n      \"code\": \":ambulance:\",\n      \"description\": \"Critical hotfix.\",\n      \"name\": \"ambulance\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"✨\",\n      \"entity\": \"&#x2728;\",\n      \"code\": \":sparkles:\",\n      \"description\": \"Introduce new features.\",\n      \"name\": \"sparkles\",\n      \"semver\": \"minor\"\n    },\n    {\n      \"emoji\": \"📝\",\n      \"entity\": \"&#x1f4dd;\",\n      \"code\": \":memo:\",\n      \"description\": \"Add or update documentation.\",\n      \"name\": \"memo\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🚀\",\n      \"entity\": \"&#x1f680;\",\n      \"code\": \":rocket:\",\n      \"description\": \"Deploy stuff.\",\n      \"name\": \"rocket\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"💄\",\n      \"entity\": \"&#ff99cc;\",\n      \"code\": \":lipstick:\",\n      \"description\": \"Add or update the UI and style files.\",\n      \"name\": \"lipstick\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🎉\",\n      \"entity\": \"&#127881;\",\n      \"code\": \":tada:\",\n      \"description\": \"Begin a project.\",\n      \"name\": \"tada\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"✅\",\n      \"entity\": \"&#x2705;\",\n      \"code\": \":white_check_mark:\",\n      \"description\": \"Add, update, or pass tests.\",\n      \"name\": \"white-check-mark\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🔒️\",\n      \"entity\": \"&#x1f512;\",\n      \"code\": \":lock:\",\n      \"description\": \"Fix security or privacy issues.\",\n      \"name\": \"lock\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🔐\",\n      \"entity\": \"&#x1f510;\",\n      \"code\": \":closed_lock_with_key:\",\n      \"description\": \"Add or update secrets.\",\n      \"name\": \"closed-lock-with-key\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🔖\",\n      \"entity\": \"&#x1f516;\",\n      \"code\": \":bookmark:\",\n      \"description\": \"Release / Version tags.\",\n      \"name\": \"bookmark\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🚨\",\n      \"entity\": \"&#x1f6a8;\",\n      \"code\": \":rotating_light:\",\n      \"description\": \"Fix compiler / linter warnings.\",\n      \"name\": \"rotating-light\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🚧\",\n      \"entity\": \"&#x1f6a7;\",\n      \"code\": \":construction:\",\n      \"description\": \"Work in progress.\",\n      \"name\": \"construction\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"💚\",\n      \"entity\": \"&#x1f49a;\",\n      \"code\": \":green_heart:\",\n      \"description\": \"Fix CI Build.\",\n      \"name\": \"green-heart\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"⬇️\",\n      \"entity\": \"⬇️\",\n      \"code\": \":arrow_down:\",\n      \"description\": \"Downgrade dependencies.\",\n      \"name\": \"arrow-down\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"⬆️\",\n      \"entity\": \"⬆️\",\n      \"code\": \":arrow_up:\",\n      \"description\": \"Upgrade dependencies.\",\n      \"name\": \"arrow-up\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"📌\",\n      \"entity\": \"&#x1F4CC;\",\n      \"code\": \":pushpin:\",\n      \"description\": \"Pin dependencies to specific versions.\",\n      \"name\": \"pushpin\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"👷\",\n      \"entity\": \"&#x1f477;\",\n      \"code\": \":construction_worker:\",\n      \"description\": \"Add or update CI build system.\",\n      \"name\": \"construction-worker\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"📈\",\n      \"entity\": \"&#x1F4C8;\",\n      \"code\": \":chart_with_upwards_trend:\",\n      \"description\": \"Add or update analytics or track code.\",\n      \"name\": \"chart-with-upwards-trend\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"♻️\",\n      \"entity\": \"&#x267b;\",\n      \"code\": \":recycle:\",\n      \"description\": \"Refactor code.\",\n      \"name\": \"recycle\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"➕\",\n      \"entity\": \"&#10133;\",\n      \"code\": \":heavy_plus_sign:\",\n      \"description\": \"Add a dependency.\",\n      \"name\": \"heavy-plus-sign\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"➖\",\n      \"entity\": \"&#10134;\",\n      \"code\": \":heavy_minus_sign:\",\n      \"description\": \"Remove a dependency.\",\n      \"name\": \"heavy-minus-sign\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🔧\",\n      \"entity\": \"&#x1f527;\",\n      \"code\": \":wrench:\",\n      \"description\": \"Add or update configuration files.\",\n      \"name\": \"wrench\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🔨\",\n      \"entity\": \"&#128296;\",\n      \"code\": \":hammer:\",\n      \"description\": \"Add or update development scripts.\",\n      \"name\": \"hammer\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🌐\",\n      \"entity\": \"&#127760;\",\n      \"code\": \":globe_with_meridians:\",\n      \"description\": \"Internationalization and localization.\",\n      \"name\": \"globe-with-meridians\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"✏️\",\n      \"entity\": \"&#59161;\",\n      \"code\": \":pencil2:\",\n      \"description\": \"Fix typos.\",\n      \"name\": \"pencil2\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"💩\",\n      \"entity\": \"&#58613;\",\n      \"code\": \":poop:\",\n      \"description\": \"Write bad code that needs to be improved.\",\n      \"name\": \"poop\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"⏪️\",\n      \"entity\": \"&#9194;\",\n      \"code\": \":rewind:\",\n      \"description\": \"Revert changes.\",\n      \"name\": \"rewind\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🔀\",\n      \"entity\": \"&#128256;\",\n      \"code\": \":twisted_rightwards_arrows:\",\n      \"description\": \"Merge branches.\",\n      \"name\": \"twisted-rightwards-arrows\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"📦️\",\n      \"entity\": \"&#1F4E6;\",\n      \"code\": \":package:\",\n      \"description\": \"Add or update compiled files or packages.\",\n      \"name\": \"package\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"👽️\",\n      \"entity\": \"&#1F47D;\",\n      \"code\": \":alien:\",\n      \"description\": \"Update code due to external API changes.\",\n      \"name\": \"alien\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🚚\",\n      \"entity\": \"&#1F69A;\",\n      \"code\": \":truck:\",\n      \"description\": \"Move or rename resources (e.g.: files, paths, routes).\",\n      \"name\": \"truck\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"📄\",\n      \"entity\": \"&#1F4C4;\",\n      \"code\": \":page_facing_up:\",\n      \"description\": \"Add or update license.\",\n      \"name\": \"page-facing-up\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"💥\",\n      \"entity\": \"&#x1f4a5;\",\n      \"code\": \":boom:\",\n      \"description\": \"Introduce breaking changes.\",\n      \"name\": \"boom\",\n      \"semver\": \"major\"\n    },\n    {\n      \"emoji\": \"🍱\",\n      \"entity\": \"&#1F371\",\n      \"code\": \":bento:\",\n      \"description\": \"Add or update assets.\",\n      \"name\": \"bento\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"♿️\",\n      \"entity\": \"&#9855;\",\n      \"code\": \":wheelchair:\",\n      \"description\": \"Improve accessibility.\",\n      \"name\": \"wheelchair\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"💡\",\n      \"entity\": \"&#128161;\",\n      \"code\": \":bulb:\",\n      \"description\": \"Add or update comments in source code.\",\n      \"name\": \"bulb\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🍻\",\n      \"entity\": \"&#x1f37b;\",\n      \"code\": \":beers:\",\n      \"description\": \"Write code drunkenly.\",\n      \"name\": \"beers\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"💬\",\n      \"entity\": \"&#128172;\",\n      \"code\": \":speech_balloon:\",\n      \"description\": \"Add or update text and literals.\",\n      \"name\": \"speech-balloon\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🗃️\",\n      \"entity\": \"&#128451;\",\n      \"code\": \":card_file_box:\",\n      \"description\": \"Perform database related changes.\",\n      \"name\": \"card-file-box\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🔊\",\n      \"entity\": \"&#128266;\",\n      \"code\": \":loud_sound:\",\n      \"description\": \"Add or update logs.\",\n      \"name\": \"loud-sound\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🔇\",\n      \"entity\": \"&#128263;\",\n      \"code\": \":mute:\",\n      \"description\": \"Remove logs.\",\n      \"name\": \"mute\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"👥\",\n      \"entity\": \"&#128101;\",\n      \"code\": \":busts_in_silhouette:\",\n      \"description\": \"Add or update contributor(s).\",\n      \"name\": \"busts-in-silhouette\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🚸\",\n      \"entity\": \"&#128696;\",\n      \"code\": \":children_crossing:\",\n      \"description\": \"Improve user experience / usability.\",\n      \"name\": \"children-crossing\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🏗️\",\n      \"entity\": \"&#1f3d7;\",\n      \"code\": \":building_construction:\",\n      \"description\": \"Make architectural changes.\",\n      \"name\": \"building-construction\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"📱\",\n      \"entity\": \"&#128241;\",\n      \"code\": \":iphone:\",\n      \"description\": \"Work on responsive design.\",\n      \"name\": \"iphone\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🤡\",\n      \"entity\": \"&#129313;\",\n      \"code\": \":clown_face:\",\n      \"description\": \"Mock things.\",\n      \"name\": \"clown-face\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🥚\",\n      \"entity\": \"&#129370;\",\n      \"code\": \":egg:\",\n      \"description\": \"Add or update an easter egg.\",\n      \"name\": \"egg\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🙈\",\n      \"entity\": \"&#8bdfe7;\",\n      \"code\": \":see_no_evil:\",\n      \"description\": \"Add or update a .gitignore file.\",\n      \"name\": \"see-no-evil\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"📸\",\n      \"entity\": \"&#128248;\",\n      \"code\": \":camera_flash:\",\n      \"description\": \"Add or update snapshots.\",\n      \"name\": \"camera-flash\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"⚗️\",\n      \"entity\": \"&#x2697;\",\n      \"code\": \":alembic:\",\n      \"description\": \"Perform experiments.\",\n      \"name\": \"alembic\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🔍️\",\n      \"entity\": \"&#128269;\",\n      \"code\": \":mag:\",\n      \"description\": \"Improve SEO.\",\n      \"name\": \"mag\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🏷️\",\n      \"entity\": \"&#127991;\",\n      \"code\": \":label:\",\n      \"description\": \"Add or update types.\",\n      \"name\": \"label\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🌱\",\n      \"entity\": \"&#127793;\",\n      \"code\": \":seedling:\",\n      \"description\": \"Add or update seed files.\",\n      \"name\": \"seedling\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🚩\",\n      \"entity\": \"&#x1F6A9;\",\n      \"code\": \":triangular_flag_on_post:\",\n      \"description\": \"Add, update, or remove feature flags.\",\n      \"name\": \"triangular-flag-on-post\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🥅\",\n      \"entity\": \"&#x1F945;\",\n      \"code\": \":goal_net:\",\n      \"description\": \"Catch errors.\",\n      \"name\": \"goal-net\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"💫\",\n      \"entity\": \"&#x1f4ab;\",\n      \"code\": \":dizzy:\",\n      \"description\": \"Add or update animations and transitions.\",\n      \"name\": \"dizzy\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🗑️\",\n      \"entity\": \"&#x1F5D1;\",\n      \"code\": \":wastebasket:\",\n      \"description\": \"Deprecate code that needs to be cleaned up.\",\n      \"name\": \"wastebasket\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🛂\",\n      \"entity\": \"&#x1F6C2;\",\n      \"code\": \":passport_control:\",\n      \"description\": \"Work on code related to authorization, roles and permissions.\",\n      \"name\": \"passport-control\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🩹\",\n      \"entity\": \"&#x1FA79;\",\n      \"code\": \":adhesive_bandage:\",\n      \"description\": \"Simple fix for a non-critical issue.\",\n      \"name\": \"adhesive-bandage\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🧐\",\n      \"entity\": \"&#x1F9D0;\",\n      \"code\": \":monocle_face:\",\n      \"description\": \"Data exploration/inspection.\",\n      \"name\": \"monocle-face\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"⚰️\",\n      \"entity\": \"&#x26B0;\",\n      \"code\": \":coffin:\",\n      \"description\": \"Remove dead code.\",\n      \"name\": \"coffin\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🧪\",\n      \"entity\": \"&#x1F9EA;\",\n      \"code\": \":test_tube:\",\n      \"description\": \"Add a failing test.\",\n      \"name\": \"test-tube\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"👔\",\n      \"entity\": \"&#128084;\",\n      \"code\": \":necktie:\",\n      \"description\": \"Add or update business logic.\",\n      \"name\": \"necktie\",\n      \"semver\": \"patch\"\n    },\n    {\n      \"emoji\": \"🩺\",\n      \"entity\": \"&#x1FA7A;\",\n      \"code\": \":stethoscope:\",\n      \"description\": \"Add or update healthcheck.\",\n      \"name\": \"stethoscope\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🧱\",\n      \"entity\": \"&#x1f9f1;\",\n      \"code\": \":bricks:\",\n      \"description\": \"Infrastructure related changes.\",\n      \"name\": \"bricks\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🧑‍💻\",\n      \"entity\": \"&#129489;&#8205;&#128187;\",\n      \"code\": \":technologist:\",\n      \"description\": \"Improve developer experience.\",\n      \"name\": \"technologist\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"💸\",\n      \"entity\": \"&#x1F4B8;\",\n      \"code\": \":money_with_wings:\",\n      \"description\": \"Add sponsorships or money related infrastructure.\",\n      \"name\": \"money-with-wings\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🧵\",\n      \"entity\": \"&#x1F9F5;\",\n      \"code\": \":thread:\",\n      \"description\": \"Add or update code related to multithreading or concurrency.\",\n      \"name\": \"thread\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🦺\",\n      \"entity\": \"&#x1F9BA;\",\n      \"code\": \":safety_vest:\",\n      \"description\": \"Add or update code related to validation.\",\n      \"name\": \"safety-vest\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"✈️\",\n      \"entity\": \"&#x2708;\",\n      \"code\": \":airplane:\",\n      \"description\": \"Improve offline support.\",\n      \"name\": \"airplane\",\n      \"semver\": null\n    },\n    {\n      \"emoji\": \"🦖\",\n      \"entity\": \"&#x2708;\",\n      \"code\": \":t-rex:\",\n      \"description\": \"Code that adds backwards compatibility.\",\n      \"name\": \"t-rex\",\n      \"semver\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/gitmojis/src/index.d.ts",
    "content": "declare module 'gitmojis' {\n  type Gitmoji = {\n    /**\n     * Gitmoji unicode character\n     * @example '🎨', '⚡️', '🔥', '🐛'\n     */\n    readonly emoji: string\n    /**\n     * Gitmoji hexadecimal entity.\n     * @example '&#x1f3a8;', '&#x26a1;', '&#x1f525;', '&#x1f41b;'\n     */\n    readonly entity: `&#${string};`\n    /**\n     * Gitmoji use-case description.\n     */\n    readonly description: string\n    /**\n     * Gitmoji name.\n     * @example 'art', 'zap', 'fire', 'bug'\n     */\n    readonly name: string\n    /**\n     * Gitmoji semver range. Can be `null` if not specified.\n     */\n    readonly semver: 'patch' | 'minor' | 'major' | null\n    /**\n     * Gitmoji character formatted as a shortcode.\n     * @example ':art:', ':zap:', ':fire:', ':bug:'\n     */\n    readonly code: `:${string}:`\n  }\n\n  export const gitmojis: readonly Gitmoji[]\n\n  export const schema: readonly any\n}\n"
  },
  {
    "path": "packages/gitmojis/src/index.js",
    "content": "import gitmojisJson from './gitmojis.json' assert { type: 'json' }\n\nexport { default as schema } from './schema.json' assert { type: 'json' }\n\nexport const gitmojis = gitmojisJson.gitmojis\n"
  },
  {
    "path": "packages/gitmojis/src/schema.json",
    "content": "{\n  \"type\": \"object\",\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"required\": [\"gitmojis\"],\n  \"properties\": {\n    \"gitmojis\": {\n      \"type\": \"array\",\n      \"minItems\": 1,\n      \"uniqueItems\": true,\n      \"items\": {\n        \"type\": \"object\",\n        \"required\": [\n          \"emoji\",\n          \"entity\",\n          \"code\",\n          \"description\",\n          \"name\",\n          \"semver\"\n        ],\n        \"properties\": {\n          \"code\": {\n            \"type\": \"string\"\n          },\n          \"entity\": {\n            \"type\": \"string\"\n          },\n          \"description\": {\n            \"type\": \"string\"\n          },\n          \"emoji\": {\n            \"type\": \"string\"\n          },\n          \"name\": {\n            \"type\": \"string\"\n          },\n          \"semver\": {\n            \"enum\": [\"major\", \"minor\", \"patch\", null]\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/website/.lintstagedrc.json",
    "content": "{\n  \"./src/**/*.{ts,tsx,css}\": [\n    \"eslint --cache --fix\",\n    \"prettier --write ./src/**/*.{ts,tsx,css}\"\n  ]\n}\n"
  },
  {
    "path": "packages/website/__mocks__/svg.js",
    "content": "module.exports = 'svg-mock'\n"
  },
  {
    "path": "packages/website/eslint.config.mjs",
    "content": "import { FlatCompat } from '@eslint/eslintrc'\nimport js from '@eslint/js'\nimport typescriptParser from '@typescript-eslint/parser'\nimport typescriptPlugin from '@typescript-eslint/eslint-plugin'\nimport reactPlugin from 'eslint-plugin-react'\nimport importPlugin from 'eslint-plugin-import'\nimport nextPlugin from '@next/eslint-plugin-next'\nimport prettierConfig from 'eslint-config-prettier'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\nconst compat = new FlatCompat({\n  baseDirectory: __dirname,\n})\n\nexport default [\n  js.configs.recommended,\n  ...compat.extends('plugin:@typescript-eslint/recommended'),\n  prettierConfig,\n  {\n    files: ['**/*.{js,mjs,cjs,ts,tsx}'],\n    languageOptions: {\n      parser: typescriptParser,\n      parserOptions: {\n        ecmaVersion: 12,\n        sourceType: 'module',\n        ecmaFeatures: {\n          jsx: true,\n        },\n      },\n      globals: {\n        React: 'readonly',\n        JSX: 'readonly',\n        window: 'readonly',\n        document: 'readonly',\n        navigator: 'readonly',\n        console: 'readonly',\n        process: 'readonly',\n        __dirname: 'readonly',\n        __filename: 'readonly',\n        module: 'readonly',\n        require: 'readonly',\n        jest: 'readonly',\n        describe: 'readonly',\n        it: 'readonly',\n        test: 'readonly',\n        expect: 'readonly',\n        beforeAll: 'readonly',\n        beforeEach: 'readonly',\n        afterAll: 'readonly',\n        afterEach: 'readonly',\n      },\n    },\n    plugins: {\n      '@typescript-eslint': typescriptPlugin,\n      react: reactPlugin,\n      import: importPlugin,\n      '@next/next': nextPlugin,\n    },\n    settings: {\n      react: {\n        version: 'detect',\n      },\n      'import/resolver': {\n        typescript: true,\n        node: true,\n        alias: {\n          map: [['src', './src']],\n        },\n      },\n    },\n    rules: {\n      'react/react-in-jsx-scope': 'off',\n      '@next/next/no-img-element': 'off',\n      'react/no-unknown-property': [\n        'error',\n        {\n          ignore: ['jsx', 'global'],\n        },\n      ],\n      'import/order': [\n        'error',\n        {\n          groups: [\n            ['builtin', 'external'],\n            ['internal', 'parent', 'sibling', 'index'],\n          ],\n          'newlines-between': 'always',\n        },\n      ],\n    },\n  },\n]\n"
  },
  {
    "path": "packages/website/jest.config.js",
    "content": "const nextJest = require('next/jest')\n\nconst createJestConfig = nextJest({ dir: './' })\n\nasync function jestConfig() {\n  const nextJestConfig = await createJestConfig({\n    \"collectCoverageFrom\": [\n      \"src/**/*.{ts,tsx}\",\n    ],\n    \"testMatch\": [\n      \"**/*.(spec).(ts)\",\n      \"**/*.(spec).(tsx)\"\n    ],\n    \"moduleNameMapper\": {\n      \"src/(.*)$\": \"<rootDir>/src/$1\",\n      \"\\\\.svg$\": \"<rootDir>/__mocks__/svg.js\"\n    },\n    \"testEnvironment\": \"jsdom\",\n    \"setupFilesAfterEnv\": [\"<rootDir>/jest.setup.js\"],\n    \"reporters\": [\n      \"default\",\n      \"github-actions\"\n    ]\n  })()\n\n  // Add ignores for specific ESM packages so they are transformed by Jest\n  // See: https://github.com/vercel/next.js/issues/35634\n  nextJestConfig.transformIgnorePatterns[0] = '/node_modules/(!@vercel/analytics)/'\n\n  return nextJestConfig\n}\n\nmodule.exports = jestConfig\n"
  },
  {
    "path": "packages/website/jest.d.ts",
    "content": "/// <reference types=\"@testing-library/jest-dom\" />\n"
  },
  {
    "path": "packages/website/jest.setup.js",
    "content": "import '@testing-library/jest-dom'\nimport React from 'react'\n\n// Mock next/dynamic to load components synchronously in tests\njest.mock('next/dynamic', () => ({\n  __esModule: true,\n  default: (...args) => {\n    const dynamicModule = jest.requireActual('next/dynamic')\n    const dynamicActualComp = dynamicModule.default\n    const RequiredComponent = dynamicActualComp(args[0])\n    RequiredComponent.preload ? RequiredComponent.preload() : RequiredComponent.render.preload()\n    return RequiredComponent\n  },\n}))\n\n// Mock matchMedia for components that use it\nObject.defineProperty(window, 'matchMedia', {\n  writable: true,\n  value: jest.fn().mockImplementation((query) => ({\n    matches: false,\n    media: query,\n    onchange: null,\n    addListener: jest.fn(),\n    removeListener: jest.fn(),\n    addEventListener: jest.fn(),\n    removeEventListener: jest.fn(),\n    dispatchEvent: jest.fn(),\n  })),\n})\n\n// Silence known React/JSDOM warnings in tests that don't affect functionality\nconst originalError = console.error\nbeforeAll(() => {\n  console.error = (...args) => {\n    // Suppress SVG element warnings - these are JSDOM limitations, not actual errors\n    // The SVG elements work fine in real browsers\n    if (\n      typeof args[0] === 'string' &&\n      (args[0].includes('The tag <') && args[0].includes('is unrecognized in this browser'))\n    ) {\n      return\n    }\n    originalError.call(console, ...args)\n  }\n})\n\nafterAll(() => {\n  console.error = originalError\n})\n\n// Mock SVG namespace attributes for JSDOM\n// JSDOM doesn't fully support SVG namespaced attributes like xlink:href\nconst originalCreateElement = document.createElement.bind(document)\nconst originalCreateElementNS = document.createElementNS.bind(document)\n\ndocument.createElement = function (tagName, options) {\n  const element = originalCreateElement(tagName, options)\n  if (tagName.toLowerCase() === 'svg') {\n    element.setAttribute = function (name, value) {\n      if (name === 'xlinkHref') {\n        this.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', value)\n      } else {\n        Element.prototype.setAttribute.call(this, name, value)\n      }\n    }\n  }\n  return element\n}\n\ndocument.createElementNS = function (namespaceURI, qualifiedName) {\n  const element = originalCreateElementNS(namespaceURI, qualifiedName)\n  if (namespaceURI === 'http://www.w3.org/2000/svg') {\n    element.setAttribute = function (name, value) {\n      if (name === 'xlinkHref') {\n        this.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', value)\n      } else {\n        Element.prototype.setAttribute.call(this, name, value)\n      }\n    }\n  }\n  return element\n}\n"
  },
  {
    "path": "packages/website/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\"\n  }\n}\n"
  },
  {
    "path": "packages/website/next-env.d.ts",
    "content": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\nimport \"./.next/types/routes.d.ts\";\n\n// NOTE: This file should not be edited\n// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.\n"
  },
  {
    "path": "packages/website/next-sitemap.config.js",
    "content": "/** @type {import('next-sitemap').IConfig} */\nmodule.exports = {\n  siteUrl: 'https://gitmoji.dev',\n  generateRobotsTxt: true,\n}\n"
  },
  {
    "path": "packages/website/next-sitemap.js",
    "content": "module.exports = {\n  siteUrl: 'https://gitmoji.dev',\n  generateRobotsTxt: true,\n}\n"
  },
  {
    "path": "packages/website/next.config.js",
    "content": "module.exports = {\n  reactStrictMode: true,\n  output: 'export',\n}\n"
  },
  {
    "path": "packages/website/package.json",
    "content": "{\n  \"name\": \"website\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"engines\": {\n    \"node\": \"24\"\n  },\n  \"scripts\": {\n    \"build\": \"node scripts/generate-api.js && next build && next-sitemap\",\n    \"tscheck\": \"pnpm exec tsc --noEmit\",\n    \"dev\": \"next dev\",\n    \"lint\": \"eslint ./src && prettier --check ./src/**/*.{ts,tsx,css}\",\n    \"start\": \"next start\",\n    \"test\": \"FORCE_COLOR=1 jest --coverage\"\n  },\n  \"devDependencies\": {\n    \"@eslint/eslintrc\": \"3.3.3\",\n    \"@eslint/js\": \"9.39.2\",\n    \"@next/eslint-plugin-next\": \"16.1.6\",\n    \"@testing-library/jest-dom\": \"6.9.1\",\n    \"@testing-library/react\": \"16.3.2\",\n    \"@testing-library/user-event\": \"14.6.1\",\n    \"@types/fetch-mock\": \"^7.3.8\",\n    \"@types/jest\": \"^29.5.14\",\n    \"@types/react\": \"^19.2.14\",\n    \"@typescript-eslint/eslint-plugin\": \"^8.52.0\",\n    \"@typescript-eslint/parser\": \"^8.53.0\",\n    \"clipboard\": \"^2.0.11\",\n    \"eslint\": \"^9.39.2\",\n    \"eslint-config-next\": \"^16.1.6\",\n    \"eslint-config-prettier\": \"^10.1.8\",\n    \"eslint-import-resolver-alias\": \"^1.1.2\",\n    \"eslint-import-resolver-typescript\": \"^4.4.4\",\n    \"eslint-plugin-import\": \"^2.32.0\",\n    \"eslint-plugin-jest\": \"^29.12.1\",\n    \"eslint-plugin-react\": \"^7.37.5\",\n    \"focus-trap-react\": \"^12.0.0\",\n    \"gitmojis\": \"workspace:*\",\n    \"jest\": \"^29.7.0\",\n    \"jest-environment-jsdom\": \"^30.2.0\",\n    \"jest-fetch-mock\": \"^3.0.3\",\n    \"lint-staged\": \"^16.2.7\",\n    \"next\": \"^16.1.6\",\n    \"next-sitemap\": \"^4.2.3\",\n    \"next-themes\": \"^0.4.6\",\n    \"node-mocks-http\": \"^1.17.2\",\n    \"prettier\": \"3.8.1\",\n    \"prop-types\": \"^15.8.1\",\n    \"react\": \"^19.2.4\",\n    \"react-dom\": \"^19.2.4\",\n    \"react-hot-toast\": \"^2.5.2\",\n    \"typescript\": \"^5.9.3\"\n  },\n  \"author\": {\n    \"name\": \"carloscuesta\",\n    \"email\": \"hi@carloscuesta.me\",\n    \"url\": \"https://carloscuesta.me\"\n  },\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/carloscuesta/gitmoji/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/carloscuesta/gitmoji.git\"\n  },\n  \"homepage\": \"https://gitmoji.dev\",\n  \"keywords\": [\n    \"gitmoji\",\n    \"emoji\",\n    \"carloscuesta\",\n    \"commit\"\n  ],\n  \"prettier\": {\n    \"semi\": false,\n    \"singleQuote\": true,\n    \"arrowParens\": \"always\"\n  }\n}\n"
  },
  {
    "path": "packages/website/public/_redirects",
    "content": "/api/gitmojis  /api/gitmojis/index.json  200\n"
  },
  {
    "path": "packages/website/public/static/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig><msapplication><tile><square70x70logo src=\"/static/ms-icon-70x70.png\"/><square150x150logo src=\"/static/ms-icon-150x150.png\"/><square310x310logo src=\"/static/ms-icon-310x310.png\"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>\n"
  },
  {
    "path": "packages/website/public/static/manifest.json",
    "content": "{\n  \"name\": \"Gitmoji\",\n  \"display\": \"minimal-ui\",\n  \"start_url\": \"/\",\n  \"theme_color\": \"#FFDD67\",\n  \"background_color\": \"#FFF\",\n  \"icons\": [\n    {\n      \"src\": \"/static/android-icon-36x36.png\",\n      \"sizes\": \"36x36\",\n      \"type\": \"image/png\",\n      \"density\": \"0.75\"\n    },\n    {\n      \"src\": \"/static/android-icon-48x48.png\",\n      \"sizes\": \"48x48\",\n      \"type\": \"image/png\",\n      \"density\": \"1.0\"\n    },\n    {\n      \"src\": \"/static/android-icon-72x72.png\",\n      \"sizes\": \"72x72\",\n      \"type\": \"image/png\",\n      \"density\": \"1.5\"\n    },\n    {\n      \"src\": \"/static/android-icon-96x96.png\",\n      \"sizes\": \"96x96\",\n      \"type\": \"image/png\",\n      \"density\": \"2.0\"\n    },\n    {\n      \"src\": \"/static/android-icon-144x144.png\",\n      \"sizes\": \"144x144\",\n      \"type\": \"image/png\",\n      \"density\": \"3.0\"\n    },\n    {\n      \"src\": \"/static/android-icon-192x192.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\",\n      \"density\": \"4.0\"\n    },\n    {\n      \"src\": \"/static/android-icon-512x512.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\",\n      \"density\": \"4.0\"\n    },\n    {\n      \"src\": \"/static/maskable_icon.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\",\n      \"purpose\": \"maskable\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/website/public/static/opensearchdescription.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\">\n  <ShortName>Gitmoji</ShortName>\n  <Description>An emoji guide for your commit messages.</Description>\n  <Tags>gitmoji emoji git</Tags>\n  <Image height=\"16\" width=\"16\" type=\"image/png\">https://gitmoji.dev/static/favicon-16x16.png</Image>\n  <Image height=\"32\" width=\"32\" type=\"image/png\">https://gitmoji.dev/static/favicon-32x32.png</Image>\n  <Image height=\"96\" width=\"96\" type=\"image/png\">https://gitmoji.dev/static/favicon-96x96.png</Image>\n  <Url type=\"text/html\" template=\"https://gitmoji.dev/?search={searchTerms}\"/>\n</OpenSearchDescription>\n"
  },
  {
    "path": "packages/website/scripts/generate-api.js",
    "content": "const { gitmojis } = require('gitmojis')\nconst fs = require('fs')\nconst path = require('path')\n\nconst outputDir = path.join(__dirname, '../public/api/gitmojis')\nfs.mkdirSync(outputDir, { recursive: true })\nfs.writeFileSync(\n  path.join(outputDir, 'index.json'),\n  JSON.stringify({ gitmojis }, null, 2)\n)\n\nconsole.log('Generated static API at public/api/gitmojis/index.json')\n"
  },
  {
    "path": "packages/website/src/__tests__/pages.spec.tsx",
    "content": "import { render, screen } from '@testing-library/react'\n\nimport RootLayout from '../app/layout'\nimport Home from '../app/page'\nimport About from '../app/about/page'\nimport Specification from '../app/specification/page'\nimport RelatedTools from '../app/related-tools/page'\n\njest.mock('next/navigation', () => ({\n  useRouter: jest.fn(() => ({\n    push: jest.fn(),\n    replace: jest.fn(),\n    prefetch: jest.fn(),\n  })),\n  useSearchParams: jest.fn(() => new URLSearchParams()),\n  usePathname: jest.fn(() => '/'),\n}))\n\njest.mock('next-themes', () => ({\n  ThemeProvider: ({ children }: { children: React.ReactNode }) => (\n    <div>{children}</div>\n  ),\n  useTheme: jest.fn(() => ({\n    resolvedTheme: 'light',\n    setTheme: jest.fn(),\n  })),\n}))\n\ndescribe('Pages', () => {\n  beforeAll(() => {\n    Math.random = jest.fn().mockReturnValue(1)\n  })\n\n  describe('RootLayout', () => {\n    it('should include theme provider and layout wrapper', () => {\n      expect(RootLayout).toBeDefined()\n      expect(typeof RootLayout).toBe('function')\n    })\n  })\n\n  describe('Home', () => {\n    it('should render the page', () => {\n      const { container } = render(<Home />)\n      expect(container.firstChild).toBeInTheDocument()\n    })\n  })\n\n  describe('About', () => {\n    it('should render the page with about content', () => {\n      render(<About />)\n      expect(screen.getByText(/About/i)).toBeInTheDocument()\n    })\n  })\n\n  describe('Specification', () => {\n    it('should render the page with specification content', () => {\n      render(<Specification />)\n      const heading = screen.getByRole('heading', {\n        name: /Specification/i,\n        level: 1,\n      })\n      expect(heading).toBeInTheDocument()\n    })\n  })\n\n  describe('Related tools', () => {\n    it('should render the page', () => {\n      render(<RelatedTools />)\n      expect(screen.getByText(/Related Tools/i)).toBeInTheDocument()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/website/src/__tests__/stubs.tsx",
    "content": "export const appProps = {\n  Component: (props: object) => <div {...props}>Component</div>,\n  pageProps: { test: '' },\n}\n\nexport const contributors = [\n  {\n    url: 'https://github.com/profile',\n    avatar: 'https://github.com/avatar',\n    id: 'contributor-id-123',\n  },\n]\n\nexport const contributorsMock = [\n  {\n    html_url: 'https://github.com/profile',\n    avatar_url: 'https://github.com/avatar',\n    id: 'contributor-id-123',\n    login: 'carloscuesta',\n  },\n]\n"
  },
  {
    "path": "packages/website/src/app/about/page.tsx",
    "content": "import type { Metadata } from 'next'\nimport Link from 'next/link'\n\nimport CarbonAd from 'src/components/CarbonAd'\n\nexport const metadata: Metadata = {\n  title: 'gitmoji | About | An emoji guide for your commit messages',\n  alternates: {\n    canonical: '/about',\n  },\n}\n\nexport default function About() {\n  return (\n    <main>\n      <CarbonAd />\n      <section>\n        <h1>About</h1>\n\n        <p>\n          <strong>Gitmoji is an emoji guide for GitHub commit messages</strong>.\n          Aims to be a standarization cheatsheet - guide for using emojis on\n          GitHub&#39;s commit messages.\n        </p>\n\n        <p>\n          <strong>Using emojis</strong> on <strong>commit messages</strong>{' '}\n          provides an <strong>easy way</strong> of{' '}\n          <strong>identifying the purpose or intention of a commit</strong> with\n          only looking at the emojis used. As there are a lot of different\n          emojis I found the need of creating a guide that can help to use\n          emojis easier.\n        </p>\n\n        <p>\n          This project is Open Source, that means everyone can participate,\n          suggesting, discussing and adding new emojis. Take a look at the{' '}\n          <Link href=\"#contributing-gitmoji\">contributing section</Link> and{' '}\n          <a href=\"https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md\">\n            guidelines for contributing\n          </a>\n          .\n        </p>\n      </section>\n\n      <section>\n        <h1>\n          Using gitmoji with{' '}\n          <a href=\"https://github.com/carloscuesta/gitmoji-cli\">gitmoji-cli</a>\n        </h1>\n\n        <p>\n          An easy solution for using gitmoji from your command line, is to\n          install{' '}\n          <a href=\"https://github.com/carloscuesta/gitmoji-cli\">gitmoji-cli</a>.\n          A gitmoji interactive client for using emojis on commit messages.\n        </p>\n\n        <pre className=\"overflow-x-adjust\">\n          <code>$ npm i -g gitmoji-cli</code>\n        </pre>\n      </section>\n\n      <section>\n        <h1 id=\"specification\">Specification</h1>\n\n        <p>\n          To understand how to use gitmoji properly, please check the official\n          specification <Link href=\"/specification\">here</Link> 👈.\n        </p>\n      </section>\n\n      <section>\n        <h1 id=\"contributing-gitmoji\">Contributing to gitmoji</h1>\n\n        <p>\n          Contributing to gitmoji is a piece of 🍰! This project is a static\n          website built with <i>Next.js</i>. All the gitmojis displayed are\n          rendered from a JSON file. Before submitting any pull request, please\n          follow these steps:\n        </p>\n\n        <ol>\n          <li>\n            <a href=\"https://github.com/carloscuesta/gitmoji/issues/new\">\n              Create an issue\n            </a>{' '}\n            filling the template.\n          </li>\n          <li>\n            After discussing the idea, feature or suggestion,{' '}\n            <a href=\"https://github.com/carloscuesta/gitmoji/blob/master/.github/CONTRIBUTING.md\">\n              read the contribution docs.\n            </a>\n          </li>\n          <li>\n            <a href=\"https://github.com/carloscuesta/gitmoji/fork\">\n              Create a fork{' '}\n            </a>\n            of gitmoji.\n          </li>\n          <li>\n            Create a new branch with the feature name. (Eg: add-emoji-deploy,\n            fix-website-header)\n          </li>\n          <li>\n            Make your changes and send a{' '}\n            <a href=\"https://help.github.com/articles/creating-a-pull-request/\">\n              pull request{' '}\n            </a>\n            .\n          </li>\n        </ol>\n      </section>\n    </main>\n  )\n}\n"
  },
  {
    "path": "packages/website/src/app/contributors/page.tsx",
    "content": "import type { Metadata } from 'next'\n\nimport ContributorsList from 'src/components/ContributorsList'\nimport CarbonAd from 'src/components/CarbonAd'\n\nexport const metadata: Metadata = {\n  title: 'gitmoji | Contributors | An emoji guide for your commit messages',\n  alternates: {\n    canonical: '/contributors',\n  },\n}\n\ntype Contributor = {\n  avatar: string\n  id: string\n  url: string\n}\n\ntype GitHubContributor = {\n  avatar_url: string\n  id: string\n  html_url: string\n  login: string\n}\n\nasync function getContributors(): Promise<Contributor[]> {\n  const response = await fetch(\n    'https://api.github.com/repos/carloscuesta/gitmoji/contributors',\n    { next: { revalidate: 3600 * 3 } },\n  )\n  const contributors: GitHubContributor[] = await response.json()\n\n  return contributors\n    .filter((contributor) => !contributor.login.includes('bot'))\n    .map((contributor) => ({\n      avatar: contributor.avatar_url,\n      id: contributor.id,\n      url: contributor.html_url,\n    }))\n}\n\nexport default async function Contributors() {\n  const contributors = await getContributors()\n\n  return (\n    <main>\n      <CarbonAd />\n      <section>\n        <h1>Contributors</h1>\n\n        <ContributorsList contributors={contributors} />\n      </section>\n    </main>\n  )\n}\n"
  },
  {
    "path": "packages/website/src/app/layout.tsx",
    "content": "import type { Metadata } from 'next'\nimport { ThemeProvider } from 'next-themes'\n\nimport Layout from 'src/components/Layout'\nimport 'src/utils/theme/theme.css'\n\nexport const metadata: Metadata = {\n  title: 'gitmoji | An emoji guide for your commit messages',\n  description:\n    \"Gitmoji is an emoji guide for your commit messages. Aims to be a standarization cheatsheet for using emojis on GitHub's commit messages.\",\n  authors: [{ name: 'Carlos Cuesta', url: 'https://carloscuesta.me' }],\n  keywords: ['gitmoji', 'emoji', 'carloscuesta', 'commit'],\n  metadataBase: new URL('https://gitmoji.dev'),\n  alternates: {\n    canonical: '/',\n  },\n  robots: 'index, follow',\n  openGraph: {\n    title: 'gitmoji',\n    description: 'An emoji guide for your commit messages.',\n    url: 'https://gitmoji.dev',\n    images: [\n      {\n        url: 'https://gitmoji.dev/static/gitmoji.gif',\n      },\n    ],\n  },\n  twitter: {\n    card: 'summary',\n    title: 'gitmoji',\n    description: 'An emoji guide for your commit messages.',\n    creator: '@crloscuesta',\n    images: ['https://gitmoji.dev/static/gitmoji.gif'],\n  },\n  icons: {\n    icon: [\n      { url: '/static/favicon-16x16.png', sizes: '16x16', type: 'image/png' },\n      { url: '/static/favicon-32x32.png', sizes: '32x32', type: 'image/png' },\n      { url: '/static/favicon-96x96.png', sizes: '96x96', type: 'image/png' },\n      {\n        url: '/static/android-icon-192x192.png',\n        sizes: '192x192',\n        type: 'image/png',\n      },\n    ],\n    apple: [\n      { url: '/static/apple-icon-57x57.png', sizes: '57x57' },\n      { url: '/static/apple-icon-60x60.png', sizes: '60x60' },\n      { url: '/static/apple-icon-72x72.png', sizes: '72x72' },\n      { url: '/static/apple-icon-76x76.png', sizes: '76x76' },\n      { url: '/static/apple-icon-114x114.png', sizes: '114x114' },\n      { url: '/static/apple-icon-120x120.png', sizes: '120x120' },\n      { url: '/static/apple-icon-144x144.png', sizes: '144x144' },\n      { url: '/static/apple-icon-152x152.png', sizes: '152x152' },\n      { url: '/static/apple-icon-180x180.png', sizes: '180x180' },\n    ],\n  },\n  manifest: '/static/manifest.json',\n  other: {\n    'msapplication-TileColor': '#FFDD67',\n    'msapplication-TileImage': '/ms-icon-144x144.png',\n    'google-site-verification': '78vmlhi_erc-UGybxcGwHyiUtf04wzYExTLa-4LoWio',\n  },\n}\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode\n}) {\n  return (\n    <html lang=\"en\" suppressHydrationWarning>\n      <head>\n        <meta name=\"theme-color\" content=\"#FFDD67\" />\n        <link\n          rel=\"search\"\n          type=\"application/opensearchdescription+xml\"\n          href=\"/static/opensearchdescription.xml\"\n        />\n        <script\n          type=\"text/javascript\"\n          dangerouslySetInnerHTML={{\n            __html: `(function(a,e,f,g,b,c,d){a.GoogleAnalyticsObject=b;a[b]=a[b]||function(){(a[b].q=a[b].q||[]).push(arguments)};a[b].l=1*new Date;c=e.createElement(f);d=e.getElementsByTagName(f)[0];c.async=1;c.src=g;d.parentNode.insertBefore(c,d)})(window,document,\"script\",\"//www.google-analytics.com/analytics.js\",\"ga\");ga(\"create\",\"UA-67824860-7\",\"auto\");ga(\"send\",\"pageview\");`,\n          }}\n        />\n      </head>\n      <body>\n        <ThemeProvider attribute=\"data-theme\" defaultTheme=\"light\">\n          <Layout>{children}</Layout>\n        </ThemeProvider>\n      </body>\n    </html>\n  )\n}\n"
  },
  {
    "path": "packages/website/src/app/page.tsx",
    "content": "import { Toaster } from 'react-hot-toast'\nimport { gitmojis } from 'gitmojis'\n\nimport GitmojiList from 'src/components/GitmojiList'\nimport CarbonAd from 'src/components/CarbonAd'\n\nexport default function Home() {\n  return (\n    <main>\n      <CarbonAd />\n      <GitmojiList gitmojis={gitmojis} />\n      <Toaster position=\"top-left\" />\n    </main>\n  )\n}\n"
  },
  {
    "path": "packages/website/src/app/related-tools/page.tsx",
    "content": "import type { Metadata } from 'next'\n\nimport CarbonAd from 'src/components/CarbonAd'\n\nexport const metadata: Metadata = {\n  title: 'gitmoji | Related tools | An emoji guide for your commit messages',\n  alternates: {\n    canonical: '/related-tools',\n  },\n}\n\nconst tools = [\n  {\n    name: 'gitmoji-changelog',\n    description: 'A changelog generator for gitmoji.',\n    link: 'https://github.com/frinyvonnick/gitmoji-changelog/',\n  },\n  {\n    name: 'gitmemoji',\n    description: 'A game to learn gitmojis.',\n    link: 'https://github.com/ImBIOS/gitmemoji/',\n  },\n  {\n    name: 'gitmoji-browser-extension',\n    description: 'The Gitmoji extension to easily search and copy gitmojis.',\n    link: 'https://github.com/johannchopin/gitmoji-browser-extension',\n  },\n  {\n    name: 'gitmoji-vscode',\n    description: 'Gitmoji tool for git commit messages in VS Code',\n    link: 'https://github.com/seatonjiang/gitmoji-vscode',\n  },\n  {\n    name: 'gitmoji-intellij-plugin',\n    description:\n      'A Jetbrains suite plugin to easily add gitmoji when committing',\n    link: 'https://plugins.jetbrains.com/plugin/12383-gitmoji-plus-commit-button',\n  },\n  {\n    name: 'gitmoji-sublimetext',\n    description: 'A Sublime Text plugin to add emojis in git commit messages.',\n    link: 'https://packagecontrol.io/packages/Gitmoji',\n  },\n  {\n    name: 'gitimoji',\n    description: 'A Gitmoji App for macOS.',\n    link: 'https://github.com/TimoZacherl/gitimoji',\n  },\n  {\n    name: 'gitmoji-atom',\n    description: 'Gitmoji for Atom',\n    link: 'https://github.com/ThatXliner/gitmoji-atom',\n  },\n  {\n    name: 'gitmoji-regex',\n    description: 'A Gitmoji::Regex for Ruby.',\n    link: 'https://github.com/pboling/gitmoji-regex',\n  },\n  {\n    name: 'traymoji',\n    description: 'A Electron Tray App for Gitmojis',\n    link: 'https://github.com/CoenWarmer/traymoji',\n  },\n  {\n    name: 'alfred-gitmoji',\n    description: 'Gitmoji Workflow for Alfred',\n    link: 'https://github.com/techouse/alfred-gitmoji',\n  },\n  {\n    name: 'gitmojiapp',\n    description: 'A Flutter Gitmoji App for macOS, Linux, and Windows',\n    link: 'https://github.com/patrick-fu/GitmojiApp',\n  },\n  {\n    name: 'githubmoji',\n    description:\n      'A Firefox addon that adds a predictive gitmoji picker to GitHub commit message inputs.',\n    link: 'https://github.com/ma1ted/githubmoji',\n  },\n  {\n    name: 'gitmoji-changelog-action',\n    description: 'GitHub Action for gitmoji-changelog',\n    link: 'https://github.com/sercanuste/gitmoji-changelog-action',\n  },\n  {\n    name: 'raycast-gitmoji-search',\n    description: 'Gitmoji extension for Raycast',\n    link: 'https://www.raycast.com/ricoberger/gitmoji',\n  },\n  {\n    name: 'gitmoji-fuzzy-hook',\n    description:\n      'Fuzzy finder git-commit-hook for prepending a gitmoji (cmd & GUI).',\n    link: 'https://gitlab.com/raabf/gitmoji-fuzzy-hook',\n  },\n  {\n    name: 'genmoji',\n    description: 'Gitmoji commit message generation using AI',\n    link: 'https://github.com/segersniels/genmoji',\n  },\n  {\n    name: 'gitmoji-plus-flow-launcher',\n    description: 'A flow launcher plugin to search and copy gitmojis',\n    link: 'https://github.com/tho-myr/Flow.Launcher.Plugin.Gitmoji_Plus',\n  },\n]\n\nexport default function RelatedTools() {\n  return (\n    <main>\n      <CarbonAd />\n      <section>\n        <h1>Related tools</h1>\n\n        <p>\n          This is a list of tools which are related with the <b>gitmoji</b>{' '}\n          convention.\n        </p>\n\n        <ul>\n          {tools.map((tool) => (\n            <li key={tool.name}>\n              <a href={tool.link} target=\"_blank\" rel=\"noopener noreferrer\">\n                <b>{tool.name}</b>\n              </a>\n              {`: ${tool.description}`}\n            </li>\n          ))}\n        </ul>\n      </section>\n    </main>\n  )\n}\n"
  },
  {
    "path": "packages/website/src/app/specification/page.tsx",
    "content": "import type { Metadata } from 'next'\nimport Link from 'next/link'\n\nimport CarbonAd from 'src/components/CarbonAd'\n\nexport const metadata: Metadata = {\n  title: 'gitmoji | Specification | An emoji guide for your commit messages',\n  alternates: {\n    canonical: '/specification',\n  },\n}\n\nexport default function Specification() {\n  return (\n    <main>\n      <CarbonAd />\n      <section>\n        <h1 id=\"specification\">Specification</h1>\n\n        <p>\n          You can extend Gitmoji and make it your own, but in case you want to\n          follow the official specification, please continue reading 👀\n        </p>\n\n        <p>\n          A gitmoji commit message consists is composed using the following\n          pieces:\n        </p>\n\n        <ul>\n          <li>\n            <b>intention</b>: The intention you want to express with the commit,\n            using an emoji from the <Link href=\"/\">list</Link>. Either in the\n            :shortcode: or unicode format.\n          </li>\n          <li>\n            <b>scope</b>: An optional string that adds contextual information\n            for the scope of the change.\n          </li>\n          <li>\n            <b>message</b>: A brief explanation of the change.\n          </li>\n        </ul>\n\n        <pre className=\"overflow-x-adjust\">\n          <code>&lt;intention&gt; [scope?][:?] &lt;message&gt;</code>\n        </pre>\n      </section>\n\n      <section>\n        <h1 id=\"specification-examples\">Examples</h1>\n\n        <ul>\n          <li>⚡️ Lazyload home screen images.</li>\n          <li>🐛 Fix `onClick` event handler</li>\n          <li>🔖 Bump version `1.2.0`</li>\n          <li>♻️ (components): Transform classes to hooks</li>\n          <li>📈 Add analytics to the dashboard</li>\n          <li>🌐 Support Japanese language</li>\n          <li>♿️ (account): Improve modals a11y</li>\n        </ul>\n      </section>\n\n      <section>\n        <h1 id=\"shortcode-vs-unicode-format\">Shortcode vs Unicode format</h1>\n\n        <p>\n          You&#39;ll notice that when using emojis in commits, it&#39;s possible\n          to use either the shortcode or the unicode format.\n        </p>\n\n        <p>\n          The difference between both is that the unicode represents the emoji\n          itself while the shortcode is a text representation of the emoji that\n          will be converted to the unicode character when rendered on a Git\n          platform, such as GitHub, GitLab etc.\n        </p>\n\n        <p>\n          Both approaches are completely fine, you can choose the one you&#39;re\n          most comfortable and suits you best. Let&#39;s understand the pros and\n          cons of each approach so you can decide on it:\n        </p>\n\n        <h2>Unicode</h2>\n\n        <h3>Pros ✅</h3>\n\n        <ul>\n          <li>\n            It represents the actual emoji no external systems are needed.\n          </li>\n          <li>Better git log.</li>\n          <li>Easier to type.</li>\n          <li>Takes less characters of the commit title.</li>\n        </ul>\n\n        <h3>Cons ❌</h3>\n        <ul>\n          <li>Might not be supported in all terminals / operating systems.</li>\n        </ul>\n\n        <h2>Shortcode</h2>\n        <h3>Pros ✅</h3>\n        <ul>\n          <li>\n            Supported everywhere as it&#39;s a text representation of the emoji.\n          </li>\n        </ul>\n        <h3>Cons ❌</h3>\n        <ul>\n          <li>\n            You&#39;ll need a platform / system that knows how to properly\n            render the shortcode.\n          </li>\n          <li>\n            Different platforms / systems might use different shortcode namings,\n            eg: GitHub and GitLab have some differences.\n          </li>\n          <li>Takes more characters of the commit title.</li>\n        </ul>\n      </section>\n    </main>\n  )\n}\n"
  },
  {
    "path": "packages/website/src/components/Button/__tests__/button.spec.tsx",
    "content": "import { render, screen } from '@testing-library/react'\n\nimport Button from '../index'\nimport * as stubs from './stubs'\n\ndescribe('Button', () => {\n  it('should render the component with correct attributes', () => {\n    render(<Button {...stubs.props} />)\n\n    const link = screen.getByRole('link', { name: /GitHub/i })\n    expect(link).toBeInTheDocument()\n    expect(link).toHaveAttribute('href', '/')\n    expect(link).toHaveAttribute('target', '_blank')\n  })\n\n  it('should render without icon when icon prop is not provided', () => {\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    const { icon, ...propsWithoutIcon } = stubs.props\n    const { container } = render(<Button {...propsWithoutIcon} />)\n\n    const link = screen.getByRole('link', { name: /GitHub/i })\n    expect(link).toBeInTheDocument()\n    expect(container.querySelector('svg')).not.toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/website/src/components/Button/__tests__/stubs.ts",
    "content": "export const props = {\n  target: '_blank',\n  icon: 'star',\n  text: 'GitHub',\n  link: '/',\n}\n"
  },
  {
    "path": "packages/website/src/components/Button/index.tsx",
    "content": "import Icon from 'src/components/Icon'\nimport styles from './styles.module.css'\n\ntype Props = { target?: string; icon?: string; text: string; link: string }\n\nconst Button = (props: Props) => (\n  <a\n    className={styles.button}\n    target={props.target && props.target}\n    href={props.link}\n  >\n    {props.icon && <Icon name={props.icon} />}\n    {props.text}\n  </a>\n)\n\nexport default Button\n"
  },
  {
    "path": "packages/website/src/components/Button/styles.module.css",
    "content": ".button {\n  border-radius: 4px;\n  cursor: pointer;\n  display: inline-block;\n  font-weight: 600;\n  margin: 0.25em 0;\n  padding: 0.75em 1em;\n  position: relative;\n  transition: none;\n  background-color: var(--secondary);\n  color: var(--textInSecondary);\n  box-shadow: 0 4px var(--secondaryShadow);\n}\n\n.button:hover {\n  top: 2px;\n  box-shadow: 0 2px var(--secondaryShadow);\n  animation: none;\n}\n\n.button:active {\n  box-shadow: 0 0 var(--secondary);\n  top: 4px;\n}\n"
  },
  {
    "path": "packages/website/src/components/CarbonAd/__tests__/carbonAd.spec.tsx",
    "content": "import { render, waitFor } from '@testing-library/react'\n\nimport CarbonAd from '../index'\nimport styles from '../styles.module.css'\n\ndescribe('CarbonAd', () => {\n  it('should render the component with carbon ads script container', async () => {\n    const { container } = render(<CarbonAd />)\n\n    await waitFor(() => {\n      const carbonAdContainer = container.querySelector(\n        `.${styles.carbonContainer}`,\n      )\n      expect(carbonAdContainer).toBeInTheDocument()\n    })\n  })\n})\n"
  },
  {
    "path": "packages/website/src/components/CarbonAd/index.tsx",
    "content": "'use client'\n\nimport { useRef, useEffect } from 'react'\n\nimport styles from './styles.module.css'\n\nconst CarbonAd = () => {\n  const adsContainer = useRef<HTMLDivElement>(null)\n\n  useEffect(() => {\n    if (!adsContainer.current || typeof window === 'undefined') {\n      return\n    }\n\n    const existingScript = document.getElementById('_carbonads_js')\n\n    if (existingScript) {\n      const existingAd = document.getElementById('carbonads')\n\n      if (existingAd && adsContainer.current) {\n        adsContainer.current.appendChild(existingAd)\n      }\n\n      return\n    }\n\n    const carbonAdsScript = document.createElement('script')\n    carbonAdsScript.src =\n      '//cdn.carbonads.com/carbon.js' + '?serve=CE7DL5QJ&placement=gitmojidev'\n    carbonAdsScript.async = true\n    carbonAdsScript.id = '_carbonads_js'\n\n    adsContainer.current.appendChild(carbonAdsScript)\n\n    return () => {}\n  }, [])\n\n  return (\n    <div className=\"col-xs-12\">\n      <div\n        ref={adsContainer}\n        className={`${styles.carbonContainer} row center-xs`}\n      />\n    </div>\n  )\n}\n\nexport default CarbonAd\n"
  },
  {
    "path": "packages/website/src/components/CarbonAd/styles.module.css",
    "content": ".carbonContainer {\n  height: 100px;\n}\n\n:global(#carbonads) {\n  display: block;\n  overflow: hidden;\n  max-width: 728px;\n  border-radius: 4px;\n  position: relative;\n  box-shadow: 0 1px 2px 0 var(--cardShadow);\n}\n\n:global(#carbonads > span) {\n  display: block;\n}\n\n:global(#carbonads a) {\n  color: inherit;\n  text-decoration: none;\n}\n\n:global(#carbonads a:hover) {\n  color: inherit;\n  animation: none;\n}\n\n:global(.carbon-wrap) {\n  display: flex;\n  align-items: center;\n}\n\n:global(.carbon-img) {\n  display: block;\n  margin: 0;\n  line-height: 1;\n}\n\n:global(.carbon-img img) {\n  display: block;\n  height: 90px;\n  width: auto;\n}\n\n:global(.carbon-text) {\n  display: block;\n  padding: 0 1em;\n  line-height: 1.35;\n  text-align: center;\n  width: 100%;\n  font-size: 14px;\n}\n\n:global(.carbon-poweredby) {\n  display: block;\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  padding: 6px 10px;\n  background: var(--carbonAdBadgeBackground);\n  text-align: center;\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n  font-weight: 600;\n  font-size: 8px;\n  border-top-left-radius: 4px;\n  line-height: 1;\n}\n"
  },
  {
    "path": "packages/website/src/components/ContributorsList/Contributor/index.tsx",
    "content": "import styles from './styles.module.css'\n\ntype Props = { avatar: string; url: string }\n\nconst Contributor = (props: Props) => (\n  <article className=\"col-xs-3 col-sm-2\">\n    <a href={props.url} target=\"_blank\" rel=\"noreferrer\">\n      <img className={styles.picture} src={props.avatar} />\n    </a>\n  </article>\n)\n\nexport default Contributor\n"
  },
  {
    "path": "packages/website/src/components/ContributorsList/Contributor/styles.module.css",
    "content": ".picture {\n  max-width: 100%;\n  border-radius: 50%;\n  padding: 0.5em;\n}\n"
  },
  {
    "path": "packages/website/src/components/ContributorsList/__tests__/contributorsList.spec.tsx",
    "content": "import { render } from '@testing-library/react'\n\nimport ContributorsList from '../index'\nimport Contributor from '../Contributor'\nimport * as stubs from './stubs'\n\ndescribe('ContributorsList', () => {\n  describe('Contributor', () => {\n    it('should render the contributor with link and avatar', () => {\n      const { container } = render(<Contributor {...stubs.contributor} />)\n\n      const link = container.querySelector('a')\n      expect(link).toBeInTheDocument()\n      expect(link).toHaveAttribute('href', stubs.contributor.url)\n      expect(link).toHaveAttribute('target', '_blank')\n      expect(link).toHaveAttribute('rel', 'noreferrer')\n\n      const img = container.querySelector('img')\n      expect(img).toBeInTheDocument()\n      expect(img).toHaveAttribute('src', stubs.contributor.avatar)\n    })\n  })\n\n  it('should render the list of contributors', () => {\n    const { container } = render(<ContributorsList {...stubs.props} />)\n\n    const links = container.querySelectorAll('a')\n    expect(links).toHaveLength(stubs.props.contributors.length)\n    expect(links[0]).toHaveAttribute('href', stubs.contributor.url)\n  })\n})\n"
  },
  {
    "path": "packages/website/src/components/ContributorsList/__tests__/stubs.ts",
    "content": "export const contributor = {\n  url: 'https://github.com/profile',\n  avatar: 'https://github.com/avatar',\n  id: 'contributor-id-123',\n}\n\nexport const props = {\n  contributors: [contributor],\n}\n"
  },
  {
    "path": "packages/website/src/components/ContributorsList/index.tsx",
    "content": "import Contributor from './Contributor'\n\ntype Props = {\n  contributors: Array<{\n    avatar: string\n    id: string\n    url: string\n  }>\n}\n\nconst ContributorsList = (props: Props) => (\n  <div className=\"row center-xs\">\n    {props.contributors.map((contributor) => (\n      <Contributor\n        key={contributor.id}\n        url={contributor.url}\n        avatar={contributor.avatar}\n      />\n    ))}\n  </div>\n)\n\nexport default ContributorsList\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Gitmoji/index.tsx",
    "content": "import emojiColorsMap from '../emojiColorsMap'\nimport styles from './styles.module.css'\n\ntype Props = {\n  code: string\n  description: string\n  emoji: string\n  isListMode: boolean\n  name: keyof typeof emojiColorsMap\n}\n\nconst Gitmoji = (props: Props) => {\n  const style = {\n    '--emojiColor': emojiColorsMap[props.name],\n  } as React.CSSProperties\n\n  return (\n    <article\n      style={style}\n      className={`${styles.emoji} col-xs-12 col-sm-6 ${\n        props.isListMode ? 'col-md-4' : 'col-md-3'\n      }`}\n    >\n      <div\n        className={`${styles.card} ${props.isListMode ? styles.cardList : ''}`}\n      >\n        <header className={`${styles.cardHeader}`}>\n          <button\n            type=\"button\"\n            className={`gitmoji-clipboard-emoji ${styles.gitmoji}`}\n            data-clipboard-text={props.emoji}\n          >\n            {props.emoji}\n          </button>\n        </header>\n        <div className={styles.gitmojiInfo}>\n          <button\n            className={`gitmoji-clipboard-code ${styles.gitmojiCode}`}\n            data-clipboard-text={props.code}\n            tabIndex={-1}\n            type=\"button\"\n          >\n            <code>\n              {replaceWithJSX(\n                props.code,\n                '_',\n                <>\n                  _<wbr />\n                </>,\n              )}\n            </code>\n          </button>\n          <p>{props.description}</p>\n        </div>\n      </div>\n    </article>\n  )\n}\n\nconst replaceWithJSX = (\n  text: string,\n  find: string,\n  replace: React.JSX.Element,\n) => {\n  const nodes: (string | React.JSX.Element)[] = text.split(find)\n  const first = nodes.shift()\n\n  return nodes\n    .reduce((newNodes, part) => [...newNodes, replace, part], [first])\n    .map((el, index) => <span key={index}>{el}</span>)\n}\n\nexport default Gitmoji\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Gitmoji/styles.module.css",
    "content": ".emoji {\n  display: flex;\n  box-sizing: border-box;\n}\n\n.card {\n  background-color: var(--cardBackground);\n  border-radius: 4px;\n  box-shadow: 0 1px 2px 0 var(--cardShadow);\n  flex: 1;\n  margin: 1em 0;\n  transition: all 0.25s ease-out;\n  text-align: center;\n  overflow: hidden;\n}\n\n.cardList {\n  display: flex;\n}\n\n.cardList .gitmoji {\n  font-size: 3.5em;\n}\n\n.cardList .cardHeader {\n  height: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  padding: 0 1rem;\n}\n\n.cardList .gitmojiInfo {\n  text-align: left;\n  padding: 1rem;\n}\n\n.cardList .gitmojiCode {\n  text-align: left;\n}\n\n.cardList .gitmojiInfo p {\n  padding: 0;\n  margin: 0;\n  padding-top: 0.5rem;\n}\n\n.card:hover {\n  box-shadow: 0 10px 20px 0 var(--cardShadow);\n  transform: translateY(-1px);\n}\n\n[data-theme='dark'] .card:hover {\n  box-shadow: none;\n  background-color: #3b3b3b;\n}\n\n.cardHeader {\n  background-color: var(--emojiColor);\n  align-self: flex-start;\n  padding-top: 2em;\n  padding-bottom: 0.85em;\n  border-top-left-radius: 4px;\n  border-top-right-radius: 4px;\n}\n\n.gitmoji,\n.gitmojiCode {\n  background-color: transparent;\n  border: none;\n  color: inherit;\n  font: inherit;\n  padding: 0;\n}\n\n.gitmoji {\n  border-radius: none;\n  cursor: pointer;\n  display: inline-block;\n  font-size: 5em;\n  font-family:\n    'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji',\n    'Segoe UI Symbol', 'Android Emoji', 'EmojiSymbols';\n}\n\n.gitmoji:hover,\n.gitmoji:focus {\n  animation-name: bounce;\n  animation-duration: 0.5s;\n}\n\n.gitmojiCode {\n  display: inline-block;\n  position: relative;\n  border-radius: 4px;\n  transition-duration: 0.3s;\n  cursor: pointer;\n  white-space: nowrap;\n}\n\n.gitmojiCode::after {\n  content: '';\n  position: absolute;\n  left: 0;\n  bottom: 0;\n  width: 0;\n  height: 0.2em;\n  border-radius: 4px;\n  transition: width 0.15s;\n  background-color: var(--emojiColor);\n}\n\n.gitmojiCode:hover::after {\n  width: 100%;\n}\n\n.gitmojiInfo {\n  padding: 1.5em;\n  word-break: break-all;\n  color: var(--emojiCodeText);\n}\n\n.gitmojiInfo p {\n  color: var(--cardText);\n  word-break: normal;\n}\n\n@media (max-width: 768px) {\n  .gitmoji,\n  .cardList .gitmoji {\n    font-size: 50px;\n  }\n\n  .cardHeader {\n    padding-bottom: 1em;\n  }\n}\n\n/*\n  This code has been obtained from:\n  https://github.com/daneden/animate.css/blob/master/source/attention_seekers/bounce.css\n*/\n@keyframes bounce {\n  from,\n  20%,\n  53%,\n  80%,\n  to {\n    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);\n    transform: translate3d(0, 0, 0);\n  }\n\n  40%,\n  43% {\n    animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);\n    transform: translate3d(0, -9px, 0);\n  }\n\n  70% {\n    animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);\n    transform: translate3d(0, -5px, 0);\n  }\n\n  90% {\n    transform: translate3d(0, -2px, 0);\n  }\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/SearchParamsSync.tsx",
    "content": "'use client'\n\nimport { useEffect } from 'react'\nimport { useRouter, useSearchParams } from 'next/navigation'\n\ntype Props = {\n  searchInput: string\n  setSearchInput: (value: string) => void\n}\n\n/**\n * Small client component that syncs URL search params with the search input state.\n * Wrapped in Suspense to avoid CSR bailout while keeping the main list static.\n */\nexport default function SearchParamsSync({\n  searchInput,\n  setSearchInput,\n}: Props) {\n  const router = useRouter()\n  const searchParams = useSearchParams()\n\n  useEffect(() => {\n    const search = searchParams.get('search')\n    if (search) {\n      setSearchInput(search)\n    }\n  }, [searchParams, setSearchInput])\n\n  useEffect(() => {\n    const search = searchParams.get('search')\n    if (search && !searchInput) {\n      router.push('/')\n    }\n  }, [searchInput, searchParams, router])\n\n  return null\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Toolbar/Kbd/index.tsx",
    "content": "import styles from './styles.module.css'\n\nconst isMacOs = () => {\n  return (\n    typeof window !== 'undefined' &&\n    window.navigator.platform.toUpperCase().includes('MAC')\n  )\n}\n\nconst Kbd = () => {\n  return <kbd className={styles.kbd}>{isMacOs() ? '⌘' : 'Ctrl'} K</kbd>\n}\n\nexport default Kbd\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Toolbar/Kbd/styles.module.css",
    "content": ".kbd {\n  right: 0;\n  align-items: center;\n  border-radius: 3px;\n  border: solid 1px #999;\n  color: #595959;\n  display: flex;\n  font-family: system-ui;\n  margin-right: 0.5rem;\n  padding: 0.25rem 0.5rem;\n}\n\n[data-theme='dark'] .kbd {\n  color: #b8b8b8;\n}\n\n@media (max-width: 568px) {\n  .kbd {\n    display: none;\n  }\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Toolbar/ListModeSelector/index.tsx",
    "content": "import Icon from 'src/components/Icon'\nimport styles from './styles.module.css'\n\ntype Props = {\n  isListMode: boolean\n  setIsListMode: (isListMode: boolean) => void\n}\n\nconst ListModeSelector = (props: Props) => (\n  <div className={styles.container}>\n    <button\n      className={`${styles.button} ${\n        !props.isListMode ? styles.buttonActive : ''\n      }`}\n      disabled={!props.isListMode}\n      onClick={() => props.setIsListMode(false)}\n    >\n      <Icon name=\"grid\" />\n    </button>\n\n    <button\n      className={`${styles.button} ${\n        props.isListMode ? styles.buttonActive : ''\n      }`}\n      disabled={props.isListMode}\n      onClick={() => props.setIsListMode(true)}\n    >\n      <Icon name=\"list\" />\n    </button>\n  </div>\n)\n\nexport default ListModeSelector\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Toolbar/ListModeSelector/styles.module.css",
    "content": ".container {\n  display: flex;\n}\n\n.button {\n  align-items: center;\n  border-radius: 4px;\n  border: none;\n  color: var(--text);\n  cursor: pointer;\n  display: flex;\n  background-color: var(--cardBackground);\n  box-shadow: 0 2px 4px 0 var(--cardShadow);\n  font-size: 16px;\n  height: 48px;\n  justify-content: center;\n  margin: 8px;\n  width: 48px;\n}\n\n.button svg {\n  margin: 0;\n}\n\n.buttonActive {\n  color: var(--secondary);\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Toolbar/ThemeSelector/index.tsx",
    "content": "'use client'\n\nimport { useEffect, useState } from 'react'\nimport { useTheme } from 'next-themes'\n\nimport Icon from 'src/components/Icon'\nimport styles from './styles.module.css'\n\nconst ThemeSelector = () => {\n  const [isMounted, setIsMounted] = useState(false)\n  const { resolvedTheme, setTheme } = useTheme()\n  const nextTheme = resolvedTheme === 'light' ? 'dark' : 'light'\n\n  useEffect(() => setIsMounted(true), [])\n\n  if (!isMounted) {\n    return (\n      <div className={styles.container}>\n        <button disabled className={`${styles.button}`} />\n      </div>\n    )\n  }\n\n  return (\n    <button className={`${styles.button}`} onClick={() => setTheme(nextTheme)}>\n      <Icon name={nextTheme} />\n    </button>\n  )\n}\n\nexport default ThemeSelector\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Toolbar/ThemeSelector/styles.module.css",
    "content": ".button {\n  display: flex;\n  align-items: center;\n  border-radius: 4px;\n  border: none;\n  color: var(--text);\n  cursor: pointer;\n  background-color: var(--cardBackground);\n  box-shadow: 0 2px 4px 0 var(--cardShadow);\n  font-size: 16px;\n  height: 48px;\n  justify-content: center;\n  margin: 8px;\n  width: 48px;\n}\n\n.button svg {\n  margin: 0;\n}\n\n@media (max-width: 568px) {\n  .button {\n    margin-left: 0;\n  }\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Toolbar/index.tsx",
    "content": "'use client'\n\nimport { useEffect, useRef } from 'react'\nimport dynamic from 'next/dynamic'\n\nimport ListModeSelector from './ListModeSelector'\nimport ThemeSelector from './ThemeSelector'\nconst Kbd = dynamic(() => import('./Kbd'), { ssr: false })\nimport styles from './styles.module.css'\n\ntype Props = {\n  isListMode: boolean\n  searchInput?: string\n  setIsListMode: (searchInput: boolean) => void\n  setSearchInput: (searchInput: string) => void\n}\n\nconst Toolbar = (props: Props) => {\n  const searchInputRef = useRef<HTMLInputElement>(null)\n\n  useEffect(() => {\n    const keyboardEventListener = (event: KeyboardEvent) => {\n      const searchInput = searchInputRef.current\n      if (\n        searchInput &&\n        (event.ctrlKey || event.metaKey) &&\n        event.key === 'k'\n      ) {\n        event.preventDefault()\n        searchInput.focus()\n      }\n    }\n\n    if (typeof window !== 'undefined') {\n      document.addEventListener('keydown', keyboardEventListener, false)\n    }\n\n    return () => {\n      document.removeEventListener('keydown', keyboardEventListener, false)\n    }\n  }, [])\n\n  return (\n    <div className={styles.container}>\n      <div className={styles.inputWrapper}>\n        <input\n          className={styles.searchInput}\n          ref={searchInputRef}\n          name=\"searchInput\"\n          onChange={(event) => props.setSearchInput(event.target.value)}\n          placeholder=\"Search your gitmoji...\"\n          type=\"search\"\n          value={props.searchInput}\n        />\n\n        <Kbd />\n      </div>\n\n      <div className={styles.actionsContainer}>\n        <ThemeSelector />\n\n        <ListModeSelector\n          isListMode={props.isListMode}\n          setIsListMode={props.setIsListMode}\n        />\n      </div>\n    </div>\n  )\n}\n\nexport default Toolbar\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/Toolbar/styles.module.css",
    "content": ".container {\n  align-items: center;\n  display: flex;\n  flex-direction: row;\n  margin-bottom: 0.5rem;\n  margin-top: 1.5rem;\n}\n\n.actionsContainer {\n  display: flex;\n}\n\n.inputWrapper {\n  flex: 1;\n  display: flex;\n  align-items: center;\n  border-radius: 4px;\n  border: 0;\n  box-shadow: 0 2px 4px 0 var(--cardShadow);\n  margin-right: 1rem;\n  background-color: var(--cardBackground);\n}\n\n.inputWrapper:focus-within {\n  outline: -webkit-focus-ring-color auto 1px;\n}\n\n.searchInput {\n  background-color: transparent;\n  border: none;\n  flex-grow: 1;\n  font-size: 1rem;\n  padding: 1rem;\n}\n\n.searchInput:focus-visible {\n  outline: none;\n}\n\n.searchInput:focus {\n  outline: none;\n}\n\n[data-theme='dark'] .searchInput {\n  color: var(--text);\n}\n\n@media (max-width: 568px) {\n  .searchInput {\n    margin: 0;\n    margin-top: 0.5rem;\n  }\n\n  .container {\n    flex-direction: column-reverse;\n    align-items: stretch;\n  }\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/__tests__/gitmojiList.spec.tsx",
    "content": "import { useRouter, useSearchParams } from 'next/navigation'\nimport { render, screen, fireEvent } from '@testing-library/react'\n\nimport GitmojiList from '../index'\nimport * as stubs from './stubs'\n\njest.mock('next/navigation', () => ({\n  useRouter: jest.fn(),\n  useSearchParams: jest.fn(),\n  usePathname: jest.fn(() => '/'),\n}))\n\nconst useRouterMock = useRouter as jest.Mock\nconst useSearchParamsMock = useSearchParams as jest.Mock\n\ndescribe('GitmojiList', () => {\n  beforeEach(() => {\n    useRouterMock.mockReturnValue(stubs.appRouterMock())\n    useSearchParamsMock.mockReturnValue(stubs.searchParamsMock())\n  })\n\n  describe('when is not list mode', () => {\n    it('should render the component in grid mode by default', () => {\n      const { container } = render(<GitmojiList {...stubs.props} />)\n\n      const articles = container.querySelectorAll('article')\n      expect(articles.length).toBeGreaterThan(0)\n    })\n  })\n\n  describe('when is list mode', () => {\n    it('should switch to list mode when clicking the list button', () => {\n      const { container } = render(<GitmojiList {...stubs.props} />)\n\n      const buttons = screen.getAllByRole('button')\n      const listModeButton = buttons[1]\n\n      fireEvent.click(listModeButton)\n\n      const articles = container.querySelectorAll('article')\n      expect(articles.length).toBeGreaterThan(0)\n    })\n  })\n\n  describe('when user search the fire gitmoji', () => {\n    beforeEach(() => {\n      useRouterMock.mockReturnValue(stubs.appRouterMock())\n      useSearchParamsMock.mockReturnValue(stubs.searchParamsMock())\n    })\n\n    it('should find the fire gitmoji by code', () => {\n      const { container } = render(<GitmojiList {...stubs.props} />)\n      const input = screen.getByRole('searchbox')\n      const query = 'Fire'\n\n      fireEvent.change(input, { target: { value: query } })\n\n      const articles = container.querySelectorAll('article')\n      expect(articles.length).toEqual(1)\n    })\n\n    it('should find the fire gitmoji by description', () => {\n      const { container } = render(<GitmojiList {...stubs.props} />)\n      const input = screen.getByRole('searchbox')\n      const query = 'remove'\n\n      fireEvent.change(input, { target: { value: query } })\n\n      const articles = container.querySelectorAll('article')\n      expect(articles.length).toEqual(1)\n    })\n\n    it('should find the fire gitmoji by emoji', () => {\n      const { container } = render(<GitmojiList {...stubs.props} />)\n      const input = screen.getByRole('searchbox')\n      const query = '🔥'\n\n      fireEvent.change(input, { target: { value: query } })\n\n      const articles = container.querySelectorAll('article')\n      expect(articles.length).toEqual(1)\n    })\n  })\n\n  describe('when search is provided by query string', () => {\n    beforeEach(() => {\n      useRouterMock.mockReturnValue(stubs.appRouterMock())\n      useSearchParamsMock.mockReturnValue(stubs.searchParamsMock('fire'))\n    })\n\n    it('should set the search input value to query.search', () => {\n      render(<GitmojiList {...stubs.props} />)\n      const query = 'fire'\n\n      const input = screen.getByRole('searchbox')\n      expect(input).toHaveValue(query)\n    })\n\n    describe('when the user deletes the search input', () => {\n      it('should clear the query string', () => {\n        const mockRouter = stubs.appRouterMock()\n        useRouterMock.mockReturnValue(mockRouter)\n        useSearchParamsMock.mockReturnValue(stubs.searchParamsMock('fire'))\n\n        render(<GitmojiList {...stubs.props} />)\n        const input = screen.getByRole('searchbox')\n\n        fireEvent.change(input, { target: { value: '' } })\n\n        expect(mockRouter.push).toHaveBeenCalledWith('/')\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/__tests__/stubs.ts",
    "content": "import { gitmojis } from 'gitmojis'\n\nexport const props = {\n  gitmojis: gitmojis.slice(0, 6),\n}\n\nexport const routerMock = (query = {}) => ({\n  query,\n  push: jest.fn(),\n})\n\nexport const appRouterMock = () => ({\n  push: jest.fn(),\n  replace: jest.fn(),\n  prefetch: jest.fn(),\n  back: jest.fn(),\n  forward: jest.fn(),\n  refresh: jest.fn(),\n})\n\nexport const searchParamsMock = (searchValue?: string) => {\n  const params = new URLSearchParams()\n  if (searchValue) {\n    params.set('search', searchValue)\n  }\n  return params\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/emojiColorsMap.ts",
    "content": "export default {\n  'adhesive-bandage': '#fbcfb7',\n  alembic: '#7f39fb',\n  alien: '#c5e763',\n  ambulance: '#fb584a',\n  dizzy: '#ffdb3a',\n  'arrow-down': '#ef5350',\n  'arrow-up': '#00e676',\n  art: '#ff7281',\n  beers: '#fbb64b',\n  bento: '#ff5864',\n  bookmark: '#80deea',\n  boom: '#f94f28',\n  bug: '#8cd842',\n  'building-construction': '#ffe55f',\n  bulb: '#ffce49',\n  'busts-in-silhouette': '#ffce49',\n  'camera-flash': '#00a9f0',\n  'card-file-box': '#c5e763',\n  'chart-with-upwards-trend': '#cedae6',\n  'children-crossing': '#ffce49',\n  'clown-face': '#ff7281',\n  'construction-worker': '#64b5f6',\n  construction: '#ffb74d',\n  egg: '#77e856',\n  fire: '#ff9d44',\n  'globe-with-meridians': '#e7f4ff',\n  'goal-net': '#c7cb12',\n  'green-heart': '#c5e763',\n  hammer: '#ffc400',\n  coffin: '#d9e3e8',\n  'heavy-minus-sign': '#ef5350',\n  'heavy-plus-sign': '#00e676',\n  iphone: '#40c4ff',\n  label: '#cb63e6',\n  lipstick: '#80deea',\n  lock: '#ffce49',\n  'closed-lock-with-key': '#83beec',\n  'loud-sound': '#23b4d2',\n  mag: '#ffe55f',\n  memo: '#00e676',\n  mute: '#e6ebef',\n  'ok-hand': '#c5e763',\n  package: '#fdd0ae',\n  'page-facing-up': '#d9e3e8',\n  'passport-control': '#4dc6dc',\n  pencil: '#ffce49',\n  pencil2: '#ffce49',\n  poop: '#a78674',\n  pushpin: '#39c2f1',\n  recycle: '#77e856',\n  rewind: '#56d1d8',\n  rocket: '#00a9f0',\n  'rotating-light': '#536dfe',\n  'safety-vest': '#f2ad52',\n  'see-no-evil': '#8bdfe7',\n  seedling: '#c5e763',\n  sparkles: '#ffe55f',\n  'speech-balloon': '#cedae6',\n  stethoscope: '#77e856',\n  tada: '#f74d5f',\n  'test-tube': '#fb584a',\n  'triangular-flag-on-post': '#ffce49',\n  truck: '#ef584a',\n  'twisted-rightwards-arrows': '#56d1d8',\n  wastebasket: '#d9e3e8',\n  wheelchair: '#00b1fb',\n  'white-check-mark': '#77e856',\n  wrench: '#ffc400',\n  zap: '#40c4ff',\n  'monocle-face': '#ffe55f',\n  necktie: '#83beec',\n  bricks: '#ff6723',\n  technologist: '#86B837',\n  'money-with-wings': '#b3c0b1',\n  thread: '#ffbe7b',\n  airplane: '#74d4ec',\n  't-rex': '#56d1d8',\n} as const\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/hooks/__tests__/stubs.ts",
    "content": "export const localStorageMock = {\n  key: 'gitmojiTestKey',\n  value: 'gitmojiTestValue',\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/hooks/__tests__/useLocalStorage.spec.tsx",
    "content": "import { render } from '@testing-library/react'\n\nimport useLocalStorage from '../useLocalStorage'\nimport * as stubs from './stubs'\n\nconst TestComponent = ({\n  storageKey,\n  storageValue,\n}: {\n  storageKey: string\n  storageValue: string\n}) => {\n  useLocalStorage(storageKey, storageValue)\n\n  return null\n}\n\nObject.defineProperty(window, 'localStorage', {\n  writable: true,\n  value: { setItem: jest.fn(), getItem: jest.fn() },\n})\n\nconst getItem = window.localStorage.getItem as jest.Mock\nconst setItem = window.localStorage.setItem as jest.Mock\n\ndescribe('useLocalStorage', () => {\n  beforeEach(() => {\n    jest.clearAllMocks()\n  })\n\n  describe('when value is not persisted', () => {\n    beforeEach(() => {\n      getItem.mockReturnValue(null)\n    })\n\n    it('should call localStorage.setItem', () => {\n      const { rerender } = render(\n        <TestComponent\n          storageKey={stubs.localStorageMock.key}\n          storageValue={stubs.localStorageMock.value}\n        />,\n      )\n\n      rerender(\n        <TestComponent\n          storageKey={stubs.localStorageMock.key}\n          storageValue={stubs.localStorageMock.value}\n        />,\n      )\n\n      expect(setItem).toHaveBeenCalledWith(\n        stubs.localStorageMock.key,\n        stubs.localStorageMock.value,\n      )\n    })\n  })\n\n  describe('when there is an error', () => {\n    const consoleError = console.error\n\n    beforeEach(() => {\n      getItem.mockImplementation(() => {\n        throw new Error('Test')\n      })\n\n      Object.defineProperty(console, 'error', {\n        writable: true,\n        value: jest.fn(),\n      })\n    })\n\n    afterEach(() => {\n      Object.defineProperty(console, 'error', {\n        writable: true,\n        value: consoleError,\n      })\n    })\n\n    it('should call console.error', () => {\n      const { rerender } = render(\n        <TestComponent\n          storageKey={stubs.localStorageMock.key}\n          storageValue={stubs.localStorageMock.value}\n        />,\n      )\n\n      rerender(\n        <TestComponent\n          storageKey={stubs.localStorageMock.key}\n          storageValue={stubs.localStorageMock.value}\n        />,\n      )\n\n      expect(console.error).toHaveBeenCalledWith(expect.any(String))\n    })\n  })\n})\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/hooks/useLocalStorage.tsx",
    "content": "import { useState, useEffect } from 'react'\n\nexport default function useLocalStorage<T>(key: string, defaultValue: T) {\n  const [state, setState] = useState(defaultValue)\n\n  useEffect(() => {\n    try {\n      const localValue = window.localStorage.getItem(key)\n\n      if (localValue !== null) {\n        setState(JSON.parse(localValue))\n      }\n    } catch (error) {\n      console.error(`ERROR: Loading ${key} from localStorage – ${error}`)\n    }\n  }, [])\n\n  useEffect(() => {\n    window.localStorage.setItem(key, `${state}`)\n  }, [state])\n\n  return [state, setState] as const\n}\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/index.tsx",
    "content": "'use client'\n\nimport { Suspense, useEffect, useState } from 'react'\nimport Clipboard from 'clipboard'\nimport type { Gitmoji as GitmojiType } from 'gitmojis'\nimport toast from 'react-hot-toast'\n\nimport Gitmoji from './Gitmoji'\nimport Toolbar from './Toolbar'\nimport SearchParamsSync from './SearchParamsSync'\nimport useLocalStorage from './hooks/useLocalStorage'\nimport styles from './styles.module.css'\n\ntype Props = {\n  gitmojis: readonly GitmojiType[]\n}\n\nconst GitmojiList = (props: Props) => {\n  const [searchInput, setSearchInput] = useState('')\n  const [isListMode, setIsListMode] = useLocalStorage('isListMode', false)\n\n  const gitmojis = searchInput\n    ? props.gitmojis.filter(({ emoji, code, description }) => {\n        const lowerCasedSearch = searchInput.toLowerCase()\n\n        return (\n          code.includes(lowerCasedSearch) ||\n          description.toLowerCase().includes(lowerCasedSearch) ||\n          emoji == searchInput\n        )\n      })\n    : props.gitmojis\n\n  useEffect(() => {\n    const clipboard = new Clipboard(\n      '.gitmoji-clipboard-emoji, .gitmoji-clipboard-code',\n    )\n\n    clipboard.on('success', function (e) {\n      toast(\n        (t) => (\n          <span className={styles.notification}>\n            <p>\n              Hey! Gitmoji <span className={styles.gitmojiCode}>{e.text}</span>{' '}\n              copied to the clipboard 😜\n            </p>\n            <span\n              className={styles.closeButton}\n              onClick={() => toast.dismiss(t.id)}\n            />\n          </span>\n        ),\n        {\n          id: 'clipboard',\n          style: {\n            background: '#ff5a79',\n            color: '#ffffff',\n            fontWeight: 600,\n            fontSize: '90%',\n          },\n        },\n      )\n    })\n\n    return () => clipboard.destroy()\n  }, [])\n\n  return (\n    <div className=\"row\" id=\"gitmoji-list\">\n      <Suspense fallback={null}>\n        <SearchParamsSync\n          searchInput={searchInput}\n          setSearchInput={setSearchInput}\n        />\n      </Suspense>\n      <div className=\"col-xs-12\">\n        <Toolbar\n          isListMode={isListMode}\n          searchInput={searchInput}\n          setIsListMode={setIsListMode}\n          setSearchInput={setSearchInput}\n        />\n      </div>\n\n      {gitmojis.length === 0 ? (\n        <h2>No gitmojis found for search: {searchInput}</h2>\n      ) : (\n        gitmojis.map((gitmoji, index) => (\n          <Gitmoji\n            code={gitmoji.code}\n            description={gitmoji.description}\n            emoji={gitmoji.emoji}\n            isListMode={isListMode}\n            key={index}\n            // @ts-expect-error: This should be replaced with something like:\n            // typeof gitmojis[number]['name'] but JSON can't be exported `as const`\n            name={gitmoji.name}\n          />\n        ))\n      )}\n    </div>\n  )\n}\n\nexport default GitmojiList\n"
  },
  {
    "path": "packages/website/src/components/GitmojiList/styles.module.css",
    "content": ".gitmojiCode {\n  padding: 0 4px;\n  border-radius: 4px;\n  background-color: var(--notificationEmojiCodeColor);\n  color: var(--notificationText);\n}\n\n.closeButton {\n  width: 20px;\n  height: 20px;\n  position: absolute;\n  right: 4px;\n  top: 4px;\n  overflow: hidden;\n  text-indent: 100%;\n  cursor: pointer;\n  backface-visibility: hidden;\n}\n\n.closeButton:hover,\n.closeButton:focus {\n  outline: none;\n}\n\n.closeButton::before,\n.closeButton::after {\n  content: '';\n  position: absolute;\n  width: 3px;\n  height: 60%;\n  top: 50%;\n  left: 50%;\n  background: var(--notificationText);\n}\n\n.closeButton::before {\n  transform: translate(-50%, -50%) rotate(45deg);\n}\n\n.closeButton::after {\n  transform: translate(-50%, -50%) rotate(-45deg);\n}\n"
  },
  {
    "path": "packages/website/src/components/Icon/__tests__/icon.spec.tsx",
    "content": "import { render } from '@testing-library/react'\n\nimport Icon, { IconDefinitions } from '../index'\nimport * as stubs from './stubs'\n\ndescribe('Icon', () => {\n  it('should render the component with correct icon reference', () => {\n    const { container } = render(<Icon {...stubs.props} />)\n\n    const svg = container.querySelector('svg')\n    expect(svg).toBeInTheDocument()\n    expect(svg).toHaveClass(`icon-${stubs.props.name}`)\n\n    const use = container.querySelector('use')\n    expect(use).toBeInTheDocument()\n    expect(use).toHaveAttribute('xlink:href', `#icon-${stubs.props.name}`)\n  })\n\n  it('should render IconDefinitions with all symbols', () => {\n    const { container } = render(<IconDefinitions />)\n\n    const svg = container.querySelector('svg')\n    expect(svg).toBeInTheDocument()\n\n    const defs = container.querySelector('defs')\n    expect(defs).toBeInTheDocument()\n  })\n})\n"
  },
  {
    "path": "packages/website/src/components/Icon/__tests__/stubs.ts",
    "content": "export const props = {\n  name: 'star',\n}\n"
  },
  {
    "path": "packages/website/src/components/Icon/definitions.tsx",
    "content": "export const IconDefinitions = () => (\n  <svg\n    style={{ position: 'absolute', width: 0, height: 0 }}\n    width={0}\n    height={0}\n    version=\"1.1\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    xmlnsXlink=\"http://www.w3.org/1999/xlink\"\n  >\n    <defs>\n      <symbol id=\"icon-heart\" viewBox=\"0 0 64 64\">\n        <title>heart</title>\n        <path\n          className=\"heart\"\n          d=\"m61.1 18.2c-6.4-17-27.2-9.4-29.1-.9-2.6-9-22.9-15.7-29.1.9-6.9 18.5 26.7 35.1 29.1 37.8 2.4-2.2 36-19.6 29.1-37.8\"\n          fill=\"#ff5a79\"\n        />\n      </symbol>\n      <symbol id=\"icon-star\" viewBox=\"0 0 64 64\">\n        <title>star</title>\n        <path\n          className=\"twitter\"\n          d=\"M62,25.2H39.1L32,3l-7.1,22.2H2l18.5,13.7l-7,22.1L32,47.3L50.5,61l-7.1-22.2L62,25.2z\"\n          fill=\"#FFDD67\"\n        />\n      </symbol>\n      <symbol id=\"icon-twitter\" viewBox=\"0 0 64 64\">\n        <title>twitter</title>\n        <g fill=\"#42ade2\">\n          <path d=\"m59.8 24.3c0 0 1.1-6.2-3.5-3.4 0 0-.4-6.3-4.3-1.9 0 0-2.1-3.9-4.4-.3-3.1 4.8-5.2 12.4-3.2 25l3.8-2.5c2.7-7.9 12.4-8.8 13.7-13.1.9-3-2.1-3.8-2.1-3.8\" />\n          <path d=\"m22.1 17.6l-9.9 3.6c2.2-12 16.6-11.2 16.6-11.2s-6.8 3.2-6.7 7.6\" />\n          <path d=\"m23.7 19.8l-10.5 1.4c4.8-11.2 18.7-7.3 18.7-7.3s-7.3 1.6-8.2 5.9\" />\n        </g>\n        <g fill=\"#ffd93b\">\n          <path d=\"m2 29l5.4-1.4v3.6c0-.1-3.3-.6-5.4-2.2\" />\n          <path d=\"M7.4,27.5L2,24.8c3.6-2.8,7.7-1.9,7.7-1.9L7.4,27.5z\" />\n        </g>\n        <g fill=\"#e08828\">\n          <path d=\"m33.8 53h-2.1v7.9c-.3.1-2.1-.1-2.9-.1-1.8 0-3.3 1.3-3.3 1.3h8.3v-9.1\" />\n          <path d=\"m25 53h-2.1v7.9c-.3.1-2.1-.1-2.9-.1-1.8 0-3.3 1.3-3.3 1.3h8.3v-9.1\" />\n          <path\n            d=\"m54 36.2c3.9 0-4.1 17.5-23.3 17.5-13 0-23.9-5.2-23.9-21.5 0-10.1 6.4-18.3 19.5-15 13.3 3.5 6.5 19 27.7 19\"\n            fill=\"#42ade2\"\n          />\n          <path\n            d=\"m37.6 51.7c-15.6 0-14-12-27.9-11.2 5.1 15.8 27.9 11.2 27.9 11.2\"\n            fill=\"#fff\"\n          />\n          <path\n            d=\"m39.1 29.2c-10-9.8-20.2 6.2-7.9 12.6 12.1 6.2 20.4-4.8 20.4-4.8s-6.1-1.5-12.5-7.8\"\n            fill=\"#297b9d\"\n          />\n        </g>\n        <circle cx=\"15.1\" cy=\"24.9\" r=\"2.5\" fill=\"#3e4347\" />\n      </symbol>\n      <symbol id=\"icon-twitter-x\" viewBox=\"0 0 48 35\">\n        <title>twitter-x</title>\n        <path d=\"M12.91 5.477l14.813 19.882-14.907 16.164h3.356l13.05-14.152 10.544 14.152h11.418l-15.645-21L49.414 5.477H46.06l-12.02 13.035-9.71-13.035zm4.934 2.48h5.242L46.25 39.043h-5.246zm0 0\"></path>\n      </symbol>\n      <symbol id=\"icon-list\" x=\"0px\" y=\"0px\" viewBox=\"0 0 512 512\">\n        <title>list</title>\n        <path\n          fill=\"currentColor\"\n          d=\"M149.333 216v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-80c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zM125.333 32H24C10.745 32 0 42.745 0 56v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24zm80 448H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm-24-424v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24zm24 264H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24z\"\n          className=\"\"\n        ></path>\n      </symbol>\n      <symbol id=\"icon-grid\" viewBox=\"0 0 512 512\">\n        <title>grid</title>\n        <path\n          fill=\"currentColor\"\n          d=\"M149.333 56v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zm181.334 240v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm32-240v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24zm-32 80V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm-205.334 56H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm386.667-56H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm0 160H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zM181.333 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24z\"\n        ></path>\n      </symbol>\n      <symbol id=\"icon-light\" viewBox=\"0 0 24 24\">\n        <title>light</title>\n        <path\n          fill=\"currentColor\"\n          d=\"M3.563 18.563l1.781-1.828 1.406 1.406-1.781 1.828zM11.016 22.453v-2.953h1.969v2.953h-1.969zM12 5.484q2.484 0 4.242 1.758t1.758 4.242-1.758 4.242-4.242 1.758-4.242-1.758-1.758-4.242 1.758-4.242 4.242-1.758zM20.016 10.5h3v2.016h-3v-2.016zM17.25 18.141l1.406-1.359 1.781 1.781-1.406 1.406zM20.438 4.453l-1.781 1.781-1.406-1.406 1.781-1.781zM12.984 0.563v2.953h-1.969v-2.953h1.969zM3.984 10.5v2.016h-3v-2.016h3zM6.75 4.828l-1.406 1.406-1.781-1.781 1.406-1.406z\"\n        ></path>\n      </symbol>\n\n      <symbol id=\"icon-dark\" viewBox=\"0 0 24 24\">\n        <title>dark</title>\n        <path\n          fill=\"currentColor\"\n          d=\"M9.984 2.016q4.172 0 7.102 2.93t2.93 7.055-2.93 7.055-7.102 2.93q-2.719 0-4.969-1.313 2.297-1.313 3.633-3.633t1.336-5.039-1.336-5.039-3.633-3.633q2.25-1.313 4.969-1.313z\"\n        ></path>\n      </symbol>\n    </defs>\n  </svg>\n)\n"
  },
  {
    "path": "packages/website/src/components/Icon/index.tsx",
    "content": "export { IconDefinitions } from './definitions'\nimport styles from './styles.module.css'\n\ntype Props = { name: string }\n\nconst Icon = (props: Props) => (\n  <svg className={`${styles.icon} icon-${props.name}`}>\n    <use xlinkHref={`#icon-${props.name}`} />\n  </svg>\n)\n\nexport default Icon\n"
  },
  {
    "path": "packages/website/src/components/Icon/styles.module.css",
    "content": ".icon {\n  width: 1em;\n  height: 1em;\n  margin-right: 0.25em;\n}\n\n.icon:global(.icon-heart) {\n  margin: 0;\n}\n"
  },
  {
    "path": "packages/website/src/components/Layout/Footer/index.tsx",
    "content": "import Link from 'next/link'\n\nimport Icon from 'src/components/Icon'\nimport styles from './styles.module.css'\n\nconst Footer = () => (\n  <footer className={styles.footer}>\n    <div className=\"wrap\">\n      <div className=\"row middle-xs\">\n        <div className={`col-sm-6 ${styles.madeWithLove}`}>\n          <h3>\n            Made with <Icon name=\"heart\" /> by{' '}\n            <a href=\"https://carloscuesta.me\">Carlos Cuesta</a>\n          </h3>\n        </div>\n        <div className={`col-sm-6 ${styles.footerNav}`}>\n          <nav>\n            <Link href=\"/about\">About</Link>\n            <Link href=\"/contributors\">Contributors</Link>\n            <a href=\"https://github.com/carloscuesta/gitmoji\">GitHub</a>\n          </nav>\n        </div>\n      </div>\n    </div>\n  </footer>\n)\n\nexport default Footer\n"
  },
  {
    "path": "packages/website/src/components/Layout/Footer/styles.module.css",
    "content": ".footer {\n  padding: 1.5em;\n  background-color: var(--footerBackground);\n  color: var(--textInSecondary);\n}\n\n.footerNav {\n  -webkit-box-pack: end;\n  -ms-flex-pack: end;\n  justify-content: flex-end;\n  text-align: end;\n}\n\n.footerNav a:after {\n  content: '·';\n  color: var(--textInSecondary);\n  margin: 0 0.75em;\n}\n\n.footerNav a:last-child:after {\n  content: '';\n  margin: 0;\n}\n\n@media (max-width: 768px) {\n  .footer,\n  .footerNav {\n    justify-content: center;\n    text-align: center;\n  }\n\n  .madeWithLove,\n  .footerNav {\n    flex-basis: 100%;\n    max-width: 100%;\n  }\n}\n"
  },
  {
    "path": "packages/website/src/components/Layout/Hamburger/CloseIcon/index.tsx",
    "content": "const CloseIcon = () => (\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    width=\"48\"\n    height=\"48\"\n    fill=\"currentColor\"\n  >\n    <path d=\"M37.968 12.844L26.812 24L37.968 35.156L35.156 37.968L24 26.812L12.844 37.968L10.032 35.156L21.188 24L10.032 12.844L12.844 10.032L24 21.188L35.156 10.032L37.968 12.844Z\" />\n  </svg>\n)\n\nexport default CloseIcon\n"
  },
  {
    "path": "packages/website/src/components/Layout/Hamburger/MenuLink/index.tsx",
    "content": "'use client'\n\nimport Link from 'next/link'\nimport { usePathname } from 'next/navigation'\n\nimport styles from './styles.module.css'\n\ntype Props = { href: string; text: string }\n\nconst MenuLink = (props: Props) => {\n  const pathname = usePathname()\n  const isUserOnLinkPage: boolean = props.href === pathname\n\n  if (!props.href.startsWith('/')) {\n    return (\n      <a\n        className={styles.link}\n        href={props.href}\n        rel=\"noopener noreferrer\"\n        target=\"_blank\"\n      >\n        {props.text}\n      </a>\n    )\n  }\n\n  return (\n    <Link\n      className={[styles.link, isUserOnLinkPage && styles.linkActive].join(' ')}\n      href={props.href}\n    >\n      {props.text}\n    </Link>\n  )\n}\n\nexport default MenuLink\n"
  },
  {
    "path": "packages/website/src/components/Layout/Hamburger/MenuLink/styles.module.css",
    "content": ".link {\n  color: var(--text);\n  text-decoration: none;\n  font-weight: bold;\n}\n\n.link:hover {\n  text-decoration: underline;\n}\n\n.linkActive {\n  text-decoration: underline;\n}\n"
  },
  {
    "path": "packages/website/src/components/Layout/Hamburger/OpenIcon/index.tsx",
    "content": "const OpenIcon = () => (\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    width=\"48\"\n    height=\"48\"\n    fill=\"currentColor\"\n  >\n    <path d=\"M6 12H42V16.032H6V12ZM6 25.968V22.03H42V25.968H6ZM6 36V31.968H42V36H6Z\" />\n  </svg>\n)\n\nexport default OpenIcon\n"
  },
  {
    "path": "packages/website/src/components/Layout/Hamburger/index.tsx",
    "content": "'use client'\n\nimport { useState, useEffect } from 'react'\nimport { usePathname } from 'next/navigation'\nimport FocusTrap from 'focus-trap-react'\n\nimport MenuLink from './MenuLink'\nimport OpenIcon from './OpenIcon'\nimport CloseIcon from './CloseIcon'\nimport styles from './styles.module.css'\n\nconst Hamburger = () => {\n  const pathname = usePathname()\n  const [isOpen, setIsOpen] = useState(false)\n\n  useEffect(() => {\n    setIsOpen(false)\n  }, [pathname])\n\n  useEffect(() => {\n    if (isOpen) {\n      document.body.classList.add('overflow-hidden')\n    } else {\n      document.body.classList.remove('overflow-hidden')\n    }\n  }, [isOpen])\n\n  return (\n    <div className={styles.hamburger}>\n      <button\n        aria-label=\"Open navigation menu\"\n        className={styles.button}\n        onClick={() => setIsOpen(true)}\n      >\n        <OpenIcon />\n      </button>\n\n      {isOpen && (\n        <FocusTrap active={isOpen}>\n          <nav className={styles.menu}>\n            <div className={styles.closeContainer}>\n              <button\n                aria-label=\"Close navigation menu\"\n                className={styles.button}\n                onClick={() => setIsOpen(false)}\n              >\n                <CloseIcon />\n              </button>\n            </div>\n\n            <ul className={styles.links}>\n              <li>\n                <MenuLink href=\"/\" text=\"Home\" />\n              </li>\n              <li>\n                <MenuLink href=\"/about\" text=\"About\" />\n              </li>\n              <li>\n                <MenuLink href=\"/specification\" text=\"Specification\" />\n              </li>\n              <li>\n                <MenuLink href=\"/contributors\" text=\"Contributors\" />\n              </li>\n              <li>\n                <MenuLink href=\"/related-tools\" text=\"Related tools\" />\n              </li>\n            </ul>\n          </nav>\n        </FocusTrap>\n      )}\n    </div>\n  )\n}\n\nexport default Hamburger\n"
  },
  {
    "path": "packages/website/src/components/Layout/Hamburger/styles.module.css",
    "content": ".hamburger {\n  position: fixed;\n  right: 0;\n  z-index: 1;\n}\n\n.menu {\n  background: var(--menuBackground);\n  bottom: 0;\n  left: 0;\n  position: fixed;\n  right: 0;\n  top: 0;\n}\n\n.button {\n  background-color: transparent;\n  border: none;\n  color: inherit;\n  color: var(--secondary);\n  cursor: pointer;\n  display: flex;\n  font: inherit;\n  margin: 0;\n  padding: 0.75em;\n}\n\n.closeContainer {\n  position: absolute;\n  right: 0;\n}\n\n.closeContainer .button {\n  color: var(--textInSecondary);\n}\n\n.links {\n  align-items: center;\n  color: var(--textInSecondary);\n  display: flex;\n  flex-direction: column;\n  flex: 1;\n  font-size: 3em;\n  height: 100%;\n  justify-content: center;\n  list-style-type: none;\n  margin: 0;\n  padding: 0;\n}\n\n.links li {\n  padding: 0.5em 0;\n}\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/Status/Joy/index.tsx",
    "content": "export const Joy = () => (\n  <g id=\"joy\" transform=\"translate(304 32)\">\n    <g id=\"Group\">\n      <circle id=\"Oval\" cy={39} cx={39} r={39} fill=\"#FFDD67\" />\n      <path\n        id=\"Shape\"\n        fill=\"#664E27\"\n        d=\"m62 42.2c-0.5-0.7-1.5-0.6-2.5-0.6h-41c-1 0-2-0.1-2.5 0.6-5.1 6.4 0.9 25.4 23 25.4s28.1-19 23-25.4z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#4C3526\"\n        d=\"m41.4 51.7c-0.8-0.1-1.9 0.6-1.5 2.5 0.2 0.9 1.6 2.1 1.6 3.6 0 3.1-5 3.1-5 0 0-1.5 1.4-2.7 1.6-3.6 0.4-1.9-0.7-2.6-1.5-2.5-2 0-5.4 2.2-5.4 5.9 0 4.2 3.5 7.6 7.8 7.6s7.8-3.4 7.8-7.6c0-3.7-3.4-5.9-5.4-5.9z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#FF717F\"\n        d=\"m29 63.3c2.9 1.2 6.2 1.9 10 1.9s7.1-0.7 10-1.9c-2.8-1.4-6.1-2.2-10-2.2s-7.2 0.8-10 2.2z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#fff\"\n        d=\"m58.4 44.2h-38.8c-2.7 0-2.7 5.2-0.1 5.2h39c2.6 0 2.6-5.2-0.1-5.2z\"\n      />\n      <g id=\"Shape\" fill=\"#65B1EF\" transform=\"translate(0 37.7)\">\n        <path d=\"m74.7 7.64c9.5 9.96-3.4 23.6-12.9 13.6-7-7.3-7.3-21.2-7.3-21.2 0 0.013 13.2 0.347 20.2 7.64zm-58.5 13.6c-9.46 10-22.4-3.6-12.9-13.6 7-7.25 20.2-7.59 20.2-7.59 0 0.003-0.3 13.9-7.3 21.2z\" />\n      </g>\n      <g id=\"Shape\" fill=\"#664E27\" transform=\"translate(14.3 24.7)\">\n        <path d=\"m20.2 9.97c-2.4-6.64-6.1-9.97-9.7-9.97-3.66 0-7.3 3.33-9.71 9.97-0.243 0.63 1 1.83 1.63 1.23 2.34-2.48 5.14-3.47 8.08-3.47 2.9 0 5.7 0.99 8.1 3.47 0.6 0.6 1.8-0.6 1.6-1.23zm28.4 0c-2.4-6.64-6-9.97-9.7-9.97-3.6 0-7.3 3.33-9.7 9.97-0.2 0.63 1 1.83 1.6 1.23 2.4-2.48 5.2-3.47 8.1-3.47s5.7 0.99 8.1 3.47c0.6 0.6 1.9-0.6 1.6-1.23z\" />\n      </g>\n    </g>\n  </g>\n)\n\nexport default Joy\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/Status/Loved/index.tsx",
    "content": "export const Loved = () => (\n  <g id=\"loved\" transform=\"translate(304 32)\">\n    <g id=\"Group\">\n      <path\n        id=\"Shape\"\n        fill=\"#FFDD67\"\n        d=\"m78 39c0 21.5-17.5 39-39 39s-39-17.5-39-39 17.5-39 39-39 39 17.5 39 39z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#F46767\"\n        d=\"m77.8 14.6c-0.6-3.5-2.6-6.37-5.8-7.23-3.4-0.95-6.6 0.41-9.7 3.53-1.7-4.74-4.3-8.24-8.4-10-4.3-1.89-8.4-0.645-11 2.64-2.7 3.42-3.8 8.66-0.9 15.6 2.7 6.5 14.9 19.5 15.2 19.9 0.5-0.3 14-8.7 17.3-12.9 3.2-4 3.9-8.1 3.3-11.5zm-42.7-11.1c-2.6-3.28-6.7-4.53-11-2.68-4.1 1.8-6.7 5.3-8.4 10-3.1-3.12-6.25-4.48-9.7-3.53-3.16 0.86-5.2 3.73-5.8 7.23-0.599 3.4 0.072 7.5 3.31 11.5 3.31 4.2 16.8 12.6 17.3 12.9 0.3-0.4 12.5-13.4 15.2-19.9 2.9-6.9 1.8-12.1-0.9-15.6v0.04z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#664E27\"\n        d=\"m61.1 46.9c0-1.1-0.6-2.4-2.4-2.7-4.5-0.9-11.1-1.8-19.7-1.8s-15.2 0.9-19.7 1.8c-1.8 0.3-2.4 1.6-2.4 2.7 0 9.4 7.3 18.9 22.1 18.9s22.1-9.5 22.1-18.9z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#fff\"\n        d=\"m55.5 47.2c-2.9-0.5-8.9-1.3-16.5-1.3s-13.6 0.8-16.5 1.3c-1.7 0.3-1.8 0.9-1.7 1.9 0.1 0.6 0.2 1.3 0.4 2 0.2 0.9 0.3 1.2 1.6 1.1 2.5-0.3 29.9-0.3 32.4 0 1.3 0.1 1.4-0.2 1.6-1.1 0.2-0.7 0.3-1.4 0.4-2 0.1-1 0-1.6-1.7-1.9z\"\n      />\n    </g>\n  </g>\n)\n\nexport default Loved\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/Status/Sexy/index.tsx",
    "content": "export const Sexy = () => (\n  <g id=\"sexy\" transform=\"translate(304 32)\">\n    <g id=\"Group\">\n      <ellipse id=\"Oval\" rx={39} ry={39} cy={39} cx={39} fill=\"#FFDD67\" />\n      <ellipse\n        id=\"Oval\"\n        rx=\"10.4\"\n        ry=\"10.4\"\n        cy=\"45.7\"\n        cx=\"66.1\"\n        fill=\"#FF717F\"\n      />\n      <ellipse\n        id=\"Oval\"\n        rx=\"10.4\"\n        ry=\"10.4\"\n        cy=\"45.7\"\n        cx=\"11.9\"\n        fill=\"#FF717F\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#917524\"\n        d=\"m68.4 24.2c-3.5-4.2-8.7-6.7-14.2-6.6-0.8 0-1-2.9 0-2.9 6.3 0 12.4 2.8 16.4 7.7 0.6 0.7-1.7 2.4-2.2 1.8zm-44.6-6.8c-5.5 0-10.7 2.4-14.2 6.6-0.52 0.6-2.81-1.1-2.23-1.8 4.03-4.9 10.1-7.7 16.4-7.7 1 0 0.8 2.9 0 2.9z\"\n      />\n      <ellipse id=\"Oval\" rx=\"5.85\" ry=\"5.85\" cy=\"61.7\" cx={39} fill=\"#664E27\" />\n      <path\n        id=\"Shape\"\n        fill=\"#fff\"\n        d=\"m35.8 35.3c0 6.4-5.3 11.7-11.8 11.7-6.4 0-11.6-5.3-11.6-11.7 0-6.5 5.2-11.7 11.6-11.7 6.5 0 11.8 5.2 11.8 11.7z\"\n      />\n      <ellipse id=\"Oval\" rx=\"5.85\" ry=\"5.85\" cy=\"35.3\" cx={24} fill=\"#664E27\" />\n      <g transform=\"translate(41.6 23.4)\">\n        <path\n          id=\"Shape\"\n          fill=\"#fff\"\n          d=\"m24 11.9c0 6.4-5.2 11.7-11.6 11.7-6.51 0-11.8-5.3-11.8-11.7 0.05-6.48 5.29-11.7 11.8-11.7 6.4-0.022 11.6 5.22 11.6 11.7z\"\n        />\n        <ellipse\n          id=\"Oval\"\n          rx=\"5.85\"\n          ry=\"5.85\"\n          cy=\"11.9\"\n          cx=\"12.4\"\n          fill=\"#664E27\"\n        />\n      </g>\n    </g>\n  </g>\n)\n\nexport default Sexy\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/Status/Smiling/index.tsx",
    "content": "export const Smiling = () => (\n  <g id=\"haha\" transform=\"translate(304 32)\">\n    <g id=\"Group\">\n      <path\n        id=\"Oval\"\n        fill=\"#FFDD67\"\n        d=\"m39 78c21.5 0 39-17.5 39-39s-17.5-39-39-39-39 17.5-39 39 17.5 39 39 39z\"\n      />\n      <g id=\"Shape\" fill=\"#664E27\" transform=\"translate(11.7 20.5)\">\n        <path d=\"m52.9 2.09c0.3 0.15 0.4 0.47 0.4 0.79-0.1 0.32-0.3 0.57-0.6 0.63-3.5 0.52-7.3 1.12-10.8 3.07 5.2 0.87 9.4 3.52 11.7 6.32 0.5 0.6-0.1 1.4-0.7 1.2-6.2-2.3-12.6-3.5-20.6-2.6-0.6 0-1.2-0.3-1-0.9 2.1-9.39 14.2-12.9 21.6-8.51zm-51.2 0c-0.29 0.15-0.45 0.47-0.4 0.79s0.3 0.57 0.62 0.63c3.5 0.52 7.21 1.12 10.8 3.07-5.35 0.87-9.55 3.52-11.8 6.32-0.538 0.6 0.11 1.4 0.68 1.2 6.2-2.3 12.6-3.5 20.6-2.6 0.6 0 1.2-0.3 1-0.9-2.1-9.39-14.2-12.9-21.6-8.51h0.03z\" />\n      </g>\n      <path\n        id=\"Shape\"\n        fill=\"#664E27\"\n        d=\"m62 42.2c-0.5-0.7-1.5-0.6-2.5-0.6h-41c-1 0-2-0.1-2.5 0.6-5.1 6.4 0.9 25.4 23 25.4s28.1-19 23-25.4z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#4C3526\"\n        d=\"m41.4 51.7c-0.8-0.1-1.9 0.6-1.5 2.5 0.2 0.9 1.6 2.1 1.6 3.6 0 3.1-5 3.1-5 0 0-1.5 1.4-2.7 1.6-3.6 0.4-1.9-0.7-2.6-1.5-2.5-2 0-5.4 2.2-5.4 5.9 0 4.2 3.5 7.6 7.8 7.6s7.8-3.4 7.8-7.6c0-3.7-3.4-5.9-5.4-5.9z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#FF717F\"\n        d=\"m29 63.3c2.9 1.2 6.2 1.9 10 1.9s7.1-0.7 10-1.9c-2.8-1.4-6.1-2.2-10-2.2s-7.2 0.8-10 2.2z\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#fff\"\n        d=\"m58.4 44.2h-38.8c-2.7 0-2.7 5.2-0.1 5.2h39c2.6 0 2.6-5.2-0.1-5.2z\"\n      />\n    </g>\n  </g>\n)\n\nexport default Smiling\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/Status/Sunglasses/index.tsx",
    "content": "export const Sunglasses = () => (\n  <g id=\"sunglasses\" transform=\"translate(304 32)\">\n    <g id=\"Group\">\n      <path\n        id=\"Shape\"\n        fill=\"#FFDD67\"\n        d=\"m39 0c21.5 0 39 17.5 39 39s-17.5 39-39 39-39-17.5-39-39 17.5-39 39-39\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#494949\"\n        d=\"m44 24c-2.9 1.4-7.1 1.4-10 0-3.1-1.6-6.8-2.6-11.3-2.9-4.3-0.4-13.6-0.4-18.2 1.2-0.52 0.2-1.04 0.4-1.55 0.7-0.28 0.1-0.34 0.2-0.34 0.8v0.7c0 1.3-0.16 0.8 0.76 1.3 1.8 1 2.82 3.8 3.36 7.5 0.78 5.5 3.47 8.9 7.87 10.6 4 1.5 8.5 1.5 12.6-0.2 2.2-0.8 4.1-2.2 5.6-4.5 2.7-3.9 1.9-6.4 3.3-9.8 1.2-2.9 4.6-2.9 5.8 0 1.4 3.4 0.6 5.9 3.3 9.8 1.5 2.3 3.4 3.7 5.6 4.5 4.1 1.7 8.6 1.7 12.6 0.2 4.4-1.7 7.1-5.1 7.9-10.6 0.5-3.7 1.5-6.5 3.3-7.5 0.9-0.5 0.8 0 0.8-1.3v-0.7c0-0.6-0.1-0.7-0.4-0.8-0.5-0.3-1-0.5-1.5-0.7-4.6-1.6-13.9-1.6-18.2-1.2-4.5 0.3-8.2 1.3-11.3 2.9\"\n      />\n      <path\n        id=\"Shape\"\n        fill=\"#664E27\"\n        d=\"m55.4 52.4c-10.6 7.3-22.3 7.3-32.8 0-1.2-0.9-2.4 0.6-1.5 2 3.2 5.3 9.6 10 17.9 10s14.7-4.7 17.9-10c0.9-1.4-0.3-2.9-1.5-2z\"\n      />\n    </g>\n  </g>\n)\n\nexport default Sunglasses\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/Status/Tongue/index.tsx",
    "content": "export const Tongue = () => (\n  <g id=\"tongue\" transform=\"translate(304 32)\">\n    <g id=\"Group\">\n      <ellipse id=\"Oval\" rx={39} ry={39} cy={39} cx={39} fill=\"#FFDD67\" />\n      <path\n        id=\"Shape\"\n        fill=\"#fff\"\n        d=\"m38 29.4c0 7.1-5.8 13-13 13s-13-5.9-13-13c0-7.2 5.8-13 13-13s13 5.8 13 13z\"\n      />\n      <ellipse id=\"Oval\" rx=\"5.85\" ry=\"5.85\" cy=\"29.4\" cx={25} fill=\"#664E27\" />\n      <path\n        id=\"Shape\"\n        fill=\"#664E27\"\n        d=\"m63.7 35.3c-2.5-5.3-6.1-8-9.7-8-3.7 0-7.3 2.7-9.8 8-0.2 0.5 1 1.5 1.7 0.9 2.3-1.9 5.1-2.7 8.1-2.7 2.9 0 5.7 0.8 8 2.7 0.7 0.6 1.9-0.4 1.7-0.9z\"\n      />\n      <g id=\"Shape\" transform=\"translate(16.9 46.8)\">\n        <path\n          d=\"m42.7 0h-41.2c-0.989 0-1.5 0.659-1.5 1.3 0.0013 9.5 7.75 19.5 22.1 19.5s22.1-10 22.1-19.5c0-0.641-0.5-1.3-1.5-1.3z\"\n          fill=\"#664E27\"\n        />\n        <path\n          d=\"m34 7.8h-11.9-11.9c-0.95 0-1.1 0.41-1.1 1.1v5.2c0 11.4 5.8 17.1 13 17.1s13-5.7 13-17.1v-5.2c0-0.69-0.1-1.1-1.1-1.1z\"\n          fill=\"#FF717F\"\n        />\n        <polygon points=\"24 7.8 22.1 25.7 20.2 7.8\" fill=\"#E2596C\" />\n      </g>\n    </g>\n  </g>\n)\n\nexport default Tongue\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/Status/index.tsx",
    "content": "import Joy from './Joy'\nimport Loved from './Loved'\nimport Sexy from './Sexy'\nimport Smiling from './Smiling'\nimport Sunglasses from './Sunglasses'\nimport Tongue from './Tongue'\n\nexport const LOGO_STATUSES = {\n  JOY: 'JOY',\n  LOVED: 'LOVED',\n  SEXY: 'SEXY',\n  SMILING: 'SMILING',\n  SUNGLASSES: 'SUNGLASSES',\n  TONGUE: 'TONGUE',\n} as const\n\nexport type EmojiLogoStatus = keyof typeof LOGO_STATUSES | null\n\ntype Props = { status: EmojiLogoStatus }\n\nconst Status = (props: Props) => {\n  switch (props.status) {\n    case LOGO_STATUSES.JOY:\n      return <Joy />\n    case LOGO_STATUSES.LOVED:\n      return <Loved />\n    case LOGO_STATUSES.SEXY:\n      return <Sexy />\n    case LOGO_STATUSES.SMILING:\n      return <Smiling />\n    case LOGO_STATUSES.SUNGLASSES:\n      return <Sunglasses />\n    case LOGO_STATUSES.TONGUE:\n      return <Tongue />\n    default:\n      return null\n  }\n}\n\nexport default Status\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/Status/styles.module.css",
    "content": ""
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/index.tsx",
    "content": "'use client'\n\nimport { useState, useEffect } from 'react'\n\nimport Status, { LOGO_STATUSES, type EmojiLogoStatus } from './Status'\nimport styles from './styles.module.css'\n\nconst Logo = () => {\n  const statuses = Object.values(LOGO_STATUSES)\n  const [status, setStatus] = useState<EmojiLogoStatus>(null)\n\n  useEffect(() => {\n    setStatus(statuses[Math.floor(Math.random() * statuses.length)])\n  }, [])\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={styles.logo}\n      height=\"137px\"\n      width=\"457px\"\n      version=\"1.1\"\n      xmlnsXlink=\"http://www.w3.org/1999/xlink\"\n      viewBox=\"0 0 457 137\"\n    >\n      <title>gitmoji</title>\n      <g id=\"gitmoji\" fillRule=\"evenodd\" fill=\"none\">\n        <g id=\"Logo\" transform=\"translate(-270 -430)\">\n          <g id=\"gitmoji\" transform=\"translate(270 430)\">\n            <path\n              d=\"m17.5 106c0.6 4 2.4 7 5.3 10 2.9 2 6.6 4 11.2 4 6.1 0 10.7-2 14-5s4.9-8 4.9-15.1v-5.1c-1.5 2.3-3.8 4.4-7.1 6.2-3.2 2-7.5 3-12.6 3-4.7 0-9.1-1-13.1-3-4.1-1.5-7.6-3.9-10.5-7-2.91-3-5.22-6.7-6.9-10.8-1.68-4.2-2.52-8.8-2.52-13.8 0.004-4.7 0.82-9.1 2.45-13.3s3.89-7.9 6.77-11c2.9-3.2 6.3-5.7 10.4-7.5 4-1.8 8.5-2.7 13.4-2.7 5.6 0 10.1 1 13.4 3 3.2 2 5.5 4.2 6.7 6.6v-8.3h18.5v63.2c0 4.6-0.7 9.6-2.1 13.6-1.4 5-3.6 9-6.6 12-3 4-6.8 6-11.5 8s-10.4 4-17 4c-4.9 0-9.3-1-13.3-3-4-1-7.5-3-10.5-5-2.94-3-5.34-5-7.16-8-1.82-4-2.98-7-3.46-10l17.3-5zm19-18.6c4.9 0 8.9-1.6 12-4.9 3.1-3.2 4.7-7.6 4.7-13.1s-1.7-9.8-4.9-13c-3.3-3.2-7.2-4.8-11.8-4.8-2.4 0-4.7 0.4-6.7 1.2-2.1 0.8-3.9 2-5.4 3.6-1.6 1.6-2.8 3.5-3.6 5.7-0.9 2.2-1.3 4.6-1.3 7.3 0 5.6 1.6 10 4.7 13.2 3.2 3.2 7.3 4.8 12.3 4.8zm54.7 19.6v-70.8h18.8v70.8h-18.8zm-2.3-94c0-3.39 1.1-6.22 3.4-8.53 2.3-2.3 5.1-3.45 8.7-3.45 3 0 6 1.15 8 3.45 2 2.31 4 5.14 4 8.53 0 3.1-2 5.9-4 8.2s-5 3.4-8 3.4c-3.6 0-6.4-1.1-8.7-3.4s-3.4-5.1-3.4-8.2zm65.1 23.2h15v16.9h-15v29.7c0 3.1 1 5.2 2 6.4 2 1.2 4 1.8 7 1.8 1 0 2 0 3-0.1s2-0.3 3-0.5v15.6c-1 1-3 1-4 1-2 1-4 1-7 1-7 0-13-2-17-6-4-3.6-6-9-6-15.9v-33h-12v-16.9h3c4 0 7-1.1 8-3.3 2-2.1 3-4.8 3-8v-9.9h17v21.2zm30 70.8v-70.8h18v8.6c1-1.7 2-3.3 4-4.6 1-1.4 3-2.5 5-3.3 2-0.9 4-1.6 6-2 2-0.5 4-0.8 6-0.8 5 0 9 1 13 3.1 3 2 6 4.9 8 8.7 3-4.3 6-7.3 10-9.1s8-2.7 12-2.7 7 0.5 10 1.5c3 1.1 6 2.7 8 4.9 3 2.2 4 5 6 8.4 1 3.4 2 7.5 2 12.2v45.9h-19v-42c0-3.9 0-7.1-2-9.6-2-2.6-6-3.8-10-3.8s-7 1.3-10 4.1c-2 2.7-3 6-3 9.8v41.5h-19v-42c0-3.9-1-7.1-3-9.6-2-2.6-5-3.8-10-3.8-4 0-7 1.3-9 4-3 2.7-4 6-4 9.9v41.5h-19zm159-15.3c3 0 5-0.4 7-1.3 2-0.8 4-2.1 6-3.8 1-1.7 3-3.7 4-6.2s1-5.5 1-8.8c0-3.4 0-6.3-1-8.8s-3-4.6-4-6.3c-2-1.7-4-2.9-6-3.8s-4-1.3-7-1.3c-2 0-4 0.4-6 1.3-3 0.9-5 2.1-6 3.8-2 1.7-3 3.8-4 6.3s-2 5.4-2 8.8c0 3.3 1 6.3 2 8.8s2 4.5 4 6.2c1 1.7 3 3 6 3.8 2 0.9 4 1.3 6 1.3zm0-57.7c6 0 11 0.9 15 2.8 5 1.9 9 4.5 12 7.8s6 7.2 8 11.9c2 4.6 2 9.6 2 15.1 0 5.4 0 10.5-2 15-2 4.6-5 8.5-8 11.9-3 3.5-7 5.5-12 7.5-4 2-9 3-15 3-5 0-10-1-14-3-5-2-9-4-12-7.5-4-3.4-6-7.3-8-11.9-2-4.5-3-9.6-3-15 0-5.5 1-10.5 3-15.1 2-4.7 4-8.6 8-11.9 3-3.3 7-5.9 12-7.8 4-1.9 9-2.8 14-2.8zm53 2.2h19v76.8c0 4-1 7-2 10-1 2-2 5-4 7s-4 4-7 5-6 2-9 2-6-1-8-1c-2-1-3-1-3-1v-16h2c1 1 2 1 4 1 3 0 5-1 6-3 1-1 2-3 2-6v-74.8zm-3-23.4c0-3.34 1-6.17 4-8.47 2-2.31 5-3.46 8-3.46 3 0.002 6 1.15 9 3.46 2 2.3 3 5.13 3 8.47 0 3.3-1 6-3 8.3-3 2.3-6 3.4-9 3.4s-6-1.1-8-3.4c-3-2.3-4-5-4-8.3zm42 94.2v-70.8h19v70.8h-19zm-2-94c0-3.39 1-6.22 3-8.53 3-2.3 5-3.45 9-3.45 3 0 6 1.15 8 3.45 2 2.31 4 5.14 4 8.53 0 3.1-2 5.9-4 8.2s-5 3.4-8 3.4c-4 0-6-1.1-9-3.4-2-2.3-3-5.1-3-8.2z\"\n              fill=\"#000\"\n            />\n            <Status status={status} />\n          </g>\n        </g>\n      </g>\n    </svg>\n  )\n}\n\nexport default Logo\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/Logo/styles.module.css",
    "content": ".logo {\n  width: 100%;\n  height: 115px;\n}\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/index.tsx",
    "content": "import Button from 'src/components/Button'\nimport Logo from './Logo'\nimport styles from './styles.module.css'\n\ntype Props = { withHeadline: boolean }\n\nconst Header = (props: Props) => (\n  <header className={styles.header}>\n    <Logo />\n    {props.withHeadline && (\n      <h2 className={styles.title}>An emoji guide for your commit messages</h2>\n    )}\n    <div className={styles.buttons}>\n      <Button\n        icon=\"star\"\n        link=\"https://github.com/carloscuesta/gitmoji\"\n        text=\"GitHub\"\n      />\n      <Button\n        icon=\"twitter-x\"\n        link={\n          'https://twitter.com/intent/tweet?text=gitmoji' +\n          '%20%E2%80%93%20An%20%23emoji%20guide%20for%20your%20commit' +\n          '%20messages%20by%20%40crloscuesta%20%F0%9F%98%8D%F0%9F%98%9C' +\n          '&url=https://gitmoji.dev'\n        }\n        target=\"_blank\"\n        text=\"Share\"\n      />\n    </div>\n  </header>\n)\n\nexport default Header\n"
  },
  {
    "path": "packages/website/src/components/Layout/Header/styles.module.css",
    "content": ".header {\n  background-color: var(--primary);\n  padding: 4.5em 2em;\n  text-align: center;\n}\n\n.title {\n  padding: 0.5em 0;\n  margin: 0;\n  font-size: 2em;\n  color: var(--textInPrimary);\n}\n\n.buttons {\n  padding: 1em 0;\n  text-align: center;\n}\n\n.buttons a:first-child {\n  margin-right: 1em;\n}\n"
  },
  {
    "path": "packages/website/src/components/Layout/__tests__/layout.spec.tsx",
    "content": "import { render, screen } from '@testing-library/react'\n\nimport Layout from '../index'\nimport Status, { LOGO_STATUSES } from '../Header/Logo/Status'\nimport * as stubs from './stubs'\n\njest.mock('next/navigation', () => ({\n  usePathname: jest.fn(() => '/'),\n}))\n\ndescribe('Layout', () => {\n  beforeAll(() => {\n    Math.random = jest.fn().mockReturnValue(1)\n  })\n\n  beforeEach(() => {\n    jest.clearAllMocks()\n  })\n\n  it('should render the component with children', () => {\n    render(\n      <Layout {...stubs.props}>\n        <p>Some children</p>\n      </Layout>,\n    )\n\n    expect(screen.getByText('Some children')).toBeInTheDocument()\n  })\n\n  describe('Logo', () => {\n    Object.values(LOGO_STATUSES)\n      .map((status) => status)\n      .forEach((status) => {\n        it('should render Logo with status ' + status, () => {\n          const { container } = render(<Status status={status} />)\n\n          expect(container.firstChild).toBeInTheDocument()\n        })\n      })\n  })\n})\n"
  },
  {
    "path": "packages/website/src/components/Layout/__tests__/stubs.ts",
    "content": "export const props = {\n  headerWithSocialButtons: true,\n}\n"
  },
  {
    "path": "packages/website/src/components/Layout/index.tsx",
    "content": "import { IconDefinitions } from 'src/components/Icon'\nimport Header from './Header'\nimport Hamburger from './Hamburger'\nimport Footer from './Footer'\n\ntype Props = { children: React.ReactNode }\n\nconst Layout = (props: Props) => (\n  <>\n    <IconDefinitions />\n    <Hamburger />\n    <Header withHeadline />\n    <main className=\"wrap\">{props.children}</main>\n    <Footer />\n  </>\n)\n\nexport default Layout\n"
  },
  {
    "path": "packages/website/src/utils/theme/theme.css",
    "content": ":root {\n  --background: #ffffff;\n  --primary: #ffdd67;\n  --primaryShadow: #ffcc1b;\n  --secondary: #ff5a79;\n  --secondaryShadow: #f3002e;\n  --textInPrimary: #000000;\n  --textInSecondary: #ffffff;\n  --footerBackground: #00e5ff;\n  --cardBackground: #ffffff;\n  --cardText: #999999;\n  --emojiCodeText: #000000;\n  --cardShadow: rgba(168, 182, 191, 0.6);\n  --notificationText: #ffffff;\n  --notificationShadow: rgba(0, 0, 0, 0.05);\n  --notificationEmojiCodeColor: rgba(0, 0, 0, 0.85);\n  --menuBackground: #ff5a79;\n  --carbonAdBadgeBackground: #f1f1f1;\n}\n\n[data-theme='dark'] {\n  --background: #121212;\n  --primary: #ffdd67;\n  --primaryShadow: #ffcc1b;\n  --secondary: #ff5a79;\n  --secondaryShadow: #f3002e;\n  --textInPrimary: #000000;\n  --textInSecondary: #ffffff;\n  --footerBackground: #00e5ff;\n  --cardBackground: #2b2b2b;\n  --cardText: #ffffff;\n  --emojiCodeText: #ffffff;\n  --cardShadow: none;\n  --notificationText: #ffffff;\n  --notificationShadow: rgba(0, 0, 0, 0.05);\n  --notificationEmojiCodeColor: rgba(0, 0, 0, 0.85);\n  --menuBackground: #ff5a79;\n  --carbonAdBadgeBackground: #2b2b2b;\n}\n\n[data-theme='dark'] body {\n  color: var(--cardText);\n}\n\nhtml,\nbody {\n  background-color: var(--background);\n  margin: 0;\n  padding: 0;\n  font-size: 16.5px;\n  font-family:\n    Avenir,\n    -apple-system,\n    BlinkMacSystemFont,\n    'Segoe UI',\n    'Roboto',\n    'Oxygen',\n    'Ubuntu',\n    'Cantarell',\n    'Fira Sans',\n    'Droid Sans',\n    'Helvetica Neue',\n    sans-serif;\n}\n\nh1 {\n  font-size: 2em;\n}\n\na {\n  text-decoration: none;\n  color: var(--secondary);\n}\n\na:hover {\n  animation: zomg 0.5s infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  a:hover {\n    animation: none;\n    text-decoration: underline;\n  }\n}\n\ncode {\n  font-family:\n    Avenir,\n    -apple-system,\n    BlinkMacSystemFont,\n    'Segoe UI',\n    'Roboto',\n    'Oxygen',\n    'Ubuntu',\n    'Cantarell',\n    'Fira Sans',\n    'Droid Sans',\n    'Helvetica Neue',\n    sans-serif;\n  font-weight: 700;\n  font-size: 1.25em;\n  word-break: break-all;\n}\n\nsection {\n  padding: 0.5em;\n}\n\npre {\n  background-color: var(--primary);\n  border-radius: 4px;\n  box-shadow: 0 4px var(--primaryShadow);\n  color: var(--textInPrimary);\n  padding: 1em;\n}\n\n.overflow-hidden {\n  overflow: hidden;\n}\n\n.overflow-x-adjust {\n  overflow-x: auto;\n}\n\n.wrap {\n  max-width: 1100px;\n  margin: 0 auto;\n}\n\nmain.wrap {\n  padding: 2em;\n}\n\n@keyframes zomg {\n  0%,\n  100% {\n    color: #7ccdea;\n  }\n\n  16% {\n    color: #0074d9;\n  }\n\n  32% {\n    color: #2ecc40;\n  }\n\n  48% {\n    color: #ffdc00;\n  }\n\n  64% {\n    color: #b10dc9;\n  }\n\n  80% {\n    color: #ff4136;\n  }\n}\n\n@media (min-width: 2048px) {\n  html,\n  body {\n    font-size: 19px;\n  }\n}\n\n/* Flexboxgrid critical */\n\n.col-sm-2,\n.col-xs-12,\n.col-xs-3,\n.row {\n  box-sizing: border-box;\n}\n.container {\n  margin-right: auto;\n  margin-left: auto;\n}\n.row {\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-flex: 0;\n  -webkit-flex: 0 1 auto;\n  -ms-flex: 0 1 auto;\n  flex: 0 1 auto;\n  -webkit-box-orient: horizontal;\n  -webkit-box-direction: normal;\n  -webkit-flex-direction: row;\n  -ms-flex-direction: row;\n  flex-direction: row;\n  -webkit-flex-wrap: wrap;\n  -ms-flex-wrap: wrap;\n  flex-wrap: wrap;\n  margin-right: -0.5rem;\n  margin-left: -0.5rem;\n}\n.col-xs-12,\n.col-xs-3 {\n  -webkit-box-flex: 0;\n  -webkit-flex: 0 0 auto;\n  -ms-flex: 0 0 auto;\n  flex: 0 0 auto;\n  padding-right: 1.25rem;\n  padding-left: 1.25rem;\n}\n.col-xs-12 {\n  -webkit-flex-basis: 100%;\n  -ms-flex-preferred-size: 100%;\n  flex-basis: 100%;\n  max-width: 100%;\n}\n.col-xs-3 {\n  -ms-flex-preferred-size: 25%;\n  flex-basis: 25%;\n  max-width: 25%;\n}\n.center-xs {\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  text-align: center;\n}\n.middle-xs {\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n  -ms-flex-align: center;\n  align-items: center;\n}\n@media only screen and (min-width: 48em) {\n  .container {\n    width: 49rem;\n  }\n  .col-sm-2,\n  .col-sm-6 {\n    box-sizing: border-box;\n    -webkit-box-flex: 0;\n    -webkit-flex: 0 0 auto;\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    padding-right: 1.25rem;\n    padding-left: 1.25rem;\n  }\n  .col-sm-6 {\n    -webkit-flex-basis: 50%;\n    -ms-flex-preferred-size: 50%;\n    flex-basis: 50%;\n    max-width: 50%;\n  }\n  .col-sm-2 {\n    -ms-flex-preferred-size: 16.66666667%;\n    flex-basis: 16.66666667%;\n    max-width: 16.66666667%;\n  }\n}\n@media only screen and (min-width: 64em) {\n  .container {\n    width: 65rem;\n  }\n  .col-md-3 {\n    box-sizing: border-box;\n    -webkit-box-flex: 0;\n    -webkit-flex: 0 0 auto;\n    -ms-flex: 0 0 auto;\n    flex: 0 0 auto;\n    padding-right: 1.25rem;\n    padding-left: 1.25rem;\n    -ms-flex-preferred-size: 25%;\n    flex-basis: 25%;\n    max-width: 25%;\n  }\n  .col-md-4 {\n    -ms-flex-preferred-size: 33.33333333%;\n    flex-basis: 33.33333333%;\n    max-width: 33.33333333%;\n  }\n}\n"
  },
  {
    "path": "packages/website/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"target\": \"es6\",\n    \"lib\": [\n      \"dom\",\n      \"dom.iterable\",\n      \"esnext\"\n    ],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noEmit\": true,\n    \"incremental\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ]\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".next/dev/types/**/*.ts\"\n  ],\n  \"exclude\": [\n    \"node_modules\"\n  ]\n}\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - 'packages/*'\n"
  },
  {
    "path": "turbo.json",
    "content": "{\n  \"$schema\": \"https://turbo.build/schema.json\",\n  \"tasks\": {\n    \"dev\": {\n      \"dependsOn\": [\"^build\"],\n      \"cache\": false,\n      \"persistent\": true\n    },\n    \"lint\": {\n      \"dependsOn\": [\"^build\"],\n      \"outputs\": []\n    },\n    \"tscheck\": {\n      \"dependsOn\": [\"^build\"],\n      \"outputs\": []\n    },\n    \"test\": {\n      \"dependsOn\": [\"^build\"],\n      \"outputs\": [\"coverage/**\"]\n    },\n    \"build\": {\n      \"outputs\": [\".next/**\", \"public/**\", \"dist/**\"],\n      \"dependsOn\": [\"^build\"]\n    },\n    \"publishPackage\": {\n      \"dependsOn\": [\"^lint\"],\n      \"outputs\": []\n    }\n  }\n}\n"
  }
]