static async _initAdventureBookElements () {
		await BrewUtil2.pInit();
		const [adventureBookIndex] = await Promise.all([
			DataUtil.loadJSON(`${Renderer.get().baseUrl}data/generated/gendata-nav-adventure-book-index.json`),
			ExcludeUtil.pInitialise(),
		]);
		const brew = await BrewUtil2.pGetBrewProcessed();

		[
			{
				prop: "book",
				parentCategory: NavBar._CAT_BOOKS,
				page: "book.html",
				fnSort: SortUtil.ascSortBook.bind(SortUtil),
			},
			{
				prop: "adventure",
				page: "adventure.html",
				parentCategory: NavBar._CAT_ADVENTURES,
				fnSort: SortUtil.ascSortAdventure.bind(SortUtil),
			},
		].forEach(({prop, parentCategory, page, fnSort}) => {
			const formBrew = MiscUtil.copy(brew[prop] || []);
			formBrew.forEach(it => {
				if (it.parentSource) it.parentName = Parser.sourceJsonToFull(it.parentSource);
			});

			const metas = [...adventureBookIndex[prop], ...formBrew]
				.filter(it => !ExcludeUtil.isExcluded(UrlUtil.encodeForHash(it.id), prop, it.source, {isNoCount: true}));

			if (!metas.length) return;

			SourceUtil.ADV_BOOK_GROUPS
				.forEach(({group, displayName}) => {
					const inGroup = metas.filter(it => (it.group || "other") === group);
					if (!inGroup.length) return;

					this._addElement_divider(parentCategory);
					this._addElement_label(parentCategory, displayName, {isAddDateSpacer: true});

					const seenYears = new Set();

					inGroup
						.sort(fnSort)
						.forEach(indexMeta => {
							const year = indexMeta.published ? (new Date(indexMeta.published).getFullYear()) : null;
							const isNewYear = year != null && !seenYears.has(year);
							if (year != null) seenYears.add(year);

							if (indexMeta.parentSource) {
								if (!this._getNode(indexMeta.parentName)) {
									this._addElement_accordion(
										parentCategory,
										indexMeta.parentName,
										{
											date: isNewYear ? year : null,
											source: indexMeta.parentSource,
											isAddDateSpacer: !isNewYear,
										},
									);
								}

								let cleanName = indexMeta.name.startsWith(indexMeta.parentName)
									? indexMeta.name.slice(indexMeta.parentName.length).replace(/^:\s+/, "")
									: indexMeta.name;
								this._addElement_li(
									indexMeta.parentName,
									page,
									cleanName,
									{
										aHash: indexMeta.id,
										isAddDateSpacer: true,
										isSide: true,
										isInAccordion: true,
									},
								);

								return;
							}

							this._addElement_li(
								parentCategory,
								page,
								indexMeta.name,
								{
									aHash: indexMeta.id,
									date: isNewYear ? year : null,
									isAddDateSpacer: !isNewYear,
									source: indexMeta.source,
									isSide: true,
								},
							);
						});
				});
		});

		NavBar.highlightCurrentPage();
	}
/**
	 * Adventure/book elements are added as a second, asynchronous, step, as they require loading of:
	 * - An index JSON file.
	 * - The user's Blacklist.
	 */
Adventure/book elements are added as a second, asynchronous, step, as they require loading of:
- An index JSON file.
- The user's Blacklist.
Adventure / book elements are added as a second asynchronous step as they require loading of : - An index JSON file . - The user ' s Blacklist .
static async _initAdventureBookElements () {
		await BrewUtil2.pInit();
		const [adventureBookIndex] = await Promise.all([
			DataUtil.loadJSON(`${Renderer.get().baseUrl}data/generated/gendata-nav-adventure-book-index.json`),
			ExcludeUtil.pInitialise(),
		]);
		const brew = await BrewUtil2.pGetBrewProcessed();
		[
			{
				prop: "book",
				parentCategory: NavBar._CAT_BOOKS,
				page: "book.html",
				fnSort: SortUtil.ascSortBook.bind(SortUtil),
			},
			{
				prop: "adventure",
				page: "adventure.html",
				parentCategory: NavBar._CAT_ADVENTURES,
				fnSort: SortUtil.ascSortAdventure.bind(SortUtil),
			},
		].forEach(({prop, parentCategory, page, fnSort}) => {
			const formBrew = MiscUtil.copy(brew[prop] || []);
			formBrew.forEach(it => {
				if (it.parentSource) it.parentName = Parser.sourceJsonToFull(it.parentSource);
			});
			const metas = [...adventureBookIndex[prop], ...formBrew]
				.filter(it => !ExcludeUtil.isExcluded(UrlUtil.encodeForHash(it.id), prop, it.source, {isNoCount: true}));
			if (!metas.length) return;
			SourceUtil.ADV_BOOK_GROUPS
				.forEach(({group, displayName}) => {
					const inGroup = metas.filter(it => (it.group || "other") === group);
					if (!inGroup.length) return;
					this._addElement_divider(parentCategory);
					this._addElement_label(parentCategory, displayName, {isAddDateSpacer: true});
					const seenYears = new Set();
					inGroup
						.sort(fnSort)
						.forEach(indexMeta => {
							const year = indexMeta.published ? (new Date(indexMeta.published).getFullYear()) : null;
							const isNewYear = year != null && !seenYears.has(year);
							if (year != null) seenYears.add(year);
							if (indexMeta.parentSource) {
								if (!this._getNode(indexMeta.parentName)) {
									this._addElement_accordion(
										parentCategory,
										indexMeta.parentName,
										{
											date: isNewYear ? year : null,
											source: indexMeta.parentSource,
											isAddDateSpacer: !isNewYear,
										},
									);
								}
								let cleanName = indexMeta.name.startsWith(indexMeta.parentName)
									? indexMeta.name.slice(indexMeta.parentName.length).replace(/^:\s+/, "")
									: indexMeta.name;
								this._addElement_li(
									indexMeta.parentName,
									page,
									cleanName,
									{
										aHash: indexMeta.id,
										isAddDateSpacer: true,
										isSide: true,
										isInAccordion: true,
									},
								);
								return;
							}
							this._addElement_li(
								parentCategory,
								page,
								indexMeta.name,
								{
									aHash: indexMeta.id,
									date: isNewYear ? year : null,
									isAddDateSpacer: !isNewYear,
									source: indexMeta.source,
									isSide: true,
								},
							);
						});
				});
		});
		NavBar.highlightCurrentPage();
	}
static async _initAdventureBookElements ( ) { await BrewUtil2 . pInit ( ) ; const [ adventureBookIndex ] = await Promise . all ( [ DataUtil . loadJSON ( ` ${ Renderer . get ( ) . baseUrl } ` ) , ExcludeUtil . pInitialise ( ) , ] ) ; const brew = await BrewUtil2 . pGetBrewProcessed ( ) ; [ { prop : "book" , parentCategory : NavBar . _CAT_BOOKS , page : "book.html" , fnSort : SortUtil . ascSortBook . bind ( SortUtil ) , } , { prop : "adventure" , page : "adventure.html" , parentCategory : NavBar . _CAT_ADVENTURES , fnSort : SortUtil . ascSortAdventure . bind ( SortUtil ) , } , ] . forEach ( ( { prop , parentCategory , page , fnSort } ) => { const formBrew = MiscUtil . copy ( brew [ prop ] || [ ] ) ; formBrew . forEach ( it => { if ( it . parentSource ) it . parentName = Parser . sourceJsonToFull ( it . parentSource ) ; } ) ; const metas = [ ... adventureBookIndex [ prop ] , ... formBrew ] . filter ( it => ! ExcludeUtil . isExcluded ( UrlUtil . encodeForHash ( it . id ) , prop , it . source , { isNoCount : true } ) ) ; if ( ! metas . length ) return ; SourceUtil . ADV_BOOK_GROUPS . forEach ( ( { group , displayName } ) => { const inGroup = metas . filter ( it => ( it . group || "other" ) === group ) ; if ( ! inGroup . length ) return ; this . _addElement_divider ( parentCategory ) ; this . _addElement_label ( parentCategory , displayName , { isAddDateSpacer : true } ) ; const seenYears = new Set ( ) ; inGroup . sort ( fnSort ) . forEach ( indexMeta => { const year = indexMeta . published ? ( new Date ( indexMeta . published ) . getFullYear ( ) ) : null ; const isNewYear = year != null && ! seenYears . has ( year ) ; if ( year != null ) seenYears . add ( year ) ; if ( indexMeta . parentSource ) { if ( ! this . _getNode ( indexMeta . parentName ) ) { this . _addElement_accordion ( parentCategory , indexMeta . parentName , { date : isNewYear ? year : null , source : indexMeta . parentSource , isAddDateSpacer : ! isNewYear , } , ) ; } let cleanName = indexMeta . name . startsWith ( indexMeta . parentName ) ? indexMeta . name . slice ( indexMeta . parentName . length ) . replace ( / ^:\s+ / , "" ) : indexMeta . name ; this . _addElement_li ( indexMeta . parentName , page , cleanName , { aHash : indexMeta . id , isAddDateSpacer : true , isSide : true , isInAccordion : true , } , ) ; return ; } this . _addElement_li ( parentCategory , page , indexMeta . name , { aHash : indexMeta . id , date : isNewYear ? year : null , isAddDateSpacer : ! isNewYear , source : indexMeta . source , isSide : true , } , ) ; } ) ; } ) ; } ) ; NavBar . highlightCurrentPage ( ) ; }
Adventure/book elements are added as a second, asynchronous, step, as they require loading of:
 - An index JSON file.
Adventure / book elements are added as a second asynchronous step as they require loading of : - An index JSON file .