@schukai/monster 3.26.0 → 3.28.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  import {Embed} from '@schukai/monster/source/i18n/providers/embed.mjs';
2
2
 
3
- // read from scritp tag with id i18n
3
+ // read from script tag with id i18n
4
4
  const translation = new Embed('i18n');
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schukai/monster",
3
- "version": "3.26.0",
3
+ "version": "3.28.0",
4
4
  "description": "Monster is a simple library for creating fast, robust and lightweight websites.",
5
5
  "keywords": [
6
6
  "framework",
@@ -295,25 +295,45 @@ class CustomElement extends HTMLElement {
295
295
  * Before you can use this method, you must have loaded the translations.
296
296
  *
297
297
  * @returns {Monster.DOM.CustomElement}
298
+ * @throws {Error} Cannot find element with translations. Add a translations object to the document.
298
299
  */
299
300
  updateI18n() {
300
-
301
301
  const translations = getDocumentTranslations();
302
302
  if (!translations) {
303
303
  return this;
304
304
  }
305
305
 
306
- const labels = this.getOption("labels");
307
- if (!isIterable(labels)) {
306
+ let labels = this.getOption("labels");
307
+ if (!(isObject(labels) || isIterable(labels))) {
308
308
  return this;
309
309
  }
310
310
 
311
311
  for (const key in labels) {
312
- const text = translations.getText(key, labels[key]);
313
- if (text !== labels[key]) {
314
- this.setOption("labels." + key, text);
312
+ const def = labels[key];
313
+
314
+ if (isString(def)) {
315
+ const text = translations.getText(key, def);
316
+ if (text !== def) {
317
+ this.setOption("labels." + key, text);
318
+ }
319
+ continue;
320
+ } else if (isObject(def)) {
321
+ for (const k in def) {
322
+ const d = def[k];
323
+
324
+ const text = translations.getPluralRuleText(key, k, d);
325
+ if (!isString(text)) {
326
+ throw new Error("Invalid labels definition");
327
+ }
328
+ if (text !== d) {
329
+ this.setOption("labels." + key + "." + k, text);
330
+ }
331
+ }
332
+ continue;
315
333
  }
316
334
 
335
+ throw new Error("Invalid labels definition");
336
+
317
337
  }
318
338
  return this;
319
339
  }
@@ -973,10 +993,10 @@ function registerCustomElement(element) {
973
993
  if (customElements === undefined) {
974
994
  throw new Error("customElements is not supported.");
975
995
  }
976
-
996
+
977
997
  if (customElements.get(element.getTag()) !== undefined) {
978
998
  return;
979
999
  }
980
-
1000
+
981
1001
  customElements.define(element.getTag(), element);
982
1002
  }
@@ -5,14 +5,14 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
- import { internalSymbol } from "../constants.mjs";
9
- import { extend } from "../data/extend.mjs";
8
+ import {instanceSymbol, internalSymbol} from "../constants.mjs";
9
+ import {extend} from "../data/extend.mjs";
10
10
 
11
- import { Formatter as TextFormatter } from "../text/formatter.mjs";
12
- import { validateInstance, validateString } from "../types/validate.mjs";
13
- import { Translations } from "./translations.mjs";
11
+ import {Formatter as TextFormatter} from "../text/formatter.mjs";
12
+ import {validateInstance, validateString} from "../types/validate.mjs";
13
+ import {Translations} from "./translations.mjs";
14
14
 
15
- export { Formatter };
15
+ export {Formatter};
16
16
 
17
17
  /**
18
18
  * @private
@@ -41,6 +41,15 @@ class Formatter extends TextFormatter {
41
41
  this[internalTranslationSymbol] = validateInstance(translation, Translations);
42
42
  }
43
43
 
44
+ /**
45
+ * This method is called by the `instanceof` operator.
46
+ * @returns {symbol}
47
+ * @since 3.27.0
48
+ */
49
+ static get [instanceSymbol]() {
50
+ return Symbol.for("@schukai/monster/i18n/formatter@@instance");
51
+ }
52
+
44
53
  /**
45
54
  * @property {object} marker
46
55
  * @property {array} marker.open=["i18n{","${"]
@@ -5,6 +5,7 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
+ import {instanceSymbol} from "../constants.mjs";
8
9
  import { Base } from "../types/base.mjs";
9
10
  import { validateString } from "../types/validate.mjs";
10
11
  import { clone } from "../util/clone.mjs";
@@ -100,6 +101,15 @@ class Locale extends Base {
100
101
  this[localeStringSymbol] = s.join("-");
101
102
  }
102
103
 
104
+ /**
105
+ * This method is called by the `instanceof` operator.
106
+ * @returns {symbol}
107
+ * @since 3.27.0
108
+ */
109
+ static get [instanceSymbol]() {
110
+ return Symbol.for("@schukai/monster/i18n/locale@@instance");
111
+ }
112
+
103
113
  /**
104
114
  * @return {string}
105
115
  */
@@ -5,6 +5,7 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
+ import {instanceSymbol} from "../constants.mjs";
8
9
  import {hasObjectLink, getLinkedObjects,addToObjectLink} from "../dom/attributes.mjs";
9
10
  import {getLocaleOfDocument} from "../dom/locale.mjs";
10
11
  import {BaseWithOptions} from "../types/basewithoptions.mjs";
@@ -32,6 +33,16 @@ const translationsLinkSymbol = Symbol.for("@schukai/monster/i18n/translations@@l
32
33
  * @see {@link https://datatracker.ietf.org/doc/html/rfc3066}
33
34
  */
34
35
  class Provider extends BaseWithOptions {
36
+
37
+ /**
38
+ * This method is called by the `instanceof` operator.
39
+ * @returns {symbol}
40
+ * @since 3.27.0
41
+ */
42
+ static get [instanceSymbol]() {
43
+ return Symbol.for("@schukai/monster/i18n/provider@@instance");
44
+ }
45
+
35
46
  /**
36
47
  * @param {Locale|string} locale
37
48
  * @return {Promise}
@@ -5,7 +5,8 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
- import { getLinkedObjects,hasObjectLink} from "../dom/attributes.mjs";
8
+ import {instanceSymbol} from "../constants.mjs";
9
+ import {getLinkedObjects, hasObjectLink} from "../dom/attributes.mjs";
9
10
  import {ATTRIBUTE_OBJECTLINK} from "../dom/constants.mjs";
10
11
  import {getDocument} from "../dom/util.mjs";
11
12
  import {Base} from "../types/base.mjs";
@@ -44,6 +45,15 @@ class Translations extends Base {
44
45
  this.storage = new Map();
45
46
  }
46
47
 
48
+ /**
49
+ * This method is called by the `instanceof` operator.
50
+ * @returns {symbol}
51
+ * @since 3.27.0
52
+ */
53
+ static get [instanceSymbol]() {
54
+ return Symbol.for("@schukai/monster/i18n/translations@@instance");
55
+ }
56
+
47
57
  /**
48
58
  * Fetches a text using the specified key.
49
59
  * If no suitable key is found, `defaultText` is taken.
@@ -94,7 +104,7 @@ class Translations extends Base {
94
104
  } else {
95
105
  count = validateInteger(count);
96
106
  if (count === 0) {
97
- // special handlig for zero count
107
+ // special handling for zero count
98
108
  if (r.hasOwnProperty("zero")) {
99
109
  return validateString(r["zero"]);
100
110
  }
@@ -107,9 +117,11 @@ class Translations extends Base {
107
117
  return validateString(r[keyword]);
108
118
  }
109
119
 
110
- if (r.hasOwnProperty(DEFAULT_KEY)) {
111
- return validateString(r[DEFAULT_KEY]);
112
- }
120
+ // @deprecated since 2023-03-14
121
+ // DEFAULT_KEY is undefined
122
+ // if (r.hasOwnProperty(DEFAULT_KEY)) {
123
+ // return validateString(r[DEFAULT_KEY]);
124
+ // }
113
125
 
114
126
  return validateString(defaultText);
115
127
  }
@@ -171,7 +183,7 @@ class Translations extends Base {
171
183
  */
172
184
  assignTranslations(translations) {
173
185
  validateObject(translations);
174
-
186
+
175
187
  if (translations instanceof Translations) {
176
188
  translations.storage.forEach((v, k) => {
177
189
  this.setText(k, v);
@@ -202,7 +214,7 @@ function getDocumentTranslations(element) {
202
214
  const d = getDocument()
203
215
 
204
216
  if (!(element instanceof HTMLElement)) {
205
- element = d.querySelector('['+ATTRIBUTE_OBJECTLINK+'~="' + translationsLinkSymbol.toString() + '"]');
217
+ element = d.querySelector('[' + ATTRIBUTE_OBJECTLINK + '~="' + translationsLinkSymbol.toString() + '"]');
206
218
  if (element === null) {
207
219
  throw new Error("Cannot find element with translations. Add a translations object to the document.");
208
220
  }
@@ -215,9 +227,9 @@ function getDocumentTranslations(element) {
215
227
  if (!hasObjectLink(element, translationsLinkSymbol)) {
216
228
  throw new Error("This element has no translations.");
217
229
  }
218
-
230
+
219
231
  let obj = getLinkedObjects(element, translationsLinkSymbol);
220
-
232
+
221
233
  for (const t of obj) {
222
234
  if (t instanceof Translations) {
223
235
  return t;
@@ -142,7 +142,7 @@ function getMonsterVersion() {
142
142
  }
143
143
 
144
144
  /** don't touch, replaced by make with package.json version */
145
- monsterVersion = new Version("3.26.0");
145
+ monsterVersion = new Version("3.28.0");
146
146
 
147
147
  return monsterVersion;
148
148
  }
@@ -7,7 +7,7 @@ describe('Monster', function () {
7
7
  let monsterVersion
8
8
 
9
9
  /** don´t touch, replaced by make with package.json version */
10
- monsterVersion = new Version("3.26.0")
10
+ monsterVersion = new Version("3.28.0")
11
11
 
12
12
  let m = getMonsterVersion();
13
13