lightnet 3.4.4 → 3.4.6

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,17 @@
1
1
  # lightnet
2
2
 
3
+ ## 3.4.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#271](https://github.com/LightNetDev/LightNet/pull/271) [`1ad0515`](https://github.com/LightNetDev/LightNet/commit/1ad051587cdf68c34a919f414ad2b5c15ffd273e) Thanks [@smn-cds](https://github.com/smn-cds)! - Fix markdown sanitation for search result descriptions.
8
+
9
+ ## 3.4.5
10
+
11
+ ### Patch Changes
12
+
13
+ - [#266](https://github.com/LightNetDev/LightNet/pull/266) [`4aff54c`](https://github.com/LightNetDev/LightNet/commit/4aff54c7bdd9f9cef26006950cfe7222685fba6c) Thanks [@smn-cds](https://github.com/smn-cds)! - Improve build performance of details pages.
14
+
3
15
  ## 3.4.4
4
16
 
5
17
  ### Patch Changes
@@ -6,9 +6,9 @@ case `uname` in
6
6
  esac
7
7
 
8
8
  if [ -z "$NODE_PATH" ]; then
9
- export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.7.13_@types+node@22.15.21_jiti@2.4.2_lightningcss@1.29.1_rollup@4.41.0_terser@5.39.0_typescript@5.8.3_yaml@2.8.0/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.7.13_@types+node@22.15.21_jiti@2.4.2_lightningcss@1.29.1_rollup@4.41.0_terser@5.39.0_typescript@5.8.3_yaml@2.8.0/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.8.1_@types+node@22.15.29_jiti@2.4.2_lightningcss@1.29.1_rollup@4.41.1_terser@5.39.0_typescript@5.8.3_yaml@2.8.0/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.8.1_@types+node@22.15.29_jiti@2.4.2_lightningcss@1.29.1_rollup@4.41.1_terser@5.39.0_typescript@5.8.3_yaml@2.8.0/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules"
10
10
  else
11
- export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.7.13_@types+node@22.15.21_jiti@2.4.2_lightningcss@1.29.1_rollup@4.41.0_terser@5.39.0_typescript@5.8.3_yaml@2.8.0/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.7.13_@types+node@22.15.21_jiti@2.4.2_lightningcss@1.29.1_rollup@4.41.0_terser@5.39.0_typescript@5.8.3_yaml@2.8.0/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.8.1_@types+node@22.15.29_jiti@2.4.2_lightningcss@1.29.1_rollup@4.41.1_terser@5.39.0_typescript@5.8.3_yaml@2.8.0/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.8.1_@types+node@22.15.29_jiti@2.4.2_lightningcss@1.29.1_rollup@4.41.1_terser@5.39.0_typescript@5.8.3_yaml@2.8.0/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules:$NODE_PATH"
12
12
  fi
13
13
  if [ -x "$basedir/node" ]; then
14
14
  exec "$basedir/node" "$basedir/../astro/astro.js" "$@"
@@ -4,11 +4,11 @@
4
4
  "version": "0.0.1",
5
5
  "private": "true",
6
6
  "dependencies": {
7
- "@astrojs/react": "^4.2.7",
7
+ "@astrojs/react": "^4.3.0",
8
8
  "@astrojs/tailwind": "^6.0.2",
9
9
  "@lightnet/decap-admin": "^3.1.1",
10
- "astro": "^5.7.13",
11
- "lightnet": "^3.4.3",
10
+ "astro": "^5.8.1",
11
+ "lightnet": "^3.4.4",
12
12
  "react": "^19.1.0",
13
13
  "react-dom": "^19.1.0",
14
14
  "sharp": "^0.33.5",
@@ -2,6 +2,27 @@ import { expect, test } from "vitest"
2
2
 
3
3
  import { markdownToText } from "../../src/utils/markdown"
4
4
 
5
+ test("Should remove '\\' to force new lines", () => {
6
+ expect(markdownToText("a\\\nb\\ \nc")).toBe("a\nb \nc")
7
+ })
8
+
9
+ test("Should remove <br> to force new lines", () => {
10
+ expect(markdownToText("a <br> b<br>\nc")).toBe("a b \nc")
11
+ })
12
+
13
+ test("Should remove double white space", () => {
14
+ expect(markdownToText("a b")).toBe("a b")
15
+ })
16
+
17
+ test("Should remove triple white space", () => {
18
+ expect(markdownToText("a b")).toBe("a b")
19
+ })
20
+
21
+ test("Should remove escape character '\\'", () => {
22
+ // eslint-disable-next-line no-useless-escape
23
+ expect(markdownToText("a \\\* \\\# b")).toBe("a * # b")
24
+ })
25
+
5
26
  test("Should remove headers", () => {
6
27
  expect(markdownToText("# H1\n## H2 words#")).toBe("H1\nH2 words#")
7
28
  })
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "lightnet",
3
3
  "type": "module",
4
4
  "license": "MIT",
5
- "version": "3.4.4",
5
+ "version": "3.4.6",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/LightNetDev/lightnet",
@@ -45,16 +45,16 @@
45
45
  "@iconify-json/mdi": "^1.2.3",
46
46
  "@iconify/tailwind": "^1.2.0",
47
47
  "@tailwindcss/typography": "^0.5.16",
48
- "@types/react": "^19.1.5",
48
+ "@types/react": "^19.1.6",
49
49
  "daisyui": "^4.12.24",
50
50
  "fuse.js": "^7.1.0",
51
- "i18next": "^25.2.0",
51
+ "i18next": "^25.2.1",
52
52
  "marked": "^15.0.12",
53
53
  "yaml": "^2.8.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@playwright/test": "^1.52.0",
57
- "@types/node": "^22.15.21",
57
+ "@types/node": "^22.15.29",
58
58
  "vitest": "^3.1.4"
59
59
  },
60
60
  "scripts": {
@@ -0,0 +1,24 @@
1
+ import type { MediaItemEntry } from "./content-schema-internal"
2
+
3
+ export function compareMediaCollectionItems(
4
+ item1: MediaItemEntry,
5
+ item2: MediaItemEntry,
6
+ collectionId: string,
7
+ ) {
8
+ const getIndex = (item: MediaItemEntry) =>
9
+ item.data.collections?.find(
10
+ ({ collection }) => collection.id === collectionId,
11
+ )?.index
12
+ const index1 = getIndex(item1)
13
+ const index2 = getIndex(item2)
14
+ if (index1 === index2) {
15
+ return item1.id.localeCompare(item2.id)
16
+ }
17
+ if (index1 === undefined && index2 !== undefined) {
18
+ return 1
19
+ }
20
+ if (index1 !== undefined && index2 === undefined) {
21
+ return -1
22
+ }
23
+ return index1! - index2!
24
+ }
@@ -1,3 +1,4 @@
1
+ import { compareMediaCollectionItems } from "./compare-media-collection-items"
1
2
  import type { MediaItemEntry } from "./content-schema-internal"
2
3
 
3
4
  export type MediaItemQuery<TMediaItem extends MediaItemEntry> = {
@@ -59,31 +60,8 @@ export const queryMediaItems = async <TMediaItem extends MediaItemEntry>(
59
60
  }
60
61
  const { collection } = where
61
62
  if (!orderBy && collection) {
62
- items.sort((a, b) => compareCollectionItems(a, b, collection))
63
+ items.sort((a, b) => compareMediaCollectionItems(a, b, collection))
63
64
  }
64
65
 
65
66
  return items.slice(0, limit)
66
67
  }
67
-
68
- function compareCollectionItems(
69
- item1: MediaItemEntry,
70
- item2: MediaItemEntry,
71
- collectionId: string,
72
- ) {
73
- const getIndex = (item: MediaItemEntry) =>
74
- item.data.collections?.find(
75
- ({ collection }) => collection.id === collectionId,
76
- )?.index
77
- const index1 = getIndex(item1)
78
- const index2 = getIndex(item2)
79
- if (index1 === index2) {
80
- return item1.id.localeCompare(item2.id)
81
- }
82
- if (index1 === undefined && index2 !== undefined) {
83
- return 1
84
- }
85
- if (index1 !== undefined && index2 === undefined) {
86
- return -1
87
- }
88
- return index1! - index2!
89
- }
@@ -1,9 +1,10 @@
1
1
  ---
2
2
  import type { GetStaticPaths } from "astro"
3
3
  import { AstroError } from "astro/errors"
4
+ import { getCollection } from "astro:content"
4
5
  import config from "virtual:lightnet/config"
5
6
 
6
- import { getMediaItem, getMediaItems } from "../../content/get-media-items"
7
+ import { getMediaItem } from "../../content/get-media-items"
7
8
  import { getMediaType } from "../../content/get-media-types"
8
9
  import { resolveLocales } from "../../i18n/resolve-locales"
9
10
  import AudioDetailsPage from "./AudioDetailsPage.astro"
@@ -11,7 +12,7 @@ import DefaultDetailsPage from "./DefaultDetailsPage.astro"
11
12
  import VideoDetailsPage from "./VideoDetailsPage.astro"
12
13
 
13
14
  export const getStaticPaths = (async () => {
14
- const mediaItems = await getMediaItems()
15
+ const mediaItems = await getCollection("media")
15
16
  return resolveLocales(config).flatMap((locale) =>
16
17
  mediaItems.map(({ id: mediaId }) => ({ params: { mediaId, locale } })),
17
18
  )
@@ -3,8 +3,7 @@ import { AstroError } from "astro/errors"
3
3
  import { getEntry } from "astro:content"
4
4
 
5
5
  import MediaList from "../../../components/MediaList.astro"
6
- import { getMediaItems } from "../../../content/get-media-items"
7
- import { queryMediaItems } from "../../../content/query-media-items"
6
+ import { getCollectionItems } from "../utils/get-collection-items"
8
7
 
9
8
  interface Props {
10
9
  collectionId: string
@@ -19,11 +18,10 @@ if (!collection) {
19
18
  `To fix the issue, add a media-collection at "src/content/media-collections/${collectionId}.json".`,
20
19
  )
21
20
  }
22
- const items = (
23
- await queryMediaItems(getMediaItems(), {
24
- where: { collection: collection.id },
25
- })
26
- ).map((item) => ({ ...item, disabled: item.id === disableItem }))
21
+ const items = (await getCollectionItems(collection.id)).map((item) => ({
22
+ ...item,
23
+ disabled: item.id === disableItem,
24
+ }))
27
25
 
28
26
  if (items.length < 2) {
29
27
  return
@@ -1,10 +1,8 @@
1
1
  ---
2
- import {
3
- getMediaItem,
4
- getMediaItems,
5
- } from "../../../../content/get-media-items"
2
+ import { getMediaItem } from "../../../../content/get-media-items"
6
3
  import { resolveTranslatedLanguage } from "../../../../i18n/resolve-language"
7
4
  import { detailsPagePath } from "../../../../utils/paths"
5
+ import { getTranslations } from "../../utils/get-translations"
8
6
  import Label from "./Label.astro"
9
7
 
10
8
  interface Props {
@@ -14,12 +12,7 @@ interface Props {
14
12
  const item = await getMediaItem(Astro.props.mediaId)
15
13
 
16
14
  const { mediaId } = Astro.props
17
- const translations = (await getMediaItems())
18
- .filter(
19
- (entry) =>
20
- entry.data.commonId === item.data.commonId && entry.id !== mediaId,
21
- )
22
- .sort((a, b) => a.data.language.localeCompare(b.data.language))
15
+ const translations = await getTranslations(mediaId)
23
16
 
24
17
  const { t } = Astro.locals.i18n
25
18
  ---
@@ -35,9 +28,9 @@ const { t } = Astro.locals.i18n
35
28
  <li class="flex rounded-lg border border-gray-200 px-4 py-1 text-gray-600 hover:bg-gray-200">
36
29
  <a
37
30
  href={detailsPagePath(Astro.currentLocale, translation)}
38
- hreflang={translation.data.language}
31
+ hreflang={translation.language}
39
32
  >
40
- {resolveTranslatedLanguage(translation.data.language, t).name}
33
+ {resolveTranslatedLanguage(translation.language, t).name}
41
34
  </a>
42
35
  </li>
43
36
  ))
@@ -0,0 +1,29 @@
1
+ import { compareMediaCollectionItems } from "../../../content/compare-media-collection-items"
2
+ import type { MediaItemEntry } from "../../../content/content-schema-internal"
3
+ import { getMediaItems } from "../../../content/get-media-items"
4
+
5
+ const groupItemsByCollections = async () => {
6
+ const items = await getMediaItems()
7
+ items.forEach((item) => {
8
+ item.data.collections?.forEach(({ collection }) => {
9
+ if (!itemsByCollections.has(collection.id)) {
10
+ itemsByCollections.set(collection.id, [])
11
+ }
12
+ itemsByCollections.get(collection.id)?.push(item)
13
+ })
14
+ })
15
+ itemsByCollections.forEach((entries, collectionId) =>
16
+ entries.sort((a, b) => compareMediaCollectionItems(a, b, collectionId)),
17
+ )
18
+ }
19
+
20
+ let isInitialized = false
21
+ const itemsByCollections = new Map<string, MediaItemEntry[]>()
22
+
23
+ export const getCollectionItems = async (collectionId: string) => {
24
+ if (!isInitialized) {
25
+ isInitialized = true
26
+ await groupItemsByCollections()
27
+ }
28
+ return itemsByCollections.get(collectionId) ?? []
29
+ }
@@ -0,0 +1,34 @@
1
+ import { getMediaItem, getMediaItems } from "../../../content/get-media-items"
2
+
3
+ const groupItemsByCommonId = async () => {
4
+ const items = await getMediaItems()
5
+ items.forEach(({ id, data: { commonId, language } }) => {
6
+ if (!itemsByCommonId.has(commonId)) {
7
+ itemsByCommonId.set(commonId, [])
8
+ }
9
+ itemsByCommonId.get(commonId)?.push({ id, language })
10
+ })
11
+ itemsByCommonId.forEach((value, key) => {
12
+ if (value.length < 2) {
13
+ itemsByCommonId.delete(key)
14
+ }
15
+ })
16
+ }
17
+
18
+ let isInitialized = false
19
+ const itemsByCommonId = new Map<string, { id: string; language: string }[]>()
20
+
21
+ export const getTranslations = async (mediaId: string) => {
22
+ if (!isInitialized) {
23
+ isInitialized = true
24
+ await groupItemsByCommonId()
25
+ }
26
+ const item = await getMediaItem(mediaId)
27
+ const sameCommonId = itemsByCommonId.get(item.data.commonId)
28
+ if (!sameCommonId) {
29
+ return []
30
+ }
31
+ return sameCommonId
32
+ .filter(({ id }) => id !== mediaId)
33
+ .sort((a, b) => a.language.localeCompare(b.language))
34
+ }
@@ -6,12 +6,15 @@ import { marked } from "marked"
6
6
  * @param markdown string
7
7
  * @returns plain text
8
8
  */
9
+
9
10
  export function markdownToText(markdown?: string) {
10
11
  if (!markdown) {
11
12
  return markdown
12
13
  }
13
14
  return (
14
15
  markdown
16
+ // line breaks
17
+ .replaceAll(/<br>/g, " ")
15
18
  //headers
16
19
  .replaceAll(/^#+ ?/gm, "")
17
20
  // lists
@@ -19,11 +22,15 @@ export function markdownToText(markdown?: string) {
19
22
  // block quotes
20
23
  .replaceAll(/^>+ ?/gm, "")
21
24
  // bold and italics
22
- .replaceAll(/[*_]/g, "")
25
+ .replaceAll(/(?<!\\)[*_]/g, "")
23
26
  // images
24
27
  .replaceAll(/!\[(.*?)\]\(.*?\)/g, (_, imgAlt) => imgAlt)
25
28
  // links
26
29
  .replaceAll(/\[(.*?)\]\(.*?\)/g, (_, linkLabel) => linkLabel)
30
+ // escape character '\'
31
+ .replaceAll(/\\/g, "")
32
+ // multi white spaces
33
+ .replaceAll(/ +/g, " ")
27
34
  )
28
35
  }
29
36