lightnet 4.0.7 → 4.1.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +1 -1
  3. package/exports/content.ts +5 -7
  4. package/package.json +13 -13
  5. package/src/api/versions.ts +1 -1
  6. package/src/astro-integration/config.ts +15 -25
  7. package/src/components/CategoriesSection.astro +2 -2
  8. package/src/components/MediaGallerySection.astro +4 -9
  9. package/src/components/MediaList.astro +13 -13
  10. package/src/content/content-schema.ts +5 -292
  11. package/src/content/get-categories.ts +26 -29
  12. package/src/content/get-languages.ts +13 -26
  13. package/src/content/get-media-collections.ts +1 -1
  14. package/src/content/get-media-items.ts +1 -1
  15. package/src/content/get-media-types.ts +21 -14
  16. package/src/content/query-media-items.ts +2 -1
  17. package/src/content/schema/category.ts +40 -0
  18. package/src/content/schema/media-collection.ts +31 -0
  19. package/src/content/schema/media-item.ts +137 -0
  20. package/src/content/schema/media-type.ts +90 -0
  21. package/src/i18n/locals.d.ts +22 -0
  22. package/src/i18n/locals.ts +3 -1
  23. package/src/i18n/record-translation.ts +74 -0
  24. package/src/i18n/resolve-language.ts +12 -5
  25. package/src/i18n/translate-map.ts +129 -19
  26. package/src/i18n/translate.ts +38 -0
  27. package/src/i18n/translation-map-schema.ts +17 -0
  28. package/src/i18n/translations/TRANSLATION-STATUS.md +13 -41
  29. package/src/i18n/translations/ar.yml +1 -0
  30. package/src/i18n/translations/bn.yml +1 -0
  31. package/src/i18n/translations/de.yml +1 -0
  32. package/src/i18n/translations/es.yml +1 -0
  33. package/src/i18n/translations/fi.yml +1 -0
  34. package/src/i18n/translations/fr.yml +1 -0
  35. package/src/i18n/translations/hi.yml +1 -0
  36. package/src/i18n/translations/kk.yml +3 -0
  37. package/src/i18n/translations/pt.yml +1 -0
  38. package/src/i18n/translations/ru.yml +1 -0
  39. package/src/i18n/translations/uk.yml +1 -0
  40. package/src/i18n/translations/ur.yml +1 -0
  41. package/src/i18n/translations/zh.yml +1 -0
  42. package/src/i18n/translations.ts +5 -2
  43. package/src/layouts/Page.astro +3 -4
  44. package/src/layouts/components/Footer.astro +72 -10
  45. package/src/layouts/components/LanguagePicker.astro +2 -2
  46. package/src/layouts/components/PageNavigation.astro +17 -21
  47. package/src/layouts/components/PageTitle.astro +4 -13
  48. package/src/pages/details-page/DefaultDetailsPage.astro +2 -15
  49. package/src/pages/details-page/components/AudioPanel.astro +5 -4
  50. package/src/pages/details-page/components/ContentSection.astro +5 -4
  51. package/src/pages/details-page/components/MediaCollection.astro +2 -6
  52. package/src/pages/details-page/components/main-details/OpenButton.astro +20 -18
  53. package/src/pages/details-page/components/more-details/Categories.astro +3 -5
  54. package/src/pages/details-page/components/more-details/Languages.astro +7 -3
  55. package/src/pages/details-page/utils/create-content-metadata.ts +8 -22
  56. package/src/pages/search-page/api/search.ts +1 -1
  57. package/src/pages/search-page/components/SearchFilter.astro +5 -5
  58. package/src/pages/search-page/components/SearchList.astro +22 -19
  59. package/src/astro-integration/validators/validate-inline-translations.ts +0 -51
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # lightnet
2
2
 
3
+ ## 4.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#386](https://github.com/LightNetDev/LightNet/pull/386) [`3297d11`](https://github.com/LightNetDev/LightNet/commit/3297d11b8ae2d5d569291f72048f06ce0a99b556) Thanks [@vilgax-the-villain-with-99bugs](https://github.com/vilgax-the-villain-with-99bugs)! - Added customizable footer text and links.
8
+
9
+ - [#387](https://github.com/LightNetDev/LightNet/pull/387) [`d7969dc`](https://github.com/LightNetDev/LightNet/commit/d7969dcaa65417316b129f50602d3473813f52fe) Thanks [@smn-cds](https://github.com/smn-cds)! - Add `tConfigField` and `tContentField` to LightNet's i18n locals to distinguish
10
+ between inline translation maps from config fields and content fields.
11
+
12
+ These helpers resolve inline translation maps for the current locale while
13
+ preserving the existing `tMap` helper for cases where the field context is
14
+ provided manually.
15
+
16
+ ### Patch Changes
17
+
18
+ - [#387](https://github.com/LightNetDev/LightNet/pull/387) [`d7969dc`](https://github.com/LightNetDev/LightNet/commit/d7969dcaa65417316b129f50602d3473813f52fe) Thanks [@smn-cds](https://github.com/smn-cds)! - Update dependencies
19
+
20
+ ## 4.0.8
21
+
22
+ ### Patch Changes
23
+
24
+ - [#382](https://github.com/LightNetDev/LightNet/pull/382) [`c6c8f31`](https://github.com/LightNetDev/LightNet/commit/c6c8f31adf464a842739f2b99d858aa0ba5d43e9) Thanks [@smn-cds](https://github.com/smn-cds)! - Update internal dependency marked to v18
25
+
26
+ - [#382](https://github.com/LightNetDev/LightNet/pull/382) [`c6c8f31`](https://github.com/LightNetDev/LightNet/commit/c6c8f31adf464a842739f2b99d858aa0ba5d43e9) Thanks [@smn-cds](https://github.com/smn-cds)! - Update dependencies
27
+
3
28
  ## 4.0.7
4
29
 
5
30
  ### Patch Changes
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ![LightNet](https://github.com/LightNetDev/lightnet/blob/main/lightnet-banner.webp)
2
2
 
3
- Many ministries struggle to share media content effectively. LightNet makes it easy to **run your own digital media library**, so more people can find what they need and grow in faith.
3
+ **Running digital media libraries for ministries** can be complex and time consuming. LightNet makes this easier for developers, so ministries can share media more effectively.
4
4
 
5
5
  Built as an integration for the [Astro framework](https://astro.build), LightNet creates fast, static sites that run anywhere.
6
6
 
@@ -1,10 +1,8 @@
1
- export {
2
- createCategorySchema as categorySchema,
3
- LIGHTNET_COLLECTIONS,
4
- mediaCollectionSchema,
5
- createMediaItemSchema as mediaItemSchema,
6
- mediaTypeSchema,
7
- } from "../src/content/content-schema"
1
+ export { LIGHTNET_COLLECTIONS } from "../src/content/content-schema"
2
+ export { createCategorySchema as categorySchema } from "../src/content/schema/category"
3
+ export { mediaCollectionSchema } from "../src/content/schema/media-collection"
4
+ export { createMediaItemSchema as mediaItemSchema } from "../src/content/schema/media-item"
5
+ export { mediaTypeSchema } from "../src/content/schema/media-type"
8
6
 
9
7
  import { type CollectionEntry, getCollection } from "astro:content"
10
8
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "LightNet makes it easy to run your own digital media library.",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
- "version": "4.0.7",
6
+ "version": "4.1.0",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "https://github.com/LightNetDev/lightnet",
@@ -51,29 +51,29 @@
51
51
  "tailwindcss": ">=3.4.0 <4.0.0"
52
52
  },
53
53
  "dependencies": {
54
- "@astrojs/react": "^5.0.3",
55
- "@iconify-json/lucide": "^1.2.102",
54
+ "@astrojs/react": "^5.0.4",
55
+ "@iconify-json/lucide": "^1.2.105",
56
56
  "@iconify-json/mdi": "^1.2.3",
57
57
  "@iconify/tailwind": "^1.2.0",
58
58
  "@tailwindcss/typography": "^0.5.19",
59
- "@tanstack/react-virtual": "^3.13.23",
60
- "autoprefixer": "^10.4.27",
59
+ "@tanstack/react-virtual": "^3.13.24",
60
+ "autoprefixer": "^10.5.0",
61
61
  "embla-carousel": "^8.6.0",
62
62
  "embla-carousel-wheel-gestures": "^8.1.0",
63
63
  "fuse.js": "^7.3.0",
64
- "i18next": "^26.0.4",
65
- "lucide-react": "^1.8.0",
66
- "marked": "^17.0.6",
67
- "postcss": "^8.5.9",
64
+ "i18next": "^26.0.8",
65
+ "lucide-react": "^1.14.0",
66
+ "marked": "^18.0.3",
67
+ "postcss": "^8.5.14",
68
68
  "postcss-load-config": "^6.0.1",
69
- "yaml": "^2.8.3"
69
+ "yaml": "^2.8.4"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@playwright/test": "^1.59.1",
73
73
  "@types/react": "^19.2.14",
74
- "astro": "^6.1.5",
75
- "typescript": "^5.9.3",
76
- "vitest": "^4.1.4",
74
+ "astro": "^6.2.2",
75
+ "typescript": "^6.0.3",
76
+ "vitest": "^4.1.5",
77
77
  "@internal/e2e-test-utils": "^0.0.1"
78
78
  },
79
79
  "engines": {
@@ -1,6 +1,6 @@
1
1
  import type { APIRoute } from "astro"
2
2
 
3
- import pkg from "../../package.json" assert { type: "json" }
3
+ import pkg from "../../package.json"
4
4
 
5
5
  export const GET: APIRoute = () => {
6
6
  return new Response(JSON.stringify({ lightnet: pkg.version }))
@@ -1,25 +1,9 @@
1
1
  import { z } from "astro/zod"
2
2
 
3
3
  import { isBcp47 } from "../i18n/bcp-47"
4
- import { validateInlineTranslations } from "./validators/validate-inline-translations"
4
+ import { translationMapSchema } from "../i18n/translation-map-schema"
5
5
  import { validateLanguages } from "./validators/validate-languages"
6
6
 
7
- /**
8
- * Translations by BCP-47 tags.
9
- * We can only do basic validation here because we cannot access locales
10
- * from the same config.
11
- *
12
- * @example
13
- * {
14
- * de: "Hallo",
15
- * en: "Hello"
16
- * }
17
- */
18
- export const inlineTranslationSchema = z.record(
19
- z.string(),
20
- z.string().nonempty(),
21
- )
22
-
23
7
  /**
24
8
  * Link Schema.
25
9
  */
@@ -35,7 +19,7 @@ const linkSchema = z.object({
35
19
  * Must define a value for the default site locale.
36
20
  * Other configured site locales are optional.
37
21
  */
38
- label: inlineTranslationSchema,
22
+ label: translationMapSchema,
39
23
  /**
40
24
  * If this is set to true the currentLocale will be appended to
41
25
  * the href path. Eg. for href="/about"
@@ -61,7 +45,7 @@ const languageSchema = z
61
45
  /**
62
46
  * Display name for this language.
63
47
  */
64
- label: inlineTranslationSchema,
48
+ label: translationMapSchema,
65
49
  /**
66
50
  * Whether this language should be exposed as a site UI language.
67
51
  */
@@ -116,7 +100,7 @@ export const configSchema = z.object({
116
100
  /**
117
101
  * Title of the web site.
118
102
  */
119
- title: inlineTranslationSchema,
103
+ title: translationMapSchema,
120
104
  /**
121
105
  * Languages supported by this site.
122
106
  */
@@ -129,6 +113,15 @@ export const configSchema = z.object({
129
113
  * Enable displaying a “Powered by LightNet” link in your site’s footer.
130
114
  */
131
115
  credits: z.boolean().default(false),
116
+ /**
117
+ * Optional localized text to display in your site's footer.
118
+ */
119
+ footerText: translationMapSchema.optional(),
120
+ /**
121
+ * Optional links to display in your site's footer.
122
+ */
123
+ footerLinks: z.array(linkSchema).optional(),
124
+
132
125
  /**
133
126
  * Link to manifest file within public/ folder
134
127
  */
@@ -151,7 +144,7 @@ export const configSchema = z.object({
151
144
  * Must define a value for the default site locale.
152
145
  * Other configured site locales are optional.
153
146
  */
154
- alt: inlineTranslationSchema.optional(),
147
+ alt: translationMapSchema.optional(),
155
148
  /**
156
149
  * Size in px to use for the logo on the header bar.
157
150
  * The size will be applied to the shorter side of your logo image.
@@ -217,16 +210,13 @@ export const configSchema = z.object({
217
210
  experimental: z.object({}).optional(),
218
211
  })
219
212
 
220
- export const extendedConfigSchema = configSchema.transform((config, ctx) => {
213
+ export const extendedConfigSchema = configSchema.transform((config) => {
221
214
  const locales = config.languages
222
215
  .filter((language) => language.isSiteLanguage)
223
216
  .map((language) => language.code)
224
217
  const defaultLocale =
225
218
  config.languages.find((language) => language.isDefaultSiteLanguage)?.code ??
226
219
  ""
227
-
228
- validateInlineTranslations(config, locales, defaultLocale, ctx)
229
-
230
220
  return {
231
221
  ...config,
232
222
  locales,
@@ -12,10 +12,10 @@ type Props = Omit<SectionProps, "maxWidth"> & {
12
12
  }
13
13
 
14
14
  const { title, layout = "carousel", ...props } = Astro.props
15
- const { t, tMap, currentLocale } = Astro.locals.i18n
15
+ const { t, tContentField, currentLocale } = Astro.locals.i18n
16
16
  const resolvedTitle = title ?? t("ln.categories")
17
17
 
18
- const categories = await getUsedCategories(currentLocale, tMap)
18
+ const categories = await getUsedCategories(currentLocale, tContentField)
19
19
  type Category = (typeof categories)[number]
20
20
 
21
21
  function getImage({ image, id }: Category) {
@@ -2,7 +2,7 @@
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
4
 
5
- import { getMediaTypes } from "../content/get-media-types"
5
+ import { getTranslatedMediaTypes } from "../content/get-media-types"
6
6
  import { detailsPagePath } from "../utils/paths"
7
7
  import CarouselSection from "./CarouselSection.astro"
8
8
  import CoverImageDecorator from "./CoverImageDecorator"
@@ -31,17 +31,12 @@ const {
31
31
  ...sectionProps
32
32
  } = Astro.props
33
33
 
34
- const { currentLocale, tMap } = Astro.locals.i18n
34
+ const { currentLocale, tContentField } = Astro.locals.i18n
35
35
 
36
36
  const types = Object.fromEntries(
37
- (await getMediaTypes()).map((type) => [
37
+ (await getTranslatedMediaTypes(currentLocale, tContentField)).map((type) => [
38
38
  type.id,
39
- {
40
- ...type.data,
41
- labelText: tMap(type.data.label, {
42
- path: ["media-types", type.id, "label"],
43
- }),
44
- },
39
+ type,
45
40
  ]),
46
41
  )
47
42
 
@@ -3,7 +3,7 @@ import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
4
  import { ChevronRightIcon } from "lucide-react"
5
5
 
6
- import { getMediaTypes } from "../content/get-media-types"
6
+ import { getTranslatedMediaTypes } from "../content/get-media-types"
7
7
  import { detailsPagePath } from "../utils/paths"
8
8
  import CoverImageDecorator from "./CoverImageDecorator"
9
9
  import Icon from "./Icon"
@@ -28,20 +28,20 @@ interface Props {
28
28
  // this is in the return type of getEntry
29
29
  const items = Astro.props.items.filter((item) => !!item)
30
30
 
31
- const { direction, currentLocale, tMap } = Astro.locals.i18n
31
+ const { direction, currentLocale, tContentField } = Astro.locals.i18n
32
32
 
33
33
  const mediaTypes = Object.fromEntries(
34
- (await getMediaTypes()).map((type) => [
35
- type.id,
36
- {
37
- id: type.id,
38
- labelText: tMap(type.data.label, {
39
- path: ["media-types", type.id, "label"],
40
- }),
41
- icon: type.data.icon,
42
- coverImageStyle: type.data.coverImageStyle,
43
- },
44
- ]),
34
+ (await getTranslatedMediaTypes(currentLocale, tContentField)).map(
35
+ ({ id, labelText, icon, coverImageStyle }) => [
36
+ id,
37
+ {
38
+ id,
39
+ labelText,
40
+ icon,
41
+ coverImageStyle,
42
+ },
43
+ ],
44
+ ),
45
45
  )
46
46
  const iconDirectionClass = direction === "rtl" ? "scale-x-[-1]" : ""
47
47
  ---
@@ -1,273 +1,10 @@
1
1
  import { glob } from "astro/loaders"
2
- import { z } from "astro/zod"
3
- import type { SchemaContext } from "astro:content"
4
- import { defineCollection, reference } from "astro:content"
2
+ import { defineCollection } from "astro:content"
5
3
 
6
- import { imageSchema } from "./astro-image"
7
-
8
- /**
9
- * Translations by BCP-47 tag
10
- * Must contain at least one localized value.
11
- *
12
- * @example
13
- * {
14
- * de: "Hallo",
15
- * en: "Hello"
16
- * }
17
- */
18
- export const inlineTranslationSchema = z
19
- .record(z.string(), z.string())
20
- .refine((value) => Object.keys(value).length > 0, {
21
- message: "Inline translations must contain at least one entry",
22
- })
23
-
24
- /**
25
- * Category Schema
26
- */
27
- export const categorySchema = z.object({
28
- /**
29
- * Name of the category.
30
- *
31
- * Label translated for the default locale. Other configured site locales are optional.
32
- */
33
- label: inlineTranslationSchema,
34
-
35
- /* Relative path to the thumbnail image of this category.
36
- *
37
- * The image is expected to be inside the `images` folder next to category definition json.
38
- * It can have one of these file types: png, jpg, tiff, webp, gif, svg, avif.
39
- * We suggest to give it a size of at least 1000px for it's longer side.
40
- *
41
- * @example "./images/devotionals.jpg"
42
- */
43
- image: imageSchema.optional(),
44
- })
45
-
46
- /**
47
- * Media Collection Schema
48
- */
49
- export const mediaCollectionSchema = z.object({
50
- /**
51
- * Name of the collection.
52
- *
53
- * Label translated for the default locale. Other configured site locales are optional.
54
- */
55
- label: inlineTranslationSchema,
56
- /**
57
- * Ordered list of media items included in this collection.
58
- * The array order defines how items are shown when querying by collection.
59
- *
60
- * @example ["my-book--en", "my-video--en"]
61
- */
62
- mediaItems: z.array(reference("media")),
63
- })
64
-
65
- /**
66
- * Media Item Schema
67
- */
68
- export const mediaItemSchema = z.object({
69
- /**
70
- * Optional identifier used to link translated variants of a media item.
71
- * If other media items share the same commonId they will show up as translations.
72
- * If omitted, the media item is treated as standalone and has no translations.
73
- * The common id will show up in the media item's url combined with it's language.
74
- *
75
- * We suggest you use the english name of the media item, all lower case, words separated with hyphens.
76
- *
77
- * @example "a-book-about-love"
78
- */
79
- commonId: z.string().optional(),
80
- /**
81
- * Title of this media item.
82
- * This is expected to be in the language that is defined by the 'language' property.
83
- *
84
- * @example "A book about love"
85
- */
86
- title: z.string(),
87
- /**
88
- * References one media-type by its filename without .json suffix.
89
- *
90
- * @example "book"
91
- */
92
- type: reference("media-types"),
93
- /**
94
- *Describes this media item. You can use markdown syntax to add formatting.
95
- * This is expected to be in the language that is defined by the 'language' property.
96
- *
97
- * @example "This is a book about **love**..."
98
- */
99
- description: z.string().optional(),
100
- /**
101
- * List of authors of this media item.
102
- *
103
- * @example ["George Miller", "Timothy Meier"]
104
- */
105
- authors: z.array(z.string()).nullish(),
106
- /**
107
- * Date this media item has been created on this lightnet instance.
108
- * Format is YYYY-MM-DD
109
- *
110
- * @example 2024-09-10
111
- */
112
- dateCreated: z.iso.date(),
113
- /**
114
- * List of categories of this media item.
115
- *
116
- * @example ["family"]
117
- */
118
- categories: z.array(reference("categories")).nullish(),
119
- /**
120
- * BCP-47 language code of this media item.
121
- *
122
- * @example "en"
123
- */
124
- language: z.string().nonempty(),
125
- /**
126
- * Relative path to the image of this media item. Eg. a book cover or video thumbnail.
127
- *
128
- * The image is expected to be inside the `images` folder next to the media item definition json.
129
- * This image will be used for previews and on the media item detail page.
130
- * It can have one of these file types: png, jpg, tiff, webp, gif, svg, avif.
131
- * We suggest to give it a size of at least 1000px for it's longer side.
132
- *
133
- * @example "./images/a-book-about-love--en.jpg"
134
- */
135
- image: imageSchema,
136
- /**
137
- * List of objects defining the content of this media item.
138
- */
139
- content: z
140
- .array(
141
- z.object({
142
- /**
143
- * Storage kind for this content item.
144
- *
145
- * - `"upload"`: a file managed by this LightNet site (typically a relative path like `/files/...`)
146
- * - `"link"`: an external URL (typically `https://...`)
147
- *
148
- * @example "upload"
149
- */
150
- type: z.enum(["upload", "link"]),
151
- /**
152
- * Urls might be:
153
- * - links to youtube videos
154
- * - links to vimeo videos
155
- * - links to .mp4 video files
156
- * - links to .mp3 audio files
157
- * - links to external websites
158
- * - links to pdfs (might be hosted inside the public/files/ folder)
159
- * - links to epubs (might be hosted inside the public/files/ folder)
160
- *
161
- * @example "/files/a-book-about-love.pdf"
162
- */
163
- url: z.string(),
164
- /**
165
- * The name of the content translated for the default locale.
166
- * Other configured site locales are optional.
167
- * If this is not set, the file name from URL will be used.
168
- */
169
- label: inlineTranslationSchema.optional(),
170
- }),
171
- )
172
- .min(1),
173
- })
174
-
175
- /**
176
- * MediaItemSchema above defines the shape of a media item.
177
- * We need this function to accept the astro content's image function that
178
- * is available inside defineCollection.
179
- *
180
- * @param schemaContext that is passed by astro's defineCollection schema.
181
- * @returns schema with image mixed in.
182
- */
183
- export const createMediaItemSchema = ({ image }: SchemaContext) =>
184
- mediaItemSchema.extend({
185
- image: image(),
186
- })
187
-
188
- export const createCategorySchema = ({ image }: SchemaContext) =>
189
- categorySchema.extend({
190
- image: image().optional(),
191
- })
192
-
193
- /**
194
- * Media Type Schema
195
- */
196
- export const mediaTypeSchema = z.object({
197
- /**
198
- * Name of this media type that will be shown on the pages.
199
- *
200
- * Label translated for the default locale. Other configured site locales are optional.
201
- */
202
- label: inlineTranslationSchema,
203
- /**
204
- * Defines how the cover image for a media item of this type is rendered.
205
- *
206
- * Options:
207
- * - `"default"` — Renders the media item image with no modifications.
208
- * - `"book"` — Adds a book fold effect and sharper edges, styled like a book cover.
209
- * - `"video"` — Constrains the image to a 16:9 aspect ratio with a black background.
210
- *
211
- * @default "default"
212
- */
213
- coverImageStyle: z.enum(["default", "book", "video"]).default("default"),
214
- /**
215
- * What media item details page to use for media items with this type.
216
- *
217
- */
218
- detailsPage: z
219
- .discriminatedUnion("layout", [
220
- z.object({
221
- /**
222
- * Details page for all media types.
223
- */
224
- layout: z.literal("default"),
225
- /**
226
- * Label for the open action button. Use this if you want to change the text
227
- * of the "Open" button to be more matching to your media item.
228
- * For example you could change the text to be "Read" for a book media type.
229
- *
230
- * Label translated for the default locale. Other configured site locales are optional.
231
- */
232
- openActionLabel: inlineTranslationSchema.optional(),
233
- }),
234
- z.object({
235
- /**
236
- * Custom details page.
237
- */
238
- layout: z.literal("custom"),
239
- /**
240
- * This references a custom component name to be used for the
241
- * details page. The custom component has be located at src/details-pages/
242
- *
243
- * @example "MyArticleDetails.astro"
244
- */
245
- customComponent: z.string(),
246
- }),
247
- z.object({
248
- /**
249
- * Detail page for videos.
250
- */
251
- layout: z.literal("video"),
252
- }),
253
- z.object({
254
- /**
255
- * Detail page for audio files.
256
- *
257
- * This only supports mp3 files.
258
- */
259
- layout: z.literal("audio"),
260
- }),
261
- ])
262
- .optional(),
263
- /**
264
- * Pick the media type's icon from https://lucide.dev/icons/
265
- * Prefix it's name with "lucide--"
266
- *
267
- * @example "lucide--book-open"
268
- */
269
- icon: z.string(),
270
- })
4
+ import { createCategorySchema } from "./schema/category"
5
+ import { mediaCollectionSchema } from "./schema/media-collection"
6
+ import { createMediaItemSchema } from "./schema/media-item"
7
+ import { mediaTypeSchema } from "./schema/media-type"
271
8
 
272
9
  export const LIGHTNET_COLLECTIONS = {
273
10
  categories: defineCollection({
@@ -296,27 +33,3 @@ export const LIGHTNET_COLLECTIONS = {
296
33
  schema: mediaTypeSchema,
297
34
  }),
298
35
  }
299
-
300
- export const mediaItemEntrySchema = z.object({
301
- id: z.string(),
302
- data: mediaItemSchema,
303
- })
304
-
305
- export type MediaItemEntry = z.infer<typeof mediaItemEntrySchema>
306
-
307
- export const mediaTypeEntrySchema = z.object({
308
- id: z.string(),
309
- data: mediaTypeSchema,
310
- })
311
-
312
- export const categoryEntrySchema = z.object({
313
- id: z.string(),
314
- data: categorySchema,
315
- })
316
-
317
- export const mediaCollectionEntrySchema = z.object({
318
- id: z.string(),
319
- data: mediaCollectionSchema,
320
- })
321
-
322
- export type MediaCollectionEntry = z.infer<typeof mediaCollectionEntrySchema>