@rimelight/config 0.0.7 → 0.0.8

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/astro/index.js CHANGED
@@ -1,329 +1,333 @@
1
- import fs from "node:fs"
2
- import path from "node:path"
3
- import cloudflare from "@astrojs/cloudflare"
4
- import { cacheCloudflare } from "@astrojs/cloudflare/cache"
5
- import { fontProviders } from "astro/config"
6
-
7
- export function cacheRulesPreset(options = {}) {
8
- const { apiSwrSeconds = 600, pageMaxAgeSeconds = 300, customRules = {} } = options
9
- return {
10
- routeRules: {
11
- "/api/[...path]": {
12
- swr: apiSwrSeconds
13
- },
14
- "/[...path]": {
15
- maxAge: pageMaxAgeSeconds
16
- },
17
- ...customRules
18
- }
19
- }
20
- }
21
-
22
- export function fontsPreset(options = {}) {
23
- const defaultFonts = [
24
- {
25
- name: "Noto Sans",
26
- cssVariable: "--font-sans",
27
- fallbacks: ["sans-serif"],
28
- subsets: ["latin", "latin-ext"],
29
- weights: [400, 500, 600, 700],
30
- styles: ["normal"]
31
- },
32
- {
33
- name: "Noto Serif",
34
- cssVariable: "--font-serif",
35
- fallbacks: ["serif"],
36
- subsets: ["latin", "latin-ext"],
37
- weights: [400, 700],
38
- styles: ["normal"]
39
- },
40
- {
41
- name: "JetBrains Mono",
42
- cssVariable: "--font-mono",
43
- fallbacks: ["monospace"],
44
- subsets: ["latin", "latin-ext"],
45
- weights: [400, 500, 700],
46
- styles: ["normal"]
47
- }
48
- ]
49
-
50
- const provider = (options.fontProviders || fontProviders)?.fontsource
51
- ? (options.fontProviders || fontProviders).fontsource()
52
- : undefined
53
-
54
- return {
55
- fonts: (options.fonts || defaultFonts).map((font) => ({
56
- ...(provider ? { provider } : {}),
57
- ...font
58
- }))
59
- }
60
- }
61
-
62
- export function imagePreset(options = {}) {
63
- const { domains = [], layout = "constrained", responsiveStyles = true } = options
64
- return {
65
- image: {
66
- domains,
67
- layout,
68
- responsiveStyles
69
- }
70
- }
71
- }
72
-
73
- export function cloudflarePreset(options = {}) {
74
- const { adapter = cloudflare(), cacheProvider = cacheCloudflare(), session = false } = options
75
- return {
76
- output: "server",
77
- session,
78
- adapter,
79
- cache: { provider: cacheProvider }
80
- }
81
- }
82
-
83
- function discoverTranslations(dir = "./src/translations") {
84
- const translations = {}
85
- try {
86
- const resolvedDir = path.resolve(process.cwd(), dir)
87
- if (fs.existsSync(resolvedDir)) {
88
- const files = fs.readdirSync(resolvedDir)
89
- for (const file of files) {
90
- if (file.endsWith(".json")) {
91
- const locale = path.basename(file, ".json")
92
- const content = JSON.parse(fs.readFileSync(path.join(resolvedDir, file), "utf8"))
93
- translations[locale] = content
94
- }
95
- }
96
- }
97
- } catch {}
98
- return translations
99
- }
100
-
101
- function discoverLogos(dir = "./src/assets/logos") {
102
- try {
103
- const candidateDirs = [dir, "./src/assets/logo"]
104
- let resolvedDir = null
105
- for (const d of candidateDirs) {
106
- const p = path.resolve(process.cwd(), d)
107
- if (fs.existsSync(p) && fs.statSync(p).isDirectory()) {
108
- resolvedDir = p
109
- break
110
- }
111
- }
112
- if (!resolvedDir) return undefined
113
-
114
- const files = fs.readdirSync(resolvedDir)
115
- const logos = {}
116
-
117
- const variants = ["logomark", "logotype", "logo"]
118
- const modes = ["color", "white", "black", "light", "dark"]
119
- const extensions = [".svg", ".png", ".webp", ".jpg", ".jpeg", ".gif"]
120
-
121
- for (const variant of variants) {
122
- for (const mode of modes) {
123
- for (const ext of extensions) {
124
- const fileName = `${variant}_${mode}${ext}`
125
- if (files.includes(fileName)) {
126
- if (!logos[variant]) logos[variant] = {}
127
- const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
128
- logos[variant][mode] = relPath
129
- }
130
- }
131
- }
132
- for (const ext of extensions) {
133
- const fileName = `${variant}${ext}`
134
- if (files.includes(fileName) && !logos[variant]) {
135
- const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
136
- logos[variant] = relPath
137
- }
138
- }
139
- }
140
-
141
- return Object.keys(logos).length > 0 ? logos : undefined
142
- } catch {
143
- return undefined
144
- }
145
- }
146
-
147
- function defaultShortcuts() {
148
- return {
149
- categories: {
150
- system: { label: "System" },
151
- navigation: { label: "Navigation" }
152
- }
153
- }
154
- }
155
-
156
- function rimelightIntegration(options, imageDomains, domain) {
157
- return {
158
- name: "rimelight-auto-plugins",
159
- hooks: {
160
- "astro:config:setup": async ({ updateConfig }) => {
161
- const integrations = []
162
- const plugins = []
163
-
164
- if (options.solid) {
165
- const solidMod = await import("@astrojs/solid-js")
166
- const solidFn = solidMod.default || solidMod
167
- const solidOpts =
168
- typeof options.solid === "object"
169
- ? options.solid
170
- : { include: ["**/solid/**", "**/*.tsx"] }
171
- integrations.push(solidFn(solidOpts))
172
- }
173
-
174
- if (options.seo) {
175
- const seoMod = await import("@rimelight/seo")
176
- const { rimelightSeo } = seoMod
177
- const seoOpts = typeof options.seo === "object" ? options.seo : {}
178
- integrations.push(rimelightSeo(seoOpts))
179
- }
180
-
181
- if (options.cms) {
182
- const cmsMod = await import("@rimelight/cms/integration")
183
- const { rimelightCms } = cmsMod
184
- const cmsOpts = typeof options.cms === "object" ? options.cms : {}
185
- let storage = cmsOpts.storage
186
- if (!storage) {
187
- const storageMod = await import("@rimelight/cms/storage")
188
- const { r2 } = storageMod
189
- storage = r2({ binding: cmsOpts.binding || "BLOB" })
190
- }
191
- integrations.push(
192
- rimelightCms({
193
- storage,
194
- auth: cmsOpts.auth || "./src/auth/auth.ts",
195
- ...cmsOpts
196
- })
197
- )
198
- }
199
-
200
- if (options.security) {
201
- const secMod = await import("@rimelight/security")
202
- const { security: securityFn } = secMod
203
- const secOpts = typeof options.security === "object" ? options.security : {}
204
- const defaultImgSrc = imageDomains.map((d) =>
205
- d.startsWith("http://") || d.startsWith("https://") ? d : `https://${d}`
206
- )
207
- const imgSrc = secOpts.imgSrc
208
- ? Array.from(new Set([...defaultImgSrc, ...secOpts.imgSrc]))
209
- : defaultImgSrc
210
-
211
- plugins.push(
212
- securityFn({
213
- domain: secOpts.domain || domain,
214
- imgSrc,
215
- ...secOpts
216
- })
217
- )
218
- }
219
-
220
- if (options.i18n) {
221
- const i18nMod = await import("@rimelight/i18n")
222
- const { i18n: i18nFn } = i18nMod
223
- const i18nOpts = typeof options.i18n === "object" ? options.i18n : {}
224
- const translations = i18nOpts.translations || discoverTranslations()
225
- const locales = i18nOpts.locales || Object.keys(translations)
226
- const defaultLocale = i18nOpts.defaultLocale || (locales.length > 0 ? locales[0] : "en")
227
- const kvBinding =
228
- i18nOpts.kvBinding ||
229
- (domain ? `${domain.replaceAll(".", "-")}_translations` : undefined)
230
-
231
- plugins.push(
232
- i18nFn({
233
- locales,
234
- defaultLocale,
235
- prefixDefaultLocale: i18nOpts.prefixDefaultLocale ?? true,
236
- translations,
237
- ...(kvBinding ? { kvBinding } : {}),
238
- ...i18nOpts
239
- })
240
- )
241
- }
242
-
243
- if (options.ui) {
244
- const uiMod = await import("@rimelight/ui")
245
- const { ui: uiFn } = uiMod
246
- const uiOpts = typeof options.ui === "object" ? options.ui : {}
247
- const discoveredLogos = discoverLogos()
248
-
249
- const mergedLogos = uiOpts.logos
250
- ? { ...discoveredLogos, ...uiOpts.logos }
251
- : discoveredLogos
252
-
253
- const mergedShortcuts =
254
- uiOpts.shortcuts === false
255
- ? undefined
256
- : {
257
- ...defaultShortcuts(),
258
- ...(typeof uiOpts.shortcuts === "object" ? uiOpts.shortcuts : {})
259
- }
260
-
261
- plugins.push(
262
- uiFn({
263
- ...(mergedLogos ? { logos: mergedLogos } : {}),
264
- ...(mergedShortcuts ? { shortcuts: mergedShortcuts } : {}),
265
- ...uiOpts
266
- })
267
- )
268
- }
269
-
270
- updateConfig({
271
- integrations,
272
- vite: {
273
- plugins
274
- }
275
- })
276
- }
277
- }
278
- }
279
- }
280
-
281
- export function rimelightAstroConfig(options = {}) {
282
- const {
283
- domain,
284
- site = domain ? `https://${domain}` : undefined,
285
- imageDomains = domain ? [domain, `cdn.${domain}`, "cdn.rimelight.com"] : [],
286
- apiSwrSeconds = 600,
287
- pageMaxAgeSeconds = 300,
288
- adapter,
289
- cacheProvider,
290
- fonts,
291
- solid,
292
- security,
293
- i18n,
294
- cms,
295
- ui,
296
- seo,
297
- integrations = [],
298
- vite = {},
299
- ...rest
300
- } = options
301
-
302
- const hasFlags = Boolean(solid || security || i18n || cms || ui || seo)
303
-
304
- return {
305
- ...(site ? { site } : {}),
306
- prefetch: {
307
- prefetchAll: true
308
- },
309
- ...cloudflarePreset({
310
- ...(adapter !== undefined ? { adapter } : {}),
311
- ...(cacheProvider !== undefined ? { cacheProvider } : {})
312
- }),
313
- ...cacheRulesPreset({
314
- ...(apiSwrSeconds !== undefined ? { apiSwrSeconds } : {}),
315
- ...(pageMaxAgeSeconds !== undefined ? { pageMaxAgeSeconds } : {})
316
- }),
317
- ...fontsPreset(fonts !== undefined ? { fonts } : {}),
318
- ...imagePreset({ domains: imageDomains }),
319
- markdown: {
320
- syntaxHighlight: "prism"
321
- },
322
- integrations: [
323
- ...(hasFlags ? [rimelightIntegration(options, imageDomains, domain)] : []),
324
- ...integrations
325
- ],
326
- vite,
327
- ...rest
328
- }
329
- }
1
+ import fs from "node:fs"
2
+ import path from "node:path"
3
+ import cloudflare from "@astrojs/cloudflare"
4
+ import { cacheCloudflare } from "@astrojs/cloudflare/cache"
5
+ import { fontProviders } from "astro/config"
6
+
7
+ export function cacheRulesPreset(options = {}) {
8
+ const { apiSwrSeconds = 600, pageMaxAgeSeconds = 300, customRules = {} } = options
9
+ return {
10
+ routeRules: {
11
+ "/api/[...path]": {
12
+ swr: apiSwrSeconds
13
+ },
14
+ "/[...path]": {
15
+ maxAge: pageMaxAgeSeconds
16
+ },
17
+ ...customRules
18
+ }
19
+ }
20
+ }
21
+
22
+ export function fontsPreset(options = {}) {
23
+ const defaultFonts = [
24
+ {
25
+ name: "Noto Sans",
26
+ cssVariable: "--font-sans",
27
+ fallbacks: ["sans-serif"],
28
+ subsets: ["latin", "latin-ext"],
29
+ weights: [400, 500, 600, 700],
30
+ styles: ["normal"]
31
+ },
32
+ {
33
+ name: "Noto Serif",
34
+ cssVariable: "--font-serif",
35
+ fallbacks: ["serif"],
36
+ subsets: ["latin", "latin-ext"],
37
+ weights: [400, 700],
38
+ styles: ["normal"]
39
+ },
40
+ {
41
+ name: "JetBrains Mono",
42
+ cssVariable: "--font-mono",
43
+ fallbacks: ["monospace"],
44
+ subsets: ["latin", "latin-ext"],
45
+ weights: [400, 500, 700],
46
+ styles: ["normal"]
47
+ }
48
+ ]
49
+
50
+ const provider = (options.fontProviders || fontProviders)?.fontsource
51
+ ? (options.fontProviders || fontProviders).fontsource()
52
+ : undefined
53
+
54
+ return {
55
+ fonts: (options.fonts || defaultFonts).map((font) => ({
56
+ ...(provider ? { provider } : {}),
57
+ ...font
58
+ }))
59
+ }
60
+ }
61
+
62
+ export function imagePreset(options = {}) {
63
+ const { domains = [], layout = "constrained", responsiveStyles = true } = options
64
+ return {
65
+ image: {
66
+ domains,
67
+ layout,
68
+ responsiveStyles
69
+ }
70
+ }
71
+ }
72
+
73
+ export function cloudflarePreset(options = {}) {
74
+ const { adapter = cloudflare(), cacheProvider = cacheCloudflare(), session = false } = options
75
+ return {
76
+ output: "server",
77
+ session,
78
+ adapter,
79
+ cache: { provider: cacheProvider }
80
+ }
81
+ }
82
+
83
+ function discoverTranslations(dir = "./src/translations") {
84
+ const translations = {}
85
+ try {
86
+ const resolvedDir = path.resolve(process.cwd(), dir)
87
+ if (fs.existsSync(resolvedDir)) {
88
+ const files = fs.readdirSync(resolvedDir)
89
+ for (const file of files) {
90
+ if (file.endsWith(".json")) {
91
+ const locale = path.basename(file, ".json")
92
+ const content = JSON.parse(fs.readFileSync(path.join(resolvedDir, file), "utf8"))
93
+ translations[locale] = content
94
+ }
95
+ }
96
+ }
97
+ } catch {}
98
+ return translations
99
+ }
100
+
101
+ function discoverLogos(dir = "./src/assets/logos") {
102
+ try {
103
+ const candidateDirs = [dir, "./src/assets/logo"]
104
+ let resolvedDir = null
105
+ for (const d of candidateDirs) {
106
+ const p = path.resolve(process.cwd(), d)
107
+ if (fs.existsSync(p) && fs.statSync(p).isDirectory()) {
108
+ resolvedDir = p
109
+ break
110
+ }
111
+ }
112
+ if (!resolvedDir) return undefined
113
+
114
+ const files = fs.readdirSync(resolvedDir)
115
+ const logos = {}
116
+
117
+ const variants = ["logomark", "logotype", "logo"]
118
+ const modes = ["color", "white", "black", "light", "dark"]
119
+ const extensions = [".svg", ".png", ".webp", ".jpg", ".jpeg", ".gif"]
120
+
121
+ for (const variant of variants) {
122
+ for (const mode of modes) {
123
+ for (const ext of extensions) {
124
+ const fileName = `${variant}_${mode}${ext}`
125
+ if (files.includes(fileName)) {
126
+ if (!logos[variant]) logos[variant] = {}
127
+ const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
128
+ logos[variant][mode] = relPath
129
+ }
130
+ }
131
+ }
132
+ for (const ext of extensions) {
133
+ const fileName = `${variant}${ext}`
134
+ if (files.includes(fileName) && !logos[variant]) {
135
+ const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
136
+ logos[variant] = relPath
137
+ }
138
+ }
139
+ }
140
+
141
+ return Object.keys(logos).length > 0 ? logos : undefined
142
+ } catch {
143
+ return undefined
144
+ }
145
+ }
146
+
147
+ function defaultShortcuts() {
148
+ return {
149
+ categories: {
150
+ system: { label: "System" },
151
+ navigation: { label: "Navigation" }
152
+ }
153
+ }
154
+ }
155
+
156
+ function rimelightIntegration(options, imageDomains, domain) {
157
+ return {
158
+ name: "rimelight-auto-plugins",
159
+ hooks: {
160
+ "astro:config:setup": async ({ updateConfig }) => {
161
+ const integrations = []
162
+ const plugins = []
163
+
164
+ if (options.solid) {
165
+ const solidMod = await import("@astrojs/solid-js")
166
+ const solidFn = solidMod.default || solidMod
167
+ const solidOpts =
168
+ typeof options.solid === "object"
169
+ ? options.solid
170
+ : { include: ["**/solid/**", "**/*.tsx"] }
171
+ integrations.push(solidFn(solidOpts))
172
+ }
173
+
174
+ if (options.seo) {
175
+ const seoMod = await import("@rimelight/seo")
176
+ const seoFn =
177
+ seoMod.rimelightSeo ||
178
+ seoMod.default?.rimelightSeo ||
179
+ seoMod.default ||
180
+ seoMod
181
+ const seoOpts = typeof options.seo === "object" ? options.seo : {}
182
+ integrations.push(seoFn(seoOpts))
183
+ }
184
+
185
+ if (options.cms) {
186
+ const cmsMod = await import("@rimelight/cms/integration")
187
+ const { rimelightCms } = cmsMod
188
+ const cmsOpts = typeof options.cms === "object" ? options.cms : {}
189
+ let storage = cmsOpts.storage
190
+ if (!storage) {
191
+ const storageMod = await import("@rimelight/cms/storage")
192
+ const { r2 } = storageMod
193
+ storage = r2({ binding: cmsOpts.binding || "BLOB" })
194
+ }
195
+ integrations.push(
196
+ rimelightCms({
197
+ storage,
198
+ auth: cmsOpts.auth || "./src/auth/auth.ts",
199
+ ...cmsOpts
200
+ })
201
+ )
202
+ }
203
+
204
+ if (options.security) {
205
+ const secMod = await import("@rimelight/security")
206
+ const { security: securityFn } = secMod
207
+ const secOpts = typeof options.security === "object" ? options.security : {}
208
+ const defaultImgSrc = imageDomains.map((d) =>
209
+ d.startsWith("http://") || d.startsWith("https://") ? d : `https://${d}`
210
+ )
211
+ const imgSrc = secOpts.imgSrc
212
+ ? Array.from(new Set([...defaultImgSrc, ...secOpts.imgSrc]))
213
+ : defaultImgSrc
214
+
215
+ plugins.push(
216
+ securityFn({
217
+ domain: secOpts.domain || domain,
218
+ imgSrc,
219
+ ...secOpts
220
+ })
221
+ )
222
+ }
223
+
224
+ if (options.i18n) {
225
+ const i18nMod = await import("@rimelight/i18n")
226
+ const { i18n: i18nFn } = i18nMod
227
+ const i18nOpts = typeof options.i18n === "object" ? options.i18n : {}
228
+ const translations = i18nOpts.translations || discoverTranslations()
229
+ const locales = i18nOpts.locales || Object.keys(translations)
230
+ const defaultLocale = i18nOpts.defaultLocale || (locales.length > 0 ? locales[0] : "en")
231
+ const kvBinding =
232
+ i18nOpts.kvBinding ||
233
+ (domain ? `${domain.replaceAll(".", "-")}_translations` : undefined)
234
+
235
+ plugins.push(
236
+ i18nFn({
237
+ locales,
238
+ defaultLocale,
239
+ prefixDefaultLocale: i18nOpts.prefixDefaultLocale ?? true,
240
+ translations,
241
+ ...(kvBinding ? { kvBinding } : {}),
242
+ ...i18nOpts
243
+ })
244
+ )
245
+ }
246
+
247
+ if (options.ui) {
248
+ const uiMod = await import("@rimelight/ui")
249
+ const { ui: uiFn } = uiMod
250
+ const uiOpts = typeof options.ui === "object" ? options.ui : {}
251
+ const discoveredLogos = discoverLogos()
252
+
253
+ const mergedLogos = uiOpts.logos
254
+ ? { ...discoveredLogos, ...uiOpts.logos }
255
+ : discoveredLogos
256
+
257
+ const mergedShortcuts =
258
+ uiOpts.shortcuts === false
259
+ ? undefined
260
+ : {
261
+ ...defaultShortcuts(),
262
+ ...(typeof uiOpts.shortcuts === "object" ? uiOpts.shortcuts : {})
263
+ }
264
+
265
+ plugins.push(
266
+ uiFn({
267
+ ...(mergedLogos ? { logos: mergedLogos } : {}),
268
+ ...(mergedShortcuts ? { shortcuts: mergedShortcuts } : {}),
269
+ ...uiOpts
270
+ })
271
+ )
272
+ }
273
+
274
+ updateConfig({
275
+ integrations,
276
+ vite: {
277
+ plugins
278
+ }
279
+ })
280
+ }
281
+ }
282
+ }
283
+ }
284
+
285
+ export function rimelightAstroConfig(options = {}) {
286
+ const {
287
+ domain,
288
+ site = domain ? `https://${domain}` : undefined,
289
+ imageDomains = domain ? [domain, `cdn.${domain}`, "cdn.rimelight.com"] : [],
290
+ apiSwrSeconds = 600,
291
+ pageMaxAgeSeconds = 300,
292
+ adapter,
293
+ cacheProvider,
294
+ fonts,
295
+ solid,
296
+ security,
297
+ i18n,
298
+ cms,
299
+ ui,
300
+ seo,
301
+ integrations = [],
302
+ vite = {},
303
+ ...rest
304
+ } = options
305
+
306
+ const hasFlags = Boolean(solid || security || i18n || cms || ui || seo)
307
+
308
+ return {
309
+ ...(site ? { site } : {}),
310
+ prefetch: {
311
+ prefetchAll: true
312
+ },
313
+ ...cloudflarePreset({
314
+ ...(adapter !== undefined ? { adapter } : {}),
315
+ ...(cacheProvider !== undefined ? { cacheProvider } : {})
316
+ }),
317
+ ...cacheRulesPreset({
318
+ ...(apiSwrSeconds !== undefined ? { apiSwrSeconds } : {}),
319
+ ...(pageMaxAgeSeconds !== undefined ? { pageMaxAgeSeconds } : {})
320
+ }),
321
+ ...fontsPreset(fonts !== undefined ? { fonts } : {}),
322
+ ...imagePreset({ domains: imageDomains }),
323
+ markdown: {
324
+ syntaxHighlight: "prism"
325
+ },
326
+ integrations: [
327
+ ...(hasFlags ? [rimelightIntegration(options, imageDomains, domain)] : []),
328
+ ...integrations
329
+ ],
330
+ vite,
331
+ ...rest
332
+ }
333
+ }