@rr0/cms 0.3.31 → 0.3.33

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.
@@ -11,6 +11,7 @@ import { PeopleHtmlRenderer } from "./people/PeopleHtmlRenderer.js";
11
11
  import { CountryService } from "./org/country/CountryService.js";
12
12
  import { CMSContext } from "./CMSContext.js";
13
13
  import { TimeOptions } from "./time/TimeOptions.js";
14
+ import { DataOptions } from "./DataOptions.js";
14
15
  export interface CMSGeneratorOptions {
15
16
  contentRoots: string[];
16
17
  copies: string[];
@@ -18,7 +19,10 @@ export interface CMSGeneratorOptions {
18
19
  locale: string;
19
20
  googleMapsApiKey: string;
20
21
  mail: string;
21
- timeOptions: TimeOptions;
22
+ dataOptions: {
23
+ time: TimeOptions;
24
+ org: DataOptions;
25
+ };
22
26
  siteBaseUrl: string;
23
27
  timeFormat: Intl.DateTimeFormatOptions;
24
28
  directoryPages: string[];
@@ -62,7 +66,7 @@ export declare class CMSGenerator implements CMSContext {
62
66
  readonly config: FileWriteConfig;
63
67
  readonly context: RR0ContextImpl;
64
68
  readonly placeService: GooglePlaceService;
65
- readonly orgService: OrganizationService<any>;
69
+ readonly orgService: OrganizationService;
66
70
  readonly caseFactory: CaseFactory;
67
71
  readonly dataService: AllDataService;
68
72
  readonly peopleFactory: PeopleFactory;
@@ -41,6 +41,7 @@ const outputFunc = async (context, outFile) => {
41
41
  export class CMSGenerator {
42
42
  constructor(options) {
43
43
  this.options = options;
44
+ this.http = new HttpSource();
44
45
  this.config = {
45
46
  getOutputPath(context) {
46
47
  return path.join(options.outDir, context.file.name);
@@ -48,16 +49,7 @@ export class CMSGenerator {
48
49
  };
49
50
  const eventFactory = new RR0EventFactory();
50
51
  const orgFactory = new CmsOrganizationFactory(eventFactory);
51
- const countryService = this.countryService = new CountryService(countries, "org", orgFactory, undefined);
52
- const regionService = new RegionService(regions, "org", orgFactory, countryService);
53
- const departmentService = this.departmentService = new DepartmentService(departments, "org", orgFactory, regionService);
54
- const cityService = new CityService(cities, "org", orgFactory, departmentService);
55
- this.placeService = new GooglePlaceService("place", options.googleMapsApiKey);
56
- this.orgService = new OrganizationService([], "org", orgFactory, undefined);
57
- this.cityService = cityService;
58
- const timeTextBuilder = this.timeTextBuilder = new TimeTextBuilder(options.timeFormat);
59
- const timeOptions = options.timeOptions;
60
- const timeUrlBuilder = this.timeUrlBuilder = new TimeUrlBuilder(timeOptions);
52
+ const orgConfig = options.dataOptions.org;
61
53
  const sightingFactory = new EventDataFactory(eventFactory, ["sighting"], ["index"]);
62
54
  const caseFactory = this.caseFactory = new CaseFactory(eventFactory);
63
55
  const peopleFactory = this.peopleFactory = new PeopleFactory(eventFactory);
@@ -69,9 +61,18 @@ export class CMSGenerator {
69
61
  dataService.getFromDir("", ["people", "case"]).then(data => {
70
62
  console.debug(data);
71
63
  });
64
+ this.orgService = new OrganizationService(dataService, orgFactory, orgConfig, undefined, []);
65
+ const countryService = this.countryService = new CountryService(dataService, orgFactory, orgConfig, undefined, countries);
66
+ const regionService = new RegionService(dataService, orgFactory, orgConfig, countryService, regions);
67
+ const departmentService = this.departmentService = new DepartmentService(dataService, orgFactory, orgConfig, regionService, departments);
68
+ const cityService = new CityService(dataService, orgFactory, orgConfig, departmentService, cities);
69
+ this.placeService = new GooglePlaceService("place", options.googleMapsApiKey);
70
+ this.cityService = cityService;
71
+ const timeTextBuilder = this.timeTextBuilder = new TimeTextBuilder(options.timeFormat);
72
+ const timeOptions = options.dataOptions.time;
73
+ const timeUrlBuilder = this.timeUrlBuilder = new TimeUrlBuilder(timeOptions);
72
74
  this.timeRenderer = new TimeRenderer(timeUrlBuilder, timeTextBuilder);
73
75
  this.timeService = new TimeService(dataService, timeOptions);
74
- this.http = new HttpSource();
75
76
  }
76
77
  async generate(args) {
77
78
  const timeContext = new TimeContext();
@@ -90,7 +91,7 @@ export class CMSGenerator {
90
91
  const { timeFiles, timeElementFactory, timeReplacer } = this.setupTime(context);
91
92
  const orgFactory = dataService.factories.find(f => f.type === "org");
92
93
  if (orgFactory) {
93
- const orgFiles = await orgFactory.getFiles();
94
+ const orgFiles = this.options.dataOptions.org.files;
94
95
  context.setVar("orgFilesCount", orgFiles.length);
95
96
  }
96
97
  const placeFactory = dataService.factories.find(f => f.type === "place");
@@ -225,7 +226,7 @@ export class CMSGenerator {
225
226
  return { sourceRenderer, sourceFactory, sourceReplacerFactory };
226
227
  }
227
228
  setupTime(context) {
228
- const timeFiles = this.options.timeOptions.files;
229
+ const timeFiles = this.options.dataOptions.time.files;
229
230
  context.setVar("timeFilesCount", timeFiles.length);
230
231
  const timeElementFactory = new TimeElementFactory(this.timeRenderer);
231
232
  const timeReplacer = new TimeReplacer(timeElementFactory);
@@ -235,7 +236,7 @@ export class CMSGenerator {
235
236
  const peopleFiles = await this.peopleFactory.getFiles();
236
237
  const peopleService = new PeopleService(this.dataService, this.peopleFactory, { files: peopleFiles, rootDir: "people" });
237
238
  const peopleList = await peopleService.getAll();
238
- context.setVar("peopleFilesCount", peopleList.length);
239
+ context.setVar("peopleFilesCount", peopleFiles.length);
239
240
  const peopleDirectoryFactory = new PeopleDirectoryStepFactory(outputFunc, this.config, peopleService, peopleRenderer, this.options.directoryExcluded);
240
241
  const directoryOptions = this.options.directoryOptions;
241
242
  for (const directoryOption in directoryOptions) {
@@ -85,6 +85,7 @@ describe("Build", () => {
85
85
  "people/contactes.html", "people/ufologues.html", "tech/info/Personnes.html", "people/Contributeurs.html"
86
86
  ].map(path => rr0TestUtil.filePath(path));
87
87
  getTimeFiles().then(async (timeFiles) => {
88
+ const orgFiles = await glob("test/org/**/index.html");
88
89
  const directoryOptions = {
89
90
  root: rr0TestUtil.filePath("people/index.html"),
90
91
  scientists: rr0TestUtil.filePath("people/scientifiques.html"),
@@ -102,6 +103,11 @@ describe("Build", () => {
102
103
  const siteBaseUrl = "https://rr0.org/";
103
104
  const mail = "rr0@rr0.org";
104
105
  const timeOptions = { rootDir: rr0TestUtil.filePath("time"), files: timeFiles };
106
+ const orgOptions = { rootDir: rr0TestUtil.filePath("org"), files: orgFiles };
107
+ const dataOptions = {
108
+ time: timeOptions,
109
+ org: orgOptions
110
+ };
105
111
  // const actions: ChronologyReplacerActions = {read: ["backup", "fetch"], write: ["backup", "pages"]}
106
112
  // const actions: ChronologyReplacerActions = {read: [], write: ["backup"]}
107
113
  const actions = { read: ["fetch"], write: ["backup"] };
@@ -137,7 +143,7 @@ describe("Build", () => {
137
143
  new UnitReplaceCommand()
138
144
  ];
139
145
  const generator = new CMSGenerator({
140
- contentRoots, copies, outDir, locale: "fr", googleMapsApiKey, mail, timeOptions,
146
+ contentRoots, copies, outDir, locale: "fr", googleMapsApiKey, mail, dataOptions,
141
147
  siteBaseUrl, timeFormat, directoryPages,
142
148
  ufoCaseDirectoryFile: rr0TestUtil.filePath("science/crypto/ufo/enquete/dossier/index.html"),
143
149
  ufoCasesExclusions: ["science/crypto/ufo/enquete/dossier/canular"].map(path => rr0TestUtil.filePath(path)),
@@ -0,0 +1,4 @@
1
+ export type DataOptions = {
2
+ readonly rootDir: string;
3
+ readonly files: string[];
4
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -8,7 +8,7 @@ export class CaseAnchorHandler {
8
8
  async handle(context, link, pathToSearch) {
9
9
  var _a, _b, _c, _d, _e, _f;
10
10
  if (!link.title) {
11
- const foundCases = await this.caseService.get(pathToSearch);
11
+ const foundCases = await this.caseService.getFromDir(pathToSearch);
12
12
  const aCase = foundCases[0];
13
13
  if (aCase) {
14
14
  const caseContext = context.clone();
package/dist/index.d.ts CHANGED
@@ -30,3 +30,4 @@ export * from "./RR0Context.js";
30
30
  export * from "./TableReplaceCommand.js";
31
31
  export * from "./CMSGenerator.js";
32
32
  export * from "./CMSContext.js";
33
+ export * from "./DataOptions.js";
package/dist/index.js CHANGED
@@ -30,3 +30,4 @@ export * from "./RR0Context.js";
30
30
  export * from "./TableReplaceCommand.js";
31
31
  export * from "./CMSGenerator.js";
32
32
  export * from "./CMSContext.js";
33
+ export * from "./DataOptions.js";
@@ -15,6 +15,7 @@ export class NoteRenderer {
15
15
  const anchor = doc.createElement("span");
16
16
  anchor.id = noteId;
17
17
  anchor.className = "anchor";
18
+ anchor.ariaHidden = "true";
18
19
  replacement.append(anchor, contents);
19
20
  return replacement;
20
21
  }
@@ -1,6 +1,6 @@
1
1
  import { CmsOrganization } from "./CmsOrganization.js";
2
2
  import { OrganizationFactory, OrganizationJson, RR0EventFactory } from "@rr0/data";
3
- export declare class CmsOrganizationFactory extends OrganizationFactory {
3
+ export declare class CmsOrganizationFactory extends OrganizationFactory<CmsOrganization, OrganizationJson> {
4
4
  constructor(eventFactory: RR0EventFactory);
5
5
  parse(dataJson: OrganizationJson): CmsOrganization;
6
6
  }
@@ -1,14 +1,16 @@
1
1
  import { CmsOrganization } from "./CmsOrganization.js";
2
2
  import { RR0Context } from "../RR0Context.js";
3
3
  import { CmsOrganizationFactory } from "./CmsOrganizationFactory.js";
4
- export declare class OrganizationService<O extends CmsOrganization = CmsOrganization, P extends CmsOrganization = undefined> {
5
- readonly orgs: O[];
6
- readonly rootDir: string;
7
- protected factory: CmsOrganizationFactory;
4
+ import { AbstractDataService, AllDataService, OrganizationJson } from "@rr0/data";
5
+ import { DataOptions } from "../DataOptions.js";
6
+ export type OrganizationServiceConfig = DataOptions;
7
+ export declare class OrganizationService<O extends CmsOrganization = CmsOrganization, P extends CmsOrganization = undefined> extends AbstractDataService<O, OrganizationJson> {
8
+ protected config: OrganizationServiceConfig;
8
9
  readonly parentService: OrganizationService;
9
- constructor(orgs: O[], rootDir: string, factory: CmsOrganizationFactory, parentService: OrganizationService);
10
+ protected orgs: O[];
11
+ constructor(dataService: AllDataService, factory: CmsOrganizationFactory, config: OrganizationServiceConfig, parentService: OrganizationService, orgs: O[]);
10
12
  static normalizeName(name: string): string;
11
- get(code: string, parent?: P): O | undefined;
13
+ getById(code: string, parent?: P): O | undefined;
12
14
  /**
13
15
  * @param context
14
16
  * @param nameToFind
@@ -1,17 +1,18 @@
1
1
  import { StringUtil } from "../util/string/StringUtil.js";
2
2
  import assert from "assert";
3
3
  import { FileContents } from "@javarome/fileutil";
4
- export class OrganizationService {
5
- constructor(orgs, rootDir, factory, parentService) {
6
- this.orgs = orgs;
7
- this.rootDir = rootDir;
8
- this.factory = factory;
4
+ import { AbstractDataService } from "@rr0/data";
5
+ export class OrganizationService extends AbstractDataService {
6
+ constructor(dataService, factory, config, parentService, orgs) {
7
+ super(dataService, factory, config.files);
8
+ this.config = config;
9
9
  this.parentService = parentService;
10
+ this.orgs = orgs;
10
11
  }
11
12
  static normalizeName(name) {
12
13
  return StringUtil.removeAccents(name.toLowerCase().replaceAll(" ", "-"));
13
14
  }
14
- get(code, parent = undefined) {
15
+ getById(code, parent = undefined) {
15
16
  return this.orgs.find(org => {
16
17
  const foundParent = !parent || org.parent === parent;
17
18
  const foundOrg = org.id === code ? org : undefined;
@@ -52,8 +53,8 @@ export class OrganizationService {
52
53
  return foundOrg;
53
54
  }
54
55
  async read(fileName) {
55
- const file = FileContents.read(this.rootDir + fileName);
56
- const org = this.factory.create(file);
56
+ const file = FileContents.read(this.config.rootDir + fileName);
57
+ const org = this.factory.createFromFile(file);
57
58
  this.orgs.push(org);
58
59
  return org;
59
60
  }
@@ -5,8 +5,8 @@ import { rr0TestUtil } from "../../test/index.js";
5
5
  describe("CountryService", () => {
6
6
  test("get", () => {
7
7
  const countryService = rr0TestUtil.countryService;
8
- expect(countryService.get(france.id)).toBe(france);
9
- expect(countryService.get(usa.id)).toBe(usa);
10
- expect(countryService.get(usa.id)).not.toBe(france);
8
+ expect(countryService.getById(france.id)).toBe(france);
9
+ expect(countryService.getById(usa.id)).toBe(usa);
10
+ expect(countryService.getById(usa.id)).not.toBe(france);
11
11
  });
12
12
  });
@@ -7,8 +7,8 @@ import { rr0TestUtil } from "../../../test/index.js";
7
7
  describe("RegionService", () => {
8
8
  test("get", () => {
9
9
  const regionService = rr0TestUtil.regionService;
10
- expect(regionService.get(ileDeFrance.id, france)).toBe(ileDeFrance);
11
- expect(regionService.get(alabama.id, usa)).toBe(alabama);
12
- expect(regionService.get(alabama.id, france)).toBeUndefined();
10
+ expect(regionService.getById(ileDeFrance.id, france)).toBe(ileDeFrance);
11
+ expect(regionService.getById(alabama.id, usa)).toBe(alabama);
12
+ expect(regionService.getById(alabama.id, france)).toBeUndefined();
13
13
  });
14
14
  });
@@ -7,8 +7,8 @@ import { rr0TestUtil } from "../../../../test/index.js";
7
7
  describe("DepartmentService", () => {
8
8
  test("get", () => {
9
9
  const departmentService = rr0TestUtil.departmentService;
10
- expect(departmentService.get(hautsDeSeine.id, ileDeFrance)).toBe(hautsDeSeine);
11
- expect(departmentService.get(hautsDeSeine.id, undefined)).toBe(hautsDeSeine);
12
- expect(departmentService.get(sanDiego.id, california)).toBe(sanDiego);
10
+ expect(departmentService.getById(hautsDeSeine.id, ileDeFrance)).toBe(hautsDeSeine);
11
+ expect(departmentService.getById(hautsDeSeine.id, undefined)).toBe(hautsDeSeine);
12
+ expect(departmentService.getById(sanDiego.id, california)).toBe(sanDiego);
13
13
  });
14
14
  });
@@ -24,7 +24,7 @@ class MockPlaceService extends PlaceService {
24
24
  }
25
25
  class MockOrganizationService extends OrganizationService {
26
26
  constructor(dirName) {
27
- super([], "org", rr0TestUtil.orgFactory, null);
27
+ super(null, rr0TestUtil.orgFactory, { rootDir: "", files: [] }, null, []);
28
28
  this.dirName = dirName;
29
29
  }
30
30
  async read(_fileName) {
@@ -69,7 +69,7 @@ export class CaseDirectoryStep extends DirectoryStep {
69
69
  const cases = [];
70
70
  for (const dirName of dirNames) {
71
71
  try {
72
- const dirCases = await this.caseService.get(dirName);
72
+ const dirCases = await this.caseService.getFromDir(dirName);
73
73
  cases.push(...dirCases);
74
74
  }
75
75
  catch (e) {
@@ -14,6 +14,7 @@ export class SourceReplacer {
14
14
  const replacement = outputDoc.createElement("span");
15
15
  replacement.className = "source-id";
16
16
  replacement.ariaLabel = "Source";
17
+ replacement.ariaHidden = "true";
17
18
  const sourceId = this.counter.next(context);
18
19
  replacement.textContent = sourceId;
19
20
  const sourceContentsEl = outputDoc.createElement("span");
@@ -21,6 +22,7 @@ export class SourceReplacer {
21
22
  await this.content(context, original, sourceContentsEl);
22
23
  const anchor = outputDoc.createElement("span");
23
24
  anchor.id = sourceId;
25
+ anchor.ariaHidden = "true";
24
26
  anchor.className = "anchor";
25
27
  replacement.append(anchor, sourceContentsEl);
26
28
  return replacement;
@@ -21,7 +21,7 @@ export declare class RR0TestUtil implements CMSContext {
21
21
  readonly departmentService: DepartmentService;
22
22
  readonly countryService: CountryService;
23
23
  readonly regionService: RegionService;
24
- constructor(rootDir?: string, outDir?: string);
24
+ constructor(rootDir?: string, outDir?: string, orgFiles?: string[]);
25
25
  newContext(inputFileName: string, contents?: string, locale?: string): RR0Context;
26
26
  filePath(inputFileName: string): string;
27
27
  newHtmlContext(inputFileName: string, contents?: string, locale?: string): HtmlRR0Context;
@@ -10,7 +10,7 @@ import { FileContents } from "@javarome/fileutil";
10
10
  import { AllDataService, EventDataFactory, PeopleFactory, RR0EventFactory, TypedDataFactory } from "@rr0/data";
11
11
  import { CountryService } from "../org/country/CountryService.js";
12
12
  export class RR0TestUtil {
13
- constructor(rootDir = "test", outDir = "out") {
13
+ constructor(rootDir = "test", outDir = "out", orgFiles = []) {
14
14
  this.rootDir = rootDir;
15
15
  this.outDir = outDir;
16
16
  this.config = {
@@ -30,21 +30,22 @@ export class RR0TestUtil {
30
30
  const eventFactory = new RR0EventFactory();
31
31
  const sightingFactory = new EventDataFactory(eventFactory, ["sighting"], ["index"]);
32
32
  const orgFactory = this.orgFactory = new CmsOrganizationFactory(eventFactory);
33
- this.orgService = new OrganizationService([], "org", orgFactory, undefined);
34
33
  this.caseFactory = new CaseFactory(eventFactory);
35
34
  this.peopleFactory = new PeopleFactory(eventFactory);
36
35
  const apiFactory = new APIFactory(eventFactory);
37
36
  const bookFactory = new TypedDataFactory(eventFactory, "book");
38
37
  const articleFactory = new TypedDataFactory(eventFactory, "article");
39
- this.dataService = new AllDataService([orgFactory, this.caseFactory, this.peopleFactory, bookFactory, articleFactory, sightingFactory, apiFactory]);
40
- this.dataService.getFromDir("", ["people", "case"]).then(data => {
38
+ const dataService = this.dataService = new AllDataService([orgFactory, this.caseFactory, this.peopleFactory, bookFactory, articleFactory, sightingFactory, apiFactory]);
39
+ dataService.getFromDir("", ["people", "case"]).then(data => {
41
40
  // console.debug(data)
42
41
  });
42
+ const orgConfig = { rootDir: this.filePath("org"), files: orgFiles };
43
+ this.orgService = new OrganizationService(dataService, orgFactory, orgConfig, undefined, []);
43
44
  this.time = new TimeTestUtil(this);
44
- const countryService = this.countryService = new CountryService(countries, "org", orgFactory, undefined);
45
- const regionService = this.regionService = new RegionService(regions, "org", orgFactory, countryService);
46
- const departmentService = this.departmentService = new DepartmentService(departments, "org", orgFactory, regionService);
47
- this.cityService = new CityService(cities, "org", orgFactory, departmentService);
45
+ const countryService = this.countryService = new CountryService(dataService, orgFactory, orgConfig, undefined, countries);
46
+ const regionService = this.regionService = new RegionService(dataService, orgFactory, orgConfig, countryService, regions);
47
+ const departmentService = this.departmentService = new DepartmentService(dataService, orgFactory, orgConfig, regionService, departments);
48
+ this.cityService = new CityService(dataService, orgFactory, orgConfig, departmentService, cities);
48
49
  }
49
50
  newContext(inputFileName, contents, locale = "fr") {
50
51
  const context = new RR0ContextImpl(locale, new TimeContext(), this.config);
@@ -76,7 +76,7 @@ export class TimeDirectoryStep extends DirectoryStep {
76
76
  const events = [];
77
77
  for (const dirName of dirNames) {
78
78
  try {
79
- const dirEvents = await this.service.get(dirName);
79
+ const dirEvents = await this.service.getFromDir(dirName);
80
80
  events.push(...dirEvents);
81
81
  }
82
82
  catch (e) {
@@ -1,4 +1,2 @@
1
- export type TimeOptions = {
2
- readonly rootDir: string;
3
- readonly files: string[];
4
- };
1
+ import { DataOptions } from "../DataOptions.js";
2
+ export type TimeOptions = DataOptions;
@@ -19,7 +19,7 @@ export class BaseOvniFranceCaseSummaryRR0Mapper {
19
19
  publication: { publisher: this.copyright, time: EdtfDate.fromDate(sourceTime) }
20
20
  };
21
21
  const depCode = sourceCase.depCode;
22
- const dep = this.depService.get(depCode, undefined);
22
+ const dep = this.depService.getById(depCode, undefined);
23
23
  assert.ok(dep, `Could not find department "${depCode}"`);
24
24
  const placeName = sourceCase.city;
25
25
  const city = this.cityService.find(context, placeName, dep);
@@ -67,7 +67,7 @@ export class NuforcRR0Mapper {
67
67
  assert.ok(sourceCase.country, `NUFORC country code is ${sourceCase.country}`);
68
68
  const countryCode = NuforcRR0Mapper.countryMap[sourceCase.country];
69
69
  assert.ok(countryCode, `Could not find RR0 country to map from NUFORC code ${countryCode}`);
70
- const country = this.countryService.get(countryCode);
70
+ const country = this.countryService.getById(countryCode);
71
71
  assert.ok(country, `Could not find country "${countryCode}"`);
72
72
  const placeItems = /(.+?)(:?\s+\((.+)\))?$/.exec(sourceCase.city);
73
73
  const placeName = placeItems[1];
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@rr0/cms",
3
3
  "type": "module",
4
4
  "author": "Jérôme Beau <rr0@rr0.org> (https://rr0.org)",
5
- "version": "0.3.31",
5
+ "version": "0.3.33",
6
6
  "description": "RR0 Content Management System (CMS)",
7
7
  "exports": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
@@ -30,7 +30,7 @@
30
30
  "dependencies": {
31
31
  "@javarome/fileutil": "^0.3.7",
32
32
  "@rr0/common": "^1.1.3",
33
- "@rr0/data": "^0.3.27",
33
+ "@rr0/data": "^0.3.30",
34
34
  "@rr0/lang": "^0.1.12",
35
35
  "@rr0/place": "^0.5.3",
36
36
  "@rr0/time": "^0.11.0",