@terrafirmagreg-team/guide 0.1.0 → 1.2.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 (68) hide show
  1. package/package.json +18 -19
  2. package/src/components/book-switcher.tsx +12 -6
  3. package/src/components/mdx/guide-entry.tsx +48 -0
  4. package/src/components/mdx/multiblock.tsx +86 -0
  5. package/src/{lib/tree/children.ts → components/tree/children.tsx} +13 -8
  6. package/src/{lib/tree/index.ts → components/tree/index.tsx} +25 -15
  7. package/src/components/views/browser.tsx +26 -17
  8. package/src/components/views/entry/pages.tsx +4 -2
  9. package/src/components/views/entry/view.tsx +3 -1
  10. package/src/components/views/kind/links.tsx +3 -2
  11. package/src/components/views/kind/media.tsx +6 -5
  12. package/src/components/views/kind/recipe.tsx +6 -51
  13. package/src/components/views/kind/table.tsx +4 -2
  14. package/src/components/views/kind/unknown.tsx +1 -0
  15. package/src/components/views/page/category-body.tsx +3 -1
  16. package/src/components/views/page/entry-body.tsx +3 -1
  17. package/src/components/views/page/overview-body.tsx +4 -2
  18. package/src/components/views/page/text.tsx +1 -0
  19. package/src/components/views/page/view.tsx +6 -6
  20. package/src/components/views/text.tsx +4 -2
  21. package/src/hooks/use-left-sidebar-tree.ts +15 -6
  22. package/src/hooks/use-tree.ts +5 -3
  23. package/src/lib/book/convert.ts +2 -1
  24. package/src/lib/book/index-rows.ts +3 -1
  25. package/src/lib/book/index.ts +1 -0
  26. package/src/lib/book/localize.ts +3 -2
  27. package/src/lib/book/raw.ts +5 -4
  28. package/src/lib/books.ts +4 -2
  29. package/src/lib/breadcrumb.ts +3 -1
  30. package/src/lib/client/guides.ts +86 -13
  31. package/src/lib/client-payload/extras.ts +10 -8
  32. package/src/lib/client-payload/index.ts +9 -8
  33. package/src/lib/client-payload/links.ts +10 -8
  34. package/src/lib/config.ts +1 -0
  35. package/src/lib/data/dto.ts +5 -4
  36. package/src/lib/data/parse.ts +4 -3
  37. package/src/lib/dump.ts +4 -3
  38. package/src/lib/embeds.ts +12 -0
  39. package/src/lib/format.ts +3 -2
  40. package/src/lib/links.ts +1 -1
  41. package/src/lib/markdown/book.ts +1 -0
  42. package/src/lib/markdown/ctx.ts +3 -1
  43. package/src/lib/markdown/index.ts +1 -0
  44. package/src/lib/markdown/page.ts +7 -8
  45. package/src/lib/markdown/table.ts +1 -0
  46. package/src/lib/markdown/text.ts +1 -0
  47. package/src/lib/markdown-page.ts +6 -4
  48. package/src/lib/messages.ts +1 -0
  49. package/src/lib/meta.ts +1 -0
  50. package/src/lib/multiblock/index.ts +1 -0
  51. package/src/lib/multiblock/url.ts +24 -10
  52. package/src/lib/names.ts +5 -3
  53. package/src/lib/page-kind.ts +2 -1
  54. package/src/lib/paths.ts +4 -2
  55. package/src/lib/preview.ts +8 -4
  56. package/src/lib/query.ts +1 -0
  57. package/src/lib/recipe.ts +3 -2
  58. package/src/lib/reference/index.ts +1 -0
  59. package/src/lib/reference/resolver.ts +4 -4
  60. package/src/lib/search/filter.ts +2 -1
  61. package/src/lib/search/index.ts +41 -14
  62. package/src/lib/sprites.ts +1 -0
  63. package/src/lib/table.ts +1 -0
  64. package/src/lib/toc.ts +3 -2
  65. package/src/locales/en_us.json +12 -20
  66. package/src/locales/ru_ru.json +12 -20
  67. package/src/locales.ts +1 -0
  68. package/src/types/index.ts +12 -10
@@ -1,6 +1,6 @@
1
1
  import { GuideText } from '@terrafirmagreg-team/guide/components/views/text';
2
2
  import { Card } from '@terrafirmagreg-team/ui/components/ui/card';
3
- import { ItemEntry } from '@terrafirmagreg-team/game/components/entry/entry';
3
+ import { Entry } from '@terrafirmagreg-team/game/components/entry/entry';
4
4
  import {
5
5
  Table,
6
6
  TableBody,
@@ -91,7 +91,8 @@ export function TablePage(props: PageRendererProps) {
91
91
  >
92
92
  <span className="inline-flex flex-wrap items-center gap-1">
93
93
  {items.map((id) => (
94
- <ItemEntry
94
+ <Entry
95
+ kind="item"
95
96
  key={id}
96
97
  id={id}
97
98
  name={id}
@@ -136,3 +137,4 @@ export function TablePage(props: PageRendererProps) {
136
137
  </>
137
138
  );
138
139
  }
140
+
@@ -21,3 +21,4 @@ export function UnknownPage({
21
21
  </Alert>
22
22
  );
23
23
  }
24
+
@@ -1,3 +1,4 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import { Entry } from '@terrafirmagreg-team/game/components/entry/entry';
2
3
  import { ItemRow } from '@terrafirmagreg-team/ui/components/blocks/list/row';
3
4
  import { guideBookHref } from '@terrafirmagreg-team/guide/lib/paths';
@@ -5,7 +6,7 @@ import { guideMessage } from '@terrafirmagreg-team/guide/lib/messages';
5
6
  import type { GuideIndex, GuideMessages } from '@terrafirmagreg-team/guide/types';
6
7
 
7
8
  type GuideCategoryBodyProps = {
8
- dataset: string;
9
+ dataset: DatasetRef;
9
10
  lang: string;
10
11
  modId?: string;
11
12
  bookPath?: string;
@@ -54,3 +55,4 @@ export function GuideCategoryBody({
54
55
  </div>
55
56
  );
56
57
  }
58
+
@@ -1,3 +1,4 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import { EmptyState } from '@terrafirmagreg-team/ui/components/blocks/page/empty-state';
2
3
  import { EntryView } from '@terrafirmagreg-team/guide/components/views/entry/view';
3
4
  import { guideMessage } from '@terrafirmagreg-team/guide/lib/messages';
@@ -11,7 +12,7 @@ import type {
11
12
  } from '@terrafirmagreg-team/guide/types';
12
13
 
13
14
  type GuideEntryBodyProps = {
14
- dataset: string;
15
+ dataset: DatasetRef;
15
16
  lang: Lang;
16
17
  bookPath?: string;
17
18
  overview: GuideIndex;
@@ -77,3 +78,4 @@ export function GuideEntryBody({
77
78
  />
78
79
  );
79
80
  }
81
+
@@ -6,15 +6,16 @@ import {
6
6
  guideCategoryHref,
7
7
  isRootCategory,
8
8
  } from '@terrafirmagreg-team/guide/lib/paths';
9
- import { texturePublicUrl } from '@terrafirmagreg-team/game/lib/dump/assets/urls';
9
+ import { texturePublicUrl } from '@terrafirmagreg-team/dump/lib/dump/assets/urls';
10
10
  import { useDumpLocation } from '@terrafirmagreg-team/game/hooks/use-dump-location';
11
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
11
12
  import { guideMessage } from '@terrafirmagreg-team/guide/lib/messages';
12
13
  import type { PagePreviewData } from '@terrafirmagreg-team/ui/types/preview';
13
14
  import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
14
15
  import type { GuideIndex, GuideMessages } from '@terrafirmagreg-team/guide/types';
15
16
 
16
17
  type GuideOverviewBodyProps = {
17
- dataset: string;
18
+ dataset: DatasetRef;
18
19
  lang: Lang;
19
20
  modId?: string;
20
21
  bookPath?: string;
@@ -95,3 +96,4 @@ export function GuideOverviewBody({
95
96
  </div>
96
97
  );
97
98
  }
99
+
@@ -55,3 +55,4 @@ export function PageText({
55
55
  </>
56
56
  );
57
57
  }
58
+
@@ -9,7 +9,6 @@ import {
9
9
  import { guideConfig } from '@terrafirmagreg-team/guide/lib/config';
10
10
  import { GithubInfo } from '@terrafirmagreg-team/ui/components/blocks/git/github-info';
11
11
  import { sectionConfig } from '@terrafirmagreg-team/kit/lib/config';
12
- import { parseDatasetRef } from '@terrafirmagreg-team/kit/lib/location';
13
12
  import { categoryMap, guideBreadcrumbItems } from '@terrafirmagreg-team/guide/lib/breadcrumb';
14
13
  import { guideToc } from '@terrafirmagreg-team/guide/lib/toc';
15
14
  import { GuideText } from '@terrafirmagreg-team/guide/components/views/text';
@@ -17,7 +16,7 @@ import { GuideOverviewBody } from '@terrafirmagreg-team/guide/components/views/p
17
16
  import { GuideCategoryBody } from '@terrafirmagreg-team/guide/components/views/page/category-body';
18
17
  import { GuideEntryBody } from '@terrafirmagreg-team/guide/components/views/page/entry-body';
19
18
  import { guideMessage } from '@terrafirmagreg-team/guide/lib/messages';
20
- import { Comments } from '@terrafirmagreg-team/comments';
19
+ import { CommentsSlot } from '@terrafirmagreg-team/discussions/components/comments';
21
20
  import {
22
21
  guideBookHref,
23
22
  guideCategoryHref,
@@ -184,7 +183,7 @@ export function GuidePageView({
184
183
  });
185
184
 
186
185
  const datasetConf =
187
- sectionConfig().datasetConfig[parseDatasetRef(dataset).id];
186
+ sectionConfig().datasetConfig[dataset.id];
188
187
  const repoSlug = datasetConf?.repo?.split('/');
189
188
  const mdQuery = new URLSearchParams();
190
189
  if (payload.modId && payload.bookPath) {
@@ -196,7 +195,7 @@ export function GuidePageView({
196
195
  mdQuery.set('cat', payload.categoryId);
197
196
  }
198
197
  mdQuery.set('lang', lang);
199
- const mdUrl = `/guide/${dataset}.md?${mdQuery}`;
198
+ const mdUrl = `/guide/${dataset.id}.md?${mdQuery}`;
200
199
 
201
200
  const nav = guideNavItems(payload, overview);
202
201
  const {
@@ -270,10 +269,11 @@ export function GuidePageView({
270
269
  {body}
271
270
  </div>
272
271
  </WorkspaceBody>
273
- <Comments
274
- page={`guide:${dataset}:${payload.modId}:${payload.bookPath}:${payload.entry?.id ?? payload.categoryId ?? 'book'}#${lang}`}
272
+ <CommentsSlot
273
+ page={`guide:${dataset.id}:${payload.modId}:${payload.bookPath}:${payload.entry?.id ?? payload.categoryId ?? 'book'}#${lang}`}
275
274
  />
276
275
  </Workspace>
277
276
  </EntryProvider>
278
277
  );
279
278
  }
279
+
@@ -1,3 +1,4 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import { Fragment, type ReactNode } from 'react';
2
3
  import { LinkPreview } from '@terrafirmagreg-team/ui/components/blocks/link/link-preview';
3
4
  import { guideLink } from '@terrafirmagreg-team/guide/lib/reference';
@@ -29,7 +30,7 @@ export function GuideText({
29
30
  previews,
30
31
  }: {
31
32
  text: string;
32
- dataset?: string;
33
+ dataset?: DatasetRef;
33
34
  lang?: Lang;
34
35
  modId?: string;
35
36
  bookPath?: string;
@@ -89,7 +90,7 @@ export function GuideText({
89
90
  }
90
91
  if (node.type === 'text' && node.link) {
91
92
  const { href, external } = guideLink(node, {
92
- dataset: dataset ?? '',
93
+ dataset: dataset ?? { id: '' },
93
94
  lang: lang ?? 'en_us',
94
95
  modId: modId ?? '',
95
96
  bookPath: bookPath ?? '',
@@ -128,3 +129,4 @@ export function GuideText({
128
129
  }
129
130
  return <>{children}</>;
130
131
  }
132
+
@@ -1,19 +1,28 @@
1
1
  'use client';
2
2
  import { usePathname } from 'next/navigation';
3
+ import { useMemo } from 'react';
3
4
  import type * as PageTree from 'fumadocs-core/page-tree';
4
- import { useLocationSearch } from '@terrafirmagreg-team/ui/hooks/page/use-location-search';
5
+ import { useLocationSearchParams } from '@terrafirmagreg-team/ui/hooks/page/use-location-search';
5
6
  import { useResolvedLang } from '@terrafirmagreg-team/translate/hooks/use-resolved-lang';
6
7
  import { useLastValue } from '@terrafirmagreg-team/ui/hooks/use-last-value';
7
8
  import { useGuideTree } from '@terrafirmagreg-team/guide/hooks/use-tree';
8
9
  import { guideQueryFromParams } from '@terrafirmagreg-team/guide/lib/query';
9
- import { parseSectionLocation } from '@terrafirmagreg-team/kit/lib/location';
10
+ import { parseSectionLocation } from '@terrafirmagreg-team/sites/location';
10
11
 
11
12
  export function useGuideLeftSidebarTree(tree: PageTree.Root): PageTree.Root {
12
- const { dataset } = parseSectionLocation(usePathname());
13
+ const { dataset: datasetId } = parseSectionLocation(usePathname());
13
14
  const lang = useResolvedLang();
14
- const { bookId } = guideQueryFromParams(
15
- new URLSearchParams(useLocationSearch()),
15
+ const params = useLocationSearchParams();
16
+ const { bookId } = guideQueryFromParams(params);
17
+ const version = params.get('version') ?? undefined;
18
+ const dataset = useMemo(
19
+ () => (datasetId ? { id: datasetId, version } : undefined),
20
+ [datasetId, version],
21
+ );
22
+ const runtime = useLastValue(
23
+ useGuideTree(dataset, lang, bookId),
24
+ dataset?.id ?? '',
16
25
  );
17
- const runtime = useLastValue(useGuideTree(dataset, lang, bookId), dataset);
18
26
  return runtime ?? tree;
19
27
  }
28
+
@@ -1,14 +1,15 @@
1
1
  'use client';
2
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
3
 
3
4
  import type * as PageTree from 'fumadocs-core/page-tree';
4
5
  import { useAsyncValue } from '@terrafirmagreg-team/ui/hooks/use-async-value';
5
6
  import { loadClientGuideBook } from '@terrafirmagreg-team/guide/lib/client/guides';
6
7
  import { listGuideBooks } from '@terrafirmagreg-team/guide/lib/books';
7
- import { guideTreeChildren } from '@terrafirmagreg-team/guide/lib/tree/children';
8
+ import { guideTreeChildren } from '@terrafirmagreg-team/guide/components/tree/children';
8
9
  import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
9
10
 
10
11
  export function useGuideTree(
11
- dataset: string | undefined,
12
+ dataset: DatasetRef | undefined,
12
13
  lang: Lang,
13
14
  bookId: string | undefined,
14
15
  ): PageTree.Root | undefined {
@@ -24,10 +25,11 @@ export function useGuideTree(
24
25
  return {
25
26
  name: 'guide',
26
27
  children: index ? guideTreeChildren(dataset, index) : [],
27
- $id: `guide/${dataset}/${resolvedId ?? 'none'}/${lang}`,
28
+ $id: `guide/${dataset.id}/${dataset.version ?? ''}/${resolvedId ?? 'none'}/${lang}`,
28
29
  } satisfies PageTree.Root;
29
30
  }
30
31
  : undefined,
31
32
  [dataset, lang, bookId],
32
33
  );
33
34
  }
35
+
@@ -1,4 +1,4 @@
1
- import { dumpTextLines } from '@terrafirmagreg-team/game/lib/dump/assets/lang/names';
1
+ import { dumpTextLines } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
2
2
  import type {
3
3
  GuideBookJson,
4
4
  GuideBookRef,
@@ -72,3 +72,4 @@ export function bookSlug(
72
72
  if (explicit) return urlSafeSlug(explicit);
73
73
  return urlSafeSlug(ref.bookPath);
74
74
  }
75
+
@@ -1,3 +1,4 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import { parseGuideIcon } from '@terrafirmagreg-team/guide/lib/data/parse';
2
3
  import type {
3
4
  GuideBookJson,
@@ -99,7 +100,7 @@ export type BookRows = {
99
100
 
100
101
  export function indexBookRows(
101
102
  rows: BookRows,
102
- dataset: string,
103
+ dataset: DatasetRef,
103
104
  lang: Lang,
104
105
  langMap: Record<string, string>,
105
106
  rawLang?: Record<string, string>,
@@ -132,3 +133,4 @@ export function indexBookRows(
132
133
  isFallback: rows.isFallback,
133
134
  };
134
135
  }
136
+
@@ -1,2 +1,3 @@
1
1
  export { bookSlug, toBook } from './convert';
2
2
  export { type BookRows, indexBookRows } from './index-rows';
3
+
@@ -1,5 +1,5 @@
1
- import { langString } from '@terrafirmagreg-team/game/lib/dump/assets/lang/names';
2
- import type { DumpText } from '@terrafirmagreg-team/game/lib/dump/contract/text';
1
+ import { langString } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
2
+ import type { DumpText } from '@terrafirmagreg-team/dump/lib/dump/contract/text';
3
3
 
4
4
  export type FallbackTracker = {
5
5
  mark(key: string | undefined): void;
@@ -74,3 +74,4 @@ export function localizeGuideValue(
74
74
  }
75
75
  return value;
76
76
  }
77
+
@@ -1,7 +1,7 @@
1
- import { asTaggedReference } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
2
- import { asDumpTextList } from '@terrafirmagreg-team/game/lib/dump/contract/text';
3
- import type { DumpText } from '@terrafirmagreg-team/game/lib/dump/contract/text';
4
- import type { TaggedReference } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
1
+ import { asTaggedReference } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
2
+ import { asDumpTextList } from '@terrafirmagreg-team/dump/lib/dump/contract/text';
3
+ import type { DumpText } from '@terrafirmagreg-team/dump/lib/dump/contract/text';
4
+ import type { TaggedReference } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
5
5
  import { bareId } from '@terrafirmagreg-team/guide/lib/paths';
6
6
 
7
7
  export type RawRecord = Record<string, unknown>;
@@ -78,3 +78,4 @@ export function categoryMatches(
78
78
  if (!entryCategory) return false;
79
79
  return bareId(entryCategory) === bareId(categoryId);
80
80
  }
81
+
package/src/lib/books.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import { sectionConfig } from '@terrafirmagreg-team/kit/lib/config';
2
3
  import { listClientGuideBookSummaries } from '@terrafirmagreg-team/guide/lib/client/guides';
3
4
  import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
@@ -20,10 +21,11 @@ function orderGuideBooks<T extends { bookId: string }>(
20
21
  }
21
22
 
22
23
  export function listGuideBooks(
23
- dataset: string,
24
+ dataset: DatasetRef,
24
25
  lang: Lang,
25
26
  ): Promise<GuideBookSummary[]> {
26
27
  return listClientGuideBookSummaries(dataset, lang).then((books) =>
27
- orderGuideBooks(books, sectionConfig().datasetConfig[dataset]?.guide?.bookOrder),
28
+ orderGuideBooks(books, sectionConfig().datasetConfig[dataset.id]?.guide?.bookOrder),
28
29
  );
29
30
  }
31
+
@@ -1,3 +1,4 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import { guideBookHref, guideCategoryHref } from '@terrafirmagreg-team/guide/lib/paths';
2
3
  import type { GuideCategory, GuideIndex, GuidePageKind } from '@terrafirmagreg-team/guide/types';
3
4
 
@@ -24,7 +25,7 @@ export function guideBreadcrumbItems({
24
25
  }: {
25
26
  kind: GuidePageKind;
26
27
  title: string;
27
- dataset: string;
28
+ dataset: DatasetRef;
28
29
  modId?: string;
29
30
  bookPath?: string;
30
31
  overview: GuideIndex | undefined;
@@ -52,3 +53,4 @@ export function guideBreadcrumbItems({
52
53
  items.push({ name: title });
53
54
  return items;
54
55
  }
56
+
@@ -1,5 +1,9 @@
1
- import { asRecord } from '@terrafirmagreg-team/game/lib/dump/contract/read';
2
- import { joinDumpRel } from '@terrafirmagreg-team/game/lib/dump/paths';
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
+ import { asRecord, asString } from '@terrafirmagreg-team/dump/lib/dump/contract/read';
3
+ import { joinDumpRel } from '@terrafirmagreg-team/dump/lib/dump/paths';
4
+ import { bareId } from '@terrafirmagreg-team/guide/lib/paths';
5
+ import type { GuideEntry } from '@terrafirmagreg-team/guide/types';
6
+ import type { GuideMultiblock } from '@terrafirmagreg-team/guide/lib/data/dto';
3
7
  import type {
4
8
  GuideBookJson,
5
9
  GuideBookRef,
@@ -16,9 +20,9 @@ import {
16
20
  clientDumpJson,
17
21
  clientDumpLang,
18
22
  clientDumpLangRaw,
19
- loadClientDump,
20
- } from '@terrafirmagreg-team/game/lib/dump/client/dump';
21
- import { createAsyncCache } from '@terrafirmagreg-team/ui/lib/utils/async-cache';
23
+ } from '@terrafirmagreg-team/dump/lib/dump/client/dump';
24
+ import { loadDatasetDump } from '@terrafirmagreg-team/dump/lib/dump/mods/load';
25
+ import { createDatasetCache } from '@terrafirmagreg-team/dump/lib/dump/reader';
22
26
 
23
27
  type BookRow = {
24
28
  ref: GuideBookRef;
@@ -26,9 +30,9 @@ type BookRow = {
26
30
  raw?: GuideBookJson;
27
31
  };
28
32
 
29
- const listedBookRows = createAsyncCache(
30
- async (dataset: string): Promise<BookRow[]> => {
31
- const dump = await loadClientDump(dataset);
33
+ const listedBookRows = createDatasetCache(
34
+ async (dataset: DatasetRef): Promise<BookRow[]> => {
35
+ const dump = await loadDatasetDump(dataset);
32
36
  if (!dump) return [];
33
37
  const raws = await Promise.all(
34
38
  dump.mods.flatMap((mod) =>
@@ -78,7 +82,7 @@ function listedBodies(
78
82
  }
79
83
 
80
84
  async function bookRows(
81
- dataset: string,
85
+ dataset: DatasetRef,
82
86
  row: BookRow,
83
87
  lang: Lang,
84
88
  ): Promise<BookRows | null> {
@@ -138,9 +142,9 @@ async function bookRows(
138
142
  };
139
143
  }
140
144
 
141
- export const loadClientGuideBook = createAsyncCache(
145
+ export const loadClientGuideBook = createDatasetCache(
142
146
  async (
143
- dataset: string,
147
+ dataset: DatasetRef,
144
148
  lang: Lang,
145
149
  bookSlugValue: string,
146
150
  ): Promise<GuideIndex | null> => {
@@ -157,11 +161,79 @@ export const loadClientGuideBook = createAsyncCache(
157
161
  if (!rows) return null;
158
162
  return indexBookRows(rows, dataset, lang, langMap, rawLang);
159
163
  },
160
- (dataset, lang, bookSlugValue) => `${dataset}${lang}${bookSlugValue}`,
164
+ (dataset, lang, bookSlugValue) => `${dataset.id}/${dataset.version ?? ''}${lang}${bookSlugValue}`,
165
+ );
166
+
167
+ export type ClientGuideEntryHit = {
168
+ entry: GuideEntry;
169
+ modId?: string;
170
+ bookPath?: string;
171
+ };
172
+
173
+ export async function findClientGuideEntry(
174
+ dataset: DatasetRef,
175
+ lang: Lang,
176
+ entryId: string,
177
+ ): Promise<ClientGuideEntryHit | undefined> {
178
+ const needle = bareId(entryId);
179
+ const nameNeedle = entryId.trim().toLowerCase();
180
+ for (const row of await listedBookRows(dataset)) {
181
+ const entries = (row.raw as Record<string, unknown> | undefined)?.entries;
182
+ const overview = await loadClientGuideBook(dataset, lang, row.slug);
183
+ const match =
184
+ entries && typeof entries === 'object'
185
+ ? Object.keys(entries).find(
186
+ (key) => bareId(key) === needle || key === entryId,
187
+ )
188
+ : undefined;
189
+ const entry = overview?.entries.find(
190
+ (item) =>
191
+ item.id === match ||
192
+ bareId(item.id) === needle ||
193
+ item.name?.trim().toLowerCase() === nameNeedle,
194
+ );
195
+ if (entry) {
196
+ return {
197
+ entry,
198
+ modId: overview?.modId,
199
+ bookPath: overview?.bookPath,
200
+ };
201
+ }
202
+ }
203
+ return undefined;
204
+ }
205
+
206
+ export const loadMultiblockNameIndex = createDatasetCache(
207
+ async (
208
+ dataset: DatasetRef,
209
+ lang: Lang,
210
+ ): Promise<Record<string, GuideMultiblock>> => {
211
+ const index: Record<string, GuideMultiblock> = {};
212
+ const put = (key: string | undefined, spec: GuideMultiblock) => {
213
+ const normalized = key?.trim().toLowerCase();
214
+ if (normalized) index[normalized] ??= spec;
215
+ };
216
+ for (const row of await listedBookRows(dataset)) {
217
+ const overview = await loadClientGuideBook(dataset, lang, row.slug);
218
+ for (const entry of overview?.entries ?? []) {
219
+ for (const page of entry.pages ?? []) {
220
+ const spec = page?.multiblock;
221
+ if (!spec) continue;
222
+ const display = asRecord(
223
+ (page as Record<string, unknown>).display,
224
+ );
225
+ put(asString(display?.name) ?? page.name ?? page.title, spec);
226
+ put(entry.id, spec);
227
+ put(entry.name, spec);
228
+ }
229
+ }
230
+ }
231
+ return index;
232
+ },
161
233
  );
162
234
 
163
235
  export async function listClientGuideBookSummaries(
164
- dataset: string,
236
+ dataset: DatasetRef,
165
237
  lang: Lang,
166
238
  ): Promise<
167
239
  Array<{
@@ -187,3 +259,4 @@ export async function listClientGuideBookSummaries(
187
259
  })
188
260
  .sort((a, b) => a.bookId.localeCompare(b.bookId));
189
261
  }
262
+
@@ -1,9 +1,10 @@
1
- import { stackDisplayName } from '@terrafirmagreg-team/game/lib/dump/assets/lang/names';
2
- import { loadClientModAtlases } from '@terrafirmagreg-team/game/lib/dump/client/atlases';
3
- import { loadClientKeybinds } from '@terrafirmagreg-team/game/lib/dump/client/keybinds';
4
- import { loadClientRecipe } from '@terrafirmagreg-team/recipe/lib/client/recipe';
5
- import { loadClientRegistry } from '@terrafirmagreg-team/game/lib/dump/client/registry';
6
- import { parseStackId } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
+ import { stackDisplayName } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
3
+ import { loadClientModAtlases } from '@terrafirmagreg-team/dump/lib/dump/client/atlases';
4
+ import { loadClientKeybinds } from '@terrafirmagreg-team/dump/lib/dump/client/keybinds';
5
+ import { guideEmbeds } from '@terrafirmagreg-team/guide/lib/embeds';
6
+ import { loadClientRegistry } from '@terrafirmagreg-team/dump/lib/dump/client/registry';
7
+ import { parseStackId } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
7
8
  import { spriteIdsFromEntry } from '@terrafirmagreg-team/guide/lib/sprites';
8
9
  import { recipeIds } from '@terrafirmagreg-team/guide/lib/recipe';
9
10
  import { asMultiblock } from '@terrafirmagreg-team/guide/lib/meta';
@@ -14,7 +15,7 @@ import type { GuideEntry, GuideEntryExtras } from '@terrafirmagreg-team/guide/ty
14
15
  import { type QuestLinks, collectPageLinks } from './links';
15
16
 
16
17
  export async function entryExtras(
17
- dataset: string,
18
+ dataset: DatasetRef,
18
19
  lang: Lang,
19
20
  langMap: Record<string, string>,
20
21
  bookModId: string,
@@ -35,7 +36,7 @@ export async function entryExtras(
35
36
  pages.map(async (page) => {
36
37
  await Promise.all(
37
38
  recipeIds(page).map(async (id) => {
38
- const recipe = await loadClientRecipe(dataset, id);
39
+ const recipe = await guideEmbeds().recipe?.load(dataset, id);
39
40
  if (recipe) recipes[id] = recipe;
40
41
  }),
41
42
  );
@@ -99,3 +100,4 @@ export async function entryExtras(
99
100
  glbs,
100
101
  };
101
102
  }
103
+
@@ -1,8 +1,9 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import { loadClientGuideBook } from '@terrafirmagreg-team/guide/lib/client/guides';
2
3
  import { uiConfig } from '@terrafirmagreg-team/ui/lib/config';
3
4
  import { categoryMap } from '@terrafirmagreg-team/guide/lib/breadcrumb';
4
5
  import { bareId, guideBookHref } from '@terrafirmagreg-team/guide/lib/paths';
5
- import { questHref } from '@terrafirmagreg-team/quest/lib/links';
6
+ import { guideEmbeds } from '@terrafirmagreg-team/guide/lib/embeds';
6
7
  import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
7
8
  import type {
8
9
  GuideMessages,
@@ -12,7 +13,7 @@ import { entryExtras } from './extras';
12
13
  import { type QuestLinks, collectTextLinks } from './links';
13
14
 
14
15
  export async function loadClientGuidePayload(
15
- dataset: string,
16
+ dataset: DatasetRef,
16
17
  lang: Lang,
17
18
  bookId: string | undefined,
18
19
  entryId: string | undefined,
@@ -75,12 +76,11 @@ export async function loadClientGuidePayload(
75
76
  )
76
77
  : undefined;
77
78
  for (const hit of Object.values(questLinks)) {
78
- hrefs.add(
79
- questHref(dataset, undefined, {
80
- category: hit.filename,
81
- id: hit.questId,
82
- }),
83
- );
79
+ const url = guideEmbeds().quest?.href(dataset, undefined, {
80
+ category: hit.filename,
81
+ id: hit.questId,
82
+ });
83
+ if (url) hrefs.add(url);
84
84
  }
85
85
 
86
86
  const previews = await uiConfig().loadPagePreviews?.(lang, langMap, hrefs) ?? {};
@@ -110,3 +110,4 @@ export async function loadClientGuidePayload(
110
110
  messages,
111
111
  };
112
112
  }
113
+
@@ -1,7 +1,8 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import {
2
- findClientQuestLocation,
3
- type ClientQuestLocation,
4
- } from '@terrafirmagreg-team/quest/lib/client/quest';
3
+ guideEmbeds,
4
+ type EmbedQuestLocation,
5
+ } from '@terrafirmagreg-team/guide/lib/embeds';
5
6
  import { classify, pageTexts } from '@terrafirmagreg-team/guide/lib/page-kind';
6
7
  import { formatGuide } from '@terrafirmagreg-team/guide/lib/format';
7
8
  import {
@@ -11,10 +12,10 @@ import {
11
12
  import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
12
13
  import type { GuidePage } from '@terrafirmagreg-team/guide/types';
13
14
 
14
- export type QuestLinks = Record<string, ClientQuestLocation>;
15
+ export type QuestLinks = Record<string, EmbedQuestLocation>;
15
16
 
16
17
  async function collectQuestLink(
17
- dataset: string,
18
+ dataset: DatasetRef,
18
19
  questLinks: QuestLinks,
19
20
  target: string | undefined,
20
21
  force = false,
@@ -23,12 +24,12 @@ async function collectQuestLink(
23
24
  const ref = parseGuideReference(target);
24
25
  if (!force && ref.kind !== 'quest') return;
25
26
  if (questLinks[ref.id]) return;
26
- const hit = await findClientQuestLocation(dataset, ref.id);
27
+ const hit = await guideEmbeds().quest?.findLocation(dataset, ref.id);
27
28
  if (hit) questLinks[ref.id] = hit;
28
29
  }
29
30
 
30
31
  export async function collectTextLinks(
31
- dataset: string,
32
+ dataset: DatasetRef,
32
33
  questLinks: QuestLinks,
33
34
  hrefs: Set<string>,
34
35
  ctx: {
@@ -58,7 +59,7 @@ export async function collectTextLinks(
58
59
  }
59
60
 
60
61
  export async function collectPageLinks(
61
- dataset: string,
62
+ dataset: DatasetRef,
62
63
  lang: Lang,
63
64
  bookModId: string,
64
65
  bookPath: string,
@@ -99,3 +100,4 @@ export async function collectPageLinks(
99
100
  if (resolved.href) hrefs.add(resolved.href);
100
101
  }
101
102
  }
103
+
package/src/lib/config.ts CHANGED
@@ -44,3 +44,4 @@ const { register: registerGuideConfig, get: guideConfig } = createConfigRegistry
44
44
  }));
45
45
 
46
46
  export { registerGuideConfig, guideConfig };
47
+
@@ -1,7 +1,7 @@
1
- import type { TaggedReference } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
2
- import type { DumpText } from '@terrafirmagreg-team/game/lib/dump/contract/text';
3
- import type { GuideBookRef } from '@terrafirmagreg-team/game/lib/dump/mods/dto';
4
- import type { DataGuidesBook } from '@terrafirmagreg-team/game/lib/dump/gen';
1
+ import type { TaggedReference } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
2
+ import type { DumpText } from '@terrafirmagreg-team/dump/lib/dump/contract/text';
3
+ import type { GuideBookRef } from '@terrafirmagreg-team/dump/lib/dump/mods/dto';
4
+ import type { DataGuidesBook } from '@terrafirmagreg-team/dump/lib/dump/gen';
5
5
 
6
6
  export type { GuideBookRef };
7
7
 
@@ -75,3 +75,4 @@ export type GuidePage = {
75
75
  rotate?: boolean;
76
76
  [key: string]: unknown;
77
77
  };
78
+