@rr0/cms 0.3.77 → 0.3.79
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.
- package/dist/DataContentVisitor.js +4 -0
- package/dist/DataContentVisitor.test.js +10 -0
- package/dist/RR0Context.d.ts +5 -0
- package/dist/RR0Context.js +8 -1
- package/dist/lang/LanguageReplaceCommand.js +3 -1
- package/dist/lang/LanguageReplaceCommand.test.js +6 -0
- package/dist/time/html/TimeReplacer.d.ts +5 -1
- package/dist/time/html/TimeReplacer.js +15 -1
- package/dist/time/html/TimeReplacer.test.js +5 -0
- package/package.json +2 -2
|
@@ -47,6 +47,10 @@ export class DataContentVisitor {
|
|
|
47
47
|
await this.processDeath(context, event, data);
|
|
48
48
|
break;
|
|
49
49
|
case "sighting":
|
|
50
|
+
// An analyst's reading of one of the case's sightings (a UFO@home interpretation: bodies in
|
|
51
|
+
// metres, which the player stands in the scene and measures against the account). Nothing
|
|
52
|
+
// to write in the page: the player reads it from the case.json, so it only needs the player.
|
|
53
|
+
case "interpretation":
|
|
50
54
|
this.processSighting(context, data);
|
|
51
55
|
break;
|
|
52
56
|
default:
|
|
@@ -50,6 +50,16 @@ describe("DataContentVisitor", () => {
|
|
|
50
50
|
// Nothing else: no dated paragraph per sighting, which a sighting without a time used to fail the build on.
|
|
51
51
|
expect(context.file.document.querySelectorAll(".contents > p").length).toBe(1);
|
|
52
52
|
});
|
|
53
|
+
test("shows an analyst's interpretation through the same player, and writes nothing else", async () => {
|
|
54
|
+
const interpretation = { type: "event", eventType: "interpretation", sighting: "2015-05-31-T1", by: [{ org: "GEIPAN" }] };
|
|
55
|
+
const context = cmsTestUtil.newHtmlContext("people/v/VertongenJeanLuc/index.html", "<div class=\"contents\"><p>Le dossier</p></div>");
|
|
56
|
+
const visitor = new TestDataContentVisitor();
|
|
57
|
+
await visitor.renderEvent(context, sightingEvent, aCase);
|
|
58
|
+
// No time: it used to fail the build, then to be appended outside the page.
|
|
59
|
+
await visitor.renderEvent(context, interpretation, aCase);
|
|
60
|
+
expect(context.file.document.querySelectorAll(".contents > rr0-sighting").length).toBe(1);
|
|
61
|
+
expect(context.file.document.querySelectorAll("p").length).toBe(1);
|
|
62
|
+
});
|
|
53
63
|
test("leaves a player the page's author placed alone", async () => {
|
|
54
64
|
const context = cmsTestUtil.newHtmlContext("people/v/VertongenJeanLuc/index.html", "<div class=\"contents\"><p>Le dossier</p><rr0-sighting src=\"case.json\" show-witness-map></rr0-sighting></div>");
|
|
55
65
|
const visitor = new TestDataContentVisitor();
|
package/dist/RR0Context.d.ts
CHANGED
|
@@ -29,7 +29,12 @@ export declare class RR0ContextImpl extends SsgContextImpl {
|
|
|
29
29
|
readonly images: Set<string>;
|
|
30
30
|
protected readonly fileMap: Map<string, FileContents>;
|
|
31
31
|
place: PlaceContext;
|
|
32
|
+
/**
|
|
33
|
+
* The language of a passage that differs from its page's (<blockquote lang="en"> in a French page).
|
|
34
|
+
*/
|
|
35
|
+
protected localeOverride?: string;
|
|
32
36
|
constructor(locale: string, time: TimeContext, config: FileWriteConfig, people?: any, currentFile?: FileContents | undefined, _messages?: RR0Messages, cms?: CMSContext);
|
|
37
|
+
get locale(): string;
|
|
33
38
|
get messages(): RR0Messages;
|
|
34
39
|
read(filePath: string): FileContents;
|
|
35
40
|
clone(locale?: string): RR0ContextImpl;
|
package/dist/RR0Context.js
CHANGED
|
@@ -13,6 +13,10 @@ export class RR0ContextImpl extends SsgContextImpl {
|
|
|
13
13
|
this.fileMap = new Map();
|
|
14
14
|
this.place = new PlaceContext(locale, this.messages.context.place);
|
|
15
15
|
}
|
|
16
|
+
get locale() {
|
|
17
|
+
var _a;
|
|
18
|
+
return (_a = this.localeOverride) !== null && _a !== void 0 ? _a : super.locale;
|
|
19
|
+
}
|
|
16
20
|
get messages() {
|
|
17
21
|
let messages = this._messages;
|
|
18
22
|
if (!messages) {
|
|
@@ -43,7 +47,10 @@ export class RR0ContextImpl extends SsgContextImpl {
|
|
|
43
47
|
}
|
|
44
48
|
clone(locale = this.locale) {
|
|
45
49
|
var _a;
|
|
46
|
-
|
|
50
|
+
const sameLocale = locale === this.locale;
|
|
51
|
+
const clone = new RR0ContextImpl(locale, this.time.clone(), this.config, (_a = this.people) === null || _a === void 0 ? void 0 : _a.clone(), this._file, sameLocale ? this._messages : undefined, this.cms);
|
|
52
|
+
clone.localeOverride = sameLocale ? this.localeOverride : locale;
|
|
53
|
+
return clone;
|
|
47
54
|
}
|
|
48
55
|
toString() {
|
|
49
56
|
var _a;
|
|
@@ -30,7 +30,9 @@ export class LanguageReplaceCommand extends DomReplaceCommand {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
|
-
|
|
33
|
+
// A file without variant is French, unless it declares otherwise (an English document not translated yet)
|
|
34
|
+
const declared = inputFile.document.querySelector("meta[http-equiv='content-language' i]");
|
|
35
|
+
pageLang = (declared === null || declared === void 0 ? void 0 : declared.content.trim().substring(0, 2).toLowerCase()) || "fr";
|
|
34
36
|
}
|
|
35
37
|
inputFile.document.documentElement.lang = inputFile.lang.lang = pageLang;
|
|
36
38
|
const langVariants = variants.length == 1 && variants[0] == "" ? [pageLang == "fr" ? "en" : "fr"] : variants;
|
|
@@ -8,6 +8,12 @@ describe("LanguageReplaceCommand", () => {
|
|
|
8
8
|
await command.execute(context);
|
|
9
9
|
expect(context.file.contents).toBe(`<html lang="fr"><head><meta name="generator" content="ssg-api"></head><body><span id="alternate"><a href="/${cmsTestUtil.filePath(cmsTestUtil.time.filePath("1/9/6/8/CondonReport/index.html"))}">English version</a></span></body></html>`);
|
|
10
10
|
});
|
|
11
|
+
test("declared language of a file without variant", async () => {
|
|
12
|
+
const context = cmsTestUtil.time.newHtmlContext("1/9/9/0/08/index.html", `<meta http-equiv="content-language" content="en"><span id="alternate"/>`);
|
|
13
|
+
await new LanguageReplaceCommand().execute(context);
|
|
14
|
+
expect(context.file.lang.lang).toBe("en");
|
|
15
|
+
expect(context.file.document.documentElement.lang).toBe("en");
|
|
16
|
+
});
|
|
11
17
|
test("add english translation", async () => {
|
|
12
18
|
const context = cmsTestUtil.time.newHtmlContext("0/6/4/0/ChronicaMinor/index_fr.html", `<span id="alternate"/>`);
|
|
13
19
|
const command = new LanguageReplaceCommand();
|
|
@@ -20,7 +20,11 @@ export declare class TimeReplacer implements DomReplacement<HtmlRR0Context, HTML
|
|
|
20
20
|
* @return The text that precedes an element in its sentence.
|
|
21
21
|
*/
|
|
22
22
|
static precedingText(el: Element): string;
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* @return The language of the passage holding an element, if it differs from its page's.
|
|
25
|
+
*/
|
|
26
|
+
static passageLang(context: HtmlRR0Context, el: Element): string | undefined;
|
|
27
|
+
replacement(pageContext: HtmlRR0Context, origEl: HTMLTimeElement): Promise<HTMLElement>;
|
|
24
28
|
/**
|
|
25
29
|
* Renders a range of durations ("P10M/12M") as "from 10 to 12 minutes".
|
|
26
30
|
*/
|
|
@@ -24,12 +24,23 @@ export class TimeReplacer {
|
|
|
24
24
|
}
|
|
25
25
|
return (_b = (_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.textContent) !== null && _b !== void 0 ? _b : "";
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
/**
|
|
28
|
+
* @return The language of the passage holding an element, if it differs from its page's.
|
|
29
|
+
*/
|
|
30
|
+
static passageLang(context, el) {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
const lang = (_b = (_a = el.closest("[lang]")) === null || _a === void 0 ? void 0 : _a.getAttribute("lang")) === null || _b === void 0 ? void 0 : _b.trim().substring(0, 2).toLowerCase();
|
|
33
|
+
return lang && lang !== context.locale.substring(0, 2) ? lang : undefined;
|
|
34
|
+
}
|
|
35
|
+
async replacement(pageContext, origEl) {
|
|
28
36
|
let replacement;
|
|
29
37
|
if (origEl.dateTime || origEl.dataset.format === "none") { // Already done, or not to be interpreted
|
|
30
38
|
replacement = origEl;
|
|
31
39
|
}
|
|
32
40
|
else {
|
|
41
|
+
// A time in a passage of another language ("<blockquote lang='en'>") is rendered in that language
|
|
42
|
+
const passageLang = TimeReplacer.passageLang(pageContext, origEl);
|
|
43
|
+
const context = passageLang ? pageContext.clone(passageLang) : pageContext;
|
|
33
44
|
const previousContext = origEl.dataset.context === "none" ? undefined : context.clone();
|
|
34
45
|
const timeStr = origEl.textContent;
|
|
35
46
|
const { prefix, value, suffix } = this.completer.split(timeStr);
|
|
@@ -72,6 +83,9 @@ export class TimeReplacer {
|
|
|
72
83
|
wrapper.append(prefix, replacement, suffix);
|
|
73
84
|
replacement = wrapper;
|
|
74
85
|
}
|
|
86
|
+
if (context !== pageContext) {
|
|
87
|
+
pageContext.time = context.time; // The next times of the page follow this one
|
|
88
|
+
}
|
|
75
89
|
context.debug("\tReplacing time", origEl.outerHTML, "with", ObjectUtils.asSet(replacement).outerHTML);
|
|
76
90
|
}
|
|
77
91
|
return replacement;
|
|
@@ -236,6 +236,11 @@ describe("TimeReplacer", async () => {
|
|
|
236
236
|
test("but not without one", async () => {
|
|
237
237
|
expect(await renderAfter("fr", "<time>2005</time>. Puis, <time>2006</time>")).toBe("l'année suivante");
|
|
238
238
|
});
|
|
239
|
+
test("in the language of its passage", async () => {
|
|
240
|
+
expect(await renderAfter("fr", "<time>2005</time>. <q lang=\"en\">in <time>2006</time></q>")).toBe("2006");
|
|
241
|
+
expect(await renderAfter("fr", "<time>2005</time>. <q lang=\"en\">Then <time>2006</time></q>")).toBe("the year after");
|
|
242
|
+
expect(await renderAfter("fr", "<q lang=\"en\"><time>2006</time></q>. <time>2007</time>")).toBe("l'année suivante");
|
|
243
|
+
});
|
|
239
244
|
test("including the one of an open interval", async () => {
|
|
240
245
|
expect(await renderAfter("fr", "<time>2005</time>. <time>2006/</time>")).toBe("à partir de 2006");
|
|
241
246
|
expect(await renderAfter("en", "<time>2005</time>. <time>2006/</time>")).toBe("starting 2006");
|
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.
|
|
5
|
+
"version": "0.3.79",
|
|
6
6
|
"description": "RR0 Content Management System (CMS)",
|
|
7
7
|
"exports": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@javarome/fileutil": "^0.3.9",
|
|
33
33
|
"@rr0/common": "^1.1.5",
|
|
34
|
-
"@rr0/data": "^0.3.
|
|
34
|
+
"@rr0/data": "^0.3.46",
|
|
35
35
|
"@rr0/lang": "^0.1.13",
|
|
36
36
|
"@rr0/place": "^0.5.4",
|
|
37
37
|
"@rr0/time": "^0.11.3",
|