@rimelight/ui 0.0.16 → 0.0.17
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 +1 -1
- package/src/integrations/sri.ts +92 -92
- package/src/middleware/index.ts +0 -1
- package/src/middleware/security.ts +81 -11
- package/src/plugins/starlightAddons/index.ts +132 -132
- package/src/plugins/starlightAddons/libs/sidebar.ts +183 -183
- package/src/plugins/starlightAddons/libs/vite.ts +46 -46
- package/src/plugins/starlightAddons/middleware.ts +132 -132
- package/src/middleware/sri.ts +0 -78
|
@@ -1,183 +1,183 @@
|
|
|
1
|
-
import type { StarlightRouteData } from "@astrojs/starlight/route-data"
|
|
2
|
-
|
|
3
|
-
import type { StarlightSidebarTopicsSharedConfig } from "./config"
|
|
4
|
-
import { isStarlightEntryWithTopic, type StarlightEntry } from "./content"
|
|
5
|
-
import { getLocaleFromSlug, getLocalizedSlug } from "./i18n"
|
|
6
|
-
import { arePathnamesEqual, stripLeadingAndTrailingSlashes } from "./pathname"
|
|
7
|
-
|
|
8
|
-
const absoluteLinkRegex = /^https?:\/\//
|
|
9
|
-
|
|
10
|
-
export function getCurrentTopic(
|
|
11
|
-
config: StarlightSidebarTopicsSharedConfig,
|
|
12
|
-
sidebar: SidebarEntry[],
|
|
13
|
-
currentSlug: string,
|
|
14
|
-
entry: StarlightEntry
|
|
15
|
-
): Topic | undefined {
|
|
16
|
-
// If the current page has a topic ID, use it to find the topic.
|
|
17
|
-
const topicId = getTopicIdFromEntry(entry)
|
|
18
|
-
if (topicId) return getTopicById(config, sidebar, topicId)
|
|
19
|
-
|
|
20
|
-
// Start by checking if the current page is a topic root.
|
|
21
|
-
const topicFromSlug = getTopicFromSlug(config, sidebar, currentSlug)
|
|
22
|
-
if (topicFromSlug) return topicFromSlug
|
|
23
|
-
|
|
24
|
-
// Otherwise, find the current topic by looking for the current page in the sidebar.
|
|
25
|
-
const currentSidebarTopic = getCurrentSidebarTopic(sidebar)
|
|
26
|
-
if (!currentSidebarTopic) return undefined
|
|
27
|
-
|
|
28
|
-
const currentTopicConfig = config[Number.parseInt(currentSidebarTopic.label, 10)]
|
|
29
|
-
if (!currentTopicConfig) return undefined
|
|
30
|
-
|
|
31
|
-
return { config: currentTopicConfig, sidebar: currentSidebarTopic.entries }
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function isTopicFirstPage(sidebar: SidebarEntry[], currentSlug: string): boolean {
|
|
35
|
-
const currentSidebarTopic = getCurrentSidebarTopic(sidebar)
|
|
36
|
-
if (!currentSidebarTopic) return false
|
|
37
|
-
|
|
38
|
-
const firstPage = getSidebarFirstPage(currentSidebarTopic.entries)
|
|
39
|
-
if (!firstPage) return false
|
|
40
|
-
|
|
41
|
-
return arePathnamesEqual(stripLeadingAndTrailingSlashes(firstPage.href), currentSlug)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function isTopicLastPage(sidebar: SidebarEntry[], currentSlug: string): boolean {
|
|
45
|
-
const currentSidebarTopic = getCurrentSidebarTopic(sidebar)
|
|
46
|
-
if (!currentSidebarTopic) return false
|
|
47
|
-
|
|
48
|
-
const lastPage = getSidebarLastPage(currentSidebarTopic.entries)
|
|
49
|
-
if (!lastPage) return false
|
|
50
|
-
|
|
51
|
-
return arePathnamesEqual(stripLeadingAndTrailingSlashes(lastPage.href), currentSlug)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function getSidebarFirstPage(sidebar: SidebarEntry[]) {
|
|
55
|
-
const entry = sidebar[0]
|
|
56
|
-
if (!entry) return undefined
|
|
57
|
-
if (entry.type === "link") return entry
|
|
58
|
-
|
|
59
|
-
return getSidebarFirstPage(entry.entries)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function getSidebarLastPage(sidebar: SidebarEntry[]) {
|
|
63
|
-
const entry = sidebar.at(-1)
|
|
64
|
-
if (!entry) return undefined
|
|
65
|
-
if (entry.type === "link") return entry
|
|
66
|
-
|
|
67
|
-
return getSidebarLastPage(entry.entries)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function getTopicFromSlug(
|
|
71
|
-
config: StarlightSidebarTopicsSharedConfig,
|
|
72
|
-
sidebar: SidebarEntry[],
|
|
73
|
-
slug: string
|
|
74
|
-
): Topic | undefined {
|
|
75
|
-
let topicConfig: Topic["config"] | undefined
|
|
76
|
-
let topicSidebar: Topic["sidebar"] | undefined
|
|
77
|
-
|
|
78
|
-
// Start by checking if the current page is a topic homepage.
|
|
79
|
-
let groupTopicIndex = -1
|
|
80
|
-
const slugLocale = getLocaleFromSlug(slug)
|
|
81
|
-
|
|
82
|
-
for (const topic of config) {
|
|
83
|
-
if (topic.type === "group") groupTopicIndex++
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
!absoluteLinkRegex.test(topic.link) &&
|
|
87
|
-
arePathnamesEqual(
|
|
88
|
-
getLocalizedSlug(stripLeadingAndTrailingSlashes(topic.link), slugLocale),
|
|
89
|
-
slug
|
|
90
|
-
) &&
|
|
91
|
-
groupTopicIndex !== -1
|
|
92
|
-
) {
|
|
93
|
-
const sidebarTopic = sidebar[groupTopicIndex]
|
|
94
|
-
|
|
95
|
-
if (sidebarTopic?.type === "group") {
|
|
96
|
-
topicConfig = topic
|
|
97
|
-
topicSidebar = sidebarTopic.entries
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
break
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (!topicConfig || !topicSidebar) return undefined
|
|
105
|
-
|
|
106
|
-
return { config: topicConfig, sidebar: topicSidebar }
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function getTopicById(
|
|
110
|
-
config: StarlightSidebarTopicsSharedConfig,
|
|
111
|
-
sidebar: SidebarEntry[],
|
|
112
|
-
id: string
|
|
113
|
-
): Topic | undefined {
|
|
114
|
-
let topicConfig: Topic["config"] | undefined
|
|
115
|
-
let topicSidebar: Topic["sidebar"] | undefined
|
|
116
|
-
|
|
117
|
-
let groupTopicIndex = -1
|
|
118
|
-
|
|
119
|
-
for (const topic of config) {
|
|
120
|
-
if (topic.type === "group") groupTopicIndex++
|
|
121
|
-
|
|
122
|
-
if (topic.type === "group" && topic.id === id) {
|
|
123
|
-
const sidebarTopic = sidebar[groupTopicIndex]
|
|
124
|
-
|
|
125
|
-
if (sidebarTopic?.type === "group") {
|
|
126
|
-
topicConfig = topic
|
|
127
|
-
topicSidebar = sidebarTopic.entries
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
break
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (!topicConfig || !topicSidebar) return undefined
|
|
135
|
-
|
|
136
|
-
return { config: topicConfig, sidebar: topicSidebar }
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function getCurrentSidebarTopic(sidebar: SidebarEntry[]): SidebarTopic | undefined {
|
|
140
|
-
let currentSidebarTopic: SidebarTopic | undefined
|
|
141
|
-
|
|
142
|
-
for (const topic of sidebar) {
|
|
143
|
-
if (topic.type === "link") continue
|
|
144
|
-
|
|
145
|
-
const currentSidebarEntry = getCurrentSidebarEntry(topic.entries)
|
|
146
|
-
|
|
147
|
-
if (currentSidebarEntry) {
|
|
148
|
-
currentSidebarTopic = topic
|
|
149
|
-
break
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return currentSidebarTopic
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function getCurrentSidebarEntry(sidebar: SidebarEntry[]): SidebarEntry | undefined {
|
|
157
|
-
return sidebar.find((entry) => {
|
|
158
|
-
if (entry.type === "link") {
|
|
159
|
-
return entry.isCurrent
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return getCurrentSidebarEntry(entry.entries)
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function getTopicIdFromEntry(entry: StarlightEntry): string | undefined {
|
|
167
|
-
if (isStarlightEntryWithTopic(entry)) {
|
|
168
|
-
return entry.data.topic
|
|
169
|
-
}
|
|
170
|
-
return undefined
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
type SidebarEntry = StarlightRouteData["sidebar"][number]
|
|
174
|
-
|
|
175
|
-
interface SidebarTopic {
|
|
176
|
-
label: string
|
|
177
|
-
entries: SidebarEntry[]
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export interface Topic {
|
|
181
|
-
config: StarlightSidebarTopicsSharedConfig[number]
|
|
182
|
-
sidebar: SidebarEntry[]
|
|
183
|
-
}
|
|
1
|
+
import type { StarlightRouteData } from "@astrojs/starlight/route-data"
|
|
2
|
+
|
|
3
|
+
import type { StarlightSidebarTopicsSharedConfig } from "./config"
|
|
4
|
+
import { isStarlightEntryWithTopic, type StarlightEntry } from "./content"
|
|
5
|
+
import { getLocaleFromSlug, getLocalizedSlug } from "./i18n"
|
|
6
|
+
import { arePathnamesEqual, stripLeadingAndTrailingSlashes } from "./pathname"
|
|
7
|
+
|
|
8
|
+
const absoluteLinkRegex = /^https?:\/\//
|
|
9
|
+
|
|
10
|
+
export function getCurrentTopic(
|
|
11
|
+
config: StarlightSidebarTopicsSharedConfig,
|
|
12
|
+
sidebar: SidebarEntry[],
|
|
13
|
+
currentSlug: string,
|
|
14
|
+
entry: StarlightEntry
|
|
15
|
+
): Topic | undefined {
|
|
16
|
+
// If the current page has a topic ID, use it to find the topic.
|
|
17
|
+
const topicId = getTopicIdFromEntry(entry)
|
|
18
|
+
if (topicId) return getTopicById(config, sidebar, topicId)
|
|
19
|
+
|
|
20
|
+
// Start by checking if the current page is a topic root.
|
|
21
|
+
const topicFromSlug = getTopicFromSlug(config, sidebar, currentSlug)
|
|
22
|
+
if (topicFromSlug) return topicFromSlug
|
|
23
|
+
|
|
24
|
+
// Otherwise, find the current topic by looking for the current page in the sidebar.
|
|
25
|
+
const currentSidebarTopic = getCurrentSidebarTopic(sidebar)
|
|
26
|
+
if (!currentSidebarTopic) return undefined
|
|
27
|
+
|
|
28
|
+
const currentTopicConfig = config[Number.parseInt(currentSidebarTopic.label, 10)]
|
|
29
|
+
if (!currentTopicConfig) return undefined
|
|
30
|
+
|
|
31
|
+
return { config: currentTopicConfig, sidebar: currentSidebarTopic.entries }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function isTopicFirstPage(sidebar: SidebarEntry[], currentSlug: string): boolean {
|
|
35
|
+
const currentSidebarTopic = getCurrentSidebarTopic(sidebar)
|
|
36
|
+
if (!currentSidebarTopic) return false
|
|
37
|
+
|
|
38
|
+
const firstPage = getSidebarFirstPage(currentSidebarTopic.entries)
|
|
39
|
+
if (!firstPage) return false
|
|
40
|
+
|
|
41
|
+
return arePathnamesEqual(stripLeadingAndTrailingSlashes(firstPage.href), currentSlug)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isTopicLastPage(sidebar: SidebarEntry[], currentSlug: string): boolean {
|
|
45
|
+
const currentSidebarTopic = getCurrentSidebarTopic(sidebar)
|
|
46
|
+
if (!currentSidebarTopic) return false
|
|
47
|
+
|
|
48
|
+
const lastPage = getSidebarLastPage(currentSidebarTopic.entries)
|
|
49
|
+
if (!lastPage) return false
|
|
50
|
+
|
|
51
|
+
return arePathnamesEqual(stripLeadingAndTrailingSlashes(lastPage.href), currentSlug)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getSidebarFirstPage(sidebar: SidebarEntry[]) {
|
|
55
|
+
const entry = sidebar[0]
|
|
56
|
+
if (!entry) return undefined
|
|
57
|
+
if (entry.type === "link") return entry
|
|
58
|
+
|
|
59
|
+
return getSidebarFirstPage(entry.entries)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function getSidebarLastPage(sidebar: SidebarEntry[]) {
|
|
63
|
+
const entry = sidebar.at(-1)
|
|
64
|
+
if (!entry) return undefined
|
|
65
|
+
if (entry.type === "link") return entry
|
|
66
|
+
|
|
67
|
+
return getSidebarLastPage(entry.entries)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getTopicFromSlug(
|
|
71
|
+
config: StarlightSidebarTopicsSharedConfig,
|
|
72
|
+
sidebar: SidebarEntry[],
|
|
73
|
+
slug: string
|
|
74
|
+
): Topic | undefined {
|
|
75
|
+
let topicConfig: Topic["config"] | undefined
|
|
76
|
+
let topicSidebar: Topic["sidebar"] | undefined
|
|
77
|
+
|
|
78
|
+
// Start by checking if the current page is a topic homepage.
|
|
79
|
+
let groupTopicIndex = -1
|
|
80
|
+
const slugLocale = getLocaleFromSlug(slug)
|
|
81
|
+
|
|
82
|
+
for (const topic of config) {
|
|
83
|
+
if (topic.type === "group") groupTopicIndex++
|
|
84
|
+
|
|
85
|
+
if (
|
|
86
|
+
!absoluteLinkRegex.test(topic.link) &&
|
|
87
|
+
arePathnamesEqual(
|
|
88
|
+
getLocalizedSlug(stripLeadingAndTrailingSlashes(topic.link), slugLocale),
|
|
89
|
+
slug
|
|
90
|
+
) &&
|
|
91
|
+
groupTopicIndex !== -1
|
|
92
|
+
) {
|
|
93
|
+
const sidebarTopic = sidebar[groupTopicIndex]
|
|
94
|
+
|
|
95
|
+
if (sidebarTopic?.type === "group") {
|
|
96
|
+
topicConfig = topic
|
|
97
|
+
topicSidebar = sidebarTopic.entries
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
break
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!topicConfig || !topicSidebar) return undefined
|
|
105
|
+
|
|
106
|
+
return { config: topicConfig, sidebar: topicSidebar }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function getTopicById(
|
|
110
|
+
config: StarlightSidebarTopicsSharedConfig,
|
|
111
|
+
sidebar: SidebarEntry[],
|
|
112
|
+
id: string
|
|
113
|
+
): Topic | undefined {
|
|
114
|
+
let topicConfig: Topic["config"] | undefined
|
|
115
|
+
let topicSidebar: Topic["sidebar"] | undefined
|
|
116
|
+
|
|
117
|
+
let groupTopicIndex = -1
|
|
118
|
+
|
|
119
|
+
for (const topic of config) {
|
|
120
|
+
if (topic.type === "group") groupTopicIndex++
|
|
121
|
+
|
|
122
|
+
if (topic.type === "group" && topic.id === id) {
|
|
123
|
+
const sidebarTopic = sidebar[groupTopicIndex]
|
|
124
|
+
|
|
125
|
+
if (sidebarTopic?.type === "group") {
|
|
126
|
+
topicConfig = topic
|
|
127
|
+
topicSidebar = sidebarTopic.entries
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
break
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!topicConfig || !topicSidebar) return undefined
|
|
135
|
+
|
|
136
|
+
return { config: topicConfig, sidebar: topicSidebar }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function getCurrentSidebarTopic(sidebar: SidebarEntry[]): SidebarTopic | undefined {
|
|
140
|
+
let currentSidebarTopic: SidebarTopic | undefined
|
|
141
|
+
|
|
142
|
+
for (const topic of sidebar) {
|
|
143
|
+
if (topic.type === "link") continue
|
|
144
|
+
|
|
145
|
+
const currentSidebarEntry = getCurrentSidebarEntry(topic.entries)
|
|
146
|
+
|
|
147
|
+
if (currentSidebarEntry) {
|
|
148
|
+
currentSidebarTopic = topic
|
|
149
|
+
break
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return currentSidebarTopic
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function getCurrentSidebarEntry(sidebar: SidebarEntry[]): SidebarEntry | undefined {
|
|
157
|
+
return sidebar.find((entry) => {
|
|
158
|
+
if (entry.type === "link") {
|
|
159
|
+
return entry.isCurrent
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return getCurrentSidebarEntry(entry.entries)
|
|
163
|
+
})
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function getTopicIdFromEntry(entry: StarlightEntry): string | undefined {
|
|
167
|
+
if (isStarlightEntryWithTopic(entry)) {
|
|
168
|
+
return entry.data.topic
|
|
169
|
+
}
|
|
170
|
+
return undefined
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
type SidebarEntry = StarlightRouteData["sidebar"][number]
|
|
174
|
+
|
|
175
|
+
interface SidebarTopic {
|
|
176
|
+
label: string
|
|
177
|
+
entries: SidebarEntry[]
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface Topic {
|
|
181
|
+
config: StarlightSidebarTopicsSharedConfig[number]
|
|
182
|
+
sidebar: SidebarEntry[]
|
|
183
|
+
}
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import type { ViteUserConfig } from "astro"
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
StarlightSidebarTopicsConfig,
|
|
5
|
-
StarlightSidebarTopicsOptions,
|
|
6
|
-
StarlightSidebarTopicsSharedConfig
|
|
7
|
-
} from "./config"
|
|
8
|
-
|
|
9
|
-
export function vitePluginStarlightSidebarTopics(
|
|
10
|
-
config: StarlightSidebarTopicsConfig,
|
|
11
|
-
options: StarlightSidebarTopicsOptions
|
|
12
|
-
): VitePlugin {
|
|
13
|
-
const sharedConfig: StarlightSidebarTopicsSharedConfig = config.map((topic) => {
|
|
14
|
-
if (!("items" in topic)) return { ...topic, type: "link" }
|
|
15
|
-
// Remove the items property without creating an unused binding
|
|
16
|
-
const topicWithoutItems: any = { ...topic }
|
|
17
|
-
delete topicWithoutItems.items
|
|
18
|
-
return { ...topicWithoutItems, type: "group" }
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
const modules: Record<string, string> = {
|
|
22
|
-
"virtual:starlight-sidebar-topics/config": `export default ${JSON.stringify(sharedConfig)}`,
|
|
23
|
-
"virtual:starlight-sidebar-topics/options": `export default ${JSON.stringify(options)}`
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const moduleResolutionMap = Object.fromEntries(
|
|
27
|
-
Object.keys(modules).map((key) => [resolveVirtualModuleId(key), key])
|
|
28
|
-
) as Record<string, string>
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
name: "vite-plugin-starlight-sidebar-topics",
|
|
32
|
-
load(id) {
|
|
33
|
-
const moduleId = moduleResolutionMap[id]
|
|
34
|
-
return moduleId ? modules[moduleId] : undefined
|
|
35
|
-
},
|
|
36
|
-
resolveId(id) {
|
|
37
|
-
return id in modules ? resolveVirtualModuleId(id) : undefined
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function resolveVirtualModuleId<TModuleId extends string>(id: TModuleId): `\0${TModuleId}` {
|
|
43
|
-
return `\0${id}`
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
type VitePlugin = NonNullable<ViteUserConfig["plugins"]>[number]
|
|
1
|
+
import type { ViteUserConfig } from "astro"
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
StarlightSidebarTopicsConfig,
|
|
5
|
+
StarlightSidebarTopicsOptions,
|
|
6
|
+
StarlightSidebarTopicsSharedConfig
|
|
7
|
+
} from "./config"
|
|
8
|
+
|
|
9
|
+
export function vitePluginStarlightSidebarTopics(
|
|
10
|
+
config: StarlightSidebarTopicsConfig,
|
|
11
|
+
options: StarlightSidebarTopicsOptions
|
|
12
|
+
): VitePlugin {
|
|
13
|
+
const sharedConfig: StarlightSidebarTopicsSharedConfig = config.map((topic) => {
|
|
14
|
+
if (!("items" in topic)) return { ...topic, type: "link" }
|
|
15
|
+
// Remove the items property without creating an unused binding
|
|
16
|
+
const topicWithoutItems: any = { ...topic }
|
|
17
|
+
delete topicWithoutItems.items
|
|
18
|
+
return { ...topicWithoutItems, type: "group" }
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const modules: Record<string, string> = {
|
|
22
|
+
"virtual:starlight-sidebar-topics/config": `export default ${JSON.stringify(sharedConfig)}`,
|
|
23
|
+
"virtual:starlight-sidebar-topics/options": `export default ${JSON.stringify(options)}`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const moduleResolutionMap = Object.fromEntries(
|
|
27
|
+
Object.keys(modules).map((key) => [resolveVirtualModuleId(key), key])
|
|
28
|
+
) as Record<string, string>
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
name: "vite-plugin-starlight-sidebar-topics",
|
|
32
|
+
load(id) {
|
|
33
|
+
const moduleId = moduleResolutionMap[id]
|
|
34
|
+
return moduleId ? modules[moduleId] : undefined
|
|
35
|
+
},
|
|
36
|
+
resolveId(id) {
|
|
37
|
+
return id in modules ? resolveVirtualModuleId(id) : undefined
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function resolveVirtualModuleId<TModuleId extends string>(id: TModuleId): `\0${TModuleId}` {
|
|
43
|
+
return `\0${id}`
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type VitePlugin = NonNullable<ViteUserConfig["plugins"]>[number]
|