starlight-theme-nova 0.3.0 → 0.4.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "starlight-theme-nova",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.4.0",
5
5
  "description": "",
6
6
  "author": "ocavue <ocavue@gmail.com>",
7
7
  "license": "MIT",
@@ -0,0 +1,64 @@
1
+ ---
2
+ import type { ComponentProps } from 'astro/types'
3
+ import { existsSync } from 'node:fs'
4
+ import fs from 'node:fs/promises'
5
+ import { basename } from 'node:path'
6
+ import Code from './Code.astro'
7
+ import config from 'virtual:starlight-theme-nova/user-config'
8
+ import { fileURLToPath } from 'node:url'
9
+
10
+ type CodeProps = ComponentProps<typeof Code>
11
+
12
+ interface Props extends Omit<CodeProps, 'code' | 'lang'> {
13
+ /**
14
+ * The file path relative to the project root.
15
+ */
16
+ path: string
17
+
18
+ /**
19
+ * The title of the file. If not provided, the file name will be used.
20
+ */
21
+ title?: string
22
+
23
+ /**
24
+ * The language of the file. If not provided, the file extension will be used.
25
+ */
26
+ lang?: CodeProps['lang']
27
+ }
28
+
29
+ const { path, title, lang, meta, ...rest } = Astro.props
30
+
31
+ if (!path) {
32
+ throw new Error('path is required for <CodeFile> component')
33
+ }
34
+
35
+ const root = new URL(config.rootHref)
36
+ const url = new URL(path, root)
37
+ const absolutePath = fileURLToPath(url)
38
+ if (!existsSync(absolutePath)) {
39
+ throw new Error(`Unable to find file ${absolutePath}`)
40
+ }
41
+
42
+ let code: string
43
+ try {
44
+ code = await fs.readFile(absolutePath, 'utf-8')
45
+ } catch (error) {
46
+ throw new Error(`Unable to read file ${absolutePath}: ${error}`, {
47
+ cause: error,
48
+ })
49
+ }
50
+
51
+ let fileName = basename(path)
52
+ let defaultLang = (fileName.split('.').pop() || 'plaintext') as 'plaintext'
53
+ let defaultTitle = fileName
54
+ let titleMeta = `title="${title || defaultTitle}"`
55
+
56
+ const codeProps: CodeProps = {
57
+ ...rest,
58
+ lang: lang ?? defaultLang,
59
+ meta: meta ? `${meta} ${titleMeta}` : titleMeta,
60
+ code,
61
+ }
62
+ ---
63
+
64
+ <Code {...codeProps} />
@@ -1,6 +1,7 @@
1
1
  export { default as Code } from './Code.astro'
2
+ export { default as CodeFile } from './CodeFile.astro'
2
3
  export { default as CodePackageManagers } from './CodePackageManagers.astro'
3
- export { default as CodeTabs } from './CodeTabs.astro'
4
4
  export { default as CodeTabItem } from './CodeTabItem.astro'
5
+ export { default as CodeTabs } from './CodeTabs.astro'
5
6
  export { default as LinkButton } from './LinkButton.astro'
6
7
  export { default as LinkCard } from './LinkCard.astro'
package/src/index.ts CHANGED
@@ -32,7 +32,7 @@ export default function starlightThemeNova(
32
32
  return {
33
33
  name: 'starlight-theme-nova',
34
34
  hooks: {
35
- setup({ config, updateConfig, addIntegration }) {
35
+ setup({ config, updateConfig, addIntegration, astroConfig }) {
36
36
  const newConfig = {
37
37
  customCss: [
38
38
  // Including any user CSS *after* our own.
@@ -58,7 +58,12 @@ export default function starlightThemeNova(
58
58
  shikiConfig: createShikiConfig({ twoslash: true }),
59
59
  },
60
60
  vite: {
61
- plugins: [vitePluginUserConfig(options)],
61
+ plugins: [
62
+ vitePluginUserConfig({
63
+ nav: options.nav,
64
+ rootHref: astroConfig.root.toString(),
65
+ }),
66
+ ],
62
67
  },
63
68
  })
64
69
  },
@@ -6,3 +6,11 @@ export interface NavItem {
6
6
  export interface ThemeNovaOptions {
7
7
  nav?: NavItem[]
8
8
  }
9
+
10
+ /**
11
+ * @internal
12
+ */
13
+ export interface ConfigSerialized {
14
+ nav?: NavItem[]
15
+ rootHref: string
16
+ }
@@ -1,8 +1,8 @@
1
1
  /* eslint-disable @typescript-eslint/consistent-type-imports */
2
2
 
3
3
  declare module 'virtual:starlight-theme-nova/user-config' {
4
- const options: import('./user-options').ThemeNovaOptions
5
- export default options
4
+ const config: import('./user-options').ConfigSerialized
5
+ export default config
6
6
  }
7
7
  declare module 'virtual:starlight/components/Search' {
8
8
  const Search: typeof import('./components/Search.astro').default
@@ -1,6 +1,6 @@
1
1
  import { type ViteUserConfig } from 'astro'
2
2
 
3
- import type { ThemeNovaOptions } from './user-options'
3
+ import type { ConfigSerialized } from './user-options'
4
4
 
5
5
  function resolveVirtualModuleId<T extends string>(id: T): `\0${T}` {
6
6
  return `\0${id}`
@@ -8,11 +8,11 @@ function resolveVirtualModuleId<T extends string>(id: T): `\0${T}` {
8
8
 
9
9
  /** Vite plugin that exposes user config via virtual modules. */
10
10
  export function vitePluginUserConfig(
11
- options: ThemeNovaOptions,
11
+ config: ConfigSerialized,
12
12
  ): NonNullable<ViteUserConfig['plugins']>[number] {
13
13
  /** Map of virtual module names to their code contents as strings. */
14
14
  const modules = {
15
- 'virtual:starlight-theme-nova/user-config': `export default ${JSON.stringify(options)}`,
15
+ 'virtual:starlight-theme-nova/user-config': `export default ${JSON.stringify(config)}`,
16
16
  } satisfies Record<string, string>
17
17
 
18
18
  /** Mapping names prefixed with `\0` to their original form. */