@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.
- package/package.json +18 -19
- package/src/components/book-switcher.tsx +12 -6
- package/src/components/mdx/guide-entry.tsx +48 -0
- package/src/components/mdx/multiblock.tsx +86 -0
- package/src/{lib/tree/children.ts → components/tree/children.tsx} +13 -8
- package/src/{lib/tree/index.ts → components/tree/index.tsx} +25 -15
- package/src/components/views/browser.tsx +26 -17
- package/src/components/views/entry/pages.tsx +4 -2
- package/src/components/views/entry/view.tsx +3 -1
- package/src/components/views/kind/links.tsx +3 -2
- package/src/components/views/kind/media.tsx +6 -5
- package/src/components/views/kind/recipe.tsx +6 -51
- package/src/components/views/kind/table.tsx +4 -2
- package/src/components/views/kind/unknown.tsx +1 -0
- package/src/components/views/page/category-body.tsx +3 -1
- package/src/components/views/page/entry-body.tsx +3 -1
- package/src/components/views/page/overview-body.tsx +4 -2
- package/src/components/views/page/text.tsx +1 -0
- package/src/components/views/page/view.tsx +6 -6
- package/src/components/views/text.tsx +4 -2
- package/src/hooks/use-left-sidebar-tree.ts +15 -6
- package/src/hooks/use-tree.ts +5 -3
- package/src/lib/book/convert.ts +2 -1
- package/src/lib/book/index-rows.ts +3 -1
- package/src/lib/book/index.ts +1 -0
- package/src/lib/book/localize.ts +3 -2
- package/src/lib/book/raw.ts +5 -4
- package/src/lib/books.ts +4 -2
- package/src/lib/breadcrumb.ts +3 -1
- package/src/lib/client/guides.ts +86 -13
- package/src/lib/client-payload/extras.ts +10 -8
- package/src/lib/client-payload/index.ts +9 -8
- package/src/lib/client-payload/links.ts +10 -8
- package/src/lib/config.ts +1 -0
- package/src/lib/data/dto.ts +5 -4
- package/src/lib/data/parse.ts +4 -3
- package/src/lib/dump.ts +4 -3
- package/src/lib/embeds.ts +12 -0
- package/src/lib/format.ts +3 -2
- package/src/lib/links.ts +1 -1
- package/src/lib/markdown/book.ts +1 -0
- package/src/lib/markdown/ctx.ts +3 -1
- package/src/lib/markdown/index.ts +1 -0
- package/src/lib/markdown/page.ts +7 -8
- package/src/lib/markdown/table.ts +1 -0
- package/src/lib/markdown/text.ts +1 -0
- package/src/lib/markdown-page.ts +6 -4
- package/src/lib/messages.ts +1 -0
- package/src/lib/meta.ts +1 -0
- package/src/lib/multiblock/index.ts +1 -0
- package/src/lib/multiblock/url.ts +24 -10
- package/src/lib/names.ts +5 -3
- package/src/lib/page-kind.ts +2 -1
- package/src/lib/paths.ts +4 -2
- package/src/lib/preview.ts +8 -4
- package/src/lib/query.ts +1 -0
- package/src/lib/recipe.ts +3 -2
- package/src/lib/reference/index.ts +1 -0
- package/src/lib/reference/resolver.ts +4 -4
- package/src/lib/search/filter.ts +2 -1
- package/src/lib/search/index.ts +41 -14
- package/src/lib/sprites.ts +1 -0
- package/src/lib/table.ts +1 -0
- package/src/lib/toc.ts +3 -2
- package/src/locales/en_us.json +12 -20
- package/src/locales/ru_ru.json +12 -20
- package/src/locales.ts +1 -0
- package/src/types/index.ts +12 -10
package/src/lib/data/parse.ts
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
asTaggedReference,
|
|
3
3
|
stackIdFromRef,
|
|
4
4
|
type TaggedReference,
|
|
5
|
-
} from '@terrafirmagreg-team/
|
|
6
|
-
import { asString } from '@terrafirmagreg-team/
|
|
7
|
-
import { referenceFrom, type ResourceKind } from '@terrafirmagreg-team/
|
|
5
|
+
} from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
|
|
6
|
+
import { asString } from '@terrafirmagreg-team/dump/lib/dump/contract/read';
|
|
7
|
+
import { referenceFrom, type ResourceKind } from '@terrafirmagreg-team/dump/lib/dump/contract/kind';
|
|
8
8
|
|
|
9
9
|
function itemstackIds(value: string): string[] {
|
|
10
10
|
return value
|
|
@@ -91,3 +91,4 @@ export function classifyGuidePageType(type: string | undefined): ResourceKind |
|
|
|
91
91
|
return undefined;
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
+
|
package/src/lib/dump.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export function guideDumpHasContent(dump: {
|
|
2
|
+
mods: readonly { books: readonly unknown[] }[];
|
|
3
|
+
}): boolean {
|
|
4
4
|
return dump.mods.some((mod) => mod.books.length > 0);
|
|
5
5
|
}
|
|
6
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createConfig } from '@terrafirmagreg-team/kit/lib/config';
|
|
2
|
+
import type { SectionEmbeds } from '@terrafirmagreg-team/kit/types/embeds';
|
|
3
|
+
|
|
4
|
+
export type {
|
|
5
|
+
EmbedRecipe,
|
|
6
|
+
EmbedRecipeCardProps,
|
|
7
|
+
EmbedQuestLocation,
|
|
8
|
+
SectionEmbeds,
|
|
9
|
+
} from '@terrafirmagreg-team/kit/types/embeds';
|
|
10
|
+
|
|
11
|
+
export const { register: registerGuideEmbeds, get: guideEmbeds } =
|
|
12
|
+
createConfig<SectionEmbeds>('GuideEmbeds');
|
package/src/lib/format.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type {
|
|
|
3
3
|
GuideFormatOptions,
|
|
4
4
|
PageRendererProps,
|
|
5
5
|
} from '@terrafirmagreg-team/guide/types';
|
|
6
|
-
import { MC_FORMAT_COLORS } from '@terrafirmagreg-team/
|
|
7
|
-
import { langString } from '@terrafirmagreg-team/
|
|
6
|
+
import { MC_FORMAT_COLORS } from '@terrafirmagreg-team/dump/lib/dump/contract/text';
|
|
7
|
+
import { langString } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
|
|
8
8
|
|
|
9
9
|
type State = {
|
|
10
10
|
styles: string[];
|
|
@@ -229,3 +229,4 @@ export function keybindLabels(
|
|
|
229
229
|
title: bindName,
|
|
230
230
|
};
|
|
231
231
|
}
|
|
232
|
+
|
package/src/lib/links.ts
CHANGED
package/src/lib/markdown/book.ts
CHANGED
package/src/lib/markdown/ctx.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
|
|
1
2
|
import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
|
|
2
3
|
import type { GuideReferenceContext } from '@terrafirmagreg-team/guide/types';
|
|
3
4
|
|
|
4
5
|
export type GuideMarkdownCtx = {
|
|
5
|
-
dataset:
|
|
6
|
+
dataset: DatasetRef;
|
|
6
7
|
lang: Lang;
|
|
7
8
|
langMap: Record<string, string>;
|
|
8
9
|
keybinds?: Record<string, string>;
|
|
@@ -24,3 +25,4 @@ export function refCtx(ctx: GuideMarkdownCtx): GuideReferenceContext {
|
|
|
24
25
|
questLinks: ctx.questLinks,
|
|
25
26
|
};
|
|
26
27
|
}
|
|
28
|
+
|
package/src/lib/markdown/page.ts
CHANGED
|
@@ -5,12 +5,10 @@ import type {
|
|
|
5
5
|
import { classify, isIndexPage, pageTexts } from '@terrafirmagreg-team/guide/lib/page-kind';
|
|
6
6
|
import { guideLink } from '@terrafirmagreg-team/guide/lib/reference';
|
|
7
7
|
import { bareId } from '@terrafirmagreg-team/guide/lib/paths';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { recipeTitle } from '@terrafirmagreg-team/recipe/lib/data/parse';
|
|
11
|
-
import { texturePublicUrl } from '@terrafirmagreg-team/game/lib/dump/assets/urls';
|
|
8
|
+
import { guideEmbeds } from '@terrafirmagreg-team/guide/lib/embeds';
|
|
9
|
+
import { texturePublicUrl } from '@terrafirmagreg-team/dump/lib/dump/assets/urls';
|
|
12
10
|
import { collectItemIds } from '@terrafirmagreg-team/guide/lib/data/parse';
|
|
13
|
-
import { stackDisplayName } from '@terrafirmagreg-team/
|
|
11
|
+
import { stackDisplayName } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
|
|
14
12
|
import { type GuideMarkdownCtx, refCtx } from './ctx';
|
|
15
13
|
import { guideTextMarkdown } from './text';
|
|
16
14
|
import { tableMarkdown } from './table';
|
|
@@ -70,8 +68,8 @@ export function guidePageMarkdown(
|
|
|
70
68
|
];
|
|
71
69
|
for (const id of ids) {
|
|
72
70
|
const recipe = payload?.extras?.recipes[id];
|
|
73
|
-
const label = recipe ?
|
|
74
|
-
parts.push(`- [${label}](${
|
|
71
|
+
const label = recipe ? guideEmbeds().recipe?.title(recipe, ctx.langMap) : id;
|
|
72
|
+
parts.push(`- [${label}](${guideEmbeds().recipe?.href(ctx.dataset, undefined, { id })})`);
|
|
75
73
|
}
|
|
76
74
|
for (const raw of pageTexts(page)) parts.push(guideTextMarkdown(raw, ctx));
|
|
77
75
|
break;
|
|
@@ -131,7 +129,7 @@ export function guidePageMarkdown(
|
|
|
131
129
|
const url =
|
|
132
130
|
href ??
|
|
133
131
|
(hit
|
|
134
|
-
?
|
|
132
|
+
? guideEmbeds().quest?.href(ctx.dataset, undefined, {
|
|
135
133
|
category: hit.filename,
|
|
136
134
|
id: hit.questId,
|
|
137
135
|
})
|
|
@@ -152,3 +150,4 @@ export function guidePageMarkdown(
|
|
|
152
150
|
}
|
|
153
151
|
return parts.filter(Boolean).join('\n\n');
|
|
154
152
|
}
|
|
153
|
+
|
package/src/lib/markdown/text.ts
CHANGED
package/src/lib/markdown-page.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
|
|
2
|
+
import { registerMarkdownProvider } from '@terrafirmagreg-team/mdx/lib/markdown';
|
|
2
3
|
import { loadClientGuidePayload } from '@terrafirmagreg-team/guide/lib/client-payload';
|
|
3
|
-
import { clientDumpLang } from '@terrafirmagreg-team/
|
|
4
|
+
import { clientDumpLang } from '@terrafirmagreg-team/dump/lib/dump/client/dump';
|
|
4
5
|
import { categoryMap } from '@terrafirmagreg-team/guide/lib/breadcrumb';
|
|
5
6
|
import {
|
|
6
7
|
guideCategoryMarkdown,
|
|
@@ -13,7 +14,7 @@ import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
|
|
|
13
14
|
|
|
14
15
|
export async function guideMarkdown(
|
|
15
16
|
req: Request,
|
|
16
|
-
dataset:
|
|
17
|
+
dataset: DatasetRef | undefined,
|
|
17
18
|
lang: Lang,
|
|
18
19
|
): Promise<Response | undefined> {
|
|
19
20
|
if (!dataset) return undefined;
|
|
@@ -68,5 +69,6 @@ export async function guideMarkdown(
|
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
registerMarkdownProvider('guide', (req, { slugs, lang }) =>
|
|
71
|
-
guideMarkdown(req, slugs[0], lang),
|
|
72
|
+
guideMarkdown(req, slugs[0] ? { id: slugs[0] } : undefined, lang),
|
|
72
73
|
);
|
|
74
|
+
|
package/src/lib/messages.ts
CHANGED
package/src/lib/meta.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
|
|
2
|
+
import { asRecord, asString } from '@terrafirmagreg-team/dump/lib/dump/contract/read';
|
|
3
|
+
import { splitDumpId } from '@terrafirmagreg-team/dump/lib/dump/paths';
|
|
4
|
+
import { modelPublicUrl } from '@terrafirmagreg-team/dump/lib/dump/assets/urls';
|
|
4
5
|
import {
|
|
5
6
|
clientDumpJson,
|
|
6
7
|
dumpModelUrl,
|
|
7
|
-
|
|
8
|
-
} from '@terrafirmagreg-team/
|
|
9
|
-
import {
|
|
8
|
+
} from '@terrafirmagreg-team/dump/lib/dump/client/dump';
|
|
9
|
+
import { loadDatasetDump } from '@terrafirmagreg-team/dump/lib/dump/mods/load';
|
|
10
|
+
import { createDatasetCache } from '@terrafirmagreg-team/dump/lib/dump/reader';
|
|
11
|
+
import { loadMultiblockNameIndex } from '@terrafirmagreg-team/guide/lib/client/guides';
|
|
12
|
+
import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
|
|
10
13
|
import type { GuideMultiblock } from '@terrafirmagreg-team/guide/types';
|
|
11
14
|
|
|
12
15
|
async function sha256Hex(text: string): Promise<string> {
|
|
@@ -21,8 +24,8 @@ function inlineMultiblockHash(data: unknown): Promise<string> {
|
|
|
21
24
|
return sha256Hex(JSON.stringify(data));
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
const multiblockIndex =
|
|
25
|
-
const dump = await
|
|
27
|
+
const multiblockIndex = createDatasetCache(async (dataset: DatasetRef) => {
|
|
28
|
+
const dump = await loadDatasetDump(dataset);
|
|
26
29
|
const entries = await Promise.all(
|
|
27
30
|
(dump?.mods ?? []).map(async (ns) => {
|
|
28
31
|
const index = asRecord(
|
|
@@ -40,11 +43,21 @@ const multiblockIndex = createAsyncCache(async (dataset: string) => {
|
|
|
40
43
|
});
|
|
41
44
|
|
|
42
45
|
export async function glbFor(
|
|
43
|
-
dataset:
|
|
46
|
+
dataset: DatasetRef,
|
|
44
47
|
_bookModId: string,
|
|
45
48
|
spec: { id?: string; data?: GuideMultiblock },
|
|
49
|
+
lang?: string,
|
|
46
50
|
): Promise<string | null> {
|
|
47
|
-
if (spec.id)
|
|
51
|
+
if (spec.id) {
|
|
52
|
+
const direct = await dumpModelUrl(dataset, spec.id);
|
|
53
|
+
if (direct) return direct;
|
|
54
|
+
if (lang) {
|
|
55
|
+
const names = await loadMultiblockNameIndex(dataset, lang as Lang);
|
|
56
|
+
const named = names[spec.id.trim().toLowerCase()];
|
|
57
|
+
if (named) return glbFor(dataset, _bookModId, { data: named }, lang);
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
48
61
|
if (!spec.data) return null;
|
|
49
62
|
const hash = await inlineMultiblockHash(spec.data);
|
|
50
63
|
const index = await multiblockIndex(dataset);
|
|
@@ -59,3 +72,4 @@ export async function glbFor(
|
|
|
59
72
|
}
|
|
60
73
|
return null;
|
|
61
74
|
}
|
|
75
|
+
|
package/src/lib/names.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
|
|
2
|
+
import type { AtlasBundle } from '@terrafirmagreg-team/dump/lib/dump/assets/atlas/dto';
|
|
3
|
+
import { lookupSpriteInBundle } from '@terrafirmagreg-team/dump/lib/dump/assets/atlas/lookup';
|
|
3
4
|
import { stackDisplayName } from '@terrafirmagreg-team/game/lib/entry/display';
|
|
4
5
|
import { matchGuideEntryKey } from '@terrafirmagreg-team/guide/lib/reference/resolver';
|
|
5
6
|
import type { GuideEntryRef } from '@terrafirmagreg-team/guide/types';
|
|
6
7
|
|
|
7
8
|
export function spriteName(
|
|
8
|
-
dataset:
|
|
9
|
+
dataset: DatasetRef,
|
|
9
10
|
langMap: Record<string, string>,
|
|
10
11
|
atlases: Record<string, AtlasBundle> | undefined,
|
|
11
12
|
id: string,
|
|
@@ -33,3 +34,4 @@ export function entryLabel(
|
|
|
33
34
|
): string {
|
|
34
35
|
return entryRef(refs, id)?.name ?? stackDisplayName(langMap, id);
|
|
35
36
|
}
|
|
37
|
+
|
package/src/lib/page-kind.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GuidePage } from '@terrafirmagreg-team/guide/types';
|
|
2
|
-
import { langString } from '@terrafirmagreg-team/
|
|
2
|
+
import { langString } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
|
|
3
3
|
|
|
4
4
|
export type PageKind =
|
|
5
5
|
| 'empty'
|
|
@@ -115,3 +115,4 @@ export function isIndexPage(
|
|
|
115
115
|
return linkListOnly(text);
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
|
+
|
package/src/lib/paths.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
|
|
1
2
|
import type { Lang } from '@terrafirmagreg-team/translate/types/locale';
|
|
2
3
|
import type { GuideCategoryRef } from '@terrafirmagreg-team/guide/types';
|
|
3
4
|
import { guideHref as guideQueryHref } from '@terrafirmagreg-team/guide/lib/links';
|
|
@@ -14,7 +15,7 @@ export function bookOptionId(modId: string, bookPath: string): string {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export function guideBookHref(
|
|
17
|
-
dataset:
|
|
18
|
+
dataset: DatasetRef,
|
|
18
19
|
lang: Lang | undefined,
|
|
19
20
|
modId?: string,
|
|
20
21
|
bookPath?: string,
|
|
@@ -27,7 +28,7 @@ export function guideBookHref(
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export function guideCategoryHref(
|
|
30
|
-
dataset:
|
|
31
|
+
dataset: DatasetRef,
|
|
31
32
|
lang: Lang | undefined,
|
|
32
33
|
modId: string,
|
|
33
34
|
bookPath: string,
|
|
@@ -50,3 +51,4 @@ export function isRootCategory(
|
|
|
50
51
|
): boolean {
|
|
51
52
|
return true;
|
|
52
53
|
}
|
|
54
|
+
|
package/src/lib/preview.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { registerPreviewResolver } from '@terrafirmagreg-team/
|
|
1
|
+
import { registerPreviewResolver } from '@terrafirmagreg-team/preview/lib';
|
|
2
2
|
import { loadClientGuideBook } from '@terrafirmagreg-team/guide/lib/client/guides';
|
|
3
3
|
import { entryPreviewIcon } from '@terrafirmagreg-team/game/lib/preview';
|
|
4
|
-
import type { PreviewResolverCtx } from '@terrafirmagreg-team/
|
|
4
|
+
import type { PreviewResolverCtx } from '@terrafirmagreg-team/preview/lib';
|
|
5
5
|
import type { PagePreviewData } from '@terrafirmagreg-team/ui/types/preview';
|
|
6
6
|
|
|
7
7
|
export async function guideLinkPreview({
|
|
@@ -9,9 +9,12 @@ export async function guideLinkPreview({
|
|
|
9
9
|
query,
|
|
10
10
|
lang,
|
|
11
11
|
}: PreviewResolverCtx): Promise<PagePreviewData | undefined> {
|
|
12
|
-
const dataset =
|
|
12
|
+
const dataset = {
|
|
13
|
+
id: parts[1] ?? '',
|
|
14
|
+
version: query.get('version') ?? undefined,
|
|
15
|
+
};
|
|
13
16
|
const bookId = query.get('book');
|
|
14
|
-
if (!dataset || !bookId) return undefined;
|
|
17
|
+
if (!dataset.id || !bookId) return undefined;
|
|
15
18
|
const index = await loadClientGuideBook(dataset, lang, bookId);
|
|
16
19
|
if (!index) return undefined;
|
|
17
20
|
const entryId = query.get('entry');
|
|
@@ -31,3 +34,4 @@ export async function guideLinkPreview({
|
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
registerPreviewResolver('guide', guideLinkPreview);
|
|
37
|
+
|
package/src/lib/query.ts
CHANGED
package/src/lib/recipe.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GuidePage } from '@terrafirmagreg-team/guide/types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { EmbedRecipe } from '@terrafirmagreg-team/guide/lib/embeds';
|
|
3
3
|
import { stackDisplayName } from '@terrafirmagreg-team/game/lib/entry/display';
|
|
4
4
|
|
|
5
5
|
export function recipeIds(page: GuidePage): string[] {
|
|
@@ -10,7 +10,7 @@ export function recipeIds(page: GuidePage): string[] {
|
|
|
10
10
|
|
|
11
11
|
export function recipeNameScope(
|
|
12
12
|
langMap: Record<string, string>,
|
|
13
|
-
recipe:
|
|
13
|
+
recipe: EmbedRecipe,
|
|
14
14
|
): Record<string, string> {
|
|
15
15
|
const ids = new Set<string>([recipe.id]);
|
|
16
16
|
for (const ing of [...recipe.inputs, ...recipe.outputs]) ids.add(ing.id);
|
|
@@ -28,3 +28,4 @@ export function recipeNameScope(
|
|
|
28
28
|
for (const id of ids) names[id] = stackDisplayName(langMap, id);
|
|
29
29
|
return names;
|
|
30
30
|
}
|
|
31
|
+
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { questHref } from '@terrafirmagreg-team/quest/lib/links';
|
|
1
|
+
import { guideEmbeds } from '@terrafirmagreg-team/guide/lib/embeds';
|
|
3
2
|
import {
|
|
4
3
|
bareId,
|
|
5
4
|
guideBookHref,
|
|
@@ -67,13 +66,13 @@ export function resolveGuideReference(
|
|
|
67
66
|
case 'recipe': {
|
|
68
67
|
const href =
|
|
69
68
|
context.targets?.recipe?.(reference.id) ??
|
|
70
|
-
|
|
69
|
+
guideEmbeds().recipe?.href(context.dataset, undefined, { id: reference.id });
|
|
71
70
|
return { ...reference, href, available: Boolean(href) };
|
|
72
71
|
}
|
|
73
72
|
case 'quest': {
|
|
74
73
|
const hit = context.questLinks?.[reference.id];
|
|
75
74
|
const href = hit
|
|
76
|
-
?
|
|
75
|
+
? guideEmbeds().quest?.href(context.dataset, undefined, {
|
|
77
76
|
category: hit.filename,
|
|
78
77
|
id: hit.questId,
|
|
79
78
|
})
|
|
@@ -86,3 +85,4 @@ export function resolveGuideReference(
|
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
87
|
}
|
|
88
|
+
|
package/src/lib/search/filter.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerSearchHitFilter } from '@terrafirmagreg-team/
|
|
1
|
+
import { registerSearchHitFilter } from '@terrafirmagreg-team/search/lib';
|
|
2
2
|
import type { SortedResult } from '@terrafirmagreg-team/ui/types/search';
|
|
3
3
|
|
|
4
4
|
export function guideHitFilter(
|
|
@@ -15,3 +15,4 @@ export function guideHitFilter(
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
registerSearchHitFilter('guide', guideHitFilter);
|
|
18
|
+
|
package/src/lib/search/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
|
|
1
2
|
import type { AdvancedIndex } from 'fumadocs-core/search/server';
|
|
2
|
-
import { dumpTextString, langString } from '@terrafirmagreg-team/
|
|
3
|
+
import { dumpTextString, langString } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
|
|
4
|
+
import { formatGuide } from '@terrafirmagreg-team/guide/lib/format';
|
|
3
5
|
import { isIndexPage } from '@terrafirmagreg-team/guide/lib/page-kind';
|
|
4
|
-
import type { DumpIndex } from '@terrafirmagreg-team/
|
|
6
|
+
import type { DumpIndex } from '@terrafirmagreg-team/dump/lib/dump/mods/dto';
|
|
5
7
|
|
|
6
8
|
export type GuideIndex = AdvancedIndex & { locale: string };
|
|
7
9
|
|
|
@@ -12,25 +14,41 @@ export interface DumpSource {
|
|
|
12
14
|
|
|
13
15
|
type DumpTextNode = Parameters<typeof dumpTextString>[1];
|
|
14
16
|
|
|
17
|
+
function plainText(raw: string, macros?: Record<string, string>): string {
|
|
18
|
+
let out = '';
|
|
19
|
+
for (const node of formatGuide(raw, { macros })) {
|
|
20
|
+
if (node.type === 'break') out += '\n';
|
|
21
|
+
else out += (node.type === 'command' ? node.label : undefined) ?? node.value;
|
|
22
|
+
}
|
|
23
|
+
return out
|
|
24
|
+
.replace(/\s*\$\([^)]*$/, '')
|
|
25
|
+
.replace(/[ \t]*\n[ \t]*/g, '\n')
|
|
26
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
27
|
+
.trim();
|
|
28
|
+
}
|
|
29
|
+
|
|
15
30
|
function resolveText(
|
|
16
31
|
map: Record<string, string>,
|
|
17
32
|
node: unknown,
|
|
33
|
+
macros?: Record<string, string>,
|
|
18
34
|
): string | undefined {
|
|
19
35
|
if (typeof node === 'string') {
|
|
20
36
|
const bare =
|
|
21
37
|
node.startsWith('{') && node.endsWith('}')
|
|
22
38
|
? node.slice(1, -1).trim()
|
|
23
39
|
: undefined;
|
|
24
|
-
|
|
40
|
+
const resolved = langString(map, node) ?? bare ?? (bare ? undefined : node);
|
|
41
|
+
return resolved ? plainText(resolved, macros) || undefined : undefined;
|
|
25
42
|
}
|
|
26
43
|
if (Array.isArray(node)) {
|
|
27
44
|
const parts = node
|
|
28
|
-
.map((item) => resolveText(map, item))
|
|
45
|
+
.map((item) => resolveText(map, item, macros))
|
|
29
46
|
.filter((part): part is string => Boolean(part));
|
|
30
47
|
return parts.length ? parts.join('\n') : undefined;
|
|
31
48
|
}
|
|
32
49
|
if (node && typeof node === 'object') {
|
|
33
|
-
|
|
50
|
+
const resolved = dumpTextString(map, node as DumpTextNode);
|
|
51
|
+
return resolved ? plainText(resolved, macros) || undefined : undefined;
|
|
34
52
|
}
|
|
35
53
|
return undefined;
|
|
36
54
|
}
|
|
@@ -49,40 +67,47 @@ interface RawEntry {
|
|
|
49
67
|
interface RawBook {
|
|
50
68
|
id?: unknown;
|
|
51
69
|
entries?: Record<string, string>;
|
|
70
|
+
macros?: Record<string, string>;
|
|
52
71
|
}
|
|
53
72
|
|
|
54
73
|
function entryIndex(
|
|
55
|
-
dataset:
|
|
74
|
+
dataset: DatasetRef,
|
|
56
75
|
bookId: string,
|
|
57
76
|
entryId: string,
|
|
58
77
|
entry: RawEntry,
|
|
59
78
|
map: Record<string, string>,
|
|
60
79
|
lang: string,
|
|
80
|
+
macros?: Record<string, string>,
|
|
61
81
|
) {
|
|
62
82
|
const title =
|
|
63
|
-
resolveText(map, entry.display?.name
|
|
83
|
+
resolveText(map, entry.display?.name, macros) ??
|
|
84
|
+
entryId.split('/').pop() ??
|
|
85
|
+
entryId;
|
|
64
86
|
const contents = (entry.pages ?? [])
|
|
65
87
|
.map((page) => {
|
|
66
88
|
if (isIndexPage(page, map)) return null;
|
|
67
|
-
const heading = resolveText(map, page.title);
|
|
68
|
-
const content = resolveText(map, page.texts);
|
|
89
|
+
const heading = resolveText(map, page.title, macros);
|
|
90
|
+
const content = resolveText(map, page.texts, macros);
|
|
69
91
|
return content ? { heading: heading ?? title, content } : null;
|
|
70
92
|
})
|
|
71
93
|
.filter((c): c is { heading: string; content: string } => c !== null);
|
|
72
94
|
const body = contents.map((c) => c.content).join('\n');
|
|
73
95
|
if (!body && !title) return null;
|
|
96
|
+
const params = new URLSearchParams({ book: bookId, entry: entryId });
|
|
97
|
+
if (dataset.version) params.set('version', dataset.version);
|
|
98
|
+
const refKey = `${dataset.id}/${dataset.version ?? ''}`;
|
|
74
99
|
return {
|
|
75
100
|
title,
|
|
76
|
-
url: `/guide/${dataset}
|
|
77
|
-
id: `guide:${
|
|
78
|
-
tag: `guide:${
|
|
101
|
+
url: `/guide/${dataset.id}?${params}`,
|
|
102
|
+
id: `guide:${refKey}:${bookId}:${entryId}:${lang}`,
|
|
103
|
+
tag: `guide:${refKey}`,
|
|
79
104
|
locale: lang,
|
|
80
105
|
structuredData: { headings: [], contents },
|
|
81
106
|
};
|
|
82
107
|
}
|
|
83
108
|
|
|
84
109
|
async function bookIndexes(
|
|
85
|
-
dataset:
|
|
110
|
+
dataset: DatasetRef,
|
|
86
111
|
dir: string,
|
|
87
112
|
bookId: string,
|
|
88
113
|
langs: string[],
|
|
@@ -123,6 +148,7 @@ async function bookIndexes(
|
|
|
123
148
|
entry,
|
|
124
149
|
maps.get(lang) ?? {},
|
|
125
150
|
lang,
|
|
151
|
+
book.macros,
|
|
126
152
|
);
|
|
127
153
|
if (index) out.push(index);
|
|
128
154
|
}
|
|
@@ -131,7 +157,7 @@ async function bookIndexes(
|
|
|
131
157
|
}
|
|
132
158
|
|
|
133
159
|
export async function guideSearchIndexes(
|
|
134
|
-
dataset:
|
|
160
|
+
dataset: DatasetRef,
|
|
135
161
|
dump: DumpIndex,
|
|
136
162
|
source: DumpSource,
|
|
137
163
|
): Promise<GuideIndex[]> {
|
|
@@ -154,3 +180,4 @@ export async function guideSearchIndexes(
|
|
|
154
180
|
return true;
|
|
155
181
|
});
|
|
156
182
|
}
|
|
183
|
+
|
package/src/lib/sprites.ts
CHANGED
package/src/lib/table.ts
CHANGED
package/src/lib/toc.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TOCItemType } from 'fumadocs-core/toc';
|
|
2
|
-
import type { TaggedReference } from '@terrafirmagreg-team/
|
|
3
|
-
import { langString } from '@terrafirmagreg-team/
|
|
2
|
+
import type { TaggedReference } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
|
|
3
|
+
import { langString } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
|
|
4
4
|
import { stackDisplayName } from '@terrafirmagreg-team/game/lib/entry/display';
|
|
5
5
|
import {
|
|
6
6
|
classifyGuidePageType,
|
|
@@ -135,3 +135,4 @@ export function guideToc(
|
|
|
135
135
|
return [{ title, url: `#${anchors[i]}`, depth: 2 }];
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
|
+
|
package/src/locales/en_us.json
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"guide":
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
"
|
|
14
|
-
"select_book": "Select book"
|
|
15
|
-
},
|
|
16
|
-
"sections": {
|
|
17
|
-
"guide": "Guide",
|
|
18
|
-
"desc": {
|
|
19
|
-
"guide": "Gameplay guide"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
2
|
+
"Entity preview unavailable(guide.entity_unavailable)": "Entity preview unavailable",
|
|
3
|
+
"Entry not found(guide.entry_missing)": "Entry not found",
|
|
4
|
+
"Gameplay guide(sections.desc.guide)": "Gameplay guide",
|
|
5
|
+
"Guide(sections.guide)": "Guide",
|
|
6
|
+
"No recipes(guide.recipe_empty)": "No recipes",
|
|
7
|
+
"Objective(guide.objective)": "Objective",
|
|
8
|
+
"Open(guide.link)": "Open",
|
|
9
|
+
"Quest(guide.quest)": "Quest",
|
|
10
|
+
"Related(guide.related)": "Related",
|
|
11
|
+
"Select book(ui.select_book)": "Select book",
|
|
12
|
+
"{count} entries(guide.entry_count)": "{count} entries",
|
|
13
|
+
"{count} pages(guide.page_count)": "{count} pages"
|
|
22
14
|
}
|