@rr0/cms 0.1.19 → 0.1.21

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.
@@ -1,9 +1,28 @@
1
1
  import { TimeServiceOptions } from "./time";
2
2
  import { FileWriteConfig } from "ssg-api";
3
3
  import { PeopleDirectoryStepOptions } from "./people";
4
+ export interface RR0BuildOptions {
5
+ contentRoots: string[];
6
+ copies: string[];
7
+ outDir: string;
8
+ locale: string;
9
+ googleMapsApiKey: string;
10
+ mail: string;
11
+ timeOptions: TimeServiceOptions;
12
+ siteBaseUrl: string;
13
+ timeFormat: Intl.DateTimeFormatOptions;
14
+ timeFiles: string[];
15
+ directoryPages: string[];
16
+ ufoCaseDirectoryFile: string;
17
+ ufoCasesExclusions: string[];
18
+ sourceRegistryFileName: string;
19
+ directoryExcluded: string[];
20
+ directoryOptions: PeopleDirectoryStepOptions;
21
+ inDir?: (path: string) => string;
22
+ }
4
23
  export interface RR0BuildArgs {
5
24
  /**
6
- * Configuration file
25
+ * Configuration file name.
7
26
  */
8
27
  config?: string;
9
28
  /**
@@ -29,19 +48,7 @@ export interface RR0BuildArgs {
29
48
  force?: string;
30
49
  }
31
50
  export declare class RR0Build {
32
- protected contentRoots: string[];
33
- protected copies: string[];
34
- protected outDir: string;
35
- protected timeOptions: TimeServiceOptions;
36
- protected siteBaseUrl: string;
37
- protected timeFormat: Intl.DateTimeFormatOptions;
38
- protected timeFiles: string[];
39
- protected directoryPages: string[];
40
- protected ufoCaseDirectoryFile: string;
41
- protected ufoCasesExclusions: string[];
42
- protected sourceRegistryFileName: string;
43
- protected directoryExcluded: string[];
44
- protected directoryOptions: PeopleDirectoryStepOptions;
51
+ protected options: RR0BuildOptions;
45
52
  config: FileWriteConfig;
46
53
  private context;
47
54
  private placeService;
@@ -51,6 +58,6 @@ export declare class RR0Build {
51
58
  private dataService;
52
59
  private peopleFactory;
53
60
  private timeTextBuilder;
54
- constructor(contentRoots: string[], copies: string[], outDir: string, locale: string, googleMapsApiKey: string, mail: string, timeOptions: TimeServiceOptions, siteBaseUrl: string, timeFormat: Intl.DateTimeFormatOptions, timeFiles: string[], directoryPages: string[], ufoCaseDirectoryFile: string, ufoCasesExclusions: string[], sourceRegistryFileName: string, directoryExcluded: string[], directoryOptions: PeopleDirectoryStepOptions);
61
+ constructor(options: RR0BuildOptions);
55
62
  run(args: RR0BuildArgs): Promise<void>;
56
63
  }
package/dist/RR0Build.js CHANGED
@@ -41,33 +41,23 @@ const outputFunc = async (context, outFile) => {
41
41
  }
42
42
  };
43
43
  export class RR0Build {
44
- constructor(contentRoots, copies, outDir, locale, googleMapsApiKey, mail, timeOptions, siteBaseUrl, timeFormat, timeFiles, directoryPages, ufoCaseDirectoryFile, ufoCasesExclusions, sourceRegistryFileName, directoryExcluded, directoryOptions) {
45
- this.contentRoots = contentRoots;
46
- this.copies = copies;
47
- this.outDir = outDir;
48
- this.timeOptions = timeOptions;
49
- this.siteBaseUrl = siteBaseUrl;
50
- this.timeFormat = timeFormat;
51
- this.timeFiles = timeFiles;
52
- this.directoryPages = directoryPages;
53
- this.ufoCaseDirectoryFile = ufoCaseDirectoryFile;
54
- this.ufoCasesExclusions = ufoCasesExclusions;
55
- this.sourceRegistryFileName = sourceRegistryFileName;
56
- this.directoryExcluded = directoryExcluded;
57
- this.directoryOptions = directoryOptions;
44
+ constructor(options) {
45
+ this.options = options;
58
46
  this.config = {
59
47
  getOutputPath(context) {
60
- return path.join(outDir, context.file.name);
48
+ return path.join(options.outDir, context.file.name);
61
49
  }
62
50
  };
63
51
  const timeContext = new TimeContext();
64
- const context = this.context = new RR0ContextImpl(locale, timeContext, this.config);
65
- context.setVar("mapsApiKey", googleMapsApiKey);
66
- context.setVar("mail", mail);
67
- this.placeService = new GooglePlaceService("place", googleMapsApiKey);
52
+ const context = this.context = new RR0ContextImpl(options.locale, timeContext, this.config);
53
+ context.setVar("mapsApiKey", options.googleMapsApiKey);
54
+ context.setVar("mail", options.mail);
55
+ this.placeService = new GooglePlaceService("place", options.googleMapsApiKey);
68
56
  this.orgService = new OrganizationService([], "org", undefined);
69
- const timeTextBuilder = this.timeTextBuilder = new TimeTextBuilder(timeFormat);
70
- const timeUrlBuilder = new TimeUrlBuilder({ rootDir: timeOptions.root });
57
+ const timeTextBuilder = this.timeTextBuilder = new TimeTextBuilder(options.timeFormat);
58
+ const timeOptions = options.timeOptions;
59
+ const timeRoot = this.options.inDir(timeOptions.root);
60
+ const timeUrlBuilder = new TimeUrlBuilder({ rootDir: timeRoot });
71
61
  const eventFactory = new RR0EventFactory();
72
62
  const sightingFactory = new TypedDataFactory(eventFactory, "sighting", ["index"]);
73
63
  const orgFactory = new OrganizationFactory(eventFactory);
@@ -84,7 +74,7 @@ export class RR0Build {
84
74
  }
85
75
  async run(args) {
86
76
  const context = this.context;
87
- const timeFiles = this.timeFiles;
77
+ const timeFiles = this.options.timeFiles;
88
78
  context.setVar("timeFilesCount", timeFiles.length);
89
79
  const timeService = this.timeService;
90
80
  const timeElementFactory = new TimeElementFactory(timeService.renderer);
@@ -99,13 +89,19 @@ export class RR0Build {
99
89
  const bookMeta = new Map();
100
90
  const bookLinks = new Map();
101
91
  const config = this.config;
102
- const ufoCasesStep = new CaseDirectoryStep(caseService, caseService.files, this.ufoCasesExclusions, this.ufoCaseDirectoryFile, outputFunc, config);
103
- const peopleDirectoryFactory = new PeopleDirectoryStepFactory(outputFunc, config, peopleService, this.directoryExcluded);
104
- const peopleSteps = await peopleDirectoryFactory.create(this.directoryOptions);
92
+ const ufoCaseDirectoryFile = this.options.inDir(this.options.ufoCaseDirectoryFile);
93
+ const ufoCasesExclusions = this.options.ufoCasesExclusions.map(this.options.inDir);
94
+ const ufoCasesStep = new CaseDirectoryStep(caseService, caseService.files, ufoCasesExclusions, ufoCaseDirectoryFile, outputFunc, config);
95
+ const peopleDirectoryFactory = new PeopleDirectoryStepFactory(outputFunc, config, peopleService, this.options.directoryExcluded);
96
+ const directoryOptions = this.options.directoryOptions;
97
+ for (const directoryOption in directoryOptions) {
98
+ directoryOptions[directoryOption] = this.options.inDir(directoryOptions[directoryOption]);
99
+ }
100
+ const peopleSteps = await peopleDirectoryFactory.create(directoryOptions);
105
101
  // Publish case.json files so that vraiufo.com will find them
106
- const copies = this.copies;
102
+ const copies = this.options.copies;
107
103
  copies.push(...(ufoCasesStep.config.rootDirs).map(dir => path.join(dir, "case.json")));
108
- const outDir = this.outDir;
104
+ const outDir = this.options.outDir;
109
105
  await writeFile(path.join(outDir, "casesDirs.json"), JSON.stringify(ufoCasesStep.config.rootDirs), "utf-8");
110
106
  copies.push(...(peopleSteps.reduce((rootDirs, peopleStep) => {
111
107
  rootDirs.push(...peopleStep.config.rootDirs);
@@ -116,9 +112,10 @@ export class RR0Build {
116
112
  const searchVisitor = new SearchVisitor({ notIndexedUrls: ["404.html", "Referencement.html"], indexWords: false }, timeTextBuilder);
117
113
  const sourceRenderer = new SourceRenderer(timeTextBuilder);
118
114
  const http = new HttpSource();
119
- const baseUrl = this.siteBaseUrl;
120
- const timeFormat = this.timeFormat;
121
- const sourceFactory = new PersistentSourceRegistry(dataService, http, baseUrl, this.sourceRegistryFileName, timeFormat);
115
+ const baseUrl = this.options.siteBaseUrl;
116
+ const timeFormat = this.options.timeFormat;
117
+ const sourceRegistryFileName = this.options.inDir(this.options.sourceRegistryFileName);
118
+ const sourceFactory = new PersistentSourceRegistry(dataService, http, baseUrl, sourceRegistryFileName, timeFormat);
122
119
  const noteCounter = new NoteFileCounter();
123
120
  const noteRenderer = new NoteRenderer(noteCounter);
124
121
  const caseRenderer = new CaseSummaryRenderer(noteRenderer, sourceFactory, sourceRenderer, timeElementFactory);
@@ -171,7 +168,7 @@ export class RR0Build {
171
168
  const ssg = new Ssg(config);
172
169
  const getOutputPath = (context) => path.join(outDir, context.file.name);
173
170
  const force = args.force === "true";
174
- const toProcess = new Set(this.directoryPages);
171
+ const toProcess = new Set(this.options.directoryPages);
175
172
  const csvTransformer = new class {
176
173
  transform(context, file) {
177
174
  const fileName = file.name;
@@ -191,10 +188,17 @@ export class RR0Build {
191
188
  return path.join(outDir, "netlify.toml");
192
189
  }
193
190
  };
194
- const contentRoots = this.contentRoots;
191
+ const options = this.options;
192
+ const contentRoots = options.contentRoots.map(options.inDir);
195
193
  const includeStep = new RR0ContentStep([htAccessToNetlifyConfig, {
196
194
  roots: contentRoots,
197
- replacements: [new SsiIncludeReplaceCommand([csvTransformer])],
195
+ replacements: [new class extends SsiIncludeReplaceCommand {
196
+ filePath(context, fileNameArg) {
197
+ const dirName = path.dirname(context.file.name);
198
+ return fileNameArg.startsWith("/") ?
199
+ path.join(process.cwd(), options.inDir(fileNameArg)) : path.join(dirName, fileNameArg);
200
+ }
201
+ }([csvTransformer])],
198
202
  getOutputPath
199
203
  }], outputFunc, [], [], force, "content includes", toProcess);
200
204
  ssg.add(includeStep);
@@ -224,13 +228,13 @@ export class RR0Build {
224
228
  ssg.add(new SearchIndexStep("search/index.json", searchVisitor));
225
229
  }
226
230
  if (reindex === null || reindex === void 0 ? void 0 : reindex.includes("sources")) {
227
- ssg.add(new SourceIndexStep(this.sourceRegistryFileName, sourceFactory));
231
+ ssg.add(new SourceIndexStep(sourceRegistryFileName, sourceFactory));
228
232
  }
229
233
  if (copies) {
230
234
  const copyConfig = {
231
235
  getOutputPath,
232
- sourcePatterns: copies,
233
- options: { ignore: ["node_modules/**", "out/**"] }
236
+ sourcePatterns: copies.map(this.options.inDir),
237
+ options: { ignore: ["node_modules/**", "out/**"].map(this.options.inDir) }
234
238
  };
235
239
  ssg.add(new CopyStep(copyConfig));
236
240
  }
@@ -1,13 +1,10 @@
1
- import path from "path";
2
1
  import { glob } from "glob";
3
2
  import { describe } from "@javarome/testscript";
4
3
  import { FileContents } from "@javarome/fileutil";
5
4
  import { CLI } from "./util/index.js";
6
5
  import { RR0Build } from "./RR0Build.js";
7
- import { rr0TestUtil } from "./test";
8
- function testFilePath(filePath) {
9
- return path.join(rr0TestUtil.rootDir, filePath);
10
- }
6
+ import { testFilePath } from "./test";
7
+ import * as process from "node:process";
11
8
  describe("Build", () => {
12
9
  console.time("ssg");
13
10
  let args = new CLI().getArgs();
@@ -50,14 +47,14 @@ describe("Build", () => {
50
47
  "time/DualRangeComponent.mjs",
51
48
  "index/index.js", "lang/form.js", "lang/form.css", "lang/speech.js", "lang/speech.css",
52
49
  "croyance/divin/theisme/mono/livre/islam/coran/index.js"
53
- ].map(testFilePath);
50
+ ];
54
51
  const outDir = "out";
55
52
  const googleMapsApiKey = process.env.GOOGLE_MAPS_API_KEY;
56
53
  if (!googleMapsApiKey) {
57
54
  throw Error("GOOGLE_MAPS_API_KEY is required");
58
55
  }
59
56
  const timeOptions = {
60
- root: testFilePath("time"),
57
+ root: "time",
61
58
  files: []
62
59
  };
63
60
  const timeFormat = {
@@ -85,22 +82,31 @@ describe("Build", () => {
85
82
  ].map(testFilePath);
86
83
  getTimeFiles().then(async (timeFiles) => {
87
84
  const directoryOptions = {
88
- root: testFilePath("people/index.html"),
89
- scientists: testFilePath("people/scientifiques.html"),
90
- ufologists: testFilePath("people/ufologues.html"),
91
- ufoWitnesses: testFilePath("people/witness/index.html"),
92
- astronomers: testFilePath("people/astronomes.html"),
93
- contactees: testFilePath("people/contactes.html"),
94
- pilots: testFilePath("people/pilotes.html"),
95
- military: testFilePath("people/militaires.html"),
96
- softwareEngineers: testFilePath("tech/info/Personnes.html"),
97
- politicians: testFilePath("people/politicians.html"),
98
- rulers: testFilePath("people/dirigeants.html")
85
+ root: "people/index.html",
86
+ scientists: "people/scientifiques.html",
87
+ ufologists: "people/ufologues.html",
88
+ ufoWitnesses: "people/witness/index.html",
89
+ astronomers: "people/astronomes.html",
90
+ contactees: "people/contactes.html",
91
+ pilots: "people/pilotes.html",
92
+ military: "people/militaires.html",
93
+ softwareEngineers: "tech/info/Personnes.html",
94
+ politicians: "people/politicians.html",
95
+ rulers: "people/dirigeants.html"
99
96
  };
100
- const sourceRegistryFileName = testFilePath("source/index.json");
97
+ const sourceRegistryFileName = "source/index.json";
101
98
  const siteBaseUrl = "https://rr0.org/";
102
99
  const mail = "rr0@rr0.org";
103
- const build = new RR0Build(contentRoots, copies, outDir, "fr", googleMapsApiKey, mail, timeOptions, siteBaseUrl, timeFormat, timeFiles, directoryPages, testFilePath("science/crypto/ufo/enquete/dossier/index.html"), [testFilePath("science/crypto/ufo/enquete/dossier/canular")], sourceRegistryFileName, ["people/Astronomers_fichiers", "people/witness", "people/author"], directoryOptions);
100
+ const build = new RR0Build({
101
+ contentRoots, copies, outDir, locale: "fr", googleMapsApiKey, mail, timeOptions,
102
+ siteBaseUrl, timeFormat, timeFiles, directoryPages,
103
+ ufoCaseDirectoryFile: "science/crypto/ufo/enquete/dossier/index.html",
104
+ ufoCasesExclusions: ["science/crypto/ufo/enquete/dossier/canular"],
105
+ sourceRegistryFileName,
106
+ directoryExcluded: ["people/Astronomers_fichiers", "people/witness", "people/author"],
107
+ directoryOptions,
108
+ inDir: testFilePath
109
+ });
104
110
  await build.run(args);
105
111
  });
106
112
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ import { ConsoleLogger } from "ssg-api";
2
+ import { CLI } from "../util/cli/CLI.js";
3
+ import path from "path";
4
+ import { PeopleFactory, PeopleService } from "../people";
5
+ import { AllDataService, RR0EventFactory, TypedDataFactory } from "@rr0/data";
6
+ import { BookService } from "./BookService";
7
+ import { TimeUrlBuilder } from "../time";
8
+ import { testFilePath } from "../test";
9
+ const logger = new ConsoleLogger("rr0-books");
10
+ const args = new CLI().getArgs();
11
+ const fileName = args.import;
12
+ const dry = args.dry === "true";
13
+ const peopleFactory = new PeopleFactory(new RR0EventFactory());
14
+ const eventFactory = new RR0EventFactory();
15
+ const bookFactory = new TypedDataFactory(eventFactory, "book");
16
+ const dataService = new AllDataService([bookFactory, peopleFactory]);
17
+ const outDir = "out";
18
+ const config = {
19
+ getOutputPath(context) {
20
+ return path.join(outDir, context.file.name);
21
+ }
22
+ };
23
+ const timeOptions = {
24
+ root: testFilePath("time"),
25
+ files: []
26
+ };
27
+ const timeUrlBuilder = new TimeUrlBuilder({ rootDir: timeOptions.root });
28
+ let files = [];
29
+ const books = new BookService(logger, dry, new PeopleService(dataService, peopleFactory, files), timeUrlBuilder, config);
30
+ books.import(fileName).then((result) => {
31
+ logger.log("Wrote", result.length, "books");
32
+ });
@@ -19,3 +19,4 @@ export declare class RR0TestUtil {
19
19
  newHtmlContext(inputFileName: string, contents?: string, locale?: string): HtmlRR0Context;
20
20
  }
21
21
  export declare const rr0TestUtil: RR0TestUtil;
22
+ export declare function testFilePath(filePath: string): string;
@@ -65,8 +65,12 @@ export class RR0TestUtil {
65
65
  const lang = currentFile.lang;
66
66
  context.file = new HtmlFileContents(currentFile.name, currentFile.encoding, currentFile.contents, currentFile.lastModified, lang, { author: [] }, {}, title);
67
67
  const htmlContext = context;
68
- Object.assign(htmlContext.time, Time.contextFromFileName(htmlContext, inputFileName));
68
+ const timeContext = Time.contextFromFileName(htmlContext, inputFileName);
69
+ Object.assign(htmlContext.time, timeContext);
69
70
  return htmlContext;
70
71
  }
71
72
  }
72
73
  export const rr0TestUtil = new RR0TestUtil();
74
+ export function testFilePath(filePath) {
75
+ return path.join(rr0TestUtil.rootDir, filePath);
76
+ }
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.1.19",
5
+ "version": "0.1.21",
6
6
  "description": "RR0 Content Management System (CMS)",
7
7
  "exports": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "build": "rm -Rf dist && tsc --project tsconfig.prod.json",
24
24
  "prepublishOnly": "npm run build",
25
25
  "test": "testscript",
26
- "test-one": "rm -Rf out && tsx src/time/datasource/JsonMapper.test.ts",
26
+ "test-one": "rm -Rf out && tsx src/RR0Build.test.ts",
27
27
  "test-ci": "rm -Rf out && testscript"
28
28
  },
29
29
  "dependencies": {
@@ -34,7 +34,7 @@
34
34
  "@rr0/place": "^0.3.2",
35
35
  "@rr0/data": "^0.1.2",
36
36
  "@javarome/fileutil": "^0.3.6",
37
- "ssg-api": "^1.16.10",
37
+ "ssg-api": "^1.16.11",
38
38
  "canvas": "^2.11.2",
39
39
  "csv-parser": "^3.0.0",
40
40
  "glob": "^11.0.0",