Files
5etools-mirror-2.github.io/js/utils-generate-tables-data.js
TheGiddyLimit 8117ebddc5 v1.198.1
2024-01-01 19:34:49 +00:00

324 lines
8.2 KiB
JavaScript

"use strict";
class UtilGenTables {
static _getTableSectionIndex (sectionOrders, chapterName, sectionName) {
((sectionOrders[chapterName] =
sectionOrders[chapterName] || {})[sectionName] =
sectionOrders[chapterName][sectionName] || 1);
const val = sectionOrders[chapterName][sectionName];
sectionOrders[chapterName][sectionName]++;
return val;
}
/**
* @param opts
* @param opts.sectionOrders
* @param opts.path
* @param opts.tmpMeta
* @param opts.section
* @param opts.data
* @param opts.stacks
* @param opts.isRequireIncludes
*/
static _doSearch (opts) {
const {sectionOrders, path, tmpMeta, section, data, stacks, isRequireIncludes} = opts;
if (data.data && data.data.tableIgnore) return;
if (data.entries) {
const nxtSection = data.name || section;
if (data.name || data.page) {
const {name, page} = data;
path.push({name, page});
}
data.entries.forEach(ent => this._doSearch({...opts, section: nxtSection, data: ent}));
if (data.name || data.page) path.pop();
} else if (data.items) {
if (data.name || data.page) {
const {name, page} = data;
path.push({name, page});
}
data.items.forEach(item => this._doSearch({...opts, data: item}));
if (data.name || data.page) path.pop();
} else if (data.type === "table" || data.type === "tableGroup") {
if (isRequireIncludes && !(data.data && data.data[VeCt.ENTDATA_TABLE_INCLUDE])) return;
const cpy = MiscUtil.copy(data);
cpy._tmpMeta = MiscUtil.copy(tmpMeta);
cpy.path = MiscUtil.copy(path);
cpy.section = section;
cpy.sectionIndex = this._getTableSectionIndex(sectionOrders, tmpMeta.name, section);
stacks[data.type].push(cpy);
}
}
static _getCleanSectionName (name) {
return name.replace(/^(?:Step )?[-\d]+[:.]?\s*/, "");
}
static _isSectionInTitle (sections, title) {
const lowTitle = title.toLowerCase();
return sections.some(section => lowTitle.includes(section.toLowerCase()));
}
static _mutDataAddPage (table) {
for (let i = table.path.length - 1; i >= 0; --i) {
if (table.path[i].page) {
table.page = table.path[i].page;
break;
}
}
}
static _mutCleanData (table) {
delete table.path;
delete table.section;
delete table.sectionIndex;
if (table._tmpMeta.metaType === "adventure-book") {
table.chapter = table._tmpMeta;
delete table._tmpMeta;
// clean chapter
if (table.data && table.data.tableChapterIgnore) {
delete table.chapter;
} else {
const chapterOut = {};
chapterOut.name = table.chapter.name;
chapterOut.ordinal = table.chapter.ordinal;
chapterOut.index = table.chapter.index;
table.chapter = chapterOut;
}
} else if (table._tmpMeta.metaType === "class") {
table.parentEntity = {
type: table._tmpMeta.metaType,
name: table._tmpMeta.className,
source: table._tmpMeta.classSource,
};
delete table._tmpMeta;
} else if (table._tmpMeta.metaType === "subclass") {
table.parentEntity = {
type: table._tmpMeta.metaType,
name: table._tmpMeta.subclassName,
shortName: table._tmpMeta.subclassShortName,
source: table._tmpMeta.subclassSource,
className: table._tmpMeta.className,
classSource: table._tmpMeta.classSource,
};
delete table._tmpMeta;
} else {
table.parentEntity = {
type: table._tmpMeta.metaType,
name: table._tmpMeta.name,
source: table._tmpMeta.source,
};
delete table._tmpMeta;
}
if (table.type === "table") delete table.type;
delete table.data;
if (table.name) table.name = Renderer.stripTags(table.name);
}
/**
* @param doc
* @param opts
* @param opts.headProp
* @param opts.bodyProp
* @param [opts.isRequireIncludes]
*/
static getAdventureBookTables (doc, opts) {
const sectionOrders = {};
const stacks = {table: [], tableGroup: []};
if (!(doc[opts.headProp] && doc[opts.bodyProp])) return;
doc[opts.bodyProp].data.forEach((chapter, ixChapter) => {
const tmpMeta = MiscUtil.copy(doc[opts.headProp].contents[ixChapter]);
tmpMeta.index = ixChapter;
tmpMeta.metaType = "adventure-book";
const path = [];
this._doSearch({
sectionOrders,
path,
tmpMeta: tmpMeta,
section: doc[opts.headProp].name,
data: chapter,
stacks: stacks,
isRequireIncludes: opts.isRequireIncludes,
});
});
stacks.table.forEach(tbl => {
const cleanSectionNames = tbl.path.filter(ent => ent.name).map(ent => this._getCleanSectionName(ent.name));
if (tbl.data && tbl.data.tableNamePrefix && tbl.caption) {
tbl.name = `${tbl.data.tableNamePrefix}; ${tbl.caption}`;
} else if (tbl.data && tbl.data.tableName) {
tbl.name = tbl.data.tableName;
} else if (tbl.caption) {
if (this._isSectionInTitle(cleanSectionNames, tbl.caption) || (tbl.data && tbl.data.skipSectionPrefix)) {
tbl.name = tbl.caption;
} else {
tbl.name = cleanSectionNames.length ? `${cleanSectionNames.last()}; ${tbl.caption}` : tbl.caption;
}
} else {
// If this is the only table in this section, remove the numerical suffix
if (tbl.sectionIndex === 1 && sectionOrders[tbl._tmpMeta.name][tbl.section] === 2) {
tbl.name = cleanSectionNames.last();
} else {
tbl.name = `${cleanSectionNames.last()}; ${tbl.sectionIndex}`;
}
}
this._mutDataAddPage(tbl);
tbl.source = doc[opts.headProp].source || doc[opts.headProp].id;
this._mutCleanData(tbl);
});
stacks.tableGroup.forEach(tg => {
const cleanSections = tg.path.filter(ent => ent.name).map(ent => this._getCleanSectionName(ent.name));
if (!tg.name) throw new Error("Group had no name!");
if (!this._isSectionInTitle(cleanSections, tg.name)) {
tg.name = `${cleanSections.last()}; ${tg.name}`;
}
this._mutDataAddPage(tg);
tg.source = doc[opts.headProp].source || doc[opts.headProp].id;
this._mutCleanData(tg);
});
return stacks;
}
static getClassTables (cls) {
const sectionOrders = {};
const stacks = {table: [], tableGroup: []};
const path = [];
cls.classFeatures.forEach((lvl, lvlI) => {
const tmpMeta = {
metaType: "class",
className: cls.name,
classSource: cls.source || Parser.SRC_PHB,
level: lvlI + 1,
};
lvl.forEach(feat => this._doSearch({
sectionOrders,
path,
tmpMeta,
section: cls.name,
data: feat,
stacks: stacks,
isRequireIncludes: true,
// Used to deduplicate headers
name: cls.name,
}));
});
stacks.table.forEach(it => {
it.name = it.caption;
it.source = it._tmpMeta.subclassSource || it._tmpMeta.classSource;
it.srd = !!cls.srd;
this._mutDataAddPage(it);
this._mutCleanData(it);
});
return stacks;
}
static getSubclassTables (sc) {
const sectionOrders = {};
const stacks = {table: [], tableGroup: []};
const path = [];
sc.subclassFeatures.forEach(lvl => {
const level = lvl[0].level;
const tmpMeta = {
metaType: "subclass",
className: sc.className,
classSource: sc.classSource || Parser.SRC_PHB,
level,
subclassName: sc.name,
subclassShortName: sc.shortName,
subclassSource: sc.source || sc.classSource || Parser.SRC_PHB,
// Used to deduplicate headers
name: sc.name,
};
lvl.forEach(feat => this._doSearch({
sectionOrders,
path,
tmpMeta,
section: sc.className,
data: feat,
stacks: stacks,
isRequireIncludes: true,
}));
});
stacks.table.forEach(it => {
it.name = it.caption;
it.source = it._tmpMeta.subclassSource || it._tmpMeta.classSource;
it.srd = !!sc.srd;
this._mutDataAddPage(it);
this._mutCleanData(it);
});
return stacks;
}
static getGenericTables (entity, metaType, ...props) {
const sectionOrders = {};
const stacks = {table: [], tableGroup: []};
const path = [];
props.forEach(prop => {
if (!entity[prop]) return;
const tmpMeta = {
metaType: metaType,
name: entity.name,
source: entity.source,
};
entity[prop].forEach(ent => {
this._doSearch({
sectionOrders,
path,
tmpMeta,
section: entity.name,
data: ent,
stacks: stacks,
isRequireIncludes: true,
// Used to deduplicate headers
name: entity.name,
});
});
});
stacks.table.forEach(it => {
it.name = it.caption;
it.source = it._tmpMeta.source;
this._mutDataAddPage(it);
this._mutCleanData(it);
});
return stacks;
}
}
globalThis.UtilGenTables = UtilGenTables;