UNPKG

@rr0/cms

Version:

RR0 Content Management System (CMS)

116 lines (115 loc) 4.74 kB
import { RR0HttpDatasource } from "./rr0/RR0HttpDatasource.js"; import { HttpSource } from "./HttpSource.js"; /** * Replaces a (ul) tag from (chronology) files with case summaries from external datasources. */ export class ChronologyReplacer { constructor(mappings, renderer) { this.mappings = mappings; this.renderer = renderer; /** * Remember already processed datasources. * * @protected */ this.done = new Set(); } async replacement(context, element) { element.classList.add("indexed"); // Make sure the user can share an anchor to a list item. await this.aggregate(context, element); return element; } async aggregate(context, element) { const existingCases = []; const casesToAdd = []; for (const mapping of this.mappings) { const datasource = mapping.datasource; if (datasource instanceof RR0HttpDatasource) { datasource.http = new class extends HttpSource { async get(queryUrl, init = {}, resOut = {}) { return context.file.document.documentElement; } }(); datasource.findRows = (_doc) => { return Array.from(element.children); // Use local RR0 rows instead of remote ones }; } const datasourceKey = context.file.name + "$" + datasource.copyright; if (!this.done.has(datasourceKey)) { await this.aggregateDatasource(context, mapping, existingCases, casesToAdd); this.done.add(datasourceKey); const merge = mapping.actions.write.includes("pages"); if (merge) { const allCases = existingCases.concat(casesToAdd); for (const c of allCases) { const outDoc = context.file.document; const eventEl = outDoc.createElement("li"); await this.renderer.render(context, c, eventEl, { url: true, contentOnly: true }); element.append(eventEl); } } } } } async aggregateDatasource(context, mapping, existingCases, casesToAdd) { let fetched; const datasource = mapping.datasource; const backupDatasource = mapping.backupDatasource; if (!backupDatasource) { context.warn(`${mapping.constructor.name} has no backupDatasource`); return; } for (const readMethod of mapping.actions.read) { if (fetched) { break; } switch (readMethod) { case "backup": try { fetched = await backupDatasource.fetch(context); } catch (e) { if (e.code !== "ENOENT") { throw e; } else { context.debug("No backup file to read for" + context.time); } } break; case "fetch": fetched = await datasource.fetch(context); break; default: throw new Error(`Unsupported "${(mapping.actions.read)}" read method`); } } const fetchTime = new Date(); for (const writeMethod of mapping.actions.write) { switch (writeMethod) { case "backup": backupDatasource.save(context, fetched, fetchTime); break; case "pages": const toAddFromThisDatasource = this.merge(context, fetched, fetchTime, mapping, existingCases); casesToAdd.concat(toAddFromThisDatasource); break; } } } merge(context, sourceCases, fetchTime, mapping, existingCases) { const casesToMerge = sourceCases.map(sourceCase => mapping.mapper.map(context, sourceCase, fetchTime)); const casesToAdd = []; for (const caseToMerge of casesToMerge) { const foundExisting = existingCases.find(existingCase => existingCase.time.isEqual(caseToMerge.time) && existingCase.place === caseToMerge.place); if (foundExisting) { context.logger.debug("Merging ", caseToMerge, " into ", foundExisting); } else { casesToAdd.push(caseToMerge); } } return casesToAdd; } }