# Package Manager Tabs

Convert package-manager commands into synced tabs in Markdown and MDX.

import { Callout, Steps } from '@prosefly/astro-components';

The `proseflyComponents()` integration enables package manager tabs so authors can
write one familiar command and let the docs render equivalent commands for
other package managers.

<Callout type="tip" title="Using a Prosefly theme">
  [Dahlia](https://astro-theme-dahlia.prosefly.dev/) and
  [Lotus](https://astro-theme-lotus.prosefly.dev/) already register the
  `proseflyComponents()` integration. Theme projects do not need to add it again.
</Callout>

## What Authors Write

Write a supported command in a shell code block:

````markdown
```sh
npm install @prosefly/astro-components
```
````

The transform renders tabs for `pnpm`, `npm`, `yarn`, and `bun`. The generated
commands keep the same package names and normalize install syntax for each
tool.

```sh
npm install @prosefly/astro-components
```

## Supported Node Commands

- `npm install`
- `npm install <packages>`
- `npm i <packages>`
- `npm add <packages>`
- `npm run <script>`
- `npm create <initializer>`
- `npx <command>`
- `npm dlx <command>`

Install commands preserve package names and normalize dev-dependency flags for
each package manager. For example, `npm install --save-dev typescript` becomes
the matching `pnpm add -D`, `yarn add -D`, and `bun add -d` command.

**Examples**:

```sh
npm run build
```

```sh
npx astro add mdx
```

## Supported Python Commands

Python install commands render as `pip`, `uv`, `poetry`, and `pdm` tabs.

````markdown
```sh
pip install prosefly
```
````

```sh
pip install prosefly
```

Supported forms include:

- `pip install <packages>`
- `python -m pip install <packages>`
- `python3 -m pip install <packages>`
- `uv pip install <packages>`
- `uv add <packages>`
- `poetry add <packages>`
- `pdm add <packages>`

## Standalone Astro Setup

If you are not using a Prosefly theme, register the shared integration in
`astro.config.ts`. Package manager tabs are enabled by default.

```ts title="astro.config.ts"
import { defineConfig } from 'astro/config';
import proseflyComponents from '@prosefly/astro-components/integration';

export default defineConfig({
  integrations: [proseflyComponents()],
});
```

The integration configures `remarkPackageManagerTabs`, which generates tab HTML
in both `.md` and `.mdx` files while preserving code blocks for syntax highlighting.
The integration loads the shared styles and browser runtime. Supported commands
are also transformed when nested in components such as `Steps`; commands inside manual
`Tabs` and `TabItem` components are left unchanged to avoid nested tabs.

To keep the other integration features but disable this transform, set
`markdown.packageManagerTabs` to `false`.

```ts title="astro.config.ts"
proseflyComponents({
  markdown: { packageManagerTabs: false },
})
```

## Authoring Rules

<Steps>

1. **Use a shell code fence.**

   The plugin transforms `sh`, `shell`, `bash`, `zsh`, `terminal`, and
   `console` blocks. It also handles code fences without a language.

2. **Keep prompts simple.**

   Lines may start with `$ `, and the prompt is preserved in each generated
   command. Other prompt formats remain normal code blocks.

3. **Keep each transformed block consistent.**

   A block can contain multiple commands, but they must belong to the same
   package-manager family. Do not mix Node and Python commands in the same code
   block.

4. **Leave custom commands alone.**

   Unsupported commands remain normal code blocks. Use manual `Tabs` when the
   alternatives need custom wording.

</Steps>

<Callout type="warning" title="Avoid double configuration">
  Dahlia and Lotus already register the shared integration. Adding another
  `proseflyComponents()` instance can duplicate Markdown transforms and is rejected
  during configuration.
</Callout>
