@chassis-ui/docs 0.5.0 → 0.6.0-next.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/UPGRADING.md ADDED
@@ -0,0 +1,243 @@
1
+ # Upgrading @chassis-ui/docs
2
+
3
+ ## From 0.5 to 0.6
4
+
5
+ 0.6.0 is a breaking release. In 0.5 a site had to supply five modules behind a `@libs/*`
6
+ path alias, and every site carried its own copy of them. In 0.6 the package owns that code.
7
+ A site adds one integration and deletes its copies.
8
+
9
+ Do the steps in order. The build fails with a message that names the step you missed.
10
+
11
+ ### 1. Update the dependency
12
+
13
+ ```sh
14
+ pnpm add -D @chassis-ui/docs@^0.6.0
15
+ ```
16
+
17
+ The package now brings these itself. Remove each one that your own code does not import:
18
+ `js-yaml`, `zod`, `clipboard`, `unified`, `unist-util-visit`, `mdast-util-mdx-jsx`,
19
+ `@types/mdast` and `astro-auto-import`.
20
+
21
+ ### 2. Rename the keys of `config.yml`
22
+
23
+ | 0.5 | 0.6 |
24
+ | --------------------- | ------------------------------------------- |
25
+ | `current_version` | `currentVersion` |
26
+ | `github_org` | `githubOrg` |
27
+ | `figma_handle` | `figmaHandle` |
28
+ | `x_username` | `xUsername` |
29
+ | `analytics.google_id` | `analytics.googleId` |
30
+ | `docsDir` | Delete it. The site root is the Astro root. |
31
+
32
+ - `githubOrg` is the name of the organisation, such as `chassis-ui`. A URL is rejected.
33
+ - `sourceDir` is now relative to the site's root, not to the working directory of the
34
+ build. For a site that is built from its own directory, the value stays the same.
35
+ - The schema is strict. A key that the package does not know fails the build. See step 4
36
+ for the keys of your own, such as `blog`, `download` or `cdn`.
37
+
38
+ Write your own keys in camelCase too, for example `docsVersion` and `exampleIcon`.
39
+
40
+ Replace the old names in the content as well:
41
+
42
+ ```sh
43
+ grep -rl '\[\[config:current_version\]\]' content src \
44
+ | xargs sed -i '' 's/\[\[config:current_version\]\]/[[config:currentVersion]]/g'
45
+ ```
46
+
47
+ Three keys outside `config.yml` were renamed as well. An old name fails the build.
48
+
49
+ | File | 0.5 | 0.6 |
50
+ | -------------------------- | ------------------ | ----------------- |
51
+ | `data/sidebar.yml` | `icon_color` | `iconColor` |
52
+ | Frontmatter of a docs page | `added.show_badge` | `added.showBadge` |
53
+ | Frontmatter of a docs page | `extra_js` | `extraJs` |
54
+
55
+ ```sh
56
+ sed -i '' 's/icon_color:/iconColor:/' data/sidebar.yml
57
+ grep -rlE '^ *(show_badge|extra_js):' content \
58
+ | xargs sed -i '' -E 's/^( *)show_badge:/\1showBadge:/; s/^( *)extra_js:/\1extraJs:/'
59
+ ```
60
+
61
+ Rename them in your own components and collection schemas too, where they read
62
+ `icon_color`, `show_badge` or `extra_js`.
63
+
64
+ ### 3. Replace the Astro configuration
65
+
66
+ Before:
67
+
68
+ ```ts
69
+ import { chassis } from './src/libs/astro'
70
+ import { getConfig } from './src/libs/config'
71
+ import { remarkCxConfig, remarkCxDocsref } from './src/libs/remark'
72
+ import { chassisAutoImportPlugin } from './src/libs/shortcode'
73
+ import { getSiteUrl, getDocsMarkdownConfig } from '@chassis-ui/docs'
74
+
75
+ export default defineConfig({
76
+ site: getSiteUrl(getConfig()),
77
+ integrations: [chassis()],
78
+ markdown: getDocsMarkdownConfig({
79
+ anchors: getConfig().anchors,
80
+ remarkPlugins: [chassisAutoImportPlugin(), remarkCxConfig, remarkCxDocsref, myPlugin]
81
+ })
82
+ // ...
83
+ })
84
+ ```
85
+
86
+ After:
87
+
88
+ ```ts
89
+ import { loadConfig } from '@chassis-ui/docs'
90
+ import { chassisDocs } from '@chassis-ui/docs/integration'
91
+ import { chassis } from './src/libs/astro'
92
+ import { siteConfigSchema } from './src/libs/config'
93
+
94
+ const root = import.meta.dirname
95
+ const config = loadConfig({ root, schema: siteConfigSchema })
96
+
97
+ export default defineConfig({
98
+ integrations: [
99
+ chassisDocs({ config, markdown: { remarkPlugins: [myPlugin] } }),
100
+ chassis({ config, root })
101
+ ]
102
+ // ...
103
+ })
104
+ ```
105
+
106
+ - Remove `site` and `markdown`. The integration sets both.
107
+ - Pass only your own remark and rehype plugins. `rehypeCxTable` is already included.
108
+ - A site that does not need the config in `astro.config.ts` calls `chassisDocs()` with
109
+ `configSchema` and does not call `loadConfig()`.
110
+ - Remove the Sass load path that points to `@chassis-ui/css/scss/vendor`, the folder of the
111
+ default `_chassis-tokens.scss`. The integration adds it, after the site's own load paths.
112
+ Keep a load path that points to tokens of your own.
113
+
114
+ ### 4. Replace the files in `src/libs`
115
+
116
+ | File | What to do |
117
+ | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
118
+ | `config.ts` | Replace the content with the schema of your own keys. See below. Delete the file if you have none. |
119
+ | `validation.ts` | Delete. `zVersionSemver`, `zVersionMajorMinor`, `zPrefixedVersionSemver` and `zLanguageCode` are in `@chassis-ui/docs/schema`. Keep validators of your own. |
120
+ | `clipboard.ts` | Delete. Import `initCopyButtons` from `@chassis-ui/docs/js/clipboard.ts` if your own code calls it. |
121
+ | `shortcode.ts` | Delete. See step 6. |
122
+ | `path.ts` | Delete. See step 5 for the replacements. |
123
+ | `remark.ts` | Delete `remarkCxConfig`, `remarkCxDocsref` and their helpers. Keep plugins of your own. |
124
+ | `data.ts` | Delete if `sidebar` was the only data you read. Otherwise replace the loader with `createDataLoader()`. See below. |
125
+ | `content.ts` | Delete `callouts`, `getCalloutByName` and `CalloutName`. Keep the collections that your own pages read. |
126
+ | `astro.ts` | Keep. It copies the static files and adds `mdx()` and `sitemap()`. Change it as described below. |
127
+
128
+ `src/libs/config.ts`:
129
+
130
+ ```ts
131
+ import { configSchema, z } from '@chassis-ui/docs/schema'
132
+
133
+ export const siteConfigSchema = configSchema.extend({
134
+ blog: z.url()
135
+ })
136
+
137
+ export type SiteConfig = z.infer<typeof siteConfigSchema>
138
+ ```
139
+
140
+ `src/libs/data.ts`, for a site with data files of its own:
141
+
142
+ ```ts
143
+ import { createDataLoader } from '@chassis-ui/docs/site'
144
+ import { z } from '@chassis-ui/docs/schema'
145
+
146
+ export const getData = createDataLoader({
147
+ breakpoints: z.object({ name: z.string() }).array()
148
+ })
149
+ ```
150
+
151
+ `src/libs/astro.ts`:
152
+
153
+ - Take `{ config, root }` as the argument of `chassis()`, and stop calling `getConfig()`.
154
+ - Remove `chassisAutoImportIntegration()` from the list of integrations.
155
+ - Remove the `astro:build:done` hook that calls `validateChassisDocsPaths()`.
156
+ - Import `getChassisAssetsFsPath`, `getChassisCSSFsPath`, `getChassisIconsFsPath` and
157
+ `getChassisTokensFsPath` from `@chassis-ui/docs` and call them with `{ root }`. Pass
158
+ `dir` when the folder is not the installed package, as in `chassis-css`, which copies
159
+ from `../css/dist`.
160
+ - Replace `getDocsFsPath()` with `root`, `getDocsPublicFsPath()` with
161
+ `path.join(root, 'public')`, and `getDocsStaticFsPath()` with
162
+ `path.join(root, 'static')`.
163
+ - Remove the Vite alias for `@chassis-ui/css` and `optimizeDeps: { exclude:
164
+ ['@chassis-ui/docs'] }`. The integration now makes every script use one copy of
165
+ `@chassis-ui/css`, in the dev server and in the build. It needs no alias.
166
+
167
+ ### 5. Replace the imports in pages and components
168
+
169
+ | 0.5 | 0.6 |
170
+ | --------------------------------------------------- | -------------------------------------------------- |
171
+ | `getConfig` from `@libs/config` | `getConfig` from `@chassis-ui/docs/site` |
172
+ | `getData('sidebar')` from `@libs/data` | `getSidebar()` from `@chassis-ui/docs/site` |
173
+ | `getChassisDocsPath` from `@libs/path` | `getDocsPath` from `@chassis-ui/docs/site` |
174
+ | `getDocsFsPath` from `@libs/path` | `getSiteRoot` from `@chassis-ui/docs/site` |
175
+ | `getDocsPublicFsPath` from `@libs/path` | `getPublicFsPath` from `@chassis-ui/docs/site` |
176
+ | `getDocsRelativePath(file)` from `@libs/path` | `getSiteFsPath(file)` from `@chassis-ui/docs/site` |
177
+ | `replaceConfigInText` from `@libs/remark` | `resolveConfigRefs` from `@chassis-ui/docs/site` |
178
+ | `replaceDocsrefInText` from `@libs/remark` | `resolveDocsrefs` from `@chassis-ui/docs/site` |
179
+ | `getCalloutByName` from `@libs/content` | `getCallout` from `@chassis-ui/docs/site` |
180
+ | A path into `node_modules/@chassis-ui/docs/src/` | `getPackageFilePath('js/color-modes.js')` |
181
+ | `@chassis-ui/docs/components/shortcodes/Icon.astro` | `@chassis-ui/docs/shortcodes/Icon.astro` |
182
+
183
+ Only the paths that the README lists under "Exports" resolve. `@chassis-ui/docs/libs/*`, the
184
+ folders inside `layouts/` and `components/`, and the partials under `scss/` other than `main`
185
+ and `vars` fail with "not exported". Import a layout or component by its name, such as
186
+ `@chassis-ui/docs/layouts/DocsLayout.astro`.
187
+
188
+ `getConfig()` returns the keys of the package. For the keys of your own, name your type:
189
+ `getConfig<SiteConfig>()`.
190
+
191
+ Use the schemas of the package in `src/content.config.ts`:
192
+
193
+ ```ts
194
+ import { calloutsSchema, docsSchema } from '@chassis-ui/docs/schema'
195
+
196
+ const docsCollection = defineCollection({
197
+ loader: glob({ pattern: '**/*.{md,mdx}', base: './content/docs' }),
198
+ schema: docsSchema
199
+ })
200
+ ```
201
+
202
+ `docsSchema` is already partial. Do not call `.partial()` on it.
203
+
204
+ ### 6. Shortcodes
205
+
206
+ - Delete `src/types/auto-import.d.ts`. The integration writes the declarations into
207
+ `.astro/`.
208
+ - A shortcode in `src/components/shortcodes/` replaces the package's shortcode of the same
209
+ name. No configuration is needed.
210
+ - To leave out a shortcode of the package, pass
211
+ `chassisDocs({ shortcodes: { exclude: ['Icon'] } })`.
212
+
213
+ ### 7. Path aliases
214
+
215
+ The package no longer needs `@libs/*`, `@scss/*` or `@shortcodes/*` in `tsconfig.json`.
216
+ Keep the ones that your own code imports.
217
+
218
+ The stylesheet that every page loads was `@scss/docs.scss`. It is now `src/scss/docs.scss`
219
+ in the site's root, which is the same file. Pass `styles` to the integration to name
220
+ another one.
221
+
222
+ ### What changes in behaviour
223
+
224
+ - **Broken `[[docsref:]]` links fail the build.** Five sites only logged them. Fix the
225
+ links, or pass `brokenDocsrefs: 'warn'` until they are fixed.
226
+ - **A page of the sidebar may have no `title`.** The schema of `data/sidebar.yml` now
227
+ allows groups, so the type of `title` is `string | undefined`. Code of your own that
228
+ reads the sidebar has to handle that.
229
+ - **The header shows the Figma and GitHub links only when `figmaHandle` and `githubOrg`
230
+ are set.** The same holds for the X meta tags and `xUsername`, and for Google Analytics
231
+ and `analytics.googleId`.
232
+ - **`@chassis-ui/docs` and `@chassis-ui/css` are not pre-bundled in the dev server.** Both
233
+ are served from source, so a script of the site and a script of the package import the
234
+ same copy of `@chassis-ui/css`. The dependency `clipboard` is still pre-bundled.
235
+ - **The working directory of the build does not matter.** `config.yml`, `data/` and the
236
+ `file` props are found from the Astro root. A site that is built with
237
+ `astro build --root site` no longer names `./site/` in its paths.
238
+
239
+ ### Check the result
240
+
241
+ Build the site before and after the upgrade and compare the output. An upgrade from 0.5.1
242
+ changes nothing in the output. An upgrade from 0.5.0 or 0.5.0-0 changes the "View on
243
+ GitHub" links, as the changelog describes for 0.5.1.
package/index.ts CHANGED
@@ -1,11 +1,17 @@
1
- // Shared libraries for documentation sites
1
+ // Library functions. They are safe to import anywhere: in `astro.config.ts`, in a site's own
2
+ // integrations, and in pages. What pages read from the site is in `@chassis-ui/docs/site`.
3
+ export * from './src/libs/config'
4
+ export * from './src/libs/docs-path'
2
5
  export * from './src/libs/highlight'
3
6
  export * from './src/libs/image'
4
7
  export * from './src/libs/layout'
5
8
  export * from './src/libs/markdown'
9
+ export * from './src/libs/paths'
6
10
  export * from './src/libs/placeholder'
7
11
  export * from './src/libs/rehype'
12
+ export * from './src/libs/remark'
8
13
  export * from './src/libs/shortcodes'
9
14
  export * from './src/libs/site'
15
+ export * from './src/libs/source'
10
16
  export * from './src/libs/toc'
11
17
  export * from './src/libs/utils'
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.0",
4
+ "version": "0.6.0-next.0",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -25,21 +25,42 @@
25
25
  "files": [
26
26
  "src",
27
27
  "index.ts",
28
- "README.md"
28
+ "virtual.d.ts",
29
+ "README.md",
30
+ "UPGRADING.md",
31
+ "LICENSE",
32
+ "CHANGELOG.md"
29
33
  ],
30
34
  "main": "index.ts",
31
35
  "exports": {
32
36
  ".": "./index.ts",
33
- "./components/*": "./src/components/*",
37
+ "./integration": "./src/integration.ts",
38
+ "./schema": "./src/libs/schema.ts",
39
+ "./site": "./src/site.ts",
40
+ "./layouts/BaseLayout.astro": "./src/layouts/BaseLayout.astro",
41
+ "./layouts/DocsLayout.astro": "./src/layouts/DocsLayout.astro",
42
+ "./layouts/RedirectLayout.astro": "./src/layouts/RedirectLayout.astro",
43
+ "./layouts/SingleLayout.astro": "./src/layouts/SingleLayout.astro",
44
+ "./components/DocsSidebar.astro": "./src/components/DocsSidebar.astro",
45
+ "./components/FeatureCard.astro": "./src/components/FeatureCard.astro",
46
+ "./components/NavLink.astro": "./src/components/NavLink.astro",
47
+ "./components/ResponsiveImage.astro": "./src/components/ResponsiveImage.astro",
48
+ "./components/TableOfContents.astro": "./src/components/TableOfContents.astro",
49
+ "./components/ThemeToggler.astro": "./src/components/ThemeToggler.astro",
34
50
  "./shortcodes/*": "./src/components/shortcodes/*",
35
- "./layouts/*": "./src/layouts/*",
36
- "./libs/*": "./src/libs/*",
37
51
  "./js/*": "./src/js/*",
38
- "./scss/*": "./src/scss/*"
52
+ "./scss/main": "./src/scss/main.scss",
53
+ "./scss/main.scss": "./src/scss/main.scss",
54
+ "./scss/vars": "./src/scss/_vars.scss",
55
+ "./scss/_vars.scss": "./src/scss/_vars.scss",
56
+ "./package.json": "./package.json"
39
57
  },
40
58
  "publishConfig": {
41
59
  "access": "public"
42
60
  },
61
+ "engines": {
62
+ "node": ">=22.12.0"
63
+ },
43
64
  "scripts": {
44
65
  "astro": "astro"
45
66
  },
@@ -55,18 +76,24 @@
55
76
  "shiki": "^4.3.1"
56
77
  },
57
78
  "dependencies": {
79
+ "@types/hast": "^3.0.5",
80
+ "@types/mdast": "^4.0.4",
81
+ "clipboard": "^2.0.11",
58
82
  "github-slugger": "^2.0.0",
59
- "image-size": "^2.0.2",
83
+ "image-size": "^2.0.4",
84
+ "js-yaml": "^5.4.2",
60
85
  "mdast-util-from-markdown": "^2.0.3",
86
+ "mdast-util-mdx-jsx": "^3.2.0",
61
87
  "mdast-util-to-string": "^4.0.0",
62
88
  "medium-zoom": "^1.1.0",
63
89
  "remark": "^15.0.1",
64
90
  "remark-html": "^16.0.1",
91
+ "unified": "^11.0.5",
65
92
  "unist-util-visit": "^5.1.0"
66
93
  },
67
94
  "devDependencies": {
68
- "@types/hast": "^3.0.4",
69
- "astro": "^7.0.6",
70
- "unified": "^11.0.5"
95
+ "astro": "^7.3.5",
96
+ "remark-mdx": "^3.1.1",
97
+ "vfile": "^6.0.3"
71
98
  }
72
99
  }
@@ -5,13 +5,13 @@
5
5
  * Navigation sidebar for documentation pages with hierarchical menu structure.
6
6
  */
7
7
 
8
- import { getData, type SidebarItem, type SidebarSubItem } from '@libs/data'
9
- import { getConfig } from '@libs/config'
10
- import { docsPages } from '@libs/content'
8
+ import type { SidebarItem, SidebarSubItem } from '../libs/schema'
11
9
  import { getSlug } from '../libs/utils'
10
+ import { getDocsPages, getDocsPath, getSidebar } from '../site'
12
11
  import Icon from './shortcodes/Icon.astro'
13
12
 
14
- const sidebar = getData('sidebar')
13
+ const sidebar = getSidebar()
14
+ const docsPages = await getDocsPages()
15
15
  ---
16
16
 
17
17
  <nav class="cxd-links w-100" id="cxd-docs-nav" aria-label="Docs navigation">
@@ -32,7 +32,7 @@ const sidebar = getData('sidebar')
32
32
  {group.icon && (
33
33
  <Icon
34
34
  name={group.icon}
35
- style={group.icon_color && `color: var(--cx-${group.icon_color});`}
35
+ style={group.iconColor && `color: var(--cx-${group.iconColor});`}
36
36
  />
37
37
  )}
38
38
  {group.title}
@@ -48,7 +48,7 @@ const sidebar = getData('sidebar')
48
48
  const docSlug = getSlug(page.title)
49
49
  const unversionedPageSlug = `${groupSlug}/${docSlug}`
50
50
 
51
- const url = `${getConfig().docsPath}/${unversionedPageSlug}`
51
+ const url = getDocsPath(unversionedPageSlug)
52
52
  const active = Astro.params.slug === unversionedPageSlug
53
53
 
54
54
  const generatedPage = docsPages.find(
@@ -58,7 +58,7 @@ const sidebar = getData('sidebar')
58
58
  // This test should not be necessary, see comments for `getSlug()` in `src/libs/utils.ts`.
59
59
  if (!generatedPage) {
60
60
  throw new Error(
61
- `The page '${page.title}' referenced in 'site/data/sidebar.yml' does not exist at '${url}'.`
61
+ `The page '${page.title}' referenced in 'data/sidebar.yml' does not exist at '${url}'.`
62
62
  )
63
63
  }
64
64
 
@@ -86,7 +86,7 @@ const sidebar = getData('sidebar')
86
86
  const docSlug = getSlug(item.title)
87
87
  const unversionedPageSlug = `${groupSlug}/${docSlug}`
88
88
 
89
- const url = `${getConfig().docsPath}/${unversionedPageSlug}`
89
+ const url = getDocsPath(unversionedPageSlug)
90
90
  const active = Astro.params.slug === unversionedPageSlug
91
91
 
92
92
  const generatedPage = docsPages.find((page) => page.id === unversionedPageSlug)
@@ -120,7 +120,7 @@ const sidebar = getData('sidebar')
120
120
  <>
121
121
  <li class="cxd-links-span-all mt-2xs mb-md mx-lg border-top" />
122
122
  <a
123
- href={`${getConfig().docsPath}/${groupSlug}/`}
123
+ href={getDocsPath(`${groupSlug}/`)}
124
124
  class:list={['cxd-links-link cxd-links-span-all', { active }]}
125
125
  aria-current={active ? 'page' : undefined}
126
126
  >
@@ -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
- class=`${layout === 'examples' ? 'visually-hidden' : 'lg:d-none ms-xs'}`
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
- class="badge lg info smooth mb-md rounded-md"
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
  >
@@ -5,16 +5,16 @@
5
5
  * Display informational callout boxes with different types (info, danger, warning).
6
6
  */
7
7
 
8
- import { getCalloutByName, type CalloutName } from '@libs/content'
9
8
  import { render } from 'astro:content'
9
+ import { getCallout } from '../../site'
10
10
  import type { MarkdownInstance } from 'astro'
11
11
 
12
12
  interface Props {
13
13
  /**
14
- * The name of an existing callout to display located in `src/content/callouts`.
14
+ * The name of an entry of the site's `callouts` collection to display.
15
15
  * This will override any content passed in via the default slot.
16
16
  */
17
- name?: CalloutName
17
+ name?: string
18
18
  /**
19
19
  * The type of callout to display. One of `info`, `danger`, or `warning`.
20
20
  * @default 'info'
@@ -31,7 +31,7 @@ const { name, type = 'info', class: className } = Astro.props
31
31
  let Content: MarkdownInstance<{}>['Content'] | undefined
32
32
 
33
33
  if (name) {
34
- const callout = await getCalloutByName(name)
34
+ const callout = await getCallout(name)
35
35
 
36
36
  if (!callout) {
37
37
  throw new Error(`Could not find callout with name '${name}'.`)
@@ -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 '../../site'
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 root of the repository.
43
+ * A path to the file containing the code to highlight, relative to the `sourceDir` of the
44
+ * site's `config.yml` (the site's root 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(path.join(process.cwd(), filePath), 'utf8')
122
+ ? fs.readFileSync(getSourceFsPath(filePath), 'utf8')
125
123
  : Array.isArray(code)
126
124
  ? code.join('\n')
127
125
  : code
@@ -149,7 +147,7 @@ if (codeToDisplay && detectedLang) {
149
147
 
150
148
  <script>
151
149
  import { Tooltip } from '@chassis-ui/css'
152
- import { initCopyButtons } from '@libs/clipboard'
150
+ import { initCopyButtons } from '../../js/clipboard'
153
151
 
154
152
  document.querySelectorAll('.button-edit').forEach((button) => {
155
153
  Tooltip.getOrCreateInstance(button, { title: 'Edit on StackBlitz' })
@@ -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
- class="badge lg primary smooth mb-md rounded-md"
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,7 @@
1
1
  ---
2
2
  import fs from 'node:fs'
3
+ import { getSourceFsPath } from '../../site'
4
+ import { extractDocsSnippet } from '../../libs/snippet'
3
5
  import Code from './Code.astro'
4
6
 
5
7
  // Prints everything between `// js-docs-start "name"` and `// js-docs-end "name"`
@@ -11,7 +13,8 @@ interface Props {
11
13
  */
12
14
  name: string
13
15
  /**
14
- * File path that contains the content to display relative to the root of the repository.
16
+ * File path that contains the content to display, relative to the `sourceDir` of the site's
17
+ * `config.yml` (the site's root when it is not set).
15
18
  */
16
19
  file: string
17
20
  }
@@ -27,19 +30,17 @@ if (!name || !file) {
27
30
  let content: string
28
31
 
29
32
  try {
30
- const fileContent = fs.readFileSync(file, 'utf8')
33
+ const fileContent = fs.readFileSync(getSourceFsPath(file), 'utf8')
31
34
 
32
- const matches = fileContent.match(
33
- new RegExp(`// js-docs-start ${name}\n((?:.|\n)*)// js-docs-end ${name}`, 'm')
34
- )
35
+ const snippet = extractDocsSnippet(fileContent, 'js', name)
35
36
 
36
- if (!matches || !matches[1]) {
37
+ if (!snippet) {
37
38
  throw new Error(
38
39
  `Failed to find the content named '${name}', make sure that '// js-docs-start ${name}' and '// js-docs-end ${name}' are defined.`
39
40
  )
40
41
  }
41
42
 
42
- content = matches[1]
43
+ content = snippet
43
44
 
44
45
  // Fix the identation by removing extra spaces at the beginning of each line
45
46
  const lines = content.split('\n')
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  import fs from 'node:fs'
3
- import path from 'node:path'
4
3
  import * as sass from 'sass'
4
+ import { getNodeModulesPaths, getSourceFsPath } from '../../site'
5
+ import { extractDocsSnippet } from '../../libs/snippet'
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 root of the repository.
18
+ * File path that contains the content to display, relative to the `sourceDir` of the site's
19
+ * `config.yml` (the site's root when it is not set).
18
20
  */
19
21
  file: string
20
22
  /**
@@ -74,23 +76,21 @@ 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
- const matches = fileContent.match(
80
- new RegExp(`// scss-docs-start ${name}\n((?:.|\n)*)// scss-docs-end ${name}`, 'm')
81
- )
81
+ const snippet = extractDocsSnippet(fileContent, 'scss', name)
82
82
 
83
- if (!matches || !matches[1]) {
83
+ if (!snippet) {
84
84
  throw new Error(
85
85
  `Failed to find the content named '${name}', make sure that '// scss-docs-start ${name}' and '// scss-docs-end ${name}' are defined.`
86
86
  )
87
87
  }
88
88
 
89
- const rawContent = matches[1]
89
+ const rawContent = snippet
90
90
 
91
91
  if (compile) {
92
92
  // Derive the SCSS load path from the file argument (e.g. "scss/_foo.scss" → "scss/")
93
- const scssLoadPath = path.resolve(process.cwd(), file.split('/')[0])
93
+ const scssLoadPath = getSourceFsPath(file.split('/')[0])
94
94
 
95
95
  const scssInput = [
96
96
  '@use "config" as *;',
@@ -107,11 +107,11 @@ try {
107
107
  const result = await sass.compileStringAsync(scssInput, {
108
108
  loadPaths: [
109
109
  scssLoadPath,
110
- path.resolve(process.cwd(), 'scss/vendor'),
110
+ getSourceFsPath('scss/vendor'),
111
111
  // Vite's own Sass importer resolves bare npm specifiers (e.g. `@chassis-ui/tokens/...`)
112
112
  // through its module resolver, independent of `loadPaths`. This raw Sass JS API call
113
113
  // bypasses Vite, so `node_modules` must be added here explicitly.
114
- path.resolve(process.cwd(), 'node_modules')
114
+ ...getNodeModulesPaths()
115
115
  ],
116
116
  // Match the same deprecation silencing used in astro.config.ts / vite scss options
117
117
  silenceDeprecations: ['import', 'global-builtin', 'color-functions', 'if-function'] as any