@rr0/cms 0.3.76 → 0.3.78
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/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/TimeElementFactory.js +2 -1
- package/dist/time/html/TimeReplacer.d.ts +5 -1
- package/dist/time/html/TimeReplacer.js +15 -1
- package/dist/time/html/TimeReplacer.test.js +9 -0
- package/package.json +1 -1
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();
|
|
@@ -53,12 +53,13 @@ export class TimeElementFactory {
|
|
|
53
53
|
return replacement;
|
|
54
54
|
}
|
|
55
55
|
createStarting(fromContext, previousContext, options) {
|
|
56
|
+
options = { ...options, relativeWords: false }; // Not "à partir de l'année suivante"
|
|
56
57
|
const { result, replacement } = this.renderer.renderContent(fromContext, previousContext, options);
|
|
57
58
|
let startingReplacement;
|
|
58
59
|
startingReplacement = fromContext.file.document.createElement("span");
|
|
59
60
|
startingReplacement.className = "time-interval";
|
|
60
61
|
const approximate = !fromContext.time.getDayOfMonth();
|
|
61
|
-
startingReplacement.
|
|
62
|
+
startingReplacement.textContent = fromContext.messages.context.time.starting(approximate);
|
|
62
63
|
result.append(startingReplacement, replacement);
|
|
63
64
|
return result;
|
|
64
65
|
}
|
|
@@ -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,15 @@ 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
|
+
});
|
|
244
|
+
test("including the one of an open interval", async () => {
|
|
245
|
+
expect(await renderAfter("fr", "<time>2005</time>. <time>2006/</time>")).toBe("à partir de 2006");
|
|
246
|
+
expect(await renderAfter("en", "<time>2005</time>. <time>2006/</time>")).toBe("starting 2006");
|
|
247
|
+
});
|
|
239
248
|
});
|
|
240
249
|
test("avoids linking to current file", async () => {
|
|
241
250
|
const context = cmsTestUtil.time.newHtmlContext("1/9/9/0/08/index.html", "");
|
package/package.json
CHANGED