Skip to content

Commit

Permalink
docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Javarome committed Aug 8, 2024
1 parent 29236e6 commit 476d8c5
Show file tree
Hide file tree
Showing 88 changed files with 1,059 additions and 897 deletions.
62 changes: 62 additions & 0 deletions AbstractDataFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { RR0Data } from "./RR0Data"
import { TimeContext } from "./time/TimeContext"

import { RR0DataFactory } from "./RR0DataFactory"
import path from "path"
import fs from "fs"
import { RR0Event } from "./event/RR0Event"
import { RR0EventFactory } from "./event/RR0EventFactory"

export class AbstractDataFactory<T extends RR0Data> implements RR0DataFactory<T> {

static readonly defaultImageFileNames = ["portrait.jpg", "portrait.gif", "portrait.png", "portrait.webp"]

constructor(protected eventFactory: RR0EventFactory) {
}

createTimeFromString(timeStr: string): TimeContext | undefined {
if (timeStr) {
const time = new TimeContext({})
time.updateFromStr(timeStr)
return time
} else {
return undefined
}
}

createFromData(data: RR0Data): T {
data.time = this.createTimeFromString(data.time as any)
const events = data.events || []
const birthTime = (data as any).birthTime as unknown as string
if (birthTime) {
delete (data as any).birthTime
events.push({type: "birth", time: birthTime as any, events: []})
}
const deathTime = (data as any).deathTime as unknown as string
if (deathTime) {
delete (data as any).deathTime
events.push({type: "death", time: deathTime as any, events: []})
}
if (!data.image) {
let hasPortrait = false
for (const defaultImageFile of AbstractDataFactory.defaultImageFileNames) {
const portraitPath = path.join(data.dirName, defaultImageFile)
hasPortrait = fs.existsSync(path.join(data.dirName, defaultImageFile))
if (hasPortrait) {
events.push({type: "image", url: defaultImageFile as any, name: data.name, events: []})
break
}
}
}
data.events = this.parseEvents(events)
return data as T
}

protected parseEvents(events: RR0Data[] = []): RR0Event[] {
const parsed: RR0Event[] = []
for (const event of events) {
parsed.push(this.eventFactory.createFromData(event))
}
return parsed
}
}
85 changes: 4 additions & 81 deletions DataService.ts
Original file line number Diff line number Diff line change
@@ -1,84 +1,7 @@
import { sync as glob } from "glob-promise"
import { FileContents } from "ssg-api"
import { RR0Data } from "./RR0Data"
import { sync as glob } from "glob-promise"
import path from "path"
import { TimeContext } from "./time/TimeContext"
import { TimeElementFactory } from "./time/TimeElementFactory"

/**
* Instantiates RR0Data from (JSON) file contents.
*/
export interface RR0DataFactory<T extends RR0Data> {

/**
* The data type ("case", "people", "org", etc.)
*/
readonly type: string

/**
* The supported file names ("case.json", "index.json", etc.).
*/
readonly fileNames: string[]

/**
* Instantiate data from a file.
*
* @param file The file to read
* @return the RR0Data subtype (People, RR0Case, etc.) instance,
* or undefined if the file name/contents are not supported by this factory.
*/
create(file: FileContents): T | undefined
}

/**
* A RR0Data factory which can read either <someType>.json files of index.json with a "type": "<someType>" property.
*/
export class DefaultDataFactory<T extends RR0Data> implements RR0DataFactory<T> {

constructor(readonly type: string, readonly fileNames: string[] = [type]) {
}

create(file: FileContents): T | undefined {
const data = JSON.parse(file.contents) as RR0Data
const basename = path.basename(file.name)
let datum: T | undefined
if (data.type === this.type || this.fileNames.reduce(
(hasIt: boolean, fileName) => basename.startsWith(fileName) ? true : hasIt,
false)) {
const dirName = path.dirname(file.name)
datum = this.createFromData(dirName, data)
}
return datum
}

createTimeFromString(timeStr: string): TimeContext | undefined {
if (timeStr) {
const time = new TimeContext({})
TimeElementFactory.updateTimeFromStr(time, timeStr)
return time
} else {
return undefined
}
}

protected createFromData(dirName: string, data: any): T {
const t = Object.assign({dirName, title: ""}, data) as unknown as T
t.time = this.createTimeFromString(data.time as any)
return t
}

protected parseEvents(data: RR0Data[]) {
for (const datum of data) {
datum.time = this.createTimeFromString(datum.time)
switch (datum.type) {
default:
if (typeof datum.place === "string") {
datum.place = {name: datum.place}
}
}
}
}
}
import { DefaultDataFactory } from "./DefaultDataFactory"

/**
* Fetch RR0 data from JSON files.
Expand All @@ -91,7 +14,7 @@ export class DataService {
*
* @param factories The factories to instantiate different RR0Data types.
*/
constructor(readonly factories: RR0DataFactory<RR0Data>[]) {
constructor(readonly factories: DefaultDataFactory<RR0Data>[]) {
}

async getFromDir<T extends RR0Data = RR0Data>(dirName: string, types: string[],
Expand Down Expand Up @@ -120,7 +43,7 @@ export class DataService {
try {
data = factory.create(dataFile)
} catch (e) {
console.warn("Could not create a", factory.type, "from", dataFile)
console.warn("Could not create a", factory.type, "from", dataFile, "because of", e)
}
}
if (data) {
Expand Down
29 changes: 14 additions & 15 deletions DefaultContentVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { RR0Data } from "./RR0Data"
import { NamedPlace } from "./time/datasource/rr0/RR0CaseSummary"
import { EventRenderer } from "./time/EventRenderer"
import { People } from "./people/People"
import { PeopleFactory } from "./people/PeopleFactory"
import { RR0Event } from "./RR0Event"
import { RR0Event } from "./event/RR0Event"
import { SourceFactory } from "./source/SourceFactory"
import { Source } from "./source/Source"
import assert from "assert"

export class DefaultContentVisitor implements ContentVisitor {

Expand Down Expand Up @@ -39,10 +39,6 @@ export class DefaultContentVisitor implements ContentVisitor {
this.processURL(context, data)
const events = data.events.sort(
(event1, event2) => event1.time ? event2.time ? event1.time.isBefore(event2.time) ? -1 : 1 : -1 : 1)
if (!events.find(event => event.type === "image" && PeopleFactory.defaultPortraitFileNames.includes(
event.url as unknown as string))) {
events.push({type: "image", url: data.image as any, name: data.name, events: []})
}
const doc = context.file.document
for (const event of events) {
switch (event.type) {
Expand Down Expand Up @@ -74,23 +70,25 @@ export class DefaultContentVisitor implements ContentVisitor {

protected async processImage(context: HtmlRR0SsgContext, imageData: RR0Data) {
const doc = context.file.document
const side = context.people ? "left" : "right"
const portraitEl = doc.querySelector(`.contents figcaption`)
const caption = imageData.name
if (!portraitEl || portraitEl.textContent !== caption) {
const parentEl = doc.querySelector(".contents")
if (parentEl) {
const contents = doc.querySelector(".contents")
if (contents) {
const side = context.people ? "left" : "right"
const imgEl = contents.querySelector("img")
const captionEl = contents.querySelector("figcaption")
const caption = imageData.name
const src = imageData.url as any
if (imgEl?.src !== src || captionEl?.textContent !== caption) {
const imgEl = doc.createElement("img")
imgEl.src = imageData.url as any
imgEl.src = src
imgEl.alt = imageData.title
const figcaptionEl = doc.createElement("figcaption")
figcaptionEl.textContent = caption
const figureEl = doc.createElement("figure")
figureEl.classList.add(side, "side")
figureEl.append(imgEl)
figureEl.append(figcaptionEl)
const insertEl = parentEl.querySelector("*")
parentEl.insertBefore(figureEl, insertEl)
const insertEl = contents.querySelector("*")
contents.insertBefore(figureEl, insertEl)
}
}
}
Expand All @@ -109,6 +107,7 @@ export class DefaultContentVisitor implements ContentVisitor {
const eventP = context.file.document.createElement("p")
const eventContext = context.clone()
const eventTime = event.time
assert.ok(eventTime, "Event has no time: " + JSON.stringify(event))
const time = context.time
if (!time.min || eventTime.isBefore(time.min)) {
time.min = eventTime
Expand Down
28 changes: 28 additions & 0 deletions DefaultDataFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import path from "path"
import { RR0Data } from "./RR0Data"
import { AbstractDataFactory } from "./AbstractDataFactory"
import { FileContents } from "ssg-api"
import { RR0EventFactory } from "./event/RR0EventFactory"

/**
* A RR0Data factory which can read either <someType>.json files of index.json with a "type": "<someType>" property.
*/
export class DefaultDataFactory<T extends RR0Data> extends AbstractDataFactory<T> {

constructor(eventFactory: RR0EventFactory, readonly type: string, readonly fileNames: string[] = [type]) {
super(eventFactory)
}

create(file: FileContents): T | undefined {
const data = JSON.parse(file.contents) as RR0Data
const basename = path.basename(file.name)
let datum: T | undefined
if (data.type === this.type || this.fileNames.reduce(
(hasIt: boolean, fileName) => basename.startsWith(fileName) ? true : hasIt,
false)) {
data.dirName = path.dirname(file.name)
datum = this.createFromData(data)
}
return datum
}
}
6 changes: 4 additions & 2 deletions RR0Data.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TimeContext } from "./time/TimeContext"
import { Source } from "./source/Source"
import { NamedPlace } from "./time/datasource/rr0/RR0CaseSummary"
import { RR0Event } from "./RR0Event"
import { RR0Event } from "./event/RR0Event"

/**
* Any kind of data on RR0 (see implementing classes).
Expand All @@ -13,11 +13,13 @@ export class RR0Data {
* The data type ("people", "place", "org", "book", "case", "sighting"...)
*/
public id?: string,

/**
* A unique identifier for this data.
* // TODO: Make it mandatory
*/
readonly dirName?: string,
public dirName?: string,

/**
* The directory where the data is stored, relatively to RR0's root.
* Should end with a trailing slash ("/").
Expand Down
9 changes: 9 additions & 0 deletions RR0DataFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { RR0Data } from "./RR0Data"

/**
* Instantiates RR0Data from (JSON) file contents.
*/
export interface RR0DataFactory<T extends RR0Data> {

createFromData(data: RR0Data): T
}
3 changes: 2 additions & 1 deletion anchor/AnchorReplaceCommandTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { AnchorReplaceCommand } from "./AnchorReplaceCommand"
import { rr0TestUtil } from "../test/RR0TestUtil"
import { describe, expect, test } from "@javarome/testscript"
import { CaseAnchorHandler } from "./CaseAnchorHandler"
import { DataService, DefaultDataFactory } from "../DataService"
import { DataService } from "../DataService"
import { RR0Case } from "../science/crypto/ufo/enquete/dossier/RR0Case"
import { CaseService } from "../science/crypto/ufo/enquete/dossier/CaseService"
import { TimeRenderer } from "../time/TimeRenderer"
import { TimeReplacer } from "../time/TimeReplacer"
import { DefaultDataFactory } from "../DefaultDataFactory"

describe("AnchorReplaceCommand", () => {

Expand Down
3 changes: 1 addition & 2 deletions anchor/CaseAnchorHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { HtmlRR0SsgContext } from "../RR0SsgContext"
import { TimeTextBuilder } from "../time/TimeTextBuilder"
import { CaseService } from "../science/crypto/ufo/enquete/dossier/CaseService"
import path from "path"
import { TimeElementFactory } from "../time/TimeElementFactory"

export class CaseAnchorHandler implements AnchorHandler {

Expand All @@ -29,7 +28,7 @@ export class CaseAnchorHandler implements AnchorHandler {
}
const timeStr = aCase.time
if (timeStr && !titles.includes(timeStr)) {
TimeElementFactory.updateTimeFromStr(caseContext.time, timeStr)
caseContext.time.updateFromStr(timeStr)
titles.push(TimeTextBuilder.build(caseContext))
}
const place = aCase.place
Expand Down
17 changes: 10 additions & 7 deletions build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import { rr0Mapping } from "./time/datasource/rr0/RR0Mapping"
import { PeopleService } from "./people/PeopleService"
import { ContentVisitor, RR0ContentStep } from "./RR0ContentStep"
import { CaseAnchorHandler } from "./anchor/CaseAnchorHandler"
import { DataService, DefaultDataFactory } from "./DataService"
import { DataService } from "./DataService"
import { DataAnchorHandler } from "./anchor/DataAnchorHandler"
import { CaseSummaryRenderer } from "./time/CaseSummaryRenderer"
import { EventReplacer, EventReplacerFactory } from "./time/EventReplacerFactory"
Expand All @@ -82,6 +82,8 @@ import { DefaultContentVisitor } from "./DefaultContentVisitor"
import { PeopleFactory } from "./people/PeopleFactory"
import { OrganizationFactory } from "./org/OrganizationFactory"
import { APIFactory } from "./tech/info/soft/APIFactory"
import { RR0EventFactory } from "./event/RR0EventFactory"
import { DefaultDataFactory } from "./DefaultDataFactory"

interface RR0BuildArgs {
/**
Expand Down Expand Up @@ -188,13 +190,14 @@ timeService.getFiles().then(async (timeFiles) => {
const timeElementFactory = new TimeElementFactory(timeService.renderer)
context.setVar("timeFilesCount", timeFiles.length)
const peopleFiles = await glob("people/?/*")
const sightingFactory = new DefaultDataFactory("sighting", ["index"])
const orgFactory = new OrganizationFactory()
const caseFactory = new DefaultDataFactory("case")
const peopleFactory = new PeopleFactory()
const eventFactory = new RR0EventFactory()
const sightingFactory = new DefaultDataFactory(eventFactory, "sighting", ["index"])
const orgFactory = new OrganizationFactory(eventFactory)
const caseFactory = new DefaultDataFactory(eventFactory, "case")
const peopleFactory = new PeopleFactory(eventFactory)
const apiFactory = new APIFactory()
const bookFactory = new DefaultDataFactory("book")
const articleFactory = new DefaultDataFactory("article")
const bookFactory = new DefaultDataFactory(eventFactory, "book")
const articleFactory = new DefaultDataFactory(eventFactory, "article")
const dataService = new DataService(
[orgFactory, caseFactory, peopleFactory, bookFactory, articleFactory, sightingFactory, apiFactory])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ <h3>Massacre</h3>
pieds de Mustapha au sol.</q></p>
<section>
<h4>Face-à-face</h4>

<p>Les pas se rapprochent. Un des tireurs, <q>habillé comme un type du GIGN</q>, contourne lentement le muret et
la met en joue. Il porte une cagoule noire. <q>Je l’ai regardé. Il avait de grands yeux noirs, un regard très
doux. J’ai senti un moment de trouble chez lui, comme s’il cherchait mon nom. Mon cerveau fonctionnait très
Expand Down
2 changes: 1 addition & 1 deletion RR0Event.ts → event/RR0Event.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RR0Data } from "./RR0Data"
import { RR0Data } from "../RR0Data"

export type RR0EventType =
"birth"
Expand Down
Loading

0 comments on commit 476d8c5

Please sign in to comment.