@rr0/cms 0.3.16 → 0.3.17

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.
Files changed (51) hide show
  1. package/dist/{BuildContext.d.ts → CMSContext.d.ts} +1 -1
  2. package/dist/{RR0Build.d.ts → CMSGenerator.d.ts} +30 -10
  3. package/dist/{RR0Build.js → CMSGenerator.js} +92 -91
  4. package/dist/CMSGenerator.test.d.ts +1 -0
  5. package/dist/{RR0Build.test.js → CMSGenerator.test.js} +39 -27
  6. package/dist/{DefaultContentVisitor.d.ts → DataContentVisitor.d.ts} +4 -1
  7. package/dist/{DefaultContentVisitor.js → DataContentVisitor.js} +4 -1
  8. package/dist/OpenGraphCommand.js +1 -1
  9. package/dist/RR0Context.d.ts +4 -1
  10. package/dist/RR0Context.js +3 -2
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.js +3 -2
  13. package/dist/org/eu/fr/cnes/geipan/geipan/GeipanFileDatasource.d.ts +1 -1
  14. package/dist/org/eu/fr/cnes/geipan/geipan/GeipanRR0Mapping.d.ts +2 -2
  15. package/dist/search/SearchVisitor.js +1 -2
  16. package/dist/test/RR0TestUtil.d.ts +2 -2
  17. package/dist/test/RR0TestUtil.js +1 -1
  18. package/dist/time/SsiTitleReplaceCommand.d.ts +4 -0
  19. package/dist/time/SsiTitleReplaceCommand.js +16 -11
  20. package/dist/time/TimeDirectoryStep.d.ts +46 -0
  21. package/dist/time/TimeDirectoryStep.js +88 -0
  22. package/dist/time/TimeDirectoryStep.test.js +36 -0
  23. package/dist/time/TimeService.d.ts +1 -3
  24. package/dist/time/TimeService.js +4 -11
  25. package/dist/time/datasource/CsvFileSource.d.ts +1 -1
  26. package/dist/time/datasource/CsvMapper.d.ts +5 -3
  27. package/dist/time/datasource/CsvMapper.js +17 -12
  28. package/dist/time/datasource/CsvMapper.test.js +29 -0
  29. package/dist/time/datasource/FileSource.d.ts +1 -1
  30. package/dist/time/datasource/FileSource.js +1 -0
  31. package/dist/time/datasource/baseovnifrance/BaseOvniFranceRR0Mapping.d.ts +2 -2
  32. package/dist/time/datasource/fufora/FuforaRR0Mapping.d.ts +2 -2
  33. package/dist/time/datasource/nuforc/NuforcRR0Mapping.d.ts +2 -2
  34. package/dist/time/datasource/rr0/RR0CaseMapping.d.ts +2 -2
  35. package/dist/time/datasource/rr0/RR0Datasource.d.ts +0 -3
  36. package/dist/time/datasource/rr0/RR0Datasource.js +3 -6
  37. package/dist/time/datasource/rr0/RR0Datasource.test.d.ts +2 -2
  38. package/dist/time/datasource/rr0/RR0Datasource.test.js +4 -2
  39. package/dist/time/datasource/rr0/RR0FileDatasource.d.ts +1 -1
  40. package/dist/time/datasource/rr0/RR0FileDatasource.test.d.ts +1 -0
  41. package/dist/time/datasource/rr0/RR0FileDatasource.test.js +14 -0
  42. package/dist/time/datasource/rr0/RR0Mapping.d.ts +2 -2
  43. package/dist/time/datasource/sceau/SceauDatasource.test.d.ts +2 -2
  44. package/dist/time/datasource/sceau/SceauRR0Mapping.d.ts +2 -2
  45. package/dist/time/datasource/ufo-search/UfoSearchMapping.d.ts +2 -2
  46. package/dist/time/datasource/urecat/UrecatRR0Mapping.d.ts +2 -2
  47. package/dist/time/html/TimeRenderer.js +3 -2
  48. package/dist/time/html/TimeReplacer.test.js +0 -1
  49. package/package.json +3 -3
  50. /package/dist/{BuildContext.js → CMSContext.js} +0 -0
  51. /package/dist/{RR0Build.test.d.ts → time/TimeDirectoryStep.test.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { CityService, DepartmentService } from "./org";
2
2
  import { CountryService } from "./org/country/CountryService";
3
- export interface BuildContext {
3
+ export interface CMSContext {
4
4
  cityService: CityService;
5
5
  departmentService: DepartmentService;
6
6
  countryService: CountryService;
@@ -1,16 +1,18 @@
1
- import { RR0CaseMapping, TimeRenderer, TimeService, TimeTextBuilder, TimeUrlBuilder } from "./time";
1
+ import { HttpSource, RR0CaseMapping, TimeElementFactory, TimeRenderer, TimeReplacer, TimeService, TimeTextBuilder, TimeUrlBuilder } from "./time";
2
2
  import { CaseFactory } from "./science/index.js";
3
3
  import { CityService, DepartmentService, OrganizationService } from "./org/index.js";
4
4
  import { HtmlRR0Context, RR0ContextImpl } from "./RR0Context.js";
5
5
  import { FileWriteConfig } from "ssg-api";
6
6
  import { PeopleDirectoryStepOptions } from "./people";
7
- import { AllDataService, PeopleFactory } from "@rr0/data";
7
+ import { PersistentSourceRegistry, SourceRenderer, SourceReplacerFactory } from "./source";
8
+ import { AllDataService, PeopleFactory, PeopleService } from "@rr0/data";
8
9
  import { GooglePlaceService } from "@rr0/place";
10
+ import { PeopleHtmlRenderer } from "./people/PeopleHtmlRenderer";
9
11
  import { CountryService } from "./org/country/CountryService";
10
- import { BuildContext } from "./BuildContext";
12
+ import { CMSContext } from "./CMSContext";
11
13
  import { ReplaceCommand } from "ssg-api/dist/src/step/content/replace";
12
14
  import { TimeOptions } from "./time/TimeOptions";
13
- export interface RR0BuildOptions {
15
+ export interface CMSGeneratorOptions {
14
16
  contentRoots: string[];
15
17
  copies: string[];
16
18
  outDir: string;
@@ -27,9 +29,9 @@ export interface RR0BuildOptions {
27
29
  directoryExcluded: string[];
28
30
  directoryOptions: PeopleDirectoryStepOptions;
29
31
  mappings: RR0CaseMapping<any>[];
30
- contentReplacers: ReplaceCommand<HtmlRR0Context>[];
32
+ contentReplacers?: ReplaceCommand<HtmlRR0Context>[];
31
33
  }
32
- export interface RR0BuildArgs {
34
+ export interface CMSGenerationOptions {
33
35
  /**
34
36
  * Configuration file name.
35
37
  */
@@ -56,8 +58,8 @@ export interface RR0BuildArgs {
56
58
  */
57
59
  force?: string;
58
60
  }
59
- export declare class RR0Build implements BuildContext {
60
- protected options: RR0BuildOptions;
61
+ export declare class CMSGenerator implements CMSContext {
62
+ protected options: CMSGeneratorOptions;
61
63
  readonly config: FileWriteConfig;
62
64
  readonly context: RR0ContextImpl;
63
65
  readonly placeService: GooglePlaceService;
@@ -72,6 +74,24 @@ export declare class RR0Build implements BuildContext {
72
74
  readonly timeService: TimeService;
73
75
  readonly timeRenderer: TimeRenderer;
74
76
  readonly timeUrlBuilder: TimeUrlBuilder;
75
- constructor(options: RR0BuildOptions);
76
- run(args: RR0BuildArgs): Promise<void>;
77
+ readonly http: HttpSource;
78
+ constructor(options: CMSGeneratorOptions);
79
+ generate(args: CMSGenerationOptions): Promise<void>;
80
+ protected setupSources(timeTextBuilder: TimeTextBuilder, timeFormat: Intl.DateTimeFormatOptions): {
81
+ sourceRenderer: SourceRenderer;
82
+ sourceFactory: PersistentSourceRegistry;
83
+ sourceReplacerFactory: SourceReplacerFactory;
84
+ };
85
+ protected setupTime(context: RR0ContextImpl): {
86
+ timeFiles: string[];
87
+ timeElementFactory: TimeElementFactory;
88
+ timeReplacer: TimeReplacer;
89
+ };
90
+ protected peopleSetup(context: RR0ContextImpl, peopleRenderer: PeopleHtmlRenderer, copies: string[]): Promise<{
91
+ peopleService: PeopleService;
92
+ peopleSteps: import("./people").PeopleDirectoryStep[];
93
+ copies: string[];
94
+ }>;
95
+ private setupNotes;
96
+ private setupCases;
77
97
  }
@@ -2,12 +2,11 @@ import path from "path";
2
2
  import fs from "fs";
3
3
  import { CaseSummaryRenderer, ChronologyReplacerFactory, CsvMapper, EventReplacer, EventReplacerFactory, HttpSource, SsiTitleReplaceCommand, TimeElementFactory, TimeLinkDefaultHandler, TimeRenderer, TimeReplacer, TimeReplacerFactory, TimeService, TimeTextBuilder, TimeUrlBuilder } from "./time";
4
4
  import { CaseDirectoryStep, CaseFactory, CaseService } from "./science/index.js";
5
- import { PlaceReplacerFactory } from "./place/index.js";
6
5
  import { cities, CityService, CmsOrganizationFactory, countries, departments, DepartmentService, OrganizationService, regions, RegionService } from "./org/index.js";
7
6
  import { RR0ContextImpl } from "./RR0Context.js";
8
7
  import { HtmlTable } from "./util/index.js";
9
8
  import { ClassDomReplaceCommand, CopyStep, DomReplaceCommand, HtAccessToNetlifyConfigReplaceCommand, HtmlFileContents, Ssg, SsiIncludeReplaceCommand } from "ssg-api";
10
- import { AuthorReplaceCommand, PeopleDirectoryStepFactory, PeopleReplacerFactory, WitnessReplacerFactory } from "./people";
9
+ import { AuthorReplaceCommand, PeopleDirectoryStepFactory, PeopleReplacerFactory } from "./people";
11
10
  import { PersistentSourceRegistry, SourceFileCounter, SourceIndexStep, SourceRenderer, SourceReplacer, SourceReplacerFactory } from "./source";
12
11
  import { NoteFileCounter, NoteRenderer, NoteReplacer, NoteReplacerFactory } from "./note/index.js";
13
12
  import { AnchorReplaceCommand, CaseAnchorHandler, DataAnchorHandler } from "./anchor/index.js";
@@ -17,11 +16,9 @@ import { ImageCommand } from "./ImageCommand.js";
17
16
  import { SearchIndexStep, SearchVisitor } from "./search/index.js";
18
17
  import { OpenGraphCommand } from "./OpenGraphCommand.js";
19
18
  import { BookContentVisitor, BookDirectoryStep } from "./book/index.js";
20
- import { IndexedReplacerFactory } from "./index/IndexedReplacerFactory.js";
21
- import { APIFactory, CodeReplacerFactory } from "./tech/index.js";
19
+ import { APIFactory } from "./tech/index.js";
22
20
  import { RR0ContentStep } from "./RR0ContentStep.js";
23
- import { UnitReplaceCommand } from "./value/index.js";
24
- import { DefaultContentVisitor } from "./DefaultContentVisitor.js";
21
+ import { DataContentVisitor } from "./DataContentVisitor.js";
25
22
  import { TimeContext } from "@rr0/time";
26
23
  import { writeFile } from "@javarome/fileutil";
27
24
  import { AllDataService, EventDataFactory, PeopleFactory, PeopleService, RR0EventFactory, TypedDataFactory } from "@rr0/data";
@@ -41,7 +38,7 @@ const outputFunc = async (context, outFile) => {
41
38
  context.error(outFile.name, e);
42
39
  }
43
40
  };
44
- export class RR0Build {
41
+ export class CMSGenerator {
45
42
  constructor(options) {
46
43
  this.options = options;
47
44
  this.config = {
@@ -49,10 +46,6 @@ export class RR0Build {
49
46
  return path.join(options.outDir, context.file.name);
50
47
  }
51
48
  };
52
- const timeContext = new TimeContext();
53
- const context = this.context = new RR0ContextImpl(options.locale, timeContext, this.config);
54
- context.setVar("mapsApiKey", options.googleMapsApiKey);
55
- context.setVar("mail", options.mail);
56
49
  const eventFactory = new RR0EventFactory();
57
50
  const orgFactory = new CmsOrganizationFactory(eventFactory);
58
51
  const countryService = this.countryService = new CountryService(countries, "org", orgFactory, undefined);
@@ -65,7 +58,7 @@ export class RR0Build {
65
58
  const timeTextBuilder = this.timeTextBuilder = new TimeTextBuilder(options.timeFormat);
66
59
  const timeOptions = options.timeOptions;
67
60
  const timeUrlBuilder = this.timeUrlBuilder = new TimeUrlBuilder(timeOptions);
68
- const sightingFactory = new EventDataFactory(eventFactory, "sighting", ["index"]);
61
+ const sightingFactory = new EventDataFactory(eventFactory, ["sighting"], ["index"]);
69
62
  const caseFactory = this.caseFactory = new CaseFactory(eventFactory);
70
63
  const peopleFactory = this.peopleFactory = new PeopleFactory(eventFactory);
71
64
  const apiFactory = new APIFactory(eventFactory);
@@ -78,76 +71,37 @@ export class RR0Build {
78
71
  });
79
72
  this.timeRenderer = new TimeRenderer(timeUrlBuilder, timeTextBuilder);
80
73
  this.timeService = new TimeService(dataService, timeOptions);
74
+ this.http = new HttpSource();
81
75
  }
82
- async run(args) {
83
- const context = this.context;
84
- const timeFiles = this.options.timeOptions.files;
85
- context.setVar("timeFilesCount", timeFiles.length);
86
- const timeRenderer = this.timeRenderer;
87
- const timeElementFactory = new TimeElementFactory(timeRenderer);
88
- const timeReplacer = new TimeReplacer(timeElementFactory);
89
- const caseFiles = await this.caseFactory.getFiles();
90
- let dataService = this.dataService;
91
- const caseService = new CaseService(dataService, this.caseFactory, timeElementFactory, caseFiles);
92
- const peopleFiles = await this.peopleFactory.getFiles();
93
- const peopleService = new PeopleService(dataService, this.peopleFactory, { files: peopleFiles, rootDir: "people" });
94
- const peopleList = await peopleService.getAll();
95
- context.setVar("peopleFilesCount", peopleList.length);
96
- const bookMeta = new Map();
97
- const bookLinks = new Map();
76
+ async generate(args) {
77
+ const timeContext = new TimeContext();
78
+ const context = new RR0ContextImpl(this.options.locale, timeContext, this.config, undefined, undefined, undefined, this);
79
+ context.setVar("mapsApiKey", this.options.googleMapsApiKey);
80
+ context.setVar("mail", this.options.mail);
98
81
  const config = this.config;
99
- const ufoCaseDirectoryFile = this.options.ufoCaseDirectoryFile;
100
- const ufoCasesExclusions = this.options.ufoCasesExclusions;
101
- const ufoCasesStep = new CaseDirectoryStep(caseService, caseService.files, ufoCasesExclusions, ufoCaseDirectoryFile, outputFunc, config);
102
- const peopleRenderer = new PeopleHtmlRenderer();
103
- const peopleDirectoryFactory = new PeopleDirectoryStepFactory(outputFunc, config, peopleService, peopleRenderer, this.options.directoryExcluded);
104
- const directoryOptions = this.options.directoryOptions;
105
- for (const directoryOption in directoryOptions) {
106
- directoryOptions[directoryOption] = directoryOptions[directoryOption];
107
- }
108
- const peopleSteps = await peopleDirectoryFactory.create(directoryOptions);
109
- // Publish case.json files so that vraiufo.com will find them
110
82
  const copies = this.options.copies;
111
- const ufoCasesRootDirs = ufoCasesStep.config.rootDirs;
112
- copies.push(...ufoCasesRootDirs.map(dir => path.join(dir, "case.json")));
113
83
  const outDir = this.options.outDir;
114
- await writeFile(path.join(outDir, "casesDirs.json"), JSON.stringify(ufoCasesRootDirs), "utf-8");
115
- const dirsContainingPeopleJson = peopleSteps.reduce((rootDirs, peopleStep) => {
116
- rootDirs.push(...peopleStep.config.rootDirs);
117
- return rootDirs;
118
- }, []);
119
- copies.push(...dirsContainingPeopleJson.map(dir => path.join(dir, "people.json")));
120
- await writeFile(path.join(outDir, "peopleDirs.json"), JSON.stringify(peopleList.map(people => people.dirName)), "utf-8");
84
+ const force = args.force === "true";
85
+ const ssg = new Ssg(config);
86
+ const dataService = this.dataService;
87
+ const timeService = this.timeService;
88
+ const timeRenderer = this.timeRenderer;
89
+ const timeFormat = this.options.timeFormat;
90
+ const { timeFiles, timeElementFactory, timeReplacer } = this.setupTime(context);
91
+ const { caseService, ufoCasesStep } = await this.setupCases(timeElementFactory);
92
+ const peopleRenderer = new PeopleHtmlRenderer();
93
+ const { peopleService, peopleSteps } = await this.peopleSetup(context, peopleRenderer, this.options.copies);
121
94
  const timeTextBuilder = this.timeTextBuilder;
122
95
  const searchVisitor = new SearchVisitor({ notIndexedUrls: ["404.html", "Referencement.html"], indexWords: false }, timeTextBuilder);
123
- const sourceRenderer = new SourceRenderer(timeTextBuilder);
124
- const http = new HttpSource();
125
- const baseUrl = this.options.siteBaseUrl;
126
- const timeFormat = this.options.timeFormat;
127
- const sourceRegistryFileName = this.options.sourceRegistryFileName;
128
- const timeService = this.timeService;
129
- const sourceFactory = new PersistentSourceRegistry(dataService, http, baseUrl, sourceRegistryFileName, timeFormat, timeService);
130
- const noteCounter = new NoteFileCounter();
131
- const noteRenderer = new NoteRenderer(noteCounter);
96
+ const { sourceRenderer, sourceFactory, sourceReplacerFactory } = this.setupSources(timeTextBuilder, timeFormat);
97
+ const { noteRenderer, noteReplacerFactory } = this.setupNotes();
132
98
  const caseRenderer = new CaseSummaryRenderer(noteRenderer, sourceFactory, sourceRenderer, timeElementFactory);
133
99
  const mappings = this.options.mappings || [];
134
100
  mappings.forEach(mapping => mapping.init(this));
135
101
  const timeUrlBuilder = this.timeUrlBuilder;
136
102
  const databaseAggregationCommand = new DomReplaceCommand(".contents ul", new ChronologyReplacerFactory(timeUrlBuilder, mappings, caseRenderer));
137
- const timeDefaultHandler = (context) => {
138
- let title;
139
- title = timeService.titleFromFile(context, context.file.name, timeTextBuilder);
140
- return title;
141
- };
142
- const sourceCounter = new SourceFileCounter();
143
- const sourceReplacer = new SourceReplacer(sourceRenderer, sourceFactory, sourceCounter);
144
- const sourceReplacerFactory = new SourceReplacerFactory(sourceReplacer);
145
- const noteReplacer = new NoteReplacer(noteRenderer);
146
- const noteReplacerFactory = new NoteReplacerFactory(noteReplacer);
147
103
  const eventReplacer = new EventReplacer(caseRenderer, dataService);
148
- const ssg = new Ssg(config);
149
104
  const getOutputPath = (context) => path.join(outDir, context.file.name);
150
- const force = args.force === "true";
151
105
  const toProcess = new Set(this.options.directoryPages);
152
106
  const csvTransformer = new class {
153
107
  transform(context, file) {
@@ -162,11 +116,9 @@ export class RR0Build {
162
116
  }
163
117
  }();
164
118
  const htAccessToNetlifyConfig = {
165
- replacements: [new HtAccessToNetlifyConfigReplaceCommand(baseUrl)],
119
+ replacements: [new HtAccessToNetlifyConfigReplaceCommand(this.options.siteBaseUrl)],
166
120
  roots: [".htaccess"],
167
- getOutputPath(_context) {
168
- return path.join(outDir, "netlify.toml");
169
- }
121
+ getOutputPath: (_context) => path.join(outDir, "netlify.toml")
170
122
  };
171
123
  const contentRoots = this.options.contentRoots;
172
124
  const contentStepOptions = {
@@ -187,27 +139,20 @@ export class RR0Build {
187
139
  ssg.add(ufoCasesStep);
188
140
  ssg.add(...peopleSteps);
189
141
  if (contentRoots) {
190
- const contentVisitor = new DefaultContentVisitor(dataService, caseRenderer, timeElementFactory);
191
- const contentVisitors = [contentVisitor, searchVisitor];
192
- if (args.books) {
193
- contentVisitors.push(new BookContentVisitor(bookMeta, bookLinks));
194
- }
142
+ const dataContentVisitor = new DataContentVisitor(dataService, caseRenderer, timeElementFactory);
143
+ const contentVisitors = [dataContentVisitor, searchVisitor];
144
+ const timeDefaultHandler = (context) => this.timeService.titleFromFile(context, context.file.name, this.timeTextBuilder);
195
145
  const pageReplaceCommands = [
196
- ...this.options.contentReplacers,
197
146
  new SsiTitleReplaceCommand([timeDefaultHandler]),
198
- new AuthorReplaceCommand(timeRenderer)
147
+ new AuthorReplaceCommand(timeRenderer),
148
+ ...this.options.contentReplacers
199
149
  ];
200
150
  const contentsReplaceCommand = [
201
151
  new ClassDomReplaceCommand(new EventReplacerFactory(eventReplacer), "event"),
202
152
  new ClassDomReplaceCommand(sourceReplacerFactory, "source"),
203
153
  new DomReplaceCommand("time", new TimeReplacerFactory(timeReplacer, timeUrlBuilder)),
204
- new DomReplaceCommand("code", new CodeReplacerFactory()),
205
154
  new ClassDomReplaceCommand(new PeopleReplacerFactory(peopleService, peopleRenderer), "people"),
206
- new ClassDomReplaceCommand(new PlaceReplacerFactory(), "place"),
207
- new ClassDomReplaceCommand(new WitnessReplacerFactory(), "temoin", "temoin1", "temoin2", "temoin3"),
208
155
  new ClassDomReplaceCommand(noteReplacerFactory, "note"),
209
- new ClassDomReplaceCommand(new IndexedReplacerFactory(), "indexed"),
210
- new UnitReplaceCommand(),
211
156
  new MetaLinkReplaceCommand(new TimeLinkDefaultHandler(timeService, timeUrlBuilder, timeTextBuilder)),
212
157
  databaseAggregationCommand
213
158
  ];
@@ -215,24 +160,27 @@ export class RR0Build {
215
160
  ...pageReplaceCommands,
216
161
  ...contentsReplaceCommand,
217
162
  new OutlineReplaceCommand(),
218
- new AnchorReplaceCommand(baseUrl, [new CaseAnchorHandler(caseService, timeTextBuilder), new DataAnchorHandler(dataService)]),
163
+ new AnchorReplaceCommand(this.options.siteBaseUrl, [new CaseAnchorHandler(caseService, timeTextBuilder), new DataAnchorHandler(dataService)]),
219
164
  new ImageCommand(outDir, 275, 500),
220
- new OpenGraphCommand(outDir, timeFiles, baseUrl, timeService, timeTextBuilder)
165
+ new OpenGraphCommand(outDir, timeFiles, this.options.siteBaseUrl, timeService, timeTextBuilder)
221
166
  ];
222
167
  ssg.add(new RR0ContentStep({
223
168
  contentConfigs: [{ roots: contentRoots, replacements: contentReplacements, getOutputPath }],
224
169
  outputFunc, fileVisitors: [], contentVisitors, force, name: "contents replacements", toProcess
225
170
  }, timeService));
226
- }
227
- if (args.books) {
228
- ssg.add(await BookDirectoryStep.create(outputFunc, config, bookMeta, bookLinks));
171
+ if (args.books) {
172
+ const bookMeta = new Map();
173
+ const bookLinks = new Map();
174
+ contentVisitors.push(new BookContentVisitor(bookMeta, bookLinks));
175
+ ssg.add(await BookDirectoryStep.create(outputFunc, config, bookMeta, bookLinks));
176
+ }
229
177
  }
230
178
  const reindex = args.reindex;
231
179
  if (reindex === null || reindex === void 0 ? void 0 : reindex.includes("search")) {
232
180
  ssg.add(new SearchIndexStep("search/index.json", searchVisitor));
233
181
  }
234
182
  if (reindex === null || reindex === void 0 ? void 0 : reindex.includes("sources")) {
235
- ssg.add(new SourceIndexStep(sourceRegistryFileName, sourceFactory));
183
+ ssg.add(new SourceIndexStep(this.options.sourceRegistryFileName, sourceFactory));
236
184
  }
237
185
  if (copies) {
238
186
  const copyConfig = {
@@ -258,4 +206,57 @@ export class RR0Build {
258
206
  console.timeEnd("ssg");
259
207
  }
260
208
  }
209
+ setupSources(timeTextBuilder, timeFormat) {
210
+ const sourceRenderer = new SourceRenderer(timeTextBuilder);
211
+ const sourceFactory = new PersistentSourceRegistry(this.dataService, this.http, this.options.siteBaseUrl, this.options.sourceRegistryFileName, timeFormat, this.timeService);
212
+ const sourceCounter = new SourceFileCounter();
213
+ const sourceReplacer = new SourceReplacer(sourceRenderer, sourceFactory, sourceCounter);
214
+ const sourceReplacerFactory = new SourceReplacerFactory(sourceReplacer);
215
+ return { sourceRenderer, sourceFactory, sourceReplacerFactory };
216
+ }
217
+ setupTime(context) {
218
+ const timeFiles = this.options.timeOptions.files;
219
+ context.setVar("timeFilesCount", timeFiles.length);
220
+ const timeElementFactory = new TimeElementFactory(this.timeRenderer);
221
+ const timeReplacer = new TimeReplacer(timeElementFactory);
222
+ return { timeFiles, timeElementFactory, timeReplacer };
223
+ }
224
+ async peopleSetup(context, peopleRenderer, copies) {
225
+ const peopleFiles = await this.peopleFactory.getFiles();
226
+ const peopleService = new PeopleService(this.dataService, this.peopleFactory, { files: peopleFiles, rootDir: "people" });
227
+ const peopleList = await peopleService.getAll();
228
+ context.setVar("peopleFilesCount", peopleList.length);
229
+ const peopleDirectoryFactory = new PeopleDirectoryStepFactory(outputFunc, this.config, peopleService, peopleRenderer, this.options.directoryExcluded);
230
+ const directoryOptions = this.options.directoryOptions;
231
+ for (const directoryOption in directoryOptions) {
232
+ directoryOptions[directoryOption] = directoryOptions[directoryOption];
233
+ }
234
+ const peopleSteps = await peopleDirectoryFactory.create(directoryOptions);
235
+ const dirsContainingPeopleJson = peopleSteps.reduce((rootDirs, peopleStep) => {
236
+ rootDirs.push(...peopleStep.config.rootDirs);
237
+ return rootDirs;
238
+ }, []);
239
+ copies.push(...dirsContainingPeopleJson.map(dir => path.join(dir, "people.json")));
240
+ await writeFile(path.join(this.options.outDir, "peopleDirs.json"), JSON.stringify(peopleList.map(people => people.dirName)), "utf-8");
241
+ return { peopleService, peopleSteps, copies };
242
+ }
243
+ setupNotes() {
244
+ const noteCounter = new NoteFileCounter();
245
+ const noteRenderer = new NoteRenderer(noteCounter);
246
+ const noteReplacer = new NoteReplacer(noteRenderer);
247
+ const noteReplacerFactory = new NoteReplacerFactory(noteReplacer);
248
+ return { noteRenderer, noteReplacerFactory };
249
+ }
250
+ async setupCases(timeElementFactory) {
251
+ const caseFiles = await this.caseFactory.getFiles();
252
+ const caseService = new CaseService(this.dataService, this.caseFactory, timeElementFactory, caseFiles);
253
+ const ufoCaseDirectoryFile = this.options.ufoCaseDirectoryFile;
254
+ const ufoCasesExclusions = this.options.ufoCasesExclusions;
255
+ const ufoCasesStep = new CaseDirectoryStep(caseService, caseService.files, ufoCasesExclusions, ufoCaseDirectoryFile, outputFunc, this.config);
256
+ // Publish case.json files so that vraiufo.com will find them
257
+ const ufoCasesRootDirs = ufoCasesStep.config.rootDirs;
258
+ this.options.copies.push(...ufoCasesRootDirs.map(dir => path.join(dir, "case.json")));
259
+ await writeFile(path.join(this.options.outDir, "casesDirs.json"), JSON.stringify(ufoCasesRootDirs), "utf-8");
260
+ return { caseService, ufoCasesStep };
261
+ }
261
262
  }
@@ -0,0 +1 @@
1
+ export declare function getTimeFiles(): Promise<string[]>;
@@ -1,15 +1,29 @@
1
1
  import { glob } from "glob";
2
2
  import { describe } from "@javarome/testscript";
3
- import { RR0Build } from "./RR0Build.js";
3
+ import { CMSGenerator } from "./CMSGenerator.js";
4
4
  import { BaseOvniFranceRR0Mapping, FuforaRR0Mapping, NuforcRR0Mapping, RR0Mapping, SceauRR0Mapping, UrecatRR0Mapping } from "./time/index.js";
5
+ import { WitnessReplacerFactory } from "./people/index.js";
5
6
  import { testFilePath } from "./test";
6
7
  import * as process from "node:process";
7
8
  import { GeipanRR0Mapping } from "./org/eu/fr/cnes/geipan/geipan/GeipanRR0Mapping";
8
9
  import { BaseReplaceCommand } from "./BaseReplaceCommand";
9
10
  import { LanguageReplaceCommand } from "./lang";
10
- import { AngularExpressionReplaceCommand, SsiEchoVarReplaceCommand, SsiIfReplaceCommand, SsiLastModifiedReplaceCommand, SsiSetVarReplaceCommand, StringEchoVarReplaceCommand } from "ssg-api";
11
+ import { AngularExpressionReplaceCommand, ClassDomReplaceCommand, DomReplaceCommand, SsiEchoVarReplaceCommand, SsiIfReplaceCommand, SsiLastModifiedReplaceCommand, SsiSetVarReplaceCommand, StringEchoVarReplaceCommand } from "ssg-api";
11
12
  import { rr0DefaultCopyright } from "./RR0DefaultCopyright";
12
13
  import { DescriptionReplaceCommand } from "./DescriptionReplaceCommand";
14
+ import { CodeReplacerFactory } from "./tech";
15
+ import { PlaceReplacerFactory } from "./place";
16
+ import { IndexedReplacerFactory, UnitReplaceCommand } from "./index";
17
+ export async function getTimeFiles() {
18
+ const minusYearFiles = await glob(testFilePath("time/-?/?/?/?/index.html"));
19
+ const year1Files = await glob(testFilePath("time/?/index.html"));
20
+ const year2Files = await glob(testFilePath("time/?/?/index.html"));
21
+ const year3Files = await glob(testFilePath("time/?/?/?/index.html"));
22
+ const year4Files = await glob(testFilePath("time/?/?/?/?/index.html"));
23
+ const monthFiles = await glob(testFilePath("time/?/?/?/?/??/index.html"));
24
+ const dayFiles = await glob(testFilePath("time/?/?/?/?/??/??/index.html"));
25
+ return year1Files.concat(year2Files).concat(year3Files).concat(year4Files).concat(minusYearFiles).concat(monthFiles).concat(dayFiles).sort();
26
+ }
13
27
  describe("Build", () => {
14
28
  console.time("ssg");
15
29
  const args = {
@@ -65,16 +79,6 @@ describe("Build", () => {
65
79
  hour: "2-digit",
66
80
  minute: "2-digit"
67
81
  };
68
- async function getTimeFiles() {
69
- const minusYearFiles = await glob(testFilePath("time/-?/?/?/?/index.html"));
70
- const year1Files = await glob(testFilePath("time/?/index.html"));
71
- const year2Files = await glob(testFilePath("time/?/?/index.html"));
72
- const year3Files = await glob(testFilePath("time/?/?/?/index.html"));
73
- const year4Files = await glob(testFilePath("time/?/?/?/?/index.html"));
74
- const monthFiles = await glob(testFilePath("time/?/?/?/?/??/index.html"));
75
- const dayFiles = await glob(testFilePath("time/?/?/?/?/??/??/index.html"));
76
- return year1Files.concat(year2Files).concat(year3Files).concat(year4Files).concat(minusYearFiles).concat(monthFiles).concat(dayFiles).sort();
77
- }
78
82
  const directoryPages = [
79
83
  "people/index.html", "people/witness/index.html", "people/militaires.html", "people/scientifiques.html",
80
84
  "people/astronomes.html", "people/politicians.html", "people/dirigeants.html", "people/pilotes.html",
@@ -108,12 +112,31 @@ describe("Build", () => {
108
112
  const nuforcRR0Mapping = new NuforcRR0Mapping(actions);
109
113
  const urecatRR0Mapping = new UrecatRR0Mapping(actions);
110
114
  const sceauRR0Mapping = new SceauRR0Mapping(actions);
111
- const mappings = [rr0Mapping,
115
+ const mappings = [rr0Mapping
112
116
  /* geipanRR0Mapping,
113
117
  baseOvniFranceRR0Mapping, fuforaRR0Mapping, nuforcRR0Mapping, urecatRR0Mapping,
114
118
  sceauRR0Mapping*/
115
119
  ];
116
- const build = new RR0Build({
120
+ const pageReplacers = [
121
+ new BaseReplaceCommand("/"),
122
+ new LanguageReplaceCommand(),
123
+ new SsiEchoVarReplaceCommand("copyright", [rr0DefaultCopyright]),
124
+ new StringEchoVarReplaceCommand(),
125
+ new AngularExpressionReplaceCommand(),
126
+ new SsiIfReplaceCommand(),
127
+ new SsiSetVarReplaceCommand("title", (_match, ...args) => `<title>${args[0]}</title>`),
128
+ new SsiSetVarReplaceCommand("url", (_match, ...args) => `<meta name="url" content="${args[0]}"/>`),
129
+ new SsiLastModifiedReplaceCommand(timeFormat),
130
+ new DescriptionReplaceCommand("UFO data for french-reading people", "abstract")
131
+ ];
132
+ const contentsReplacers = [
133
+ new DomReplaceCommand("code", new CodeReplacerFactory()),
134
+ new ClassDomReplaceCommand(new PlaceReplacerFactory(), "place"),
135
+ new ClassDomReplaceCommand(new WitnessReplacerFactory(), "temoin", "temoin1", "temoin2", "temoin3"),
136
+ new ClassDomReplaceCommand(new IndexedReplacerFactory(), "indexed"),
137
+ new UnitReplaceCommand()
138
+ ];
139
+ const generator = new CMSGenerator({
117
140
  contentRoots, copies, outDir, locale: "fr", googleMapsApiKey, mail, timeOptions,
118
141
  siteBaseUrl, timeFormat, directoryPages,
119
142
  ufoCaseDirectoryFile: testFilePath("science/crypto/ufo/enquete/dossier/index.html"),
@@ -122,19 +145,8 @@ describe("Build", () => {
122
145
  directoryExcluded: ["people/Astronomers_fichiers", "people/witness", "people/author"].map(testFilePath),
123
146
  directoryOptions,
124
147
  mappings,
125
- contentReplacers: [
126
- new BaseReplaceCommand("/"),
127
- new LanguageReplaceCommand(),
128
- new SsiEchoVarReplaceCommand("copyright", [rr0DefaultCopyright]),
129
- new StringEchoVarReplaceCommand(),
130
- new AngularExpressionReplaceCommand(),
131
- new SsiIfReplaceCommand(),
132
- new SsiSetVarReplaceCommand("title", (_match, ...args) => `<title>${args[0]}</title>`),
133
- new SsiSetVarReplaceCommand("url", (_match, ...args) => `<meta name="url" content="${args[0]}"/>`),
134
- new SsiLastModifiedReplaceCommand(timeFormat),
135
- new DescriptionReplaceCommand("UFO data for french-reading people", "abstract")
136
- ]
148
+ contentReplacers: [...pageReplacers, ...contentsReplacers]
137
149
  });
138
- await build.run(args);
150
+ await generator.generate(args);
139
151
  });
140
152
  });
@@ -3,7 +3,10 @@ import { ContentVisitor } from "./RR0ContentStep.js";
3
3
  import { HtmlRR0Context } from "./RR0Context.js";
4
4
  import { EventRenderer } from "./time/EventRenderer.js";
5
5
  import { AllDataService, RR0Data, RR0Event } from "@rr0/data";
6
- export declare class DefaultContentVisitor implements ContentVisitor {
6
+ /**
7
+ * Insert content in context file, according to data found in .json files aside of it.
8
+ */
9
+ export declare class DataContentVisitor implements ContentVisitor {
7
10
  protected service: AllDataService;
8
11
  protected eventRenderer: EventRenderer<RR0Event>;
9
12
  protected timeElementFactory: TimeElementFactory;
@@ -1,6 +1,9 @@
1
1
  import path from "path";
2
2
  import assert from "assert";
3
- export class DefaultContentVisitor {
3
+ /**
4
+ * Insert content in context file, according to data found in .json files aside of it.
5
+ */
6
+ export class DataContentVisitor {
4
7
  constructor(service, eventRenderer, timeElementFactory) {
5
8
  this.service = service;
6
9
  this.eventRenderer = eventRenderer;
@@ -49,7 +49,7 @@ export class OpenGraphCommand {
49
49
  timeStr = "Chronologie";
50
50
  }
51
51
  else {
52
- const timeContext = this.timeService.gSetTimeFromPath(context, fileName);
52
+ const timeContext = this.timeService.setContextFromFile(context, fileName);
53
53
  if (timeContext) {
54
54
  context.time.setYear(timeContext.getYear());
55
55
  context.time.setMonth(timeContext.getMonth());
@@ -4,6 +4,7 @@ import { TimeContext } from "@rr0/time";
4
4
  import { FileContents } from "@javarome/fileutil";
5
5
  import { PlaceContext } from "@rr0/place";
6
6
  import { People } from "@rr0/data";
7
+ import { CMSContext } from "./CMSContext";
7
8
  export interface RR0Context extends SsgContext {
8
9
  readonly messages: RR0Messages;
9
10
  readonly time: TimeContext;
@@ -16,6 +17,7 @@ export interface HtmlRR0Context extends HtmlSsgContext {
16
17
  people: People;
17
18
  readonly images: Set<string>;
18
19
  readonly config: FileWriteConfig;
20
+ readonly cms: CMSContext;
19
21
  clone(locale?: string): HtmlRR0Context;
20
22
  }
21
23
  export declare class RR0ContextImpl extends SsgContextImpl {
@@ -23,10 +25,11 @@ export declare class RR0ContextImpl extends SsgContextImpl {
23
25
  readonly config: FileWriteConfig;
24
26
  readonly people: any;
25
27
  readonly messages: RR0Messages;
28
+ readonly cms: CMSContext;
26
29
  readonly images: Set<string>;
27
30
  protected readonly fileMap: Map<string, FileContents>;
28
31
  place: PlaceContext;
29
- constructor(locale: string, time: TimeContext, config: FileWriteConfig, people?: any, currentFile?: FileContents | undefined, messages?: RR0Messages);
32
+ constructor(locale: string, time: TimeContext, config: FileWriteConfig, people?: any, currentFile?: FileContents | undefined, messages?: RR0Messages, cms?: CMSContext);
30
33
  read(filePath: string): FileContents;
31
34
  clone(locale?: string): RR0ContextImpl;
32
35
  toString(): string;
@@ -2,12 +2,13 @@ import { ssgMessages } from "./lang/index.js";
2
2
  import { ConsoleLogger, SsgContextImpl } from "ssg-api";
3
3
  import { PlaceContext } from "@rr0/place";
4
4
  export class RR0ContextImpl extends SsgContextImpl {
5
- constructor(locale, time, config, people = undefined, currentFile = undefined, messages = ssgMessages[locale]) {
5
+ constructor(locale, time, config, people = undefined, currentFile = undefined, messages = ssgMessages[locale], cms = undefined) {
6
6
  super(locale, new Map(), "RR0", new ConsoleLogger("RR0"), currentFile);
7
7
  this.time = time;
8
8
  this.config = config;
9
9
  this.people = people;
10
10
  this.messages = messages;
11
+ this.cms = cms;
11
12
  this.images = new Set();
12
13
  this.fileMap = new Map();
13
14
  while (!this.messages) {
@@ -35,7 +36,7 @@ export class RR0ContextImpl extends SsgContextImpl {
35
36
  }
36
37
  clone(locale = this.locale) {
37
38
  var _a;
38
- return new RR0ContextImpl(locale, this.time.clone(), this.config, (_a = this.people) === null || _a === void 0 ? void 0 : _a.clone(), this._file);
39
+ return new RR0ContextImpl(locale, this.time.clone(), this.config, (_a = this.people) === null || _a === void 0 ? void 0 : _a.clone(), this._file, this.messages, this.cms);
39
40
  }
40
41
  toString() {
41
42
  var _a;
package/dist/index.d.ts CHANGED
@@ -16,7 +16,7 @@ export * from "./util/index.js";
16
16
  export * from "./value/index.js";
17
17
  export * from "./BaseReplaceCommand.js";
18
18
  export * from "./CSVFileReader.js";
19
- export * from "./DefaultContentVisitor.js";
19
+ export * from "./DataContentVisitor.js";
20
20
  export * from "./DescriptionReplaceCommand.js";
21
21
  export * from "./ImageCommand.js";
22
22
  export * from "./LocalAnchor.js";
@@ -28,5 +28,5 @@ export * from "./RR0ContentStep.js";
28
28
  export * from "./RR0DefaultCopyright.js";
29
29
  export * from "./RR0Context.js";
30
30
  export * from "./TableReplaceCommand.js";
31
- export * from "./RR0Build.js";
32
- export { BuildContext } from "./BuildContext";
31
+ export * from "./CMSGenerator.js";
32
+ export * from "./CMSContext.js";
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ export * from "./util/index.js";
16
16
  export * from "./value/index.js";
17
17
  export * from "./BaseReplaceCommand.js";
18
18
  export * from "./CSVFileReader.js";
19
- export * from "./DefaultContentVisitor.js";
19
+ export * from "./DataContentVisitor.js";
20
20
  export * from "./DescriptionReplaceCommand.js";
21
21
  export * from "./ImageCommand.js";
22
22
  export * from "./LocalAnchor.js";
@@ -28,4 +28,5 @@ export * from "./RR0ContentStep.js";
28
28
  export * from "./RR0DefaultCopyright.js";
29
29
  export * from "./RR0Context.js";
30
30
  export * from "./TableReplaceCommand.js";
31
- export * from "./RR0Build.js";
31
+ export * from "./CMSGenerator.js";
32
+ export * from "./CMSContext.js";
@@ -10,6 +10,6 @@ export declare class GeipanFileDatasource extends GeipanDatasource implements Da
10
10
  protected readonly file: CsvFileSource<GeipanCase>;
11
11
  protected writeMapper: GeipanSummaryToCaseMapper;
12
12
  constructor(defaultFileName: string, encoding: BufferEncoding);
13
- save(context: HtmlRR0Context, fetched: GeipanCaseSummary[], fetchTime: Date): void;
13
+ save(context: HtmlRR0Context, fetched: GeipanCaseSummary[], fetchTime: Date): string;
14
14
  protected readCases(context: HtmlRR0Context): Promise<GeipanCaseSummary[]>;
15
15
  }
@@ -3,7 +3,7 @@ import { GeipanCaseSummaryRR0Mapper } from "./GeipanCaseSummaryRR0Mapper.js";
3
3
  import { GeipanFileDatasource } from "./GeipanFileDatasource.js";
4
4
  import { GeipanCaseSummary } from "./GeipanCaseSummary.js";
5
5
  import { ChronologyReplacerActions, RR0CaseMapping } from "../../../../../../time/index.js";
6
- import { BuildContext } from "../../../../../../BuildContext";
6
+ import { CMSContext } from "../../../../../../CMSContext";
7
7
  export declare const geipanHttpDatasource: GeipanHttpDatasource;
8
8
  export declare const geipanFileDatasource: GeipanFileDatasource;
9
9
  export declare class GeipanRR0Mapping implements RR0CaseMapping<GeipanCaseSummary> {
@@ -12,5 +12,5 @@ export declare class GeipanRR0Mapping implements RR0CaseMapping<GeipanCaseSummar
12
12
  backupDatasource: GeipanFileDatasource;
13
13
  mapper: GeipanCaseSummaryRR0Mapper;
14
14
  constructor(actions: ChronologyReplacerActions);
15
- init(build: BuildContext): this;
15
+ init(build: CMSContext): this;
16
16
  }
@@ -33,8 +33,7 @@ export class SearchVisitor {
33
33
  if (titleIndexed) {
34
34
  this.handleAlreadyIndexed(title, url, titleIndexed);
35
35
  }
36
- const indexContext = context.clone();
37
- const time = this.timeTextBuilder.build(indexContext, { year: "numeric", month: "short", day: "numeric" }).toLowerCase();
36
+ const time = this.timeTextBuilder.build(context, { year: "numeric", month: "short", day: "numeric" }).toLowerCase();
38
37
  indexedPages.push({ title, url, time });
39
38
  }
40
39
  if (this.config.indexWords) {