@rimelight/ui 0.0.16 → 0.0.18

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.
@@ -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]