starlight-package-managers 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/PackageManagers.astro +150 -0
- package/README.md +81 -0
- package/index.ts +1 -0
- package/package.json +50 -0
- package/pkg.ts +98 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-present, HiDeoo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Tabs, TabItem } from '@astrojs/starlight/components'
|
|
3
|
+
import { Code } from 'astro/components'
|
|
4
|
+
|
|
5
|
+
import { type CommandType, getCommand, type CommandOptions, getSupportedPkgManagers, type PackageManager } from './pkg'
|
|
6
|
+
|
|
7
|
+
export type PackageManagersProps = Props
|
|
8
|
+
|
|
9
|
+
interface Props extends CommandOptions {
|
|
10
|
+
pkg?: string | undefined
|
|
11
|
+
pkgManagers?: PackageManager[]
|
|
12
|
+
type?: CommandType
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { pkg, pkgManagers, type = 'add', ...options } = Astro.props
|
|
16
|
+
const singlePkgManager = pkgManagers?.length === 1 ? pkgManagers[0] : undefined
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
{
|
|
20
|
+
singlePkgManager ? (
|
|
21
|
+
<Code code={getCommand(singlePkgManager, type, pkg, options)} lang="sh" theme="css-variables" />
|
|
22
|
+
) : (
|
|
23
|
+
<starlight-package-managers>
|
|
24
|
+
<Tabs>
|
|
25
|
+
{getSupportedPkgManagers(type, pkgManagers).map((pkgManager) => (
|
|
26
|
+
<TabItem label={pkgManager}>
|
|
27
|
+
<Code code={getCommand(pkgManager, type, pkg, options)} lang="sh" theme="css-variables" />
|
|
28
|
+
</TabItem>
|
|
29
|
+
))}
|
|
30
|
+
</Tabs>
|
|
31
|
+
</starlight-package-managers>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
<style>
|
|
36
|
+
starlight-package-managers {
|
|
37
|
+
display: block;
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
40
|
+
|
|
41
|
+
<script>
|
|
42
|
+
customElements.define(
|
|
43
|
+
'starlight-package-managers',
|
|
44
|
+
class StarlightPackageManagers extends HTMLElement {
|
|
45
|
+
#observer: MutationObserver
|
|
46
|
+
#observerConfig: MutationObserverInit = { attributes: true, attributeFilter: ['aria-selected'] }
|
|
47
|
+
|
|
48
|
+
#tabs: NodeListOf<HTMLAnchorElement>
|
|
49
|
+
|
|
50
|
+
constructor() {
|
|
51
|
+
super()
|
|
52
|
+
|
|
53
|
+
this.#observer = new MutationObserver(this.#handleTabChange)
|
|
54
|
+
this.#tabs = this.querySelectorAll<HTMLAnchorElement>('starlight-tabs [role="tablist"] [role="tab"]')
|
|
55
|
+
|
|
56
|
+
this.observeTabs()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
observeTabs = () => {
|
|
60
|
+
for (const tab of this.#tabs) {
|
|
61
|
+
this.#observer.observe(tab, this.#observerConfig)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
disconnectTabs = () => {
|
|
66
|
+
this.#observer.disconnect()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#handleTabChange = (mutations: MutationRecord[]) => {
|
|
70
|
+
const pkgTabs = [...document.querySelectorAll<this>('starlight-package-managers')]
|
|
71
|
+
|
|
72
|
+
for (const pkgTab of pkgTabs) {
|
|
73
|
+
pkgTab.disconnectTabs()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let newFocusedTab: HTMLAnchorElement | null = null
|
|
77
|
+
|
|
78
|
+
for (const mutation of mutations) {
|
|
79
|
+
if (mutation.attributeName !== 'aria-selected' || !(mutation.target instanceof HTMLAnchorElement)) {
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (mutation.target.getAttribute('aria-selected') !== 'true') {
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
newFocusedTab = mutation.target
|
|
88
|
+
|
|
89
|
+
const newPkgManager = newFocusedTab.textContent?.trim() ?? ''
|
|
90
|
+
const otherTabs = pkgTabs.filter((tabs) => tabs !== this)
|
|
91
|
+
|
|
92
|
+
for (const otherTab of otherTabs) {
|
|
93
|
+
const starlightTabs = otherTab.querySelector('starlight-tabs')
|
|
94
|
+
|
|
95
|
+
if (!this.#isStarlightTabs(starlightTabs)) {
|
|
96
|
+
continue
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// We cannot use the `switchTab()` method provided by Starlight as it focuses the new tab which will cause
|
|
100
|
+
// the page to scroll for every set of tabs.
|
|
101
|
+
this.#switchTabs(starlightTabs, newPkgManager)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
requestAnimationFrame(() => {
|
|
106
|
+
for (const pkgTab of pkgTabs) {
|
|
107
|
+
pkgTab.observeTabs()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
newFocusedTab?.focus()
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// https://github.com/withastro/starlight/blob/290af4f0b5f65619fa4c65609940c3a911a7e698/packages/starlight/user-components/Tabs.astro#L116-L135
|
|
115
|
+
#switchTabs(starlightTabs: StarlightTabs, newPkgManager: string) {
|
|
116
|
+
const tabs = starlightTabs.tabs
|
|
117
|
+
const newTabIndex = tabs.findIndex((tab) => tab.textContent?.trim() === newPkgManager)
|
|
118
|
+
const newTab = tabs[newTabIndex]
|
|
119
|
+
const newPanel = starlightTabs.panels[newTabIndex]
|
|
120
|
+
|
|
121
|
+
if (!newTab || !newPanel) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
for (const tab of starlightTabs.tabs) {
|
|
126
|
+
tab.removeAttribute('aria-selected')
|
|
127
|
+
tab.setAttribute('tabindex', '-1')
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
for (const panel of starlightTabs.panels) {
|
|
131
|
+
panel.hidden = true
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
newPanel.hidden = false
|
|
135
|
+
// Restore active tab to the default tab order.
|
|
136
|
+
newTab.removeAttribute('tabindex')
|
|
137
|
+
newTab.setAttribute('aria-selected', 'true')
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
#isStarlightTabs(element: Element | null): element is StarlightTabs {
|
|
141
|
+
return element instanceof Element && 'tabs' in element && 'panels' in element
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
type StarlightTabs = Element & {
|
|
147
|
+
panels: HTMLElement[]
|
|
148
|
+
tabs: HTMLAnchorElement[]
|
|
149
|
+
}
|
|
150
|
+
</script>
|
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>starlight-package-managers 🗃</h1>
|
|
3
|
+
<p>Quickly display npm related commands for multiple package managers in your Starlight documentation site.</p>
|
|
4
|
+
<p>
|
|
5
|
+
<a href="https://github.com/HiDeoo/vercel-env-push/assets/494699/a5ac0d80-984c-418f-8ecd-41a034b2e25a" title="Demo of starlight-package-managers">
|
|
6
|
+
<img alt="Demo of starlight-package-managers" src="https://github.com/HiDeoo/vercel-env-push/assets/494699/a5ac0d80-984c-418f-8ecd-41a034b2e25a" width="520" />
|
|
7
|
+
</a>
|
|
8
|
+
</p>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<div align="center">
|
|
12
|
+
<a href="https://github.com/HiDeoo/starlight-package-managers/actions/workflows/integration.yml">
|
|
13
|
+
<img alt="Integration Status" src="https://github.com/HiDeoo/starlight-package-managers/actions/workflows/integration.yml/badge.svg" />
|
|
14
|
+
</a>
|
|
15
|
+
<a href="https://github.com/HiDeoo/starlight-package-managers/blob/main/LICENSE">
|
|
16
|
+
<img alt="License" src="https://badgen.net/github/license/HiDeoo/starlight-package-managers" />
|
|
17
|
+
</a>
|
|
18
|
+
<br />
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
## Getting Started
|
|
22
|
+
|
|
23
|
+
Want to get started immediately? Check out the [getting started guide](https://starlight-package-managers.vercel.app/guides/getting-started/).
|
|
24
|
+
|
|
25
|
+
## Description
|
|
26
|
+
|
|
27
|
+
Replace the following MDX code:
|
|
28
|
+
|
|
29
|
+
````mdx
|
|
30
|
+
<Tabs>
|
|
31
|
+
<TabItem label="npm">
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
npm create astro@latest -- --template starlight
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
</TabItem>
|
|
38
|
+
<TabItem label="pnpm">
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pnpm create astro --template starlight
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
</TabItem>
|
|
45
|
+
<TabItem label="Yarn">
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
yarn create astro --template starlight
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
</TabItem>
|
|
52
|
+
</Tabs>
|
|
53
|
+
````
|
|
54
|
+
|
|
55
|
+
By this one:
|
|
56
|
+
|
|
57
|
+
```mdx
|
|
58
|
+
<PackageManagers type="create" pkg="astro@latest" args="--template starlight" />
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
- Support for various package managers: [npm](https://www.npmjs.com), [yarn](https://yarnpkg.com), [pnpm](https://pnpm.io), [bun](https://bun.sh) & [ni](https://github.com/antfu/ni).
|
|
64
|
+
- Support for various types of command: [`add`](https://starlight-package-managers.vercel.app/guides/usage/#add), [`create`](https://starlight-package-managers.vercel.app/guides/usage/#create), [`exec`](https://starlight-package-managers.vercel.app/guides/usage/#exec) & [`run`](https://starlight-package-managers.vercel.app/guides/usage/#run).
|
|
65
|
+
- Synced tabs between each instance on the same page.
|
|
66
|
+
- Customizable output with [extra arguments](https://starlight-package-managers.vercel.app/guides/usage/#extra-arguments), [comments](https://starlight-package-managers.vercel.app/guides/usage/#comment) & [prefixes](https://starlight-package-managers.vercel.app/guides/usage/#prefix).
|
|
67
|
+
|
|
68
|
+
## Documentation
|
|
69
|
+
|
|
70
|
+
Check out the [Starlight Package Managers documentation](https://starlight-package-managers.vercel.app).
|
|
71
|
+
|
|
72
|
+
## Related Projects
|
|
73
|
+
|
|
74
|
+
- [npm-package-manager-extension](https://github.com/HiDeoo/npm-package-manager-extension)
|
|
75
|
+
- [npm-install-block](https://github.com/HiDeoo/npm-install-block)
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
Licensed under the MIT License, Copyright © HiDeoo.
|
|
80
|
+
|
|
81
|
+
See [LICENSE](https://github.com/HiDeoo/starlight-package-managers/blob/main/LICENSE) for more information.
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PackageManagers, type PackageManagersProps } from './PackageManagers.astro'
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "starlight-package-managers",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Quickly display npm related commands for multiple package managers in your Starlight documentation site.",
|
|
6
|
+
"author": "HiDeoo <github@hideoo.dev> (https://hideoo.dev)",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.ts",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@astrojs/starlight": "0.6.0",
|
|
14
|
+
"@playwright/test": "1.36.2",
|
|
15
|
+
"astro": "2.9.6",
|
|
16
|
+
"vitest": "0.33.0"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@astrojs/starlight": ">=0.5.0",
|
|
20
|
+
"astro": ">=2.5.0"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18"
|
|
24
|
+
},
|
|
25
|
+
"packageManager": "pnpm@8.6.10",
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"keywords": [
|
|
31
|
+
"astro-component",
|
|
32
|
+
"withastro",
|
|
33
|
+
"starlight",
|
|
34
|
+
"package",
|
|
35
|
+
"manager",
|
|
36
|
+
"npm"
|
|
37
|
+
],
|
|
38
|
+
"homepage": "https://github.com/HiDeoo/starlight-package-managers",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/HiDeoo/starlight-package-managers.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": "https://github.com/HiDeoo/starlight-package-managers/issues",
|
|
44
|
+
"scripts": {
|
|
45
|
+
"test": "pnpm test:unit && pnpm test:e2e",
|
|
46
|
+
"test:unit": "vitest",
|
|
47
|
+
"test:e2e": "playwright test",
|
|
48
|
+
"lint": "prettier -c --cache . && eslint . --cache --max-warnings=0"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/pkg.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const pkgManagers = ['npm', 'yarn', 'pnpm', 'bun', 'ni'] as const
|
|
2
|
+
|
|
3
|
+
const defaultPkgManagers: PackageManager[] = ['npm', 'yarn', 'pnpm']
|
|
4
|
+
|
|
5
|
+
const commands: Commands = {
|
|
6
|
+
npm: {
|
|
7
|
+
add: 'npm i',
|
|
8
|
+
create: 'npm create',
|
|
9
|
+
devOption: '-D',
|
|
10
|
+
exec: 'npx',
|
|
11
|
+
run: 'npm run',
|
|
12
|
+
},
|
|
13
|
+
yarn: {
|
|
14
|
+
add: 'yarn add',
|
|
15
|
+
create: 'yarn create',
|
|
16
|
+
devOption: '-D',
|
|
17
|
+
exec: 'yarn',
|
|
18
|
+
run: 'yarn run',
|
|
19
|
+
},
|
|
20
|
+
pnpm: {
|
|
21
|
+
add: 'pnpm add',
|
|
22
|
+
create: 'pnpm create',
|
|
23
|
+
devOption: '-D',
|
|
24
|
+
exec: 'pnpm',
|
|
25
|
+
run: 'pnpm run',
|
|
26
|
+
},
|
|
27
|
+
bun: {
|
|
28
|
+
add: 'bun add',
|
|
29
|
+
devOption: '-d',
|
|
30
|
+
exec: 'bunx',
|
|
31
|
+
run: 'bun run',
|
|
32
|
+
},
|
|
33
|
+
ni: {
|
|
34
|
+
add: 'ni',
|
|
35
|
+
devOption: '-D',
|
|
36
|
+
exec: 'nlx',
|
|
37
|
+
run: 'nr',
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function getSupportedPkgManagers(type: CommandType, userPkgManagers: PackageManager[] | undefined) {
|
|
42
|
+
return (userPkgManagers ?? defaultPkgManagers).filter((pkgManager) => commands[pkgManager][type] !== undefined)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function getCommand(
|
|
46
|
+
pkgManager: PackageManager,
|
|
47
|
+
type: CommandType,
|
|
48
|
+
pkg: string | undefined,
|
|
49
|
+
options: CommandOptions,
|
|
50
|
+
) {
|
|
51
|
+
let command = commands[pkgManager][type]
|
|
52
|
+
|
|
53
|
+
if (!command) {
|
|
54
|
+
throw new Error(`Command type '${type}' is not supported for package manager '${pkgManager}'.`)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (options.prefix) {
|
|
58
|
+
command = `${options.prefix} ${command}`
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (options.comment) {
|
|
62
|
+
command = `# ${options.comment.replaceAll('{PKG}', pkgManager)}\n${command}`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (type === 'add' && options.dev) {
|
|
66
|
+
command += ` ${commands[pkgManager].devOption}`
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (pkg) {
|
|
70
|
+
command += ` ${pkg}`
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (options.args && options.args.length > 0) {
|
|
74
|
+
if (pkgManager === 'npm' && type !== 'exec' && type !== 'run') {
|
|
75
|
+
command += ' --'
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
command += ` ${options.args}`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return command
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type CommandType = 'add' | 'create' | 'exec' | 'run'
|
|
85
|
+
|
|
86
|
+
export interface CommandOptions {
|
|
87
|
+
args?: string
|
|
88
|
+
comment?: string
|
|
89
|
+
dev?: boolean
|
|
90
|
+
prefix?: string
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
type Commands = Record<
|
|
94
|
+
PackageManager,
|
|
95
|
+
Record<Exclude<CommandType, 'create'> | 'devOption', string> & { create?: string }
|
|
96
|
+
>
|
|
97
|
+
|
|
98
|
+
export type PackageManager = (typeof pkgManagers)[number]
|