@chassis-ui/docs 0.5.0 → 0.5.1
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/README.md +50 -3
- package/package.json +9 -5
- package/src/components/ThemeToggler.astro +2 -3
- package/src/components/shortcodes/CSSOnly.astro +2 -4
- package/src/components/shortcodes/Code.astro +5 -7
- package/src/components/shortcodes/InFigma.astro +2 -4
- package/src/components/shortcodes/JsDocs.astro +4 -2
- package/src/components/shortcodes/ScssDocs.astro +6 -4
- package/src/components/shortcodes/ScssDocsSimple.astro +4 -2
- package/src/layouts/DocsLayout.astro +14 -4
- package/src/libs/source.ts +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ozgur Gunes
|
|
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.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Shared Astro layouts, components, and utilities for Chassis documentation sites.
|
|
4
4
|
|
|
5
|
-
[](https://opensource.org/licenses/MIT) [](https://opensource.org/licenses/MIT) [](https://www.npmjs.com/package/@chassis-ui/docs) [](https://www.npmjs.com/package/@chassis-ui/docs)
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
@@ -27,7 +27,7 @@ npm install @chassis-ui/docs
|
|
|
27
27
|
```json
|
|
28
28
|
{
|
|
29
29
|
"@astrojs/markdown-remark": "^7.0.0",
|
|
30
|
-
"@chassis-ui/css": "
|
|
30
|
+
"@chassis-ui/css": "^0.5.0-0",
|
|
31
31
|
"@pagefind/component-ui": "^1.0.0",
|
|
32
32
|
"@shikijs/transformers": "^4.3.1",
|
|
33
33
|
"astro": "^7.0.0",
|
|
@@ -51,7 +51,7 @@ import SingleLayout from '@chassis-ui/docs/layouts/SingleLayout.astro'
|
|
|
51
51
|
import TableOfContents from '@chassis-ui/docs/components/TableOfContents.astro'
|
|
52
52
|
import ThemeToggler from '@chassis-ui/docs/components/ThemeToggler.astro'
|
|
53
53
|
|
|
54
|
-
import {
|
|
54
|
+
import { generateToc, getStaticImageSize } from '@chassis-ui/docs'
|
|
55
55
|
---
|
|
56
56
|
|
|
57
57
|
<SingleLayout title="About" description="…">
|
|
@@ -59,6 +59,53 @@ import { generateTOC, processImage } from '@chassis-ui/docs'
|
|
|
59
59
|
</SingleLayout>
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
## What a site must provide
|
|
63
|
+
|
|
64
|
+
The layouts and components read from the consuming site. A site must provide the
|
|
65
|
+
following, or the build fails.
|
|
66
|
+
|
|
67
|
+
### Modules behind the `@libs/*` path alias
|
|
68
|
+
|
|
69
|
+
The site maps `@libs/*` to its own `src/libs/*` in `tsconfig.json`, and each module
|
|
70
|
+
exports:
|
|
71
|
+
|
|
72
|
+
| Module | Exports | Read by |
|
|
73
|
+
| ----------------- | ------------------------------------------------------------------------------- | -------------------------------------- |
|
|
74
|
+
| `@libs/config` | `getConfig()`, returning the parsed `config.yml` | most layouts and components |
|
|
75
|
+
| `@libs/content` | `docsPages`, the `docs` collection. `getCalloutByName(name)` and `CalloutName`. | `DocsLayout`, `DocsSidebar`, `Callout` |
|
|
76
|
+
| `@libs/data` | `getData('sidebar')`, and the types `SidebarItem` and `SidebarSubItem` | `DocsSidebar` |
|
|
77
|
+
| `@libs/path` | `getChassisDocsPath(path)` and `getDocsPublicFsPath()` | `DocsLayout`, `Social` |
|
|
78
|
+
| `@libs/clipboard` | `initCopyButtons(selector, getText)` | `Code` |
|
|
79
|
+
|
|
80
|
+
The site also defines a `docs` content collection. Its entry type is used by
|
|
81
|
+
`BaseLayout` and `DocsLayout`.
|
|
82
|
+
|
|
83
|
+
### Keys in `config.yml`
|
|
84
|
+
|
|
85
|
+
`getConfig()` must return these keys:
|
|
86
|
+
|
|
87
|
+
- `title`, `subtitle`, `description`, `authors`
|
|
88
|
+
- `repo`, `current_version`, `docsPath`
|
|
89
|
+
- `github_org`, `figma_handle`, `x_username`
|
|
90
|
+
- `anchors.min`, `anchors.max`
|
|
91
|
+
- `analytics.google_id`
|
|
92
|
+
|
|
93
|
+
These keys are optional. They say where files live when the site is not built from the
|
|
94
|
+
root of its repository:
|
|
95
|
+
|
|
96
|
+
| Key | Meaning | Example |
|
|
97
|
+
| ------------ | ----------------------------------------------------------------------------------------------------------------- | ----------------- |
|
|
98
|
+
| `sourceDir` | Directory that the `file` props of the source-file shortcodes are relative to, from the build's working directory | `"../css"` |
|
|
99
|
+
| `sourcePath` | The same directory, from the root of the repository | `"packages/css"` |
|
|
100
|
+
| `sitePath` | The site's root, from the root of the repository | `"packages/site"` |
|
|
101
|
+
| `siteBranch` | The branch that "View on GitHub" links to. Defaults to `main`. | `"main"` |
|
|
102
|
+
|
|
103
|
+
The source-file shortcodes are `<ScssDocs>`, `<ScssDocsSimple>`, `<JsDocs>` and
|
|
104
|
+
`<Code filePath>`. They link to their files at the tag `v<current_version>`.
|
|
105
|
+
|
|
106
|
+
A site that validates `config.yml` with `z.object` must add the optional keys to its
|
|
107
|
+
schema. Otherwise they are dropped silently.
|
|
108
|
+
|
|
62
109
|
## Exports
|
|
63
110
|
|
|
64
111
|
| Subpath | Contents |
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chassis-ui/docs",
|
|
3
3
|
"description": "Shared Astro components and layouts for Chassis documentation sites.",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"src",
|
|
27
27
|
"index.ts",
|
|
28
|
-
"README.md"
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
29
30
|
],
|
|
30
31
|
"main": "index.ts",
|
|
31
32
|
"exports": {
|
|
@@ -40,6 +41,9 @@
|
|
|
40
41
|
"publishConfig": {
|
|
41
42
|
"access": "public"
|
|
42
43
|
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=22.12.0"
|
|
46
|
+
},
|
|
43
47
|
"scripts": {
|
|
44
48
|
"astro": "astro"
|
|
45
49
|
},
|
|
@@ -56,7 +60,7 @@
|
|
|
56
60
|
},
|
|
57
61
|
"dependencies": {
|
|
58
62
|
"github-slugger": "^2.0.0",
|
|
59
|
-
"image-size": "^2.0.
|
|
63
|
+
"image-size": "^2.0.4",
|
|
60
64
|
"mdast-util-from-markdown": "^2.0.3",
|
|
61
65
|
"mdast-util-to-string": "^4.0.0",
|
|
62
66
|
"medium-zoom": "^1.1.0",
|
|
@@ -65,8 +69,8 @@
|
|
|
65
69
|
"unist-util-visit": "^5.1.0"
|
|
66
70
|
},
|
|
67
71
|
"devDependencies": {
|
|
68
|
-
"@types/hast": "^3.0.
|
|
69
|
-
"astro": "^7.
|
|
72
|
+
"@types/hast": "^3.0.5",
|
|
73
|
+
"astro": "^7.3.5",
|
|
70
74
|
"unified": "^11.0.5"
|
|
71
75
|
}
|
|
72
76
|
}
|
|
@@ -26,9 +26,8 @@ const { layout } = Astro.props
|
|
|
26
26
|
data-cx-placement="bottom-end"
|
|
27
27
|
>
|
|
28
28
|
<Icon name="circle-half-solid" class="theme-icon-active" />
|
|
29
|
-
<span
|
|
30
|
-
|
|
31
|
-
id="cxd-theme-text">Toggle theme</span
|
|
29
|
+
<span class=`${layout === 'examples' ? 'visually-hidden' : 'lg:d-none ms-xs'}` id="cxd-theme-text"
|
|
30
|
+
>Toggle theme</span
|
|
32
31
|
>
|
|
33
32
|
</button>
|
|
34
33
|
<ul class="menu" role="menu" aria-label="Theme options">
|
|
@@ -15,8 +15,6 @@ const { tooltip = 'This feature is only available in CSS and not in Figma compon
|
|
|
15
15
|
Astro.props
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
<span
|
|
19
|
-
|
|
20
|
-
data-cx-toggle="tooltip"
|
|
21
|
-
title={tooltip}>CSS Only</span
|
|
18
|
+
<span class="badge lg info smooth mb-md rounded-md" data-cx-toggle="tooltip" title={tooltip}
|
|
19
|
+
>CSS Only</span
|
|
22
20
|
>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
import fs from 'node:fs'
|
|
3
|
-
import path from 'node:path'
|
|
4
3
|
import { transformerNotationDiff, transformerNotationHighlight } from '@shikijs/transformers'
|
|
5
|
-
import { getConfig } from '@libs/config'
|
|
6
4
|
import { highlightCode } from '../../libs/highlight'
|
|
5
|
+
import { getSourceFsPath, getSourceUrl } from '../../libs/source'
|
|
7
6
|
import Icon from './Icon.astro'
|
|
8
7
|
|
|
9
8
|
interface Props {
|
|
@@ -41,7 +40,8 @@ interface Props {
|
|
|
41
40
|
*/
|
|
42
41
|
fileMatch?: string
|
|
43
42
|
/**
|
|
44
|
-
* A path to the file containing the code to highlight relative to the
|
|
43
|
+
* A path to the file containing the code to highlight, relative to the `sourceDir` of the
|
|
44
|
+
* site's `config.yml` (the working directory of the build when it is not set).
|
|
45
45
|
* This takes precedence over the `code` prop.
|
|
46
46
|
*/
|
|
47
47
|
filePath?: string
|
|
@@ -87,9 +87,7 @@ const {
|
|
|
87
87
|
hasPreview = false
|
|
88
88
|
} = Astro.props
|
|
89
89
|
|
|
90
|
-
const fileUrl = file
|
|
91
|
-
? `${getConfig().repo}/blob/v${getConfig().current_version}/${file}`.replaceAll('\\', '/')
|
|
92
|
-
: null
|
|
90
|
+
const fileUrl = file ? getSourceUrl(file) : null
|
|
93
91
|
|
|
94
92
|
// Extract language from multiple possible sources (for markdown code blocks)
|
|
95
93
|
// Priority: lang prop > data-language attribute > className pattern
|
|
@@ -121,7 +119,7 @@ const displayLang = detectedLang
|
|
|
121
119
|
: ''
|
|
122
120
|
|
|
123
121
|
let codeToDisplay = filePath
|
|
124
|
-
? fs.readFileSync(
|
|
122
|
+
? fs.readFileSync(getSourceFsPath(filePath), 'utf8')
|
|
125
123
|
: Array.isArray(code)
|
|
126
124
|
? code.join('\n')
|
|
127
125
|
: code
|
|
@@ -19,8 +19,6 @@ const tooltipText =
|
|
|
19
19
|
`This variant${plural ? 's' : ''} exist${plural ? '' : 's'} in the Figma component library with bound design tokens.`
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
-
<span
|
|
23
|
-
|
|
24
|
-
data-cx-toggle="tooltip"
|
|
25
|
-
title={tooltipText}>In Figma</span
|
|
22
|
+
<span class="badge lg primary smooth mb-md rounded-md" data-cx-toggle="tooltip" title={tooltipText}
|
|
23
|
+
>In Figma</span
|
|
26
24
|
>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import fs from 'node:fs'
|
|
3
|
+
import { getSourceFsPath } from '../../libs/source'
|
|
3
4
|
import Code from './Code.astro'
|
|
4
5
|
|
|
5
6
|
// Prints everything between `// js-docs-start "name"` and `// js-docs-end "name"`
|
|
@@ -11,7 +12,8 @@ interface Props {
|
|
|
11
12
|
*/
|
|
12
13
|
name: string
|
|
13
14
|
/**
|
|
14
|
-
* File path that contains the content to display relative to the
|
|
15
|
+
* File path that contains the content to display, relative to the `sourceDir` of the site's
|
|
16
|
+
* `config.yml` (the working directory of the build when it is not set).
|
|
15
17
|
*/
|
|
16
18
|
file: string
|
|
17
19
|
}
|
|
@@ -27,7 +29,7 @@ if (!name || !file) {
|
|
|
27
29
|
let content: string
|
|
28
30
|
|
|
29
31
|
try {
|
|
30
|
-
const fileContent = fs.readFileSync(file, 'utf8')
|
|
32
|
+
const fileContent = fs.readFileSync(getSourceFsPath(file), 'utf8')
|
|
31
33
|
|
|
32
34
|
const matches = fileContent.match(
|
|
33
35
|
new RegExp(`// js-docs-start ${name}\n((?:.|\n)*)// js-docs-end ${name}`, 'm')
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import fs from 'node:fs'
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
import * as sass from 'sass'
|
|
5
|
+
import { getSourceFsPath } from '../../libs/source'
|
|
5
6
|
import Code from './Code.astro'
|
|
6
7
|
|
|
7
8
|
// Prints everything between `// scss-docs-start "name"` and `// scss-docs-end "name"`
|
|
@@ -14,7 +15,8 @@ interface Props {
|
|
|
14
15
|
*/
|
|
15
16
|
name: string
|
|
16
17
|
/**
|
|
17
|
-
* File path that contains the content to display relative to the
|
|
18
|
+
* File path that contains the content to display, relative to the `sourceDir` of the site's
|
|
19
|
+
* `config.yml` (the working directory of the build when it is not set).
|
|
18
20
|
*/
|
|
19
21
|
file: string
|
|
20
22
|
/**
|
|
@@ -74,7 +76,7 @@ let content: string
|
|
|
74
76
|
let lang: string = 'scss'
|
|
75
77
|
|
|
76
78
|
try {
|
|
77
|
-
const fileContent = fs.readFileSync(file, 'utf8')
|
|
79
|
+
const fileContent = fs.readFileSync(getSourceFsPath(file), 'utf8')
|
|
78
80
|
|
|
79
81
|
const matches = fileContent.match(
|
|
80
82
|
new RegExp(`// scss-docs-start ${name}\n((?:.|\n)*)// scss-docs-end ${name}`, 'm')
|
|
@@ -90,7 +92,7 @@ try {
|
|
|
90
92
|
|
|
91
93
|
if (compile) {
|
|
92
94
|
// Derive the SCSS load path from the file argument (e.g. "scss/_foo.scss" → "scss/")
|
|
93
|
-
const scssLoadPath =
|
|
95
|
+
const scssLoadPath = getSourceFsPath(file.split('/')[0])
|
|
94
96
|
|
|
95
97
|
const scssInput = [
|
|
96
98
|
'@use "config" as *;',
|
|
@@ -107,7 +109,7 @@ try {
|
|
|
107
109
|
const result = await sass.compileStringAsync(scssInput, {
|
|
108
110
|
loadPaths: [
|
|
109
111
|
scssLoadPath,
|
|
110
|
-
|
|
112
|
+
getSourceFsPath('scss/vendor'),
|
|
111
113
|
// Vite's own Sass importer resolves bare npm specifiers (e.g. `@chassis-ui/tokens/...`)
|
|
112
114
|
// through its module resolver, independent of `loadPaths`. This raw Sass JS API call
|
|
113
115
|
// bypasses Vite, so `node_modules` must be added here explicitly.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import fs from 'node:fs'
|
|
3
|
+
import { getSourceFsPath } from '../../libs/source'
|
|
3
4
|
import Code from './Code.astro'
|
|
4
5
|
|
|
5
6
|
// Prints everything between `// scss-docs-start "name"` and `// scss-docs-end "name"`
|
|
@@ -11,7 +12,8 @@ interface Props {
|
|
|
11
12
|
*/
|
|
12
13
|
name: string
|
|
13
14
|
/**
|
|
14
|
-
* File path that contains the content to display relative to the
|
|
15
|
+
* File path that contains the content to display, relative to the `sourceDir` of the site's
|
|
16
|
+
* `config.yml` (the working directory of the build when it is not set).
|
|
15
17
|
*/
|
|
16
18
|
file: string
|
|
17
19
|
}
|
|
@@ -29,7 +31,7 @@ if (!name || !file) {
|
|
|
29
31
|
let content: string
|
|
30
32
|
|
|
31
33
|
try {
|
|
32
|
-
const fileContent = fs.readFileSync(file, 'utf8')
|
|
34
|
+
const fileContent = fs.readFileSync(getSourceFsPath(file), 'utf8')
|
|
33
35
|
|
|
34
36
|
const matches = fileContent.match(
|
|
35
37
|
new RegExp(`// scss-docs-start ${name}\n((?:.|\n)*)// scss-docs-end ${name}`, 'm')
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
import type { MarkdownHeading } from 'astro'
|
|
9
9
|
import type { CollectionEntry } from 'astro:content'
|
|
10
10
|
import { getConfig } from '@libs/config'
|
|
11
|
+
import { docsPages } from '@libs/content'
|
|
11
12
|
import { getChassisDocsPath } from '@libs/path'
|
|
12
13
|
import type { LayoutOverridesHTMLAttributes } from '../libs/layout'
|
|
14
|
+
import { getSiteFileUrl } from '../libs/source'
|
|
13
15
|
import { getSlug, processMarkdownToHtml } from '../libs/utils'
|
|
14
16
|
import BaseLayout from './BaseLayout.astro'
|
|
15
17
|
import DocsSidebar from '../components/DocsSidebar.astro'
|
|
@@ -23,10 +25,20 @@ interface Props {
|
|
|
23
25
|
headings?: MarkdownHeading[]
|
|
24
26
|
/** Document ID from the docs collection */
|
|
25
27
|
id: CollectionEntry<'docs'>['id']
|
|
28
|
+
/**
|
|
29
|
+
* Path of the page's source file from the site's root. Looked up from the docs collection
|
|
30
|
+
* by `id` when omitted.
|
|
31
|
+
*/
|
|
32
|
+
filePath?: string
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
const { frontmatter, headings, id } = Astro.props
|
|
29
36
|
|
|
37
|
+
// "View on GitHub" links to the page's own source file. The old link, which assumed the
|
|
38
|
+
// file sat at `<id>.mdx` in the repository root, is kept only when no file path is known.
|
|
39
|
+
const filePath = Astro.props.filePath ?? docsPages.find((page) => page.id === id)?.filePath
|
|
40
|
+
const githubUrl = filePath ? getSiteFileUrl(filePath) : `${getConfig().repo}/blob/${id}.mdx`
|
|
41
|
+
|
|
30
42
|
type DocSection = NonNullable<typeof frontmatter.sections>[number]
|
|
31
43
|
|
|
32
44
|
// Extract the directory/section from the ID (format: "directory/filename.mdx")
|
|
@@ -71,9 +83,7 @@ if (frontmatter.toc) {
|
|
|
71
83
|
<main class="cxd-main">
|
|
72
84
|
<div class="cxd-intro">
|
|
73
85
|
<slot name="intro">
|
|
74
|
-
<div
|
|
75
|
-
class="md:d-flex md:flex-row-reverse justify-content-between align-items-start"
|
|
76
|
-
>
|
|
86
|
+
<div class="md:d-flex md:flex-row-reverse justify-content-between align-items-start">
|
|
77
87
|
<div class="mb-md md:mb-0 d-flex text-nowrap">
|
|
78
88
|
{
|
|
79
89
|
// This is needed because we want to show the badge if show_badge isn't present or is set to false
|
|
@@ -88,7 +98,7 @@ if (frontmatter.toc) {
|
|
|
88
98
|
}
|
|
89
99
|
<a
|
|
90
100
|
class="button default sm"
|
|
91
|
-
href={
|
|
101
|
+
href={githubUrl}
|
|
92
102
|
title="View and edit this file on GitHub"
|
|
93
103
|
target="_blank"
|
|
94
104
|
rel="noopener"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { getConfig } from '@libs/config'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The part of the site's `config.yml` that says where files live, on disk and on GitHub.
|
|
6
|
+
*
|
|
7
|
+
* All four location keys are optional. A site that sets none of them is assumed to be built
|
|
8
|
+
* from the root of its repository, with its source files in that root.
|
|
9
|
+
*/
|
|
10
|
+
interface SourceConfig {
|
|
11
|
+
/** Repository URL (e.g. `"https://github.com/chassis-ui/css"`). */
|
|
12
|
+
repo: string
|
|
13
|
+
/** Version of the release that links to source files name. */
|
|
14
|
+
current_version: string
|
|
15
|
+
/**
|
|
16
|
+
* Directory the `file` props of `<ScssDocs>`, `<ScssDocsSimple>`, `<JsDocs>` and `<Code>` are
|
|
17
|
+
* relative to, itself relative to the working directory of the build (e.g. `"../css"` for a
|
|
18
|
+
* site in `packages/site`).
|
|
19
|
+
*/
|
|
20
|
+
sourceDir?: string
|
|
21
|
+
/** The same directory from the root of the repository (e.g. `"packages/css"`). */
|
|
22
|
+
sourcePath?: string
|
|
23
|
+
/** The site's root from the root of the repository (e.g. `"packages/site"`). */
|
|
24
|
+
sitePath?: string
|
|
25
|
+
/** The branch that "View on GitHub" links to. Defaults to `"main"`. */
|
|
26
|
+
siteBranch?: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getSourceConfig(): SourceConfig {
|
|
30
|
+
return getConfig() as SourceConfig
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Joins URL segments, skipping empty ones, and resolves any `..` in them. */
|
|
34
|
+
function toUrl(segments: (string | undefined)[]): string {
|
|
35
|
+
const url = segments.filter(Boolean).join('/').replaceAll('\\', '/')
|
|
36
|
+
|
|
37
|
+
return new URL(url).href
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Absolute path of a file or directory that a `file` prop names. */
|
|
41
|
+
export function getSourceFsPath(file = ''): string {
|
|
42
|
+
return path.resolve(process.cwd(), getSourceConfig().sourceDir ?? '.', file)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** URL of a source file on GitHub, in the tag of the current version. */
|
|
46
|
+
export function getSourceUrl(file: string): string {
|
|
47
|
+
const { repo, current_version: version, sourcePath } = getSourceConfig()
|
|
48
|
+
|
|
49
|
+
return toUrl([repo, 'blob', `v${version}`, sourcePath, file])
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* URL of a file of the site on GitHub, on the site's branch.
|
|
54
|
+
*
|
|
55
|
+
* @param filePath Path of the file from the site's root, as Astro stores it in a content
|
|
56
|
+
* entry's `filePath` (e.g. `"content/docs/getting-started/introduction.mdx"`).
|
|
57
|
+
*/
|
|
58
|
+
export function getSiteFileUrl(filePath: string): string {
|
|
59
|
+
const { repo, sitePath, siteBranch = 'main' } = getSourceConfig()
|
|
60
|
+
|
|
61
|
+
return toUrl([repo, 'blob', siteBranch, sitePath, filePath])
|
|
62
|
+
}
|