diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 83759a3f32b..c4fe46cd76d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -166,6 +166,17 @@ The content of the Ionic docs is written as [Markdown](https://commonmark.org/) 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. +### 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. + ### Reference Content The Markdown in `docs/` does not only contain manually written markdown files: diff --git a/docs/api/item.mdx b/docs/api/item.mdx index 89ebdb07ca5..77133929321 100644 --- a/docs/api/item.mdx +++ b/docs/api/item.mdx @@ -9,6 +9,7 @@ import Parts from '@ionic-internal/component-api/v9/item/parts.mdx'; import CustomProps from '@ionic-internal/component-api/v9/item/custom-props.mdx'; import Slots from '@ionic-internal/component-api/v9/item/slots.mdx'; +import Link from '@docusaurus/Link'; import useBaseUrl from '@docusaurus/useBaseUrl'; import BestPracticeFigure from '@components/global/BestPracticeFigure'; import Tabs from '@theme/Tabs'; @@ -78,8 +79,8 @@ The text content type includes form control labels or other visible text. This t text={ <> If you find that you need a few more sentences to clarify the item's purpose, consider moving the additional - sentences to a Note at the bottom of the list. Adding the item to its own - list makes it clear which item the text is associated with. + sentences to a Note at the bottom of the list. Adding the item to its own list makes + it clear which item the text is associated with. } doText="Move long text outside of the list" @@ -165,15 +166,14 @@ Developers should avoid creating [nested interactives](https://dequeuniversity.c - Actions can be added by using the Item Sliding component. Actions can - also be placed directly inside of the Item without the use of Item Sliding, but this should be limited to no more - than 2 actions. + Actions can be added by using the Item Sliding component. Actions can also be + placed directly inside of the Item without the use of Item Sliding, but this should be limited to no more than 2 + actions. } doText={ <> - Use an Item Sliding to reveal multiple actions by swiping on the - Item. + Use an Item Sliding to reveal multiple actions by swiping on the Item. } doNotText="Don't put more than 2 actions within an Item." @@ -206,8 +206,8 @@ Controls are form components such as checkboxes, inputs, radios, and more. Each <> Metadata such as helper text or character counts should not be used on form controls in list views. If such metadata is needed, the form control should be placed outside of a list.{' '} - Filled Inputs are a great way of visually defining the input - container outside of a list. + Filled Inputs are a great way of visually defining the input container + outside of a list. } doText="Place inputs with metadata outside of the list." @@ -229,8 +229,7 @@ Controls are form components such as checkboxes, inputs, radios, and more. Each - Alternatively, the metadata can be placed in a Note at the bottom of the - list. + Alternatively, the metadata can be placed in a Note at the bottom of the list. } doText="Place metadata for inputs at the end of a list." @@ -253,7 +252,7 @@ Controls are form components such as checkboxes, inputs, radios, and more. Each text={ <> Items should typically have no more than two controls. If you need more controls, consider adding the additional - controls in a Modal that is accessible from the item. + controls in a Modal that is accessible from the item. } doText="Move additional controls to a submenu accessible from the item." diff --git a/docs/intro/vscode-extension.mdx b/docs/intro/vscode-extension.mdx index 9bade67c741..7822c66b74e 100644 --- a/docs/intro/vscode-extension.mdx +++ b/docs/intro/vscode-extension.mdx @@ -2,6 +2,8 @@ title: VS Code Extension --- +import Link from '@docusaurus/Link'; + VS Code Extension @@ -11,12 +13,12 @@ The [WebNative Visual Studio Code extension](https://marketplace.visualstudio.co If you have VS Code on this computer click Install below. You can also find the extension by searching for "WebNative". - + - - + + - + ## Additional Documentation {/* #additional-documentation */} diff --git a/docs/troubleshooting/native.mdx b/docs/troubleshooting/native.mdx index 073151db8f6..40785f15e1f 100644 --- a/docs/troubleshooting/native.mdx +++ b/docs/troubleshooting/native.mdx @@ -24,7 +24,7 @@ Running an app on an iOS device requires a provisioning profile. If a provisioni For Cordova, open the `config.xml` file and modify the `id` attribute of the root element, ``. Refer to [the Cordova documentation](https://cordova.apache.org/docs/en/latest/config_ref/#widget) for more information. -2. **Open the project in **Xcode**.** +2. **Open the project in Xcode.** For Capacitor, run the following to open the app in Xcode: @@ -34,11 +34,11 @@ Running an app on an iOS device requires a provisioning profile. If a provisioni For Cordova, open Xcode. Use **File** » **Open** and locate the app. Open the app's `platforms/ios` directory. -3. **In **Project navigator**, select the project root to open the project editor. Under the **Identity** section, verify that the Package ID that was set matches the Bundle Identifier.** +3. **In Project navigator, select the project root to open the project editor. Under the Identity section, verify that the Package ID that was set matches the Bundle Identifier.** ![Xcode showing the Identity section for an iOS app with fields for Display Name, Bundle Identifier, Version, and Build.](/img/running/ios-xcode-identity-setup.png 'Xcode Identity Section') -4. **In the same project editor, under the **Signing** section, ensure **Automatically manage signing** is enabled.** Then, select a Development Team. Given a Development Team, Xcode will attempt to automatically prepare provisioning and signing. +4. **In the same project editor, under the Signing section, ensure Automatically manage signing is enabled.** Then, select a Development Team. Given a Development Team, Xcode will attempt to automatically prepare provisioning and signing. ![Xcode showing the Signing section with 'Automatically manage signing' enabled and a Development Team selected.](/img/running/ios-xcode-signing-setup.png 'Xcode Signing Section') diff --git a/src/components/global/BestPracticeFigure/index.tsx b/src/components/global/BestPracticeFigure/index.tsx index cc024dca957..d66f48e2412 100644 --- a/src/components/global/BestPracticeFigure/index.tsx +++ b/src/components/global/BestPracticeFigure/index.tsx @@ -19,7 +19,7 @@ import './best-practice-figure.css'; Custom HTML can also be passed to any of the text properties by using curly braces: - text={<>My text with a link} + text={<>My text with a link} Markdown such as backticks will not be processed when using curly braces. The tag can be used instead: diff --git a/src/components/global/DocDemo/index.js b/src/components/global/DocDemo/index.js index a03f01fb987..21984c697bc 100644 --- a/src/components/global/DocDemo/index.js +++ b/src/components/global/DocDemo/index.js @@ -1,5 +1,6 @@ import React, { useEffect, useState, useRef, useCallback } from 'react'; import clsx from 'clsx'; +import Link from '@docusaurus/Link'; import './demo.css'; @@ -57,9 +58,9 @@ const DocDemo = (props) => { ); const sourceLink = ( - + View Source - + ); const device = ( diff --git a/src/components/global/DocsCard/index.tsx b/src/components/global/DocsCard/index.tsx index b4e8724c63e..3aa3ba4b16a 100644 --- a/src/components/global/DocsCard/index.tsx +++ b/src/components/global/DocsCard/index.tsx @@ -17,7 +17,6 @@ interface Props extends React.HTMLAttributes { function DocsCard(props: Props): ReactNode { const isStatic = typeof props.href === 'undefined'; - const isOutbound = typeof props.href !== 'undefined' ? /^http/.test(props.href) : false; const header = props.header === 'undefined' ? null :
{props.header}
; const hoverIcon = props.hoverIcon || props.icon; @@ -65,16 +64,6 @@ function DocsCard(props: Props): ReactNode { ); } - if (isOutbound) { - return ( - - - {content} - - - ); - } - return ( diff --git a/src/components/global/Playground/index.tsx b/src/components/global/Playground/index.tsx index 10b61dd4a90..9211c19481e 100644 --- a/src/components/global/Playground/index.tsx +++ b/src/components/global/Playground/index.tsx @@ -9,6 +9,7 @@ import React, { useState, } from 'react'; +import Link from '@docusaurus/Link'; import useBaseUrl from '@docusaurus/useBaseUrl'; import './playground.css'; import { EditorOptions, openAngularEditor, openHtmlEditor, openReactEditor, openVueEditor } from './stackblitz.utils'; @@ -871,12 +872,10 @@ export default function Playground({ - - + diff --git a/src/components/page/api/APIList/index.tsx b/src/components/page/api/APIList/index.tsx index 6e17b419b87..37cdb1f64e6 100644 --- a/src/components/page/api/APIList/index.tsx +++ b/src/components/page/api/APIList/index.tsx @@ -1,5 +1,7 @@ import React, { type ComponentProps, type ReactNode } from 'react'; +import Link from '@docusaurus/Link'; +import Heading from '@theme/Heading'; import sidebars from '@site/sidebars'; import clsx from 'clsx'; @@ -11,14 +13,14 @@ function APIList({ sidebar, ...props }: ComponentProps<'div'> & { sidebar?: unkn return ( <> -

{section.label}

+ {section.label}
    {section.items.map((item) => { return ( item && item.replace && (
  • - {item.replace('api/', '')} + {item.replace('api/', '')}
  • ) ); diff --git a/src/components/page/intro/AppWizard/index.tsx b/src/components/page/intro/AppWizard/index.tsx index 5a211d66edd..74cc43f57d4 100644 --- a/src/components/page/intro/AppWizard/index.tsx +++ b/src/components/page/intro/AppWizard/index.tsx @@ -1,4 +1,5 @@ import clsx from 'clsx'; +import Link from '@docusaurus/Link'; import React, { type ComponentProps } from 'react'; import styles from './index.module.scss'; @@ -14,9 +15,9 @@ export default function AppWizard(props: ComponentProps<'div'>) {

    ); diff --git a/src/components/page/intro/next/DeveloperExperts/index.tsx b/src/components/page/intro/next/DeveloperExperts/index.tsx index 0d9311c7875..d0ff60f870e 100644 --- a/src/components/page/intro/next/DeveloperExperts/index.tsx +++ b/src/components/page/intro/next/DeveloperExperts/index.tsx @@ -1,28 +1,24 @@ import React from 'react'; +import Link from '@docusaurus/Link'; +import Heading from '@theme/Heading'; import styles from './index.module.scss'; export default function DeveloperExperts() { return (
    -

    Featured Ionic Developer Expert Projects

    + + Featured Ionic Developer Expert Projects +

    Extend your knowledge of Ionic from premium educational materials made by community members.

    - - Ionic Academy → - - - Ionic Start → - - - Ionic Themes → - - - Ionic React Hub → - + Ionic Academy → + Ionic Start → + Ionic Themes → + Ionic React Hub →
    ); diff --git a/src/components/page/native/NativeEnterpriseCard/index.tsx b/src/components/page/native/NativeEnterpriseCard/index.tsx index d8238fa9fa7..4d8ee7d9f7d 100644 --- a/src/components/page/native/NativeEnterpriseCard/index.tsx +++ b/src/components/page/native/NativeEnterpriseCard/index.tsx @@ -1,3 +1,4 @@ +import Link from '@docusaurus/Link'; import useBaseUrl from '@docusaurus/useBaseUrl'; import clsx from 'clsx'; import React, { type ComponentProps } from 'react'; @@ -6,11 +7,7 @@ import styles from './index.module.scss'; export default function NativeEnterpriseCard(props: ComponentProps<'a'>) { return ( - +
    @@ -22,6 +19,6 @@ export default function NativeEnterpriseCard(props: ComponentProps<'a'>) { enterprise-grade apps.

    -
    + ); } diff --git a/src/components/page/reference/ReleaseNotes/index.tsx b/src/components/page/reference/ReleaseNotes/index.tsx index 5f8cfcc03ef..1f49d40dca5 100644 --- a/src/components/page/reference/ReleaseNotes/index.tsx +++ b/src/components/page/reference/ReleaseNotes/index.tsx @@ -1,4 +1,5 @@ import Link from '@docusaurus/Link'; +import Heading from '@theme/Heading'; import clsx from 'clsx'; import React from 'react'; import releases from './release-notes.json'; @@ -49,9 +50,9 @@ export default function ReleaseNotes(props: { [key: string]: any }) {
    -

    + {release.version} -

    + {release.type} {index === 0 ? ( @@ -61,7 +62,7 @@ export default function ReleaseNotes(props: { [key: string]: any }) { ) : null}
    -

    {release.published_at}

    + {release.published_at}
    & { useTextAndBackgroundStepColors?: boolean }) { @@ -29,10 +30,10 @@ export default function ColorGenerator(props: ComponentProps<'div'> & { useTextA
    -

    Background

    + Background -

    Text

    + Text
    diff --git a/src/theme/TOC/index.tsx b/src/theme/TOC/index.tsx
    index a399275a026..750de6bf10a 100644
    --- a/src/theme/TOC/index.tsx
    +++ b/src/theme/TOC/index.tsx
    @@ -10,9 +10,11 @@
     import React, { useState, useEffect, type ReactNode } from 'react';
     import TOC from '@theme-original/TOC';
     import type { Props } from '@theme/TOC';
    +import Heading from '@theme/Heading';
     
     import EditThisPage from '@theme-original/EditThisPage';
     import { useLocation } from '@docusaurus/router';
    +import Link from '@docusaurus/Link';
     import { usePluginData } from '@docusaurus/useGlobalData';
     import { PrismicRichText } from '@prismicio/react';
     import { useDoc } from '@docusaurus/plugin-content-docs/client';
    @@ -37,13 +39,13 @@ export default function TOCWrapper(props: TOCProps): ReactNode {
     
       return (
         
    diff --git a/versioned_docs/version-v8/angular/testing.mdx b/versioned_docs/version-v8/angular/testing.mdx
    index 7fd3668a467..f29cfd3dc1b 100644
    --- a/versioned_docs/version-v8/angular/testing.mdx
    +++ b/versioned_docs/version-v8/angular/testing.mdx
    @@ -317,7 +317,7 @@ Since end-to-end tests exercise user stories and cover the application as a whol
     
     ### Test Structure
     
    -When an `@ionic/angular` application is generated, a default end-to-end test application is generated in the `e2e` folder. This application uses Protractor to control the browser and Jasmine to structure and execute the tests. The application initially consists of four files:
    +When an `@ionic/angular` application is generated, a default end-to-end test application is generated in the `e2e` folder. This application uses [Protractor](https://www.protractortest.org/) to control the browser and [Jasmine](https://jasmine.github.io/) to structure and execute the tests. The application initially consists of four files:
     
     - `protractor.conf.js` - the Protractor configuration file
     - `tsconfig.e2e.json` - specific TypeScript configuration for the testing application
    diff --git a/versioned_docs/version-v8/api/item.mdx b/versioned_docs/version-v8/api/item.mdx
    index 5f090c61972..4cee22b8ad8 100644
    --- a/versioned_docs/version-v8/api/item.mdx
    +++ b/versioned_docs/version-v8/api/item.mdx
    @@ -9,6 +9,7 @@ import Parts from '@ionic-internal/component-api/v8/item/parts.mdx';
     import CustomProps from '@ionic-internal/component-api/v8/item/custom-props.mdx';
     import Slots from '@ionic-internal/component-api/v8/item/slots.mdx';
     
    +import Link from '@docusaurus/Link';
     import useBaseUrl from '@docusaurus/useBaseUrl';
     import BestPracticeFigure from '@components/global/BestPracticeFigure';
     
    @@ -76,8 +77,8 @@ The text content type includes form control labels or other visible text. This t
       text={
         <>
           If you find that you need a few more sentences to clarify the item's purpose, consider moving the additional
    -      sentences to a Note at the bottom of the list. Adding the item to its own
    -      list makes it clear which item the text is associated with.
    +      sentences to a Note at the bottom of the list. Adding the item to its own list
    +      makes it clear which item the text is associated with.
         
       }
       doText="Move long text outside of the list"
    @@ -163,15 +164,14 @@ Developers should avoid creating [nested interactives](https://dequeuniversity.c
     
    -      Actions can be added by using the Item Sliding component. Actions can
    -      also be placed directly inside of the Item without the use of Item Sliding, but this should be limited to no more
    -      than 2 actions.
    +      Actions can be added by using the Item Sliding component. Actions can also
    +      be placed directly inside of the Item without the use of Item Sliding, but this should be limited to no more than
    +      2 actions.
         
       }
       doText={
         <>
    -      Use an Item Sliding to reveal multiple actions by swiping on the
    -      Item.
    +      Use an Item Sliding to reveal multiple actions by swiping on the Item.
         
       }
       doNotText="Don't put more than 2 actions within an Item."
    @@ -204,7 +204,7 @@ Controls are form components such as checkboxes, inputs, radios, and more. Each
         <>
           Metadata such as helper text or character counts should not be used on form controls in list views. If such
           metadata is needed, the form control should be placed outside of a list.{' '}
    -      Filled Inputs are a great way of visually defining the input
    +      Filled Inputs are a great way of visually defining the input
           container outside of a list.
         
       }
    @@ -227,8 +227,7 @@ Controls are form components such as checkboxes, inputs, radios, and more. Each
     
    -      Alternatively, the metadata can be placed in a Note at the bottom of the
    -      list.
    +      Alternatively, the metadata can be placed in a Note at the bottom of the list.
         
       }
       doText="Place metadata for inputs at the end of a list."
    @@ -251,7 +250,7 @@ Controls are form components such as checkboxes, inputs, radios, and more. Each
       text={
         <>
           Items should typically have no more than two controls. If you need more controls, consider adding the additional
    -      controls in a Modal that is accessible from the item.
    +      controls in a Modal that is accessible from the item.
         
       }
       doText="Move additional controls to a submenu accessible from the item."
    diff --git a/versioned_docs/version-v8/intro/vscode-extension.mdx b/versioned_docs/version-v8/intro/vscode-extension.mdx
    index 2a4d3bddeac..b9827a9db9e 100644
    --- a/versioned_docs/version-v8/intro/vscode-extension.mdx
    +++ b/versioned_docs/version-v8/intro/vscode-extension.mdx
    @@ -2,6 +2,8 @@
     title: VS Code Extension
     ---
     
    +import Link from '@docusaurus/Link';
    +
     
       VS Code Extension
       
    @@ -11,12 +13,12 @@ The [WebNative Visual Studio Code extension](https://marketplace.visualstudio.co
     
     If you have VS Code on this computer click Install below. You can also find the extension by searching for "WebNative".
     
    -
    +
       
    -
    -
    +
    +
       
    -
    +
     
     ## Additional Documentation
     
    diff --git a/versioned_docs/version-v8/troubleshooting/native.mdx b/versioned_docs/version-v8/troubleshooting/native.mdx
    index cd288459839..40fa3beb1a1 100644
    --- a/versioned_docs/version-v8/troubleshooting/native.mdx
    +++ b/versioned_docs/version-v8/troubleshooting/native.mdx
    @@ -24,7 +24,7 @@ Running an app on an iOS device requires a provisioning profile. If a provisioni
     
        For Cordova, open the `config.xml` file and modify the `id` attribute of the root element, ``. Refer to [the Cordova documentation](https://cordova.apache.org/docs/en/latest/config_ref/#widget) for more information.
     
    -2. **Open the project in **Xcode**.**
    +2. **Open the project in Xcode.**
     
        For Capacitor, run the following to open the app in Xcode:
     
    @@ -34,11 +34,11 @@ Running an app on an iOS device requires a provisioning profile. If a provisioni
     
        For Cordova, open Xcode. Use **File** » **Open** and locate the app. Open the app's `platforms/ios` directory.
     
    -3. **In **Project navigator**, select the project root to open the project editor. Under the **Identity** section, verify that the Package ID that was set matches the Bundle Identifier.**
    +3. **In Project navigator, select the project root to open the project editor. Under the Identity section, verify that the Package ID that was set matches the Bundle Identifier.**
     
        ![Xcode showing the Identity section for an iOS app with fields for Display Name, Bundle Identifier, Version, and Build.](/img/running/ios-xcode-identity-setup.png 'Xcode Identity Section')
     
    -4. **In the same project editor, under the **Signing** section, ensure **Automatically manage signing** is enabled.** Then, select a Development Team. Given a Development Team, Xcode will attempt to automatically prepare provisioning and signing.
    +4. **In the same project editor, under the Signing section, ensure Automatically manage signing is enabled.** Then, select a Development Team. Given a Development Team, Xcode will attempt to automatically prepare provisioning and signing.
     
        ![Xcode showing the Signing section with 'Automatically manage signing' enabled and a Development Team selected.](/img/running/ios-xcode-signing-setup.png 'Xcode Signing Section')