react-i18next 17.0.9 → 17.0.11
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/.eslintcache +1 -0
- package/CHANGELOG.md +11 -0
- package/TransWithoutContext.d.ts +2 -1
- package/dist/amd/react-i18next.js +343 -170
- package/dist/amd/react-i18next.min.js +1 -1
- package/dist/commonjs/TransWithoutContext.js +6 -43
- package/dist/commonjs/useTranslation.js +8 -1
- package/dist/es/TransWithoutContext.js +6 -43
- package/dist/es/package.json +1 -1
- package/dist/es/useTranslation.js +8 -1
- package/dist/umd/react-i18next.js +343 -170
- package/dist/umd/react-i18next.min.js +1 -1
- package/package.json +2 -2
- package/react-i18next.js +343 -170
- package/react-i18next.min.js +1 -1
- package/src/TransWithoutContext.js +8 -80
- package/src/useTranslation.js +16 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## 17.0.11
|
|
2
|
+
|
|
3
|
+
- chore: `html-parse-stringify` updated to `^4.0.1`. The parser powering `<Trans>` is now actively maintained under the i18next org ([i18next/html-parse-stringify](https://github.com/i18next/html-parse-stringify)) after years without upstream releases. 4.x brings modern dual ESM/CJS packaging with an `exports` map, zero runtime dependencies, reworked TypeScript types and a long list of parser fixes (literal `<` in text, multiline/CRLF attribute values, comments containing `>`, doctype handling, quote-aware bracket handling).
|
|
4
|
+
- refactor(Trans): the internal `escapeLiteralLessThan` scanner (~80 lines) is replaced by the parser's new `allowedTags` option with identical semantics: only numbered tags, kept basic HTML tags and known component names are parsed as markup, any other tag-shaped sequence in the translation stays literal text. Rendered output is unchanged (all 493 tests pass, including the [#1880](https://github.com/i18next/react-i18next/issues/1880) and [#1893](https://github.com/i18next/react-i18next/issues/1893) escaping cases).
|
|
5
|
+
|
|
6
|
+
## 17.0.10
|
|
7
|
+
|
|
8
|
+
- fix(warnings): the `useTranslation` and `Trans` "You will need to pass in an i18next instance" warnings now match the `useSSR` wording, mentioning the props/context alternatives and the most common unexplained cause at scale: duplicate react-i18next copies in monorepo setups. The `Trans` variant also referenced the internal `i18nextReactModule` name; it now points to the public `initReactI18next` API.
|
|
9
|
+
- feat(warnings): development-only warning (`SUSPENDED_WHILE_LOADING`, logged once) right before `useTranslation` suspends while translations are loading. With the default `useSuspense: true` and no `<Suspense>` boundary this previously surfaced as a blank screen or a cryptic React error; the warning now names both fixes (add a `<Suspense>` boundary or set `react.useSuspense: false`). No-op in production builds; the `process.env.NODE_ENV` check is wrapped so runtimes without a `process` global (raw ESM in the browser, some edge runtimes) stay silent instead of throwing.
|
|
10
|
+
- ci: weekly workflow typechecking the test suite against `@types/react@next` / `@types/react-dom@next`, so the next React major's type changes (like the React 18 `TFunctionResult`/children wave) surface before user reports.
|
|
11
|
+
|
|
1
12
|
## 17.0.9
|
|
2
13
|
|
|
3
14
|
- fix: allow TypeScript 7 in the optional `typescript` peer dependency range (`^5 || ^6 || ^7`). With `typescript@7.0.2` in a project, `npm install` failed with an `ERESOLVE` peer conflict. Fixes [#1927](https://github.com/i18next/react-i18next/issues/1927), thanks @andikapradanaarif.
|
package/TransWithoutContext.d.ts
CHANGED
|
@@ -128,7 +128,8 @@ export type ErrorCode =
|
|
|
128
128
|
| 'TRANS_INVALID_OBJ'
|
|
129
129
|
| 'TRANS_INVALID_VAR'
|
|
130
130
|
| 'TRANS_INVALID_COMPONENTS'
|
|
131
|
-
| 'USE_T_BEFORE_READY'
|
|
131
|
+
| 'USE_T_BEFORE_READY'
|
|
132
|
+
| 'SUSPENDED_WHILE_LOADING';
|
|
132
133
|
|
|
133
134
|
export type ErrorMeta = {
|
|
134
135
|
code: ErrorCode;
|
|
@@ -93,7 +93,7 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
93
93
|
const deepExtend = (target, source, overwrite) => {
|
|
94
94
|
for (const prop in source) {
|
|
95
95
|
if (prop !== '__proto__' && prop !== 'constructor') {
|
|
96
|
-
if (prop
|
|
96
|
+
if (Object.prototype.hasOwnProperty.call(target, prop)) {
|
|
97
97
|
if (isString$1(target[prop]) || target[prop] instanceof String || isString$1(source[prop]) || source[prop] instanceof String) {
|
|
98
98
|
if (overwrite) target[prop] = source[prop];
|
|
99
99
|
} else {
|
|
@@ -457,11 +457,15 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
457
457
|
} = selector(createProxy());
|
|
458
458
|
const keySeparator = opts?.keySeparator ?? '.';
|
|
459
459
|
const nsSeparator = opts?.nsSeparator ?? ':';
|
|
460
|
+
const strict = opts?.enableSelector === 'strict';
|
|
460
461
|
if (path.length > 1 && nsSeparator) {
|
|
461
462
|
const ns = opts?.ns;
|
|
462
|
-
const
|
|
463
|
-
if (
|
|
464
|
-
|
|
463
|
+
const nsList = strict ? Array.isArray(ns) ? ns : ns ? [ns] : null : Array.isArray(ns) ? ns : null;
|
|
464
|
+
if (nsList) {
|
|
465
|
+
const candidates = strict ? nsList : nsList.length > 1 ? nsList.slice(1) : [];
|
|
466
|
+
if (candidates.includes(path[0])) {
|
|
467
|
+
return `${path[0]}${nsSeparator}${path.slice(1).join(keySeparator)}`;
|
|
468
|
+
}
|
|
465
469
|
}
|
|
466
470
|
}
|
|
467
471
|
return path.join(keySeparator);
|
|
@@ -873,7 +877,10 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
873
877
|
const useOptionsReplaceForData = options.replace && !isString$1(options.replace);
|
|
874
878
|
let data = useOptionsReplaceForData ? options.replace : options;
|
|
875
879
|
if (useOptionsReplaceForData && typeof options.count !== 'undefined') {
|
|
876
|
-
data
|
|
880
|
+
data = {
|
|
881
|
+
...data,
|
|
882
|
+
count: options.count
|
|
883
|
+
};
|
|
877
884
|
}
|
|
878
885
|
if (this.options.interpolation.defaultVariables) {
|
|
879
886
|
data = {
|
|
@@ -1183,10 +1190,10 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
1183
1190
|
const skipOnVariables = options?.interpolation?.skipOnVariables !== undefined ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables;
|
|
1184
1191
|
const todos = [{
|
|
1185
1192
|
regex: this.regexpUnescape,
|
|
1186
|
-
safeValue: val =>
|
|
1193
|
+
safeValue: val => val
|
|
1187
1194
|
}, {
|
|
1188
1195
|
regex: this.regexp,
|
|
1189
|
-
safeValue: val => this.escapeValue ?
|
|
1196
|
+
safeValue: val => this.escapeValue ? this.escape(val) : val
|
|
1190
1197
|
}];
|
|
1191
1198
|
todos.forEach(todo => {
|
|
1192
1199
|
replaces = 0;
|
|
@@ -1210,9 +1217,9 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
1210
1217
|
value = makeString(value);
|
|
1211
1218
|
}
|
|
1212
1219
|
const safeValue = todo.safeValue(value);
|
|
1213
|
-
str = str.replace(match[0], safeValue);
|
|
1220
|
+
str = str.replace(match[0], regexSafe(safeValue));
|
|
1214
1221
|
if (skipOnVariables) {
|
|
1215
|
-
todo.regex.lastIndex +=
|
|
1222
|
+
todo.regex.lastIndex += safeValue.length;
|
|
1216
1223
|
todo.regex.lastIndex -= match[0].length;
|
|
1217
1224
|
} else {
|
|
1218
1225
|
todo.regex.lastIndex = 0;
|
|
@@ -1262,7 +1269,7 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
1262
1269
|
clonedOptions = clonedOptions.replace && !isString$1(clonedOptions.replace) ? clonedOptions.replace : clonedOptions;
|
|
1263
1270
|
clonedOptions.applyPostProcessor = false;
|
|
1264
1271
|
delete clonedOptions.defaultValue;
|
|
1265
|
-
const keyEndIndex = /{.*}
|
|
1272
|
+
const keyEndIndex = /{.*}/s.test(match[1]) ? match[1].lastIndexOf('}') + 1 : match[1].indexOf(this.formatSeparator);
|
|
1266
1273
|
if (keyEndIndex !== -1) {
|
|
1267
1274
|
formatters = match[1].slice(keyEndIndex).split(this.formatSeparator).map(elem => elem.trim()).filter(Boolean);
|
|
1268
1275
|
match[1] = match[1].slice(0, keyEndIndex);
|
|
@@ -1391,10 +1398,14 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
1391
1398
|
format(value, format, lng, options = {}) {
|
|
1392
1399
|
if (!format) return value;
|
|
1393
1400
|
if (value == null) return value;
|
|
1394
|
-
const
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1401
|
+
const rawFormats = format.split(this.formatSeparator);
|
|
1402
|
+
const formats = [];
|
|
1403
|
+
for (let i = 0; i < rawFormats.length; i++) {
|
|
1404
|
+
let f = rawFormats[i];
|
|
1405
|
+
while (f.indexOf('(') > -1 && !f.includes(')') && i + 1 < rawFormats.length) {
|
|
1406
|
+
f = `${f}${this.formatSeparator}${rawFormats[++i]}`;
|
|
1407
|
+
}
|
|
1408
|
+
formats.push(f);
|
|
1398
1409
|
}
|
|
1399
1410
|
const result = formats.reduce((mem, f) => {
|
|
1400
1411
|
const {
|
|
@@ -1653,6 +1664,7 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
1653
1664
|
nsSeparator: ':',
|
|
1654
1665
|
pluralSeparator: '_',
|
|
1655
1666
|
contextSeparator: '_',
|
|
1667
|
+
enableSelector: false,
|
|
1656
1668
|
partialBundledLanguages: false,
|
|
1657
1669
|
saveMissing: false,
|
|
1658
1670
|
updateMissing: false,
|
|
@@ -2229,127 +2241,318 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
2229
2241
|
instance.loadNamespaces;
|
|
2230
2242
|
instance.loadLanguages;
|
|
2231
2243
|
|
|
2232
|
-
|
|
2233
|
-
|
|
2244
|
+
const voidElements = {
|
|
2245
|
+
area: true,
|
|
2246
|
+
base: true,
|
|
2247
|
+
br: true,
|
|
2248
|
+
col: true,
|
|
2249
|
+
embed: true,
|
|
2250
|
+
hr: true,
|
|
2251
|
+
img: true,
|
|
2252
|
+
input: true,
|
|
2253
|
+
link: true,
|
|
2254
|
+
meta: true,
|
|
2255
|
+
param: true,
|
|
2256
|
+
source: true,
|
|
2257
|
+
track: true,
|
|
2258
|
+
wbr: true,
|
|
2259
|
+
'!doctype': true,
|
|
2260
|
+
'!DOCTYPE': true
|
|
2261
|
+
};
|
|
2262
|
+
const attrRE = /\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?("[^"]*"|'[^']*')/g;
|
|
2263
|
+
function parseTag(tag) {
|
|
2264
|
+
const res = {
|
|
2265
|
+
type: 'tag',
|
|
2266
|
+
name: '',
|
|
2267
|
+
voidElement: false,
|
|
2268
|
+
attrs: {},
|
|
2269
|
+
children: []
|
|
2270
|
+
};
|
|
2271
|
+
const tagMatch = tag.match(/<\/?([^\s]+?)[/\s>]/);
|
|
2272
|
+
if (tagMatch) {
|
|
2273
|
+
res.name = tagMatch[1];
|
|
2274
|
+
if (voidElements[tagMatch[1]] || tag.charAt(tag.length - 2) === '/') {
|
|
2275
|
+
res.voidElement = true;
|
|
2276
|
+
}
|
|
2277
|
+
if (res.name.startsWith('!--')) {
|
|
2278
|
+
const endIndex = tag.indexOf('-->');
|
|
2279
|
+
return {
|
|
2280
|
+
type: 'comment',
|
|
2281
|
+
comment: endIndex !== -1 ? tag.slice(4, endIndex) : ''
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
const reg = new RegExp(attrRE);
|
|
2286
|
+
let result = null;
|
|
2287
|
+
for (;;) {
|
|
2288
|
+
result = reg.exec(tag);
|
|
2289
|
+
if (result === null) {
|
|
2290
|
+
break;
|
|
2291
|
+
}
|
|
2292
|
+
if (!result[0].trim()) {
|
|
2293
|
+
continue;
|
|
2294
|
+
}
|
|
2295
|
+
if (result[1]) {
|
|
2296
|
+
const attr = result[1].trim();
|
|
2297
|
+
let arr = [attr, null];
|
|
2298
|
+
const eq = attr.indexOf('=');
|
|
2299
|
+
if (eq > -1) {
|
|
2300
|
+
arr = [attr.slice(0, eq), attr.slice(eq + 1)];
|
|
2301
|
+
}
|
|
2302
|
+
res.attrs[arr[0]] = arr[1];
|
|
2303
|
+
reg.lastIndex--;
|
|
2304
|
+
} else if (result[2]) {
|
|
2305
|
+
res.attrs[result[2]] = result[3].trim().substring(1, result[3].length - 1);
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
return res;
|
|
2234
2309
|
}
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2310
|
+
const tagRE = /<!--[\s\S]*?-->|<[a-zA-Z0-9\-!/](?:"[^"]*"|'[^']*'|[^'">])*>/g;
|
|
2311
|
+
const tagNameRE = /<\/?([^\s]+?)[/\s>]/;
|
|
2312
|
+
const whitespaceRE = /^\s*$/;
|
|
2313
|
+
const rawTextRE = /^(script|style)$/i;
|
|
2314
|
+
const sentinel = '\u0000';
|
|
2315
|
+
const empty = Object.create(null);
|
|
2316
|
+
function restoreSentinels(nodes) {
|
|
2317
|
+
nodes.forEach(function (node) {
|
|
2318
|
+
if (node.type === 'text') {
|
|
2319
|
+
node.content = node.content.split(sentinel).join('<');
|
|
2320
|
+
return;
|
|
2321
|
+
}
|
|
2322
|
+
if (node.type === 'comment') {
|
|
2323
|
+
node.comment = node.comment.split(sentinel).join('<');
|
|
2324
|
+
return;
|
|
2325
|
+
}
|
|
2326
|
+
for (const key in node.attrs) {
|
|
2327
|
+
const value = node.attrs[key];
|
|
2328
|
+
if (typeof value === 'string' && value.indexOf(sentinel) > -1) {
|
|
2329
|
+
node.attrs[key] = value.split(sentinel).join('<');
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
if (node.children.length) {
|
|
2333
|
+
restoreSentinels(node.children);
|
|
2334
|
+
}
|
|
2335
|
+
});
|
|
2259
2336
|
}
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
type: "tag",
|
|
2268
|
-
name: "",
|
|
2269
|
-
voidElement: false,
|
|
2270
|
-
attrs: {},
|
|
2271
|
-
children: []
|
|
2272
|
-
},
|
|
2273
|
-
i = n.match(/<\/?([^\s]+?)[/\s>]/);
|
|
2274
|
-
if (i && (r.name = i[1], (e[i[1]] || "/" === n.charAt(n.length - 2)) && (r.voidElement = true), r.name.startsWith("!--"))) {
|
|
2275
|
-
var s = n.indexOf("--\x3e");
|
|
2276
|
-
return {
|
|
2277
|
-
type: "comment",
|
|
2278
|
-
comment: -1 !== s ? n.slice(4, s) : ""
|
|
2337
|
+
function parse(html, options) {
|
|
2338
|
+
const components = options && options.components || empty;
|
|
2339
|
+
const allowedTags = options && options.allowedTags;
|
|
2340
|
+
let restoreNeeded = false;
|
|
2341
|
+
if (allowedTags) {
|
|
2342
|
+
const isAllowed = typeof allowedTags === 'function' ? allowedTags : function (name) {
|
|
2343
|
+
return allowedTags.indexOf(name) > -1;
|
|
2279
2344
|
};
|
|
2345
|
+
let out = '';
|
|
2346
|
+
let pos = 0;
|
|
2347
|
+
tagRE.lastIndex = 0;
|
|
2348
|
+
let am;
|
|
2349
|
+
while (am = tagRE.exec(html)) {
|
|
2350
|
+
const tag = am[0];
|
|
2351
|
+
out += html.slice(pos, am.index);
|
|
2352
|
+
const nameMatch = tag.match(tagNameRE);
|
|
2353
|
+
if (tag.startsWith('<!--') || nameMatch && isAllowed(nameMatch[1])) {
|
|
2354
|
+
out += tag;
|
|
2355
|
+
pos = am.index + tag.length;
|
|
2356
|
+
} else {
|
|
2357
|
+
restoreNeeded = true;
|
|
2358
|
+
out += sentinel;
|
|
2359
|
+
pos = am.index + 1;
|
|
2360
|
+
tagRE.lastIndex = pos;
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
html = out + html.slice(pos);
|
|
2280
2364
|
}
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
return e + t.content;
|
|
2295
|
-
case "tag":
|
|
2296
|
-
return e += "<" + t.name + (t.attrs ? function (e) {
|
|
2297
|
-
var t = [];
|
|
2298
|
-
for (var n in e) t.push(n + '="' + e[n] + '"');
|
|
2299
|
-
return t.length ? " " + t.join(" ") : "";
|
|
2300
|
-
}(t.attrs) : "") + (t.voidElement ? "/>" : ">"), t.voidElement ? e : e + t.children.reduce(a, "") + "</" + t.name + ">";
|
|
2301
|
-
case "comment":
|
|
2302
|
-
return e + "\x3c!--" + t.comment + "--\x3e";
|
|
2365
|
+
const result = [];
|
|
2366
|
+
const arr = [];
|
|
2367
|
+
let current;
|
|
2368
|
+
let level = -1;
|
|
2369
|
+
let inComponent = false;
|
|
2370
|
+
let rawUntil = 0;
|
|
2371
|
+
let htmlLower;
|
|
2372
|
+
if (html.indexOf('<') !== 0) {
|
|
2373
|
+
const end = html.indexOf('<');
|
|
2374
|
+
result.push({
|
|
2375
|
+
type: 'text',
|
|
2376
|
+
content: end === -1 ? html : html.substring(0, end)
|
|
2377
|
+
});
|
|
2303
2378
|
}
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2379
|
+
const matches = [];
|
|
2380
|
+
let m;
|
|
2381
|
+
while (m = tagRE.exec(html)) {
|
|
2382
|
+
matches.push(m);
|
|
2383
|
+
}
|
|
2384
|
+
matches.forEach(function (match, i) {
|
|
2385
|
+
const tag = match[0];
|
|
2386
|
+
if (!tag) return;
|
|
2387
|
+
if (tag.startsWith('<!--')) return;
|
|
2388
|
+
let lts = 0;
|
|
2389
|
+
let gts = 0;
|
|
2390
|
+
let secondLt = -1;
|
|
2391
|
+
let quote = null;
|
|
2392
|
+
for (let j = 0; j < tag.length; j++) {
|
|
2393
|
+
const c = tag.charAt(j);
|
|
2394
|
+
if (quote) {
|
|
2395
|
+
if (c === quote) quote = null;
|
|
2396
|
+
} else if (c === '"' || c === "'") {
|
|
2397
|
+
quote = c;
|
|
2398
|
+
} else if (c === '<') {
|
|
2399
|
+
lts++;
|
|
2400
|
+
if (lts === 2) secondLt = j;
|
|
2401
|
+
} else if (c === '>') {
|
|
2402
|
+
gts++;
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
const validSplit = secondLt > -1 && /[a-zA-Z0-9\-!/]/.test(tag.charAt(secondLt + 1));
|
|
2406
|
+
if (lts > gts && validSplit) {
|
|
2407
|
+
const firstPart = tag.substring(0, secondLt);
|
|
2408
|
+
const secondPart = tag.substring(firstPart.length);
|
|
2409
|
+
matches[i][0] = secondPart;
|
|
2410
|
+
matches[i].index += firstPart.length;
|
|
2319
2411
|
}
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2412
|
+
});
|
|
2413
|
+
matches.forEach(function (match, i) {
|
|
2414
|
+
const tag = match[0];
|
|
2415
|
+
if (!tag) return;
|
|
2416
|
+
const index = match.index;
|
|
2417
|
+
if (index < rawUntil) return;
|
|
2418
|
+
if (inComponent) {
|
|
2419
|
+
if (tag !== '</' + current.name + '>') {
|
|
2420
|
+
return;
|
|
2421
|
+
} else {
|
|
2422
|
+
inComponent = false;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
const isOpen = tag.charAt(1) !== '/';
|
|
2426
|
+
const isComment = tag.startsWith('<!--');
|
|
2427
|
+
const start = index + tag.length;
|
|
2428
|
+
const nextChar = html.charAt(start);
|
|
2429
|
+
const nextMatch = matches[i + 1];
|
|
2430
|
+
let isText;
|
|
2431
|
+
if (nextChar === '<' && nextMatch) {
|
|
2432
|
+
const nextTag = html.substring(start, nextMatch.index);
|
|
2433
|
+
isText = nextTag.split('<').length > nextTag.split('>').length;
|
|
2434
|
+
}
|
|
2435
|
+
let parent;
|
|
2436
|
+
if (isComment) {
|
|
2437
|
+
const comment = parseTag(tag);
|
|
2438
|
+
if (level < 0) {
|
|
2439
|
+
result.push(comment);
|
|
2440
|
+
return result;
|
|
2441
|
+
}
|
|
2442
|
+
parent = arr[level];
|
|
2443
|
+
parent.children.push(comment);
|
|
2444
|
+
const text = html.slice(start, nextMatch ? nextMatch.index : undefined);
|
|
2445
|
+
if (text.length > 0) {
|
|
2446
|
+
parent.children.push({
|
|
2447
|
+
type: 'text',
|
|
2448
|
+
content: text
|
|
2344
2449
|
});
|
|
2345
2450
|
}
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2451
|
+
return result;
|
|
2452
|
+
}
|
|
2453
|
+
if (isOpen) {
|
|
2454
|
+
level++;
|
|
2455
|
+
current = parseTag(tag);
|
|
2456
|
+
if (current.type === 'tag' && components[current.name]) {
|
|
2457
|
+
current.type = 'component';
|
|
2458
|
+
inComponent = true;
|
|
2459
|
+
}
|
|
2460
|
+
let isRawText = false;
|
|
2461
|
+
if (!inComponent && !current.voidElement && rawTextRE.test(current.name)) {
|
|
2462
|
+
isRawText = true;
|
|
2463
|
+
htmlLower || (htmlLower = html.toLowerCase());
|
|
2464
|
+
const closeIndex = htmlLower.indexOf('</' + current.name.toLowerCase() + '>', start);
|
|
2465
|
+
const contentEnd = closeIndex === -1 ? html.length : closeIndex;
|
|
2466
|
+
const content = html.slice(start, contentEnd);
|
|
2467
|
+
if (content) {
|
|
2468
|
+
current.children.push({
|
|
2469
|
+
type: 'text',
|
|
2470
|
+
content
|
|
2471
|
+
});
|
|
2472
|
+
}
|
|
2473
|
+
rawUntil = contentEnd;
|
|
2474
|
+
}
|
|
2475
|
+
if (!current.voidElement && !inComponent && !isRawText && nextChar && nextChar !== '<') {
|
|
2476
|
+
current.children.push({
|
|
2477
|
+
type: 'text',
|
|
2478
|
+
content: html.slice(start, nextMatch ? nextMatch.index : undefined)
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
if (level === 0) {
|
|
2482
|
+
result.push(current);
|
|
2483
|
+
}
|
|
2484
|
+
parent = arr[level - 1];
|
|
2485
|
+
if (parent) {
|
|
2486
|
+
parent.children.push(current);
|
|
2487
|
+
}
|
|
2488
|
+
arr[level] = current;
|
|
2489
|
+
}
|
|
2490
|
+
if (!isOpen || current.voidElement) {
|
|
2491
|
+
if (level > -1 && (current.voidElement || current.name === tag.slice(2, -1))) {
|
|
2492
|
+
level--;
|
|
2493
|
+
current = level === -1 ? result : arr[level];
|
|
2494
|
+
}
|
|
2495
|
+
if (!inComponent && (nextChar !== '<' || isText) && nextChar) {
|
|
2496
|
+
parent = level === -1 ? result : arr[level].children;
|
|
2497
|
+
const end = nextMatch ? nextMatch.index : -1;
|
|
2498
|
+
let content = html.slice(start, end === -1 ? undefined : end);
|
|
2499
|
+
if (whitespaceRE.test(content)) {
|
|
2500
|
+
content = ' ';
|
|
2501
|
+
}
|
|
2502
|
+
if (end > -1 && level + parent.length >= 0 || content !== ' ') {
|
|
2503
|
+
parent.push({
|
|
2504
|
+
type: 'text',
|
|
2505
|
+
content
|
|
2506
|
+
});
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
});
|
|
2511
|
+
if (restoreNeeded) {
|
|
2512
|
+
restoreSentinels(result);
|
|
2513
|
+
}
|
|
2514
|
+
return result;
|
|
2515
|
+
}
|
|
2516
|
+
function attrString(attrs) {
|
|
2517
|
+
const buff = [];
|
|
2518
|
+
for (const key in attrs) {
|
|
2519
|
+
if (attrs[key] === null) {
|
|
2520
|
+
buff.push(key);
|
|
2521
|
+
} else {
|
|
2522
|
+
buff.push(key + '="' + String(attrs[key]).replace(/"/g, '"') + '"');
|
|
2523
|
+
}
|
|
2352
2524
|
}
|
|
2525
|
+
if (!buff.length) {
|
|
2526
|
+
return '';
|
|
2527
|
+
}
|
|
2528
|
+
return ' ' + buff.join(' ');
|
|
2529
|
+
}
|
|
2530
|
+
function stringifyNode(buff, doc) {
|
|
2531
|
+
switch (doc.type) {
|
|
2532
|
+
case 'text':
|
|
2533
|
+
return buff + doc.content;
|
|
2534
|
+
case 'tag':
|
|
2535
|
+
{
|
|
2536
|
+
const tagEnd = doc.voidElement && doc.name.toLowerCase() !== '!doctype' ? '/>' : '>';
|
|
2537
|
+
buff += '<' + doc.name + (doc.attrs ? attrString(doc.attrs) : '') + tagEnd;
|
|
2538
|
+
if (doc.voidElement) {
|
|
2539
|
+
return buff;
|
|
2540
|
+
}
|
|
2541
|
+
return buff + doc.children.reduce(stringifyNode, '') + '</' + doc.name + '>';
|
|
2542
|
+
}
|
|
2543
|
+
case 'comment':
|
|
2544
|
+
buff += '<!--' + doc.comment + '-->';
|
|
2545
|
+
return buff;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
function stringify(doc) {
|
|
2549
|
+
return doc.reduce(function (token, rootEl) {
|
|
2550
|
+
return token + stringifyNode('', rootEl);
|
|
2551
|
+
}, '');
|
|
2552
|
+
}
|
|
2553
|
+
var index = {
|
|
2554
|
+
parse,
|
|
2555
|
+
stringify
|
|
2353
2556
|
};
|
|
2354
2557
|
|
|
2355
2558
|
const warn = (i18n, code, msg, rest) => {
|
|
@@ -2567,46 +2770,6 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
2567
2770
|
});
|
|
2568
2771
|
return stringNode;
|
|
2569
2772
|
};
|
|
2570
|
-
const escapeLiteralLessThan = (str, keepArray = [], knownComponentsMap = {}) => {
|
|
2571
|
-
if (!str) return str;
|
|
2572
|
-
const knownNames = Object.keys(knownComponentsMap);
|
|
2573
|
-
const allValidNames = [...keepArray, ...knownNames];
|
|
2574
|
-
let result = '';
|
|
2575
|
-
let i = 0;
|
|
2576
|
-
while (i < str.length) {
|
|
2577
|
-
if (str[i] === '<') {
|
|
2578
|
-
let isValidTag = false;
|
|
2579
|
-
const closingMatch = str.slice(i).match(/^<\/(\d+|[a-zA-Z][a-zA-Z0-9_-]*)>/);
|
|
2580
|
-
if (closingMatch) {
|
|
2581
|
-
const tagName = closingMatch[1];
|
|
2582
|
-
if (/^\d+$/.test(tagName) || allValidNames.includes(tagName)) {
|
|
2583
|
-
isValidTag = true;
|
|
2584
|
-
result += closingMatch[0];
|
|
2585
|
-
i += closingMatch[0].length;
|
|
2586
|
-
}
|
|
2587
|
-
}
|
|
2588
|
-
if (!isValidTag) {
|
|
2589
|
-
const openingMatch = str.slice(i).match(/^<(\d+|[a-zA-Z][a-zA-Z0-9_-]*)(\s+[\w-]+(?:=(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s*(\/)?>/);
|
|
2590
|
-
if (openingMatch) {
|
|
2591
|
-
const tagName = openingMatch[1];
|
|
2592
|
-
if (/^\d+$/.test(tagName) || allValidNames.includes(tagName)) {
|
|
2593
|
-
isValidTag = true;
|
|
2594
|
-
result += openingMatch[0];
|
|
2595
|
-
i += openingMatch[0].length;
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
if (!isValidTag) {
|
|
2600
|
-
result += '<';
|
|
2601
|
-
i += 1;
|
|
2602
|
-
}
|
|
2603
|
-
} else {
|
|
2604
|
-
result += str[i];
|
|
2605
|
-
i += 1;
|
|
2606
|
-
}
|
|
2607
|
-
}
|
|
2608
|
-
return result;
|
|
2609
|
-
};
|
|
2610
2773
|
const renderNodes = (children, knownComponentsMap, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
|
2611
2774
|
if (targetString === '') return [];
|
|
2612
2775
|
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
|
@@ -2621,8 +2784,11 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
2621
2784
|
});
|
|
2622
2785
|
};
|
|
2623
2786
|
getData(children);
|
|
2624
|
-
const
|
|
2625
|
-
const
|
|
2787
|
+
const knownNames = Object.keys(data);
|
|
2788
|
+
const allowedTags = name => /^\d+$/.test(name) || keepArray.indexOf(name) > -1 || knownNames.indexOf(name) > -1;
|
|
2789
|
+
const ast = index.parse(`<0>${targetString}</0>`, {
|
|
2790
|
+
allowedTags
|
|
2791
|
+
});
|
|
2626
2792
|
const opts = {
|
|
2627
2793
|
...data,
|
|
2628
2794
|
...combinedTOpts
|
|
@@ -2827,7 +2993,7 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
2827
2993
|
}) {
|
|
2828
2994
|
const i18n = i18nFromProps || getI18n();
|
|
2829
2995
|
if (!i18n) {
|
|
2830
|
-
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', `Trans: You need to pass in an i18next instance using
|
|
2996
|
+
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', `Trans: You need to pass in an i18next instance using initReactI18next or by passing it via props or context. In monorepo setups, make sure there is only one instance of react-i18next.`, {
|
|
2831
2997
|
i18nKey
|
|
2832
2998
|
});
|
|
2833
2999
|
return children;
|
|
@@ -3575,7 +3741,7 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
3575
3741
|
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
|
3576
3742
|
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
|
3577
3743
|
if (!i18n) {
|
|
3578
|
-
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: You will need to pass in an i18next instance by using initReactI18next');
|
|
3744
|
+
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: You will need to pass in an i18next instance by using initReactI18next or by passing it via props or context. In monorepo setups, make sure there is only one instance of react-i18next.');
|
|
3579
3745
|
}
|
|
3580
3746
|
const i18nOptions = React.useMemo(() => ({
|
|
3581
3747
|
...getDefaults(),
|
|
@@ -3697,6 +3863,13 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
3697
3863
|
return arr;
|
|
3698
3864
|
}, [t, finalI18n, ready, finalI18n.resolvedLanguage, finalI18n.language, finalI18n.languages]);
|
|
3699
3865
|
if (i18n && useSuspense && !ready) {
|
|
3866
|
+
let inDevelopment = false;
|
|
3867
|
+
try {
|
|
3868
|
+
inDevelopment = "development" !== 'production';
|
|
3869
|
+
} catch (e) {}
|
|
3870
|
+
if (inDevelopment) {
|
|
3871
|
+
warnOnce(i18n, 'SUSPENDED_WHILE_LOADING', 'useTranslation: suspended while translations are loading (useSuspense is true by default). Add a <Suspense> boundary above this component, or set react.useSuspense: false in the i18next init options. https://react.i18next.com/latest/usetranslation-hook');
|
|
3872
|
+
}
|
|
3700
3873
|
throw new Promise(resolve => {
|
|
3701
3874
|
const onLoaded = () => resolve();
|
|
3702
3875
|
if (props.lng) {
|