diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index c4a8fee5514..00000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2018, - "sourceType": "module", - "ecmaFeatures": { - "jsx": true - } - }, - "plugins": ["@typescript-eslint"], - "rules": { - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-unused-vars": "off", - "no-prototype-builtins": "off", - "no-useless-escape": "off", - "prefer-spread": "off" - } -} diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 750cea4b16e..f893380efb0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,33 +2,117 @@ # https://help.github.com/en/articles/about-github-actions # https://help.github.com/en/articles/workflow-syntax-for-github-actions -name: Install Dependencies, Lint +name: Validate Docs on: [pull_request] +# A new push supersedes the run before it. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: 24 + jobs: - test: - name: Test on ${{ matrix.os }} + # Needs no dependencies, so it reports in seconds rather than queueing behind + # npm ci and lint. + admonitions: + name: Check Admonitions + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # The check diffs against the pull request base, so it needs history. + fetch-depth: 0 + - uses: ./.github/workflows/actions/check-admonitions + + # These produce the same verdict on any operating system, so they run once. + checks: + name: Checks + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: ⚙️ Use Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + - name: 🕸️ Install Dependencies + run: npm ci + - name: Test + run: npm run test + - name: 🧩 Typecheck + run: npm run typecheck + - name: 🔤 Spell Check + run: npm run spellcheck + # Docusaurus derives a heading's anchor from its text, so renaming a + # heading moves the anchor and breaks every inbound link. An explicit id + # survives the rename, and lets a translation keep the English anchor + # after the heading text is translated. + # + # Nothing in Docusaurus enforces this: a page whose headings are all + # unpinned builds clean. So run its own generator and fail if it had + # anything to add. + - name: 🔗 Heading IDs + run: | + npm run heading-ids + if ! git diff --quiet -- docs; then + echo "::error::Headings are missing explicit ids. Run \`npm run heading-ids\` and commit the result." + git diff -- docs + exit 1 + fi + - uses: ./.github/workflows/actions/check-translations + # Vercel builds on Linux, where imports are case-sensitive. No other check + # resolves the imports in doc pages, so an import with the wrong casing only + # fails when the site is built. + - name: 🏗️ Build + run: | + npm run generate-markdown + npm run build:preview + env: + # The release notes page reads releases from the GitHub API, and the + # script fails in CI without a token. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + cross-platform: + name: Cross-platform on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: matrix: - node_version: [20] + # Prettier rewrites line endings, so Lint is the one check whose + # verdict depends on the operating system. os: [windows-latest, macOS-latest] steps: - - uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node_version }} - uses: actions/setup-node@v4 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: ⚙️ Use Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: - node-version: ${{ matrix.node_version }} - - name: Install Dependencies - run: npm ci --legacy-peer-deps - - name: Lint + node-version: ${{ env.NODE_VERSION }} + cache: npm + - name: 🕸️ Install Dependencies + run: npm ci + - name: 🖌️ Lint run: npm run lint - - name: Spell Check - run: npm run spellcheck - # Lint and spell check changes should be pushed - # to the branch before the branch is merge eligible. - - name: Check Diff + # Lint changes should be pushed to the branch before the branch is merge + # eligible. + - name: 🔍 Check Diff run: git diff --exit-code shell: bash + + verify: + # The one required check on main and the feature branches, so the jobs + # above can change without touching the protection rules. Renaming this + # blocks merges until those rules are updated to match. + name: Verify + if: ${{ always() }} + needs: [admonitions, checks, cross-platform] + runs-on: ubuntu-latest + + steps: + - name: Check job status + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + run: exit 1 diff --git a/.github/workflows/actions/check-admonitions/action.yml b/.github/workflows/actions/check-admonitions/action.yml new file mode 100644 index 00000000000..8cd33474a5d --- /dev/null +++ b/.github/workflows/actions/check-admonitions/action.yml @@ -0,0 +1,89 @@ +name: 'Check Admonitions' +description: 'Fails on admonition titles using the MDX v1 syntax' +runs: + using: 'composite' + steps: + # `:::note My Title` was MDX v1 syntax that Docusaurus rewrote for us. + # With `future.v4.mdx1CompatDisabledByDefault` that shim is off, and + # the block `:::note My Title` stops being a directive: it renders as + # literal `:::note` text on the page, with no warning and a successful + # build. + # + # The other MDX v1 forms, HTML comments and `{#heading-ids}`, fail the + # build on their own, so this only covers the one that fails silently. + # + # Only the files the pull request touches are checked, so an existing + # page is never anyone else's problem to fix. + # + # The caller has to check out with `fetch-depth: 0`, which a composite + # action cannot require for itself. + - name: 🔎 Check Admonitions + shell: bash + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + CHANGED_FILES: ${{ runner.temp }}/changed-files.txt + run: | + git diff --name-only --diff-filter=ACMR "$BASE_SHA" HEAD > "$CHANGED_FILES" + node <<'JS' + const { readFileSync } = require('fs'); + + // Files Docusaurus compiles as MDX. Under `static/usage` that is + // only the `index` files; the rest are raw code samples. + const compiled = (f) => + !f.endsWith('README.md') && + ((/^(docs|versioned_docs|src\/pages)\//.test(f) && /\.mdx?$/.test(f)) || + (f.startsWith('static/usage/') && f.endsWith('.mdx'))); + + // Defaults from `@docusaurus/mdx-loader/lib/remark/admonitions`. + const keywords = + 'secondary|info|success|danger|note|tip|warning|important|caution'; + const legacyTitle = new RegExp( + `^[ \\t]*:::(?:${keywords})[ \\t]+(?!\\[)\\S[^\\n]*`, + 'gm' + ); + + // A `:::note` in a code sample is an example, not a directive. + // Blank out code samples with spaces, same length so line numbers + // still match. + const blank = (m) => m.replace(/[^\n]/g, ' '); + const mask = (t) => + t + .replace(/^([ \t]*)(`{3,}|~{3,})[^\n]*\n[\s\S]*?^\1\2[ \t]*$/gm, blank) + .replace(/(`+)(?:(?!\1)[\s\S])+?\1/g, blank); + + const files = readFileSync(process.env.CHANGED_FILES, 'utf8') + .split('\n') + .filter(compiled); + + if (!files.length) { + console.log('No MDX files changed.'); + process.exit(0); + } + + const findings = []; + for (const file of files) { + const source = readFileSync(file, 'utf8'); + for (const m of mask(source).matchAll(legacyTitle)) { + findings.push({ + file, + line: source.slice(0, m.index).split('\n').length, + text: source.slice(m.index, m.index + m[0].length).trim(), + }); + } + } + + if (!findings.length) { + console.log(`No MDX v1 admonition titles in ${files.length} changed file(s).`); + process.exit(0); + } + + // `::error` puts each one on the offending line in the Files changed + // tab and prints it in red in the log, so the failure is not something + // to go hunting for. The message leads with the fix because the found + // text starts with `:::`, which reads badly right after the delimiter. + for (const { file, line, text } of findings) { + const fix = 'Wrap the title in brackets, for example :::note[My Title]'; + console.log(`::error file=${file},line=${line},title=MDX v1 admonition title::${fix}%0A%0AFound: ${text}`); + } + process.exit(1); + JS diff --git a/.github/workflows/actions/check-translations/action.yml b/.github/workflows/actions/check-translations/action.yml new file mode 100644 index 00000000000..3e53a643597 --- /dev/null +++ b/.github/workflows/actions/check-translations/action.yml @@ -0,0 +1,20 @@ +name: 'Check Translations' +description: 'Validates the translated locales without building them' +runs: + using: 'composite' + steps: + # Surfaces failures unique to a translated locale, such as duplicate + # translation keys, while the changes are still in review. Previews only + # build the default locale, so translated locale issues would not surface + # until after merging into main. + # + # The sidebars reference the native and CLI docs, which are generated rather + # than committed, so those have to exist before the translations can be + # extracted. + - name: 🇯🇵 Extract Translations + shell: bash + run: | + trap 'rm -rf i18n' EXIT + node scripts/native.mjs + node scripts/cli.mjs + npx docusaurus write-translations --locale ja diff --git a/.gitignore b/.gitignore index a1ae05b6ea1..37f55c23bec 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ # Generated files .docusaurus .cache-loader +.eslintcache +.cspellcache src/components/page/reference/ReleaseNotes/release-notes.json # Misc diff --git a/.prettierignore b/.prettierignore index e523352d6cd..90a6a6c2be7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,13 +1,29 @@ -src/theme/DocItem -src/theme/DocRoot -legacy-stencil-components -scripts/bak +# Ejected components keep upstream's formatting so they stay diffable against +# @docusaurus/theme-classic. Refer to `src/theme/README.md`. +# Wrapped components are our own code, so they follow the repo's formatting. +src/theme/DocItem/Layout/index.tsx +src/theme/EditMetaRow/index.tsx +src/theme/Icon/DarkMode/index.tsx +src/theme/Icon/Edit/index.tsx +src/theme/Icon/LightMode/index.tsx +src/theme/Icon/Language/index.tsx +src/theme/Layout/index.tsx +src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx +src/theme/prism-include-languages.ts -docs/api + +# Auto-generated files docs/native versioned_docs/version-v*/native docs/cli/commands -docs/reference/glossary.md +versioned_docs/version-v*/cli/commands + +# Archived versions +versioned_docs/version-v5 +versioned_docs/version-v6 +versioned_docs/version-v7 +static/usage/v6 +static/usage/v7 static/code/stackblitz diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000000..2b532afe4ce --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,11 @@ +/** + * Prettier configuration for the docs site. + */ + +const ionicConfig = require('@ionic/prettier-config'); + +module.exports = { + ...ionicConfig, + // Override the trailingComma setting to avoid trailing commas in function arguments and JSX props. + trailingComma: 'es5', +}; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6f589964046..a009111539f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,17 +8,23 @@ Thanks for your interest in contributing to Ionic's documentation! :tada: Check - [Development Workflow](#development-workflow) - [Previewing Changes](#previewing-changes) + - [Checking Links](#checking-links) - [Linting Documentation](#linting-documentation) - [Spell Check](#spell-check) + - [Heading IDs](#heading-ids) - [Using VS Code on Windows](#using-vs-code-on-windows) - [Project Structure](#project-structure) - [Directories](#directories) - [Authoring Content](#authoring-content) + - [Admonitions](#admonitions) + - [Links and Headings](#links-and-headings) + - [Playgrounds](#playgrounds) - [Reference Content](#reference-content) - [Translation](#translation) - [Reporting Issues](#reporting-issues) - [Pull Request Guidelines](#pull-request-guidelines) - [Deploying](#deploying) + - [Archiving a Version](#archiving-a-version) - [License](#license) --- @@ -27,16 +33,62 @@ Thanks for your interest in contributing to Ionic's documentation! :tada: Check ### Previewing Changes -In order to run the documentation locally, install the dependencies and run the development server: +In order to run the documentation locally, use Node.js 24 or later, install the dependencies and run the development server: ```sh -npm install +npm ci npm start ``` +#### GitHub Token + +The documentation build requires a GitHub Personal Access Token to fetch Ionic Framework release notes. The build still works locally without it, with an empty release notes page, but Vercel preview and production builds fail without it. + +**Local Development:** + +1. Create a [fine-grained Personal Access Token](https://github.com/settings/personal-access-tokens/new) with: + + - **Repository access**: Public repositories (read-only) + - **Expiration**: 366 days (update annually) + +2. Add the token to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.): + + ```sh + export GITHUB_TOKEN=github_pat_... + ``` + +3. Reload your shell or run `source ~/.zshrc` (or equivalent) + +**Vercel:** + +1. Create a [fine-grained Personal Access Token](https://github.com/settings/personal-access-tokens/new) with the same settings as above, but with: + + - **Owner**: ionic-team organization (not your personal account) + +2. Add the token to Vercel project settings: + + - Go to your project on Vercel + - Navigate to **Settings → Environment Variables** + - Add `GITHUB_TOKEN` with the token value + - Select Production and Preview environments + +3. Redeploy the project for the token to take effect + +If the token is missing, Vercel builds fail with `GITHUB_TOKEN environment variable is required.` + +### Checking Links + +The development server does not check for broken links or anchors. Only a build does, and it fails on any it finds. Build the site before pushing a change that adds or moves links or headings: + +```sh +npm run build:preview +``` + +This builds the English site only, the same build as a Vercel preview. + ### Linting Documentation -This repository uses [Prettier](https://prettier.io/), an opinionated code formatter, in order to keep consistent formatting throughout the documentation. Run the following command to automatically fix all formatting, and then push any changes: +This repository uses [ESLint](https://eslint.org/) to catch markup the build cannot check, such as raw links and headings and misaligned JSDoc comments, and [Prettier](https://prettier.io/), an opinionated code formatter, to keep consistent formatting throughout the documentation. Run the following command to report ESLint errors and automatically fix all formatting, and then push any changes: ``` npm run lint @@ -62,17 +114,17 @@ npm run spellcheck - A **directory** or anything matching a **regular expression**, update the following file: `cspell.json` - For example, we don't want to flag anything inside of code ticks (`) or code blocks (```), so there are regular expressions added to ignore anything inside of these. - An **entire line**, add the following comment above it: - ```markdown - + ```mdx + {/* cspell:disable-next-line */} ``` - **Multiple lines**, add comments above and below the lines to be ignored: - ```markdown - + ```mdx + {/* cspell:disable */} -

Everything inside of these comments will be ignored by the spell checkr. Proofread your own words carefully.

+

Everything inside of these comments will be ignored by the spell checker. Proofread your own words carefully.

- + {/* cspell:enable */} ``` > [!IMPORTANT] @@ -87,11 +139,25 @@ Comments disabling the next line or entire sections of documentation are useful In general, we should try to avoid ignoring words unless they are technical terms that are used throughout the documentation and wouldn't necessarily make sense formatted as code. +### Heading IDs + +Every heading in `docs/` needs an explicit ID, so that renaming the heading doesn't change its anchor and break links to it: + +```mdx +## Basic Usage {/* #basic-usage */} +``` + +Run the following command to add IDs to any new headings, and then push the changes. CI fails if a heading is missing one. + +``` +npm run heading-ids +``` + --- ## Using VS Code on Windows -The Ionic docs were originally built in a Mac-based environment, so Mac-focused linting rules apply when committing changes. To contribute on Windows, do the following: +Prettier expects LF line endings, and CI fails if `npm run lint` changes any file. To contribute on Windows, do the following: - Configure VS Code to read/save files using line breaks (LF) instead of carriage returns (CRLF). Set it globally by navigating to: Settings -> Text Editor -> Files -> Eol. Set to `\n`. - Check that the Git setting `core.autocrlf` is set to `false`: run `git config -l | grep autocrlf`. Switch it to false using: `git config --global core.autocrlf false`. @@ -103,14 +169,19 @@ Ionic's documentation is built using [Docusaurus](https://docusaurus.io/). The c ### Directories +- `_templates/` - templates used by `npm run playground:new` +- `docs/` - content of the current version of the docs +- `plugins/` - local Docusaurus plugins, such as the one that generates the component API pages - `scripts/` - build scripts used to generate markdown or json files -- `src/` - source code and content of the docs +- `src/` - source code of the site - `components/` - components used across the site - `global/` - components used globally - `page/` - components used on a single page or in a limited scope - `styles/` - global styles and variables - `components/` - styles split out into the components they target + - `theme/` - Docusaurus theme components that have been swizzled - `static/` + - `code/` - StackBlitz project templates used by the playgrounds - `demos/` - self-contained demos, optionally presented by pages via `demoUrl` YAML frontmatter - `usage/` - playgrounds that can be created by running `npm run playground:new` [(docs)](_templates/README.md#new-playground-template) - `versioned_docs/` - versions of the docs created by the docusaurus versioning command @@ -121,22 +192,81 @@ Ionic's documentation is built using [Docusaurus](https://docusaurus.io/). The c The content of the Ionic docs is written as [Markdown](https://commonmark.org/) in `docs/`. Each Markdown file corresponds to a route unless explicitly changed in the frontmatter. ``` -/docs/ => src/pages/index.md -/docs/intro/cli => src/pages/intro/cli.md -/docs/theming/advanced => src/pages/theming/advanced.md -/docs/theming => src/pages/theming.md +/docs => docs/index.mdx +/docs/intro/cli => docs/intro/cli.mdx +/docs/theming/basics => docs/theming/basics.mdx +/docs/v8/intro/cli => versioned_docs/version-v8/intro/cli.mdx +``` + +`/docs` maps to `docs/index.mdx` through `slug: /` in its frontmatter. Older versions live in `versioned_docs/` and are served under their version, such as `/docs/v8/`. + +Versions listed in [`versions.json`](versions.json) are actively maintained. If your change also applies to one of them, make the same change in its `versioned_docs/version-/` folder. Versions listed in [`versionsArchived.json`](versionsArchived.json) are frozen deployments that are no longer built, so changes to their folders never reach the site. + +Markdown links resolve within their own version, but JSX paths such as `` and `useBaseUrl` do not. In an older version, prefix them with the version, such as ``. + +You can make copy edits to the site by [editing the Markdown files directly on GitHub](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files). In your pull request, please explain what was missing from or inaccurate about the content. + +### Admonitions + +Give an admonition a title with square brackets. The older `:::note My Title` form renders as plain text with no build error, so CI fails on it: + +```mdx +:::note[My Title] + +Content + +::: +``` + +### Links and Headings + +Use Markdown for links and headings whenever possible. When you need JSX, such as inside a component prop or in `src/`, use the Docusaurus components instead of raw HTML: + +- [``](https://docusaurus.io/docs/docusaurus-core#link) from `@docusaurus/Link` instead of ``. It handles the base URL and locale, and opens external URLs in a new tab with `rel="noopener noreferrer"`. +- [``](https://docusaurus.io/docs/api/misc/@docusaurus/eslint-plugin/prefer-docusaurus-heading) from `@theme/Heading` instead of `

` to `

`. + +The build only checks links and anchors that go through Markdown or these components. A raw `` to a page that doesn't exist builds without errors, and a raw heading's `id` can't be used as a link target. + +Markup inside code samples is exempt, since it's example code rather than part of the page. CI fails on a raw `` or heading anywhere else. To check before pushing, run: + +``` +npm run lint +``` + +### Playgrounds + +A playground is the interactive example on a component page. It shows a live demo that switches between iOS and Material Design modes, the code for JavaScript, Angular, React and Vue, and a button to open the example in StackBlitz. + +Each playground is a folder in `static/usage////`: + +- `demo.html`: the live demo, so update it along with the framework code +- `javascript.md`, `react.md`, `vue.md` and `angular/`: the code shown for each framework +- `index.mdx`: renders the `Playground` component with those files + +Run the following command to generate a playground, and then import its `index.mdx` into the page: + +``` +npm run playground:new +``` + +```mdx +import Basic from '@site/static/usage/v9/button/basic/index.mdx'; + + ``` -You can make copy edits to the site by [editing the Markdown files directly on GitHub](https://help.github.com/articles/editing-files-in-another-user-s-repository/). In your pull request, please explain what was missing from or inaccurate about the content. +For the generator's prompts, refer to the [playground template docs](_templates/README.md#new-playground-template). For the `Playground` options, refer to its [README](src/components/global/Playground/README.md). ### Reference Content The Markdown in `docs/` does not only contain manually written markdown files: -- Paths matching `/docs/api/*` are built from the [Ionic Framework](https://github.com/ionic-team/ionic) source code -- Paths matching `/docs/native/*` are built from the [Ionic Native](https://github.com/ionic-team/ionic-native) source code +- The properties, events, methods, and other API tables on `/docs/api/*` pages are built from the [Ionic Framework](https://github.com/ionic-team/ionic-framework) source code +- Paths matching `/docs/native/*` are built from the [Capacitor plugins](https://github.com/ionic-team/capacitor-plugins) READMEs - Paths matching `/docs/cli/commands/*` are built from the [Ionic CLI](https://github.com/ionic-team/ionic-cli) source code +The `native/` and `cli/commands/` pages are generated when you run `npm start` or build the site, and they are not committed. To change them, edit the plugin's README in [capacitor-plugins](https://github.com/ionic-team/capacitor-plugins) or the command's source in [ionic-cli](https://github.com/ionic-team/ionic-cli). + ## Translation The Ionic docs have been translated into Japanese and are in the process of being translated into Chinese, French, Portuguese, and Spanish. We've chosen these languages because we believe they have the greatest number of developers where English-only documentation would be a barrier. @@ -147,7 +277,7 @@ _Please submit translation issues to the Crowdin page and not the Ionic Docs Git -The Japanese translation of the docs were built by an independent team, lead by [rdlabo](https://github.com/rdlabo) and can be found and contributed to on the [ionic-jp group's `ionic-docs` project page](https://github.com/ionic-jp/ionic-docs). +The Japanese translation of the docs were built by an independent team, led by [rdlabo](https://github.com/rdlabo) and can be found and contributed to on the [ionic-jp group's `ionic-docs` project page](https://github.com/ionic-jp/ionic-docs). ## Reporting Issues @@ -158,7 +288,7 @@ If the issue you're reporting is a bug, please be sure it is an issue with the I - Steps to reproduce - Expected behavior - OS and browser versions -- If possible, a demo repo or CodePen/CodeSandbox +- If possible, a demo repo or StackBlitz > [!NOTE] > Some [reference content](#reference-content) is pulled from other Ionic repos. In that case, please submit your issue on the docs repo with a link to the repo where the content lives. @@ -169,12 +299,135 @@ If the issue you're reporting is a bug, please be sure it is an issue with the I When submitting pull requests, please keep the scope of your change contained to a single feature or bug. When in doubt, err on the side of smaller pull requests. If your pull request is a new feature, we would recommend opening an issue first to come to an agreement about the feature before putting in significant time. +Title your pull request in the [Conventional Commits](https://www.conventionalcommits.org/) format, such as `docs(button): add an icon-only example`. Pull requests are squash merged, so the title becomes the commit message on `main`. + +Each pull request gets a Vercel preview deployment. Use it to check your change on the built site. + --- ## Deploying The Ionic documentation's `main` branch is deployed automatically and separately from the [Ionic site](https://github.com/ionic-team/ionic-site) itself. The Ionic site then uses a proxy for paths under `/docs` to request the deployed documentation. +### Archiving a Version + +Archived versions are served from a frozen Vercel deployment instead of being rebuilt on every `main` deploy, which keeps build times and memory usage low. That deployment is a full snapshot of the site, so it serves every version that was in the build. Two files control this: + +- [`versions.json`](./versions.json): lists the older versions Docusaurus rebuilds on every deploy. It does not include the current version, which is built from `docs/` and takes its label from `versions.current` in `docusaurus.config.js`. +- [`versionsArchived.json`](./versionsArchived.json): maps each archived version to the frozen deployment URL the version picker links to. + +The docs keep the current version plus one older version rebuildable, so each major release archives one version and involves two different version numbers. The steps below refer to them as: + +- ``: the version being frozen and removed from `versions.json`. +- ``: the version that just stopped being current and moved into `versions.json`. It is not being archived, but step 1 has to account for it. + +For example, when `v9` becomes current: `v8` is `` and `v7` is ``. + +The archived URL has to point at a build that _included_ ``, so you build it first, then move it to `versionsArchived.json`: + +1. **Check the `vercel.json` redirects.** The frozen deployment bakes in whatever `vercel.json` looked like at build time, and it serves every version in that build. Any `:version(...)` group missing a version therefore stays broken on that host for good. Make sure the groups already list ``, which is the one most likely to be missing since it only just moved into `versions.json`. The `angular`, `react`, `vue` and `javascript` landing pages each need a group, as no version ships an index page for them: + + ```json + { + "source": "/docs/:version(v6|v7|)/angular", + "destination": "/docs/:version/angular/overview" + }, + { + "source": "/docs/:version()/javascript", + "destination": "/docs/:version/javascript/overview" + } + ``` + + The groups accumulate, so existing entries stay in place whether or not that version is archived and you are only ever adding to them. The `javascript` group only covers versions that have a `javascript/` section. + +Everything from here on refers to ``: + +2. **Build ``.** Make sure it is in `versions.json`. If you are refreshing an already-archived version, move it out of `versionsArchived.json` and back into `versions.json`, and add it back to the generation scripts in step 10. Commit, push and let Vercel deploy. +3. **Promote the deployment.** In the Vercel dashboard, open that deployment and **Promote to Production** so it does not get cleaned up. Wait for the build to finish before pushing again, or it may get canceled. +4. **Copy its URL.** Use the deployment's unique `ionic-docs--ionic1.vercel.app` URL, not the branch or production alias. +5. **Archive it.** Remove `` from `versions.json`, then add it to `versionsArchived.json` with `/docs/` appended and no trailing slash (a trailing slash causes a brief 404 flash): + + _`versions.json`_ + + ```diff + [ + - "v8", + - "" + + "v8" + ] + ``` + + _`versionsArchived.json`_ + + ```json + { + "": "https://ionic-docs--ionic1.vercel.app/docs/", + "v6": "https://ionic-docs-lq0if04rc-ionic1.vercel.app/docs/v6", + "v5": "https://ionic-docs-5utg8ms4c-ionic1.vercel.app/docs/v5" + } + ``` + +6. **Update `.prettierignore`.** Add the archived version folders to the archived versions group to keep Prettier from formatting generated files: + + ``` + static/usage/ + versioned_docs/version- + ``` + +7. **Update `cspell.json`.** Add the archived version to the `ignorePaths` array so the spell checker skips generated files: + + ```diff + "ignorePaths": [ + ... + "versioned_docs/version-v5", + "versioned_docs/version-v6", + + "versioned_docs/version-" + ] + ``` + +8. **Update `renovate.json`.** Add the archived version's StackBlitz examples to `ignorePaths` so Renovate stops opening dependency PRs against frozen examples: + + ```diff + "ignorePaths": [ + "static/code/stackblitz/v6/**", + + "static/code/stackblitz//**" + ] + ``` + + Then remove that version's `@ionic/` `allowedVersions` rule from `packageRules`, since it no longer has anything to match. + +9. **Update the playground generator.** Remove `` from the version choices in [`_templates/playground/new/index.js`](./_templates/playground/new/index.js) so `npm run playground:new` stops offering a version that is no longer built. The choices are bare numbers, without the `v`: + + ```diff + - choices: ['', '8', '9'], + + choices: ['8', '9'], + ``` + +10. **Update the generation scripts.** Remove `` from the write lists in [`scripts/native.mjs`](./scripts/native.mjs) and [`scripts/cli.mjs`](./scripts/cli.mjs), so every build stops regenerating content for a version served from a frozen deployment. The remaining targets are `docs/` (the current version) and the one older version still in `versions.json`. + + _`scripts/native.mjs`_ + + ```diff + writeFileSync(`docs/native/${fileName}`, apiContent); + - writeFileSync(`versioned_docs/version-/native/${fileName}`, apiContent); + writeFileSync(`versioned_docs/version-v8/native/${fileName}`, apiContent); + ``` + + _`scripts/cli.mjs`_ + + ```diff + writeFileSync(`docs/${path}`, data); + - writeFileSync(`versioned_docs/version-/${path}`, data); + writeFileSync(`versioned_docs/version-v8/${path}`, data); + ``` + +11. **Open a PR.** Once merged, the version picker links to the archive and `main` stops building ``. + +Removed versions keep their authored `versioned_docs/` and `versioned_sidebars/` content, so they can be rebuilt anytime by adding them back to `versions.json`. Their `native/` and `cli/commands/` pages are generated rather than committed, so a rebuild also needs the version back in the write lists from step 10. Without it those sections build empty. + +> [!NOTE] +> Ionic v3 and v4 use other build tools and are not managed here. + --- ## License diff --git a/_templates/README.md b/_templates/README.md index 60a3ebef83d..1391840dc16 100644 --- a/_templates/README.md +++ b/_templates/README.md @@ -11,22 +11,25 @@ Some helpful docs links for updating/creating templates: ## Generation -To create a new playground, run `npm run playground:new`. This will walk you through some prompts to decide what files for the generator to create for the playground, and what their paths should be. +To create a new playground, run `npm run playground:new`. This will walk you through some prompts to decide what files for the generator to create for the playground, and what their paths should be: -The path defaults to `basic`. If there is already a basic playground, you'll want to input a different path for the playground. - -The CSS option will add extra files if you need to include custom CSS in your playground. +- **Component or guide:** a component playground goes under the component's name, such as `button`. Any other playground goes under a guide section, such as `animations`, and starts with an `ion-card`. +- **Path:** the folder for the playground under that name, such as `basic` or `theming/colors`. Use `basic` for a component's first playground. +- **Version:** the Ionic Framework version the playground is for. +- **CSS:** adds extra files if you need to include custom CSS in your playground. If you need a component for multiple versions of Ionic Framework, you (currently) need to run the generator once for each version. +If the version you pick is not published to npm yet, such as the next major on a major branch, the generated `demo.html` loads the latest published version from the CDN instead, since the CDN has nothing to serve for an unpublished version. The demo renders, but APIs new in that version do not work in it until the version is published. The generator also adds a `TODO(FW-XXXX)` comment above the CDN links. Replace `FW-XXXX` with the ticket that tracks the update, and create one if it does not exist yet. + ## Usage -Once you've generated your playground, you need to add it to the main markdown file in the docs (e.g. [docs/api/button.md](../docs/api/button.md)) by doing something similar to the following example: +Once you've generated your playground, you need to add it to the main markdown file in the docs (e.g. [docs/api/button.mdx](../docs/api/button.mdx)). The generator prints the snippet to paste when it finishes, which looks similar to the following example: ``` ## Feature -import Feature from '@site/static/usage/v8/button/feature/index.md'; +import Feature from '@site/static/usage/v9/button/feature/index.mdx'; ``` diff --git a/_templates/playground/new/angular_example_component_ts.md.ejs.t b/_templates/playground/new/angular_example_component_ts.md.ejs.t index 548a45dd57b..348bbb0b8df 100644 --- a/_templates/playground/new/angular_example_component_ts.md.ejs.t +++ b/_templates/playground/new/angular_example_component_ts.md.ejs.t @@ -4,7 +4,7 @@ to: "<%= `static/usage/v${version}/${name}/${path}/angular/example_component_ts. --- ```ts import { Component } from '@angular/core'; -import { <%= pascalComponent %> } from '@ionic/angular/standalone'; +import { <%= pascalComponent %> } from '@ionic/angular'; @Component({ selector: 'app-example', diff --git a/_templates/playground/new/demo.html.ejs.t b/_templates/playground/new/demo.html.ejs.t index 3a6a9cadff9..62475d8262a 100644 --- a/_templates/playground/new/demo.html.ejs.t +++ b/_templates/playground/new/demo.html.ejs.t @@ -9,9 +9,10 @@ to: "<%= `static/usage/v${version}/${name}/${path}/demo.html` %>" <%= h.changeCase.titleCase(name) %> - - - <% if (css){ %> + <% if (cdnVersion !== version) { %> + <% } %> + + <% if (css){ %> - - -Ionic apps are made of high-level building blocks called Components, which allow you to quickly construct the UI for your app. Ionic comes stock with a number of components, including cards, lists, and tabs. Once you're familiar with the basics, refer to the [API Index](api.md) for a complete list of each component and sub-component. - - - - - -

Accordions provide collapsible sections in your content to reduce vertical space while providing a way of organizing and grouping information.

-
- - -

Action Sheets display a set of options with the ability to confirm or cancel an action.

-
- - -

Alerts are a great way to offer the user the ability to choose a specific action or list of actions.

-
- - -

Badges are a small component that typically communicate a numerical value to the user.

-
- - -

Breadcrumbs are navigation items that are used to indicate where a user is on an app.

-
- - -

Buttons let your users take action. They're an essential way to interact with and navigate through an app.

-
- - -

- Cards are a great way to display an important piece of content, and can contain images, buttons, text, and more. -

-
- - -

Checkboxes can be used to let the user know they need to make a binary decision.

-
- - -

Chips are a compact way to display data or actions.

-
- - -

Content is the quintessential way to interact with and navigate through an app.

-
- - -

Date & time pickers are used to present an interface that makes it easy for users to select dates and times.

-
- - -

Floating action buttons are circular buttons that perform a primary action on a screen.

-
- - -

The grid is a powerful mobile-first system for building custom layouts.

-
- - -

Beautifully designed icons for use in web, iOS, and Android apps.

-
- - -

Infinite scroll allows you to load new data as the user scrolls through your app.

-
- - -

Inputs provides a way for users to enter data in your app.

-
- - -

- Items are elements that can contain text, icons, avatars, images, inputs, and any other native or custom elements. - Items can be swiped, deleted, reordered, edited, and more. -

-
- - -

Lists can display rows of information, such as a contact list, playlist, or menu.

-
- - -

- A collection of media components, including avatars, icons, images, and thumbnails, designed to enhance visual - content. -

-
- - -

Menus are a common navigation pattern. They can be permanently on-screen, or revealed when needed.

-
- - -

Modals slide in and off screen to display a temporary UI and are often used for login or sign-up pages.

-
- - -

Navigation is how users move between different pages in your app.

-
- - -

Popover provides an easy way to present information or options without changing contexts.

-
- - -

Progress indicators visualize the progression of an operation or activity.

-
- - -

Radio inputs allow you to present a set of exclusive options.

-
- - -

Range sliders let users select a value by dragging a knob along a track.

-
- - -

Refresher provides pull-to-refresh functionality on a content component.

-
- - -

Reorder lets users drag and drop to reorder a list of items.

-
- - -

Routing allows navigation based on the current path.

-
- - -

Searchbar is used to search or filter items, usually from a toolbar.

-
- - -

Segments provide a set of exclusive buttons that can be used as a filter or view switcher.

-
- - -

Select is similar to the native HTML select, with a few improvements to sorting and selecting.

-
- - -

Tabs enable tabbed navigation, a standard navigation pattern in modern apps.

-
- - -

Toasts are subtle notifications that appear over your app's content without interrupting user interaction.

-
- - -

Toggles are an input for binary options, often used for options and switches.

-
- - -

Toolbars are used to house information and actions relating to your app.

-
- - -

Text is used to style or change the color of text within an application.

-
-
diff --git a/docs/components.mdx b/docs/components.mdx new file mode 100644 index 00000000000..34bfd4257c5 --- /dev/null +++ b/docs/components.mdx @@ -0,0 +1,174 @@ +--- +title: UI Components +hide_table_of_contents: true +--- + +import DocsCard from '@components/global/DocsCard'; +import DocsCards from '@components/global/DocsCards'; + + + UI Components | User Interface Application Building Components + + + + +Ionic apps are made of high-level building blocks called Components, which allow you to quickly construct the UI for your app. Ionic comes stock with a number of components, including cards, lists, and tabs. Once you're familiar with the basics, refer to the [API Index](api.mdx) for a complete list of each component and sub-component. + + + +

Accordions provide collapsible sections in your content to reduce vertical space while providing a way of organizing and grouping information.

+
+ + +

Action Sheets display a set of options with the ability to confirm or cancel an action.

+
+ + +

Alerts are a great way to offer the user the ability to choose a specific action or list of actions.

+
+ + +

Badges are a small component that typically communicate a numerical value to the user.

+
+ + +

Breadcrumbs are navigation items that are used to indicate where a user is on an app.

+
+ + +

Buttons let your users take action. They're an essential way to interact with and navigate through an app.

+
+ + + Cards are a great way to display an important piece of content, and can contain images, buttons, text, and more. + + + +

Checkboxes can be used to let the user know they need to make a binary decision.

+
+ + +

Chips are a compact way to display data or actions.

+
+ + +

Content is the quintessential way to interact with and navigate through an app.

+
+ + +

Date & time pickers are used to present an interface that makes it easy for users to select dates and times.

+
+ + +

Floating action buttons are circular buttons that perform a primary action on a screen.

+
+ + +

The grid is a powerful mobile-first system for building custom layouts.

+
+ + +

Beautifully designed icons for use in web, iOS, and Android apps.

+
+ + +

Infinite scroll allows you to load new data as the user scrolls through your app.

+
+ + +

Inputs provide a way for users to enter data in your app.

+
+ + + Items are elements that can contain text, icons, avatars, images, inputs, and any other native or custom elements. + Items can be swiped, deleted, reordered, edited, and more. + + + +

Lists can display rows of information, such as a contact list, playlist, or menu.

+
+ + + A collection of media components, including avatars, icons, images, and thumbnails, designed to enhance visual + content. + + + +

Menus are a common navigation pattern. They can be permanently on-screen, or revealed when needed.

+
+ + +

Modals slide in and off screen to display a temporary UI and are often used for login or sign-up pages.

+
+ + +

Navigation is how users move between different pages in your app.

+
+ + +

Popover provides an easy way to present information or options without changing contexts.

+
+ + +

Progress indicators visualize the progression of an operation or activity.

+
+ + +

Radio inputs allow you to present a set of exclusive options.

+
+ + +

Range sliders let users select a value by dragging a knob along a track.

+
+ + +

Refresher provides pull-to-refresh functionality on a content component.

+
+ + +

Reorder lets users drag and drop to reorder a list of items.

+
+ + +

Routing allows navigation based on the current path.

+
+ + +

Searchbar is used to search or filter items, usually from a toolbar.

+
+ + +

Segments provide a set of exclusive buttons that can be used as a filter or view switcher.

+
+ + +

Select is similar to the native HTML select, with a few improvements to sorting and selecting.

+
+ + +

Tabs enable tabbed navigation, a standard navigation pattern in modern apps.

+
+ + +

Toasts are subtle notifications that appear over your app's content without interrupting user interaction.

+
+ + +

Toggles are an input for binary options, often used for options and switches.

+
+ + +

Toolbars are used to house information and actions relating to your app.

+
+ + +

Text is used to style or change the color of text within an application.

+
+
diff --git a/docs/contributing/coc.mdx b/docs/contributing/coc.mdx new file mode 100644 index 00000000000..cf7d61e3b19 --- /dev/null +++ b/docs/contributing/coc.mdx @@ -0,0 +1,13 @@ +# Code of Conduct + +As contributors and maintainers of the Ionic project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities. + +Communication through any of Ionic's channels (GitHub, Slack, Forum, IRC, mailing lists, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. + +We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Ionic project to do the same. + +If any member of the community violates this code of conduct, the maintainers of the Ionic project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate. + +If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at devrel@ionic.io. + +Please review [Ionic's full code of conduct](https://ionic.io/code-of-conduct). diff --git a/docs/contributing/how-to-contribute.md b/docs/contributing/how-to-contribute.md deleted file mode 100644 index df5f6efbd23..00000000000 --- a/docs/contributing/how-to-contribute.md +++ /dev/null @@ -1,252 +0,0 @@ ---- -sidebar_label: How to Contribute ---- - -# Contributing to Ionic - -Thanks for the interest in contributing to Ionic Framework! - -## Contributing Etiquette - -Please see the [Contributor Code of Conduct](coc.md) for information on the rules of conduct. - -## Creating an Issue - -- If you have a question about using the framework, please ask on the [Ionic Forum](http://forum.ionicframework.com/). - -- It is required that you clearly describe the steps necessary to reproduce the issue you are running into. Although we would love to help our users as much as possible, diagnosing issues without clear reproduction steps is extremely time-consuming and simply not sustainable. - -- The issue list of the [Ionic](https://github.com/ionic-team/ionic) repository is exclusively for bug reports and feature requests. Non-conforming issues will be closed immediately. - -- Issues with no clear steps to reproduce will not be triaged. If an issue is labeled with "needs: reply" and receives no further replies from the author of the issue for more than 14 days, it will be closed. - -- If you think you have found a bug, or have a new feature idea, please start by making sure it hasn't already been [reported](https://github.com/ionic-team/ionic/issues?utf8=%E2%9C%93&q=is%3Aissue). You can search through existing issues to see if there is a similar one reported. Include closed issues as it may have been closed with a solution. - -- Next, [create a new issue](https://github.com/ionic-team/ionic/issues/new/choose) that thoroughly explains the problem. Please fill out the populated issue form before submitting the issue. - -## Creating a Good Code Reproduction - -### What is a Code Reproduction? - -A code reproduction is a small application that is built to demonstrate a particular issue. The code reproduction should contain the minimum amount of code needed to recreate the issue and should focus on a single issue. - -### Why Should You Create a Reproduction? - -A code reproduction of the issue you are experiencing helps us better isolate the cause of the problem. This is an important first step to getting any bug fixed! - -Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed. In other words, creating a code reproduction of the issue helps us help you. - -### How to Create a Reproduction - -- Create a new Ionic application using one of our starter templates. The `blank` starter application is a great choice for this. You can create one using the following Ionic CLI command: `ionic start myApp blank` -- Add the minimum amount of code needed to recreate the issue you are experiencing. Do not include anything that is not required to reproduce the issue. This includes any 3rd party plugins you have installed. -- Publish the application on GitHub and include a link to it when [creating an issue](#creating-an-issue). -- Be sure to include steps to reproduce the issue. These steps should be clear and easy to follow. - -### Benefits of Creating a Reproduction - -- **Uses the latest version of Ionic:** By creating a new Ionic application, you are ensuring that you are testing against the latest version of the framework. Sometimes the issues you are experiencing have already been resolved in a newer version of the framework! -- **Minimal surface area:** By removing code that is not needed in order to reproduce the issue, it makes it easier to identify the cause of the issue. -- **No secret code needed:** Creating a minimal reproduction of the issue prevents you from having to publish any proprietary code used in your project. -- **Get help fixing the issue:** If we can reliably reproduce an issue, there is a good chance we will be able to address it. - -## Creating a Pull Request - -- We appreciate you taking the time to contribute! Before submitting a pull request, we ask that you please [create an issue](#creating-an-issue) that explains the bug or feature request and let us know that you plan on creating a pull request for it. If an issue already exists, please comment on that issue letting us know you would like to submit a pull request for it. This helps us to keep track of the pull request and make sure there isn't duplicated effort. - -- Looking for an issue to fix? Make sure to look through our issues with the [help wanted](https://github.com/ionic-team/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) label! - -### Setup - -1. [Download the installer](https://nodejs.org/) for the LTS version of Node.js. This is the best way to also [install npm](https://blog.npmjs.org/post/85484771375/how-to-install-npm#_=_). -2. Fork the [Ionic](https://github.com/ionic-team/ionic) repository. -3. Clone your fork. -4. Create a new branch from master for your change. -5. Navigate into the directory of the package you wish to modify (core, angular, etc.). -6. Run `npm install` to install dependencies for this package. -7. Follow the steps for the specific package below. - -### Core - -#### Modifying Components - -1. Locate the component(s) to modify inside `/core/src/components/`. -2. Take a look at the [Stencil Documentation](https://stenciljs.com/docs/introduction/) and other components to understand the implementation of these components. -3. Make your changes to the component. If the change is overly complex or out of the ordinary, add comments so we can understand the changes. -4. [Preview your changes](#preview-changes) locally. -5. [Modify the documentation](#modifying-documentation) if needed. -6. [Run lint](#lint-changes) on the directory and make sure there are no errors. -7. [Build the project](#building-changes). -8. After the build is finished, commit the changes. Please follow the [commit message format](#commit-message-format) for every commit. -9. [Submit a Pull Request](#submit-pull-request) of your changes. - -#### Preview Changes - -1. Run `npm start` from within the `core` directory. -2. A browser should open at `http://localhost:3333/`. -3. From here, navigate to one of the component's tests to preview your changes. -4. If a test showing your change doesn't exist, [add a new test or update an existing one](#modifying-tests). -5. To test in RTL mode, once you are in the desired component's test, add `?rtl=true` at the end of the url; for example: `http://localhost:3333/src/components/alert/test/basic?rtl=true`. - -#### Lint Changes - -1. Run `npm run lint` to lint the TypeScript and Sass. -2. If there are lint errors, run `npm run lint.fix` to automatically fix any errors. Repeat step 1 to ensure the errors have been fixed, and manually fix them if not. -3. To lint and fix only TypeScript errors, run `npm run lint.ts` and `npm run lint.ts.fix`, respectively. -4. To lint and fix only Sass errors, run `npm run lint.sass` and `npm run lint.sass.fix`, respectively. - -#### Modifying Documentation - -1. Locate the `readme.md` file in the component's directory. -2. Modify the documentation **above** the line that says `` in this file. -3. To update any of the auto generated documentation below that line, make the relevant changes in the following places: - -- `Usage`: update the component's usage examples in the component's `usage/` directory -- `Properties`, `Events`, or `Methods`: update the component's TypeScript file (`*.tsx`) -- `CSS Custom Properties`: update the component's main Sass file (`*.scss`) - -#### Modifying Tests - -1. Locate the test to modify inside the `test/` folder in the component's directory. -2. If a test exists, modify the test by adding an example to reproduce the problem fixed or feature added. -3. If a new test is needed, the easiest way is to copy the `basic/` directory from the component's `test/` directory, rename it, and edit the content in both the `index.html` and `e2e.ts` file (see [Screenshot Tests](#screenshot-tests) for more information on this file). -4. The `preview/` directory is used in the documentation as a demo. Only update this test if there is a bug in the test or if the API has a change that hasn't been updated in the test. - -##### Screenshot Tests - -1. If the test exists in screenshot, there will be a file named `e2e.ts` in the directory of the test. -2. A screenshot test can be added by including this file and adding one or more `test()` calls that include a call to `page.compareScreenshot()`. See [Stencil end-to-end testing](https://stenciljs.com/docs/end-to-end-testing) and existing tests in `core/` for examples. -3. **Important:** each `test()` should have only one screenshot (`page.compareScreenshot()`) call **or** it should check the expect at the end of each test. If there is a mismatch it will fail the test which will prevent the rest of the test from running, i.e. if the first screenshot fails the remaining screenshot calls would not be called _unless_ they are in a separate test or all of the expects are called at the end. -4. To run screenshot locally, use the following command: `npm run test.screenshot`. - - To run screenshot for a specific test, pass the path to the test or a string to search for. - - For example, running all `alert` tests: `npm run test.screenshot alert`. - - Or, running the basic `alert` tests: `npm run test.screenshot src/components/alert/test/basic/e2e.ts`. - -#### Building Changes - -1. Once all changes have been made and the documentation has been updated, run `npm run build` inside of the `core` directory. This will add your changes to any auto-generated files, if necessary. -2. Review the changes and, if everything looks correct, [commit](#commit-message-format) the changes. -3. Make sure the build has finished before committing. If you made changes to the documentation, properties, methods, or anything else that requires an update to a generate file, this needs to be committed. -4. After the changes have been pushed, publish the branch and [create a pull request](#creating-a-pull-request). - -### Submit Pull Request - -1. [Create a new pull request](https://github.com/ionic-team/ionic/compare) with the `master` branch as the `base`. You may need to click on `compare across forks` to find your changes. -2. See the [Creating a pull request from a fork](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) GitHub help article for more information. -3. Please fill out the provided Pull Request template to the best of your ability and include any issues that are related. - -## Commit Message Guidelines - -We have very precise rules over how our git commit messages should be formatted. This leads to readable messages that are easy to follow when looking through the project history. We also use the git commit messages to generate our [changelog](https://github.com/ionic-team/ionic/blob/master/CHANGELOG.md). Our format closely resembles Angular's [commit message guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit). - -### Commit Message Format - -We follow the [Conventional Commits specification](https://www.conventionalcommits.org/). A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**: - -``` -(): - - - -