diff --git a/.dockerignore b/.dockerignore index ab350a72f..0096a00a7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -38,7 +38,6 @@ node_modules/ /app/assets/javascripts/generated/* latest.dump .byebug_history -.gitdocs_build/ # Ignore application configuration /public/packs diff --git a/.gitdocs.js b/.gitdocs.js deleted file mode 100644 index 577ad7eda..000000000 --- a/.gitdocs.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is created so that it's possible to - * Run `gitdocs serve` from root - */ - -var config = require('./docs/.gitdocs.json'); - -module.exports = new Promise((resolve, reject) => { - config.root = 'docs/'; - setupHost(config); - resolve(config); -}); - -function fetchAppDomain() { - const { execSync } = require('child_process'); - - const appDomainGetCmd = - 'rails runner "puts ApplicationConfig.app_domain_no_port"'; - return execSync(appDomainGetCmd).toString().replace(/\s/g, ''); -} - -function setupHost(config) { - const appDomain = fetchAppDomain(); - - if (config.host === '0.0.0.0' && appDomain) { - config.host = appDomain; - } -} diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6cff4fb11..a2dd8c469 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -41,7 +41,7 @@ images for UI changes._ _If your PR includes UI changes, please replace this line with details on how accessibility is impacted and tested. For more info, check out the -[Forem Accessibility Docs](https://docs.forem.com/frontend/accessibility)._ +[Forem Accessibility Docs](https://developers.forem.com/frontend/accessibility)._ ## Added/updated tests? @@ -56,7 +56,7 @@ _Will this PR introduce a change that impacts Forem members or creators, the development process, or any of our internal teams? If so, please note how you will share this change with the people who need to know about it._ -- [ ] I've updated the [Developer Docs](https://docs.forem.com) and/or +- [ ] I've updated the [Developer Docs](https://developers.forem.com) and/or [Admin Guide](https://admin.forem.com/), or [Storybook](https://storybook.forem.com/) (for Crayons components) - [ ] I've updated the README or added inline documentation diff --git a/.gitignore b/.gitignore index dfcc73ac3..cabc9083a 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ node_modules/ /app/assets/javascripts/generated/* latest.dump .byebug_history -.gitdocs_build/ # Ignore application configuration /config/application.yml @@ -64,11 +63,6 @@ package-lock.json # Development Docker storage location _docker-storage/ -# YARD generated doc (in the Gitdocs folder) -docs/.static/ruby-doc/ -# ReDoc generated API doc (in the Gitdocs folder) -docs/.static/api/ - # AWS Cloud9 specific folder for user settings .c9/ diff --git a/.rubocop.yml b/.rubocop.yml index 723d0bad5..13f0a6962 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -100,7 +100,6 @@ Layout/LineLength: Description: 'Checks that line length does not exceed the configured limit.' AutoCorrect: true # this is false by default Exclude: - - docs/Gemfile - Gemfile - app/lib/constants/site_config.rb diff --git a/.slugignore b/.slugignore index 4cdf276df..572b978a4 100644 --- a/.slugignore +++ b/.slugignore @@ -7,7 +7,6 @@ .eslintignore .eslintrc.js .gitattributes -.gitdocs.js .github/ .gitpod.dockerfile .gitpod.yml @@ -40,7 +39,6 @@ cypress.dev.json cypress.json cypress/ docker-compose.yml -docs/ empty-module.js jest.config.js postcss_error.log diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ccf326758..38b0669d9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,4 +19,4 @@ We are all humans trying to work together to improve the community. Always be kind and appreciate the need for trade-offs. ❤️ Before making your first pull request or issue, give our full -[Contributor's Guide](https://docs.forem.com/contributing/forem/) a read. +[Contributor's Guide](https://developers.forem.com/contributing/forem/) a read. diff --git a/README.md b/README.md index 833141d2e..4b051cf60 100644 --- a/README.md +++ b/README.md @@ -94,14 +94,14 @@ proceed. ## Getting Started This section provides a high-level quick start guide. If you're looking for the -[installation guide](https://docs.forem.com/installation/), you'll want to refer -to our complete [Developer Documentation](https://docs.forem.com/). +[installation guide](https://developers.forem.com/installation/), you'll want to +refer to our complete [Developer Documentation](https://developers.forem.com/). We run on a [Rails](https://rubyonrails.org/) backend, and we are currently transitioning to a [Preact](https://preactjs.com/)-first frontend. A more complete overview of our stack is available in -[our docs](https://docs.forem.com/technical-overview/). +[our docs](https://developers.forem.com/technical-overview/). ### Prerequisites @@ -130,11 +130,11 @@ A more complete overview of our stack is available in ### Installation Documentation -[View Full Installation Documentation](https://docs.forem.com/installation/). +[View Full Installation Documentation](https://developers.forem.com/installation/). ## Developer Documentation -[Check out our dedicated docs page for more technical documentation](https://docs.forem.com). +[Check out our dedicated docs page for more technical documentation](https://developers.forem.com). ## Core team @@ -192,7 +192,7 @@ Agreement, which they generously made available to the public domain under Creative Commons CC0 1.0 Universal. Any questions, please refer to our -[license FAQ](https://docs.forem.com/licensing/) doc or email yo@dev.to. +[license FAQ](https://developers.forem.com/licensing/) doc or email yo@dev.to.
diff --git a/app/controllers/concerns/edge_cache_safety_check.rb b/app/controllers/concerns/edge_cache_safety_check.rb index 59d301f10..938ec0601 100644 --- a/app/controllers/concerns/edge_cache_safety_check.rb +++ b/app/controllers/concerns/edge_cache_safety_check.rb @@ -8,7 +8,7 @@ module EdgeCacheSafetyCheck def current_user # In production, current_user will cause a cache leak if it's placed within an edge-cached code path. # More information here: - # https://docs.forem.com/technical-overview/architecture/#we-cache-many-content-pages-on-the-edge + # https://developers.forem.com/technical-overview/architecture/#we-cache-many-content-pages-on-the-edge return super unless RequestStore.store[:edge_caching_in_place] return if session_current_user_id.blank? diff --git a/app/javascript/crayons/guidelines/__stories__/Components.stories.mdx b/app/javascript/crayons/guidelines/__stories__/Components.stories.mdx index 55dbbf5e5..452046dea 100644 --- a/app/javascript/crayons/guidelines/__stories__/Components.stories.mdx +++ b/app/javascript/crayons/guidelines/__stories__/Components.stories.mdx @@ -8,7 +8,7 @@ import { Meta } from '@storybook/addon-docs/blocks'; Forem is a Rails application. Most of what we build for views uses ERB templates (\*.html.erb files). We also build out parts of or sometimes complete views -using [Preact](https://docs.forem.com/frontend/preact), typically for the logged +using [Preact](https://developers.forem.com/frontend/preact), typically for the logged on user experience. For example, the main page feed. Because of that, we components that are written in pure HTML & CSS as well as diff --git a/app/views/users/_account.html.erb b/app/views/users/_account.html.erb index 48c345928..024659cce 100644 --- a/app/views/users/_account.html.erb +++ b/app/views/users/_account.html.erb @@ -7,7 +7,7 @@

<%= community_name %> API Keys

-

You can generate personal API keys to use for authentication with the <%= community_name %> API. The API is still in its beta stage. The documentation contains further information.

+

You can generate personal API keys to use for authentication with the <%= community_name %> API. The API is still in its beta stage. The documentation contains further information.

diff --git a/config/routes.rb b/config/routes.rb index 93382967b..8389f02a4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -296,7 +296,7 @@ Rails.application.routes.draw do # You can have the root of your site routed with "root get "/robots.:format", to: "pages#robots" - get "/api", to: redirect("https://docs.forem.com/api") + get "/api", to: redirect("https://developers.forem.com/api") get "/privacy", to: "pages#privacy" get "/terms", to: "pages#terms" get "/contact", to: "pages#contact" diff --git a/docs/.gitdocs.json b/docs/.gitdocs.json deleted file mode 100644 index 8ced4bda1..000000000 --- a/docs/.gitdocs.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "Forem Docs", - "root": "./", - "logo": "seedling.png", - "host": "0.0.0.0", - "header_links": [ - { - "title": "Repo", - "href": "https://github.com/forem/forem", - "target": "_blank", - "rel": "noopener noreferrer nofollow" - }, - { - "title": "DEV", - "href": "https://dev.to", - "target": "_blank", - "rel": "noopener noreferrer nofollow" - }, - { - "title": "Ruby doc", - "href": "https://docs.forem.com/ruby-doc", - "target": "_blank", - "rel": "noopener noreferrer nofollow" - }, - { - "title": "API doc", - "href": "https://docs.forem.com/api", - "target": "_blank", - "rel": "noopener noreferrer nofollow" - } - ] -} diff --git a/docs/.nvmrc b/docs/.nvmrc deleted file mode 100644 index e1fcd1ea2..000000000 --- a/docs/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -lts/erbium diff --git a/docs/.ruby-version b/docs/.ruby-version deleted file mode 100644 index 37c2961c2..000000000 --- a/docs/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.2 diff --git a/docs/.static/admin_feature_flags.png b/docs/.static/admin_feature_flags.png deleted file mode 100644 index a4071b3a6..000000000 Binary files a/docs/.static/admin_feature_flags.png and /dev/null differ diff --git a/docs/.static/cypress-test-runner.png b/docs/.static/cypress-test-runner.png deleted file mode 100644 index 4788b1526..000000000 Binary files a/docs/.static/cypress-test-runner.png and /dev/null differ diff --git a/docs/.static/devblacksquarelogo.svg b/docs/.static/devblacksquarelogo.svg deleted file mode 100644 index 57f853e7b..000000000 --- a/docs/.static/devblacksquarelogo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/.static/favicon.ico b/docs/.static/favicon.ico deleted file mode 100644 index 6f22222c0..000000000 Binary files a/docs/.static/favicon.ico and /dev/null differ diff --git a/docs/.static/jest-watch-mode-screenshot.png b/docs/.static/jest-watch-mode-screenshot.png deleted file mode 100644 index 0c3d57e26..000000000 Binary files a/docs/.static/jest-watch-mode-screenshot.png and /dev/null differ diff --git a/docs/.static/seedling.png b/docs/.static/seedling.png deleted file mode 100644 index aa93c9ce2..000000000 Binary files a/docs/.static/seedling.png and /dev/null differ diff --git a/docs/.static/vscode_launch_debugger.png b/docs/.static/vscode_launch_debugger.png deleted file mode 100644 index 0b0bbf12f..000000000 Binary files a/docs/.static/vscode_launch_debugger.png and /dev/null differ diff --git a/docs/.static/wsl-feature.png b/docs/.static/wsl-feature.png deleted file mode 100644 index 5cf46d750..000000000 Binary files a/docs/.static/wsl-feature.png and /dev/null differ diff --git a/docs/Gemfile b/docs/Gemfile deleted file mode 100644 index 06a342089..000000000 --- a/docs/Gemfile +++ /dev/null @@ -1,11 +0,0 @@ -ruby_version = File.read( - File.join(File.dirname(File.dirname(__FILE__)), ".ruby-version"), -).strip - -source "https://rubygems.org" -ruby ruby_version - -gem "activerecord", "~> 5.2.3" # Databases on Rails -gem "yard", "~> 0.9.19" # YARD is a documentation generation tool for the Ruby programming language -gem "yard-activerecord", "~> 0.0.16" # YARD extension that handles and interprets methods used when developing applications with ActiveRecord -gem "yard-activesupport-concern", "~> 0.0.1" # YARD extension that brings support for modules making use of ActiveSupport::Concern diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 48a325998..000000000 --- a/docs/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -.PHONY: build - -build: api-doc ruby-doc gitdocs - -api-doc: - # docs/.static/api will let gitdocs serve the API doc as static content - cd .. && \ - npm install -g redoc-cli@latest && \ - redoc-cli bundle docs/api_v0.yml --options.suppressWarnings --options.pathInMiddlePanel --options.jsonSampleExpandLevel=all --options.menuToggle -t docs/api_template.hbs && \ - mkdir -p docs/.static/api/ && \ - mv redoc-static.html docs/.static/api/index.html - -ruby-doc: - # docs/.static/ruby-doc will let gitdocs serve the Ruby doc as static content - cd .. && yard doc -o docs/.static/ruby-doc - -gitdocs: - npm install -g gitdocs@latest && gitdocs build diff --git a/docs/admin/admin-search.md b/docs/admin/admin-search.md deleted file mode 100644 index a9aa6048d..000000000 --- a/docs/admin/admin-search.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Admin Search ---- - -# Admin Search - -For admin views that need to take advantage of searching and filtering, we've -chosen to use [Ransack][ransack]. - -Ransack is a Ruby gem that makes searching relatively painless. It has excellent -documentation, but if you're looking for an example of how it's being used on -Forem, we've implemented it to help searching and sorting user reports. - -The view responsible for managing user reports can be found at -`/admin/moderation/reports` and Ransack can be seen in use on the -index action of the [`admin/feedback_messages_controller`][feedback_messages]. - -For Forem, Ransack is being used exclusively in admin, for search problems in -other parts of the app we use [PostgreSQL Full Text Search][postgres_fts]. - -[feedback_messages]: - https://github.com/forem/forem/blob/4e41e4a2ac893fa2a6c36990cfe475858ffb086a/app/controllers/admin/feedback_messages_controller.rb#L4 -[ransack]: https://github.com/activerecord-hackery/ransack -[postgres_fts]: https://www.postgresql.org/docs/11/textsearch.html diff --git a/docs/admin/admin-user-interface.md b/docs/admin/admin-user-interface.md deleted file mode 100644 index 4288587f2..000000000 --- a/docs/admin/admin-user-interface.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Admin User Interface ---- - -# User Interface - -Our admin dashboard is primarily ERB views that render on the server. Largely, -we try to adhere to -[ActionView](https://guides.rubyonrails.org/action_view_overview.html)'s -conventions in these views. - -For layout, basic styles, and some interactions, we use -[Bootstrap 4](https://getbootstrap.com/). Forem isn't dedicated to using -Bootstrap for everything, but because our design team hasn't spent much time on -these views, we find it's easier to stick with something many developers already -know. - -When a view requires some custom interactivity, we've historically leaned on -vanilla JavaScript or jQuery, but going forward we've elected to use -[StimulusJS](https://stimulusjs.org/) for DOM manipulation and interactivity -inside of admin. - -# Forms - -Inside of the admin views, we're -[actively moving from the old ERB syntax for forms](https://m.patrikonrails.com/rails-5-1s-form-with-vs-old-form-helpers-3a5f72a8c78a). -We tend to prefer the `form_with` helper over the previous `form_for` and -`form_tag` helpers. - -# StimulusJS - -Stimulus is a modest frontend framework; its primary purpose is manipulating -HTML. It does not provide templating features. - -In the Forem application, [Webpacker](/frontend/webpacker/) is used to load -Stimulus controllers via the `app/javascript/packs/admin.js` -[pack file](https://github.com/rails/webpacker/blob/main/docs/folder-structure.md#packs-aka-webpack-entries). -Ideally, controllers serve as an abstraction for shared functionality between -views. - -New controllers can be added in `/app/javascript/admin/controllers`. Unit tests -should exist for each controller in the adjacent -`/app/javascript/admin/__tests__/contollers` directory. diff --git a/docs/admin/readme.md b/docs/admin/readme.md deleted file mode 100644 index ab551df0a..000000000 --- a/docs/admin/readme.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Admin Guide -items: - - admin-search.md - - internal-user-interface.md ---- - -# Admin Guide - -The Forem application contains a rudimentary administration dashboard that lives -behind the admin route. - -The admin dashboard is made up of a series of views that range from -administration tools to simplified reports. These tools are used by users with -the `admin` or `super_admin` roles to administrate the Forem application. - -Authorization for these tools is handled by the [Rolify][rolify] gem. - -Currently, a workaround exists to give access to certain `admin` views via -Rolify by assigning the role `single_resource_admin` to a user. - -`single_resource_admin` users are given access to a Ruby class. In the codebase, -there are admin models, not backed by database tables, that exist for this -purpose. For example, if you needed to give a user access to only -`/admin/apps/welcome`, you'd run the following command in the Rails console: - -```ruby -user = User.find(some_user_id) -user.add_role(:single_resource_admin, Welcome) -``` - -This gives the user administration privileges on the controller associated with -an almost empty Rails model that lives in `app/models/admin/welcome.rb`: - -```ruby -class Welcome < ApplicationRecord - resourcify - # This class exists to take advantage of Rolify for limiting authorization - # on admin reports. - # NOTE: It is not backed by a database table and should not be expected to - # function like a traditional Rails model -end -``` - -Now that user will be able to access the view at `admin/welcome`. The same -workaround has been implemented for most of the admin views. - -[rolify]: https://github.com/RolifyCommunity/rolify diff --git a/docs/api_template.hbs b/docs/api_template.hbs deleted file mode 100644 index c9ddaa4e7..000000000 --- a/docs/api_template.hbs +++ /dev/null @@ -1,33 +0,0 @@ -{{! This template is used by ReDoc to render the final API doc }} -{{! It is written in HandlerbarsJS syntax }} -{{! Please refer to https://github.com/Redocly/redoc/blob/master/cli/README.md }} -{{! and https://github.com/Redocly/redoc/blob/master/cli/template.hbs }} - - - - - - DEV API (beta) - - - - - - - {{! needed for adaptive design }} - - - {{{redocHead}}} - - - - - {{{redocHTML}}} - - - diff --git a/docs/api_v0.yml b/docs/api_v0.yml deleted file mode 100644 index 6d84a7627..000000000 --- a/docs/api_v0.yml +++ /dev/null @@ -1,3782 +0,0 @@ -# This document follows the OpenAPI spec -# It contains two Redoc vendor extensions, x-codeSamples and x-logo -# x-logo: https://github.com/Redocly/redoc/blob/master/docs/redoc-vendor-extensions.md#x-logo -# x-codeSamples: https://github.com/Redocly/redoc/blob/master/docs/redoc-vendor-extensions.md#x-codesamples - -openapi: "3.0.3" -info: - title: DEV API (beta) - description: | - - Access Forem articles, users and other resources via API. - - For a real-world example of Forem in action, check out [DEV](https://www.dev.to). - - All endpoints that don't require authentication are CORS enabled. - - Dates and date times, unless otherwise specified, must be in - the [RFC 3339](https://tools.ietf.org/html/rfc3339) format. - - version: "0.9.7" - termsOfService: https://dev.to/terms - contact: - name: DEV Team - url: https://dev.to/contact - email: yo@dev.to - x-logo: - url: https://res.cloudinary.com/practicaldev/image/fetch/s--EYllUmBG--/c_limit,f_auto,fl_progressive,q_80,w_190/https://res.cloudinary.com/practicaldev/image/fetch/s--m5i3pkpk--/c_limit%252cf_auto%252cfl_progressive%252cq_auto%252cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sf6uve8ehm4ogwka0mez.png - backgroundColor: "" - altText: "Forem logo" - -servers: - - url: https://dev.to/api - description: Production server - -components: - parameters: - pageParam: - in: query - name: page - required: false - description: Pagination page. - schema: - type: integer - format: int32 - minimum: 1 - default: 1 - perPageParam10to1000: - in: query - name: per_page - required: false - description: Page size (the number of items to return per page). - schema: - type: integer - format: int32 - minimum: 1 - maximum: 1000 - default: 10 - perPageParam24to1000: - in: query - name: per_page - required: false - description: Page size (the number of items to return per page). - schema: - type: integer - format: int32 - minimum: 1 - maximum: 1000 - default: 24 - perPageParam30to1000: - in: query - name: per_page - required: false - description: Page size (the number of items to return per page). - schema: - type: integer - format: int32 - minimum: 1 - maximum: 1000 - default: 30 - perPageParam30to100: - in: query - name: per_page - required: false - description: Page size (the number of items to return per page). - schema: - type: integer - format: int32 - minimum: 1 - maximum: 100 - default: 30 - perPageParam80to1000: - in: query - name: per_page - required: false - description: Page size (the number of items to return per page). - schema: - type: integer - format: int32 - minimum: 1 - maximum: 1000 - default: 80 - listingCategoryParam: - name: category - in: query - description: | - Using this parameter will return listings belonging to the - requested category. - schema: - type: string - example: cfp - - securitySchemes: - api_key: - type: apiKey - description: | - API Key authentication. - - Authentication for some endpoints, like write operations on the - Articles API require a DEV API key. - - ### Getting an API key - - To obtain one, please follow these steps: - - - visit https://dev.to/settings/account - - in the "DEV API Keys" section create a new key by adding a - description and clicking on "Generate API Key" - - ![obtain a DEV API Key](https://user-images.githubusercontent.com/146201/64421366-af3f8b00-d0a1-11e9-8ff6-7cc0ca6e854e.png) - - You'll see the newly generated key in the same view - ![generated DEV API Key](https://user-images.githubusercontent.com/146201/64421367-af3f8b00-d0a1-11e9-9831-73d3bdfdff66.png) - name: api-key - in: header - oauth2: - type: oauth2 - description: | - OAuth2 authentication. - - OAuth2 authentication is still in private alpha. - flows: - authorizationCode: - authorizationUrl: https://dev.to/oauth/authorize - tokenUrl: https://dev.to/oauth/token - refreshUrl: https://dev.to/oauth/token - scopes: {} - clientCredentials: - tokenUrl: https://dev.to/oauth/token - refreshUrl: https://dev.to/oauth/token - scopes: {} - - schemas: - APIError: - type: object - required: - - error - - status - properties: - error: - type: string - status: - type: integer - format: int32 - ArticleIndex: - type: object - required: - - type_of - - id - - title - - description - - cover_image - - readable_publish_date - - social_image - - tag_list - - tags - - slug - - path - - url - - canonical_url - - comments_count - - positive_reactions_count - - public_reactions_count - - created_at - - edited_at - - crossposted_at - - published_at - - last_comment_at - - published_timestamp - - user - - reading_time_minutes - properties: - type_of: - type: string - id: - type: integer - format: int32 - title: - type: string - description: - type: string - cover_image: - type: string - format: url - nullable: true - readable_publish_date: - type: string - social_image: - type: string - format: url - tag_list: - type: array - items: - type: string - tags: - type: string - slug: - type: string - path: - type: string - format: path - url: - type: string - format: url - canonical_url: - type: string - format: url - comments_count: - type: integer - format: int32 - positive_reactions_count: - type: integer - format: int32 - public_reactions_count: - type: integer - format: int32 - created_at: - type: string - format: date-time - edited_at: - type: string - format: date-time - nullable: true - crossposted_at: - type: string - format: date-time - nullable: true - published_at: - type: string - format: date-time - last_comment_at: - type: string - format: date-time - published_timestamp: - description: Crossposting or published date time - type: string - format: date-time - user: - $ref: "#/components/schemas/SharedUser" - reading_time_minutes: - description: Reading time, in minutes - type: integer - format: int32 - organization: - $ref: "#/components/schemas/SharedOrganization" - flare_tag: - $ref: "#/components/schemas/ArticleFlareTag" - - ArticleShow: - type: object - required: - - type_of - - id - - title - - description - - cover_image - - readable_publish_date - - social_image - - tag_list - - tags - - slug - - path - - url - - canonical_url - - comments_count - - positive_reactions_count - - public_reactions_count - - created_at - - edited_at - - crossposted_at - - published_at - - last_comment_at - - published_timestamp - - body_html - - body_markdown - - user - - reading_time_minutes - properties: - type_of: - type: string - id: - type: integer - format: int32 - title: - type: string - description: - type: string - cover_image: - type: string - format: url - nullable: true - readable_publish_date: - type: string - social_image: - type: string - format: url - tag_list: - type: string - tags: - type: array - items: - type: string - slug: - type: string - path: - type: string - format: path - url: - type: string - format: url - canonical_url: - type: string - format: url - comments_count: - type: integer - format: int32 - positive_reactions_count: - type: integer - format: int32 - public_reactions_count: - type: integer - format: int32 - created_at: - type: string - format: date-time - edited_at: - type: string - format: date-time - nullable: true - crossposted_at: - type: string - format: date-time - nullable: true - published_at: - type: string - format: date-time - last_comment_at: - type: string - format: date-time - published_timestamp: - description: Crossposting or published date time - type: string - format: date-time - body_html: - type: string - body_markdown: - type: string - user: - $ref: "#/components/schemas/SharedUser" - reading_time_minutes: - description: Reading time, in minutes - type: integer - format: int32 - organization: - $ref: "#/components/schemas/SharedOrganization" - flare_tag: - $ref: "#/components/schemas/ArticleFlareTag" - - ArticleCreate: - type: object - properties: - article: - type: object - properties: - title: - type: string - body_markdown: - description: | - The body of the article. - - It can contain an optional front matter. For example - - ```markdown - --- - title: Hello, World! - published: true - tags: discuss, help - date: 20190701T10:00Z - series: Hello series - canonical_url: https://example.com/blog/hello - cover_image: article_published_cover_image - --- - ``` - - `date`, `series` and `canonical_url` are optional. - `date` is the publication date-time - `series` is the name of the series the article belongs to - `canonical_url` is the canonical URL of the article - `cover_image` is the main image of the article - - *If the markdown contains a front matter, it will take precedence - on the equivalent params given in the payload.* - type: string - published: - description: | - True to create a published article, false otherwise. Defaults to false - type: boolean - series: - description: | - Article series name. - - All articles belonging to the same series need to have the same name - in this parameter. - type: string - main_image: - type: string - format: url - canonical_url: - type: string - format: url - description: - type: string - tags: - type: array - items: - type: string - organization_id: - description: | - Only users belonging to an organization can assign the article to it - type: integer - format: int32 - - ArticleUpdate: - type: object - properties: - article: - type: object - properties: - title: - type: string - body_markdown: - description: | - The body of the article. - - It can contain an optional front matter. For example - - ```markdown - --- - title: Hello, World! - published: true - tags: discuss, help - date: 20190701T10:00Z - series: Hello series - canonical_url: https://example.com/blog/hello - cover_image: article_published_cover_image - --- - ``` - - `date`, `series` and `canonical_url` are optional. - `date` is the publication date-time - `series` is the name of the series the article belongs to - `canonical_url` is the canonical URL of the article - `cover_image` is the main image of the article - - *If the markdown contains a front matter, it will take precedence - on the equivalent params given in the payload.* - type: string - published: - description: | - True to create a published article, false otherwise. Defaults to false - type: boolean - series: - description: | - Article series name. - - All articles belonging to the same series need to have the same name - in this parameter. - - To remove an article from a series, the `null` value can be used. - type: string - main_image: - type: string - format: url - canonical_url: - type: string - format: url - description: - type: string - tags: - type: array - items: - type: string - organization_id: - description: | - Only users belonging to an organization can assign the article to it - type: integer - format: int32 - - ArticleMe: - type: object - required: - - type_of - - id - - title - - description - - cover_image - - published - - published_at - - tag_list - - slug - - path - - url - - canonical_url - - comments_count - - positive_reactions_count - - public_reactions_count - - page_views_count - - published_timestamp - - body_markdown - - user - - reading_time_minutes - properties: - type_of: - type: string - id: - type: integer - format: int32 - title: - type: string - description: - type: string - cover_image: - type: string - format: url - nullable: true - published: - type: boolean - published_at: - type: string - format: date-time - tag_list: - type: array - items: - type: string - slug: - type: string - path: - type: string - format: path - url: - type: string - format: url - canonical_url: - type: string - format: url - comments_count: - type: integer - format: int32 - positive_reactions_count: - type: integer - format: int32 - public_reactions_count: - type: integer - format: int32 - page_views_count: - type: integer - format: int32 - published_timestamp: - description: Crossposting or published date time - type: string - format: date-time - body_markdown: - description: The body of the article in Markdown format - type: string - user: - $ref: "#/components/schemas/SharedUser" - reading_time_minutes: - description: Reading time, in minutes - type: integer - format: int32 - organization: - $ref: "#/components/schemas/SharedOrganization" - flare_tag: - $ref: "#/components/schemas/ArticleFlareTag" - - ArticleFlareTag: - description: Flare tag of the article - type: object - properties: - name: - type: string - bg_color_hex: - description: Background color (hexadecimal) - type: string - text_color_hex: - description: Text color (hexadecimal) - type: string - - ArticleVideo: - type: object - required: - - type_of - - id - - path - - cloudinary_video_url - - title - - user_id - - video_duration_in_minutes - - video_source_url - - user - properties: - type_of: - type: string - id: - type: integer - format: int32 - path: - type: string - cloudinary_video_url: - description: The preview image of the video - type: string - format: url - title: - type: string - user_id: - type: integer - format: int32 - video_duration_in_minutes: - description: | - The duration of the video. - - If the video duration is below 1 hour, the format will be `mm:ss`, - if it's 1 hour or above the format will be `h:mm:ss`. - type: string - video_source_url: - format: url - type: string - user: - type: object - properties: - name: - description: The user's name - type: string - - Comment: - type: object - required: - - type_of - - id_code - - created_at - - body_html - - user - - children - properties: - type_of: - type: string - id_code: - type: string - created_at: - type: string - format: date-time - body_html: - description: HTML formatted comment - type: string - user: - $ref: "#/components/schemas/SharedUser" - children: - type: array - items: - $ref: "#/components/schemas/Comment" - FollowedTag: - type: object - required: - - id - - name - - points - properties: - id: - description: Tag id - type: integer - format: int64 - name: - type: string - points: - type: number - format: float - - Follower: - type: object - required: - - type_of - - created_at - - id - - name - - path - - username - - profile_image - properties: - type_of: - type: string - created_at: - description: Date the user became a follower - type: string - format: date-time - id: - description: Follow id - type: integer - format: int32 - name: - type: string - path: - type: string - username: - type: string - profile_image: - description: Profile image (60x60) - type: string - format: url - - Listing: - type: object - required: - - type_of - - id - - title - - slug - - body_markdown - - tag_list - - tags - - category - - processed_html - - published - - user - properties: - type_of: - type: string - id: - type: integer - format: int64 - title: - type: string - slug: - type: string - body_markdown: - type: string - tag_list: - type: string - tags: - type: array - items: - type: string - category: - $ref: "#/components/schemas/ListingCategory" - processed_html: - type: string - published: - type: boolean - user: - $ref: "#/components/schemas/SharedUser" - organization: - $ref: "#/components/schemas/SharedOrganization" - - ListingCategory: - type: string - enum: [cfp, forhire, collabs, education, jobs, mentors, products, mentees, forsale, events, misc] - - ListingCreate: - type: object - properties: - listing: - type: object - required: - - title - - body_markdown - - category - properties: - title: - type: string - body_markdown: - description: The body of the listing in Markdown format. - type: string - category: - $ref: "#/components/schemas/ListingCategory" - tags: - description: | - Tags related to the listing. - - A maximum of 8 tags are allowed and it takes precedence over `tag_list`. - type: array - items: - type: string - tag_list: - description: | - Comma separated list of tags. - - A maximum of 8 tags are allowed. - type: string - expires_at: - description: Date and time of expiration. - type: string - format: date-time - contact_via_connect: - description: | - True if users are allowed to contact the listing's owner - via DEV connect, false otherwise. - - Defaults to false. - type: boolean - location: - description: Geographical area or city for the listing. - type: string - organization_id: - description: | - The id of the organization the user is creating the listing for. - - Only users belonging to an organization can assign the listing to it. - type: integer - format: int64 - action: - description: Set it to "draft" to create an unpublished listing - type: string - enum: [draft] - - ListingUpdate: - type: object - properties: - listing: - type: object - properties: - title: - type: string - body_markdown: - description: The body of the listing in Markdown format. - type: string - category: - $ref: "#/components/schemas/ListingCategory" - tags: - description: | - Tags related to the listing. - - A maximum of 8 tags are allowed and it takes precedence over `tag_list`. - type: array - items: - type: string - tag_list: - description: | - Comma separated list of tags. - - A maximum of 8 tags are allowed. - type: string - expires_at: - description: Date and time of expiration. - type: string - format: date-time - contact_via_connect: - description: | - True if users are allowed to contact the listing's owner - via DEV connect, false otherwise. - - Defaults to false. - type: boolean - location: - description: Geographical area or city for the listing. - type: string - action: - description: | - This param can be provided by itself to invoke some actions: - - - `bump` bumps the listing and charge either the - organization or the user - - `publish` publishes a draft listing - - `unpublish` unpublishes a published listing - - It will take priority on any other param in the payload. - type: string - enum: [bump, publish, unpublish] - - ReadingList: - type: object - required: - - type_of - - id - - status - - created_at - - article - properties: - type_of: - type: string - id: - description: Follow id - type: integer - format: int32 - status: - type: string - enum: - - valid - - invalid - - confirmed - - archived - created_at: - type: string - format: date-time - article: - $ref: "#/components/schemas/ArticleIndex" - - PodcastEpisode: - type: object - required: - - type_of - - id - - path - - image_url - - title - - podcast - properties: - type_of: - type: string - id: - type: integer - format: int32 - path: - type: string - image_url: - type: string - format: url - title: - type: string - podcast: - type: object - properties: - title: - type: string - slug: - type: string - image_url: - type: string - format: url - - SharedUser: - description: The resource creator - type: object - properties: - name: - type: string - username: - type: string - twitter_username: - type: string - nullable: true - github_username: - type: string - nullable: true - website_url: - type: string - format: url - nullable: true - profile_image: - description: Profile image (640x640) - type: string - profile_image_90: - description: Profile image (90x90) - type: string - - SharedOrganization: - description: The organization the resource belongs to - type: object - properties: - name: - type: string - username: - type: string - slug: - type: string - profile_image: - description: Profile image (640x640) - type: string - format: url - profile_image_90: - description: Profile image (90x90) - type: string - format: url - - Tag: - type: object - required: - - id - - name - - bg_color_hex - - text_color_hex - properties: - id: - type: integer - format: int32 - name: - type: string - bg_color_hex: - description: Background color (hexadecimal) - type: string - text_color_hex: - description: Text color (hexadecimal) - type: string - - User: - type: object - required: - - type_of - - id - - username - - name - - summary - - twitter_username - - github_username - - website_url - - location - - joined_at - - profile_image - properties: - type_of: - type: string - id: - type: integer - format: int32 - username: - type: string - name: - type: string - summary: - type: string - nullable: true - twitter_username: - type: string - nullable: true - github_username: - type: string - nullable: true - website_url: - type: string - format: url - nullable: true - location: - type: string - nullable: true - joined_at: - description: Date of joining (formatted with strftime `"%b %e, %Y"`) - type: string - profile_image: - description: Profile image (320x320) - type: string - format: url - - WebhookCreate: - description: Webhook creation payload - type: object - properties: - webhook_endpoint: - type: object - required: - - source - - target_url - - events - properties: - source: - description: The name of the requester, eg. "DEV" - type: string - target_url: - type: string - format: url - events: - description: An array of events identifiers - type: array - items: - type: string - enum: - - article_created - - article_updated - - article_destroyed - - WebhookIndex: - description: Webhook - type: object - properties: - type_of: - type: string - id: - type: integer - format: int64 - source: - description: The name of the requester, eg. "DEV" - type: string - target_url: - type: string - format: url - events: - description: An array of events identifiers - type: array - items: - type: string - created_at: - type: string - format: date-time - - WebhookShow: - description: Webhook - type: object - properties: - type_of: - type: string - id: - type: integer - format: int64 - source: - description: The name of the requester, eg. "DEV" - type: string - target_url: - type: string - format: url - events: - description: An array of events identifiers - type: array - items: - type: string - created_at: - type: string - format: date-time - user: - $ref: "#/components/schemas/SharedUser" - - ProfileImage: - description: Profile image - type: object - properties: - type_of: - type: string - enum: [profile_image] - image_of: - description: "Discriminates what is the type of the profile image owner (user or organization)" - type: string - enum: [user, organization] - profile_image: - type: string - description: Profile image (640x640) - profile_image_90: - type: string - description: Profile image (90x90) - - Organization: - description: Organization - type: object - properties: - type_of: - type: string - username: - type: string - name: - type: string - summary: - type: string - nullable: true - twitter_username: - type: string - nullable: true - github_username: - type: string - nullable: true - url: - type: string - format: url - location: - type: string - nullable: true - tech_stack: - type: string - nullable: true - tag_line: - type: string - nullable: true - story: - type: string - nullable: true - joined_at: - description: Date of joining - type: string - format: date-time - profile_image: - type: string - description: Profile image (640x640) - format: url - - examples: - ErrorBadRequest: - value: - error: bad request - status: 400 - ErrorNotFound: - value: - error: not found - status: 404 - ErrorUnauthorized: - value: - error: unauthorized - status: 401 - ErrorPaymentRequired: - value: - error: not enough available credits - status: 402 - ErrorForbidden: - value: - error: forbidden - status: 403 - ErrorUnprocessableEntity: - value: - error: "param is missing or the value is empty: article" - status: 422 - ErrorTooManyRequests: - value: - error: "Rate limit reached, try again in 30 seconds" - status: 429 - - ArticlesIndex: - value: - - type_of: article - id: 194541 - title: There's a new DEV theme in town for all you 10x hackers out there (plus one - actually useful new feature) - description: '' - cover_image: https://res.cloudinary.com/practicaldev/image/fetch/s--74Bl23tz--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://res.cloudinary.com/practicaldev/image/fetch/s--xU8cbIK4--/c_imagga_scale%2Cf_auto%2Cfl_progressive%2Ch_420%2Cq_auto%2Cw_1000/https://thepracticaldev.s3.amazonaws.com/i/8a39dzf3oovzc2snl7iv.png - readable_publish_date: Oct 24 - social_image: https://res.cloudinary.com/practicaldev/image/fetch/s--SeMxdKIa--/c_imagga_scale,f_auto,fl_progressive,h_500,q_auto,w_1000/https://res.cloudinary.com/practicaldev/image/fetch/s--xU8cbIK4--/c_imagga_scale%2Cf_auto%2Cfl_progressive%2Ch_420%2Cq_auto%2Cw_1000/https://thepracticaldev.s3.amazonaws.com/i/8a39dzf3oovzc2snl7iv.png - tag_list: - - meta - - changelog - - css - - ux - tags: meta, changelog, css, ux - slug: there-s-a-new-dev-theme-in-town-for-all-you-10x-hackers-out-there-plus-one-actually-useful-new-feature-2kgk - path: "/devteam/there-s-a-new-dev-theme-in-town-for-all-you-10x-hackers-out-there-plus-one-actually-useful-new-feature-2kgk" - url: https://dev.to/devteam/there-s-a-new-dev-theme-in-town-for-all-you-10x-hackers-out-there-plus-one-actually-useful-new-feature-2kgk - canonical_url: https://dev.to/devteam/there-s-a-new-dev-theme-in-town-for-all-you-10x-hackers-out-there-plus-one-actually-useful-new-feature-2kgk - comments_count: 37 - positive_reactions_count: 12 - public_reactions_count: 142 - collection_id: - created_at: '2019-10-24T13:41:29Z' - edited_at: '2019-10-24T13:56:35Z' - crossposted_at: - published_at: '2019-10-24T13:52:17Z' - last_comment_at: '2019-10-25T08:12:43Z' - published_timestamp: '2019-10-24T13:52:17Z' - reading_time_minutes: 15 - user: - name: Ben Halpern - username: ben - twitter_username: bendhalpern - github_username: benhalpern - website_url: http://benhalpern.com - profile_image: https://res.cloudinary.com/practicaldev/image/fetch/s--Y1sq1tFG--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://thepracticaldev.s3.amazonaws.com/uploads/user/profile_image/1/f451a206-11c8-4e3d-8936-143d0a7e65bb.png - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--DcW51A6v--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://thepracticaldev.s3.amazonaws.com/uploads/user/profile_image/1/f451a206-11c8-4e3d-8936-143d0a7e65bb.png - organization: - name: The DEV Team - username: devteam - slug: devteam - profile_image: https://res.cloudinary.com/practicaldev/image/fetch/s--0kDBq1Ne--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://thepracticaldev.s3.amazonaws.com/uploads/organization/profile_image/1/0213bbaa-d5a1-4d25-9e7a-10c30b455af0.png - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--8tTU-XkZ--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://thepracticaldev.s3.amazonaws.com/uploads/organization/profile_image/1/0213bbaa-d5a1-4d25-9e7a-10c30b455af0.png - ArticleShow: - value: - type_of: article - id: 150589 - title: "Byte Sized Episode 2: The Creation of Graph Theory " - description: The full story of Leonhard Euler and the creation of this fundamental - computer science principle, delivered in a few minutes. - cover_image: https://res.cloudinary.com/practicaldev/image/fetch/s--qgutBUrH--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://thepracticaldev.s3.amazonaws.com/i/88e62fzblbluz1dm7xjf.png - readable_publish_date: Aug 1 - social_image: https://res.cloudinary.com/practicaldev/image/fetch/s--6wSHHfwd--/c_imagga_scale,f_auto,fl_progressive,h_500,q_auto,w_1000/https://thepracticaldev.s3.amazonaws.com/i/88e62fzblbluz1dm7xjf.png - tag_list: computerscience, graphtheory, bytesized, history - tags: - - computerscience - - graphtheory - - bytesized - - history - slug: byte-sized-episode-2-the-creation-of-graph-theory-34g1 - path: "/bytesized/byte-sized-episode-2-the-creation-of-graph-theory-34g1" - url: https://dev.to/bytesized/byte-sized-episode-2-the-creation-of-graph-theory-34g1 - canonical_url: https://dev.to/bytesized/byte-sized-episode-2-the-creation-of-graph-theory-34g1 - comments_count: 21 - positive_reactions_count: 122 - public_reactions_count: 322 - collection_id: 1693 - created_at: "2019-07-31T11:15:06Z" - edited_at: - crossposted_at: - published_at: "2019-08-01T15:47:54Z" - last_comment_at: "2019-08-06T16:48:10Z" - published_timestamp: "2019-08-01T15:47:54Z" - reading_time_minutes: 15 - body_html: |+ -

Today's episode of Byte Sized is about Leonhard Euler and the creation of Graph Theory.

- -

For more about how Graph Theory works, check out this video from BaseCS!

... - body_markdown: "---\r\ntitle: Byte Sized Episode 2: The Creation of Graph Theory \r\npublished: - true\r\ndescription: The full story of Leonhard Euler and the creation of this fundamental - computer science principle, delivered in a few minutes.\r\ntags: computerscience, - graphtheory, bytesized, history\r\ncover_image: https://thepracticaldev.s3.amazonaws.com/i/88e62fzblbluz1dm7xjf.png\r\nseries: - Byte Sized Season 1\r\n---\r\n\r\nToday's episode of Byte Sized is about Leonhard - Euler and the creation of [Graph Theory](https://en.wikipedia.org/wiki/Graph_theory).\r\n\r\nFor - more about how Graph Theory works, check out this video from BaseCS!..." - user: - name: Vaidehi Joshi - username: vaidehijoshi - twitter_username: vaidehijoshi - github_username: vaidehijoshi - website_url: http://www.vaidehi.com - profile_image: https://res.cloudinary.com/practicaldev/image/fetch/s--eDGAYAoK--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://thepracticaldev.s3.amazonaws.com/uploads/user/profile_image/2882/K2evUksb.jpg - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--htZnqMn3--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://thepracticaldev.s3.amazonaws.com/uploads/user/profile_image/2882/K2evUksb.jpg - organization: - name: Byte Sized - username: bytesized - slug: bytesized - profile_image: https://res.cloudinary.com/practicaldev/image/fetch/s--sq0DrZfn--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://thepracticaldev.s3.amazonaws.com/uploads/organization/profile_image/865/652f7998-32a8-4fd9-85ca-dd697d2a9ee9.png - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--1Pt_ICL---/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://thepracticaldev.s3.amazonaws.com/uploads/organization/profile_image/865/652f7998-32a8-4fd9-85ca-dd697d2a9ee9.png - ArticleCreateTitleBody: - value: - article: - title: Hello, World! - published: true - body_markdown: Hello DEV, this is my first post - tags: ["discuss", "help"] - series: Hello series - ArticleCreateFrontMatter: - value: - article: - body_markdown: | - --- - title: Hello, World! - published: true - tags: discuss, help - date: 20190701T10:00Z - series: Hello series - --- - - Hello DEV, this is my first post - ArticleCreateOrganization: - value: - article: - title: Hello, World! - published: true - body_markdown: Hello DEV, this is my first post - tags: ["discuss", "help"] - series: Hello series - organization_id: 1234 - ArticleVideo: - value: - - type_of: video_article - id: 273532 - path: "/devteam/basecs-depth-first-search-implementing-4kkl" - cloudinary_video_url: https://res.cloudinary.com/....png - title: 'BaseCS: Depth First Search Implementing' - user_id: 2882 - video_duration_in_minutes: '11:47' - video_source_url: 'https://dw71fyauz7yz9.cloudfront.net/123/123.m3u8' - user: - name: Vaidehi Joshi - - Comments: - value: - - type_of: comment - id_code: m3m0 - created_at: 2020-07-01T17:59:43Z - body_html: | - - -

...

- - - user: - name: Heriberto Morissette - username: heriberto_morissette - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...jpeg - profile_image_90: https://res.cloudinary.com/...jpeg - children: [] - - type_of: comment - id_code: m357 - created_at: 2020-07-02T17:19:40Z - body_html: | - - -

...

- -

...

- - - user: - name: Dario Waelchi - username: dario waelchi - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...png - profile_image_90: https://res.cloudinary.com/...png - children: - - type_of: comment - id_code: m35m - created_at: 2020-08-01T11:59:40Z - body_html: | - - - -

...

- - - user: - name: rhymes - username: rhymes - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...jpeg - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--SC90PuMi--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/2693/146201.jpeg - children: [] - CommentsDeleted: - value: - - type_of: comment - id_code: m357 - body_html:

[deleted]

- user: {} - children: - - type_of: comment - id_code: m35m - body_html: | - - - -

...

- - - user: - name: rhymes - username: rhymes - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...jpeg - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--SC90PuMi--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/2693/146201.jpeg - children: [] - CommentsHidden: - value: - - type_of: comment - id_code: m357 - body_html:

[hidden by post author]

- user: {} - children: - - type_of: comment - id_code: m35m - body_html: | - - - -

...

- - - user: - name: rhymes - username: rhymes - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...jpeg - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--SC90PuMi--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/2693/146201.jpeg - children: [] - Comment: - value: - type_of: comment - id_code: m357 - created_at: 2020-08-02T17:19:40Z - body_html: | - - -

...

- -

...

- - - user: - name: Dario Waelchi - username: dario waelchi - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...png - profile_image_90: https://res.cloudinary.com/...png - children: - - type_of: comment - id_code: m35m - created_at: 2020-07-02T17:19:40Z - body_html: | - - - -

...

- - - user: - name: rhymes - username: rhymes - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...jpeg - profile_image_90: https://res.cloudinary.com/....jpeg - children: [] - CommentDeleted: - value: - type_of: comment - id_code: m357 - body_html:

[deleted]

- user: {} - children: - - type_of: comment - id_code: m35m - body_html: | - - - -

...

- - - user: - name: rhymes - username: rhymes - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...jpeg - profile_image_90: https://res.cloudinary.com/...jpeg - children: [] - CommentHidden: - value: - type_of: comment - id_code: m357 - body_html:

[hidden by post author]

- user: {} - children: - - type_of: comment - id_code: m35m - body_html: | - - - -

...

- - - user: - name: rhymes - username: rhymes - twitter_username: - github_username: - website_url: - profile_image: https://res.cloudinary.com/...jpeg - profile_image_90: https://res.cloudinary.com/...jpeg - children: [] - - Followers: - value: - - type_of: user_follower - id: 12 - created_at: "2021-04-02T04:21:46Z" - name: Mrs. Neda Morissette - path: "/nedamrsmorissette" - username: nedamrsmorissette - profile_image: https://res.cloudinary.com/... - - type_of: user_follower - id: 11 - created_at: "2021-04-02T04:21:46Z" - name: Yoko Hintz - path: "/yokohintz" - username: yokohintz - profile_image: https://res.cloudinary.com/... - - Listings: - value: - - type_of: listing - id: 1157 - created_at: "2021-04-07 08:29:42 UTC" - title: TestBash Detroit - slug: testbash-detroit-50gb - body_markdown: "Do you want to learn about automation? Maybe you're interested in - AI-driven testing? Security testing? We have a selection of talks, workshops and - training courses to help you in a wide variety of areas in software testing. Join - us for our very first trip to Detroit MI! \n\nhttps://bit.ly/TBDetroit" - tag_list: events - tags: - - events - category: cfp - processed_html: | -

Do you want to learn about automation? Maybe you're interested in AI-driven testing? Security testing? We have a selection of talks, workshops and training courses to help you in a wide variety of areas in software testing. Join us for our very first trip to Detroit MI!

- -

https://bit.ly/TBDetroit

- published: true - user: - name: Heather - username: heatherr - twitter_username: - github_username: Heather-R - website_url: - profile_image: https://res.cloudinary.com/practicaldev/image/fetch/s--ggU5WPaT--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/136256/11cced64-afd2-4421-91e1-c5f7b216d49b.jpeg - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--CjladMBD--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/136256/11cced64-afd2-4421-91e1-c5f7b216d49b.jpeg - ListingsByOrganization: - value: - - type_of: listing - id: 1157 - title: TestBash Detroit - slug: testbash-detroit-50gb - body_markdown: "Do you want to learn about automation? Maybe you're interested in - AI-driven testing? Security testing? We have a selection of talks, workshops and - training courses to help you in a wide variety of areas in software testing. Join - us for our very first trip to Detroit MI! \n\nhttps://bit.ly/TBDetroit" - tag_list: events - tags: - - events - category: cfp - processed_html: | -

Do you want to learn about automation? Maybe you're interested in AI-driven testing? Security testing? We have a selection of talks, workshops and training courses to help you in a wide variety of areas in software testing. Join us for our very first trip to Detroit MI!

- -

https://bit.ly/TBDetroit

- published: true - user: - name: Heather - username: heatherr - twitter_username: - github_username: Heather-R - website_url: - profile_image: https://res.cloudinary.com/practicaldev/image/fetch/s--ggU5WPaT--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/136256/11cced64-afd2-4421-91e1-c5f7b216d49b.jpeg - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--CjladMBD--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/136256/11cced64-afd2-4421-91e1-c5f7b216d49b.jpeg - organization: - name: E Corp - username: ecorp - slug: ecorp - profile_image: https://res.cloudinary.com/practicaldev/image/fetch/s--ggU5WPaT--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/136256/11cced64-afd2-4421-91e1-c5f7b216d49b.jpeg - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--CjladMBD--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/136256/11cced64-afd2-4421-91e1-c5f7b216d49b.jpeg - Listing: - value: - type_of: listing - id: 1157 - title: TestBash Detroit - slug: testbash-detroit-50gb - body_markdown: "Do you want to learn about automation? Maybe you're interested in - AI-driven testing? Security testing? We have a selection of talks, workshops and - training courses to help you in a wide variety of areas in software testing. Join - us for our very first trip to Detroit MI! \n\nhttps://bit.ly/TBDetroit" - tag_list: events - tags: - - events - category: cfp - processed_html: | -

Do you want to learn about automation? Maybe you're interested in AI-driven testing? Security testing? We have a selection of talks, workshops and training courses to help you in a wide variety of areas in software testing. Join us for our very first trip to Detroit MI!

- -

https://bit.ly/TBDetroit

- published: true - user: - name: Heather - username: heatherr - twitter_username: - github_username: Heather-R - website_url: - profile_image: https://res.cloudinary.com/practicaldev/image/fetch/s--ggU5WPaT--/c_fill,f_auto,fl_progressive,h_640,q_auto,w_640/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/136256/11cced64-afd2-4421-91e1-c5f7b216d49b.jpeg - profile_image_90: https://res.cloudinary.com/practicaldev/image/fetch/s--CjladMBD--/c_fill,f_auto,fl_progressive,h_90,q_auto,w_90/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/136256/11cced64-afd2-4421-91e1-c5f7b216d49b.jpeg - ListingCreate: - value: - listing: - title: ACME Conference - body_markdown: Awesome conference - category: cfp - tags: - - events - ListingCreateOrganization: - value: - listing: - title: ACME Conference - body_markdown: Awesome conference - category: cfp - tags: - - events - organization_id: 1 - ListingUpdate: - value: - listing: - title: ACME New Conference - body_markdown: Awesome new conference - ListingUpdateActionBump: - value: - listing: - action: bump - ListingUpdateActionPublish: - value: - listing: - action: publish - ListingUpdateActionUnpublish: - value: - listing: - action: unpublish - - PodcastEpisodes: - value: - - type_of: podcast_episodes - id: 13894 - path: "/codenewbie/s11-e7-why-site-reliability-is-so-important-molly-struve" - image_url: https://dev-to-uploads.s3.amazonaws.com/uploads/podcast/image/2/9f50a462-9152-429a-b15e-d024baaa8e01.png - title: S11:E7 - Why site reliability is so important (Molly Struve) - podcast: - title: CodeNewbie - slug: codenewbie - image_url: https://dev-to-uploads.s3.amazonaws.com/uploads/podcast/image/2/9f50a462-9152-429a-b15e-d024baaa8e01.png - - type_of: podcast_episodes - id: 13829 - path: "/codenewbie/s11-e6-what-are-the-pros-and-cons-of-working-in-civic-tech-aidan-feldman" - image_url: https://dev-to-uploads.s3.amazonaws.com/uploads/podcast/image/2/9f50a462-9152-429a-b15e-d024baaa8e01.png - title: S11:E6 - What are the pros and cons of working in civic tech (Aidan Feldman) - podcast: - title: CodeNewbie - slug: codenewbie - image_url: https://dev-to-uploads.s3.amazonaws.com/uploads/podcast/image/2/9f50a462-9152-429a-b15e-d024baaa8e01.png - - Tags: - value: - - id: 6 - name: javascript - bg_color_hex: "#F7DF1E" - text_color_hex: "#000000" - - id: 8 - name: webdev - bg_color_hex: "#562765" - text_color_hex: "#ffffff" - TagsFollowed: - value: - - id: 13 - name: discuss - points: 3 - - id: 12 - name: webdev - points: 1 - - User: - value: - type_of: user - id: 1234 - username: bob - name: bob - summary: Hello, world - twitter_username: bob - github_username: bob - website_url: - location: New York - joined_at: Jan 1, 2017 - profile_image: https://res.cloudinary.com/...jpeg - - Users: - value: - - type_of: user - id: 1234 - username: bob - name: bob - summary: Hello, world - twitter_username: bob - github_username: bob - website_url: - location: New York - joined_at: Jan 1, 2017 - profile_image: https://res.cloudinary.com/...jpeg - - WebhookCreate: - value: - webhook_endpoint: - target_url: https://example.com/webhooks/webhook1 - source: DEV - events: - - article_created - WebhookShow: - value: - type_of: webhook_endpoint - id: 1 - source: DEV - target_url: https://example.com/webhooks/webhook1 - events: - - article_created - created_at: "2019-09-02T09:47:39.230Z" - user: - name: bob - username: bob - twitter_username: - github_username: bob - website_url: - profile_image: "..." - profile_image_90: "..." - - ProfileImage: - value: - type_of: profile_image - image_of: user - profile_image: https://res.cloudinary.com/...jpeg - profile_image_90: https://res.cloudinary.com/...jpeg - - Organization: - value: - type_of: organization - username: ecorp - name: E Corp - summary: Together we can change the world, with E Corp - twitter_username: ecorp - github_username: ecorp - url: https://ecorp.internet - location: New York - joined_at: '2019-10-24T13:41:29Z' - tech_stack: Ruby - tag_line: - story: - profile_image: https://res.cloudinary.com/...jpeg - -tags: - - name: articles - description: Articles are all the posts users create on DEV - - name: comments - description: Users can leave comments to articles and podcasts episodes - - name: follows - description: Resources are user can follow - - name: followers - description: Users can follow other users on the website - - name: listings - description: Listings are classified ads - - name: organizations - description: Users can create and join organizations - - name: podcast-episodes - description: Podcast episodes - - name: readinglist - description: User's reading list - - name: tags - description: Tags for articles - - name: users - description: Users own resources that require authentication - - name: videos - description: Video articles - - name: webhooks - description: Webhooks are HTTP endpoints registered to receive events - - name: profile images - description: User or organization profile images - -paths: - /articles: - get: - operationId: getArticles - summary: Published articles - description: | - This endpoint allows the client to retrieve a list of articles. - - "Articles" are all the posts that users create on DEV that typically - show up in the feed. They can be a blog post, a discussion question, - a help thread etc. but is referred to as article within the code. - - By default it will return featured, published articles ordered - by descending popularity. - - It supports pagination, each page will contain `30` articles by default. - tags: - - articles - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - - name: tag - in: query - description: | - Using this parameter will retrieve articles that contain the - requested tag. - - Articles will be ordered by descending popularity. - - This parameter can be used in conjuction with `top`. - schema: - type: string - example: discuss - - name: tags - in: query - description: | - Using this parameter will retrieve articles with any of the comma-separated tags. - - Articles will be ordered by descending popularity. - schema: - type: string - example: "javascript, css" - - name: tags_exclude - in: query - description: | - Using this parameter will retrieve articles that do _not_ contain _any_ of comma-separated tags. - - Articles will be ordered by descending popularity. - schema: - type: string - example: "node, java" - - name: username - in: query - description: | - Using this parameter will retrieve articles belonging - to a User or Organization ordered by descending publication date. - - If `state=all` the number of items returned will be `1000` instead of the default `30`. - - This parameter can be used in conjuction with `state`. - schema: - type: string - example: ben - - name: state - in: query - description: | - Using this parameter will allow the client to check which articles are fresh or rising. - - If `state=fresh` the server will return fresh articles. - If `state=rising` the server will return rising articles. - - This param can be used in conjuction with `username`, only if set to `all`. - schema: - type: string - enum: [fresh, rising, all] - example: fresh - - name: top - in: query - description: | - Using this parameter will allow the client to return the most popular articles - in the last `N` days. - - `top` indicates the number of days since publication of the articles - returned. - - This param can be used in conjuction with `tag`. - schema: - type: integer - format: int32 - minimum: 1 - example: 2 - - name: collection_id - in: query - description: | - Adding this will allow the client to return the list of articles - belonging to the requested collection, ordered by ascending - publication date. - schema: - type: integer - format: int32 - example: 99 - responses: - "200": - description: A list of articles - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ArticleIndex" - examples: - articles-success: - $ref: "#/components/examples/ArticlesIndex" - x-codeSamples: - - lang: Shell - label: curl (all articles) - source: | - curl https://dev.to/api/articles - - lang: Shell - label: curl (user's articles) - source: | - curl https://dev.to/api/articles?username=ben - post: - operationId: createArticle - summary: Create a new article - description: | - This endpoint allows the client to create a new article. - - "Articles" are all the posts that users create on DEV that typically - show up in the feed. They can be a blog post, a discussion question, - a help thread etc. but is referred to as article within the code. - - ### Rate limiting - - There is a limit of 10 requests per 30 seconds. - - ### Additional resources - - - [Rails tests for Articles API](https://github.com/forem/forem/blob/main/spec/requests/api/v0/articles_spec.rb) - tags: - - articles - requestBody: - description: Article to create - content: - application/json: - schema: - $ref: "#/components/schemas/ArticleCreate" - examples: - article-create-title-body: - $ref: "#/components/examples/ArticleCreateTitleBody" - article-create-front-matter: - $ref: "#/components/examples/ArticleCreateFrontMatter" - article-create-organization: - $ref: "#/components/examples/ArticleCreateOrganization" - - responses: - "201": - description: A newly created article - content: - application/json: - schema: - $ref: "#/components/schemas/ArticleShow" - examples: - article-success: - $ref: "#/components/examples/ArticleShow" - headers: - Location: - description: The URL of the new article - schema: - type: string - format: url - "400": - description: BadRequest - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-bad-request: - $ref: "#/components/examples/ErrorBadRequest" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - "403": - description: Forbidden - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-forbidden: - $ref: "#/components/examples/ErrorForbidden" - "422": - description: Unprocessable Entity - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unprocessable-entity: - $ref: "#/components/examples/ErrorUnprocessableEntity" - "429": - description: Too Many Requests - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unprocessable-entity: - $ref: "#/components/examples/ErrorTooManyRequests" - headers: - Retry-After: - description: The number of seconds to wait until the next request - schema: - type: integer - format: int32 - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -X POST -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"article":{"title":"Title","body_markdown":"Body","published":false,"tags":["discuss", "javascript"]}}' \ - https://dev.to/api/articles - - lang: Shell - label: curl (with front matter) - source: | - curl -X POST -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"article":{"body_markdown":"---\ntitle:A sample article about...\npublished:false\n---\n..."}}' \ - https://dev.to/api/articles - - /articles/latest: - get: - operationId: getLatestArticles - summary: Published articles sorted by publish date - description: | - This endpoint allows the client to retrieve a list of articles. - ordered by descending publish date. - - It supports pagination, each page will contain `30` articles by default. - tags: - - articles - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - responses: - "200": - description: A list of articles sorted by descending publish date - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ArticleIndex" - examples: - articles-success: - $ref: "#/components/examples/ArticlesIndex" - - /articles/{id}: - parameters: - - name: id - in: path - required: true - description: Id of the article - schema: - type: integer - format: int32 - minimum: 1 - example: 150589 - get: - operationId: getArticleById - summary: A published article by ID - description: | - This endpoint allows the client to retrieve a single - published article given its `id`. - tags: - - articles - responses: - "200": - description: An article - content: - application/json: - schema: - $ref: "#/components/schemas/ArticleShow" - examples: - article-success: - $ref: "#/components/examples/ArticleShow" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/articles/150589 - put: - operationId: updateArticle - summary: Update an article - description: | - This endpoint allows the client to update an existing article. - - "Articles" are all the posts that users create on DEV that typically - show up in the feed. They can be a blog post, a discussion question, - a help thread etc. but is referred to as article within the code. - - ### Rate limiting - - There is a limit of 30 requests per 30 seconds. - - ### Additional resources - - - [Rails tests for Articles API](https://github.com/forem/forem/blob/main/spec/requests/api/v0/articles_spec.rb) - tags: - - articles - requestBody: - description: | - Article params for the update. - - *Note: if the article contains a front matter in its body, its front - matter properties will still take precedence over any JSON equivalent - params, which means that the full body_markdown with the modified - front matter params needs to be provided for an update to be successful* - content: - application/json: - schema: - $ref: "#/components/schemas/ArticleUpdate" - examples: - article-update-title-body: - $ref: "#/components/examples/ArticleCreateTitleBody" - article-update-front-matter: - $ref: "#/components/examples/ArticleCreateFrontMatter" - article-update-organization: - $ref: "#/components/examples/ArticleCreateOrganization" - responses: - "200": - description: The updated article - content: - application/json: - schema: - $ref: "#/components/schemas/ArticleShow" - examples: - article-success: - $ref: "#/components/examples/ArticleShow" - "400": - description: BadRequest - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-bad-request: - $ref: "#/components/examples/ErrorBadRequest" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - "403": - description: Forbidden - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-forbidden: - $ref: "#/components/examples/ErrorForbidden" - "422": - description: Unprocessable Entity - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unprocessable-entity: - $ref: "#/components/examples/ErrorUnprocessableEntity" - "429": - description: Too Many Requests - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unprocessable-entity: - $ref: "#/components/examples/ErrorTooManyRequests" - headers: - Retry-After: - description: The number of seconds to wait until the next request - schema: - type: integer - format: int32 - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -X PUT -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"article":{"title":"Title"}}' \ - https://dev.to/api/articles/{id} - - /articles/{username}/{slug}: - parameters: - - name: username - in: path - required: true - description: User or organization username. - schema: - type: string - example: devteam - - name: slug - in: path - required: true - description: Slug of the article. - schema: - type: string - example: for-empowering-community-2k6h - get: - operationId: getArticleByPath - summary: A published article by path - description: | - This endpoint allows the client to retrieve a single - published article given its `path`. - tags: - - articles - responses: - "200": - description: An article - content: - application/json: - schema: - $ref: "#/components/schemas/ArticleShow" - examples: - article-success: - $ref: "#/components/examples/ArticleShow" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/articles/bytesized/byte-sized-episode-2-the-creation-of-graph-theory-34g1 - - /articles/me: - get: - operationId: getUserArticles - summary: User's articles - description: | - This endpoint allows the client to retrieve a list of published articles - on behalf of an authenticated user. - - "Articles" are all the posts that users create on DEV that typically - show up in the feed. They can be a blog post, a discussion question, - a help thread etc. but is referred to as article within the code. - - Published articles will be in reverse chronological publication order. - - It will return published articles with pagination. - By default a page will contain `30` articles. - tags: - - articles - - users - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - responses: - "200": - description: A list of published articles - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ArticleMe" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/articles/me - - /articles/me/published: - get: - operationId: getUserPublishedArticles - summary: User's published articles - description: | - This endpoint allows the client to retrieve a list of published articles - on behalf of an authenticated user. - - "Articles" are all the posts that users create on DEV that typically - show up in the feed. They can be a blog post, a discussion question, - a help thread etc. but is referred to as article within the code. - - Published articles will be in reverse chronological publication order. - - It will return published articles with pagination. - By default a page will contain `30` articles. - tags: - - articles - - users - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - responses: - "200": - description: A list of published articles - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ArticleMe" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/articles/me/published - - /articles/me/unpublished: - get: - operationId: getUserUnpublishedArticles - summary: User's unpublished articles - description: | - This endpoint allows the client to retrieve a list of unpublished articles - on behalf of an authenticated user. - - "Articles" are all the posts that users create on DEV that typically - show up in the feed. They can be a blog post, a discussion question, - a help thread etc. but is referred to as article within the code. - - Unpublished articles will be in reverse chronological creation order. - - It will return unpublished articles with pagination. - By default a page will contain `30` articles. - tags: - - articles - - users - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - responses: - "200": - description: A list of articles - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ArticleMe" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/articles/me/unpublished - - /articles/me/all: - get: - operationId: getUserAllArticles - summary: User's all articles - description: | - This endpoint allows the client to retrieve a list of all articles on - behalf of an authenticated user. - - "Articles" are all the posts that users create on DEV that typically - show up in the feed. They can be a blog post, a discussion question, - a help thread etc. but is referred to as article within the code. - - It will return both published and unpublished articles with pagination. - - Unpublished articles will be at the top of the list in reverse chronological creation order. - Published articles will follow in reverse chronological publication order. - - By default a page will contain `30` articles. - tags: - - articles - - users - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - responses: - "200": - description: A list of articles - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ArticleMe" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/articles/me/all - - /comments: - get: - operationId: getCommentsByArticleId - summary: Comments - description: | - This endpoint allows the client to retrieve all comments belonging to an - article or podcast episode as threaded conversations. - - It will return the all top level comments with their nested comments as - threads. See the format specification for further details. - tags: - - comments - parameters: - - name: a_id - in: query - description: Article identifier. - schema: - type: integer - format: int32 - minimum: 1 - example: 270180 - - name: p_id - in: query - description: Podcast Episode identifier. - schema: - type: integer - format: int32 - minimum: 1 - example: 124 - responses: - "200": - description: A list of threads of comments - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/Comment" - examples: - comments-success: - $ref: "#/components/examples/Comments" - comments-success-deleted: - $ref: "#/components/examples/CommentsDeleted" - comments-success-hidden: - $ref: "#/components/examples/CommentsHidden" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl (all comments of an article) - source: | - curl https://dev.to/api/comments?a_id=270180 - - lang: Shell - label: curl (all comments of a podcast episode) - source: | - curl https://dev.to/api/comments?p_id=124 - - /comments/{id}: - get: - operationId: getCommentById - summary: Comment - description: | - This endpoint allows the client to retrieve a comment as well as his - descendants comments. - - It will return the required comment (the root) with its nested - descendants as a thread. - - See the format specification for further details. - tags: - - comments - parameters: - - name: id - in: path - required: true - description: Comment identifier. - schema: - type: string - example: m35m - responses: - "200": - description: A comment and its descendants - content: - application/json: - schema: - $ref: "#/components/schemas/Comment" - examples: - comment-success: - $ref: "#/components/examples/Comment" - comments-success-deleted: - $ref: "#/components/examples/CommentDeleted" - comments-success-hidden: - $ref: "#/components/examples/CommentHidden" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl (a comment and its descendants) - source: | - curl https://dev.to/api/comments/m51e - - /followers/users: - get: - operationId: getFollowers - summary: Followers - description: | - This endpoint allows the client to retrieve a list of the followers - they have. - - "Followers" are users that are following other users on the website. - - It supports pagination, each page will contain `80` followers by default. - tags: - - followers - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam80to1000' - - in: query - name: sort - schema: - type: string - default: 'created_at' - pattern: '^-?\w+(,-?\w+)*$' - required: false - description: | - Specifies the sort order for the `created_at` param of the follow - relationship. To sort by newest followers first (descending order) - specify `?sort=-created_at`. - responses: - "200": - description: A list of followers - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/Follower" - examples: - followers-success: - $ref: "#/components/examples/Followers" - - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/followers/users - - /follows/tags: - get: - operationId: getFollowedTags - summary: Followed tags - description: | - This endpoint allows the client to retrieve a list of the tags - they follow. - tags: - - follows - - tags - responses: - "200": - description: A list of followed tags - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/FollowedTag" - examples: - followers-success: - $ref: "#/components/examples/TagsFollowed" - - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/follows/tags - - /listings: - get: - operationId: getListings - summary: Published listings - description: | - This endpoint allows the client to retrieve a list of listings. - - "Listings" are classified ads that users create on DEV. - They can be related to conference announcements, job offers, mentorships, - upcoming events and more. - - By default it will return published listings ordered by descending - freshness. - - It supports pagination, each page will contain `30` articles by default. - tags: - - listings - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - - $ref: '#/components/parameters/listingCategoryParam' - responses: - "200": - description: A list of listings - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/Listing" - examples: - listings-success: - $ref: "#/components/examples/Listings" - x-codeSamples: - - lang: Shell - label: curl (all listings) - source: | - curl https://dev.to/api/listings - post: - operationId: createListing - summary: Create a new listing - description: | - This endpoint allows the client to create a new listing. - - "Listings" are classified ads that users create on DEV. - They can be related to conference announcements, job offers, mentorships, - upcoming events and more. - - The user creating the listing or the organization on which behalf the user - is creating for need to have enough creadits for this operation to be - successful. The server will prioritize the organization's credits over - the user's credits. - - ### Additional resources - - - [Rails tests for Listings API](https://github.com/forem/forem/blob/main/spec/requests/api/v0/listings_spec.rb) - tags: - - listings - requestBody: - description: Listing to create - content: - application/json: - schema: - $ref: "#/components/schemas/ListingCreate" - examples: - listing-create: - $ref: "#/components/examples/ListingCreate" - listing-create-organization: - $ref: "#/components/examples/ListingCreateOrganization" - - responses: - "201": - description: A newly created Listing - content: - application/json: - schema: - $ref: "#/components/schemas/Listing" - examples: - article-success: - $ref: "#/components/examples/Listing" - "400": - description: BadRequest - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-bad-request: - $ref: "#/components/examples/ErrorBadRequest" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - "402": - description: PaymentRequired - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorPaymentRequired" - "422": - description: Unprocessable Entity - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unprocessable-entity: - $ref: "#/components/examples/ErrorUnprocessableEntity" - security: - - api_key: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -X POST -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"listing":{"title":"Title","body_markdown":"Body","category":"cfp"}}' \ - https://dev.to/api/listings - - lang: Shell - label: curl (with tags) - source: | - curl -X POST -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"listing":{"title":"Title","body_markdown":"Body","category":"cfp","tags":["python"]}}' \ - https://dev.to/api/listings - - lang: Shell - label: curl (draft) - source: | - curl -X POST -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"listing":{"title":"Title","body_markdown":"Body","category":"cfp","action":"draft"}}' \ - https://dev.to/api/listings - - /listings/category/{category}: - get: - operationId: getListingsByCategory - summary: Published listings by category - description: | - This endpoint allows the client to retrieve a list of listings belonging - to the specified category. - - "Listings" are classified ads that users create on DEV. - They can be related to conference announcements, job offers, mentorships, - upcoming events and more. - - By default it will return published listings ordered by descending - freshness. - - It supports pagination, each page will contain `30` articles by default. - tags: - - listings - parameters: - - name: category - in: path - required: true - description: The category of the listing - schema: - $ref: "#/components/schemas/ListingCategory" - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - responses: - "200": - description: A list of listings - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/Listing" - examples: - listings-success: - $ref: "#/components/examples/Listings" - x-codeSamples: - - lang: Shell - label: curl (call for papers listings) - source: | - curl https://dev.to/api/listings/category/cfp - - /listings/{id}: - parameters: - - name: id - in: path - required: true - description: Id of the listing - schema: - type: integer - format: int64 - minimum: 1 - example: 1 - get: - operationId: getListingById - summary: A listing - description: | - This endpoint allows the client to retrieve - a single listing given its `id`. - - An unpublished listing is only accessible if authentication is supplied - and it belongs to the authenticated user. - tags: - - listings - responses: - "200": - description: A listing - content: - application/json: - schema: - $ref: "#/components/schemas/Listing" - examples: - article-success: - $ref: "#/components/examples/Listing" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-not-found: - $ref: "#/components/examples/ErrorNotFound" - security: - - {} # this indicates that authentication is optional - - api_key: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/listings/1184 - - lang: Shell - label: curl (with authentication) - source: | - curl -H "api-key: API_KEY" https://dev.to/api/listings/1185 - put: - operationId: updateListing - summary: Update a listing - description: | - This endpoint allows the client to update an existing listing. - tags: - - listings - requestBody: - description: | - Listing params for the update. - - **Note**: except for bumping, publishing and unpublishing there are the - following restrictions on the ability to update listings: - - - the payload has to contain at least one param among `title`, `body_markdown` or `tags`/`tag_list` - - the listing can't be updated if it has not been bumped in the last 24 hours - - the listing can't be updated if it has been published but not recently bumped - content: - application/json: - schema: - $ref: "#/components/schemas/ListingUpdate" - examples: - listing-update-action-bump: - $ref: "#/components/examples/ListingUpdateActionBump" - listing-update-action-publish: - $ref: "#/components/examples/ListingUpdateActionPublish" - listing-update-action-unpublish: - $ref: "#/components/examples/ListingUpdateActionUnpublish" - listing-update: - $ref: "#/components/examples/ListingUpdate" - responses: - "200": - description: The updated article - content: - application/json: - schema: - $ref: "#/components/schemas/ArticleShow" - examples: - article-success: - $ref: "#/components/examples/ArticleShow" - "400": - description: BadRequest - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-bad-request: - $ref: "#/components/examples/ErrorBadRequest" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - "402": - description: PaymentRequired - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorPaymentRequired" - "422": - description: Unprocessable Entity - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unprocessable-entity: - $ref: "#/components/examples/ErrorUnprocessableEntity" - security: - - api_key: [] - x-codeSamples: - - lang: Shell - label: curl (bump) - source: | - curl -X PUT -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"listing":{"action":"bump"}' \ - https://dev.to/api/listings/{id} - - lang: Shell - label: curl (update) - source: | - curl -X PUT -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"listing":{"title":"Title"}' \ - https://dev.to/api/listings/{id} - - /readinglist: - get: - operationId: getReadinglist - summary: User's reading list - description: | - This endpoint allows the client to retrieve a list of readinglist reactions along with the related article for the authenticated user. - - Reading list will be in reverse chronological order base - on the creation of the reaction. - - It will return paginated reading list items along with the articles - they refer to. By default a page will contain `30` items - tags: - - readinglist - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to100' - responses: - "200": - description: The reading list with a overwiew of the article - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ReadingList" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/readinglist - - /organizations/{username}: - get: - operationId: getOrganization - summary: An organization - description: | - This endpoint allows the client to retrieve a single organization by their username - tags: - - organizations - parameters: - - name: username - in: path - required: true - description: | - Username of the organization - schema: - type: string - example: "ecorp" - responses: - "200": - description: An organization - content: - application/json: - schema: - $ref: "#/components/schemas/Organization" - examples: - user-success: - $ref: "#/components/examples/Organization" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - user-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/organizations/ecorp - - /organizations/{username}/users: - get: - operationId: getOrgUsers - summary: Organization's users - description: | - This endpoint allows the client to retrieve a list of users belonging to the organization - - It supports pagination, each page will contain `30` users by default. - tags: - - organizations - parameters: - - name: username - in: path - required: true - description: | - Username of the organization - schema: - type: string - example: "ecorp" - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - responses: - "200": - description: A list of users belonging to the organization - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/User" - examples: - user-success: - $ref: "#/components/examples/Users" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - user-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/organizations/ecorp/users - - /organizations/{username}/listings: - get: - operationId: getOrgListings - summary: Organization's listings - description: | - This endpoint allows the client to retrieve a list of listings belonging to the organization - - It supports pagination, each page will contain `30` listing by default. - tags: - - organizations - parameters: - - name: username - in: path - required: true - description: | - Username of the organization - schema: - type: string - example: "ecorp" - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - - $ref: '#/components/parameters/listingCategoryParam' - responses: - "200": - description: A list of listings belonging to the organization - content: - application/json: - schema: - type: array - items: - allOf: - - $ref: "#/components/schemas/Listing" - - required: - - organization - examples: - user-success: - $ref: "#/components/examples/ListingsByOrganization" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - user-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/organizations/ecorp/listings - - /organizations/{username}/articles: - get: - operationId: getOrgArticles - summary: Organization's Articles - description: | - This endpoint allows the client to retrieve a list of Articles belonging to the organization - - It supports pagination, each page will contain `30` listing by default. - tags: - - organizations - parameters: - - name: username - in: path - required: true - description: | - Username of the organization - schema: - type: string - example: "ecorp" - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - responses: - "200": - description: A list of users belonging to the organization - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ArticleIndex" - examples: - article-success: - $ref: "#/components/examples/ArticlesIndex" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - user-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/organizations/ecorp/listings - - /podcast_episodes: - get: - operationId: getPodcastEpisodes - summary: Published podcast episodes - description: | - This endpoint allows the client to retrieve a list of podcast episodes. - - "Podcast episodes" are episodes belonging to podcasts. - - It will only return active podcast episodes that belong to published - podcasts available on the platform, - ordered by descending publication date. - - It supports pagination, each page will contain `30` articles by default. - tags: - - podcast-episodes - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam30to1000' - - name: username - in: query - description: | - Using this parameter will retrieve episodes belonging - to a specific podcast. - schema: - type: string - example: codenewbie - responses: - "200": - description: A list of podcast episodes - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/PodcastEpisode" - examples: - articles-success: - $ref: "#/components/examples/PodcastEpisodes" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl (all podcast episodes) - source: | - curl https://dev.to/api/podcast_episodes - - lang: Shell - label: curl (all episodes belonging to a podcast) - source: | - curl https://dev.to/api/podcast_episodes?username=codenewbie - - /tags: - get: - operationId: getTags - summary: Tags - description: | - This endpoint allows the client to retrieve a list of tags - that can be used to tag articles. - - It will return tags ordered by popularity. - - It supports pagination, each page will contain `10` tags by default. - tags: - - tags - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam10to1000' - responses: - "200": - description: A list of tags - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/Tag" - examples: - articles-success: - $ref: "#/components/examples/Tags" - x-codeSamples: - - lang: Shell - label: curl (all tags) - source: | - curl https://dev.to/api/tags - - /users/{id}: - get: - operationId: getUser - summary: A user - description: | - This endpoint allows the client to retrieve a single user, either by - id or by the user's username - tags: - - users - parameters: - - name: id - in: path - required: true - description: | - Id of the user. - - It can be either of the following two values: - - - an integer representing the id of the user - - the string `by_username` (needs to be used in conjuction with the param `url`) - schema: - type: string - example: "1" - - name: url - in: query - description: Username of the user - schema: - type: string - example: ben - responses: - "200": - description: A user - content: - application/json: - schema: - $ref: "#/components/schemas/User" - examples: - user-success: - $ref: "#/components/examples/User" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - user-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl (by id) - source: | - curl https://dev.to/api/users/1 - - lang: Shell - label: curl (by username) - source: | - curl https://dev.to/api/users/by_username?url=ben - - /users/me: - get: - operationId: getUserMe - summary: The authenticated user - description: | - This endpoint allows the client to retrieve information - about the authenticated user - tags: - - users - responses: - "200": - description: A user - content: - application/json: - schema: - $ref: "#/components/schemas/User" - examples: - user-success: - $ref: "#/components/examples/User" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/users/me - - /profile_images/{username}: - get: - operationId: getProfileImage - summary: User or organization profile picture - description: | - This endpoint allows the client to retrieve a user or organization - profile image information by its corresponding username - tags: - - profile images - parameters: - - name: username - in: path - required: true - description: Username of the user or organization - schema: - type: string - example: "diogoosorio" - responses: - "200": - description: The profile image - content: - application/json: - schema: - $ref: "#/components/schemas/ProfileImage" - examples: - profile-image-success: - $ref: "#/components/examples/ProfileImage" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - profile-image-not-found: - $ref: "#/components/examples/ErrorNotFound" - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/profile_images/diogoosorio - - /videos: - get: - operationId: getArticlesWithVideo - summary: Articles with a video - description: | - This endpoint allows the client to retrieve a list of articles - that are uploaded with a video. - - It will only return published video articles - ordered by descending popularity. - - It supports pagination, each page will contain `24` articles by default. - tags: - - articles - - videos - parameters: - - $ref: '#/components/parameters/pageParam' - - $ref: '#/components/parameters/perPageParam24to1000' - responses: - "200": - description: A list of video articles - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/ArticleVideo" - examples: - articles-success: - $ref: "#/components/examples/ArticleVideo" - x-codeSamples: - - lang: Shell - label: curl (all video articles) - source: | - curl https://dev.to/api/videos - - /webhooks: - get: - operationId: getWebhooks - summary: Webhooks - description: | - This endpoint allows the client to retrieve a list of webhooks they have - previously registered. - - "Webhooks" are used to register HTTP endpoints that will be called once a relevant event is - triggered inside the web application, events like `article_created`, `article_updated`. - - It will return all webhooks, without pagination. - tags: - - webhooks - responses: - "200": - description: A list of webhooks - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/WebhookIndex" - examples: - webhooks-success: - summary: Successful response - value: - - type_of: webhook_endpoint - id: 1 - source: DEV - target_url: https://example.com/webhooks/webhook1 - events: - - article_created - created_at: "2019-09-02T09:47:39.230Z" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -H "api-key: API_KEY" https://dev.to/api/webhooks - post: - operationId: createWebhook - summary: Create a new webhook - description: | - This endpoint allows the client to create a new webhook. - - "Webhooks" are used to register HTTP endpoints that will be called once a relevant event is - triggered inside the web application, events like `article_created`, `article_updated`. - tags: - - webhooks - requestBody: - description: Webhook to create - content: - application/json: - schema: - $ref: "#/components/schemas/WebhookCreate" - examples: - webhook-create: - $ref: "#/components/examples/WebhookCreate" - - responses: - "201": - description: A newly created webhook - content: - application/json: - schema: - $ref: "#/components/schemas/WebhookShow" - examples: - webhook-success: - $ref: "#/components/examples/WebhookShow" - "400": - description: BadRequest - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-bad-request: - $ref: "#/components/examples/ErrorBadRequest" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - "422": - description: Unprocessable Entity - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - error-unprocessable-entity: - $ref: "#/components/examples/ErrorUnprocessableEntity" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -X POST -H "Content-Type: application/json" \ - -H "api-key: API_KEY" \ - -d '{"webhook_endpoint":{"target_url":"https://example.org/webhooks/webhook1","source":"DEV","events":["article_created"]}}' \ - https://dev.to/api/webhooks - - /webhooks/{id}: - parameters: - - name: id - in: path - required: true - description: Id of the webhook - schema: - type: integer - format: int64 - minimum: 1 - example: 123 - get: - operationId: getWebhookById - summary: A webhook endpoint - description: | - This endpoint allows the client to retrieve a single - webhook given its `id`. - tags: - - webhooks - responses: - "200": - description: A webhook endpoint - content: - application/json: - schema: - $ref: "#/components/schemas/WebhookShow" - examples: - webhook-success: - $ref: "#/components/examples/WebhookShow" - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-not-found: - $ref: "#/components/examples/ErrorNotFound" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl https://dev.to/api/webhooks/123 - delete: - operationId: deleteWebhook - summary: A webhook endpoint - description: | - This endpoint allows the client to delete a single - webhook given its `id`. - tags: - - webhooks - responses: - "204": - description: A successful deletion - "401": - description: Unauthorized - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-unauthorized: - $ref: "#/components/examples/ErrorUnauthorized" - "404": - description: Resource not found - content: - application/json: - schema: - $ref: "#/components/schemas/APIError" - examples: - article-not-found: - $ref: "#/components/examples/ErrorNotFound" - security: - - api_key: [] - - oauth2: [] - x-codeSamples: - - lang: Shell - label: curl - source: | - curl -X DELETE \ - -H "api-key: API_KEY" \ - https://dev.to/api/webhooks/1 diff --git a/docs/backend/audit-log.md b/docs/backend/audit-log.md deleted file mode 100644 index 63701fdcd..000000000 --- a/docs/backend/audit-log.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Audit Log ---- - -# Audit Log - -To help maintain accountability for users with elevated permissions the Forem -application has a special model that records certain actions. - -For example, when a user with the `trusted` role creates a negative reaction on -an article a record is created with certain information about that action. - -That record (which we call an `AuditLog`) looks something like this: - -```ruby -#"create", "category"=>"vomit", "controller"=>"reactions", "reactable_id"=>"16", "reactable_type"=>"Article"}, - roles: ["trusted"], - slug: "create", - updated_at: Thu, 07 May 2020 20:25:31 UTC +00:00, - user_id: 21> -``` - -You can see from this record that the user with an id of `21` created a vomit -reaction on the article with an id of `16`. If that's not obvious to you from -this object, don't worry, just take our word on it. - -You can find an example of `Audit::Logger` in action in -`app/controllers/admin/reactions_controller.rb`: - -```ruby - after_action only: [:update] do - Audit::Logger.log(:moderator, current_user, params.dup) - end -``` - -This code creates a record to indicate that a someone modified a reaction from -the admin controller. - -It's a good idea to add a similar `after_action` to any controller action that -might benefit from increased transparency. - -Additionally, the `AuditLog` is used to track important actions performed on a -user's account, e.g. adding or removing a credit card: - -```ruby -# { - category: "user.credit_card.edit", - created_at: Tue, 21 Jul 2020 06:35:13 +03 +03:00, - data: { - "action" => "create", - "controller" => "stripe_active_cards", - "user_action" => "add" - }, - id: 4, - roles: [], - slug: "credit_card_add", - updated_at: Tue, 21 Jul 2020 06:35:13 +03 +03:00, - user_id: 53 -} -``` diff --git a/docs/backend/auth-apple.md b/docs/backend/auth-apple.md deleted file mode 100644 index f292675ae..000000000 --- a/docs/backend/auth-apple.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: Apple Authentication ---- - -# Sign in with Apple Authentication - -Forem allows you to authenticate using -[Sign in with Apple](https://developer.apple.com/sign-in-with-apple/). In order -to use this authentication method you'll need to be enrolled to the -[Apple Developer Program](https://developer.apple.com/programs/) in order to -retrieve the necessary credentials and an HTTPS supported URL for the callback -configuration (HTTP won't work). Then you'll need to provide the keys to the -Rails application. - -# Apple Developer Portal Configuration - -[Register/Sign in](https://developer.apple.com/account) to your Apple Developer -Account. - -## Service ID Configuration - -1. [Create a Service ID](https://developer.apple.com/account/resources/identifiers/list/serviceId) - -![Create Service ID](https://user-images.githubusercontent.com/6045239/92610177-a5cc9e00-f274-11ea-9f63-20d8356d0bee.png) - -2. Name the Service and finalize the registration - -![Naming Service ID](https://user-images.githubusercontent.com/6045239/92610168-a36a4400-f274-11ea-8f79-7516c0c6c9c3.png) - -3. Configure Domains and Subdomains & the callback URL. This example uses - [ngrok](https://ngrok.io) for HTTPS support. - -![Callback URLS](https://user-images.githubusercontent.com/6045239/92610184-a8c78e80-f274-11ea-9439-a98c6b627567.png) - -## Key Configuration - -1. [Register a new Key](https://developer.apple.com/account/resources/authkeys/add). - Enable the "Sign in with Apple" option and configure it so it's associated - with the corresponding App ID - -![Register a new Key](https://user-images.githubusercontent.com/6045239/92611125-b3ceee80-f275-11ea-9c00-e1b5ca2f9af0.png) - -2. Download the Key - -![Download the Key](https://user-images.githubusercontent.com/6045239/92611466-0f00e100-f276-11ea-912d-f8a74b6dfb04.png) - -# Configuring the Rails Application - -Now with both the Service ID and Key you'll need to enable Apple Authentication -and pass in the credentials in the admin dashboard -`/admin/customization/config`. - -![Admin Authentication Configuration Dashboard](https://user-images.githubusercontent.com/6045239/92613383-25a83780-f278-11ea-94a7-b710da544c9d.png) - -Add the corresponding configuration data. Make sure the PEM key you downloaded -has explicit linebreaks (`\n`), don't forget the one at the very end of it. - -![Apple config](https://user-images.githubusercontent.com/6045239/92614087-e0d0d080-f278-11ea-8d20-45148e1a6b59.png) - -Save the changes and restart your server for these values to take effect. - -## Email configuration - -Apple uses what they call Private Email Relay Service to hide user's emails. For -this to work first -[create a new email source](https://developer.apple.com/account/resources/services/list). - -![Email configuration](https://user-images.githubusercontent.com/6045239/92612469-22607c00-f277-11ea-918d-697cf4a18b15.png) - -Emails sent need to be authenticated and the configuration depends on the -different providers available: - -- [Mailchimp](https://mailchimp.com/help/set-up-custom-domain-authentication-dkim-and-spf/) -- [SendGrid](https://sendgrid.com/docs/ui/account-and-settings/how-to-set-up-domain-authentication/) -- [SES](https://docs.aws.amazon.com/es_es/ses/latest/DeveloperGuide/send-email-authentication-dkim.html) diff --git a/docs/backend/auth-facebook.md b/docs/backend/auth-facebook.md deleted file mode 100644 index c165eb9b9..000000000 --- a/docs/backend/auth-facebook.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Facebook Authentication ---- - -# Facebook App and Authentication - -Forem allows you to authenticate using Facebook. In order to use this -authentication method in local development, you will need to setup a Facebook -App and retrieve its keys. Then you'll need to provide these keys to the Rails -application. - -## Sign up - -1. [Sign in](https://facebook.com) to your Facebook account. - -2. In order to get the API keys, you will have to - [convert your account to a developer account](https://developers.facebook.com/). - -## Get API keys - -1. [Sign up](#facebook-sign-up) or [sign in](https://developers.facebook.com) to - your Facebook developer account. - -2. From **My Apps** dashboard, click on **Add a New App**. - - ![facebook-1](https://user-images.githubusercontent.com/37842/90912963-1f254f00-e3a1-11ea-9db9-2b77bddfe185.png) - -3. Select **For Everything Else** - - ![facebook-2](https://user-images.githubusercontent.com/37842/90913109-627fbd80-e3a1-11ea-8d78-d0b2bde76b3d.png) - -4. Fill in the app display name and contact email, then click on **Create App - ID** - - ![facebook-3](https://user-images.githubusercontent.com/37842/90913171-7b886e80-e3a1-11ea-9359-c4642c05c7b6.png) - -5. On the **Add a Product** screen, click **Set Up** under the **Facebook - Login** section - - ![facebook-4](https://user-images.githubusercontent.com/37842/90913219-8d6a1180-e3a1-11ea-86cb-d0b0d8681887.png) - -6. Ignore the quickstart options, and click **Settings -> Basic** in the sidebar - - ![facebook-5](https://user-images.githubusercontent.com/37842/90913319-b5f20b80-e3a1-11ea-866a-0b06cf3296c7.png) - -7. From the basic settings screen dashboard copy the **App ID** and **App - Secret** values to your `.env` file accordingly (name of Facebook key -> name - of our `Settings::General` variable). - - ```text - APP ID -> FACEBOOK_APP_ID - API secret -> FACEBOOK_APP_SECRET - ``` - - ![facebook-6](https://user-images.githubusercontent.com/37842/90913396-d5893400-e3a1-11ea-93f5-a0fbb06a0c53.png) - -## Configure the Facebook App - -1. From the basic settings screen dashboard set your application's domain name - in **App Domains** field, and be sure to click **Save Changes** - - ![facebook-7](https://user-images.githubusercontent.com/37842/91494838-20fa8100-e87f-11ea-8609-0d3b92edc093.png) - -2. Naviate to **Facebook Login --> Settings**, and enter the following callback - URL in the field **Valid OAuth Redirect URIs**: - - `https://>/users/auth/facebook/callback` - - ![facebook-8](https://user-images.githubusercontent.com/37842/91509964-48624580-e8a1-11ea-9f7b-931cfcb7cd87.png) diff --git a/docs/backend/auth-github.md b/docs/backend/auth-github.md deleted file mode 100644 index feccd95b3..000000000 --- a/docs/backend/auth-github.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: GitHub Authentication ---- - -# GitHub App and Authentication - -Forem allows you to authenticate using GitHub. To use this authentication method -in local development, you will need to set up a GitHub App and retrieve its -keys. Then you'll need to provide these keys to the Rails application. - -1. [Click this link to create a new OAuth application in your Github account](https://github.com/settings/applications/new) - - you will be redirected to sign in to Github account if you have not already. - -2. Fill in the form with an application name, description, and the URL - `http://localhost:3000/users/auth/github/callback`. Replace the port `3000` if you run Forem on another - port. - - ![github-1](https://user-images.githubusercontent.com/8124558/107048692-37dec100-6797-11eb-83d0-1e72db033522.png) - -3. You will be redirected to the app's **Developer settings**. Here you will - find the keys. Add them to your `.env` file accordingly (name of GitHub key - -> name of our `ENV` variable): - - ```text - Client ID -> GITHUB_KEY - Client Secret -> GITHUB_SECRET - ``` - - ![github-2](https://user-images.githubusercontent.com/22895284/51085862-49337b80-173f-11e9-8503-f8251d07f458.png) - -4. Done. diff --git a/docs/backend/auth-twitter.md b/docs/backend/auth-twitter.md deleted file mode 100644 index 89f71e54a..000000000 --- a/docs/backend/auth-twitter.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Twitter Authentication ---- - -# Twitter App and Authentication - -Forem allows you to authenticate using Twitter. In order to use this -authentication method in local development, you will need to setup a Twitter App -and retrieve its keys. Then you'll need to provide these keys to the Rails -application. - -## Sign up - -1. [Sign in](https://developer.twitter.com/apps) to your Twitter account. - -2. In order to get the API keys, you will have to - [apply for a developer account](https://developer.twitter.com/en/apply-for-access). - Click the **Apply** button. - - ![twitter-up-1](https://user-images.githubusercontent.com/22895284/51078779-53139b00-16bb-11e9-911c-f232e229872a.png) - -3. Setup your Twitter account. Be sure you have your phone number and email - address filled in. - - ![twitter-up-2](https://user-images.githubusercontent.com/22895284/51078780-53139b00-16bb-11e9-91d5-08c9365ff08f.png) - -4. Fill in your account information and give a name to your **developer - account**. - - ![twitter-up-3](https://user-images.githubusercontent.com/22895284/51078781-53ac3180-16bb-11e9-8cf4-005efbb92d8a.png) - -5. Write down the reasons that you want to use Twitter API. Mention Forem's - community and describe the issues and tests and things that you want to work - on. Copy it, you might use it later ;) - - ![twitter-up-4](https://user-images.githubusercontent.com/22895284/51078782-53ac3180-16bb-11e9-9937-c888ae40143c.png) - -6. Read :) and accept the Terms and Conditions. - - ![twitter-up-5](https://user-images.githubusercontent.com/22895284/51078783-53ac3180-16bb-11e9-9cf1-8e009ada6e57.png) - -7. Verify your email address once more, and you will be done. - -8. You are done. - -## Get API keys - -1. [Sign up](#twitter-sign-up) or [sign in](https://developer.twitter.com/apps) - to your Twitter developer account. - -2. From **Apps** dashboard, click on **Create and app**. - - ![twitter-1](https://user-images.githubusercontent.com/22895284/51078797-9a019080-16bb-11e9-8130-1cd13008461e.png) - -3. Fill in the app name, description, and URL `https://dev.to`. - - ![twitter-2](https://user-images.githubusercontent.com/22895284/51078798-9a019080-16bb-11e9-900d-d2677d7c43c4.png) - -4. Check the **Enable Sign in with Twitter** option and fill in the Callback URL - `http://localhost:3000/users/auth/twitter/callback` (or whatever port you run - Forem on). - - ![twitter-3](https://user-images.githubusercontent.com/22895284/51078799-9a9a2700-16bb-11e9-8e88-0393260449c7.png) - -5. Fill in the information, **Terms of Service** `http://dev.to/terms` and - **Privacy policy** `http://dev.to/privacy`. - - ![twitter-4](https://user-images.githubusercontent.com/22895284/51078800-9a9a2700-16bb-11e9-9b36-d325a2624f5a.png) - -6. Write down (or paste) the things that you will work on. Press **Create**. - - ![twitter-5](https://user-images.githubusercontent.com/22895284/51078801-9a9a2700-16bb-11e9-9bd9-76c9ca1ba526.png) - -7. Review the - [Twitter Developer Terms](https://developer.twitter.com/en/developer-terms/agreement-and-policy.html) - and agree to do nothing sketchy. - - ![twitter-6](https://user-images.githubusercontent.com/22895284/51078802-9a9a2700-16bb-11e9-8789-53720bcfc9d9.png) - -8. The app is all set! - -9. One more change: From the app dashboard, go to **Permissions** and check - **Request email addresses from users** option. - - ![twitter-7](https://user-images.githubusercontent.com/22895284/51078803-9a9a2700-16bb-11e9-8f27-dbfe04b52031.png) - -10. From the same dashboard access the **Keys and tokens** and add them to your - `.env` file accordingly (name of Twitter key -> name of our `ENV` variable). - Be sure to copy the _access token_ and _access token secret_ right away - because it will be hidden from you in the future. - - ```text - API key -> TWITTER_KEY - API secret key -> TWITTER_SECRET - ``` - - ![twitter-8](https://user-images.githubusercontent.com/47985/72329507-72d30a00-36e7-11ea-83ac-ebea5d41ba39.png) diff --git a/docs/backend/authentication.md b/docs/backend/authentication.md deleted file mode 100644 index d7cc97e2c..000000000 --- a/docs/backend/authentication.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Authentication ---- - -# Authentication - -Authentication is handled by [Devise](https://github.com/plataformatec/devise) -and [OmniAuth](https://github.com/omniauth/omniauth). - -On Forem you can authenticate through Facebook, GitHub, or Twitter. Please check out -the respective guides on how to authenticate: - -- [Apple authentication](/backend/auth-apple) -- [Facebook authentication](/backend/auth-facebook) -- [Github authentication](/backend/auth-github) -- [Twitter authentication](/backend/auth-twitter) - -We may add other authentication providers in the future. Please check back -again, or search -[our GitHub repository's issues.](https://github.com/forem/forem/issues) diff --git a/docs/backend/authorization.md b/docs/backend/authorization.md deleted file mode 100644 index 4555b7d05..000000000 --- a/docs/backend/authorization.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Authorization ---- - -# Authorization - -Authorization is handled by the third-party gem -[Pundit](https://github.com/varvet/pundit) through the `authorize` method which -you can find in various controllers, look for statements like: - -```ruby -authorize @user -``` - -All authorization policies can be found in `/app/policies`. diff --git a/docs/backend/configuration.md b/docs/backend/configuration.md deleted file mode 100644 index 324149a9d..000000000 --- a/docs/backend/configuration.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Configuration ---- - -# Configuration - -We currently use the following gems for configuring the application: - -- [dotenv](https://github.com/bkeepers/dotenv) -- [rails-settings-cached](https://github.com/huacnlee/rails-settings-cached) -- [vault](https://github.com/hashicorp/vault-ruby) - -## dotenv - -This gem is used for configuring environment variables for test and development -environments. Examples: - -- `REDIS_URL` -- `FASTLY_API_KEY` -- `STRIPE_SECRET_KEY` - -Settings managed via your ENV can be found in -[Configuring Environment Variables](/getting-started/config-env)) and viewed at -`/admin/customization/config` (see [the Admin guide](/admin)): - -![Screenshot of env variable admin interface](https://user-images.githubusercontent.com/47985/73627243-67d41f80-467e-11ea-9121-221275ff8a89.png) - -## rails-settings-cached - -We use this gem for managing settings used within the app's business logic. -Examples: - -- `Settings::General.main_social_image` -- `Settings::RateLimit.follow_count_daily` -- `Settings::Authentication.twitter_secret` - -These settings can be accessed via the -[`Settings::General`](https://github.com/forem/forem/blob/master/app/models/settins/general.rb) -object and various models in the `Settings::` namespace and viewed / modified -via `/admin/customization/config` (see [the Admin guide](/admin)). - -![Screenshot of settings admin interface](https://user-images.githubusercontent.com/47985/73627238-6276d500-467e-11ea-8724-afb703f056bc.png) - -## Vault - -The vault Ruby gem allows us to interact with -[Vault](https://www.vaultproject.io/docs/what-is-vault). In a nutshell, Vault is -a tool for securely storing and accessing secrets. It is completely optional for -running a Forem. To access it we use the wrapper `AppSecrets`. - -```ruby -class AppSecrets - def self.[](key) - result = Vault.kv(namespace).read(key)&.data&.fetch(:value) if ENV["VAULT_TOKEN"].present? - result ||= ApplicationConfig[key] - - result - rescue Vault::VaultError - ApplicationConfig[key] - end - - def self.[]=(key, value) - Vault.kv(namespace).write(key, value: value) - end - - def self.namespace - ENV["VAULT_SECRET_NAMESPACE"] - end - private_class_method :namespace -end -``` - -We attempt to access a secret from Vault if it is enabled, i.e. if the -`VAULT_TOKEN` is present. If Vault is not enabled or if we cannot find the -secret in it, then we fallback to fetching the secret from the -`ApplicationConfig`. - -One advantage of using Vault with Forem is that it allows you to update your -secrets easily through the application rather than having to mess with ENV -files. If you would like to try out Vault, follow our -[installation guide for setting it up locally](/installation/vault). diff --git a/docs/backend/data-update-scripts.md b/docs/backend/data-update-scripts.md deleted file mode 100644 index 7143f8676..000000000 --- a/docs/backend/data-update-scripts.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Data Update Scripts ---- - -## What are Data Update Scripts? - -Data Update Scripts were introduced in -[this PR](https://github.com/forem/forem/pull/6025) and allow us to run any data -updates we might need. For example, if we added a column to the database and -then wanted to backfill that column with data, rather than going and manually -doing it in a console, we would use a DataUpdateScript. - -## How it works - -First off, we added a -[DataUpdateScript model](https://github.com/forem/forem/blob/master/app/models/data_update_script.rb) -to Rails and a corresponding database table. This table is what we use to keep -track of what scripts have been run and which ones have not/still need to be. - -To create a script you can use our custom Rails generator: - -``` -rails generate data_update BackfillColumnForArticles -``` - -This will create a simple Ruby class like below and all you have to do is fill -in the code it will run. - -```ruby -module DataUpdateScripts - class BackfillColumnForArticles - def run - # Place your data update logic here - # Make sure your code is idempotent and can be run safely - # multiple times at any time - end - end -end -``` - -The generator will also automatically create the corresponding spec file. - -```ruby -require "rails_helper" -require Rails.root.join( - "lib/data_updates/20201103042915_backfill_column_for_articles.rb", -) - -describe DataUpdateScripts::BackfillColumnForArticles do - pending "add some examples to (or delete) #{__FILE__}" -end -``` - -While we encourage adding tests for data update scripts, you can skip spec -creation by adding the `--no-spec` option to the `rails generate` command: - -``` -rails generate data_update BackfillColumnForArticles --no-spec -``` - -Once your script is in place then you can either run `rails data_updates:run` -manually or you can let our setup script handle it. In our local -[bin/setup](https://github.com/forem/forem/blob/main/bin/setup) script you will -see we have added an additional task to update data. This kicks off the rake -task `data_updates:run` for you. - -The rake task itself will check the `lib/data_update_scripts` folder to see if -there are any new scripts that need to be run. It does this by reading all of -the files and then checking to see if they have a corresponding database entry. -If they do not, then we create a new one and run the script. If a database entry -already exists and it indicates the script has been run, then we skip that -script. - -## In production - -DataUpdateScripts are also run automatically when a production deploy goes out. -However, to ensure the new code they need to use has been deployed we use a -[`DataUpdateWorker`](https://github.com/forem/forem/blob/main/app/workers/data_update_worker.rb) -via Sidekiq and set it to run 10 minutes after the deploy script has completed. - -## Best practices - -### Working with large collections of rows - -From time to time, scripts need to operate on a large amount of rows; in those -cases we encourage: - -- adding explicit logging to the script -- reversing the order, to start processing the most recent records first - -For example: - -```ruby -def run - Article.find_each(order: :desc).with_index do |article, index| - Rails.logging.info("...") if index % 1000 == 0 # this will log every 1000 articles - - article.save - end -end -``` diff --git a/docs/backend/emails.md b/docs/backend/emails.md deleted file mode 100644 index 9f663170a..000000000 --- a/docs/backend/emails.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Emails ---- - -# Setting up email - -If you would like to enable transactional email using services like SendGrid or -Mailgun, you can configure it by using the following environment variables: - -```shell -SMTP_ADDRESS= # ie. "smtp.sendgrid.net" -SMTP_PORT= # ie. 587 -SMTP_DOMAIN= -SMTP_USER_NAME= -SMTP_PASSWORD= -SMTP_AUTHENTICATION= # defaults to :plain -``` - -We follow the standard `ActionMailer` configuration. For more info, please check -out Rails' -[official documentation](https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration). - -# Previewing emails in development - -You can view email previews at . - -Previews are setup in the directory `spec/mailers/previews`. - -# Overriding mailer templates - -To update the contents of emails that the app sends, edit the views under -`app/views/mailers`. Note that this app uses the -[`devise_invitable` gem](https://github.com/scambra/devise_invitable) for -invitations. The views for this gem are stored under `app/views/devise/mailer`. diff --git a/docs/backend/fastly.md b/docs/backend/fastly.md deleted file mode 100644 index ba2074a98..000000000 --- a/docs/backend/fastly.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Fastly ---- - -## What is Fastly? - -[Fastly](https://www.fastly.com/) is a third party service we use for caching on -the edge. It allows us to scale up and serve our millions of visitors quickly -and efficiently. - -If you want to learn more about we use Fastly, check out this -[talk](https://www.youtube.com/watch?v=Afy7H04X9Us) that one of our founders, -[@benhalpern](https://dev.to/ben), gave at RailsConf 2018 talking about how we -made our app so fast it went viral. - -Fastly offers many different configurations (conditions, -[snippets](https://docs.fastly.com/vcl/vcl-snippets/about-vcl-snippets/), etc.). - -## Snippets - -Snippets, in general, are _"short blocks of VCL logic that can be included -directly in your service configurations. They're ideal for adding small sections -of code when you don't need more complex, specialized configurations that -sometimes require custom VCL."_ - -You can learn more about VCL snippets on -[Fastly's website](https://docs.fastly.com/vcl/vcl-snippets/about-vcl-snippets/) - -### Adding query string parameters to a safe list - -In the context of contributing, here's what you need to know about Fastly. In -order for our servers to receive any sort of query string parameters in a -request, they must first be marked as safe in Fastly. For example, if you're -creating a new API endpoint or updating an existing one to accept new -parameters, you'll need to update Fastly. - -The reason we have a safe list of parameters in Fastly this way is so we don't -have to consider junk parameters when busting the caches. Check out our -[`EdgeCache` services](https://github.com/forem/forem/tree/main/app/services/edge_cache) -to see examples of this. - -Previously this was a manual process done by an internal team member. Now we do -it programmatically using the Fastly -[gem](https://github.com/fastly/fastly-ruby). - -### How it works - -We created a new file, `config/fastly/safe_params_list.vcl`, to house all of the -safe params in Fastly. - -If you need to update this list, simply update this file. It's as easy as that! -This is a VCL file and you'll see a little Regex checking for a list of safe -params. - -_Fastly is not setup for development._ - -### In production - -If you have Fastly configured in Production, all Fastly configs are updated -automatically when a production deploy goes out. - -We do this by executing `bin/rails fastly:update_configs` in our -`release-tasks.sh` script. diff --git a/docs/backend/internationalization.md b/docs/backend/internationalization.md deleted file mode 100644 index 117ba0638..000000000 --- a/docs/backend/internationalization.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: Internationalization (i18n) ---- - -# Internationalization (i18n) - -## What is internationlization (i18n)? - -To over simplify the concept a bit, internalization (i18n for short) is the -process of making the platform more user-friendly in various languages for -people around the globe. This includes, but is certainly not limited to, things -like making the site available in different languages, changing currency values -to match your region, changing date formats, etc. - -## What do we currently support? - -We introduced some routing to lay the groundwork for a more comprehensive i18n -implementation. - -## What is the goal? - -We want everyone to feel included, regardless of where they're located or what -language(s) they speak. The goal is to make the platform available in various -languages. - -## How do you get involved? - -The following is a high level outline of an approach to internationalization. -This is by no means set in stone. - -We encourage you to open a pull request (PR) to this documentation or to -contribute to internationalization with your ideas - we're -[open-source](https://github.com/forem/forem/pulls)! - -## Routing - -We have logic for routes setup. You can visit a page and add `/locale/:locale` -to the beginning of the path. For example, if you visit the homepage, you can -add `/locale/fr-ca` for French, Canadian where `fr` is the language code and -`ca` is the region code. - -Setting up languages under this "sub-folder" approach helps with Search Engine -Optimization (SEO), routing, and more. - -_Currently, the various language routes will not do anything - it will stil show -the site in English (US)._ - -Once i18n is up and running, users will be able to select their preferred -language to view the platform in. These routes will be the location of various -languages. - -## Translating content - -There are many ways to translate static content on the platform. To start, we -can explore tools like [i18n-tasks](https://glebm.github.io/i18n-tasks/) which -also has an option to leverage Google Translate programmatically. We'll need to -create locale files (likely `.yml`) to house the translations. - -## Search Engine Optimization (SEO) - -It seems search engines, especially Google, don't particularly like content on a -page to be in multiple languages. To account for this on pages like articles, we -can try an approach using the canonical URL for the language the article was -written in. - -For example, if we detect an article is written in Spanish, we can set the -canonical URL for that article to be `/locale/es/username/article-slug`. We can -then hide comments that are not in the same language as the article/rest of the -page (Spanish in this example) only for the views the crawlers would see. That -way, when the search engine crawler hits an article written in Spanish, the -crawler will see the entire page in Spanish. We will not hide comments for the -views that real users see. - -## Caching - -The platform relies on edge caching, especially with regards to articles. To -account for this, we'll need to add logic at the edge that understands what -languages the platform currently supports and where to look up the language -variant in the cache. - -If the edge doesn't pick up on a user selected preference (possibly sent as an -additional header or cookie), the edge will look at the `Accept-Language` header -and normalize it. The header can include more specific preferences and look -something like: `Accept-Language: fr-ca, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5`. -There are 2 things going on here. 1) A user can specify country/region variants -for a language - `fr-ca` (French - Canada) and `fr-fr` (French - France). For -simplicity's sake, we want to normalize that sort of preference to `fr` to -start. 2) A user can specify priority using the q argument. We'll want to -interpret the user's priority preferences to match their highest priority -language with one we currently support. - -Once the edge is aware of what language it should be looking for, it will set -the cache key accordingly. - -We also make use of fragment caching in several places. We need to update the -keys for those caches to account for `locale` so we're not mistakenly serving a -cached fragment in a different language than intended. - -## Additional considerations - -- _Translating URLs_. For the best SEO result, we should also translate URLs - themselves into various languages. Something like the `/about` page could be - translated, for example. For now, we aren't going to account for this. -- _Translating dynamic/user generated content_. For now, we plan to _not_ - automatically translate any dynamic/user generated content (articles, - comments, listings, etc.). In the future we could explore what that looks - like, how a user can opt-in/out of that, etc. - -## Styles, design, and UI - -We'll want to expand some design aspects to support other languages that may be -right-to-left, have different spacings, have special characters, etc. - -## Next steps - -A few next steps we can take on the road to internationalization. - -- Update our logic to allow special characters/encodings in URLs. Currently, we - generate slugs on dynamic content like articles and tags that may include - characters that make the URL - invalid.[Here](https://github.com/forem/forem/issues/10116) is a good example. - We want to update this logic so these characters work in URLs as expected. -- Allow Forem Admins to set a "default language". Currently, if a user doesn't - select a language preference, it defaults to English ("en"). -- Clean up some code. There are some places we're hard-coding strings on the - frontend. We'll want to explore moving that sort data to the backend to unify - where and how we're translating. -- Translate areas of the site into English (US) first to ensure things are still - working. In other words, have the platform adhere to the default locale - instead of hard-coded strings. -- Start translating! - -## Resources - -- [Rails Guides - Rails Internationalization (I18n)](https://guides.rubyonrails.org/i18n.html) -- [i18n-tasks](https://glebm.github.io/i18n-tasks/) -- [Google: Managing multi-regional and multilingual sites](https://support.google.com/webmasters/answer/182192) -- [forem.dev post: What internationalization features should we support?](https://forem.dev/vaidehijoshi/what-internationalization-features-should-we-support-4kl) diff --git a/docs/backend/metrics.md b/docs/backend/metrics.md deleted file mode 100644 index 1af7c6292..000000000 --- a/docs/backend/metrics.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Metrics ---- - -## Time series data - -We track point-in-time data by sending data points to Datadog using -[Statdsd](https://github.com/DataDog/dogstatsd-ruby). - -Currently, we run a daily metric fetching job in `fetch.rake` which is called -via the Heroku scheduler. If we wanted to do other frequencies like hourly, etc. -we could add similar tasks. - -The rake task calls `Metrics::RecordDailyUsageWorker.perform_async`, which -performs algorithms to come up with data points to send, for example: - -```ruby -DataDogStatsClient.count("users.active_days_past_week", one_day_users, tags: { resource: "users", group: "new_users, day_count: 1 }) -``` - -If you want to create a new periodic data send, follow this pattern to do so. - -## Vendor-Agnostic - -While we currently are not vendor-agnostic in how we do this (Heroku/Datadog), -it is set up in a way that could become so in the future. The main pattern is -`Every x minutes/hours/etc. send aggregate data to warehouse where it can be examined on a timeseries basis`. -This could, in the future, be bundled right into the platform using an open -source timeseries database and data visualization. - -Once in Datadog, dashboards can created using - -![Datadog metrics](https://dev-to-uploads.s3.amazonaws.com/i/98rju6kzxeosf6m0jfhy.png) diff --git a/docs/backend/notification.md b/docs/backend/notification.md deleted file mode 100644 index 21352a8bb..000000000 --- a/docs/backend/notification.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Notifications ---- - -# Notifications - -Since notifications are run asynchronously, we'll want to make sure jobs are -running: `bundle exec sidekiq`. If that's not running, you won't receive any -notifications. You might need to create another account to pass notifications -back and forth if you're doing this all through the UI. - -Otherwise, you can generate notifications from the Rails console and run the -class methods from `app/models/notification.rb`. For example: - -```ruby -# follow notification -me = User.last -follow = User.first.follow(me) -Notification.send_new_follower_notification_without_delay(follow) -# reaction notification -rxn = Reaction.create( -user_id: 1, -category: "like", -reactable: me.articles.last, # this assumes you have an article written -) -Notification.send_reaction_notification_without_delay(rxn, me) -``` - -Notice you have to run these methods `without_delay` since this is assuming jobs -are not running. diff --git a/docs/backend/push-notifications.md b/docs/backend/push-notifications.md deleted file mode 100644 index 48e014efe..000000000 --- a/docs/backend/push-notifications.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Push Notifications ---- - -# Push Notifications Delivery - -Forem instances rely on [Rpush](https://github.com/rpush/rpush) to deliver push -notifications. This decision was heavily influenced by the desire to provide as -much flexibility as possible to Creators. In order to do this, Forem instances -can register and configure a `ConsumerApp`. - -These consumer apps represent mobile applications that users use to browse and -consume content on a Forem. Authenticated users of a specific Forem instance can -register a `Device` associated to a `ConsumerApp`. With these pieces we are able -to deliver push notifications to users devices. - -The `ConsumerApp` configuration page can be found at -`/admin/apps/consumer_apps`. The official Forem apps are supported by default -and require their secret credential to be provided via ENV variable. - -## Rpush Implementation - -We use Rpush's `rpush-redis` implementation (read -[this thread](https://github.com/forem/forem/pull/12419/files#r564660917) for -the reasons why), hence all `Rpush` models are persisted in Redis. More details -about how this works [here](https://github.com/rpush/rpush/wiki/Using-Redis). diff --git a/docs/backend/pusher.md b/docs/backend/pusher.md deleted file mode 100644 index 4b066f96e..000000000 --- a/docs/backend/pusher.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Pusher ---- - -# Pusher for Realtime Notifications - -Pusher is a third party service being used to power the -[chat system](https://dev.to/connect) and Push Notifications on -[iOS](https://apps.apple.com/us/app/dev-community/id1439094790) & -[Android](https://play.google.com/store/apps/details?id=to.dev.dev_android) -native apps. - -## Chat System - -In order to use the chat functionality within your development environment, you -will need to sign up for a free-tier Pusher account and retrieve its keys. Then -you'll need to provide those keys to the Rails application. - -1. [Sign up](https://dashboard.pusher.com/accounts/sign_up) or - [sign in](https://dashboard.pusher.com/) to your Pusher account. - -2. Once signed in, fill in the prompt to create a new Pusher Channels app. - - ![pusher-1](https://user-images.githubusercontent.com/22895284/51086056-058e4100-1742-11e9-8dca-de3e47e2bc73.png) - -3. In your new Pusher Channels app, click the "App Keys" tab. - - ![pusher-2](https://user-images.githubusercontent.com/22895284/51086057-058e4100-1742-11e9-9fb7-397187aa8689.png) - -4. Change your keys accordingly (name of Pusher key -> name of our application - key): - - ```text - app_id -> PUSHER_APP_ID - key -> PUSHER_KEY - secret -> PUSHER_SECRET - cluster -> PUSHER_CLUSTER - ``` - - ![pusher-3](https://user-images.githubusercontent.com/22895284/51086058-0626d780-1742-11e9-9c2a-26b9b10fa77f.png) - -5. Done. diff --git a/docs/backend/readme.md b/docs/backend/readme.md deleted file mode 100644 index d09a2e2d7..000000000 --- a/docs/backend/readme.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Backend Guide -items: - - audit-log.md - - authentication.md - - auth-apple.md - - auth-facebook.md - - auth-twitter.md - - auth-github.md - - authorization.md - - configuration.md - - data-update-scripts.md - - emails.md - - fastly.md - - internationalization.md - - roles.md - - pusher.md - - resource-admin.md - - notification.md - - scheduled-jobs.md - - metrics.md - - push-notifications.md - - tracking.md - - service-objects.md ---- - -# Backend Guide diff --git a/docs/backend/roles.md b/docs/backend/roles.md deleted file mode 100644 index ba483e874..000000000 --- a/docs/backend/roles.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: Roles ---- - -# Roles - -## What is a role? - -If authorization is about who has permission to be allowed to do what you want -to do, then Roles are common patterns of authorization across users - reducing -the administrative overhead. - -## Why do I need to know about roles? - -Some bugs can only be seen for users with specific roles. You will need to -change the role to reproduce a problem. - -## How do we implement roles in Forem? - -Roles are implemented in this application using [Rolify][1]. The list of roles -can be found in [app/models/role.rb][2] and you can search for [has_role in the -codebase][3] to find which pages need which roles. - -A new user starts without any roles, and there is no administrative way of -adding roles to users yet. To assign a user a role you will have to run commands -at the console. - -## Example of adding permissions to a user - -- open the Rails console - -```shell -rails console -``` - -- after verifying the user `test_user_name` is missing the `trusted` role we - proceed to add it and then verify the role has been added: - -```ruby -> user = User.find_by(username: "test_user_name") -> user.has_role?(:trusted) -=> false - -> user.add_role(:trusted) -=> # - -> user.has_role?(:trusted) -=> true -``` - -Another common requirement is changing to the administrative role, and an -example of this is found [on the admin page][5]. - -## Verification - -A more complex query to list all the users and their roles: - -```ruby -User.joins(:roles).order(:id).group(:id).pluck(:id, :username, Arel.sql("array_agg(roles.name)")) -``` - -## Further Reading - -1. [Rolify README.md][1] -2. [What is the purpose of Rolify?][4] -3. [Admin][5] - -[1]: https://github.com/RolifyCommunity/rolify -[2]: https://github.com/forem/forem/blob/main/app/models/role.rb -[3]: https://github.com/forem/forem/search?q=has_role&unscoped_q=has_role -[4]: https://stackoverflow.com/a/16096790/1511504 -[5]: /backend/resource-admin diff --git a/docs/backend/scheduled-jobs.md b/docs/backend/scheduled-jobs.md deleted file mode 100644 index e92c2b163..000000000 --- a/docs/backend/scheduled-jobs.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Scheduled Jobs ---- - -# Scheduled Jobs - -As in the [Technical Overview](/technical-overview), We use -[Heroku Scheduler](https://devcenter.heroku.com/articles/scheduler) for -scheduled jobs. As the name suggests, this is for regularly recurring tasks that -need to be run every day, week, month, year, decade, and century. - -Tasks are implemented in `forem/lib/tasks/fetch.rake`, typically in the form of: - -``` -task some_unique_task_name:, [optional_arg] => :environment do |optional_arg| - ... do your thing here ... -end -``` - -You can explore the -[official Heroku documentation](https://devcenter.heroku.com/articles/scheduler#defining-tasks) -for defining tasks and read through tasks we have implemented for busting cache, -awarding badges, and more. - -In your Pull Request, communicate with a Forem Core Team Member to discuss at -what frequency and ensure your task is scheduled on Heroku once your code is -reviewed, approved, and merged. diff --git a/docs/backend/service-objects.md b/docs/backend/service-objects.md deleted file mode 100644 index e71bef3ce..000000000 --- a/docs/backend/service-objects.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Service Objects ---- - -## What are Service Objects - -Service objects are Plain Old Ruby Objects (POROs) which encapsulate a whole -business process/user interaction. - -Our services are located in `app/services` with the corresponding specs in -`spec/services`. Their main interface is a class level method named `call`, as -in the following example: - -```ruby -class ImportUsers - def self.call(arg1) - new(arg1).call - end - - def initialize(arg1) - @arg1 = arg1 - end - - def call - # import code goes here - end -end -``` - -To distinguish services from models we often give them verb names vs noun names, -e.g. `ImportUsers` instead of `UserImporter`. - -## Generating Service Objects - -To make our services more consistent we use a custom Rails generator. Some usage -examples: - -**Generate a non-namespaced service without arguments** - -`$ rails generate service DoTheThing` - -```ruby -# app/services/do_the_thing.rb -class DoTheThing - def self.call - new.call - end - - def call - end -end -``` - -```ruby -# spec/services/do_the_thing_spec.rb -require "rails_helper" - -RSpec.describe DoTheThing, type: :service do - pending "add some examples to (or delete) #{__FILE__}" -end -``` - -**Generate a non-namespaced service with arguments:** - -`$ rails generate service DoTheThing arg1 arg2` - -```ruby -# app/services/do_the_thing.rb -class DoTheThing - def self.call(arg1, arg2) - new(arg1, arg2).call - end - - def initialize(arg1, arg2) - @arg1 = arg1 - @arg2 = arg2 - end - - def call - end -end -``` - -The generated spec is the same as above. - -**Generate a namespaced service with arguments** - -`$ rails generate service things/dothem arg1 arg2` - -```ruby -# app/services/things/do_them.rb -class Things::DoThem - def self.call(arg1, arg2) - new(arg1, arg2).call - end - - def initialize(arg1, arg2) - @arg1 = arg1 - @arg2 = arg2 - end - - def call - end -end -``` - -```ruby -# spec/services/things/do_them_spec.rb -require "rails_helper" - -RSpec.describe Things::DoThem, type: :service do - pending "add some examples to (or delete) #{__FILE__}" -end -``` diff --git a/docs/backend/tracking.md b/docs/backend/tracking.md deleted file mode 100644 index 9c5a5a03d..000000000 --- a/docs/backend/tracking.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Tracking ---- - -## Visits & Events - -For first-party analytics, we use the -[`ahoy_matey` gem](https://github.com/ankane/ahoy), which tracks visits and -events. - -We intentionally choose to limit what user data we track and persist, and have -opted to follow the GDPR compliance standards -[set by Ahoy](https://github.com/ankane/ahoy#gdpr-compliance-1). By default, we -have configured the Ahoy library to mask IP addresses, disable geocode tracking, -and not track user cookies. - -### Visits - -Ahoy creates an `Ahoy::Visit` record for each visit that it tracks. - -By default, we have turned off visit tracking in the `ApplicationController`: - -```ruby -skip_before_action :track_ahoy_visit -``` - -We currently only create visits on the server-side when they are required to be -created by events. Visits can be re-enabled for specific controller actions if -necessary, but this should be done so _with explict care_. - -We do not collect any personal user data when tracking visits. Our collected -data is limited to the user's `id`. Each user has a unique `visitor_token`, -while each visit to the site is marked with a unique `visit_token`. - -### Events - -Ahoy creates an `Ahoy::Event` record for each event that it tracks. If no visit -is recorded for a user when an event is tracked, Ahoy will simultaneously create -an `Ahoy::Visit` for the event being tracked. - -Events can be tracked in a controller action on the backend, or with JavaScript -on the frontend. Learn more about tracking events with JavaScript in our -[frontend tracking guide](/frontend/tracking). - -When an event is tracked, it should include a `name` and a `properties` hash. -When adding new events, be sure that the name is unique per-event. The -properties will help you differentiate between events. - -In order to track a specific event in a controller, use the `ahoy.track` call: - -```ruby -class YourController < ApplicationController - after_action :track_my_action - - protected - - def track_my_action - ahoy.track "A specific description of your event", request.path_parameters - end -end -``` - -Event tracking can be enabled for specific controller actions, but should be -done so _with explict care_. - -## Messages - -For email analytics, we use the -[`ahoy_messages` gem](https://github.com/ankane/ahoy_email), which tracks a -history of email messages sent to users. - -Ahoy creates an `Ahoy::Message` record for each email sent by default, but can -be disabled on a per-mailer basis. diff --git a/docs/contributing/api.md b/docs/contributing/api.md deleted file mode 100644 index 28104cb48..000000000 --- a/docs/contributing/api.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Contributing to the API Specification Docs ---- - -# Contributing to API specification docs - -The API v0 is described with the -[OpenAPI 3 specification](https://spec.openapis.org/oas/v3.0.3). - -Swagger.io has -[great docs](https://swagger.io/docs/specification/basic-structure/) that are -helpful to understand the specification better. - -## Where you can find the spec file - -We auto-generate the documentation from `api_v0.yml` within the `/docs` -directory. We use [ReDoc](https://github.com/Redocly/redoc) to turn the OpenAPI -3 format into a readable and searchable HTML documentation. - -## Updating API docs - -Whenever you make changes to the API docs, make sure to bump the version at the -top of `api_v0.yml`, in `info.version`. - -## Running and editing the docs locally - -If you want to browse the documentation locally you can use: - -```shell -yarn api-docs:serve -``` - -This will let you browse the auto-generated version of the doc locally, and it -will reload the documentation after every change of the specification file. - -## Linting and validation - -We use [spectral](https://github.com/stoplightio/spectral) and -[ibm-openapi-validator](https://github.com/IBM/openapi-validator) to validate -the spec file. The validation is performed as a `pre-commit` hook. - -You can also manually validate the document, running: - -```shell -yarn api-docs:lint -``` - -If you have Visual Studio Code, we suggest you install the following extensions -that enable validation and navigation within the spec file: - -- [OpenAPI (Swagger) editor](https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi) -- [openapi-designer live preview](https://marketplace.visualstudio.com/items?itemName=philosowaffle.openapi-designer) diff --git a/docs/contributing/docs.md b/docs/contributing/docs.md deleted file mode 100644 index e855b9ec9..000000000 --- a/docs/contributing/docs.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Contributing to the Docs ---- - -# Contributing to Forem's developer documentation - -Contributions to the documentation are always appreciated! Thank you for making -an effort to improve the developer experience of contributing to the DEV -project. - -# Running the documentation locally - -Like Forem, this site is open source and the code is [hosted on GitHub][docs]. -If you find any incorrect information, or a even a typo, we'd love to see a pull -request. Follow these steps to get the documentation site running locally. - -Forem's documentation is built with [GitDocs NodeJS library][gitdocs]. - -Once installed, you should run `yarn gitdocs serve` from the root of the `forem` -project or from the `/docs` directory. - -```shell -yarn gitdocs serve -``` - -This will start a server where you can browse the documentation: - - -If you add new pages or rename existing pages, you'll need to restart the server -for those changes to take effect. - -Since our documentation is built on GitDocs, which is built on Netlify, you can -use the generated deploy preview link to check out your documentation changes. -Once you make a PR, click on "Show all checks" and find the "deploy/netlify" -row. If your deploy preview is ready, you can click on "Details" to see the -preview. Please note that the deploy preview only reflects any documentation -changes you make (and not any changes elsewhere in the app). - -# Useful links - -The docs are a collection of [Markdown files][markdown] that also utilize -[FrontMatter][frontmatter]. - -For more information on how to use GitDocs read the [GitDocs -guide][gitdocs_guide]. - -# Regarding language & style - -We ask that you avoid trivializing terms when contributing to documentation. -This includes words like "just", "simply", "easy", "obvious", and -"straightforward". You can learn more about why we want to avoid this kind of -language in [this blog post](https://jessitron.com/2020/06/26/just-dont). - -Generally speaking, the documentation hosted on this site is informal. There is -no need to make things more complicated by writing these articles like a -textbooks. - -However, it's expected that contributions to these documents are reasonably -structured and mostly free of spelling and grammar errors. For this reason, if -you submit a PR you might be asked to make changes before your PR is merged. - -Prettier is used to autowrap lines in these files to 80 characters. Using 80 -characters per line allows us to retain a more specific git history over time. -If lines are not wrapped, changing a comma in a paragraph would attribute the -entire paragraph to one commit. By line wrapping we are helping git to correctly -attribute smaller changes to their commits. This keeps information from getting -lost over time. - -For more information on effective technical writing, check out -[writethedocs.org][writethedocs]. - -[docs]: https://github.com/forem/forem/tree/main/docs/ -[gitdocs]: https://www.npmjs.com/package/gitdocs/ -[markdown]: https://en.wikipedia.org/wiki/Markdown -[frontmatter]: https://jekyllrb.com/docs/front-matter/ -[gitdocs_guide]: https://gitdocs.netlify.com/ -[writethedocs]: https://www.writethedocs.org/guide/ diff --git a/docs/contributing/forem.md b/docs/contributing/forem.md deleted file mode 100644 index 470747a54..000000000 --- a/docs/contributing/forem.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: Contributing to Forem ---- - -# Contributing to Forem - -We expect contributors to abide by our underlying -[Code of Conduct](https://dev.to/code-of-conduct). All discussions about this -project must be respectful and harassment-free. - -Remember that communication is the lifeblood of any Open Source project. We are -all working on this together, and we are all benefiting from this software. - -It's very easy to misunderstand one another in asynchronous, text-based -conversations. When in doubt, assume everyone has the best intentions. - -If you feel anyone has violated our Code of Conduct, you should anonymously -contact the team with our [abuse report form](https://dev.to/report-abuse). - -### Where to contribute - -All [issues](https://github.com/forem/forem/issues) labeled -[ready for dev](https://github.com/forem/forem/issues?q=is%3Aissue+is%3Aopen+label%3A%22ready+for+dev%22) -and -[bug](https://github.com/forem/forem/issues?q=is%3Aissue+is%3Aopen+label%3A%22type%3A+bug%22+label%3Abug) -are up for grabs. Please note that issues with the -[Forem team](https://github.com/forem/forem/labels/Forem%20team) label are -internal tasks that will be completed by a Forem -[core team member](https://github.com/forem/forem/#core-team). - -- [good first issue](https://github.com/forem/forem/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22+) - issues are meant for newer developers. -- [difficulty: easy](https://github.com/forem/forem/issues?q=is%3Aopen+is%3Aissue+label%3A%22difficulty%3A+easy%22) - issues are usually confined to isolated areas of existing code. -- [difficulty: medium](https://github.com/forem/forem/issues?q=is%3Aopen+is%3Aissue+label%3A%22difficulty%3A+medium%22) - issues sometimes entail new features and might affect a significant area of - the codebase, but aren't overly complex. -- [difficulty: hard](https://github.com/forem/forem/issues?q=is%3Aopen+is%3Aissue+label%3A%22difficulty%3A+hard%22) - issues are typically far-reaching, and might need architecture decisions - during implementation. This label might also denote highly complex issues. - -PRs without an associated issue may still be merged, but the core team will -focus on changes that solve existing issues. We strongly encourage creating an -issue before working on a PR! - -When in doubt, ask a -[core team member](https://github.com/forem/forem/#core-team) by mentioning us -on the issue. - -**Documentation** is almost always a great place to start contributing to a new -project. Forem is an Open Source, community-driven project. Therefore, providing -and maintaining quality documentation is one of our most important jobs. You can -find more information in our -[docs guide](https://docs.forem.com/contributing/docs)! - -**Refactoring**, which involves improving the code without modifying behavior, -is a great place to help out! Generally speaking, you can rely on existing tests -to ensure that your refactor doesn't introduce any unexpected behavior. If an -area isn't well tested, you might be asked to include a regression test with -your refactoring PR. Refactors can touch many files, so we encourage breaking -big changes into small PRs. - -**Fixing bugs** is a super fast way to improve the experience for our users! -When you're fixing bugs, we appreciate communication in a GitHub issue. If an -issue exists, please claim that issue and link it in your PR, otherwise creating -an issue is the best first step! Be sure to surround bug fixes with ample tests; -bugs are magnets for other bugs. Write tests around bugs! - -**Features** tend to be subjective and might spur some debate. The Forem core -team uses an internal RFC ("request for comments") process to assess and -prioritize new features. This process is intended to provide a consistent and -standardized path for new changes to enter the Forem ecosystem. If you'd like to -propose a new feature, please visit [forem.dev](https://forem.dev) to start a -discussion around a new feature (or chime in on a pre-existing discussion!). - -There may be some open issues in our repository that we think evolve into -impactful features. For such issues, we use the -[potential RFC](https://github.com/forem/forem/labels/potential%20RFC) label in -order to highlight the potential feature to the Forem core team members so that -someone from the team can champion that feature. - -You can learn more about our internal RFC process and how we use forem.dev -[here](https://forem.dev/foremteam/internal-rfc-process-and-forem-dev-discussions-3gl4) - -### How to contribute - -1. [Fork the project](https://docs.forem.com/getting-started/forking/) and clone - it to your local machine. Follow the - [installation guide](https://docs.forem.com/installation/)! -2. Create a branch with your GitHub username and the ID of the - [issue](https://github.com/forem/forem/issues), for example: - `git checkout -b USERNAME/some-new-feature-1234` -3. Code and commit your changes. Bonus points if you write a - [good commit message](https://chris.beams.io/posts/git-commit/): - `git commit -m 'Add some feature'` -4. Push to the branch: `git push -u origin USERNAME/some-new-feature-1234` -5. [Create a pull request](https://docs.forem.com/getting-started/pull-request/) - for your branch. 🎉 - -## Contribution guidelines - -### Create an issue - -Nobody's perfect. Something doesn't work? Something could be better? Check to -see if the issue already exists, and if it does, leave a comment to get our -attention! If the issue doesn't already exist, feel free to create a new one. A -core team member will triage incoming issues. - -_Please note: core team members may update the title of an issue to reflect the -discussion._ - -### Please include tests - -Some areas of the project could use updated tests, and new features should -always include test coverage. Please give our -[testing guide](https://docs.forem.com/tests/) a read! - -### Code quality - -We use [Code Climate](https://codeclimate.com/) to find code smells. If a pull -request contains code smells, we might recommend a refactor before merging. We -like readable code, and encourage DRY when it's reasonable! - -More importantly, we avoid -[wrong abstractions](https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction). -Code quality tools are not perfect, so don't obsess over your Code Climate -score. - -### Consider accessibility in UI changes - -If the change you're proposing touches a user interface, include accessibility -in your approach. This includes things like color contrast, keyboard -accessibility, screen reader labels, and other common requirements. For more -information, check out the -[Forem Accessibility docs page](https://docs.forem.com/frontend/accessibility). - -### Please use inclusive language - -Inclusion and respect are core tenets of our -[Code of Conduct](https://dev.to/code-of-conduct). We expect thoughtful language -all the way down to the code. Some technical metaphors are alienating or -triggering. We ask that contributors go the extra mile to submit code which is -inclusive in nature. - -If you unintentionally use language deemed harmful, there is no shame. We will -work together to find a better alternative. Being thoughtful about language also -encourages more thoughtful code! - -### Create a pull request - -- Try to keep the pull requests small. A pull request should try its very best - to address only a single concern. -- For work in progress pull requests, please use the - [Draft PR](https://github.blog/2019-02-14-introducing-draft-pull-requests/) - feature. -- Make sure all tests pass and add additional tests for the code you submit. - [More info here](https://docs.forem.com/tests/). -- Document your reasoning behind the changes. Explain why you wrote the code in - the way you did. The code should explain what it does. -- If there's an existing issue, reference to it by adding something like - `References/Closes/Fixes/Resolves #123`, where 123 is the issue number. - [More info here](https://github.com/blog/1506-closing-issues-via-pull-requests). -- Please fill out the PR Template when making a PR. -- All commits in a pull request will be squashed when merged. - -_Please note: a core team member may close your PR if it has gone stale or if we -don't plan to merge the code._ - -### Pull request reviews - -All community pull requests are reviewed by our core team. - -- All contributors must sign the CLA. -- All required checks are expected to pass on each PR. - - In the case of flaky or unrelated test failures, a core team member will - restart CI. -- We require 2 approvals from core team members for each PR. -- Requested Changes must be resolved (with code or discussion) before merging. -- If you make changes to a PR, be sure to re-request a review. -- Style discussions are generally discouraged in PR reviews; make a PR to the - linter configurations instead. -- Your code will be deployed shortly after it is merged. - -### A note on "force pushing" - -After you submit your pull request, one of the members of the core team will -review your code. - -Please avoid force pushing unless you need to rebase with the main branch. - -If feedback is provided, any changes should be contained in new commits. Please -don't force push or worry about squashing your commits. - -Force pushing (despite being useful) has some drawbacks. GitHub doesn't always -keep the review history, which results in lost context for the reviewers. - -We squash every PR before merging, so there is no need to force push! - -## The bottom line - -We are all humans trying to work together to improve the community. Always be -kind and appreciate the need for tradeoffs. ❤️ diff --git a/docs/contributing/readme.md b/docs/contributing/readme.md deleted file mode 100644 index 9397e6c43..000000000 --- a/docs/contributing/readme.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Contributing Guide -items: - - docs.md - - forem.md - - api.md ---- - -# Contributing Guide diff --git a/docs/creators/configure-forem.md b/docs/creators/configure-forem.md deleted file mode 100644 index 53060fb2c..000000000 --- a/docs/creators/configure-forem.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Configuring Forem ---- - -# Basic Configuration Guide for Forem - -## Overview - -As a Forem admin, one of the first steps of managing your site will be to tailor -your content, branding and other important details based on your community -goals. This is made simple by the configuration page which can be found at -https://your.forem.url/admin/customization/config. - -_We advise that you first complete the minimum set up before sending out your -Forem link to your community._ - -## Complete your Set Up, Configure your Forem - -Once your Forem instance is set up for the first time, you will most likely see -the following banner: - -![Banner prompting for configuring mandatory settings](https://dev-to-uploads.s3.amazonaws.com/i/2nosvfr7l47ymipmyh4o.png) - -This banner indicates that the Forem configuration process hasn't been completed -yet. - -When you click on the link on banner, it will take you to the configuration page -(i.e. https://your.forem.url/admin/customization/config). - -On this page you will see that the Get Started section is expanded. It contains -all the mandatory fields that need to be filled out in order for the site to be -in a usable state. Once it is filled out and submitted, the banner will then -disappear. - -## Access and Permissions - -The following permissions are required to be able to view and/or edit the config -page: - -#### `Role: super_admin` - -When providing this role to a user they will be able to access the config page. -However, this page will be a read only view for them. They will see the -following: - -![Super Admin Permissions Role Provided](https://dev-to-uploads.s3.amazonaws.com/i/xpc8g9x46vzgi49ohc0d.png) - -#### `Role: single_resource_admin` - -When providing this role to a user they will be able to access the config page, -and they will be able to edit the config variables. - -![Super Resource Admin Role Provided](https://dev-to-uploads.s3.amazonaws.com/i/z5v2ou64imgqonmefolk.png) - -The first admin of your Forem will be given the highest permissions. Thereafter, -they can provide the necessary permissions to subsequent users via the -https://your.forem.url/admin/permissions. - -## The Configuration Sections - -Currently, the configuration page is split into 3 sections. They are as follows: - -- A **Get Started section** that contains all required fields. These are the - fields that are required to be filled out, in order to get your Forem in a - usable state. -- An **All Settings section** that contains all the possible variables that you - can configure on the site. This section is broken down into sub sections, - whereby each subsection will contain a description of what it does, and then - list the fields that are available for configuration. Each field will also - contain a concise description of what it is used for. -- An **Environment Variables section** that provides a read-only view of the - environment variables that are available to be set on the server. If your - instance is hosted by Forem, please get in touch with customer support to - change any of these variables. - -![The Settings Sections](https://user-images.githubusercontent.com/47985/116500126-13970a00-a8d8-11eb-824e-ace66e6e05d4.png) - -All required fields are marked as such. In addition, you will notice that we -have set some defaults for certain fields, you may amend them as you see -relevant for your Forem. - -## Updating your configurations - -In order to update any of the variables within the Get Started and All Settings -sections, you will set the new value and then navigate to the end of the section -where you will verify that you would like to make the change by typing the -following sentence: - -``` -My username is and this action is 100% safe and appropriate. -``` - -You will now see your updated values and the changes on your site will be in -effect. - -![Submit your data](https://dev-to-uploads.s3.amazonaws.com/i/xo0nxykuu8kw984w088n.png) diff --git a/docs/creators/readme.md b/docs/creators/readme.md deleted file mode 100644 index 8e81498ea..000000000 --- a/docs/creators/readme.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Forem Creators Guide -items: - - configure-forem.md ---- - -# Forem Creators Guide - -This document contains basic instructions for new Forem creators. It's a work in-progress, but will provide Forem Creators with a guide on how to best make use of the tools and features available to them. diff --git a/docs/design/branding.md b/docs/design/branding.md deleted file mode 100644 index 126705b15..000000000 --- a/docs/design/branding.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Branding Guidelines ---- - -# Branding Guidelines - -## Forem Theme - -Forem's design inspiration is meant to be a throwback. In personality and -design, it is ATARI inspired. Magazines like PAPER are also an inspiration in -terms of being a -[bold contrast with some more indy](https://www.google.com/search?biw=1440&bih=780&tbm=isch&sa=1&ei=KSN8W5WVLoy55gLI77TgBA&q=paper+magazine+cover&oq=paper+magazine+cover). - -We also think in terms of how people use the Forem brand for their own purposes. -Profiles are very much public-facing records of what people have put out into -the world. `dev.to/{username}` is your developer identity. - -Imagine a developer's face with the DEV heading above them. If we existed in the -80's, we would have been "DEV MAGAZINE," with the exact same branding. - -## Branding Rules - -- [Joystick](http://www.pixelsagas.com/?download=joystick) should be used for - logos, not for headlines/phrases. -- Black and white is our default logo, but the logo can be drawn in any color. -- Forem/DEV is "old school cool." -- We use bold shadows (no gradient) for boxes. -- We have a minimal approach to importing dependencies, so few if any custom - fonts on-site for that reason. -- Refer to the `variables.scss` - [file in our main repo](https://github.com/forem/forem/blob/main/app/assets/stylesheets/variables.scss) - to reference commonly-used colors and fonts. - -## Design License Info - -- We use the [Joystick](http://www.pixelsagas.com/?download=joystick) font by - Neale Davidson and [Pixel Sagas](http://www.pixelsagas.com/) for the DEV Logo. - We have a commercial license. -- We use [EmojiOne](https://www.emojione.com/) icons from JoyPixels. We have a - commercial license. diff --git a/docs/design/language.md b/docs/design/language.md deleted file mode 100644 index d78c1f4e1..000000000 --- a/docs/design/language.md +++ /dev/null @@ -1,41 +0,0 @@ -# Human Language - -Forem is built on concepts, and those concepts have names. Here are some language concepts to be aware of and some known "gotchas" where there may be multiple terms currently being used. - -This is an incomplete first take. It is also written down _so that it can be changed when needed._ No language concept is set in stone. And no concept is exclusively _english_. As we internationalize we need to evolve our notion of this, and it will remain important that we settle on unified terms so that we limit conceptual sprawl. - -# Post - -A main published unit on sites are officially called posts. The gotcha is that they are currently called `Article` in the codebase. This is because the original version of the site had much more the concept of the pure "article" but as the site has evolved and the purposes of Forem have evolved, we have diversified the use of a post idea. Just as a "tweet" could be used for different things: An announcement, a question, the start of a thread, etc. we also have a broad idea of what a post is "for", and all concepts are built off of this. - -# Comment - -A single comment is the unit of follow up dialog that lives underneath a post. Comments have some associated terminology. - - A Discussion is the collection of all comments under a post. Discussion is a word that implies a certain civility. - - A thread is a single line of comments and their reply comments within a full discussion. - - A comment within a thread may be thought of as a "reply" contextually, but it is still a comment. - -# Reaction - -The remotional responses to an article or comment, a click of a button to let the author know how one feels. The phrase "reaction" is used in the app, but should mostly be _implied_. Reactions are purposefully lightweight in nature. - -# Tag - -A tag is the main unit of organized content on a Forem. - -# User - -A signed up account is generically referred to as a "user", but contextually we've called them "members" or "people", there may be some need for unification here. - -# Listing - -The marketplace/classified-listing concept within a forem is called `/listings` and a single unit is a listing. Listings have categories for segmentation as well as tags, like posts do. - -# Connect - -Connect is the area of the site for synchronous conversation, closed group chat and/or video or audio conversation. It's generally not as site-wide or public, though they _can_ be public in some contexts. - -# Connect Channel - -A single unit of chat is called a "channel". - diff --git a/docs/design/readme.md b/docs/design/readme.md deleted file mode 100644 index 46c44423c..000000000 --- a/docs/design/readme.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Design Guide -items: - - branding.md - - language.md - - theming.md ---- - -# Design Guide diff --git a/docs/design/theming.md b/docs/design/theming.md deleted file mode 100644 index 7d00d5bfb..000000000 --- a/docs/design/theming.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Theming Guidelines ---- - -# Theming Guidelines - -Forem supports different themes, such as Default, Night, Pink. - -You can switch the theme at in the "Style -Customization" section. - -These themes are powered by -[CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties), -loaded at runtime by JavaScript via `layouts/_user_config.html.erb`. - -An example of how it works: - -```javascript -try { - const bodyClass = localStorage.getItem('config_body_class'); - - if (bodyClass) { - document.body.className = bodyClass; - - if (bodyClass.includes('night-theme')) { - document.getElementById('body-styles').innerHTML = ''; - } else if (bodyClass.includes('ten-x-hacker-theme')) { - document.getElementById('body-styles').innerHTML = '' - } else if (bodyClass.includes('pink-theme')) { - document.getElementById('body-styles').innerHTML = '' - } else if(bodyClass.includes('minimal-light-theme')) { - document.getElementById('body-styles').innerHTML = '' - } - ... -``` - -Within SCSS files located at `app/assets/stylesheets` you can use `var()` -statements, which will call these CSS custom properties. If a CSS custom -property is not defined `var()` will fall back on the second parameter provided, -which can be a SCSS variable defined in `app/assets/stylesheets/variables.scss`. - -An example of how to use `var()`: - -```scss -div { - color: var(--theme-color, $black); -} -``` - -Note that fallback values aren't used to fix the browser compatibility. If the -browser doesn't support CSS custom Properties, the fallback value won't help. To -prevent this issue on older browsers, we need to write our styles like this: - -```scss -div { - color: $black; - color: var(--theme-color, $black); -} -``` - -This can be too much work and browser fallback can be forgotten. For a better -developer experience, you should use the two mixins defined in -`app/assets/stylesheets/_mixins.scss` called `themeable` and -`themeable-important`. They take three arguments. The first argument is the CSS -property like `color` or `background`, the second argument is the CSS custom -property name (without `--`) like `theme-color`, and the third argument is the -CSS value, i.e., `$black` or `white`. - -Make sure to import the mixin in your SCSS file and use it like this: - -```scss -div { - @include themeable(color, theme-color, $black); -} -``` - -`themeable-important` is used when a CSS variable requires `!important` as a -postfix of the CSS property's value where the CSS variable is being used. You -can use it the same way you would use `themeable` mixin, but you should avoid -`!important` if possible. - -# Other user config - -In addition to themes, users can also directly configure their preferred fonts -and their nav bar preferences. The implementation of these is similar to themes. diff --git a/docs/faqs.md b/docs/faqs.md deleted file mode 100644 index 0815f6a57..000000000 --- a/docs/faqs.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: FAQs ---- - -# Frequently Asked Questions - -## How do I log in after starting up Forem for the first time? - -Seeding the database create an admin user (see -[Database](/getting-started/db/#default-admin-user)) with the following -credentials: - -``` -email: admin@forem.local -password: password -``` - -Once logged in as this admin user, you can turn on any authentication methods -you'd like (see [Authentication](/backend/authentication/)) - -## How do I build my local copy of the Ruby source code documentation? - -```shell -cd docs -make ruby-doc -``` - -Then open `.static/ruby-doc/index.html` in the `docs` directory and browse the -Ruby documentation - -## How do I enable logging to standard output in development? - -By default Rails logs to `log.development.log`. - -If, instead, you wish to log to `STDOUT` you can add the variable: - -```shell -export RAILS_LOG_TO_STDOUT=true -``` - -to your own `.env` file. - -## How do I see comments in the Feed? - -On the home Feed, we only show comments above certain "score". It's likely the -comments in the local environment will never meet this score. If you want to see -comments locally, you will need to update the score of your local comments -manually. Here's how: - -1. Open the terminal. -2. Run `rails dbconsole` to open the PostgreSQL terminal. Alternatively, run - `psql PracticalDeveloper_development` to open `psql`, the PostgreSQL - terminal. -3. Enter `update comments set score = 30;`. -4. Type `exit` to leave the PostgreSQL terminal. - -> Note: dbconsole reads database information from config/database.yml which is -> always better since database configs might change in the future. - -Once you refresh the app, you should be able to see some comments in the Feed. - -## How do I make someone follow me on my local environment? - -In certain cases, for example when testing various functionalities, you may need -to be able to make some user follow you. Here's how: - -1. Open the rails console by running `rails c` in your terminal. -2. Get any user you want to follow you, for example `user = User.first`. -3. Then make this user follow you: `user.follow(your_username)`. - -Boom, you have a new follower! - -## How do I remove / leave organization I created? - -1. Open the rails console by running `rails c` in your terminal. -2. Enter the following commands: - ```ruby - user = User.find_by(username: "your_username") - organization_id = Organization.find_by(slug: "organization_slug").id - user.organization_memberships.where(organization_id: organization_id).destroy_all - ``` - -## How do I add credits to my account? - -If you ever want to add Listings locally, you must have credits on your account -to "pay" for listing. Here's how: - -1. Open the rails console `rails console`. -2. Enter the following commands: - - ```ruby - user = User.find_by(username: "your_username") - Credit.add_to(user, 1000) - ``` - -^ This will add 1000 credits to your account. But you know, you can't really buy -anything with it :D diff --git a/docs/frontend/accessibility.md b/docs/frontend/accessibility.md deleted file mode 100644 index 389eb76f1..000000000 --- a/docs/frontend/accessibility.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Accessibility ---- - -# Accessibility - -To make Forem the most inclusive community platform around, accessibility should -be considered to enable people with disabilities to create and consume content. - -## The Basics - -Forem UI changes should consider accessibility wherever possible. Common issues -to watch out for in frontend code: - -- [Adequate color contrast](https://webaim.org/articles/contrast/evaluating) -- [Semantic structure and headings](https://webaim.org/techniques/semanticstructure/) -- [Alternative text for images](https://webaim.org/techniques/alttext/) -- [Unique button and link text](https://webaim.org/techniques/hypertext/link_text) -- [Accessible forms with labels](https://webaim.org/techniques/forms/) -- [Visible keyboard focus styles](https://www.washington.edu/accessibility/checklist/focus/) - -## More Advanced Things - -If you're working on something JavaScript-heavy or animated, there are a few -additional considerations for accessibility: - -- [Forem Accessibility Tests](https://docs.forem.com/tests/accessibility-tests/) -- [Intro to ARIA](https://webaim.org/techniques/aria/) -- [Handle focus for client-side interactions](https://dev.to/robdodson/managing-focus-64l) -- [Reducing motion with CSS media queries](https://css-tricks.com/introduction-reduced-motion-media-query/) -- [Linting with eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y) -- [Testing with Jest-axe](https://dev.to/bdougieyo/accessibility-testing-in-react-with-jest-axe-l7k) - -## Accessibility Testing - -See a list of testing steps to follow during development or for a Pull Request -review on the -[Forem Accessibility Testing Docs](https://docs.forem.com/tests/accessibility-tests/). - -## Resources - -There's a wealth of information out there to learn about digital accessibility! -Here are some resources: - -- [W3C's Web Accessibility Initiative](https://www.w3.org/WAI/) -- [Web Content Accessibility Guidelines](https://www.w3.org/TR/WCAG21/) -- [ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.1/) -- [WebAIM](http://webaim.org/) -- [A11y Project](https://a11yproject.com) -- [Deque University](https://dequeuniversity.com/) -- [React Accessibility Docs](https://reactjs.org/docs/accessibility.html) (most - will apply to Preact) -- [The Importance of Manual Accessibility Testing](https://www.smashingmagazine.com/2018/09/importance-manual-accessibility-testing/) -- [Accessibility Insights extension](https://accessibilityinsights.com) diff --git a/docs/frontend/debugging.md b/docs/frontend/debugging.md deleted file mode 100644 index 4a325f42c..000000000 --- a/docs/frontend/debugging.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Debugging ---- - -# Debugging - -## In Browser - -Browsers ship with their own developer tools. These are amazing tools to help -you debug your web application. Consider learning how to use them. - -- [Chrome Developer Tools](https://developers.google.com/web/tools/chrome-devtools) -- [Firefox Developer Tools](https://developer.mozilla.org/en-US/docs/Tools) -- [Safari Developer Tools](https://support.apple.com/en-ca/guide/safari/sfri20948/mac) - -## Visual Studio Code - -[Visual Studio Code](https://code.visualstudio.com) (VS Code) is a popular -editor that allows you to debug many languages including JavaScript. Thanks to -remote debugging technologies, we can debug our frontend code in VS Code. When -you clone the Forem repository and open the project in VS Code, you will be -prompted to install recommended extensions which include the -[Chrome Debugger](https://code.visualstudio.com/blogs/2016/02/23/introducing-chrome-debugger-for-vs-code) -and the -[Edge Debugger](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-edge). - -Setup: - -- Refer to the respective debugger extension documentation above to ensure that - your browser is running with remote debugging enabled. -- Once you have your local installation of Forem running, you can attach to - either the Chrome or Edge Debugger. - - ![Launch menu for debugger in VS Code](/vscode_launch_debugger.png 'Launch -menu for debugger in VS Code') - -- From there you can do all the usual stuff that you would do while debugging - JavaScript in the browser: setting breakpoints, setting - [logpoints](https://code.visualstudio.com/docs/editor/debugging#_logpoints), - watches etc. - -## Where is My Editor Debug Configuration? - -If you do not see your editor here, consider contributing to the documentation. -😉 - -## Preact Developer Tools - -Preact has their -[own developer tools](https://preactjs.github.io/preact-devtools/) in the form -of a browser extension. The Forem codebase is configured out of the box to -support the Preact Devtools. diff --git a/docs/frontend/dynamic-imports.md b/docs/frontend/dynamic-imports.md deleted file mode 100644 index c153fa05a..000000000 --- a/docs/frontend/dynamic-imports.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Dynamic Imports ---- - -# Dynamic Imports - -[Dynamic imports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/#Dynamic_Imports) -are supported in all major browsers except for Edge -([EdgeHTML](https://en.wikipedia.org/wiki/EdgeHTML) version) and Internet -Explorer which are both unsupported browsers for Forem. They allow you to import -JavaScript dynamically instead of statically. Why is this important? -Performance. - -Should you use them everywhere? No. They are a great tool when you need to load -a JavaScript module on the fly for functionality that is not needed immediately -for the page to be usable. - -Here are a couple of examples of dynamic import usage on Forem: - -- The - [Onboarding flow](https://github.com/forem/forem/blob/0633d85b6b0e083bb7b21b11642b2b17d3fe9de6/app/javascript/packs/Onboarding.jsx#L21). -- In - [homepage](https://github.com/forem/forem/blob/0633d85b6b0e083bb7b21b11642b2b17d3fe9de6/app/javascript/packs/homePage.jsx#L59) - (followed tags). - -Forem uses [webpacker](frontend/webpacker) (webpack), so what webpack will do is -create separate bundles for code that is dynamically imported. So not only do we -end up loading code only when we need it, we also end up with smaller bundle -sizes in the frontend. - -For a great deep dive into dynamic imports, there is a great article from -community member [@goenning](https://dev.to/goenning) about dynamic import -usage, -[How we reduced our initial JS/CSS size by 67%](https://dev.to/goenning/how-we-reduced-our-initial-jscss-size-by-67-3ac0). diff --git a/docs/frontend/instant-click.md b/docs/frontend/instant-click.md deleted file mode 100644 index cb379a8fb..000000000 --- a/docs/frontend/instant-click.md +++ /dev/null @@ -1,43 +0,0 @@ -# InstantClick - -Like the [InstantClick](http://instantclick.io/) tag line says, “InstantClick is -a JavaScript library that dramatically speeds up your website, making navigation -effectively instant in most cases.”. - -The way it works is if a user hovers over a hyperlink, chances are their -intentions are to click on it. InstantClick will start prefetching the page -while a user is hovering over a hyperlink, so that by the time they do click on -it, it's instantaneous. On mobile devices, preloading starts on -[touchstart](https://developer.mozilla.org/en-US/docs/Web/API/Element/touchstart_event). - -Aside from prefetching pages, InstantClick also allows you to customize what -happens when an InstantClick page changes. - -```javascript -// Found in https://github.com/forem/forem/blob/main/app/javascript/packs/githubRepos.jsx#L11) -window.InstantClick.on('change', () => { - loadElement(); -}); -``` - -You can also decide whether or not to reevaluate a script in an InstantClick -loaded page via the `data-no-instant` attribute. - -```javascript -// Found in https://github.com/forem/forem/blob/main/app/assets/javascripts/utilities/buildCommentHTML.js.erb#L80 -function actions(comment) { - if (comment.newly_created) { - return '
\ - \ - REPLY\ -
'; - } else { -... -``` - -For more information on this, see the -[Events and script re-evaluation in InstantClick](http://instantclick.io/scripts) -documentation. diff --git a/docs/frontend/linting-formatting.md b/docs/frontend/linting-formatting.md deleted file mode 100644 index b5744c632..000000000 --- a/docs/frontend/linting-formatting.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Linting and Formatting ---- - -# Linting and Formatting - -The project uses [eslint](https://eslint.org/) with the -[Prettier plugin](https://github.com/prettier/eslint-plugin-prettier). eslint -handles linting, but eslint rules related to code formatting, they get handled -by prettier. For the most part, out of the box rules provided by the -configurations that are extended are used but there are some tweaks. - -Forem also has some objects that live in the global scope, e.g. Pusher. The -eslint globals section of the eslint configuration is what enables these to be -reported as existing when eslint runs. - -```javascript -globals: { - InstantClick: false, - filterXSS: false, - Pusher: false, -} -``` - -## Husky and lint-staged - -The code base uses a pre-commit hook that is enabled by the -[husky](https://github.com/typicode/husky) and -[lint-staged](https://github.com/okonet/lint-staged) tools. The pre-commit hook -runs eslint before frontend code is committed. If there are any issues that can -automatically be fixed, eslint will fix them. If there are linting issues that -cannot be resolved, the commit fails and the changes need to be handled -manually. Prettier also runs during the pre-commit hook. diff --git a/docs/frontend/liquid-tags.md b/docs/frontend/liquid-tags.md deleted file mode 100644 index 0d7128d00..000000000 --- a/docs/frontend/liquid-tags.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: Liquid Tags ---- - -# Liquid Tags - -Liquid tags are special elements of the -[Forem Markdown editor](https://dev.to/new). - -They are custom embeds that are added via a `{% %}` syntax. -[Liquid](https://shopify.github.io/liquid/) is a templating language developed -by Shopify. - -Liquid embeds are for tweets, like `{% tweet 765282762081329153 %}` or a Forem -user profile preview, like `{% user jess %}` etc. - -They make for good community contributions because they can be extended and -improved consistently. It is truly how we extend the functionality of the -editor. At the moment, there could be a lot of work refactoring and improving -existing liquid tags, in addition to adding new ones. - -Liquid tags are sort of like functions, which have a name and take arguments. -Develop them with that mindset in terms of naming things. They should be -documented but also intuitive. They should also be fairly flexible in the -arguments they take. Currently, this could use improvements. - -_Note: Liquid tags are "compiled" when an article is saved. So you will need to -re-save articles to see HTML changes._ - -Here is a bunch of liquid tags supported on Forem: - -```liquid -{% link https://dev.to/kazz/boost-your-productivity-using-markdown-1be %} -{% user jess %} -{% tag git %} -{% devcomment 2d1a %} -{% podcast https://dev.to/basecspodcast/s2e2--queues-irl %} -{% twitter 834439977220112384 %} -{% glitch earthy-course %} -{% github forem/forem %} -{% youtube dQw4w9WgXcQ %} -{% vimeo 193110695 %} -{% twitch ClumsyPrettiestOilLitFam %} -{% slideshare rdOzN9kr1yK5eE %} -{% codepen https://codepen.io/twhite96/pen/XKqrJX %} -{% stackblitz ball-demo %} -{% codesandbox ppxnl191zx %} -{% jsfiddle https://jsfiddle.net/link2twenty/v2kx9jcd %} -{% dotnetfiddle https://dotnetfiddle.net/PmoDip %} -{% replit @WigWog/PositiveFineOpensource %} -{% stackery deeheber lambda-layer-example layer-resource %} -{% nexttech https://nt.dev/s/6ba1fffbd09e %} -{% instagram BXgGcAUjM39 %} -{% speakerdeck 7e9f8c0fa0c949bd8025457181913fd0 %} -{% soundcloud https://soundcloud.com/user-261265215/dev-to-review-episode-1 %} -{% spotify spotify:episode:5V4XZWqZQJvbddd31n56mf %} -{% blogcast 1234 %} -{% kotlin https://pl.kotl.in/owreUFFUG %} -{% wikipedia https://en.wikipedia.org/wiki/Wikipedia %} -{% reddit https://www.reddit.com/r/aww/comments/ag3s4b/ive_waited_28_years_to_finally_havr_my_first_pet %} -``` - -## How liquid tags are developed - -Liquid tags are a matter of parsing the "arguments" and serving relevant -JavaScript. - -Liquid tags go in the `app/liquid_tags` folder. All liquid tags inherit from the -base, like so... - -```ruby -class KotlinTag < LiquidTagBase -``` - -Each liquid tag contains an `initialize` method which takes arguments and calls -`super`. It also has a `render` method which calls the appropriate view. - -```ruby - def initialize(_tag_name, link, _parse_context) - super - stripped_link = ActionController::Base.helpers.strip_tags(link) - the_link = stripped_link.split.first - @embedded_url = KotlinTag.embedded_url(the_link) - end - - def render(_context) - ApplicationController.render( - partial: PARTIAL, - locals: { - url: @embedded_url - } - ) - end -``` - -View files can be found in `app/views/liquids`. - -Each new liquid tag should be accompanied by instructions in -`app/views/pages/_editor_guide_text.html.erb`. - -Liquid Tags should also be accompanied by tests in `spec/liquid_tags` which -confirm expected behavior. - -Some Liquid Tags are constructed using HTML and CSS within the app, and some are -constructed by displaying an iframe of an external site. - -CSS for Liquid Tags are found in `app/assets/stylesheets/ltags`. Liquid tag -classes should generally be prepended by `ltag__`. e.g. `ltag__tag__content` -etc. - -Here is an example of a good Liquid Tag pull request... -https://github.com/forem/forem/pull/3801 - -### Restricting liquid tags by roles - -To only allow users with specific roles to use a liquid tag, you need to define -a `VALID_ROLES` constant on the liquid tag itself. It needs to be an `Array` of -valid roles. For [single resource roles](/admin), it needs to be an `Array` with -the role and the resource. Here's an example: - -```ruby -class NewLiquidTag < LiquidTagBase - VALID_ROLES = [ - :admin, - [:restricted_liquid_tag, LiquidTags::UserSubscriptionTag] - ].freeze -end -``` - -Here we are saying that the `UserSubscriptionTag` is only usable by users with -the `admin` role or with a role of `:restricted_liquid_tag` and a specified -resource of `LiquidTags::UserSubscriptionTag`. - -`LiquidTags::UserSubscriptionTag` is a resource model so we that can play nicely -with the [Rolify][rolify] gem. See [/admin](/admin) for more information. - -**REMINDER: if you do not define a `VALID_ROLES` constant, the liquid tag will -be usable by all users by default.** - -### Restricting liquid tags by context - -Context, in terms of a liquid tag, is _where_ a liquid tag is being used (i.e. -`Article`, `Comment`, etc.). In other words, if you want to make a liquid tag -that can only be used in articles, you need to restrict the liquid tag by -context. - -To do this you need to add a `VALID_CONTEXTS` constant on the liquid tag itself. -It needs to be an `Array` of class names that are valid. For example, to -restrict a liquid tag to only be usable in articles you would do: - -```ruby -class NewLiquidTag < LiquidTagBase - VALID_CONTEXTS = %w[Article].freeze -end -``` - -**REMINDER: if you do not define a `VALID_CONTEXTS` constant the liquid tag will -be usable in all contexts by default.** - -[rolify]: https://github.com/RolifyCommunity/rolify diff --git a/docs/frontend/plain-js.md b/docs/frontend/plain-js.md deleted file mode 100644 index bcb6d1d21..000000000 --- a/docs/frontend/plain-js.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: JavaScript and Initializers ---- - -# JavaScript and Initializers - -Forem has two JavaScript codebases. - -One is located in the directory `app/assets/javascripts` and contains plain -JavaScript (mostly ES5+) being served using -[Sprockets](https://github.com/rails/sprockets-rails) which packages static -assets. - -Webpacker manages the other one, -[which you can read more about in this guide](/frontend/webpacker). - -This source code is not transpiled, only packaged and minified, and will be -limited to whatever flavor of JavaScript can run on the user's web browser. - -`app/assets/javascripts/application.js` contains the manifest JavaScript file -which is included globally in the primary template, -`app/views/layouts/application.html.erb`. - -`application.js` automatically includes all JS files via the statement: - -```erb -//= require_tree . -``` - -One JS file in particular, `app/assets/javascripts/initializePage.js`, -bootstraps the majority of the functionality. You will notice, within this file, -that major sections of the websites are bootstrapped, for example: - -```javascript -initializeBaseTracking(); -initializeCommentsPage(); -initEditorResize(); -initLeaveEditorWarning(); -initializeArticleReactions(); -initNotifications(); -initializeSplitTestTracking(); -``` - -All the "initializers" are in `/app/assets/javascripts/initializers`. diff --git a/docs/frontend/preact.md b/docs/frontend/preact.md deleted file mode 100644 index 288c242f2..000000000 --- a/docs/frontend/preact.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Preact ---- - -# Preact - -[Preact](https://preactjs.com/) is an alternative to React with the same modern -API. - -Preact components are packaged using [Webpacker](/frontend/webpacker) and the -Preact code is located in `app/javascript`. - -Preact components get loaded via webpacker's helper function -`javascript_packs_with_chunks_tag`. - -## PropTypes - -Preact supports -[PropTypes](https://reactjs.org/docs/typechecking-with-proptypes.html). When -creating Preact components, please ensure that you have defined your PropTypes. - -### Common PropTypes - -Using PropTypes can be repetitive. Some duplication is normal, like when a -PropType is a string or a number. But for commonly-used PropTypes, like the user -entity, you can use the provided common PropTypes, located in the -`/app/javascript/common-prop-types`, as shown below. - -```javascript -import PropTypes from 'prop-types'; - -export const userPropTypes = PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - profile_image_url: PropTypes.string.isRequired, - summary: PropTypes.string.isRequired, -}); -``` - -#### Using Common PropTypes - -Common PropTypes are imported just like any other -[JavaScript Module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). -For example, here are two scenarios where a component needs to use the -`tagPropTypes`. - -In the example below, our component `SomeComponentUsingTags` has a `tags` prop, -which is an array of the tag entity. PropTypes have a built-in method called -`arrayOf` that allows you to define a prop as an array of something. In our -case, this is the tag entity, so we can use the `tagPropTypes` PropType. - -```jsx -import { h } from 'preact'; -import PropTypes from 'prop-types'; -import { tagPropTypes } from '../../../components/common-prop-types'; - -const SomeComponentUsingTags = ({ tags = [] }) => ( -
    - {tags.map((tag) => ( -
  • {tag.name}
  • - ))} -
-); - -SomeComponentUsingTags.displayName = 'SomeComponentUsingTags'; -SomeComponentUsingTags.propTypes = { - tags: PropTypes.arrayOf(tagPropTypes).isRequired, -}; -``` - -In the following example, the `SomeComponentUsingOneTag` component has a `tag` -prop representing a single tag. In this case, we can just the `tagPropTypes` on -their own to represent the shape of the `tag` prop. - -```jsx -import { h } from 'preact'; -import { tagPropTypes } from '../../../components/common-prop-types'; - -const SomeComponentUsingOneTag = ({ tag }) =>
  • {tag.name}
  • ; - -SomeComponentUsingOneTag.displayName = 'SomeComponentUsingTags'; -SomeComponentUsingOneTag.propTypes = { - tag: tagPropTypes.isRequired, -}; -``` diff --git a/docs/frontend/readme.md b/docs/frontend/readme.md deleted file mode 100644 index 69abf5251..000000000 --- a/docs/frontend/readme.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -items: - - plain-js.md - - webpacker.md - - preact.md - - instant-click.md - - dynamic-imports.md - - styles.md - - linting-formatting.md - - liquid-tags.md - - debugging.md - - tracking.md - - accessibility.md - - tips.md ---- - -# Frontend Guide diff --git a/docs/frontend/styles.md b/docs/frontend/styles.md deleted file mode 100644 index 5d36c6edf..000000000 --- a/docs/frontend/styles.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Styles ---- - -# Styles - -The majority of the CSS in the application is written in -[SASS](https://sass-lang.com/). There are a few places in the code base that -have style blocks in ERB templates, for inlining critical CSS (good). There are -also some styles that live in ERB templates that are not critical CSS (bad). -That is a bit of refactoring that needs to be done. PRs welcome! - -Important files when working with SASS in the project: - -- variables: - [/app/assets/stylesheets/variables.scss](https://github.com/forem/forem/blob/main/app/assets/stylesheets/variables.scss) -- mixins: - [/app/assets/stylesheets/\_mixins.scss](https://github.com/forem/forem/blob/main/app/assets/stylesheets/_mixins.scss) - -SASS is compiled and served using -[Sprockets](https://github.com/rails/sprockets-rails) which packages static -assets in Rails. - -For more about branding, theming or design in general in regards to Forem, refer -to the [Design Guide](/design) documentation. - -## Crayons - -Crayons is the design system used by Forem. A -[storybook](https://storybook.js.org/) listing the various elements is available -at https://storybook.forem.com/ - -You can also run it locally with the following command: - -``` -$ yarn storybook -``` diff --git a/docs/frontend/tips.md b/docs/frontend/tips.md deleted file mode 100644 index 4c90d8c53..000000000 --- a/docs/frontend/tips.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Tips ---- - -# Tips - -## About query selectors - -JavaScript has many different query selectors, some seemingly interchangeable, -for example: - -- `document.head` and `document.body` -- `document.getElementById`, `document.getElementsByClassName` and - `document.getElementsByTagName` -- `document.querySelector` and `document.querySelectorAll` - -Knowing which to use for optimal performance depends on the situation, but a -good rule of thumb is: - -- to access the **head** of the document, use `document.head` over - `document.getElementsByTagName('head')` -- to access the **body** of the document, use `document.body` over - `document.getElementsByTagName('body')` -- to access an element by id use `document.getElementById('id')` over - `document.querySelector('#id')` -- to access one element by class name use - `document.getElementsByClassName('className')[0]` over - `document.querySelector('.className')` -- to access multiple elements by class name use - `document.getElementsByClassName('className')` over - `document.querySelectorAll('.className')` -- to access one element by tag name use - `document.getElementsByTagName('tagName')[0]` over - `document.querySelector('tagName')` -- to access multiple elements by tag name use - `document.getElementsByTagName('tagName')` over - `document.querySelectorAll('tagName')` - -In most cases `querySelector` and `querySelectorAll` should be used only on -selectors more sophisticated than a simple id, class or tag name. - -### Resources - -- [Forem PR 6380](https://github.com/forem/forem/issues/6380#issuecomment-592989438) -- [Why is getElementsByTagName() faster than querySelectorAll()?](https://humanwhocodes.com/blog/2010/09/28/why-is-getelementsbytagname-faster-that-queryselectorall/) -- [What is the difference between querySelectorAll and getElementsByTagName?](https://stackoverflow.com/a/30921553/4186181) diff --git a/docs/frontend/tracking.md b/docs/frontend/tracking.md deleted file mode 100644 index 9b552d0b8..000000000 --- a/docs/frontend/tracking.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Tracking ---- - -## Ahoy.js - -For first-party analytics, we use the -[`ahoy.js` library](https://github.com/ankane/ahoy.js), which tracks visits and -events. This library works in conjunction with the `ahoy_matey` gem, which is -documented in our [backend tracking guide](/backend/tracking). - -### Configuration - -The configuration for `ahoy.js` lives in `app/assets/javascripts/base.js.erb`. -Since we do not track user cookies on the backend, we have configured -`ahoy.js`'s defaults to match that on the frontend. - -### Events - -In order to track an event, use the `ahoy.track` function: - -```javascript -ahoy.track(name, properties); -``` - -This function will send a `POST` request to the `/ahoy/events` endpoint on our -backend with the `name` and `properties` of the event. The backend endpoint will -also create a corresponding `Ahoy::Visit` for the event if one does not exist -already. diff --git a/docs/frontend/webpacker.md b/docs/frontend/webpacker.md deleted file mode 100644 index bcf6d0cfc..000000000 --- a/docs/frontend/webpacker.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Webpacker ---- - -# Webpacker - -Forem has two JavaScript codebases. - -One contains plain JavaScript, -[which you can read more about in this guide](/frontend/plain-js). - -The other one is managed by [Webpacker](https://github.com/rails/webpacker), and -it's located inside `/app/javascript`, written using ES6+. - -Currently, it's mainly used for Preact components, served via `webpack` which is -integrated into the Rails app using `Webpacker`. - -There is a packs directory `/app/javascript/packs` where you can create new -"pack" files. Pack files are initializers for Webpacker. - -Since Forem is not a Single Page Application (SPA), Preact components are -mounted as needed by including the pack file in the view files. - -For example: - -```erb -<%= javascript_packs_with_chunks_tag "webShare", defer: true %> -``` - -The include statement corresponds to the pack `app/javascript/packs/webShare.js` - -If you have more than one webpacker pack on the page, you need to include it in -the same `javascript_packs_with_chunks_tag` call. The reason being is it avoids -loading split chunks multiple times. - -```erb -<%= javascript_packs_with_chunks_tag "webShare", "someOtherPack", defer: true %> -``` - -## Webpack aliases - -The project uses -[webpack aliases](https://webpack.js.org/configuration/resolve/#resolvealias). -The aliases used in the project can be found under `alias` in -https://github.com/forem/forem/blob/master/config/webpack/environment.js - -## Additional Resources - -For more information in regards to `javascript_packs_with_chunks_tag`, see -https://github.com/rails/webpacker/blob/main/lib/webpacker/helper.rb - -Aside from the Webpacker repository, see also Ross Kaffenberger's -[visual guide to Webpacker](https://rossta.net/blog/visual-guide-to-webpacker.html). - -If you're interested in bundles sizes and what's contained within them for a -production build, run `bin/bundleAnalyzer` from the command line. diff --git a/docs/getting-started/branching.md b/docs/getting-started/branching.md deleted file mode 100644 index d78135436..000000000 --- a/docs/getting-started/branching.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Creating a Branch ---- - -# Creating a feature/bug branch - -When you are working on a bug, feature, or improvement, you will need to create -a branch. - -Branches names should be prefixed with your own GitHub username. If they have an -associated issue, the issue ID should be added as a suffix. For example: - -```shell -git checkout -b USERNAME/that-new-feature-1234 -``` - -or - -```shell -git checkout -b USERNAME/fixing-that-bug-1234 -``` - -where `USERNAME` should be replaced by your username on GitHub and `1234` is the -ID of the issue tied to your pull request. If there is no related issue, you can -leave the number out. - -NOTE: It is ok if your branch name shows up as -`USERNAME:USERNAME/fixing-that-bug-1234` when you create the pull request diff --git a/docs/getting-started/committing.md b/docs/getting-started/committing.md deleted file mode 100644 index 936b78c7d..000000000 --- a/docs/getting-started/committing.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Committing ---- - -# Committing and pre-commit hooks - -## Commit messages - -We encourage people to write -[meaningful commit messages](https://chris.beams.io/posts/git-commit/). - -## Style guide - -This project follows -[thoughtbot's Ruby Style Guide](https://github.com/thoughtbot/guides/blob/main/ruby/.rubocop.yml), -using [Rubocop](https://github.com/bbatsov/rubocop) along with -[Rubocop-Rspec](https://github.com/backus/rubocop-rspec) as the code analyzer. -If you have Rubocop installed with your text editor of choice, you should be up -and running. - -For the frontend, [ESLint](https://eslint.org) and -[prettier](https://github.com/prettier/prettier) are used. ESLint's recommended -rules along with Preact's recommended rules are used for code-quality. -Formatting is handled by prettier. If you have ESLint installed with your text -editor of choice, you should be up and running. - -## Husky hooks - -When commits are made, a git precommit hook runs via -[husky](https://github.com/typicode/husky) and -[lint-staged](https://github.com/okonet/lint-staged). ESLint, prettier, and -Rubocop will run on your code before it's committed. If there are linting errors -that can't be automatically fixed, the commit will not happen. You will need to -fix the issue manually then attempt to commit again. - -Note: if you've already installed the [husky](https://github.com/typicode/husky) -package at least once (used for pre-commit npm script), you will need to run -`yarn --force` or `npm install --no-cache`. For some reason, the post-install -script of husky does not run when the package is pulled from yarn or npm's -cache. This is not husky specific, but rather a cached package issue. diff --git a/docs/getting-started/config-env.md b/docs/getting-started/config-env.md deleted file mode 100644 index 6444e9ed3..000000000 --- a/docs/getting-started/config-env.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Configuring Environment Variables ---- - -# Configuring environment variables and secret keys - -Take a look at `.env_sample`. This file lists all the `ENV` variables we use and -provides a fake default for any missing keys. - -The [backend guide][backend_guide] will show you how to get free API keys for -additional services that may be required to run certain parts of the app. - -To set up keys for your local instance of Forem, you'll need to create an `.env` -file. You can do this by copying the file called `.env_sample` in the app's main -directory: - -```shell -cp .env_sample .env -``` - -Then, add each key you need to the `.env` file. For example, if you're setting -up Cloudinary: - -```shell -export CLOUDINARY_API_KEY="SOME_REAL_SECURE_KEY_HERE" -export CLOUDINARY_API_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" -export CLOUDINARY_CLOUD_NAME="A_CLOUDINARY_NAME" -``` - -(Don't worry, your `.env` file is ignored by git) - -If you are missing `ENV` variables when you boot your application you will see a -warning message in your logs when you try to access that variable -`Unset ENV variable: xyz`. - -Only certain features require "real" keys, so you may be able to add them as you -work on different areas of the application. - -[backend_guide]: /backend diff --git a/docs/getting-started/db.md b/docs/getting-started/db.md deleted file mode 100644 index 28c5decb8..000000000 --- a/docs/getting-started/db.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Preparing the Database ---- - -# Preparing the database - -The next step is to create and prepare the database. Because Forem is a Rails -application, we have built-in tools to help us. - -We can use Rails to create our database, load the schema, and add some seed -data: - -```shell -rails db:setup -``` - -Note: If you've already run `bin/setup`, this will have already been done for -you. - -`db:setup` actually runs the following rake commands in order so alternatively, -you could run each of these to produce the same result: - -```shell -rails db:create -rails db:schema:load -rails db:seed -``` - -## Seed Data - -By default, the amount of articles and users generated is quite tiny so that -contributors experience a quick installation. If you require more data for your -local installation, you can tune amount of data generated with the environment -variable `SEEDS_MULTIPLIER`. - -This variable, which defaults to `1`, allows the developer to increase the size -of their local DB. For example: - -```shell -SEEDS_MULTIPLIER=2 rails db:setup -``` - -will result in creating double the default amount of items in the database. - -It's currently used only for `articles` and `users`. - -It can also be used for `rails db:seed` and `rails db:reset`. - -## Default Admin User - -Seed data creates a handful of regular users, and a single admin user that can -be used to log into the application with the Email login option: - -``` -email: admin@forem.local -password: password -``` - -### Other seed modes - -To put your local forem into "starter mode", as it would be for a new creator, -use `MODE=STARTER` i.e... - -```shell -MODE=STARTER rails db:setup -``` - -This mode skips creation of all sample data. diff --git a/docs/getting-started/forking.md b/docs/getting-started/forking.md deleted file mode 100644 index 90a10b406..000000000 --- a/docs/getting-started/forking.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Forking the Repo ---- - -# Forking the repository - -The first step in contributing to any Open Source project on GitHub is -[forking][forking] so that you can create [Pull Requests][pull_requests]. If -you're not familiar with the idea of forking a repository, [GitHub has a super -simple tutorial][forking_tutorial]! - -If you're ready to get started, [fork Forem's repository][fork_dev]! - -Once you've got a fork on GitHub, you can clone your fork to run the project -locally: - -```shell -git clone https://github.com//forem.git -``` - -As time goes on, you may need to refresh your fork. If you have trouble with -that, you can read about [keeping a fork caught up on Forem][refresh_your_fork]! - -[forking]: https://help.github.com/en/articles/fork-a-repo -[fork_dev]: https://github.com/forem/forem/fork -[forking_tutorial]: https://guides.github.com/activities/forking/ -[pull_requests]: https://help.github.com/en/articles/about-pull-requests -[refresh_your_fork]: - https://dev.to/jacobherrington/a-fool-proof-way-to-keep-your-fork-caught-up-in-git-2e2e diff --git a/docs/getting-started/pull-request.md b/docs/getting-started/pull-request.md deleted file mode 100644 index f5e066b3d..000000000 --- a/docs/getting-started/pull-request.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Preparing a Pull Request ---- - -# Preparing a pull request - -- Try to keep the pull requests small. A pull request should try its very best - to address only a single concern. -- If you plan to do further work after the PR has been submitted, please use the - [Draft PR](https://github.blog/2019-02-14-introducing-draft-pull-requests/) - feature. -- Make sure all tests pass and add additional tests for the code you submit. - [More info here](https://docs.forem.com/tests/). -- Document your reasoning behind the changes. Explain why you wrote the code in - the way you did. The code should explain what it does. -- If there's an existing issue related to the pull request, reference to it by - adding something like `References/Closes/Fixes/Resolves #305`, where 305 is - the issue number. - [More info here](https://github.com/blog/1506-closing-issues-via-pull-requests). -- Please fill out the PR Template when making a PR. -- All commits in a pull request will be squashed when merged, but when your PR - is approved and passes our CI, it will eventually be live on production! - -If the pull request affects the public API in any way, a post on Forem from the -Forem Team account should accompany it. This is the duty of the core team to -carry out. diff --git a/docs/getting-started/readme.md b/docs/getting-started/readme.md deleted file mode 100644 index 109f9199b..000000000 --- a/docs/getting-started/readme.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Getting Started -items: - - forking.md - - config-env.md - - db.md - - start-app.md - - workflow.md - - branching.md - - committing.md - - pull-request.md - - syncing.md - - architecture.md ---- - -# Getting Started! diff --git a/docs/getting-started/start-app.md b/docs/getting-started/start-app.md deleted file mode 100644 index 100fc8091..000000000 --- a/docs/getting-started/start-app.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Starting the Application ---- - -We're a Rails app, and we use [Webpacker][webpacker] to manage some of our -JavaScript. - -# Starting the application - -Start the application, Webpack, and our job runner [Sidekiq][sidekiq] by -running: - -```shell -bin/startup -``` - -(This just runs `foreman start -f Procfile.dev`, for notes on how to install -Foreman, please see [Other Tools](/installation/others/)) - -Then point your browser to http://localhost:3000/ to view the site. To log in -use the admin account created by default (see -[Database](/getting-started/db/#default-admin-user)) - -If you run into issues while trying to run `bin/setup` and the error message -isn't helpful, try running `bin/rails s -p 3000`. For example, you may need to -`yarn install` before starting the app. - -If Sidekiq is producing errors similar to -`No such file or directory - [SOME FILE]`, you may need to start Sidekiq by -itself once to help it initialize itself fully. You can use the command -`bundle exec sidekiq` to do this. - -If you're working on Forem regularly, you can use `alias start="bin/startup"` to -make this even easier. 😊 - -If you're using **`pry`** for debugging in Rails, note that using `foreman` and -`pry` together works, but it's not as clean as `bin/rails server`. - -Here are some singleton commands you may need, usually in a separate -instance/tab of your shell. - -- Running the job Sidekiq server (if using `bin/rails server`) -- this is mostly - for notifications and emails: **`bundle exec sidekiq`** - -Current gotchas: potential environment issues with external services need to be -worked out. - -# Starting the application (advanced) - -To have additional control in your local environment, you might prefer using an -advanced setup to start the application by using [Overmind][overmind]. - -The prerequisite is to install [Overmind][overmind], a process manager which -takes advantage of [tmux][tmux]. - -This will allow you to launch all your app's processes in the same terminal, -navigate the logs of each service separately, restart each service separately -and have a better debugging experience. - -After installing [Overmind][overmind], launch the application: - -```shell -overmind s -f Procfile.dev -``` - -## Debugging the Rails application - -[Overmind][overmind] lets you easily step through the Rails application in a -debugging session. - -Using the `pry` gem, you can add a `binding.pry` to set a breakpoint in the -method you're trying to debug; the application will halt its execution there. -You can then connect to the web server by opening a separate terminal window and -typing: - -```shell -overmind c web -``` - -This will open up a [tmux][tmux] window pane at the debugging statement -position, which will look something like this: - -```ruby -pry(#)> whereami - -From: /forem/app/controllers/admin/overview_controller.rb:8 Admin::OverviewController#index: - - 5: def index - 6: a = "Hello debugger" - 7: binding.pry - => 8: end -``` - -## Inspecting the logs of each service - -Overmind launches the various services required for our local setup: `web` (the -Rails web server), `webpacker` (the server managing JavaScript) and `sidekiq` -(the server managing the asynchronous queue). - -If, for example, you want to inspect just the Sidekiq logs, you can open a -separate terminal window to look at those logs specifically: - -```shell -overmind c sidekiq -``` - -This will open a `tmux` console, which will allow you to browse _only_ the -Sidekiq logs. - -There are also some handy `tmux` shortcuts that you may find useful. - -- The shortcut `C-b [` (_Control-b-open square bracket_) activates "scroll - mode", which allows you to use the arrows up and down and inspect the logs. -- The shortcut `q` deactivates "scroll mode". - -Please refer to [tmux][tmux] documentation for more information around `tmux` -configuration and for additional shortcuts. - -## Resources - -Other than the official [Overmind][overmind] and [tmux][tmux] documentation, you -may find the following resources useful: - -- [Rails quick tips #6: tmux, tmuxinator and Overmind](https://dev.to/citizen428/rails-quick-tips-6-tmux-tmuxinator-and-overmind-4850) -- [Give Your Terminal Super Powers: tmux Cheatsheet!](https://dev.to/jacobherrington/give-your-terminal-super-powers-tmux-cheatsheet-1p6p) -- [Introducing Overmind and Hivemind](https://evilmartians.com/chronicles/introducing-overmind-and-hivemind) - -[sidekiq]: https://github.com/mperham/sidekiq -[webpacker]: https://github.com/rails/webpacker -[overmind]: https://github.com/DarthSim/overmind -[tmux]: https://github.com/tmux/tmux/wiki diff --git a/docs/getting-started/syncing.md b/docs/getting-started/syncing.md deleted file mode 100644 index 2c8ebcbdf..000000000 --- a/docs/getting-started/syncing.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Keeping Your Fork In Sync ---- - -# Keeping your fork in sync - -Now that you have a fork of Forem's source code, there is work you will need to -do to keep it updated. - -## Setup your upstream - -Inside your Forem directory, add a remote to the official Forem repo: - -```shell -git remote add upstream https://github.com/forem/forem.git -``` - -## Rebasing from upstream - -Do this prior to creating each branch for a PR: - -Make sure you are on the main branch: - -```shell -$ git status -On branch main -Your branch is up-to-date with 'origin/main'. -``` - -If you aren't on `main`, finish your work and checkout the `main` branch: - -```shell -git checkout main -``` - -Do a pull with rebase against `upstream`: - -```shell -git pull --rebase upstream main -``` - -This will pull down all of the changes to the official `main` branch, without -making an additional commit in your local repo. - -(Optional) Force push your updated `main` branch to your GitHub fork - -```shell -git push origin main --force -``` - -This will overwrite the `main` branch of your fork. - -## Keeping your branch up to date - -Sometimes, your forked branch may get out of date. To get it up to date it, -carry out the following steps: - -Rebase from upstream once again: - -```shell -git checkout main -git pull --rebase upstream main -``` - -Checkout your feature branch locally and merge main back into your branch: - -```shell -git checkout -git merge main -``` - -Merge any conflicts in editor if necessary: - -```shell -git commit -m "Fix merge conflicts" -``` - -Push the changes back to your origin feature branch: - -```shell -git push origin -``` - -After you've fetched new commits from upstream, run `./bin/setup`, and it will -install new gems, npm packages, update database, and restart Rails server. - -## Additional resources - -- [Syncing a fork](https://help.github.com/articles/syncing-a-fork/) diff --git a/docs/getting-started/workflow.md b/docs/getting-started/workflow.md deleted file mode 100644 index f5a458eaf..000000000 --- a/docs/getting-started/workflow.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Suggested Workflow ---- - -# Suggested workflow - -We use [Spring](https://github.com/rails/spring), and it is already included in -the project. - -1. Use the provided bin stubs to automatically start Spring, i.e. - `bin/rails server`, `bin/rspec spec/models/`, `bin/rails db:migrate`. -1. If Spring isn't picking up on new changes, use `spring stop`. For example, - Spring should always be restarted if there's a change in the environment - keys. -1. Check Spring's status whenever with `spring status`. - -Caveat: `bin/rspec` is not equipped with Spring because it affects Simplecov's -result. Instead, use `bin/spring rspec`. - -## Synchronizing a fork with upstream / integrate latest changes - -When changes in the upstream repository happen, the fork does not get those -automatically and this is by design. To integrate the changes to the upstream -repo that were committed since you cloned your fork or synced the last time, use -the following script: `./scripts/sync_fork.sh` This will fetch the changes and -merge them into your current workspace. - -Use this: - -- to get commits from upstream main into your branch -- to sync with latest changes from upstream main before continuing with a new - feature on your current branch - -After you've fetched new commits from upstream, run `./bin/setup`, and it will -install new gems, npm packages, update database, and restart Rails server. - -Start the app by running `./bin/startup`, if it's not already running. - -## Start over / discard all your changes - -Sometimes it is neccesarry to start over from the beginning or reset the current -workspace to the state of the upstream branch. Use the helper -`./scripts/clean_fork.sh` to set your fork to the exact same state as the -upstream main branch. - -Use this: - -- before working on a new feature -- before creating a new branch to make sure to have all the latest changes in - your fork also. - -After you've done that, run `./bin/setup`, and it will update gems, npm -packages, update database, and restart Rails server. - -Start the app by running `./bin/startup`, if it's not already running. diff --git a/docs/installation/containers.md b/docs/installation/containers.md deleted file mode 100644 index 2d4891b16..000000000 --- a/docs/installation/containers.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Containers ---- - -# Installing Forem using Containers - -If you encounter any errors with our Container setup, please kindly -[report any issues](https://github.com/forem/forem/issues/new/choose)! - -## Installing prerequisites - -_These prerequisites assume you're working on an operating system supported by -Docker or Podman._ - -### Choosing a Container Engine - -A container engine is software that runs and manages containers on a computer. -One of the most widely known Container Engines is Docker, but there are many -other Container Engines available, such as [Podman](https://podman.io/), -[CRI-O](https://cri-o.io/), and -[LXD](https://linuxcontainers.org/lxd/introduction/). - -Forem supports two Container Engines: Docker and Podman. - -### Docker - -Forem can be setup with Docker and Docker Compose on macOS or Linux systems. - -Docker is available for many different operating systems. You may use Docker as -your Container Engine on both macOS and Linux workstations. As of right now -Docker is the only Container Engine for macOS and we recommend you follow the -[Docker Desktop on Mac](https://docs.docker.com/docker-for-mac/install/), -install instructions to get Docker and Docker Compose installed. - -Docker also works well on Linux distributions that have not moved to cgroup v2. -You can install it by following their -[Installation per distro](https://docs.docker.com/engine/install/) to get Docker -and you can install Docker Compose by following these -[instructions](https://docs.docker.com/compose/install/). - -### Podman - -Forem can be setup with Podman and Podman Compose on Linux systems. - -[Podman](https://podman.io/) is an FOSS project that provides a Container Engine -that is daemonless which only runs on Linux systems. It can be run as the root -user or as a non-privileged user. It also provides a Docker-compatible command -line interface. Podman is available on many different Linux distributions and it -can be installed by following these -[instructions](https://podman.io/getting-started/installation). - -[Podman Compose](https://github.com/containers/podman-compose) is a an early -project under development that is implementing docker-compose like experience -with Podman. You can install it by following these -[instructions](https://github.com/containers/podman-compose#installation). - -## Setting up Forem - -1. Fork Forem's repository, e.g. -1. Clone your forked repository, eg. - `git clone https://github.com//forem.git` -1. Set up your environment variables/secrets - - 1. Create `.env` by copying from the provided template`.env_sample` (i.e. - with bash: `cp .env_sample .env`). - - - `.env` is a personal file that is **ignored in git**. - - `.env` lists all the `ENV` variables we use and provides a fake - default for any missing keys. - - 2. For any key that you wish to enter/replace: - - - You do not need "real" keys for basic development. Some features - require certain keys, so you may be able to add them as you go. - - The [backend guide](/backend) will show you how to get free API keys - for additional services that may be required to run certain parts of - the app. - - Obtain the development variable and apply the key you wish to - enter/replace. i.e.: - - ```shell - export CLOUDINARY_API_KEY="SOME_REAL_SECURE_KEY_HERE" - export CLOUDINARY_API_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" - export CLOUDINARY_CLOUD_NAME="A_CLOUDINARY_NAME" - ``` - -## Running Forem with Docker via docker-compose - -1. Run `bin/container-setup` -2. That's it! Navigate to - -The script executes the following steps: - -1. `docker-compose build` -2. `docker-compose up` - -## Running Forem with Podman via podman-compose - -1. Run `bin/container-setup` -2. That's it! Navigate to - -The script executes the following steps: - -1. `podman-compose build` -2. `podman-compose up` - -## Known Problems & Solutions - -### Docker on Mac - -- In case `rails server` starts with the following message: - - ```shell - Data update scripts need to be run before you can start the application. Please run rails data_updates:run (RuntimeError) - ``` - - run the following command: - - ```shell - docker-compose run rails rails data_updates:run - ``` diff --git a/docs/installation/gitpod.md b/docs/installation/gitpod.md deleted file mode 100644 index 142f8c7a0..000000000 --- a/docs/installation/gitpod.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: GitPod ---- - -# GitPod - -If you prefer working on a cloud IDE, you can spin up your own instance of Forem -in the cloud, using [GitPod](https://gitpod.io/#https://github.com/forem/forem). - -[![Open in -Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/forem/forem) - -Give it a couple of minutes to prepare the workspace. Wait for 'Awaiting port 3000... ok' message in the terminal. - -You can now code, review, or just try out the project. Once you are done, simply close the tab. - -You can find more information about this, -[in a Forem's article](https://dev.to/ben/spin-up-a-local-instance-of-dev-in-the-cloud-with-gitpod-it-s-incredibly-simple-pij). diff --git a/docs/installation/imgproxy.md b/docs/installation/imgproxy.md deleted file mode 100644 index a40da208b..000000000 --- a/docs/installation/imgproxy.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: Imgproxy ---- - -# Imgproxy - -Imgproxy is a standalone server for resizing images. It is optional and you do -not need it to start Forem locally. We are currently only using it in Forem -Cloud. - -## Installation - -- MacOS: install via homebrew with `brew install imgproxy`. -- Windows: please install - [via docker](https://docs.imgproxy.net/#/installation?id=docker). -- Linux: you can either use - [docker installation](https://docs.imgproxy.net/#/installation?id=docker) or - [build from source](https://docs.imgproxy.net/#/installation?id=from-the-source). - -For more options not covered here, please take a look at the -[official installation documentation](https://docs.imgproxy.net/#/installation). - -## Usage - -1. Generate a key/salt pair by running the following in your terminal twice. - Copy those values to your `.env` in the next step - - ``` - echo $(xxd -g 2 -l 64 -p /dev/random | tr -d '\n') - ``` - -1. In your `.env`, add the following. - - ``` - export IMGPROXY_ENDPOINT='http://localhost:8080' - export IMGPROXY_KEY='1b1c9aae804e070b0864f2547fba7ce8ff31bf7..........' - export IMGPROXY_SALT='8c6d449d4fc2cada5bab538826cae709d2ade9f.........' - ``` - -1. Start the Forem app server normally. - -1. Start Imgproxy in a terminal with the key and salt. - - ``` - # If you installed via homebrew or using the binary. - > IMGPROXY_KEY='your key' IMGPROXY_SALT='your salt' imgproxy - - # If you are using Docker or Podman. The commands are identical for both - > docker run -p 8080:8080 \ - -e IMGPROXY_KEY="your key" \ - -e IMGPROXY_SALT="your salt" \ - -it darthsim/imgproxy - ``` - -1. That's it :) - -You should verify it's working by starting the Forem app locally and see that -each image is loaded properly, or run the following command while the Forem app -is running: - -``` -> curl -I http://localhost:8080/unsafe/aHR0cDovL2xvY2Fs/aG9zdDozMDAwL2Fz/c2V0cy8xLnBuZw - -HTTP/1.1 200 OK -Server: imgproxy -X-Request-Id: GYvCGXb98JUwL3ujwpjzh -Date: Tue, 27 Oct 2020 16:11:37 GMT -``` - -## Sidenote - -- Because Imgproxy is a standalone server of its own, all image URLs given to it - need to be absolute URLs. -- When working with Docker or Podman on Linux, provide the host network option - (`--network="host"`) so Imgproxy can properly access the localhost. diff --git a/docs/installation/linux.md b/docs/installation/linux.md deleted file mode 100644 index aeaf0ae64..000000000 --- a/docs/installation/linux.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: Linux ---- - -# Installing Forem on Linux - -## Installing prerequisites - -_These prerequisites assume you're working on a Linux-based operating system, -but they have only been tested on Ubuntu 18.04._ - -### Ruby - -1. If you don't already have a Ruby version manager, we highly recommend - [rbenv](https://github.com/rbenv/rbenv). Please follow their - [installation guide](https://github.com/rbenv/rbenv#installation). -1. With the Ruby version manager, install the Ruby version listed on our badge. - (ie with rbenv: `rbenv install $(cat .ruby-version)`) - -For very detailed rbenv installation directions on several distros, please visit -[DigitalOcean's guide](https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-with-rbenv-on-ubuntu-18-04). - -### Yarn - -There are two ways to install Yarn. - -- Yarn's official - [installation guide](https://yarnpkg.com/en/docs/install#debian-stable) - (recommended). -- [DigitalOcean's detailed tutorial](https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-18-04) - describes how to install - [Node version Manager](https://github.com/creationix/nvm). By installing NVM - you can select a Node version (we recommend either LTS or current); the guide - will also explain how to install NPM. This way you'll have Node, NPM, and then - you can run `npm install -g yarn` to install Yarn. - -### PostgreSQL - -Forem requires PostgreSQL version 11 or higher. - -1. Run - `sudo apt update && sudo apt install postgresql postgresql-contrib libpq-dev`. -1. To test the installation you can run `sudo -u postgres psql` which should - open a PostgreSQL prompt. Exit the prompt by running `\q` then run - `sudo -u postgres createuser -s $YOUR_USERNAME` where `$YOUR_USERNAME` is the - username you are currently logged in as. - -There are more than one ways to setup PostgreSQL. For additional configuration, -check out our [PostgreSQL setup guide](/installation/postgresql) or the official -[PostgreSQL](https://www.postgresql.org/) site for further information. - -### ImageMagick - -Forem uses [ImageMagick](https://imagemagick.org/) to manipulate images on -upload. - -Please refer to ImageMagick's -[instructions](https://imagemagick.org/script/download.php) on how to install -it. - -### Redis - -Forem requires Redis version 6.0 or higher. - -We recommend following Digital Ocean's extensive guides -[How to Install and Secure Redis](https://www.digitalocean.com/community/tutorial_collections/how-to-install-and-secure-redis) -to setup Redis. - -## Installing Forem - -1. Fork Forem's repository, e.g. -1. Clone your forked repository, e.g. - `git clone https://github.com//forem.git` -1. Install bundler with `gem install bundler` -1. Set up your environment variables/secrets - - - Take a look at `.env_sample`. This file lists all the `ENV` variables we - use and provides a fake default for any missing keys. - - If you use a remote computer as dev env, you need to set `APP_DOMAIN` - variable to the remote computer's domain name. - - The [backend guide](/backend) will show you how to get free API keys for - additional services that may be required to run certain parts of the app. - - For any key that you wish to enter/replace: - - 1. Create `.env` by copying from the provided template (i.e. with bash: - `cp .env_sample .env`). This is a personal file that is ignored in git. - 1. Obtain the development variable and apply the key you wish to - enter/replace. i.e.: - - ```shell - export CLOUDINARY_API_KEY="SOME_REAL_SECURE_KEY_HERE" - export CLOUDINARY_API_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" - export CLOUDINARY_CLOUD_NAME="A_CLOUDINARY_NAME" - ``` - - - You do not need "real" keys for basic development. Some features require - certain keys, so you may be able to add them as you go. - -1. Run `bin/setup` - -### Possible error messages - -While installing, you might run into an error due to the `pg` gem requiring -PostgreSQL libraries. If so, please run `sudo apt-get install libpq-dev` before -retrying. - -While installing, you might run into an error due to the `sass-rails` gem -requiring `sassc`, which requires the `g++` compiler. If so, please run -`sudo apt-get install g++` before retrying. - -While installing, if you didn't install `node` or `nvm` manually, you might run -into an error due to an older system node version being present, which can cause -issues while `yarn` is installing packages. If so, you'll need to -[install `nvm`](https://github.com/nvm-sh/nvm#installation-and-update) and then -run `nvm install node` to get the most recent node version before retrying. diff --git a/docs/installation/mac.md b/docs/installation/mac.md deleted file mode 100644 index 471a38a27..000000000 --- a/docs/installation/mac.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: macOS ---- - -# Installing Forem on macOS - -## Installing prerequisites - -### Ruby - -1. **Note:** MacOS ships with a version of Ruby, needed for various operating - systems. To avoid causing an issue with your operating system you should use - a version manager for Ruby. - - If you don't already have a Ruby version manager, we highly recommend - [rbenv](https://github.com/rbenv/rbenv). This will allow you to have - different versions running on a per project basis. The MacOS system version - of Ruby will stay intact while giving you the ability to use the version - needed for this Forem project. Please follow their - [installation guide](https://github.com/rbenv/rbenv#installation). - -2. With the Ruby version manager, install the Ruby version listed on our badge. - (i.e. with rbenv: `rbenv install $(cat .ruby-version)`) - - **Note:** The repository must be forked and cloned before running the - `rbenv install $(cat .ruby-version)` command. - -### Yarn - -Please refer to their [installation guide](https://yarnpkg.com/en/docs/install). - -### PostgreSQL - -Forem requires PostgreSQL version 11 or higher to run. - -The easiest way to get started is to use -[Postgres.app](https://postgresapp.com/). Alternatively, check out the official -[PostgreSQL](https://www.postgresql.org/) site for more installation options. - -For additional configuration options, check our -[PostgreSQL setup guide](/installation/postgresql). - -### ImageMagick - -Forem uses [ImageMagick](https://imagemagick.org/) to manipulate images on -upload. - -You can install ImageMagick with `brew install imagemagick`. - -### Redis - -Forem requires Redis version 6.0 or higher to run. - -We recommend using [Homebrew](https://brew.sh): - -```shell -brew install redis -``` - -you can follow the post installation instructions, we recommend using -`brew services` to start Redis in the background: - -```shell -brew services start redis -``` - -You can test if it's up and running by issuing the following command: - -```shell -redis-cli ping -``` - -## Installing Forem - -1. Fork Forem's repository, e.g. -2. Clone your forked repository in one of two ways: - - - e.g. with HTTPS: `git clone https://github.com//forem.git` - - e.g. with SSH: `git clone git@github.com:/forem.git` - -3. Install bundler with `gem install bundler` -4. Set up your environment variables/secrets - - - Take a look at `.env_sample` to see all the `ENV` variables we use and the - fake default provided for any missing keys. - - If you use a remote computer as dev env, you need to set `APP_DOMAIN` - variable to the remote computer's domain name. - - The [backend guide](/backend) will show you how to get free API keys for - additional services that may be required to run certain parts of the app. - - For any key that you wish to enter/replace, follow the steps below. - - 1. Create `.env` by copying from the provided template (i.e. with bash: - `cp .env_sample .env`). This is a personal file that is ignored in git. - 2. Obtain the development variable and apply the key you wish to - enter/replace. i.e.: - - ```shell - export CLOUDINARY_API_KEY="SOME_REAL_SECURE_KEY_HERE" - export CLOUDINARY_API_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" - export CLOUDINARY_CLOUD_NAME="A_CLOUDINARY_NAME" - ``` - - - You do not need "real" keys for basic development. Some features require - certain keys, so you may be able to add them as you go. - -5. Run `bin/setup` - -### Possible error messages - -**Error:** `rbenv install hangs at ruby-build: using readline from homebrew` - -**_Solution:_** -[Stackoverflow answer](https://stackoverflow.com/questions/63599818/rbenv-install-hangs-at-ruby-build-using-readline-from-homebrew) -`RUBY_CONFIGURE_OPTS=--with-readline-dir="$(brew --prefix readline)" rbenv install 2.0.0` - -**Error:** -`__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called` - -**_Solution:_** Run the command `export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES` -(or `set -x OBJC_DISABLE_INITIALIZE_FORK_SAFETY YES` in fish shell) - ---- - -**Error:** `User does not have CONNECT privilege.` - -**_Solution:_** Complete the steps outlined in the -[PostgreSQL setup guide](/installation/postgresql). - ---- - -**Error:** -`rbenv: version '' is not installed (set by /Path/To/Local/Repository/.ruby-version)` - -**_Solution:_** Run the command `rbenv install ` - ---- - -**Error:** `ruby-build: definition not found: ` when `rbenv` was -installed via `brew`. - -```shell -ruby-build: definition not found: - -See all available versions with `rbenv install --list`. -If the version you need is missing, try upgrading ruby-build: -``` - -**_Solution:_** Run the following to update `ruby-build`, -`brew update && brew upgrade ruby-build`. After that, rerun -`rbenv install ` and that version will get installed. - ---- - -**Error:** - -```shell -== Preparing database == - Sorry, you can't use byebug without Readline. To solve this, you need to - rebuild Ruby with Readline support. If using Ubuntu, try `sudo apt-get - install libreadline-dev` and then reinstall your Ruby. -rails aborted! -LoadError: dlopen(/Users//.rbenv/versions/2.6.5/lib/ruby/2.6.0/x86_64-darwin18/readline.bundle, 9): Library not loaded: /usr/local/opt/readline/lib/libreadline..dylib -``` - -**_Solution:_** Run -`ln -s /usr/local/opt/readline/lib/libreadline.dylib /usr/local/opt/readline/lib/libreadline..dylib` -from the command line then run `bin/setup` again. You may have a different -version of libreadline, so replace `` with the version that -errored. - ---- - -**Error:** - -```shell -PG::Error: ERROR: invalid value for parameter "TimeZone": "UTC" -: SET time zone 'UTC' -``` - -**_Solution:_** Restart your Postgres.app, or, if you installed PostgreSQL with -Homebrew, restart with: - -```shell -brew services restart postgresql -``` - -If that doesn't work, reboot your Mac. - ---- - -**Error:** - -```shell -ERROR: Error installing pg: - ERROR: Failed to build gem native extension. - [...] -Can't find the 'libpq-fe.h header -*** extconf.rb failed *** -``` - -**_Solution:_** You may encounter this when installing PostgreSQL with the -Postgres.app. Try restarting the app and reinitializing the database. If that -doesn't work, install PostgreSQL with Homebrew instead: -`brew install postgresql` - ---- - -> If you encountered any errors that you subsequently resolved, **please -> consider updating this section** with your errors and their solutions. diff --git a/docs/installation/others.md b/docs/installation/others.md deleted file mode 100644 index 8aeeda125..000000000 --- a/docs/installation/others.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Other Tools ---- - -# Miscellaneous - -## Foreman - -We use [Foreman](https://github.com/ddollar/foreman) to manage our application -through `Procfile` and `Procfile.dev`. As the -[documentation](https://github.com/ddollar/foreman/blob/master/README.md) points -out, - -> Ruby users should take care _not_ to install foreman in their project's -> `Gemfile`. See this -> [wiki article](https://github.com/ddollar/foreman/wiki/Don't-Bundle-Foreman) -> for more details. - -Instead install Foreman globally with the following command: - -```sh -$ gem install foreman -``` diff --git a/docs/installation/postgresql.md b/docs/installation/postgresql.md deleted file mode 100644 index 2bd9ccce2..000000000 --- a/docs/installation/postgresql.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: PostgreSQL ---- - -# Setup your application with PostgreSQL - -Follow the instructions in the installation guide below that corresponds to your -operating system: - -1. macOS - - [Postgres.app](https://postgresapp.com/): PostgreSQL installation as a Mac - app - - [Homebrew](https://brew.sh/): if you use Homebrew you can easily install - PostgreSQL with `brew install postgresql` -1. Linux (Ubuntu) - - [Ubuntu `14.04`](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-14-04) - - [Ubuntu `16.04 and higher`](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-16-04) -1. [Windows](https://www.postgresql.org/download/windows/) - -_You can find all installation options for a variety of operating systems -[on the official PostgreSQL download page](https://www.postgresql.org/download/)_. - -## Configuration - -By default, the application is configured to connect to a local database named -`PracticalDeveloper_development`. If you need to specify a username and a -password, you can go about it by using the environment variable `DATABASE_URL` -with a connection string. - -The -[official Rails guides](https://guides.rubyonrails.org/configuring.html#connection-preference) -go into depth on how Rails merges the existing `database.yml` with the -connection string. - -### Setup `DATABASE_URL` in .env - -1. Open your `.env` - -1. Add the following: - -```shell -export DATABASE_URL=postgresql://USERNAME:PASSWORD@localhost - -# Optional: If your test database is in a different url, be sure to set this. -export DATABASE_URL_TEST=postgresql://USERNAME:PASSWORD@localhost -``` - -1. Replace `USERNAME` with your database username, `PASSWORD` with your database - password. - -You can find more details on connection strings in -[PostgreSQL's own documentation](https://www.postgresql.org/docs/10/static/libpq-connect.html#LIBPQ-CONNSTRING). - -NOTE: due to how Rails merges `database.yml` and `DATABASE_URL` it's recommended -not to add the database name in the connection string. This will default to your -development database name also during tests, which will effectively empty the -development DB each time tests are run. - -## Connection Pooling - -We use [PgBouncer](http://www.pgbouncer.org) to manage connection pooling. - -Database pooling creates a shared pool of connections to our database, rather -than creating new connection each time. PgBouncer is a wrapper around our -database connection and ensures that we only have a finite set of "cached" -connections to the database. This means that our app doesn't need to actually -connect to the database, it only needs to connect to the pool of connections. -The number of connections to the database (the connection limit) is dependent on -our -[Heroku Postgres plan](https://devcenter.heroku.com/articles/heroku-postgres-plans). -PgBouncer ensures that we do not exceed our plan's connection limit. diff --git a/docs/installation/readme.md b/docs/installation/readme.md deleted file mode 100644 index 73f469ba4..000000000 --- a/docs/installation/readme.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -items: - - mac.md - - windows.md - - linux.md - - containers.md - - gitpod.md - - postgresql.md - - imgproxy.md - - vault.md - - others.md ---- - -# Installation Guide - -There are many different ways you can install the **development environment** so -you can help contribute code to Forem. - -## Installing locally - -You can install Forem to your local machine and we have instructions for -[Mac](/installation/mac), [Windows](/installation/windows) and -[Linux](/installation/linux). - -## Running with containers - -Installing to your local machine can be troublesome for many reasons such as a -conflicting database and runtime versions. - -Another way you can get a development environment up and running is with -containers. They will set up everything you need in an isolated environment, and -you need not worry about the details of setting everything up locally. We have -instructions for getting set up with [containers](/installation/containers) -quickly. - -## GitPod _- beginner friendly!_ - -If you are having trouble with local installation and Docker confuses you, then -you can launch a **development environment** with the press of a button with -GitPod. - -GitPod is an IDE in the cloud which is also attached to a web server. It will -install everything you need. If you are comfortable doing everything from a web -browser, then we have instructions for installing with -[GitPod](/installation/gitpod) as well. diff --git a/docs/installation/vault.md b/docs/installation/vault.md deleted file mode 100644 index 7a565af3b..000000000 --- a/docs/installation/vault.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Vault ---- - -## Installing - -To install Vault follow the -[Vault installation](https://www.vaultproject.io/docs/install) instructions. If -you have a Mac, you can install -[Vault using Homebrew](https://formulae.brew.sh/formula/vault). You can validate -that you have it installed by running the following command. - -```bash -vault -h -``` - -After Vault has been installed, the next step is to start up a Vault server. - -``` -vault server -dev -``` - -This will give you an output that looks like this: - -``` -==> Vault server configuration: - - Api Address: http://127.0.0.1:8200 - Cgo: disabled - Cluster Address: https://127.0.0.1:8201 - Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled") - Log Level: info - Mlock: supported: false, enabled: false - Recovery Mode: false - Storage: inmem - Version: Vault v1.4.2 - Version Sha: 18f1c494be8b06788c2fdda1a4296eb3c4b174ce+CHANGES - -WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory -and starts unsealed with a single unseal key. The root token is already -authenticated to the CLI, so you can immediately begin using Vault. - -You may need to set the following environment variable: - - $ export VAULT_ADDR='http://127.0.0.1:8200' - -The unseal key and root token are displayed below in case you want to -seal/unseal the Vault or re-authenticate. - -Unseal Key: -Root Token: - -Development mode should NOT be used in production installations! -``` - -## Configuring - -Once Vault is installed and running, the next step is to configure it to work -with your application. Since we want multiple applications (in production) to be -able to use the same Vault infrastructure, we control access with -[Vault policies](https://www.vaultproject.io/docs/concepts/policies) and -different -[key/value secret paths](https://www.vaultproject.io/docs/secrets/kv/kv-v2#setup). -In the following examples, `VAULT_SECRET_NAMESPACE` will be the secret path -where your secrets are stored. This can be any string (except "secrets" since -that exists by default) of your choosing, for example `local-secrets`. -`VAULT_POLICY_NAME` will be the name of the policy that we use to control access -to `VAULT_SECRET_NAMESPACE`. Once again, this should be a string. For example, -`local-policy`. - -To set up a policy and secret path run the following commands: - -``` -vault secrets enable -path=/ kv-v2 - -vault policy write VAULT_POLICY_NAME -< -``` - -Restart your application to start using Vault. One easy way to see it in action -is via the Rails console. - -```ruby -# Enabled Example -[3] pry(main)> AppSecrets["TEST_SET"]="success" -=> "success" -[4] pry(main)> AppSecrets["TEST_SET"] -=> "success" - -# Disabled Example -[2] pry(main)> AppSecrets["TEST_SET"]="success" -Vault::MissingTokenError: Missing Vault token! I cannot make requests to Vault without a token. Please -set a Vault token in the client: - - Vault.token = "1234" - -or authenticate with Vault using the Vault CLI: - - $ vault auth ... - -or set the environment variable $VAULT_TOKEN to the token value: - - $ export VAULT_TOKEN="..." - -Please refer to the documentation for more examples. -``` diff --git a/docs/installation/windows.md b/docs/installation/windows.md deleted file mode 100644 index f0fda0702..000000000 --- a/docs/installation/windows.md +++ /dev/null @@ -1,297 +0,0 @@ ---- -title: Windows ---- - -# Installing Forem on Windows 10 - -## Installing prerequisites - -These prerequisites assume you're working on a `64-bit Windows 10` operating -system machine - -- updated to _version 1903, Build 18362_ or _higher_ for **x64 system** -- updated to _version 2004, Build 19041_ or _higher_ for **ARM64 system** - -For further information regarding system requirements, head over to the -[Microsoft Docs](https://docs.microsoft.com/en-us/windows/wsl/install-win10#requirements) -or -[Microsoft's blog on extending WSL 2 Support](https://devblogs.microsoft.com/commandline/wsl-2-support-is-coming-to-windows-10-versions-1903-and-1909/). - -To check your Windows version, press `Win Logo key` + `R`, type `winver`, then -click OK. - -There are other ways to get Forem running on lower versions, but we recommend a -complete WSL 2 installation. - -### Installing WSL - -Since Forem's codebase is using the Ruby on Rails framework, we will need to -install the Windows Subsystem for Linux (WSL). Some dependencies used by the -source code triggered errors when installing on Windows, so using WSL allows you -to work on the software and not having to fix gem incompatibilities. - -Follow the instructions for -[Installing the Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10). -Once you've installed WSL, complete all the instructions under the following -sections in the link above: - -1. [Update to WSL 2](https://docs.microsoft.com/en-us/windows/wsl/install-win10#update-to-wsl-2). -2. [Enable the "Virtual Machine Platform" optional component](https://docs.microsoft.com/en-us/windows/wsl/install-win10#enable-the-virtual-machine-platform-optional-component). - Be sure to reboot your machine after this step. -3. [Set WSL 2 as your default version](https://docs.microsoft.com/en-us/windows/wsl/install-win10#set-wsl-2-as-your-default-version). - -Once all the steps mentioned above are completed, -[install Ubuntu 18.04 on Windows](https://www.microsoft.com/store/productId/9N9TNGVNDL3Q). - -On your first run, the system will ask for username and password. Take note of -both since it will be used for `sudo` commands. More information about the -process can be found at -[create a user account and password for your new Linux distribution](https://docs.microsoft.com/en-us/windows/wsl/user-support) - -### Installing rbenv - -`rbenv` is a version manager for Ruby applications which allows one to guarantee -that the Ruby version in development environment matches production. First, -install Ruby language dependencies before installing `rbenv`: - -```shell -sudo apt-get update -sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev -``` - -Now, we install [rbenv](https://github.com/rbenv/rbenv) using the following -commands: - -```shell -cd -git clone https://github.com/rbenv/rbenv.git ~/.rbenv -echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc -echo 'eval "$(rbenv init -)"' >> ~/.bashrc -exec $SHELL - -git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build -echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc -exec $SHELL -``` - -One can verify `rbenv` installation using the `rbenv-doctor` script with the -following commands: - -```shell -curl -fsSL https://raw.githubusercontent.com/rbenv/rbenv-installer/main/bin/rbenv-doctor | bash -``` - -### Installing nvm - -As a pre-requisite to install Rails, Node.js needs to be installed. -[nvm](https://github.com/nvm-sh/nvm) is a Node.js version manager that helps a -developer select a specific Node.js version for development. - -To install `nvm`, follow the instructions outlined in the -[official nvm documentation](https://github.com/nvm-sh/nvm#install--update-script). - -Be sure to reload the shell with the command `exec $SHELL` after the -installation is complete. - -Run the following command to verify that `nvm` is installed: - -```shell -command -v nvm -``` - -If the shell outputs `nvm`, the installation is successful. Installation of the -correct Node.js version will be done in a later part of the installation -process. - -### Yarn - -The fastest way to install Yarn for WSL would be from Debian package repository. -Configure the repository with the following commands: - -```shell -curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - -echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list -``` - -Since we do not have Node.js installed yet, we will be installing Yarn without -the default Node.js with the following command: - -```shell -sudo apt update && sudo apt install --no-install-recommends yarn -``` - -To verify Yarn's installation, run the command `yarn -v`. It should print -`Yarn requires Node.js 4.0 or higher to be installed.`. This indicates that the -Yarn installation succeeded but Node.js still needs to be installed for it to -work fully. We install Node.js later on in the installation process. - -### PostgreSQL - -Forem requires PostgreSQL version 11 or higher. To Install PostgreSQL on WSL, -follow steps under the -[PostgreSQL APT Repository](https://www.postgresql.org/download/linux/ubuntu/) -section. - -Once Installed, perform the following steps in order to set up a username and -password for PostgreSQL: - -1. Use `sudo -i service postgresql start` to start the server. -2. Next, replace `$YOUR_USERNAME` in the following commands with your Linux - Username and execute them: - - ```shell - sudo -u postgres createuser -s $YOUR_USERNAME - createdb - sudo -u $YOUR_USERNAME psql - ``` - -3. You should now be in PostgreSQL's shell interface. Execute `\password` to set - a password for your PostgreSQL user. -4. Be sure to make a note of your username and password for future use. Exit - PostgreSQL by executing the command `\quit`. - -For additional configuration options, check our -[PostgreSQL setup guide](/installation/postgresql). - -### ImageMagick - -Forem uses [ImageMagick](https://imagemagick.org/) to manipulate images on -upload. - -ImageMagick can be installed to WSL via installing its -[imagemagick](https://packages.ubuntu.com/bionic/imagemagick) package with the -following command: - -```shell -sudo apt update && sudo apt install imagemagick -``` - -To verify its installation, run `identify -version` command. - -### Redis - -Forem requires Redis version 6.0 or higher. - -We recommend to follow -[this guide](https://redislabs.com/blog/redis-on-windows-10/) to run Redis under -WSL. - -## Installing Forem - -1. Fork Forem's repository, eg. -1. Clone your forked repository, eg. - `git clone https://github.com//forem.git` -1. Open the cloned forem folder in terminal with `cd forem`. Next, install Ruby - with the following commands: - - ```shell - rbenv install $(cat .ruby-version) - rbenv global $(cat .ruby-version) - ruby -v - ``` - -1. Install Node.js with the following set of commands: - - ```shell - nvm install $(cat .nvmrc) - nvm use $(cat .nvmrc) - node -v - yarn -v - ``` - -1. Install bundler with `gem install bundler` -1. Set up your environment variables/secrets - - - Take a look at `.env_sample`. This file lists all the `ENV` variables we - use and provides a fake default for any missing keys. - - If you use a remote computer as dev env, you need to set `APP_DOMAIN` - variable to the remote computer's domain name. - - The [backend guide](/backend) will show you how to get free API keys for - additional services that may be required to run certain parts of the app. - - For any key that you wish to enter/replace: - - 1. Create `.env` by copying from the provided template (ie. with bash: - `cp .env_sample .env`). This is a personal file that is ignored in git. - 1. Obtain the development variable and apply the key you wish to - enter/replace. ie: - - ```shell - export GITHUB_KEY="SOME_REAL_SECURE_KEY_HERE" - export GITHUB_SECRET="ANOTHER_REAL_SECURE_KEY_HERE" - ``` - - - You do not need "real" keys for basic development. Some features require - certain keys, so you may be able to add them as you go. - -1. After ensuring that the PostgreSQL server and the Redis server are running, - run `bin/setup`. - - > The `bin/setup` script is responsible for installing a varienty of - > dependencies. One can find it inside the `bin` folder by the name of - > `setup`. - > - > - Its first task is to install the `bundler` gem. Next, it will make - > `bundler` install all the gems, including `Rails`, located in `Gemfile` - > in the root of the repository. It also installs `foreman`. - > - It then installs JavaScript dependencies using the script in `bin/yarn` - > file. These dependencies are located in `package.json` in the root of the - > repository. - > - Next, it uses various Rake files located inside the `lib` folder for the - > PostgreSQL database creation and updation. - > - Finally it cleans up all the log files and restarts the Puma server. - -### Possible error messages - -1. There is a possibility that you might encounter a _statement timeout_ when - seeding the database for the first time. Please increase the value of - `statement_timeout` to `9999999` in `config/database.yml`. - -2. If the installation process failed with the following error - `ERROR: Error installing pg`. Please consider installing the following - package `libpq-dev` : - -```bash -sudo apt-get install libpq-dev -``` - -3. If the command `bin/setup` fails at installing `cld-0.8.0` with the warnings - `'aclocal-1.10' is missing on your system` and - `'automake-1.10' is missing on your system`. Please install `automake-1.10` - using the commands below. - -```shell -cd -sudo apt-get update -sudo apt-get install autoconf -wget https://ftp.gnu.org/gnu/automake/automake-1.10.tar.gz -tar xf automake-1.10.tar.gz -cd automake-1.10/ -./configure --prefix=/usr/local -make -``` - -### WSL2 and System test - -In WSL2, hostname/IP address are no longer shared between Windows and Linux. -There are currently two work-arounds. - -1. Use dockerized selenium, ie docker-selenium. You will need docker for the - following steps - - 1. `docker run -d --name selenium-hub -p 4444:4444 selenium/hub:3.141.59-20200409` - 2. `CH=$(docker run --rm --name=ch --link selenium-hub:hub -v /dev/shm:/dev/shm selenium/node-chrome:3.141.59-20200409)` - 3. Add `export SELENIUM_URL="http://localhost:4444/wd/hub"` to your `.env` - 4. Run your System test! - -2. Port forward with `socats` (more info needed). - -> If you encountered any errors that you subsequently resolved, **please -> consider updating this section** with your errors and their solutions. - -### WSL2 and End to End Tests - -In order to run Cypress Test Runner, a few extra setup steps are required to run -GUIs natively inside of WSL2. - -[This guide](https://nickymeuleman.netlify.app/blog/gui-on-wsl2-cypress) -explains how to use graphical user interfaces like Cypress inside WSL2. diff --git a/docs/licensing.md b/docs/licensing.md deleted file mode 100644 index 48bcd699e..000000000 --- a/docs/licensing.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Licensing ---- - -# Licensing - -This program is free software: you can redistribute it and/or modify it under -the terms of the GNU Affero General Public License as published by the Free -Software Foundation, either version 3 of the License, or (at your option) any -later version. Please see the -[LICENSE](https://github.com/forem/forem/blob/main/LICENSE.md) file in our -repository for the full text. - -Like many open source projects, we require that contributors provide us with a -Contributor License Agreement (CLA). By submitting code to the Forem project, -you are granting us a right to use that code under the terms of the CLA. - -Our version of the CLA was adapted from the Microsoft Contributor License -Agreement, which they generously made available to the public domain under -Creative Commons CC0 1.0 Universal. - -## Where can I learn more about the AGPL-3 license? - -Please refer to the official -“[Why the Affero GPL](https://www.gnu.org/licenses/why-affero-gpl.html)” and the -[FAQ page](https://www.gnu.org/licenses/gpl-faq.html) on -[GNU.org](https://www.gnu.org) for full details regarding this license. - -## Why does Forem have a CLA? - -The Contributor License Agreement (CLA) is a legal document in which you state -that you are entitled to contribute your code to the Forem codebase, and are -willing to have it used in distributions and derivative work. - -The CLA helps provide confidence to future users that they will be allowed to -use the Forem codebase without fear that a contributor will try to withdraw -permissions at a later date. - -## Am I giving away the copyright of my contributions? - -No. You are granting Forem/DEV a license to use and distribute your contribution -without further restriction, not assigning the copyright. - -## What if I have other questions? - -Please check out our main repository or send an email to -[yo@dev.to](mailto:yo@dev.to). diff --git a/docs/maintainers/deploying.md b/docs/maintainers/deploying.md deleted file mode 100644 index 35e50e207..000000000 --- a/docs/maintainers/deploying.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Deployment Guide ---- - -# Deploying Forem - -Anyone with the ability to merge PRs on GitHub can deploy the application. -**Whenever a PR is merged the code is deployed. When deploying complex code, be -sure that other team members are around to help if something goes wrong.** - -Generally, it's a good idea to keep the SRE team in the loop on high risk -deploys. However, deployments are our collective responsibility, so it's -important to monitor your deploys. You can see deployment status on -Travis-ci.com and in the #deployment-pipeline channel on Slack. Be prepared to -rollback or push a fix for any deployment! - -# Deployment and CI/CD Process - -## Overview - -Forem relies on GitHub and Travis to deploy continuously to Heroku. If a Pull -Request is merged it will automatically be deployed to production once the build -steps complete successfully. The process currently takes about 20 minutes to -complete and will need a few additional minutes before the change goes live. - -## Travis Stages - -The following stages can be explored in our -[.travis.yml](https://github.com/forem/forem/blob/main/.travis.yml) and -[Procfile](https://github.com/forem/forem/blob/main/Procfile). Our Travis CI -process consists of 2 stages. - -1. Running our test suite in 3 parallel jobs. -2. Deploying the application. - -### Stage 1: Running Tests - -In stage 1, we use [KnapsackPro](https://knapsackpro.com/) to divide our Rspec -tests evenly between 3 different jobs (virtual machines). This ensures that each -job takes relatively the same amount of time to run. After running our Rspec -tests, we then run a series of other checks. These additional checks are split -up between the different jobs. Here is a list of those additional checks that -are run. - -- Job 0 is where we run JavaScript tests, Preact tests, and coverage checks. -- Job 1 is where Travis builds Storybook to ensure its integrity, and where we - check for any known vulnerabilities using `bundle-audit`. -- Job 2 is where Travis fires up a Rails console to ensure the application loads - properly. - -If all of the jobs pass then we move on to Stage 2 of the Travis CI process. - -### Stage 2: Deploying - -If the build was kicked off from a pull request being created or updated this -stage will do nothing. If the branch has been merged into main, then this stage -will kick off a deploy. The deploy will run in its own job deploying our -application to Heroku. - -Prior to deploying the code, Heroku will run database migrations and do some -final checks (more information on that below) to make sure everything is working -as expected. If these all succeed, then the deploy completes and our team is -notified. - -## Deploying to Heroku - -We use Heroku's -[Release Phase](https://devcenter.heroku.com/articles/release-phase) feature. -Upon deploy, the app installs dependencies, bundles assets, and gets the app -ready for launch. However, before it launches and releases the app Heroku runs a -release script on a one-off dyno. If that release script/step succeeds the new -app is released on all of the dynos. If that release script/step fails then the -deploy is halted and we are notified. - -The name of the script we use is `release-tasks.sh` and its in our root -directory. During this release step we do a few checks. - -1. We first check the DEPLOY_STATUS environment variable. In the event that we - want to prevent deploys, for example after a rollback, we will set - DEPLOY_STATUS to "blocked". This will cause the release script to exit with a - code of 1 which will halt the deploy. This ensures that we don't accidentally - push out code while we are waiting for a fix or running other tasks. -2. We run any outstanding migrations. This ensures that a migration finishes - successfully before the code that uses it goes live. -3. We run any data update scripts that need to be run. A data update script is - one that allows us to update data in the background separate from a - migration. -4. Following updating all of our datastores we use the Rails runner to output a - simple string. Executing a Rails runner command ensures that we can boot up - the entire app successfully before it is deployed. We deploy asynchronously, - so the website is running the new code a few minutes after deploy. A new - instance of Heroku Rails console will immediately run a new code. - -![](https://devcenter0.assets.heroku.com/article-images/1494371187-release-phase-diagram-3.png) diff --git a/docs/maintainers/pull_requests.md b/docs/maintainers/pull_requests.md deleted file mode 100644 index 39026855b..000000000 --- a/docs/maintainers/pull_requests.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Pull Requests ---- - -# Pull Requests - -## General - -- We generally follow a branch naming convention of - `/-`, e.g. `sloan/make-things-awesome-5555`. - Issue numbers can be omitted when unavailable, e.g. for things like quick - fixes, spikes, experiments, etc. -- Push early and often, you don’t need to wait until you’re finished to get - feedback. Please use GitHub draft PRs when you have a work-in-progress (WIP) - PR, or when you have a PR that is contingent on something else to be merged. - We prefer draft PRs rather than adding "DO NOT MERGE" to a PR's title. Any PR - that is not a draft should be ready to be merged by anyone once it has been - reviewed. -- Please follow our pull request template. Provide context for reviewers, when - in doubt err on the side of too much information. -- Core team members are not required to review draft PRs. To explicitly request - feedback, please assign or mention people. - -## PR Reviews - -PR review is the Core Team's opportunity to weigh-in on changes before they go -into production. - -Keep in mind that our team is distributed across the world. It's a good idea to -leave far-reaching PRs open for a day, to give everyone a change to share their -thoughts. - -- We require 2 approvals from core team members for each PR: - - One from the same team because they have context and are working towards the - same goal as you. - - One from outside your team for the following reasons: - - A different perspective from someone who has less context - - To leverage our different strengths and garner additional insights - spreading knowledge and code exposure throughout the team - - To avoid overloading individuals -- Tag people that you’d like to review your PR using GitHub’s ‘Reviewers’ - function. -- Be kind! The goal here is to work together on shipping good code, not to judge - people. -- For serious issues, use Github’s “Request changes” feature. This should be - reserved for serious problems, e.g. - - Doesn’t do what the issue said - - Foreseeable performance problems - - Provable security issues - - Breaks existing functionality -- Everything else can be posted as a comment, but it’s up to the original PR - author whether or not they want to incorporate the changes. -- Please keep style discussions to an absolute minimum, that time is better - spent making a PR for the configuration of our various lint tools. -- If you make changes to your PR, please re-request feedback from previous - reviewers. - -# Merging Pull Requests - -At the time of writing, we tend to prefer squashing PRs into a single commit and -merging them. This is easily (and safely) achieved using the GitHub UI. - -All required checks such as CI and Code Climate should be green. - -Once a PR is merged, it might need to be deployed. Deployment is a team -responsibility, and everyone on the core team should be comfortable deploying -code. For more information, read the -[deployment guide](https://docs.forem.com/maintainers/deployment). diff --git a/docs/maintainers/readme.md b/docs/maintainers/readme.md deleted file mode 100644 index 79546a553..000000000 --- a/docs/maintainers/readme.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Maintainers Guide -items: - - pull_requests.md - - deploying.md ---- - -# Maintainer Processes - -This document contains basic instructions for the maintainers of the Forem -application. It's a work in-progress, but should allow the Forem Core Team to -document processes and strategies in a transparent way! diff --git a/docs/netlify.toml b/docs/netlify.toml deleted file mode 100644 index 99506d84b..000000000 --- a/docs/netlify.toml +++ /dev/null @@ -1,17 +0,0 @@ -[build] - command = "make" - [environment] - NETLIFY_USE_YARN = 1 - -# See for more options -[[redirects]] -from = "https://docs.dev.to" -to = "https://docs.forem.com" -status = 301 -force = true - -[[redirects]] -from = "https://docs.dev.to/*" -to = "https://docs.forem.com/:splat" -status = 301 -force = true diff --git a/docs/readme.md b/docs/readme.md deleted file mode 100644 index 9430c34c6..000000000 --- a/docs/readme.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -items: - - technical-overview - - installation - - getting-started - - contributing - - backend - - frontend - - admin - - design - - tests - - faqs.md - - troubleshooting.md - - licensing.md - - self-hosting.md - - maintainers - - component: Divider - - creators ---- - -# Welcome to Forem's developer documentation - -On this site you'll find instructions to setup a [local instance of -Forem][installation], documentation on the [architecture of -Forem][architecture], [how to contribute][contributing], and many other useful -documents. - -This documentation site is the product of a number of volunteer contributors -working alongside the Forem Core Team, special thanks to all those who have -contributed to the documentation. - -# Running the documentation locally - -Like Forem, this site is open source and the code is [hosted on GitHub][docs]. -If you find any incorrect information, or a even a typo, we'd love to see a pull -request. - -Forem's documentation is built with [GitDocs NodeJS library][gitdocs]. - -To start the gitdocs server, you should run `yarn gitdocs serve` from the root -of the `forem` project or from the `/docs` directory. - -```shell -yarn gitdocs serve -``` - -This will start a server where you can browse the documentation: - - -If you add new pages or rename existing pages, you'll need to restart the server -for those changes to take effect. - -# Contributing to the docs - -If you're looking for more information on contributing, check out the -[Contributing guide][contributing]. - -[installation]: /installation/ -[architecture]: /technical-overview/architecture/ -[contributing]: /contributing/ -[docs]: https://github.com/forem/forem/tree/master/docs/ -[gitdocs]: https://www.npmjs.com/package/gitdocs/ diff --git a/docs/self-hosting.md b/docs/self-hosting.md deleted file mode 100644 index 62700e6a0..000000000 --- a/docs/self-hosting.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Self Hosting Forem ---- - -## Hosting your own Forem instance - -Visit [the official Forem Self-Host playbook](https://github.com/forem/selfhost) -in order to host on DigitalOcean, AWS, Google Cloud, or bare metal. - -If you intend to stand up a Forem, we _strongly_ encourage you to join -[forem.dev](https://forem.dev) to take part and keep up with changes. 🌱 diff --git a/docs/technical-overview/ab_testing.md b/docs/technical-overview/ab_testing.md deleted file mode 100644 index 610fc7f49..000000000 --- a/docs/technical-overview/ab_testing.md +++ /dev/null @@ -1,60 +0,0 @@ -# A/B testing - -We use the [Field Test](https://github.com/ankane/field_test) gem for conducting -simple A/B tests. - -If you want to propose an A/B test of a feature, you may make a pull request -which defines the hypotheses and what admins should look for to declare a -winner. As A/B tests are going to have results that may differ from Forem to -Forem, the process is relatively immature. In the future we may have more -studies that can return anonymous ecosystem-wide results. - -A/B tests are inherently the most useful in _large_ Forems, where qualitative -feedback may be more useful on small Forems. As such, [DEV](https://dev.to) is -our largest Forem and therefore can provide us with the most feedback for our -existing A/B tests. However, we must keep in mind that DEV results may not apply -well to future large Forems. We should seek to re-run useful experiments within -the ecosystem after time has passed. - -## Creating a new A/B test - -Follow the guidelines of the field test gem and add the test info to -[config/field_test.yml](https://github.com/forem/forem/blob/main/config/field_test.yml). - -Then where you want to trigger the variant, you'll add some code like this: - -```ruby - test_variant = field_test(:follow_implicit_points, participant: user) - case test_variant - when "no_implicit_score" - 0 - when "half_weight_after_log" - Math.log(occurrences + bonus + 1) * 0.5 - when "double_weight_after_log" - Math.log(occurrences + bonus + 1) * 2.0 - when "double_bonus_before_log" - Math.log(occurrences + (bonus * 2) + 1) - when "without_weighting_bonus" - Math.log(occurrences + 1) - else # base - Our current "default" implementation - Math.log(occurrences + bonus + 1) # + 1 in all cases is to avoid log(0) => -infinity - end -``` - -Which would find or create the test variant for that user in particular. If this -code is not called in the controller or view, you'll need to first include the -gem helpers at the top of the file... - -``` -include FieldTest::Helpers -``` - -To record a successful field test outcome, you should call something like this - -```ruby - Users::RecordFieldTestEventWorker - .perform_async(user_id, :follow_implicit_points, "user_creates_reaction") -``` - -And modify that class as needed to determine whether to record the successful -trial. diff --git a/docs/technical-overview/architecture.md b/docs/technical-overview/architecture.md deleted file mode 100644 index 6c0bee3cf..000000000 --- a/docs/technical-overview/architecture.md +++ /dev/null @@ -1,237 +0,0 @@ -# A few high-level things to know - -## We are a Ruby on Rails app - -Ruby on Rails is a web framework heavy on conventions over configuration. All -else equal, we should try to follow Rails convention. We are currently on -version 6.x.x. - -## We cache many content pages on the edge - -To decrease loading time, we use edge-caching extensively. Taking advantage of -edge-caching means that we do not go all the way to the server to render every -page. However this means that, on cached pages, we don't have access to helper -methods like `current_user`. A page is edge-cached through our CDN -([Fastly][fastly]) if the controller contains this line for the relevant action: - -``` -before_action :set_cache_control_headers -``` - -We also use server-side caching: [Rails caching][rails_caching]. If you see -`Rails.cache` or `<%= cache ... %>`, this is code affected in production by -caching. - -## Content precision - -In some situations we may want more precise content than in others. Often when -we do not need a precise number, it offers an opportunity to either estimate the -content or bust the cache less frequently. - -### Examples - -- We use the `estimated_count` for a more efficient query of registered users on - the home page. We have deemed that this is probably close enough. -- On posts and comment trees without recent comments, we do not asynchronously - fetch the absolute latest individual reaction counts for logged-out users - because this number is likely to be correct without the async call, and if it - is off-by-one, we can make the choice that it is not important that it be more - precise than this. - -## We Mostly defer scripts for usage performance improvements - -To avoid blocking the initial render, we use the `defer` attribute to accelerate -page renders. This practice results in a faster page load, and doesn't leave -users waiting on heavy assets. However, this practice limits our ability to -manipulate layout with JavaScript. As a rule, you should avoid relying on -JavaScript for layout when working on Forem. - -We have also experimented with different techniques involving inline CSS - -## We attempt to reduce our bundle size - -We use [PreactJS](/frontend/preact), a lightweight alternative to ReactJS, and -we try to reduce our bundle size with -[dynamic imports](/frontend/dynamic-imports). - -## Worst technical debt - -The most widespread elements of technical debt in this application reside on the -frontend. We use both the "old" approach (files in the `/assets` folder) and -"new" approach (files in the `app/javascript` folder) for loading JavaScript -into our Rails app. - -We also have overgrown and inconsistent CSS. This is an area we'd love to see -contributions from the community. - -We also have inconsistencies and issues with how we bust caching on the edge. -Ideally, we could practice resource-based purging as described in the [Fastly -Rails][fastly_rails] docs, but we bust specific URLs via `EdgeCache::Bust#call`. - -## The algorithm behind the feed - -The home feed is based on a combination of recent collective posts that are -cached and delivered the same to everyone in the HTML, and additional articles -fetched from a PostgreSQL Full Text Search index after page load. To determine -which posts a user sees, they are ranked based on the user's followed tags, -followed users, and relative weights for each tag. Additional fetched articles -also follow this general pattern. - -Currently, the top post on the home feed, which must have a cover image, is -shared among all users. - -## Inter-page navigation - -Forem uses a variation of "instant click", via -[InstantClick](/frontend/instant-click), which swaps out page content instead of -making full-page requests. This approach is similar to the one used by the Rails -gem `Turbolinks`, but our approach is more lightweight. The library is modified -to work specifically with this Rails app and does not swap out reused elements -like the navigation bar or the footer. The code for this functionality is -viewable in `app/assets/javascripts/base.js.erb`. - -There are a few caveats regarding this approach. Using our approach means a -non-trivial amount of functionality is reloaded on page change. A similar amount -of reloading occurs when using `window.InstantClick.on('change', someFunction)`. -This results in code that looks something like this: - -```javascript -initPreview(); -window.InstantClick.on('change', initPreview); -``` - -In some circumstances, this practice means the developer should pay special -attention to the declaration of variables and functions. JavaScript may behave -differently than expected. - -Abstracting and removing these caveats is a long term goal, and contribution on -that front is welcome! - -We use the parameter `i=i` (i for internal) to indicate to the backend that we -only want the "internal" version of the page (the one without the top nav and -footer, etc.) - -## URLS and constraints - -Because we use the top directory for user-generated pages, we need to be aware -of some constraints. `some-forem.com/sophia` could be a user, a page, an -organization, or a previously banished user. We allow users to retain two -redirects and should use `:moved_permanently` when a user changes their -username. - -Because we may silently insert `?i=i` on the frontend to indicate internal nav, -we need to maintain that parameter if we are redirecting. We use the method -`redirect_permanently_to(location)` to encompass all of this behavior. - -# General app concepts - -## Articles (or posts) - -Articles are the primary form of user generated content in the application. An -Article has many comments and taggings through the acts-as-taggable gem, belongs -to a single user (and possibly an organization), and is the core unit of -content. - -## Collections (or series) - -Although the source code refers to them as "collections" groups of articles are -referred to, throughout the user interface, as "series". They represent a -collection of articles relating to the same topic, indeed, a series. - -## Comments - -Comments belong to articles or other content (they are generally polymorphic). -They belong first and foremost to the user in our design, which is reflected by -the URL (`/username/tag-slug`), but they are present in communal areas of the -application. They are threaded, but they flatten out gradually to avoid -infinitely branching threads. - -## Users - -The user is the authorization/identity component of logging into the app. It is -also the public profile/authorship/etc. belonging to the people who use the app. - -While "user" is a perfectly good technical name, it is a fairly cold way to -refer to humans, so we should prefer labeling people as members, or by their -name/username. - -## Tags - -Tags are used to organize user generated content. Each tag has a set of rules -which are used for moderation. Each tag is a de facto community complete with -community moderators. - -Some tags behave as "flare," highlighting certain articles when viewed from the -index page. Tags that act as "flare" are defined in the `FlareTag` object. In -cases of multiple flare tags, the tag displayed is determined by its hierarchy. - -## Listings - -Listings are classified ads. They are similar to posts in some ways, but with -ore limitations. They are designed to be categorized into market areas. They -also make use of tags. - -## Credits - -Credits are the currency of the platform which users can use to buy listings. -The functionality of credits may be expanded in the future. - -## Organizations - -Users can belong to organizations, which have their own profile pages where -posts can be published etc. This can be any group endeavor such as a company, an -open source project, or any standalone publication on Forem. - -## Reactions - -Hearts, unicorns, and bookmarks. Reactions are the medium for displaying -appreciation for content. Bookmarks have the unique functionality of saving an -article in the user's reading list. - -## Follows - -How a user keeps track of the tags, users, or articles they care about. Follows -impact a user's home feed and notifications. - -Follows can have a "score" which indicates how much a user wants to see the -element in their feed. Currently we only calculate these for tag follows, but it -could be expanded to users. The user can set an "explicit" score, and the system -also calculates an "implicit" score based on their activity. - -## Roles - -Through the "rolify" gem, users can have roles like "admin", etc. A role can -also be associated with a model or a model instance. Such as "moderator of -javascript tag" - -## Organization - -An organization is a collection of users who can author under one umbrella. An -organization could be a company or perhaps just a publication on-site. - -## Notes - -Notes are an internal tool admins can use to leave information about things. -Example: "This user was warned for spammy content". - -## Pages - -`Pages` in the [admin dashboard](/admin/) represent static pages to be served on -the site. Admins are in full control to create and customize them to their needs -using markdown or custom HTML. Pages are configured with a `slug` and they will -be served on either the `/page/slug` or `/slug` path. - -In order to ease development of custom HTML Pages in local environments the rake -task `pages:sync` is available. It will listen to changes made to a local HTML -file and sync its contents to an existing Page in the database with the matching -`slug`. - -Example: `rake pages:sync[slug,/absolute/path/to/file.html]` - ---- - -This is far from a complete view of the app, but it covers a few core concepts. - -[fastly]: https://www.fastly.com/ -[rails_caching]: https://guides.rubyonrails.org/caching_with_rails.html -[fastly_rails]: https://github.com/fastly/fastly-rails diff --git a/docs/technical-overview/compatibility.md b/docs/technical-overview/compatibility.md deleted file mode 100644 index 45b01568e..000000000 --- a/docs/technical-overview/compatibility.md +++ /dev/null @@ -1,33 +0,0 @@ -# Compatibility - -To go along with effective administration and putting user security and -well-being first, for a Forem to be most useful, it maximizes its technical -compatibility. - -Compatibility means: - -- Staying updated. We need to maintain overall compatibility by keeping the - ecosystem close to the latest version as proactively as we can. -- Maintaining all programmatic interfaces, whether they be the - [API](https://api.forem.com) or Forem meta tags which can be consumed for - Forem validation. -- Maintaining human interfaces which allow users to find where they need to go - and conduct all necessary customizations. -- Maintaining great performance such that the web-based Forem ecosystem can - provide a great experience in all network conditions and in comparison to more - closed ecosystems. - -## Meta tags - -The canonical meta tags which are expected to be present as a component of -validation are as follows: - -```html - - - -``` - -This list may evolve over time. If you want to propose a new meta tag which -could improve the efficacy of an ecosystem app, please feel free to open an -issue or a discussion on [forem.dev](https://forem.dev). diff --git a/docs/technical-overview/feature_flags.md b/docs/technical-overview/feature_flags.md deleted file mode 100644 index 9e34b8f72..000000000 --- a/docs/technical-overview/feature_flags.md +++ /dev/null @@ -1,91 +0,0 @@ -# Feature flags - -We sometimes employ feature flags to develop features that aren't fully formed -at the moment of deployment. They can also be employed to roll out features in -production incrementally. - -Feature flags are meant to be temporary and part of a rollout plan resulting in -their removal. - -## Creating a new feature flag - -To create a new feature flag, we use -[data update scripts](/backend/data-update-scripts) so that they can be made -available over the entire Forem fleet, for example: - -```shell -bundle exec rails g data_update AddAwesomeAlgorithmFeatureFlag -``` - -This will generate a script and its spec. Once done, you can add the new feature -flag like this: - -```ruby -module DataUpdateScripts - class AddAwesomeAlgorithmFeatureFlag - def run - FeatureFlag.add(:awesome_algorithm) - end - end -end -``` - -and then start using it right away. - -## Guarding a feature behind a flag - -Once the feature flag is added, you can start using it to hide the feature -behind a boolean flag: - -```ruby -if FeatureFlag.enabled?(:awesome_algorithm) - # call the new code -else - # call the previous code -end -``` - -or, for example in a view: - -```erb -<% if FeatureFlag.enabled?(:blue_button) %> - <%= render "blue_button" %> -<% else %> - <%= render "good_old_button" %> -<% end %> -``` - -## Enabling/disabling a feature flag globally - -As mentioned, feature flags can be used to test a work in progress feature or to -test a new approach directly in production. - -To enable such a feature: - -- Log in to the Forem -- Go to `/admin/feature_flags` (it requires the - [`tech_admin` role](/backend/roles)) -- Click on the flag you want to enable and press "Fully Enable". - -![A screenshot of the Admin Feature Flag Panel](/admin_feature_flags.png) - -## Removing a feature flag - -Once the feature has been validated and finalized or discarded, please remember -to remove its flag with a final data update script, for example: - -```shell -bundle exec rails g data_update RemoveAwesomeAlgorithmFeatureFlag -``` - -```ruby -module DataUpdateScripts - class AwesomeAlgorithmFeatureFlag - def run - FeatureFlag.remove(:awesome_algorithm) - end - end -end -``` - -This will ensure that the feature will be removed from all Forems. diff --git a/docs/technical-overview/feed.md b/docs/technical-overview/feed.md deleted file mode 100644 index 04fdfbe78..000000000 --- a/docs/technical-overview/feed.md +++ /dev/null @@ -1,38 +0,0 @@ -# "The feed" - -The Forem feed is perhaps _the_ core functionality of the service. It's an -adaptation of a concept popularized by other social platforms in the past two -decades, and it is something we need to develop with care in a way that empowers -individual communities and users. - -The core nature of "the feed" is that it needs to evolve and be flexible. We -will learn new ideas over time. We need to take into account metrics, but also -question the relevance and "goodness" of certain metrics. We want folks finding -fulfilling and enriching content, not necessarily addictive content. - -However, we are in the fairly naive early days of the feed, so primarily it is a -matter of flexibility and experimentation. - -### Feed style - -Each Forem can have a feed style set by the admin of that community (originally -implemented [in a PR from mid-2020](https://github.com/forem/forem/pull/8721)). - -Currently, we have two styles: `rich` and `basic`. Where `rich` always displays -the cover image in the feed, `basic` hides it from the feed view. - -Over time, we'll improve and expand our feed style options. - -### Feed strategy - -Each Forem can have a feed strategy set by the admin of that community -(originally implemented -[in a late-2020 PR](https://github.com/forem/forem/pull/10245)). Currently, we -have two strategies: `basic` and `large_forem_experimental`. The "experimental" -component dictates that there is some split testing, but generally these are -just cues for an underlying algorithm which can change liberally. - -The feed endpoint is driven by the `feeds_controller` and the content is found -in objects such as `Articles::Feeds::Basic`. We should lean toward adaptability -and versatility in the long run here, even if we are just at the beginning of -this transparent journey. diff --git a/docs/technical-overview/readme.md b/docs/technical-overview/readme.md deleted file mode 100644 index b1e3e0d6f..000000000 --- a/docs/technical-overview/readme.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -items: - - stack.md - - architecture.md - - feed.md - - compatibility.md - - ab_testing.md - - feature_flags.md ---- - -# Technical Overview - -We are a [Ruby on Rails](https://rubyonrails.org) web application. - -Our [stack][stack] is composed of many tools and services. - -You can read more about our architecture and app's concepts here: [A few -high-level things to know][architecture]. - -[stack]: /technical-overview/stack -[architecture]: /technical-overview/architecture diff --git a/docs/technical-overview/stack.md b/docs/technical-overview/stack.md deleted file mode 100644 index 78a0a406d..000000000 --- a/docs/technical-overview/stack.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Stack ---- - -## 🔑 Key App tech/services - -For the Forem tech stack we use: - -- [_Puma_](https://github.com/puma/puma) as the web server -- [_PostgreSQL_](https://www.postgresql.org/) as the primary database and for - Full Text Search -- [_Redis_](https://redis.io/) to store cached data -- [_Fastly_](https://www.fastly.com/) for - [edge caching](https://dev.to/ben/making-devto-insanely-fast) -- [_Cloudinary_](https://cloudinary.com/) and/or - [_Imgproxy_](https://github.com/imgproxy/imgproxy) for image - manipulation/serving -- [_Honeybadger_](https://www.honeybadger.io/) for error monitoring -- [_Sidekiq_](https://github.com/mperham/sidekiq) and - [_Active Job_](https://guides.rubyonrails.org/active_job_basics.html) for - background workers -- [Ransack](https://github.com/activerecord-hackery/ransack) for internal search -- [_Redcarpet_](https://github.com/vmg/redcarpet) and - [_Rouge_](https://github.com/jneen/rouge) to parse Markdown -- [_Carrierwave_](https://github.com/carrierwaveuploader/carrierwave), - [_Fog_](https://github.com/fog/fog-aws) and - [_AWS S3_](https://aws.amazon.com/s3/) for image upload/storage -- [_InstantClick_](http://instantclick.io/) (a modified version) instead of - _Turbolinks_ to accelerate navigation -- [_ImageMagick_](https://imagemagick.org/) to manipulate images on upload -- [_Heroku_](https://www.heroku.com) for hosting -- [_Sendgrid_](https://sendgrid.com/) for transactional mailing -- [_Mailchimp_](https://mailchimp.com/) for marketing/outreach emails -- [_CounterCulture_](https://github.com/magnusvk/counter_culture) to keep track - of association counts (counter caches) -- [_Rolify_](https://github.com/RolifyCommunity/rolify) for role management -- [_Pundit_](https://github.com/varvet/pundit) for authorization to proxy - traffic -- [Preact](https://preactjs.com/) for some of the frontend. See - [the Frontend Guide](/frontend) for more info -- [_Pusher_](https://pusher.com) for realtime communication between the - application and users' browsers -- [_GitDocs_](https://github.com/timberio/gitdocs) for beautiful and - SEO-friendly documentation -- [Git](https://git-scm.com/) for version control -- [GitHub](https://github.com/) for hosting the source code and issue tracking - -_This list is non-exhaustive. If you see something that belongs here, feel free -to add it._ diff --git a/docs/tests/acceptance-tests.md b/docs/tests/acceptance-tests.md deleted file mode 100644 index 69739d37a..000000000 --- a/docs/tests/acceptance-tests.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Acceptance Tests ---- - -# Acceptance Tests - -Acceptance tests are tests from the perspective of the end-user. - -In the Rails world, we sometimes refer to these as Feature or System tests. A -tool called Capybara is included to help us simulate a human's actions inside of -our tests. - -Generally, we are simulating what a user could do from their web browser and -ensuring that the app behaves as intended. When a feature is heavily reliant on -interaction from a user via the browser, it's a good idea to write automated -Acceptance tests to uncover any bugs that might not be apparent from manual -testing. - -It's important to note that Rails System tests can be fairly slow, so it's -better to focus on testing core functionality or pieces of your code that you -think might be prone to regressions. Another strategy we use to help us keep -acceptance tests fast is `:aggregate_failures`. `:aggregate_failures` allows us -to make multiple assertions within a single test. The flag signals to Rspec to -run each assertion and then report all of the failures back to us rather than -just the first failure. This saves time because we only have to setup the -conditions for the spec once and then make all of our assertions instead of -setting up the conditions repeatedly for each individual assertion. - -Acceptance tests can be found in the directory `spec/system`. - -You can run all acceptance tests with: - -```shell -bundle exec rspec spec/system -``` - -To run an individual file you can use: - -```shell -bundle exec rspec spec/system/user_views_a_reading_list_spec.rb -``` - -To run a specific test case you can use: - -```shell -bundle exec rspec spec/system/user_views_a_reading_list_spec.rb:10 -``` - -where `10` is the line number of the test case that you want to execute. - -You can read the official guide -[Testing Rails Applications](https://guides.rubyonrails.org/testing.html#system-testing) -to learn more. diff --git a/docs/tests/accessibility-tests.md b/docs/tests/accessibility-tests.md deleted file mode 100644 index 5d7fc9e0f..000000000 --- a/docs/tests/accessibility-tests.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Accessibility Tests ---- - -# Accessibility Tests - -Accessibility testing is a form of automated and manual testing that helps us -identify some of the potential accessibility concerns on Forem. See also, the -[Forem Frontend Accessibility docs](https://docs.forem.com/frontend/accessibility/). - -Many accessibility (a11y) issues are not obvious to everyone who contributes to -the Forem project, therefore leaning on tools to help us identify these issues -is a good practice. - -It's a good idea to use browser plugins while you're developing to keep an eye -out for these issues, as well as including automated tests to catch regressions -in future changes. - -The [axe devtools](https://www.deque.com/axe) extension is a great place to get -started. It works in both Firefox and Chrome. Use an extension like this one to -find potential a11y issues in your workflow. - -## Automated testing in Preact - -An overarching a11y testing strategy isn't currently in place for the Forem -application, but there are some automated tools you can take advantage of in -this project. - -It is important to note that automated accessibility testing is only effective -at finding ~30% of accessibility issues. It's important to do manual a11y -testing as well. - -When you're writing Preact components, you can include some basic a11y testing -in your unit tests with [jest-axe](https://github.com/nickcolley/jest-axe). - -If you're still curious -[there are some great talks on accessibility for developers](https://www.youtube.com/watch?v=8E9AEZjglqI). - -## PR Review Checklist - -Pull Requests should include accessibility testing to prevent barriers from -making it into the codebase. Sometimes issues found may be out of scope for a -particular PR – those can be opened as separate issues to be followed up on. - -Test the functionality in Forem-supported browsers for accessibility impact: -Chrome and Firefox were popular for Windows screen reader users in 2019 -[according to WebAIM](https://webaim.org/projects/screenreadersurvey8/#browsers). -Safari is the most common choice for Voiceover users on the Mac, even if Chrome -is widely used for development. Mobile browsers are worth checking, too. - -1. Keyboard: navigate the page without using a mouse or trackpad. - - Can you reach and operate the interactive controls like menus, buttons, and - other widgets? - - Can you see your focus point on the screen, and does the focus style have - adequate contrast? - - Does your focus point get lost or hidden behind any layers with items - needing to be disabled/hidden? -1. Run a browser extension. - - Use [axe](https://deque.com/axe), - [Accessibility Insights](https://accessibilityinsights.io), Chrome's - Lighthouse Audit, or - [WAVE](https://chrome.google.com/webstore/detail/wave-evaluation-tool/jbbplnpkjmmeebjpijfedlgcdilocofh) - to run accessibility tests in the DevTools. - - Prioritize relevant, higher-impact violations and issues first. -1. Test color contrast. - - Pay extra attention to color contrast findings in your browser extension - tests, since it's the most common accessibility issue on the internet. - - The - [Chrome color picker with contrast ratio line](https://developers.google.com/web/tools/chrome-devtools/accessibility/reference#contrast) - and - [WebAIM contrast checker](https://webaim.org/resources/contrastchecker/) - are helpful tools for tweaking colors to meet - [WCAG requirements](https://webaim.org/articles/contrast/). - -### Additional accessibility tests for PR reviews - -1. Screen reader testing - - Get feedback from people who use screen readers regularly if at all - possible. - - Understand that if you're a new screen reader user, there might be a - learning curve that can impact your results. - - Navigate through a UI change using a screen reader such as Mac - [Voiceover with Safari](https://webaim.org/articles/voiceover/), and - [NVDA](https://webaim.org/articles/nvda/) with Firefox or Chrome on - Windows. -1. Zoom and magnification - - In the web browser, try zooming in from 200% to 500%. - - Would the layout or change of functionality be impacted by someone needing - to magnify their screen? Are there alternative styling or other solutions - that would make zooming any easier? diff --git a/docs/tests/code-coverage.md b/docs/tests/code-coverage.md deleted file mode 100644 index a368f8a3b..000000000 --- a/docs/tests/code-coverage.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Code Coverage ---- - -# Code coverage - -## Rails - -Rspec will generate code coverage at the end of the tests. - -To get the code coverage of the entire Rails codebase, you must run the full -Ruby test suite. You can run the full test suite with the `rspec` command: - -```shell -bundle exec rspec -``` - -or - -```shell -bin/rspec -``` - -To get the code coverage of a single file, you can run: - -```shell -bundle exec rspec spec/models/user_spec.rb -``` - -or - -```shell -bin/rspec spec/models/user_spec.rb -``` - -To get the code coverage of a particular spec in a single file, append the -line-number for that spec: - -```shell -bundle exec rspec spec/models/user_spec.rb:24 -``` - -or - -```shell -bin/rspec spec/models/user_spec.rb:24 -``` - -Once your tests have completed, the `coverage/index.html` will be regenerated -with some stats concerning the overall health of our test suite including a code -coverage metric. - -A few things to note: - -- "Coverage" indicates whether or not the test suite runs through the code in - question. It does not equate to actually testing for functionality, and - shouldn’t be thought of that way. -- Running Rspec in general will overwrite the existing `coverage/index.html` so, - if you want to reference the results of a particular run, save a copy of the - file before re-running the test suite. - -To turn off coverage report generation please set environment variable -`COVERAGE` value to `false`. - -## Preact - -Preact tests will generate code coverage at the end of the tests. - -To get the code coverage of the Preact codebase, you must run the full JS test -suite. You can run the full test suite with the npm task `test`: - -```shell -npm run test -``` - -or - -```shell -yarn test -``` - -Once the tests have completed, the test coverage metric will be visible in the -terminal window. Please note that jest will fail if test coverage thresholds are -not met. diff --git a/docs/tests/codeclimate.md b/docs/tests/codeclimate.md deleted file mode 100644 index acf810198..000000000 --- a/docs/tests/codeclimate.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Code Climate ---- - -# Code Climate - -We are using [Code Climate](https://codeclimate.com/github/forem/forem) to track -code quality and coverage. - -Code Climate offers metrics regarding code quality for each individual PR, -however, it does not calculate these metrics for the entirety of the project. If -you'd like update the current linting rule, feel free to submit a PR to change -it. - -Before merging a PR to Forem, we expected Code Climate to pass on that PR. If -you find Code Climate raising errors on your PR, please fix those issues. Do -your best to leave code in a better state than you found it! - -We don't want to make a habit of pandering to Code Climate and its metrics -blindly, so if you're in doubt regarding a suggestion on your PR please start a -conversation in the PR comments. - -Generally speaking, if you're looking for opportunities to contribute to the -project, but you don't have an issue you're interested in solving, improving the -Code Climate metrics is a good place to start. We're happy to see PRs that -refactor existing code to reduce duplication and increase readability, given -that those refactors are well tested. diff --git a/docs/tests/e2e-tests.md b/docs/tests/e2e-tests.md deleted file mode 100644 index 015697473..000000000 --- a/docs/tests/e2e-tests.md +++ /dev/null @@ -1,342 +0,0 @@ ---- -title: End to End Tests ---- - -# End to End Tests - -We use [Cypress](https://www.cypress.io), a JavaScript based framework, for end -to end (E2E) testing. You can find tests and associated utilities in the -`cypress` directory: - -``` -cypress -├── fixtures (Any hard-coded data, e.g. test users, images) -├── integration (The actual tests, grouped by user flow) -├── plugins (Cypress plugins) -└── support (Where custom commands are found and added) -``` - -## Additional tools used - -We enhance our use of Cypress with a couple of additional packages. - -### cypress-testing-library - -We use -[cypress-testing-library](https://github.com/testing-library/cypress-testing-library) -for custom Cypress commands and utilities to improve how we write our tests. -This package is part of the [Testing Library](https://testing-library.com) -family that we also use in [front-end tests](/tests/frontend-tests), offering a -similar API. - -### cypress-rails - -We use the [cypress-rails](https://github.com/testdouble/cypress-rails) gem to -start a test web server that runs a rails test environment (`RAILS_ENV=test`). - -It also resets the database between test runs by starting a database transaction -at the beginning of a test and performs a rollback at the end of a test being -run. The cypress-rails gem also provides a rake task that allows us to -coordinate all this work. - -## How to run E2E tests locally - -### 1. From the command line, run `yarn e2e` - -Note: If you want to run E2E tests for the creator onboarding flow, you can run -`yarn e2e:creator-onboarding-seed`. - -Some initial setup and checks will automatically run as part of this command: - -- `bundle check`: You will be prompted to run `bundle install` if gems for the - project are not up to date. -- `yarn install`: will ensure front-end packages are up to date. - -### 2. You will then be prompted to set up the end to end (E2E) test database - -``` -Do you need to set up your end to end (E2E) testing database? - -Answer yes if this is your first time running E2E tests on your local machine or you need to recreate your E2E test database. (y/n) -``` - -Type `y` if you need to install the E2E test database. Typically you only need -to do this the first time you run e2e tests, but you can also run it if: - -- you have added additional seed data to `seeds_e2e.rb` -- your data based might be corrupted and you want to reset it back to its - original state - -### 3. Ready to run tests! - -The -[Cypress test runner](https://docs.cypress.io/guides/core-concepts/test-runner.html#Overview) -will open and you are now ready to run end to end tests. - -While the test runner is open, any new or updated tests will be dynamically -reflected in the UI. - -![A screenshot of the Cypress test runner](/cypress-test-runner.png) - -## E2E Tests on CI/CD - -E2E tests automatically run on a dedicated build node on Travis. It runs -headless via the `bin/e2e-ci` command. These tests currently do not run in -parallel with Knapsack Pro as there were issues integrating the cypress-rails -gem with the -[knapsack-pro-cypress](https://github.com/KnapsackPro/knapsack-pro-cypress) npm -package. - -## Writing Cypress tests - -### Seed data - -When the E2E test database is set up (via the `yarn e2e` command), it is seeded -with the data in -[`spec/support/seeds/seeds_e2e.rb`.](https://github.com/forem/forem/blob/816855ce3b1c49eaa38f65c63878b33228b1ee9f/spec/support/seeds/seeds_e2e.rb) - -This seeds file can be added to as needed, and the new data will be reflected -when you next run `yarn e2e` and select `y` to the question "Do you need to set -up your end to end (E2E) testing database?". - -### Test setup - -Any individual test setup steps can be included in the `beforeEach` hook. You -will almost always want to call the -[custom Cypress command](https://docs.cypress.io/api/cypress-api/custom-commands.html): - -```js -cy.testSetup(); -``` - -This makes sure that previous cookies are cleared, and the Rails database state -is reset (e.g. clearing any articles or changes made in previous tests). - -Some other useful custom commands for setting up tests include: - -- **`cy.loginAndVisit(user, url)`**: Logs in the given user and navigates to the - URL, waiting for any user login side effects to complete. -- **`cy.loginUser(user)`**: Logs in the given user, without routing to any page. - This is handy if you need to complete any other setup steps before visiting - the page under test. -- **`cy.createArticle(articleData)`**: Creates an article for the currently - logged in user. The response returns the URL path to the new article, e.g: - `response.body.current_state_path` -- **`cy.visitAndWaitForUserSideEffects(url)`**: Visits the given page and waits - for any user related network requests to complete to make sure the UI is in a - 'ready' state for testing. Particularly useful if you couldn't use - `cy.loginAndVisit`. -- **`cy.signOutUser()`**: Logs out the current user and returns to the home - page, waiting on any side effects completing. - -You can -[see all custom commands in the Cypress support.commands.js file](https://github.com/forem/forem/blob/d21a5d8ed4501d19c4f499013081b212cc8dd97f/cypress/support/commands.js) - -### Finding elements - -In almost all cases, we use -[cypress-testing-library](https://github.com/testing-library/cypress-testing-library) -commands to find elements in tests. - -The most robust way to do this is to find by role and accessible name, e.g.: - -```js -cy.findByRole('button', { name: 'Log in' }); -``` - -We favor `findByRole` queries where possible because: - -- It is more specific and reliable than e.g. `cy.findByText('Log in')` - - narrowing our selector to only buttons helps us make sure we match with the - correct element. -- It will only return accessible elements. For example, any element with - `display: none` or similar property that would stop a user from perceiving or - interacting with the element will not be returned. -- It draws attention to problematic HTML that could impact users of assistive - technology. For example, if the "Log in" button was actually a `div`, it won't - be returned by the above selector. -- It can help highlight issues with accessible names. For example, if - `cy.findByRole('link', { name: 'Profile' })` returns 10 links for different - profiles, we can readily identify an accessiblity issue where screen reader - users would not be able to differentiate between the links. - -#### Scoping selectors - -Cypress allows for a few methods to scope our element selectors to specific -sections of the page. Scoping to a smaller area of the page can allow us to -select elements more easily, and focus in on the area of the app under test. - -##### Chaining - -One way to scope your selector is to chain it off of a previous selector. For -example, the below code will find the article link contained within the `
    ` -element, ignoring any similar links the header, etc: - -```js -cy.findByRole('main').findByRole('link', { name: 'My article' }); -``` - -This is particularly useful if you only need to find a single element in the -given section of the page. - -##### Using the `within` callback - -Another way to scope your selectors is by using the `within` method. This scopes -any selectors in the callback to the given element, and can be particularly -useful if you want to conduct all of your test steps within the same container. - -For example, the below code will find the "profile preview" card, and then scope -all queries to that card alone, ignoring any other content on the page: - -```js -cy.findByTestId('profile-preview-card').within(() => { - cy.findByRole('link', { name: 'User profile' }); - cy.findByRole('button', { name: 'Follow' }); -}); -``` - -#### Best practice in selecting elements - -We tend to follow the -[testing-library guiding principles](https://testing-library.com/docs/guiding-principles) -for selecting elements: - -> The more your tests resemble the way your software is used, the more -> confidence they can give you. - -You can -[find the suggested priority order of testing-library queries on their website](https://testing-library.com/docs/queries/about#priority), -but as a general rule, we try to favor queries which are accessible to -everyone - i.e. how would a user find a "Log in" button? They'd look for a -button with the name "Log in", so `cy.findByRole('button', { name: 'Log in' })` -seems like a good fit - -Avoid selecting elements by classname or any other property that our users -wouldn't be aware of. If you need to find an element that doesn't have an -obvious semantic HTML or accessible name query, then give your element a -`data-testid` and use `cy.findByTestId('my-element')` to find it in your test. -This should be a last resort, and will likely be most useful for scoping -selectors. - -For further reading, check out -[Kent C. Dodd's article on making UI tests resilient to change](https://kentcdodds.com/blog/making-your-ui-tests-resilient-to-change). - -## Common gotchas - -We've noticed some common "gotchas" that can cause flakiness in our Cypress -tests. - -### 1. Route changes should be followed by a unique selector - -If the page changes, for example if your test steps click on a link to an -article, then it's important to make your next selector unique to the new page. -This makes sure that Cypress doesn't find a matching element on the page you -just left. - -See the examples below of how to make these route changes more robust. - -#### 🚫 Before: Route changes, but we find the `main` element on the previous page - -```js -cy.findByRole('main').findByRole('link', { name: 'Test article' }).click(); -// After clicking the link we can _sometimes_ accidentally get a reference to the 'main' element on the page we just left -cy.findByRole('main').findByRole('button', { name: 'Share post' }); -// Cypress fails to find the 'Share post' button inside the previous page's `main` element, and the test fails -``` - -#### ✅ After: Route changes, and we find a unique element before proceeding - -```js -cy.findByRole('main').findByRole('link', { name: 'Test article' }).click(); -// The 'Share post' button doesn't exist on the page we just left, so Cypress will wait for it to be shown on the new page -cy.findByRole('button', { name: 'Share post' }); -``` - -### 2. Interactive elements must be initialized before clicking - -In a lot of places we present views in Rails-generated HTML and asynchronously -attach JavaScript event listeners after the page has loaded. This means that in -an automated test environment it is possible to click a button before its click -handler has been attached. - -For this reason, it's important to double check how a feature's click handlers -are initialized and, if necessary, make sure Cypress waits for the button to be -ready to click. - -See the examples below of how to make this kind of button interaction more -robust. - -#### 🚫 Before: We click a button without waiting for initialization - -```js -cy.findByRole('main').findByRole('link', { name: 'Test User Profile' }).click(); -// We immediately try to click a button that's initialized asynchronously in JS. Sometimes the test will fail as the click handler is not yet attached. -cy.findByRole('button', { name: 'Follow' }).click(); -``` - -#### ✅ After: We wait for a data attribute that indicates the initialization has completed - -```js -cy.findByRole('main').findByRole('link', { name: 'Test User Profile' }).click(); -// A data attribute is added to initialized follow buttons, and Cypress waits until this is present on the page -cy.get('[data-click-initialized]'); -cy.findByRole('button', { name: 'Follow' }).click(); -``` - -### 3. Lingering network requests interfere with test setup or new user login - -Before each test we usually call `cy.testSetup()` to ensure cookies are cleared -and a user may be logged in fresh. However, if a previous test triggered -user-related network requests, and didn't wait until their completion, then -occasionally responses to these requests interfere with test setup and cause the -previous user to be persisted. - -This is particularly prevalent in very short tests, but can also happen if you -try in the middle of a test to sign out as one user, and immediately log back in -as another. - -This issue is best avoided by: - -- Utilising custom Cypress commands (e.g. `cy.loginAndVisit(user, url)`, - `cy.visitAndWaitForUserSideEffects(url)`, `cy.signOutUser()`) that help ensure - side effects from network requests are accounted for -- Splitting tests into 'single user' tests (i.e. avoid logging in as multiple - users in the same test) - -#### 🚫 Before: Using the `cy.visit(url)` command directly without awaiting side effects - -```js -beforeEach(() => { - cy.testSetup(); - cy.fixture('users/articleEditorV2User.json').as('user'); - - cy.get('@user').then(() => { - cy.loginUser(user).then(() => { - // The `visit` command does not take user-related network requests into account. If a test runs quickly, the responses may bleed into the next test setup - cy.visit('/dashboard'); - }); - }); -}); -``` - -#### ✅ After: Using the custom `loginAndVisit` command - -```js -beforeEach(() => { - cy.testSetup(); - cy.fixture('users/articleEditorV2User.json').as('user'); - - cy.get('@user').then(() => { - // The custom command logs in the user and visits the page, ensuring that user-related network requests are awaited - cy.loginAndVisit(user, '/dashboard'); - }); -}); -``` - -## Additional Resources - -- [Cypress documentation](https://docs.cypress.io) -- [Making your UI tests resilient to change](https://kentcdodds.com/blog/making-your-ui-tests-resilient-to-change) - by [Kent C. Dodds](https://twitter.com/kentcdodds) -- [Static vs Unit vs Integration vs E2E Testing for Frontend Apps](https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests) - by Kent C. Dodds diff --git a/docs/tests/frontend-tests.md b/docs/tests/frontend-tests.md deleted file mode 100644 index 21106af14..000000000 --- a/docs/tests/frontend-tests.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Frontend Tests ---- - -# Frontend Tests - -The test code is located within the same directory as each component, inside a -`__tests__` directory. - -```shell -$ tree app/javascript/article-form -L 1 -app/javascript/article-form -├── __tests__ -└── articleForm.jsx -``` - -The testing library being used is [Jest](https://jestjs.io/). - -- For unit tests, use jest's [expect API](https://jestjs.io/docs/en/expect) -- For integration tests, use - [preact-testing-library](https://github.com/testing-library/preact-testing-library). - -## Running Tests - -You can run those tests with: - -```shell -npm run test -``` - -or - -```shell -yarn test -``` - -Should you want to view only a single jest test, you can run: - -```shell -npx jest app/javascript/ -``` - -## Running Tests in Watch Mode - -You can run frontend tests in watch mode by running one of the following -commands: - -```shell -npm run test:watch -``` - -or - -```shell -yarn test:watch -``` - -In watch mode, after the first test run, jest provides several options for -filtering tests. These filtering options are enhanced via the -[jest-watch-typeahead](https://github.com/jest-community/jest-watch-typeahead/blob/master/README.md) -watch plugin. It allows you to filter by test filename or test name. - -![Screenshot of the jest watch menu](/jest-watch-mode-screenshot.png) - -## Debugging a Test - -To troubleshoot any of your jest test files, add a debugger and run: - -```shell -node --inspect-brk node_modules/.bin/jest --watch --runInBand -``` - -You can read more about troubleshooting -[here](https://jestjs.io/docs/en/troubleshooting). - -At the end of the test's execution, you will see the code coverage for the -Preact components in our codebase. - -If tests require utility modules, create them in a `utilities` folder under the -`__tests__` folder. Jest is configured to not treat the `utilities` folder as a -test suite. - -You can also debug jest in your favorite editor. See the -[Debugging](/frontend/debugging/) section of the frontend documentation. diff --git a/docs/tests/integration-tests.md b/docs/tests/integration-tests.md deleted file mode 100644 index e4becf8b6..000000000 --- a/docs/tests/integration-tests.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Integration Tests ---- - -# Integration Tests - -An integration test is a test that measures the interaction of multiple systems -or parts of your application. - -An integration test may seem similar to an [acceptance -test](/tests/acceptance-tests). The main difference is that an acceptance test -is from the perspective of the end-user, while an integration test is from the -perspective of the developer. - -Integration tests can be found in the directory `spec/requests`. - -You can run all integration tests with: - -```shell -bundle exec rspec spec/requests -``` - -To run an individual file you can use: - -```shell -bundle exec rspec spec/requests/stories_show_spec.rb -``` - -To run a specific test case you can use: - -```shell -bundle exec rspec spec/requests/stories_show_spec.rb:10 -``` - -where `10` is the line number of the test case that you want to execute. diff --git a/docs/tests/manual-tests.md b/docs/tests/manual-tests.md deleted file mode 100644 index 7a2a90be0..000000000 --- a/docs/tests/manual-tests.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Manual Tests ---- - -# Manual Tests - -We try to automate as much as possible, but particularly for frontend changes it -is usually necessary to verify work with a manual test. When manually testing a -feature, it's useful to check: - -- Does the UI look consistent across different desktop browsers? -- Is the UI optimised for a mobile layout? -- Does the feature behave consistently across desktop and mobile browsers? -- Is the feature accessible? (See the - [Accessibility testing docs](/tests/accessibility-tests)) - -## Tips for testing on mobile - -For features involving touch interactions it becomes more important to test on -actual mobile devices, rather than using the browser dev-tools device simulator. -There can be some platform-specific differences in how these touch events are -handled and it's useful to make sure a feature is checked on both android and -iOS. - -One way to run your development code on your own mobile device is to use -[ngrok](https://ngrok.com/). ngrok is a free tool that allows you to access your -`localhost:3000` via a standard URL. To use it: - -- Follow [ngrok's instructions](https://ngrok.com/) to download/install the tool - (there is a free tier) -- Run `ngrok http 3000` in your terminal -- Copy the URL given in response (e.g. `xxxxxxxxx.ngrok.io`) and add it to your - `.env` file's `APP_DOMAIN` value (replacing `localhost:3000`) -- Start the app via `bin/startup` as usual -- Visit the ngrok URL on your mobile (to save copying the text, you could use a - [QR code generator](https://www.qr-code-generator.com/free-generator/) on your - desktop browser so you only need to point your camera at the screen) diff --git a/docs/tests/readme.md b/docs/tests/readme.md deleted file mode 100644 index efae0084e..000000000 --- a/docs/tests/readme.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Testing/QA Guide -items: - - acceptance-tests.md - - integration-tests.md - - unit-functional-tests.md - - frontend-tests.md - - manual-tests.md - - accessibility-tests.md - - e2e-tests.md - - regression-tests.md - - code-coverage.md - - codeclimate.md - - test-flags.md ---- - -We use the following testing tools: - -- [**RSpec**](http://rspec.info/) for testing the Rails backend -- [**Capybara**](https://github.com/teamcapybara/capybara) with - [**webdrivers**](https://github.com/titusfortner/webdrivers) for acceptance - testing -- [**guard-rspec**](https://github.com/guard/guard-rspec) for automated testing -- [**Jest**](https://jestjs.io/) for testing the frontend -- [**jest-axe**](https://github.com/nickcolley/jest-axe) for detecting basic - a11y regressions -- [**preact-testing-library**](https://github.com/testing-library/preact-testing-library) - for testing Preact components -- [**SimpleCov**](https://github.com/colszowka/simplecov) for tracking overall - test coverage on the backend - -We strive to provide tests for each pull request that adds new features or fixes -a bug. Ideally, we test the functionality of the frontend and the backend. - -If you'd like to help us improve our test coverage, we recommend checking out -our total coverage and writing tests for selected files based on SimpleCov's -test coverage results. You can also check out -[Code Climate summary](https://codeclimate.com/github/forem/forem) which -includes the test coverage. - -If you're new to writing tests in general or with Rails, we recommend reading -about -[testing with Rails, RSpec, and Capybara first](https://guides.rubyonrails.org/testing.html). - -## Continuous Integration & Continuous Deployment - -We are using Travis for CI and CD. Travis will run a build (in an isolated -environment for testing) for every push to this repository. We also recently -added [KnapsackPro](https://knapsackpro.com/) to our Travis CI setup. -KnapsackPro allows us to split up our tests evenly between 3 different -jobs(virtual machines). These 3 jobs all run in parallel which helps decrease -the time needed to run all of our specs. - -If you want more information about your CI job or how long specific specs take -to run you can find all of that information on our -[KnapsackPro public dashboard](https://knapsackpro.com/dashboard/organizations/1142/projects/1022/test_suites/1434/builds). - -Keep in mind that a passing build does not necessarily mean the project won't -run into any issues. Strive to write good tests for the code you wish to -contribute. - -Travis will deploy your pull request to production after CI passes and a member -of the Forem team has approved it. - -Our test suite is not perfect and sometimes a re-run is needed. If you encounter -a "flaky spec" that fails intermittently please open an issue so we can address -it. In order to get your test suite to pass after a flaky spec has failed simply -retry the individual job that failed rather than the entire suite in order to -save some time. When you retry the individual job, make sure to also retry the -Deploy job. Even though you may not be deploying that job must complete for the -entire build to pass. diff --git a/docs/tests/regression-tests.md b/docs/tests/regression-tests.md deleted file mode 100644 index 88dc96d5a..000000000 --- a/docs/tests/regression-tests.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Regression Testing ---- - -# Regression Testing - -Regression testing is a technique for detecting breaking changes over time in a -codebase. - -Proper Regression testing is one of the most powerful tools in a programmer's -arsenal for avoiding the bugs that crop up as a project grows in size. - -Generally speaking, Regression testing is accomplished by a combination of -[Acceptance tests][acceptance_tests] and [Integration tests][integration_tests] -performed on areas where bugs have been found in the past. As it happens, -software bugs tend to exist in groups; writing tests around buggy code will -almost always uncover new bugs as code evolves. - -The practice of Regression testing usually takes place after code has been -written, and is used to detect if recent changes have introduced new bugs by -breaking previously functional software. - -There is no perfect prescribed method for Regression testing, and it has evolved -with the introduction of [Continuous Integration][ci] practices like the ones -that Forem uses. However, CI doesn't replace the need for Regression testing. -Regression tests should still be added to the codebase when bugs are discovered. - -If you submit a bug patch to the Forem application, you might be asked to write -a Regression test around your patch to help warn future Forem contributors if -that bug ever makes another appearance. This practice has the added benefit of -helping to ensure your patch fixes the bug. - -[acceptance_tests]: /tests/acceptance-tests/ -[integration_tests]: /tests/integration-tests/ -[ci]: /maintainers/deploying/ diff --git a/docs/tests/test-flags.md b/docs/tests/test-flags.md deleted file mode 100644 index 6342ee4f2..000000000 --- a/docs/tests/test-flags.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Test Flags ---- - -# Test Flags - -When creating tests using Rspec we have the ability to add flags to those tests -that will signal to Rspec to run certain commands before, after, or around the -test example. - -Some flags that we use are: - -- `js: true` -- `throttle: true` -- `type: ` - -### `js: true` Flag - -`js: true` indicates that we want the JavaScript on the page to be executed when -the page is rendered, and a headless chrome instance will be initialized to do -so (instead of the default -[rack_test](https://github.com/teamcapybara/capybara#racktest) driver). - -If you are debugging a `js: true` spec and want to see the browser, you can set -`HEADLESS=false` before running a spec: - -```shell -HEADLESS=false bundle exec rspec spec/app/system -``` diff --git a/docs/tests/unit-functional-tests.md b/docs/tests/unit-functional-tests.md deleted file mode 100644 index c30f4cd3f..000000000 --- a/docs/tests/unit-functional-tests.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Unit and Functional Tests ---- - -# Unit and Functional Tests - -A unit test is about testing a single function/method in isolation with all of -its possible outputs. - -A functional test is about testing a single functionality, which can span -multiple methods and a controller. - -Other common terms in Rails are "model tests," "controller tests," and others. - -You can find model tests in `spec/models`, controller tests in -`spec/controllers` and additional functional tests in various directories within -the `spec` directory. - -You can run all models tests, for example, with: - -```shell -bundle exec rspec spec/models -``` - -To run an individual file you can use, for example: - -```shell -bundle exec rspec spec/models/user_spec.rb -``` - -To run a specific test case you can use, for example: - -```shell -bundle exec rspec spec/models/user_spec.rb:10 -``` - -where `10` is the line number of the test case that you want to execute. - -## Testing Controllers - -Historically, it has been common to use Rspec to write tests for Rails -controllers. This pattern isn't necessarily discouraged in the Forem codebase, -but Rspec has introduced a more effective way to test controllers via Request -Specs. - -Request specs test the actions on a controller across the entire stack, -effectively acting as Integration Tests. You can read more about request specs -in our documentation on [Integration Tests][integration_tests]. - -You can read the official guide [Testing Rails Applications][rails_guides] to -learn more. - -[integration_tests]: /tests/integration-tests/ -[rails_guides]: https://guides.rubyonrails.org/testing.html diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md deleted file mode 100644 index cf550dbfe..000000000 --- a/docs/troubleshooting.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Troubleshooting ---- - -## Tests - -### Connection timeout - -While running test cases, if you get an error message -`postgresql connection timeout`, please re-run the tests by increasing the -statement timeout, for example: - -```shell -STATEMENT_TIMEOUT=10000 bundle exec rspec -``` - -## PostgreSQL - -### How do I fix the Error `role "ec2-user" does not exist` on an AWS instance? - -After installing and configuring PostgreSQL on an AWS EC2 (or AWS Cloud9) -instance and running `bin/setup`, this error could occur. - -To fix it, run the following two commands in a terminal (assuming your -PostgreSQL user is named **postgres**): - -``` -sudo -u postgres createuser -s ec2-user -sudo -u postgres createdb ec2-user -``` - -The first command creates the user **ec2-user** and the second one creates the -database for this user because every user needs its database. Even if the first -command fails, run the second command to create the missing database. - -## CORS - -If you are experiencing CORS issues locally or need to display more information -about the CORS headers, add the following variable to your `.env`: - -```shell -export DEBUG_CORS=true -``` diff --git a/package.json b/package.json index deea324ca..84e6467d5 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,6 @@ }, "scripts": { "prepare": "husky install", - "api-docs:lint": "spectral lint -F hint -v docs/api_v0.yml", - "api-docs:serve": "redoc-cli serve docs/api_v0.yml --options.pathInMiddlePanel --options.jsonSampleExpandLevel=all --options.menuToggle -t docs/api_template.hbs --watch", "storybook-prerequisites": "sass -q app/assets/stylesheets/themes:app/javascript/storybook-static/themes && bin/generate-css-utility-classes-docs.js", "prebuild-storybook": "yarn run storybook-prerequisites", "build-storybook": "build-storybook -c app/javascript/.storybook -s app/assets -o app/javascript/storybook-static --quiet", @@ -33,9 +31,6 @@ "prettier --write", "eslint --fix -c app/assets/javascripts/.eslintrc.js" ], - "docs/api_v0.yml": [ - "spectral lint -F hint" - ], "*.{js,jsx}": [ "prettier --write", "eslint --fix", @@ -53,9 +48,6 @@ "./Gemfile": [ "bundle exec rubocop --require rubocop-rspec --auto-correct" ], - "docs/Gemfile": [ - "bundle exec rubocop --require rubocop-rspec --auto-correct" - ], "*.rake": [ "bundle exec rubocop --require rubocop-rspec --auto-correct" ], @@ -123,7 +115,6 @@ "eslint-plugin-no-only-tests": "^2.6.0", "eslint-plugin-react": "^7.24.0", "faker": "^5.5.3", - "gitdocs": "^2.0.0", "husky": "^7.0.1", "jest": "26.6.3", "jest-axe": "^4.1.0", @@ -180,11 +171,6 @@ "stimulus": "^2.0.0", "web-share-wrapper": "^0.2.2" }, - "resolutions": { - "gitdocs/markdown-to-jsx": "^6.11.4", - "gitdocs/prismjs": "^1.23.0", - "gitdocs/axios": "^0.21.1" - }, "jest": { "setupFiles": [ "jest-localstorage-mock" diff --git a/spec/requests/pages_spec.rb b/spec/requests/pages_spec.rb index d35c72f69..dab33c243 100644 --- a/spec/requests/pages_spec.rb +++ b/spec/requests/pages_spec.rb @@ -83,7 +83,7 @@ RSpec.describe "Pages", type: :request do describe "GET /api" do it "redirects to the API docs" do get "/api" - expect(response.body).to redirect_to("https://docs.forem.com/api") + expect(response.body).to redirect_to("https://developers.forem.com/api") end end diff --git a/yarn.lock b/yarn.lock index 4ddceede3..322d45eed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1243,18 +1243,6 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@emotion/babel-utils@^0.6.4": - version "0.6.10" - resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.10.tgz#83dbf3dfa933fae9fc566e54fbb45f14674c6ccc" - integrity sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow== - dependencies: - "@emotion/hash" "^0.6.6" - "@emotion/memoize" "^0.6.6" - "@emotion/serialize" "^0.9.1" - convert-source-map "^1.5.1" - find-root "^1.1.0" - source-map "^0.7.2" - "@emotion/cache@^10.0.27", "@emotion/cache@^10.0.9": version "10.0.29" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0" @@ -1291,11 +1279,6 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@emotion/hash@^0.6.2", "@emotion/hash@^0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.6.tgz#62266c5f0eac6941fece302abad69f2ee7e25e44" - integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ== - "@emotion/is-prop-valid@0.8.8", "@emotion/is-prop-valid@^0.8.6", "@emotion/is-prop-valid@^0.8.8": version "0.8.8" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" @@ -1303,23 +1286,11 @@ dependencies: "@emotion/memoize" "0.7.4" -"@emotion/is-prop-valid@^0.6.1": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.6.8.tgz#68ad02831da41213a2089d2cab4e8ac8b30cbd85" - integrity sha512-IMSL7ekYhmFlILXcouA6ket3vV7u9BqStlXzbKOF9HBtpUPMMlHU+bBxrLOa2NvleVwNIxeq/zL8LafLbeUXcA== - dependencies: - "@emotion/memoize" "^0.6.6" - "@emotion/memoize@0.7.4": version "0.7.4" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== -"@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b" - integrity sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ== - "@emotion/serialize@^0.11.15", "@emotion/serialize@^0.11.16": version "0.11.16" resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad" @@ -1331,16 +1302,6 @@ "@emotion/utils" "0.11.3" csstype "^2.5.7" -"@emotion/serialize@^0.9.1": - version "0.9.1" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.9.1.tgz#a494982a6920730dba6303eb018220a2b629c145" - integrity sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ== - dependencies: - "@emotion/hash" "^0.6.6" - "@emotion/memoize" "^0.6.6" - "@emotion/unitless" "^0.6.7" - "@emotion/utils" "^0.8.2" - "@emotion/sheet@0.9.4": version "0.9.4" resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" @@ -1369,31 +1330,16 @@ resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== -"@emotion/stylis@^0.7.0": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.7.1.tgz#50f63225e712d99e2b2b39c19c70fff023793ca5" - integrity sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ== - "@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@emotion/unitless@^0.6.2", "@emotion/unitless@^0.6.7": - version "0.6.7" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.6.7.tgz#53e9f1892f725b194d5e6a1684a7b394df592397" - integrity sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg== - "@emotion/utils@0.11.3": version "0.11.3" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== -"@emotion/utils@^0.8.2": - version "0.8.2" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc" - integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw== - "@emotion/weak-memoize@0.2.5": version "0.2.5" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" @@ -1847,7 +1793,7 @@ "@reach/utils" "0.16.0" tslib "^2.3.0" -"@reach/observe-rect@1.2.0", "@reach/observe-rect@^1.0.3": +"@reach/observe-rect@1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2" integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ== @@ -3407,32 +3353,6 @@ dependencies: "@babel/runtime" "^7.12.5" -"@timberio/ui@^2.0.1": - version "2.7.0" - resolved "https://registry.yarnpkg.com/@timberio/ui/-/ui-2.7.0.tgz#48f89704b336419fca17ec37c7d3b5d153e5c25c" - integrity sha512-7kILdZZGkLJAD89zgJFQOA0YZLRnXIMYOjhxwRv2WFWMfgQRfn9Agejwo3RAmVIREFMRwc1s3LQvkPTN2oWpLg== - dependencies: - "@reach/observe-rect" "^1.0.3" - blacklist "^1.1.4" - classnames "^2.2.6" - clean-element "^1.0.2" - deepmerge "^3.0.0" - emotion "^9.2.12" - emotion-theming "^9.2.9" - md5 "^2.2.1" - object-path "^0.11.4" - polished "^1.9.2" - prop-types "^15.6.1" - react-content-loader "^3.1.2" - react-emotion "^9.2.12" - react-feather "^1.1.5" - react-popover "^0.5.10" - react-select "^2.1.2" - react-show "2.0.4" - react-text-mask "^5.4.3" - styled-system "^3.1.11" - unfetch "^4.0.1" - "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -4196,13 +4116,6 @@ ansi-html@0.0.7, ansi-html@^0.0.7: resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= - dependencies: - ansi-wrap "0.1.0" - ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -4228,11 +4141,6 @@ ansi-regex@^6.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.0.tgz#ecc7f5933cbe5ac7b33e209a5ff409ab1669c6b2" integrity sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -4254,11 +4162,6 @@ ansi-to-html@^0.6.11: dependencies: entities "^1.1.2" -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - any-promise@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-0.1.0.tgz#830b680aa7e56f33451d4b049f3bd8044498ee27" @@ -4303,7 +4206,7 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" -argparse@^1.0.10, argparse@^1.0.7: +argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== @@ -4483,11 +4386,6 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" @@ -4515,13 +4413,6 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autolinker@~0.28.0: - version "0.28.1" - resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.28.1.tgz#0652b491881879f0775dace0cdca3233942a4e47" - integrity sha1-BlK0kYgYefB3XazgzcoyM5QqTkc= - dependencies: - gulp-header "^1.7.1" - autoprefixer@^10.3.2: version "10.3.2" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.3.2.tgz#836e4b4f59eb6876c41012c1c937be74035f3ec8" @@ -4574,52 +4465,11 @@ axe-core@^4.0.1, axe-core@^4.0.2, axe-core@^4.2.0: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.2.3.tgz#2a3afc332f0031b42f602f4a3de03c211ca98f72" integrity sha512-pXnVMfJKSIWU2Ml4JHP7pZEPIrgBO1Fd3WGx+fPBsS+KRGhE4vxooD8XBGWbQOIVSZsVK7pUDBBkCicNu80yzQ== -axios@^0.18.0, axios@^0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== - dependencies: - follow-redirects "^1.10.0" - axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.26.0, babel-core@^6.26.3: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" @@ -4637,142 +4487,6 @@ babel-eslint@^10.0.1, babel-eslint@^10.1.0: eslint-visitor-keys "^1.0.0" resolve "^1.12.0" -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-builder-react-jsx@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" - integrity sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA= - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - esutils "^2.0.2" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-jest@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" @@ -4787,15 +4501,6 @@ babel-jest@^26.6.3: graceful-fs "^4.2.4" slash "^3.0.0" -babel-loader@^7.1.4: - version "7.1.5" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68" - integrity sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw== - dependencies: - find-cache-dir "^1.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" - babel-loader@^8.2.2: version "8.2.2" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" @@ -4806,13 +4511,6 @@ babel-loader@^8.2.2: make-dir "^3.1.0" schema-utils "^2.6.5" -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= - dependencies: - babel-runtime "^6.22.0" - babel-plugin-apply-mdx-type-prop@1.6.22: version "1.6.22" resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz#d216e8fd0de91de3f1478ef3231e05446bc8705b" @@ -4821,13 +4519,6 @@ babel-plugin-apply-mdx-type-prop@1.6.22: "@babel/helper-plugin-utils" "7.10.4" "@mdx-js/util" "1.6.22" -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= - dependencies: - babel-runtime "^6.22.0" - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -4851,24 +4542,6 @@ babel-plugin-emotion@^10.0.27: find-root "^1.1.0" source-map "^0.5.7" -babel-plugin-emotion@^9.2.11: - version "9.2.11" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz#319c005a9ee1d15bb447f59fe504c35fd5807728" - integrity sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@emotion/babel-utils" "^0.6.4" - "@emotion/hash" "^0.6.2" - "@emotion/memoize" "^0.6.1" - "@emotion/stylis" "^0.7.0" - babel-plugin-macros "^2.0.0" - babel-plugin-syntax-jsx "^6.18.0" - convert-source-map "^1.5.0" - find-root "^1.1.0" - mkdirp "^0.5.1" - source-map "^0.5.7" - touch "^2.0.1" - babel-plugin-extract-import-names@1.6.22: version "1.6.22" resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" @@ -4957,329 +4630,11 @@ babel-plugin-polyfill-regenerator@^0.2.2: babel-plugin-syntax-jsx "^6.18.0" lodash "^4.17.11" -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= - -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha1-1+sjt5oxf4VDlixQW4J8fWysJ94= - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= - -babel-plugin-syntax-flow@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - integrity sha1-TDqyCiryaqIM0lmVw5jE63AxDI0= - -babel-plugin-syntax-jsx@^6.18.0, babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: +babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= - -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-class-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha1-anl2PqYdM9NvN7YRqp3vgagbRqw= - dependencies: - babel-helper-function-name "^6.24.1" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - integrity sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988= - dependencies: - babel-plugin-syntax-flow "^6.18.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-object-rest-spread@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" - -babel-plugin-transform-react-display-name@^6.23.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" - integrity sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-self@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" - integrity sha1-322AqdomEqEh5t3XVYvL7PBuY24= - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-source@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" - integrity sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY= - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" - integrity sha1-hAoCjn30YN/DotKfDA2R9jduZqM= - dependencies: - babel-helper-builder-react-jsx "^6.24.1" - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-runtime@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee" - integrity sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -5298,49 +4653,6 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-env@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.0" - -babel-preset-flow@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" - integrity sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0= - dependencies: - babel-plugin-transform-flow-strip-types "^6.22.0" - babel-preset-jest@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" @@ -5356,32 +4668,7 @@ babel-preset-preact@^2.0.0: dependencies: "@babel/plugin-transform-react-jsx" "^7.3.0" -babel-preset-react@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" - integrity sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A= - dependencies: - babel-plugin-syntax-jsx "^6.3.13" - babel-plugin-transform-react-display-name "^6.23.0" - babel-plugin-transform-react-jsx "^6.24.1" - babel-plugin-transform-react-jsx-self "^6.22.0" - babel-plugin-transform-react-jsx-source "^6.22.0" - babel-preset-flow "^6.23.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: +babel-runtime@^6.23.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= @@ -5389,47 +4676,6 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runti core-js "^2.4.0" regenerator-runtime "^0.11.0" -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - bail@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" @@ -5514,11 +4760,6 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -blacklist@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/blacklist/-/blacklist-1.1.4.tgz#b2dd09d6177625b2caa69835a37b28995fa9a2f2" - integrity sha1-st0J1hd2JbLKppg1o3somV+povI= - blob-util@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" @@ -5711,14 +4952,6 @@ browserslist@^2.0.0, browserslist@^2.11.3: caniuse-lite "^1.0.30000792" electron-to-chromium "^1.3.30" -browserslist@^3.2.6: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.12.2, browserslist@^4.16.6, browserslist@^4.16.8, browserslist@^4.6.4: version "4.16.8" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.8.tgz#cb868b0b554f137ba6e33de0ecff2eda403c4fb0" @@ -5747,11 +4980,6 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -buffer-from@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0" - integrity sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg== - buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" @@ -5887,14 +5115,6 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= - dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" - camel-case@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" @@ -5948,7 +5168,7 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001166, caniuse-lite@^1.0.30001251: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001166, caniuse-lite@^1.0.30001251: version "1.0.30001251" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz#6853a606ec50893115db660f82c094d18f096d85" integrity sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A== @@ -6001,17 +5221,6 @@ chalk@4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -6048,11 +5257,6 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== -charenc@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= - chart.js@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.5.1.tgz#73e24d23a4134a70ccdb5e79a917f156b6f3644a" @@ -6078,7 +5282,7 @@ check-more-types@^2.24.0: optionalDependencies: fsevents "~2.3.1" -chokidar@^2.0.3, chokidar@^2.1.8: +chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -6147,7 +5351,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.5, classnames@^2.2.6: +classnames@^2.2.5: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -6157,18 +5361,13 @@ classnames@^2.3.1: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== -clean-css@4.2.x, clean-css@^4.2.3: +clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== dependencies: source-map "~0.6.0" -clean-element@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/clean-element/-/clean-element-1.1.0.tgz#d3ec06ec89ec640d463e8e587f73679a3deb6b5f" - integrity sha512-hs3YycjQAqPDghZ1YZYo0C5h3VqS8mGfS7bLqndDq7rlhIl0nC6YLkUESc5fcHHsgZjelm/EmQZ3eFitIJYmGQ== - clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -6274,11 +5473,6 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -coffee-script@^1.12.4: - version "1.12.7" - resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.7.tgz#c05dae0cb79591d05b3070a8433a98c9a89ccc53" - integrity sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw== - collapse-white-space@^1.0.2: version "1.0.6" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" @@ -6391,11 +5585,6 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@2.17.x: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== - commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -6421,11 +5610,6 @@ commander@^7.1.0, commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@~2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== - common-tags@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -6482,7 +5666,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@^1.5.2: +concat-stream@^1.5.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -6492,28 +5676,11 @@ concat-stream@^1.5.0, concat-stream@^1.5.2: readable-stream "^2.2.2" typedarray "^0.0.6" -concat-with-sourcemaps@*: - version "1.1.0" - resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" - integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== - dependencies: - source-map "^0.6.1" - connect-history-api-fallback@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== -connect@^3.6.6: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -6541,7 +5708,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -6605,7 +5772,7 @@ core-js@3, core-js@^3.0.1, core-js@^3.0.4, core-js@^3.16.2, core-js@^3.6.5, core resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.16.2.tgz#3f485822889c7fc48ef463e35be5cc2a4a01a1f4" integrity sha512-P0KPukO6OjMpjBtHSceAZEWlDD1M2Cpzpg6dBbrjFqFhBHe/BwhxaP820xKOjRn/lZRQirrCusIpLS/n2sgXLQ== -core-js@^2.4.0, core-js@^2.5.0: +core-js@^2.4.0: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== @@ -6680,35 +5847,6 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.5.3" -create-emotion-server@^9.2.12: - version "9.2.12" - resolved "https://registry.yarnpkg.com/create-emotion-server/-/create-emotion-server-9.2.12.tgz#30d82507bfe440bfb3dd6c9b5c8faf24597ee954" - integrity sha512-ET+E6A5MkQTEBNDYAnjh6+0cB33qStFXhtflkZNPEaOmvzYlB/xcPnpUk4J7ul3MVa8PCQx2Ei5g2MGY/y1n+g== - dependencies: - html-tokenize "^2.0.0" - multipipe "^1.0.2" - through "^2.3.8" - -create-emotion-styled@^9.2.8: - version "9.2.8" - resolved "https://registry.yarnpkg.com/create-emotion-styled/-/create-emotion-styled-9.2.8.tgz#c0050e768ba439609bec108600467adf2de67cc3" - integrity sha512-2LrNM5MREWzI5hZK+LyiBHglwE18WE3AEbBQgpHQ1+zmyLSm/dJsUZBeFAwuIMb+TjNZP0KsMZlV776ufOtFdg== - dependencies: - "@emotion/is-prop-valid" "^0.6.1" - -create-emotion@^9.2.12: - version "9.2.12" - resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-9.2.12.tgz#0fc8e7f92c4f8bb924b0fef6781f66b1d07cb26f" - integrity sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA== - dependencies: - "@emotion/hash" "^0.6.2" - "@emotion/memoize" "^0.6.1" - "@emotion/stylis" "^0.7.0" - "@emotion/unitless" "^0.6.2" - csstype "^2.5.2" - stylis "^3.5.0" - stylis-rule-sheet "^0.0.10" - create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" @@ -6767,11 +5905,6 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -crypt@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -6930,13 +6063,6 @@ css-unit-converter@^1.1.1: resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21" integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA== -css-vendor@^0.3.1: - version "0.3.8" - resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-0.3.8.tgz#6421cfd3034ce664fe7673972fd0119fc28941fa" - integrity sha1-ZCHP0wNM5mT+dnOXL9ARn8KJQfo= - dependencies: - is-in-browser "^1.0.2" - css-what@^3.2.1: version "3.4.2" resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" @@ -7073,7 +6199,7 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -csstype@^2.5.2, csstype@^2.5.7: +csstype@^2.5.7: version "2.6.16" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.16.tgz#544d69f547013b85a40d15bff75db38f34fe9c39" integrity sha512-61FBWoDHp/gRtsoDkq/B1nWrCUG/ok1E3tUrcNbZjsE9Cxd9yzUirjS3+nAATB8U4cTtaQmAHbNndoFz5L6C9Q== @@ -7179,7 +6305,7 @@ dayjs@^1.10.4: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -7249,16 +6375,6 @@ deep-object-diff@^1.1.0: resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.0.tgz#d6fabf476c2ed1751fc94d5ca693d2ed8c18bc5a" integrity sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw== -deepmerge@^2.1.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" - integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== - -deepmerge@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.3.0.tgz#d3c47fd6f3a93d517b14426b0628a17b0125f5f7" - integrity sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA== - deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" @@ -7383,13 +6499,6 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= - dependencies: - repeating "^2.0.0" - detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -7426,11 +6535,6 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -diacritics-map@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/diacritics-map/-/diacritics-map-0.1.0.tgz#6dfc0ff9d01000a2edf2865371cac316e94977af" - integrity sha1-bfwP+dAQAKLt8oZTccrDFulJd68= - diff-sequences@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" @@ -7505,13 +6609,6 @@ dom-converter@^0.2: dependencies: utila "~0.4" -dom-helpers@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" - integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== - dependencies: - "@babel/runtime" "^7.1.2" - dom-helpers@^5.0.1: version "5.2.0" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b" @@ -7666,13 +6763,6 @@ downshift@^6.0.15: prop-types "^15.7.2" react-is "^17.0.2" -duplexer2@^0.1.2: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= - dependencies: - readable-stream "^2.0.2" - duplexer@^0.1.1, duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -7701,7 +6791,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.564: +electron-to-chromium@^1.3.30, electron-to-chromium@^1.3.564: version "1.3.692" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.692.tgz#4d00479055a7282cdd1b19caec09ed7779529640" integrity sha512-Ix+zDUAXWZuUzqKdhkgN5dP7ZM+IwMG4yAGFGDLpGJP/3vNEEwuHG1LIhtXUfW0FFV0j38t5PUv2n/3MFSRviQ== @@ -7761,13 +6851,6 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -emotion-server@^9.1.3: - version "9.2.12" - resolved "https://registry.yarnpkg.com/emotion-server/-/emotion-server-9.2.12.tgz#aaaaa04843108943d1ce5a796e0bc40b06a3223e" - integrity sha512-Bhjdl7eNoIeiAVa2QPP5d+1nP/31SiO/K1P/qI9cdXCydg91NwGYmteqhhge8u7PF8fLGTEVQfcPwj21815eBw== - dependencies: - create-emotion-server "^9.2.12" - emotion-theming@^10.0.19, emotion-theming@^10.0.27: version "10.0.27" resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.27.tgz#1887baaec15199862c89b1b984b79806f2b9ab10" @@ -7777,21 +6860,6 @@ emotion-theming@^10.0.19, emotion-theming@^10.0.27: "@emotion/weak-memoize" "0.2.5" hoist-non-react-statics "^3.3.0" -emotion-theming@^9.2.9: - version "9.2.9" - resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-9.2.9.tgz#2bfd77fdd47d3f5e60d59d97dd4cea4622657220" - integrity sha512-Ncyr1WocmDDrTbuYAzklIUC5iKiGtHy3e5ymoFXcka6SuvZl/EDMawegk4wVp72Agrcm1xemab3QOHfnOkpoMA== - dependencies: - hoist-non-react-statics "^2.3.1" - -emotion@^9.1.2, emotion@^9.1.3, emotion@^9.2.12: - version "9.2.12" - resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.12.tgz#53925aaa005614e65c6e43db8243c843574d1ea9" - integrity sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ== - dependencies: - babel-plugin-emotion "^9.2.11" - create-emotion "^9.2.12" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -7960,7 +7028,7 @@ escape-string-regexp@2.0.0, escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -8371,11 +7439,6 @@ executable@^4.1.1: dependencies: pify "^2.2.0" -exit-hook@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.2.1.tgz#007b2d92c6428eda2b76e7016a34351586934593" - integrity sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw== - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -8394,13 +7457,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" @@ -8631,14 +7687,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -file-loader@^1.1.11: - version "1.1.11" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.11.tgz#6fe886449b0f2a936e43cabaac0cdbfb369506f8" - integrity sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg== - dependencies: - loader-utils "^1.0.2" - schema-utils "^0.4.5" - file-loader@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" @@ -8671,17 +7719,6 @@ filesize@6.1.0: resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" integrity sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg== -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -8699,7 +7736,7 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.1.2, finalhandler@~1.1.2: +finalhandler@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== @@ -8712,15 +7749,6 @@ finalhandler@1.1.2, finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8= - dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^2.0.0" - find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -8829,7 +7857,7 @@ focus-visible@^5.2.0: resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.2.0.tgz#3a9e41fccf587bd25dcc2ef045508284f0a4d6b3" integrity sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ== -follow-redirects@^1.0.0, follow-redirects@^1.10.0: +follow-redirects@^1.0.0: version "1.13.3" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA== @@ -8944,15 +7972,6 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" - integrity sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -9153,59 +8172,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -gitdocs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gitdocs/-/gitdocs-2.0.0.tgz#430ea46611f43fda49a5d67ee5d83194f05fe4ee" - integrity sha512-ev6nBT62qZSCv9h7SAq7BerEhJSRDekj2V64DQqxzTNTuTizap8NrgbR6mkNyHLi7TeuWqCERvABfvyJ9D1/HQ== - dependencies: - "@timberio/ui" "^2.0.1" - axios "^0.18.0" - babel-core "^6.26.3" - babel-loader "^7.1.4" - babel-plugin-transform-class-properties "^6.24.1" - babel-plugin-transform-object-rest-spread "^6.26.0" - babel-plugin-transform-runtime "^6.23.0" - babel-preset-env "^1.7.0" - babel-preset-react "^6.24.1" - babel-register "^6.26.0" - chalk "^2.4.1" - chokidar "^2.0.3" - connect "^3.6.6" - deepmerge "^2.1.0" - emotion "^9.1.3" - emotion-server "^9.1.3" - exit-hook "^2.0.0" - file-loader "^1.1.11" - fs-extra "^6.0.1" - gray-matter "^4.0.1" - history "^4.7.2" - html-minifier "^3.5.16" - js-search "^1.4.2" - markdown-to-jsx "6.6.7" - markdown-toc "^1.2.0" - minimist "^1.2.0" - ncp "^2.0.0" - progress "^2.0.0" - prop-types "^15.6.1" - raf "^3.4.0" - react "^16.4.0" - react-click-outside "^3.0.1" - react-content-loader "^3.1.2" - react-dom "^16.4.0" - react-emotion "^9.1.3" - react-feather "^1.1.0" - react-helmet "^5.2.0" - react-highlight-words "^0.11.0" - react-router-dom "^4.2.2" - react-syntax-highlighter "^7.0.4" - serve-static "^1.13.2" - simple-git "^1.95.0" - tmp "^0.0.33" - webpack "^4.8.3" - webpack-dev-middleware "^3.1.3" - webpack-hot-middleware "^2.22.2" - ws "^5.2.0" - github-slugger@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.3.0.tgz#9bd0a95c5efdfc46005e82a906ef8e2a059124c9" @@ -9330,11 +8296,6 @@ globals@^13.6.0, globals@^13.9.0: dependencies: type-fest "^0.20.2" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - globalthis@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.2.tgz#2a235d34f4d8036219f7e34929b5de9e18166b8b" @@ -9411,27 +8372,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== -gray-matter@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-2.1.1.tgz#3042d9adec2a1ded6a7707a9ed2380f8a17a430e" - integrity sha1-MELZrewqHe1qdwep7SOA+KF6Qw4= - dependencies: - ansi-red "^0.1.1" - coffee-script "^1.12.4" - extend-shallow "^2.0.1" - js-yaml "^3.8.1" - toml "^2.3.2" - -gray-matter@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" - integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw== - dependencies: - js-yaml "^3.11.0" - kind-of "^6.0.2" - section-matter "^1.0.0" - strip-bom-string "^1.0.0" - growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -9442,15 +8382,6 @@ gud@^1.0.0: resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== -gulp-header@^1.7.1: - version "1.8.12" - resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.12.tgz#ad306be0066599127281c4f8786660e705080a84" - integrity sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ== - dependencies: - concat-with-sourcemaps "*" - lodash.template "^4.4.0" - through2 "^2.0.0" - gzip-size@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" @@ -9496,13 +8427,6 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - has-bigints@^1.0.0, has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" @@ -9668,7 +8592,7 @@ hastscript@^6.0.0: property-information "^5.0.0" space-separated-tokens "^1.0.0" -he@1.2.x, he@^1.2.0: +he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -9678,38 +8602,16 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -highlight-words-core@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/highlight-words-core/-/highlight-words-core-1.2.2.tgz#1eff6d7d9f0a22f155042a00791237791b1eeaaa" - integrity sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg== - highlight.js@^10.1.1, highlight.js@~10.6.0: version "10.6.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.6.0.tgz#0073aa71d566906965ba6e1b7be7b2682f5e18b6" integrity sha512-8mlRcn5vk/r4+QcqerapwBYTe+iPL5ih6xrNylxrnBdHQiijDETfXX7VIxC3UiCRiINBJfANBAsPzAvRQj8RpQ== -highlight.js@~9.12.0: - version "9.12.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" - integrity sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4= - highlight.js@~9.13.0: version "9.13.1" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A== -history@^4.7.2: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== - dependencies: - "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -9719,11 +8621,6 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^2.1.1, hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0: - version "2.5.5" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" - integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== - hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -9731,14 +8628,6 @@ hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0: dependencies: react-is "^16.7.0" -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - homedir-polyfill@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" @@ -9816,35 +8705,11 @@ html-minifier-terser@^5.0.1: relateurl "^0.2.7" terser "^4.6.3" -html-minifier@^3.5.16: - version "3.5.21" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" - integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== - dependencies: - camel-case "3.0.x" - clean-css "4.2.x" - commander "2.17.x" - he "1.2.x" - param-case "2.1.x" - relateurl "0.2.x" - uglify-js "3.4.x" - html-tags@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== -html-tokenize@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/html-tokenize/-/html-tokenize-2.0.1.tgz#c3b2ea6e2837d4f8c06693393e9d2a12c960be5f" - integrity sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w== - dependencies: - buffer-from "~0.1.1" - inherits "~2.0.1" - minimist "~1.2.5" - readable-stream "~1.0.27-1" - through2 "~0.4.1" - html-void-elements@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" @@ -10191,7 +9056,7 @@ intersection-observer@^0.12.0: resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.0.tgz#6c84628f67ce8698e5f9ccf857d97718745837aa" integrity sha512-2Vkz8z46Dv401zTWudDGwO7KiGHNDkMv417T5ItcNYfmvHR/1qCTVBO9vwH8zZmQ0WkA/1ARwpysR9bsnop4NQ== -invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: +invariant@^2.2.3, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -10298,7 +9163,7 @@ is-boolean-object@^1.1.0: dependencies: call-bind "^1.0.0" -is-buffer@^1.1.5, is-buffer@~1.1.6: +is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -10433,11 +9298,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -10491,11 +9351,6 @@ is-hexadecimal@^1.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== -is-in-browser@^1.0.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" - integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU= - is-installed-globally@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" @@ -10526,13 +9381,6 @@ is-number-object@^1.0.4: resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -10540,11 +9388,6 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -11221,11 +10064,6 @@ js-levenshtein@^1.1.6: resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== -js-search@^1.4.2: - version "1.4.3" - resolved "https://registry.yarnpkg.com/js-search/-/js-search-1.4.3.tgz#23a86d7e064ca53a473930edc48615b6b1c1954a" - integrity sha512-Sny5pf00kX1sM1KzvUC9nGYWXOvBfy30rmvZWeRktpg+esQKedIXrXNee/I2CAnsouCyaTjitZpRflDACx4toA== - js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -11236,12 +10074,7 @@ js-string-escape@^1.0.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - -js-yaml@^3.11.0, js-yaml@^3.13.1, js-yaml@^3.14.1, js-yaml@^3.8.1: +js-yaml@^3.13.1, js-yaml@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -11292,11 +10125,6 @@ jsep@^0.3.0, jsep@^0.3.4: resolved "https://registry.yarnpkg.com/jsep/-/jsep-0.3.5.tgz#3fd79ebd92f6f434e4857d5272aaeef7d948264d" integrity sha512-AoRLBDc6JNnKjNcmonituEABS5bcfqDhQAWWXNTFrqu6nVXBpBAGfcoTGZMFlIrh9FjmE1CQyX9CTNwZrXMMDA== -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -11349,11 +10177,6 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -11495,13 +10318,6 @@ lazy-ass@^1.6.0: resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= -lazy-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" - integrity sha1-uRkKT5EzVGlIQIWfio9whNiCImQ= - dependencies: - set-getter "^0.1.0" - lazy-universal-dotenv@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz#a6c8938414bca426ab8c9463940da451a911db38" @@ -11566,16 +10382,6 @@ lint-staged@^11.1.2: string-argv "0.3.1" stringify-object "^3.3.0" -list-item@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/list-item/-/list-item-1.1.1.tgz#0c65d00e287cb663ccb3cb3849a77e89ec268a56" - integrity sha1-DGXQDih8tmPMs8s4Sad+iewmilY= - dependencies: - expand-range "^1.8.1" - extend-shallow "^2.0.1" - is-number "^2.1.0" - repeat-string "^1.5.2" - listr2@^3.8.2, listr2@^3.8.3: version "3.10.0" resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.10.0.tgz#58105a53ed7fa1430d1b738c6055ef7bb006160f" @@ -11613,7 +10419,7 @@ loader-utils@2.0.0, loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" -loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -11652,11 +10458,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -11672,13 +10473,6 @@ lodash.debounce@4.0.8, lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= -lodash.debounce@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-3.1.1.tgz#812211c378a94cc29d5aa4e3346cf0bfce3a7df5" - integrity sha1-gSIRw3ipTMKdWqTjNGzwv846ffU= - dependencies: - lodash._getnative "^3.0.0" - lodash.defaults@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -11754,7 +10548,7 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.template@^4.2.4, lodash.template@^4.4.0, lodash.template@^4.5.0: +lodash.template@^4.2.4, lodash.template@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== @@ -11769,13 +10563,6 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "^3.0.0" -lodash.throttle@^3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-3.0.4.tgz#bc4f471fb328e4d6fdc6df2b3d3caf113f0f89c9" - integrity sha1-vE9HH7Mo5Nb9xt8rPTyvET8Pick= - dependencies: - lodash.debounce "^3.0.0" - lodash.throttle@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" @@ -11821,18 +10608,13 @@ logdown@3.3.1: dependencies: chalk "^2.3.0" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" -lower-case@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= - lower-case@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" @@ -11856,14 +10638,6 @@ lowlight@~1.11.0: fault "^1.0.2" highlight.js "~9.13.0" -lowlight@~1.9.1: - version "1.9.2" - resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.2.tgz#0b9127e3cec2c3021b7795dd81005c709a42fdd1" - integrity sha512-Ek18ElVCf/wF/jEm1b92gTnigh94CtBNWiZ2ad+vTgW7cTmQxUY3I98BjHK68gZAJEWmybGBZgx9qv3QxLQB/Q== - dependencies: - fault "^1.0.2" - highlight.js "~9.12.0" - lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -11888,13 +10662,6 @@ lz-string@^1.4.4: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY= -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -11951,11 +10718,6 @@ markdown-escapes@^1.0.0: resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== -markdown-link@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/markdown-link/-/markdown-link-0.1.1.tgz#32c5c65199a6457316322d1e4229d13407c8c7cf" - integrity sha1-MsXGUZmmRXMWMi0eQinRNAfIx88= - markdown-loader@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/markdown-loader/-/markdown-loader-6.0.0.tgz#7f8d40ee98b32d3bb8c5387d58e679600d3edeaa" @@ -11964,7 +10726,7 @@ markdown-loader@^6.0.0: loader-utils "^1.2.3" marked "^0.7.0" -markdown-to-jsx@6.6.7, markdown-to-jsx@^6.10.3, markdown-to-jsx@^6.11.4: +markdown-to-jsx@^6.10.3, markdown-to-jsx@^6.11.4: version "6.11.4" resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.11.4.tgz#b4528b1ab668aef7fe61c1535c27e837819392c5" integrity sha512-3lRCD5Sh+tfA52iGgfs/XZiw33f7fFX9Bn55aNnVNUd2GzLDkOWyKYYD8Yju2B1Vn+feiEdgJs8T6Tg0xNokPw== @@ -11982,24 +10744,6 @@ markdown-to-jsx@^7.1.3: resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.1.3.tgz#f00bae66c0abe7dd2d274123f84cb6bd2a2c7c6a" integrity sha512-jtQ6VyT7rMT5tPV0g2EJakEnXLiPksnvlYtwQsVVZ611JsWGN8bQ1tVSDX4s6JllfEH6wmsYxNjTUAMrPmNA8w== -markdown-toc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/markdown-toc/-/markdown-toc-1.2.0.tgz#44a15606844490314afc0444483f9e7b1122c339" - integrity sha512-eOsq7EGd3asV0oBfmyqngeEIhrbkc7XVP63OwcJBIhH2EpG2PzFcbZdhy1jutXSlRBBVMNXHvMtSr5LAxSUvUg== - dependencies: - concat-stream "^1.5.2" - diacritics-map "^0.1.0" - gray-matter "^2.1.0" - lazy-cache "^2.0.2" - list-item "^1.1.1" - markdown-link "^0.1.1" - minimist "^1.2.0" - mixin-deep "^1.1.3" - object.pick "^1.2.0" - remarkable "^1.7.1" - repeat-string "^1.6.1" - strip-color "^0.1.0" - marked@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" @@ -12010,11 +10754,6 @@ math-expression-evaluator@^1.2.14: resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.3.7.tgz#1b62225db86af06f7ea1fd9576a34af605a5b253" integrity sha512-nrbaifCl42w37hYd6oRLvoymFK42tWB+WQTMFtksDGQMi5GvlJwnz/CsS30FFAISFLtX+A0csJ0xLiuuyyec7w== -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -12024,15 +10763,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -md5@^2.2.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" - integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== - dependencies: - charenc "0.0.2" - crypt "0.0.2" - is-buffer "~1.1.6" - mdast-squeeze-paragraphs@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" @@ -12294,7 +11024,7 @@ minimatch@3.0.4, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -12351,7 +11081,7 @@ mississippi@^3.0.0: stream-each "^1.1.0" through2 "^2.0.0" -mixin-deep@^1.1.3, mixin-deep@^1.2.0: +mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== @@ -12433,14 +11163,6 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" -multipipe@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-1.0.2.tgz#cc13efd833c9cda99f224f868461b8e1a3fd939d" - integrity sha1-zBPv2DPJzamfIk+GhGG44aP9k50= - dependencies: - duplexer2 "^0.1.2" - object-assign "^4.1.0" - nan@^2.12.1, nan@^2.14.0: version "2.14.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" @@ -12478,11 +11200,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -ncp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -12516,13 +11233,6 @@ nimma@0.0.0: astring "^1.4.3" jsep "^0.3.4" -no-case@^2.2.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== - dependencies: - lower-case "^1.1.1" - no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -12623,13 +11333,6 @@ nopt@^5.0.0: dependencies: abbrev "1" -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= - dependencies: - abbrev "1" - normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -12813,16 +11516,6 @@ object-keys@^1.0.12, object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= - -object-path@^0.11.4: - version "0.11.5" - resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.5.tgz#d4e3cf19601a5140a55a16ad712019a9c50b577a" - integrity sha512-jgSbThcoR/s+XumvGMTMf81QVBmah+/Q7K7YduKeKVWL7N111unR2d6pZZarSk6kY/caeNxUDyxOvMWyzoU2eg== - object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" @@ -12868,7 +11561,7 @@ object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0 define-properties "^1.1.3" es-abstract "^1.18.0-next.2" -object.pick@^1.2.0, object.pick@^1.3.0: +object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= @@ -12987,16 +11680,6 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - ospath@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" @@ -13174,13 +11857,6 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@2.1.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= - dependencies: - no-case "^2.2.0" - param-case@^3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" @@ -13307,7 +11983,7 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= @@ -13332,13 +12008,6 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -13489,11 +12158,6 @@ pnp-webpack-plugin@^1.7.0: dependencies: ts-pnp "^1.1.6" -polished@^1.9.2: - version "1.9.3" - resolved "https://registry.yarnpkg.com/polished/-/polished-1.9.3.tgz#d61b8a0c4624efe31e2583ff24a358932b6b75e1" - integrity sha512-4NmSD7fMFlM8roNxs7YXPv7UFRbYzb0gufR5zBxJLRzY54+zFsavxBo6zsQzP9ep6Hh3pC2pTyrpSTBEaB6IkQ== - polished@^3.3.1: version "3.7.1" resolved "https://registry.yarnpkg.com/polished/-/polished-3.7.1.tgz#d1addc87ee16eb5b413c6165eda37600cccb9c11" @@ -14639,7 +13303,7 @@ pretty-hrtime@^1.0.3: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= -prismjs@^1.21.0, prismjs@^1.23.0, prismjs@^1.8.4, prismjs@~1.23.0: +prismjs@^1.21.0, prismjs@^1.8.4, prismjs@~1.23.0: version "1.23.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.23.0.tgz#d3b3967f7d72440690497652a9d40ff046067f33" integrity sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA== @@ -14658,11 +13322,6 @@ prismjs@~1.17.0: optionalDependencies: clipboard "^2.0.0" -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -14724,7 +13383,7 @@ prompts@2.4.0, prompts@^2.0.1, prompts@^2.4.0: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.0.0, prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.0.0, prop-types@^15.5.0, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -14886,13 +13545,6 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.2.tgz#abf64491e6ecf0f38a6502403d4cda04f372dfd3" integrity sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg== -raf@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" - integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== - dependencies: - performance-now "^2.1.0" - rails-erb-loader@^5.5.2: version "5.5.2" resolved "https://registry.yarnpkg.com/rails-erb-loader/-/rails-erb-loader-5.5.2.tgz#db3fa8ac89600f09d179a1a70a2ca18c592576ea" @@ -14911,15 +13563,6 @@ ramda@~0.27.1: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -14968,13 +13611,6 @@ raw-loader@^4.0.2: loader-utils "^2.0.0" schema-utils "^3.0.0" -react-click-outside@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/react-click-outside/-/react-click-outside-3.0.1.tgz#6e77e84d2f17afaaac26dbad743cbbf909f5e24c" - integrity sha512-d0KWFvBt+esoZUF15rL2UBB7jkeAqLU8L/Ny35oLK6fW6mIbOv/ChD+ExF4sR9PD26kVx+9hNfD0FTIqRZEyRQ== - dependencies: - hoist-non-react-statics "^2.1.1" - react-clientside-effect@^1.2.2: version "1.2.5" resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.5.tgz#e2c4dc3c9ee109f642fac4f5b6e9bf5bcd2219a3" @@ -14992,11 +13628,6 @@ react-colorful@^5.1.2: resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.2.2.tgz#0a69d0648db47e51359d343854d83d250a742243" integrity sha512-Xdb1Rl6lZ5SMdNBH59eE0lGqR1g2LVD8IgPlw0WeMDrOC65lYI8fgMEwj/0dDpVRVMh5qp73ciISDst/t2O2iQ== -react-content-loader@^3.1.2: - version "3.4.2" - resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-3.4.2.tgz#187fbec2aa389635e4613faa046713f196173f40" - integrity sha512-UsL3uyPUBZbaPXr52E+MMIOjs7qr6QpcCiF9Xt7we0ACEMAFYp6rWNxVwJbk4/1Peqe9Deajs0PRW5ymvyF5SA== - react-dev-utils@^11.0.3: version "11.0.4" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.4.tgz#a7ccb60257a1ca2e0efe7a83e38e6700d17aa37a" @@ -15027,7 +13658,7 @@ react-dev-utils@^11.0.3: strip-ansi "6.0.0" text-table "0.2.0" -react-dom@16.14.0, react-dom@^16.4.0, react-dom@^16.8.3: +react-dom@16.14.0, react-dom@^16.8.3: version "16.14.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== @@ -15062,34 +13693,16 @@ react-element-to-jsx-string@^14.3.2: "@base2/pretty-print-object" "1.0.0" is-plain-object "3.0.1" -react-emotion@^9.1.3, react-emotion@^9.2.12: - version "9.2.12" - resolved "https://registry.yarnpkg.com/react-emotion/-/react-emotion-9.2.12.tgz#74d1494f89e22d0b9442e92a33ca052461955c83" - integrity sha512-qt7XbxnEKX5sZ73rERJ92JMbEOoyOwG3BuCRFRkXrsJhEe+rFBRTljRw7yOLHZUCQC4GBObZhjXIduQ8S0ZpYw== - dependencies: - babel-plugin-emotion "^9.2.11" - create-emotion-styled "^9.2.8" - react-error-overlay@^6.0.9: version "6.0.9" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== -react-fast-compare@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" - integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== - react-fast-compare@^3.0.1, react-fast-compare@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== -react-feather@^1.1.0, react-feather@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-1.1.6.tgz#2a547e3d5cd5e383d3da0128d593cbdb3c1b32f7" - integrity sha512-iCofWhTjX+vQwvDmg7o6vg0XrUg1c41yBDZG+l83nz1FiCsleJoUgd3O+kHpOeWMXuPrRIFfCixvcqyOLGOgIg== - react-focus-lock@^2.1.0: version "2.5.0" resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.5.0.tgz#12e3a3940e897c26e2c2a0408cd25ea3c99b3709" @@ -15113,31 +13726,6 @@ react-helmet-async@^1.0.2, react-helmet-async@^1.0.7: react-fast-compare "^3.2.0" shallowequal "^1.1.0" -react-helmet@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-5.2.1.tgz#16a7192fdd09951f8e0fe22ffccbf9bb3e591ffa" - integrity sha512-CnwD822LU8NDBnjCpZ4ySh8L6HYyngViTZLfBBb3NjtrpN8m49clH8hidHouq20I51Y6TpCTISCBbqiY5GamwA== - dependencies: - object-assign "^4.1.1" - prop-types "^15.5.4" - react-fast-compare "^2.0.2" - react-side-effect "^1.1.0" - -react-highlight-words@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/react-highlight-words/-/react-highlight-words-0.11.0.tgz#4f3c2039a8fd275f3ab795e59946b0324d8e6bee" - integrity sha512-b+fgdQXNjX6RwHfiBYn6qH2D2mJEDNLuxdsqRseIiQffoCAoj7naMQ5EktUkmo9Bh1mXq/aMpJbdx7Lf2PytcQ== - dependencies: - highlight-words-core "^1.2.0" - prop-types "^15.5.8" - -react-input-autosize@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2" - integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw== - dependencies: - prop-types "^15.5.8" - react-input-autosize@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" @@ -15174,16 +13762,6 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-popover@^0.5.10: - version "0.5.10" - resolved "https://registry.yarnpkg.com/react-popover/-/react-popover-0.5.10.tgz#40d5e854300a96722ffc1620e49d840cb1ad5db6" - integrity sha512-5SYDTfncywSH00I70oHd4gFRUR8V0rJ4sRADSI/P6G0RVXp9jUgaWloJ0Bk+SFnjpLPuipTKuzQNNd2CTs5Hrw== - dependencies: - css-vendor "^0.3.1" - debug "^2.6.8" - lodash.throttle "^3.0.3" - prop-types "^15.5.10" - react-popper-tooltip@^2.8.3: version "2.11.1" resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.11.1.tgz#3c4bdfd8bc10d1c2b9a162e859bab8958f5b2644" @@ -15222,44 +13800,6 @@ react-popper@^2.2.4: react-fast-compare "^3.0.1" warning "^4.0.2" -react-router-dom@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6" - integrity sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA== - dependencies: - history "^4.7.2" - invariant "^2.2.4" - loose-envify "^1.3.1" - prop-types "^15.6.1" - react-router "^4.3.1" - warning "^4.0.1" - -react-router@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e" - integrity sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg== - dependencies: - history "^4.7.2" - hoist-non-react-statics "^2.5.0" - invariant "^2.2.4" - loose-envify "^1.3.1" - path-to-regexp "^1.7.0" - prop-types "^15.6.1" - warning "^4.0.1" - -react-select@^2.1.2: - version "2.4.4" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-2.4.4.tgz#ba72468ef1060c7d46fbb862b0748f96491f1f73" - integrity sha512-C4QPLgy9h42J/KkdrpVxNmkY6p4lb49fsrbDk/hRcZpX7JvZPNb6mGj+c5SzyEtBv1DmQ9oPH4NmhAFvCrg8Jw== - dependencies: - classnames "^2.2.5" - emotion "^9.1.2" - memoize-one "^5.0.0" - prop-types "^15.6.0" - raf "^3.4.0" - react-input-autosize "^2.2.1" - react-transition-group "^2.2.1" - react-select@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.2.0.tgz#de9284700196f5f9b5277c5d850a9ce85f5c72fe" @@ -15274,20 +13814,6 @@ react-select@^3.2.0: react-input-autosize "^3.0.0" react-transition-group "^4.3.0" -react-show@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/react-show/-/react-show-2.0.4.tgz#11724797e6baebab76028e14f72c36379871c887" - integrity sha1-EXJHl+a666t2Ao4U9yw2N5hxyIc= - dependencies: - raf "^3.4.0" - -react-side-effect@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.2.0.tgz#0e940c78faba0c73b9b0eba9cd3dda8dfb7e7dae" - integrity sha512-v1ht1aHg5k/thv56DRcjw+WtojuuDHFUgGfc+bFHOWsF4ZK6C2V57DO0Or0GPsg6+LSTE0M6Ry/gfzhzSwbc5w== - dependencies: - shallowequal "^1.0.1" - react-sizeme@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-3.0.1.tgz#4d12f4244e0e6a0fb97253e7af0314dc7c83a5a0" @@ -15320,17 +13846,6 @@ react-syntax-highlighter@^13.5.3: prismjs "^1.21.0" refractor "^3.1.0" -react-syntax-highlighter@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-7.0.4.tgz#38d0cabada32fd4a7d08db4b7fbdb33565c9420d" - integrity sha512-WtaHAlI5++csZ5uTnJc5+ozqqIzUkO/rnkv1GJ3CeRtjhTzbo12r9F0BICzhibr7gBWECd1Xgj1FKJEWZxcP4w== - dependencies: - babel-runtime "^6.18.0" - highlight.js "~9.12.0" - lowlight "~1.9.1" - prismjs "^1.8.4" - refractor "^2.4.1" - react-tabs@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-3.2.2.tgz#07bdc3cdb17bdffedd02627f32a93cd4b3d6e4d0" @@ -15339,13 +13854,6 @@ react-tabs@^3.2.2: clsx "^1.1.0" prop-types "^15.5.0" -react-text-mask@^5.4.3: - version "5.4.3" - resolved "https://registry.yarnpkg.com/react-text-mask/-/react-text-mask-5.4.3.tgz#991efb4299e30c2e6c2c46d13f617169463e0d2d" - integrity sha1-mR77QpnjDC5sLEbRP2FxaUY+DS0= - dependencies: - prop-types "^15.5.6" - react-textarea-autosize@^7.1.0: version "7.1.2" resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.1.2.tgz#70fdb333ef86bcca72717e25e623e90c336e2cda" @@ -15363,16 +13871,6 @@ react-textarea-autosize@^8.3.0: use-composed-ref "^1.0.0" use-latest "^1.0.0" -react-transition-group@^2.2.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" - integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== - dependencies: - dom-helpers "^3.4.0" - loose-envify "^1.4.0" - prop-types "^15.6.2" - react-lifecycles-compat "^3.0.4" - react-transition-group@^4.3.0: version "4.4.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" @@ -15383,7 +13881,7 @@ react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react@16.14.0, react@^16.4.0, react@^16.8.3: +react@16.14.0, react@^16.8.3: version "16.14.0" resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== @@ -15475,16 +13973,6 @@ readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@~1.0.17, readable-stream@~1.0.27-1: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -15618,7 +14106,7 @@ regenerate-unicode-properties@^8.2.0: dependencies: regenerate "^1.4.0" -regenerate@^1.2.1, regenerate@^1.4.0: +regenerate@^1.4.0: version "1.4.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== @@ -15633,15 +14121,6 @@ regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7, regenerator-runtime@^0 resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - regenerator-transform@^0.14.2: version "0.14.5" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" @@ -15670,15 +14149,6 @@ regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - regexpu-core@^4.7.1: version "4.7.1" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" @@ -15691,23 +14161,11 @@ regexpu-core@^4.7.1: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.2.0" -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= - regjsgen@^0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= - dependencies: - jsesc "~0.5.0" - regjsparser@^0.6.4: version "0.6.7" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.7.tgz#c00164e1e6713c2e3ee641f1701c4b7aa0a7f86c" @@ -15715,7 +14173,7 @@ regjsparser@^0.6.4: dependencies: jsesc "~0.5.0" -relateurl@0.2.x, relateurl@^0.2.7: +relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= @@ -15788,14 +14246,6 @@ remark-squeeze-paragraphs@4.0.0: dependencies: mdast-squeeze-paragraphs "^4.0.0" -remarkable@^1.7.1: - version "1.7.4" - resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.4.tgz#19073cb960398c87a7d6546eaa5e50d2022fcd00" - integrity sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg== - dependencies: - argparse "^1.0.10" - autolinker "~0.28.0" - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -15817,18 +14267,11 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - request-progress@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" @@ -15929,11 +14372,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -16148,14 +14586,6 @@ schema-utils@2.7.0: ajv "^6.12.2" ajv-keywords "^3.4.1" -schema-utils@^0.4.5: - version "0.4.7" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" - integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== - dependencies: - ajv "^6.1.0" - ajv-keywords "^3.1.0" - schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -16183,14 +14613,6 @@ schema-utils@^3.0.0, schema-utils@^3.1.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -section-matter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" - integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== - dependencies: - extend-shallow "^2.0.1" - kind-of "^6.0.0" - select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -16213,7 +14635,7 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -16297,7 +14719,7 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.14.1, serve-static@^1.13.2: +serve-static@1.14.1: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== @@ -16312,13 +14734,6 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-getter@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.1.tgz#a3110e1b461d31a9cfc8c5c9ee2e9737ad447102" - integrity sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw== - dependencies: - to-object-path "^0.3.0" - set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -16357,7 +14772,7 @@ shallow-equal@^1.1.0: resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da" integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA== -shallowequal@^1.0.1, shallowequal@^1.1.0: +shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== @@ -16468,13 +14883,6 @@ simple-get@^3.0.3: once "^1.3.1" simple-concat "^1.0.0" -simple-git@^1.95.0: - version "1.132.0" - resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.132.0.tgz#53ac4c5ec9e74e37c2fd461e23309f22fcdf09b1" - integrity sha512-xauHm1YqCTom1sC9eOjfq3/9RKiUA9iPnxBbrY2DdL8l4ADMu0jjM5l5lphQP5YWNqAL2aXC/OeuQ76vHtW5fg== - dependencies: - debug "^4.0.1" - simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" @@ -16516,11 +14924,6 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" @@ -16651,13 +15054,6 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -16681,7 +15077,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.2, source-map@^0.7.3, source-map@~0.7.2: +source-map@^0.7.3, source-map@~0.7.2: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== @@ -17025,11 +15421,6 @@ strip-ansi@^7.0.0: dependencies: ansi-regex "^6.0.0" -strip-bom-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -17040,11 +15431,6 @@ strip-bom@^4.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== -strip-color@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/strip-color/-/strip-color-0.1.0.tgz#106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b" - integrity sha1-EG9l09PmotlAHKwOsM6LinArT3s= - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -17106,14 +15492,6 @@ styled-components@^5.3.0: shallowequal "^1.1.0" supports-color "^5.5.0" -styled-system@^3.1.11: - version "3.2.1" - resolved "https://registry.yarnpkg.com/styled-system/-/styled-system-3.2.1.tgz#491e1e6f88d7ee021f6f49376f12852cde8007cb" - integrity sha512-ag0Yp7UeVHHc3t+1uM3jvlljaZYzwqpbJ8hMrFvpaKfUd8xsB9JeQXLwMpEsz8iLx8Lz/+9j0coWFZjmw8MogQ== - dependencies: - "@babel/runtime" "^7.1.2" - prop-types "^15.6.2" - stylehacks@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" @@ -17123,16 +15501,6 @@ stylehacks@^4.0.0: postcss "^7.0.0" postcss-selector-parser "^3.0.0" -stylis-rule-sheet@^0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" - integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== - -stylis@^3.5.0: - version "3.5.4" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" - integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== - sugarss@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-1.0.1.tgz#be826d9003e0f247735f92365dc3fd7f1bae9e44" @@ -17140,11 +15508,6 @@ sugarss@^1.0.1: dependencies: postcss "^6.0.14" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -17444,14 +15807,6 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through2@~0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" - integrity sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s= - dependencies: - readable-stream "~1.0.17" - xtend "~2.1.1" - through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -17479,23 +15834,11 @@ tiny-emitter@^2.0.0: resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== -tiny-invariant@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" - integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== - -tiny-warning@^1.0.0, tiny-warning@^1.0.3: +tiny-warning@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmp@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" @@ -17513,11 +15856,6 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -17565,23 +15903,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== -toml@^2.3.2: - version "2.3.6" - resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.6.tgz#25b0866483a9722474895559088b436fd11f861b" - integrity sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ== - totalist@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== -touch@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/touch/-/touch-2.0.2.tgz#ca0b2a3ae3211246a61b16ba9e6cbf1596287164" - integrity sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A== - dependencies: - nopt "~1.0.10" - tough-cookie@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" @@ -17606,11 +15932,6 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - trim-trailing-lines@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" @@ -17758,14 +16079,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -uglify-js@3.4.x: - version "3.4.10" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" - integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== - dependencies: - commander "~2.19.0" - source-map "~0.6.1" - uglify-js@^3.1.4: version "3.13.1" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.1.tgz#2749d4b8b5b7d67460b4a418023ff73c3fefa60a" @@ -17791,7 +16104,7 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" -unfetch@^4.0.1, unfetch@^4.2.0: +unfetch@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== @@ -17977,11 +16290,6 @@ upath@^1.1.1: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -upper-case@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -18147,11 +16455,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -18225,7 +16528,7 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -warning@^4.0.1, warning@^4.0.2, warning@^4.0.3: +warning@^4.0.2, warning@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== @@ -18322,7 +16625,7 @@ webpack-cli@^3.3.12: v8-compile-cache "^2.1.1" yargs "^13.3.2" -webpack-dev-middleware@^3.1.3, webpack-dev-middleware@^3.7.3: +webpack-dev-middleware@^3.7.3: version "3.7.3" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== @@ -18381,7 +16684,7 @@ webpack-filter-warnings-plugin@^1.2.1: resolved "https://registry.yarnpkg.com/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz#dc61521cf4f9b4a336fbc89108a75ae1da951cdb" integrity sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg== -webpack-hot-middleware@^2.22.2, webpack-hot-middleware@^2.25.0: +webpack-hot-middleware@^2.25.0: version "2.25.0" resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.25.0.tgz#4528a0a63ec37f8f8ef565cf9e534d57d09fe706" integrity sha512-xs5dPOrGPCzuRXNi8F6rwhawWvQQkeli5Ro48PRuQh8pYPCPmNnltP9itiUPT4xI8oW+y0m59lyyeQk54s5VgA== @@ -18414,7 +16717,7 @@ webpack-virtual-modules@^0.2.2: dependencies: debug "^3.0.0" -webpack@4, webpack@^4.46.0, webpack@^4.8.3: +webpack@4, webpack@^4.46.0: version "4.46.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== @@ -18593,13 +16896,6 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -ws@^5.2.0: - version "5.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" - integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== - dependencies: - async-limiter "~1.0.0" - ws@^7.3.1, ws@^7.4.6: version "7.5.3" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" @@ -18630,13 +16926,6 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= - dependencies: - object-keys "~0.4.0" - y18n@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"