lightnet 4.8.0 → 4.9.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # lightnet
2
2
 
3
+ ## 4.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#475](https://github.com/LightNetDev/LightNet/pull/475) [`24a5813`](https://github.com/LightNetDev/LightNet/commit/24a58138e83824c7f740b77c2373f152c6d02eb7) - Support `SoftwareApplication` and `WebPage` as media type structured data classifications in JSON definitions and the admin interface. For these types, use the first content entry's HTTP(S) link as the resource URL and identify the LightNet detail page with `mainEntityOfPage`. Retain the detail URL when the first entry is an upload or has no valid HTTP(S) URL.
8
+
3
9
  ## 4.8.0
4
10
 
5
11
  ### Minor Changes
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.8.0",
6
+ "version": "4.9.0",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "https://github.com/LightNetDev/lightnet",
@@ -16,6 +16,8 @@ export const mediaTypeSchema = z.object({
16
16
  * Schema.org type of the work described on media detail pages.
17
17
  * Independent of the page layout and downloadable file formats.
18
18
  * If omitted, structured data is inferred from the layout and content.
19
+ * WebPage and SoftwareApplication use the first content entry's HTTP(S)
20
+ * link as the work URL, with the LightNet detail page as mainEntityOfPage.
19
21
  */
20
22
  schemaType: z
21
23
  .enum([
@@ -26,6 +28,8 @@ export const mediaTypeSchema = z.object({
26
28
  "AudioObject",
27
29
  "VideoObject",
28
30
  "ImageObject",
31
+ "SoftwareApplication",
32
+ "WebPage",
29
33
  ])
30
34
  .optional(),
31
35
  /**
@@ -61,13 +61,8 @@ export function createMediaItemJsonLd({
61
61
  }
62
62
 
63
63
  const media = item.content.map(({ url }, index) => {
64
- let resolvedUrl: URL
65
- try {
66
- resolvedUrl = new URL(url, canonicalUrl)
67
- } catch {
68
- return undefined
69
- }
70
- if (!["http:", "https:"].includes(resolvedUrl.protocol)) {
64
+ const resolvedUrl = resolveHttpUrl(url, canonicalUrl)
65
+ if (!resolvedUrl) {
71
66
  return undefined
72
67
  }
73
68
 
@@ -92,6 +87,20 @@ export function createMediaItemJsonLd({
92
87
  })
93
88
 
94
89
  const encodings = media.filter((entry) => entry !== undefined)
90
+ if (schemaType === "SoftwareApplication" || schemaType === "WebPage") {
91
+ const primary = item.content[0]
92
+ const resourceUrl =
93
+ primary?.type === "link"
94
+ ? resolveHttpUrl(primary.url, canonicalUrl)
95
+ : undefined
96
+ return {
97
+ ...base,
98
+ url: resourceUrl?.href ?? canonicalUrl.href,
99
+ mainEntityOfPage: canonicalUrl.href,
100
+ encoding: encodings.length ? encodings : undefined,
101
+ }
102
+ }
103
+
95
104
  if (
96
105
  schemaType === "AudioObject" ||
97
106
  schemaType === "VideoObject" ||
@@ -145,6 +154,15 @@ export function createMediaItemJsonLd({
145
154
  return { ...base, encoding: encodings.length ? encodings : undefined }
146
155
  }
147
156
 
157
+ function resolveHttpUrl(value: string, base: URL) {
158
+ try {
159
+ const url = new URL(value, base)
160
+ return ["http:", "https:"].includes(url.protocol) ? url : undefined
161
+ } catch {
162
+ return undefined
163
+ }
164
+ }
165
+
148
166
  function getVideoEmbedUrl(url: URL) {
149
167
  if (url.hostname === "www.youtube.com" || url.hostname === "youtube.com") {
150
168
  const id = url.pathname.startsWith("/embed/")