react-i18next 17.0.10 → 17.0.12
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 -1
- package/CHANGELOG.md +9 -0
- package/README.md +1 -1
- package/TransWithoutContext.d.ts +1 -2
- package/dist/amd/react-i18next.js +336 -155
- package/dist/amd/react-i18next.min.js +1 -1
- package/dist/commonjs/IcuTransWithoutContext.js +1 -1
- package/dist/commonjs/TransWithoutContext.js +5 -42
- package/dist/es/IcuTransWithoutContext.js +1 -1
- package/dist/es/TransWithoutContext.js +5 -42
- package/dist/es/package.json +1 -1
- package/dist/umd/react-i18next.js +336 -155
- package/dist/umd/react-i18next.min.js +1 -1
- package/package.json +31 -34
- package/react-i18next.js +336 -155
- package/react-i18next.min.js +1 -1
- package/src/IcuTransWithoutContext.js +4 -2
- package/src/TransWithoutContext.js +7 -79
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 17.0.12
|
|
2
|
+
|
|
3
|
+
- fix(IcuTrans): key-less `icu.macro` nodes (`<Trans>Welcome, {name}!</Trans>`, `<Select>`, `<Plural>` without `i18nKey`) rendered an empty string since 17.0.0. The macro now emits `<IcuTrans defaultTranslation="…">` without a key and `IcuTrans` passed `undefined` to `t()`, which returns `''`. Like `Trans`, `IcuTrans` now uses `defaultTranslation` as the key when `i18nKey` is not provided.
|
|
4
|
+
|
|
5
|
+
## 17.0.11
|
|
6
|
+
|
|
7
|
+
- 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).
|
|
8
|
+
- 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).
|
|
9
|
+
|
|
1
10
|
## 17.0.10
|
|
2
11
|
|
|
3
12
|
- 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.
|
package/README.md
CHANGED
|
@@ -137,7 +137,7 @@ Some basics of i18next and some cool possibilities on how to optimize your local
|
|
|
137
137
|
|
|
138
138
|
#### v9
|
|
139
139
|
|
|
140
|
-
- react >= **0.14.0** (in case of < v16 or preact you will need to define parent in [Trans component](https://react.i18next.com/
|
|
140
|
+
- react >= **0.14.0** (in case of < v16 or preact you will need to define parent in [Trans component](https://react.i18next.com/latest/trans-component#trans-props) or globally in [i18next.react options](https://react.i18next.com/latest/trans-component#i18next-options))
|
|
141
141
|
- i18next >= **2.0.0**
|
|
142
142
|
|
|
143
143
|
## Core Contributors
|
package/TransWithoutContext.d.ts
CHANGED
|
@@ -97,8 +97,7 @@ export interface TransSelector {
|
|
|
97
97
|
<
|
|
98
98
|
Target extends ConstrainTarget<TOpt>,
|
|
99
99
|
Key extends
|
|
100
|
-
|
|
101
|
-
| SelectorKey,
|
|
100
|
+
SelectorFn<GetSource<$NoInfer<Ns>, KPrefix>, ApplyTarget<Target, TOpt>, TOpt> | SelectorKey,
|
|
102
101
|
const Ns extends Namespace = _DefaultNamespace,
|
|
103
102
|
KPrefix = undefined,
|
|
104
103
|
TContext extends string | undefined = undefined,
|
|
@@ -913,6 +913,10 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
913
913
|
this.options = options;
|
|
914
914
|
this.supportedLngs = this.options.supportedLngs || false;
|
|
915
915
|
this.logger = baseLogger.create('languageUtils');
|
|
916
|
+
this.resolveHierarchyCache = {};
|
|
917
|
+
}
|
|
918
|
+
clearCache() {
|
|
919
|
+
this.resolveHierarchyCache = {};
|
|
916
920
|
}
|
|
917
921
|
getScriptPartFromCode(code) {
|
|
918
922
|
code = getCleanedCode(code);
|
|
@@ -993,6 +997,25 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
993
997
|
return found || [];
|
|
994
998
|
}
|
|
995
999
|
toResolveHierarchy(code, fallbackCode) {
|
|
1000
|
+
const fallbackLng = this.options.fallbackLng;
|
|
1001
|
+
const fallbackLngKey = Array.isArray(fallbackLng) ? fallbackLng.join('|') : fallbackLng;
|
|
1002
|
+
if (fallbackLngKey !== this._cachedFallbackLng) {
|
|
1003
|
+
this.resolveHierarchyCache = {};
|
|
1004
|
+
this._cachedFallbackLng = fallbackLngKey;
|
|
1005
|
+
}
|
|
1006
|
+
const hasCacheableFallback = fallbackCode === undefined || fallbackCode === false || isString$1(fallbackCode);
|
|
1007
|
+
const usesUncacheableOptionsFallback = fallbackCode === undefined && typeof this.options.fallbackLng === 'function';
|
|
1008
|
+
const cacheable = isString$1(code) && hasCacheableFallback && !usesUncacheableOptionsFallback;
|
|
1009
|
+
let cacheKey = null;
|
|
1010
|
+
if (cacheable) {
|
|
1011
|
+
let fallbackCacheKey;
|
|
1012
|
+
if (fallbackCode === undefined) fallbackCacheKey = 'undefined';else if (fallbackCode === false) fallbackCacheKey = 'boolean:false';else fallbackCacheKey = `string:${fallbackCode}`;
|
|
1013
|
+
cacheKey = `${code.length}:${code}|${fallbackCacheKey}`;
|
|
1014
|
+
}
|
|
1015
|
+
if (cacheKey !== null) {
|
|
1016
|
+
const cached = this.resolveHierarchyCache[cacheKey];
|
|
1017
|
+
if (cached !== undefined) return cached.slice();
|
|
1018
|
+
}
|
|
996
1019
|
const fallbackCodes = this.getFallbackCodes((fallbackCode === false ? [] : fallbackCode) || this.options.fallbackLng || [], code);
|
|
997
1020
|
const codes = [];
|
|
998
1021
|
const addCode = c => {
|
|
@@ -1013,6 +1036,10 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
1013
1036
|
fallbackCodes.forEach(fc => {
|
|
1014
1037
|
if (!codes.includes(fc)) addCode(this.formatLanguageCode(fc));
|
|
1015
1038
|
});
|
|
1039
|
+
if (cacheKey !== null) {
|
|
1040
|
+
this.resolveHierarchyCache[cacheKey] = codes;
|
|
1041
|
+
return codes.slice();
|
|
1042
|
+
}
|
|
1016
1043
|
return codes;
|
|
1017
1044
|
}
|
|
1018
1045
|
}
|
|
@@ -2241,127 +2268,318 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
2241
2268
|
instance.loadNamespaces;
|
|
2242
2269
|
instance.loadLanguages;
|
|
2243
2270
|
|
|
2244
|
-
|
|
2245
|
-
|
|
2271
|
+
const voidElements = {
|
|
2272
|
+
area: true,
|
|
2273
|
+
base: true,
|
|
2274
|
+
br: true,
|
|
2275
|
+
col: true,
|
|
2276
|
+
embed: true,
|
|
2277
|
+
hr: true,
|
|
2278
|
+
img: true,
|
|
2279
|
+
input: true,
|
|
2280
|
+
link: true,
|
|
2281
|
+
meta: true,
|
|
2282
|
+
param: true,
|
|
2283
|
+
source: true,
|
|
2284
|
+
track: true,
|
|
2285
|
+
wbr: true,
|
|
2286
|
+
'!doctype': true,
|
|
2287
|
+
'!DOCTYPE': true
|
|
2288
|
+
};
|
|
2289
|
+
const attrRE = /\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?("[^"]*"|'[^']*')/g;
|
|
2290
|
+
function parseTag(tag) {
|
|
2291
|
+
const res = {
|
|
2292
|
+
type: 'tag',
|
|
2293
|
+
name: '',
|
|
2294
|
+
voidElement: false,
|
|
2295
|
+
attrs: {},
|
|
2296
|
+
children: []
|
|
2297
|
+
};
|
|
2298
|
+
const tagMatch = tag.match(/<\/?([^\s]+?)[/\s>]/);
|
|
2299
|
+
if (tagMatch) {
|
|
2300
|
+
res.name = tagMatch[1];
|
|
2301
|
+
if (voidElements[tagMatch[1]] || tag.charAt(tag.length - 2) === '/') {
|
|
2302
|
+
res.voidElement = true;
|
|
2303
|
+
}
|
|
2304
|
+
if (res.name.startsWith('!--')) {
|
|
2305
|
+
const endIndex = tag.indexOf('-->');
|
|
2306
|
+
return {
|
|
2307
|
+
type: 'comment',
|
|
2308
|
+
comment: endIndex !== -1 ? tag.slice(4, endIndex) : ''
|
|
2309
|
+
};
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
const reg = new RegExp(attrRE);
|
|
2313
|
+
let result = null;
|
|
2314
|
+
for (;;) {
|
|
2315
|
+
result = reg.exec(tag);
|
|
2316
|
+
if (result === null) {
|
|
2317
|
+
break;
|
|
2318
|
+
}
|
|
2319
|
+
if (!result[0].trim()) {
|
|
2320
|
+
continue;
|
|
2321
|
+
}
|
|
2322
|
+
if (result[1]) {
|
|
2323
|
+
const attr = result[1].trim();
|
|
2324
|
+
let arr = [attr, null];
|
|
2325
|
+
const eq = attr.indexOf('=');
|
|
2326
|
+
if (eq > -1) {
|
|
2327
|
+
arr = [attr.slice(0, eq), attr.slice(eq + 1)];
|
|
2328
|
+
}
|
|
2329
|
+
res.attrs[arr[0]] = arr[1];
|
|
2330
|
+
reg.lastIndex--;
|
|
2331
|
+
} else if (result[2]) {
|
|
2332
|
+
res.attrs[result[2]] = result[3].trim().substring(1, result[3].length - 1);
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
return res;
|
|
2246
2336
|
}
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2337
|
+
const tagRE = /<!--[\s\S]*?-->|<[a-zA-Z0-9\-!/](?:"[^"]*"|'[^']*'|[^'">])*>/g;
|
|
2338
|
+
const tagNameRE = /<\/?([^\s]+?)[/\s>]/;
|
|
2339
|
+
const whitespaceRE = /^\s*$/;
|
|
2340
|
+
const rawTextRE = /^(script|style)$/i;
|
|
2341
|
+
const sentinel = '\u0000';
|
|
2342
|
+
const empty = Object.create(null);
|
|
2343
|
+
function restoreSentinels(nodes) {
|
|
2344
|
+
nodes.forEach(function (node) {
|
|
2345
|
+
if (node.type === 'text') {
|
|
2346
|
+
node.content = node.content.split(sentinel).join('<');
|
|
2347
|
+
return;
|
|
2348
|
+
}
|
|
2349
|
+
if (node.type === 'comment') {
|
|
2350
|
+
node.comment = node.comment.split(sentinel).join('<');
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
for (const key in node.attrs) {
|
|
2354
|
+
const value = node.attrs[key];
|
|
2355
|
+
if (typeof value === 'string' && value.indexOf(sentinel) > -1) {
|
|
2356
|
+
node.attrs[key] = value.split(sentinel).join('<');
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
if (node.children.length) {
|
|
2360
|
+
restoreSentinels(node.children);
|
|
2361
|
+
}
|
|
2362
|
+
});
|
|
2271
2363
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
type: "tag",
|
|
2280
|
-
name: "",
|
|
2281
|
-
voidElement: false,
|
|
2282
|
-
attrs: {},
|
|
2283
|
-
children: []
|
|
2284
|
-
},
|
|
2285
|
-
i = n.match(/<\/?([^\s]+?)[/\s>]/);
|
|
2286
|
-
if (i && (r.name = i[1], (e[i[1]] || "/" === n.charAt(n.length - 2)) && (r.voidElement = true), r.name.startsWith("!--"))) {
|
|
2287
|
-
var s = n.indexOf("--\x3e");
|
|
2288
|
-
return {
|
|
2289
|
-
type: "comment",
|
|
2290
|
-
comment: -1 !== s ? n.slice(4, s) : ""
|
|
2364
|
+
function parse(html, options) {
|
|
2365
|
+
const components = options && options.components || empty;
|
|
2366
|
+
const allowedTags = options && options.allowedTags;
|
|
2367
|
+
let restoreNeeded = false;
|
|
2368
|
+
if (allowedTags) {
|
|
2369
|
+
const isAllowed = typeof allowedTags === 'function' ? allowedTags : function (name) {
|
|
2370
|
+
return allowedTags.indexOf(name) > -1;
|
|
2291
2371
|
};
|
|
2372
|
+
let out = '';
|
|
2373
|
+
let pos = 0;
|
|
2374
|
+
tagRE.lastIndex = 0;
|
|
2375
|
+
let am;
|
|
2376
|
+
while (am = tagRE.exec(html)) {
|
|
2377
|
+
const tag = am[0];
|
|
2378
|
+
out += html.slice(pos, am.index);
|
|
2379
|
+
const nameMatch = tag.match(tagNameRE);
|
|
2380
|
+
if (tag.startsWith('<!--') || nameMatch && isAllowed(nameMatch[1])) {
|
|
2381
|
+
out += tag;
|
|
2382
|
+
pos = am.index + tag.length;
|
|
2383
|
+
} else {
|
|
2384
|
+
restoreNeeded = true;
|
|
2385
|
+
out += sentinel;
|
|
2386
|
+
pos = am.index + 1;
|
|
2387
|
+
tagRE.lastIndex = pos;
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
html = out + html.slice(pos);
|
|
2292
2391
|
}
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
return e + t.content;
|
|
2307
|
-
case "tag":
|
|
2308
|
-
return e += "<" + t.name + (t.attrs ? function (e) {
|
|
2309
|
-
var t = [];
|
|
2310
|
-
for (var n in e) t.push(n + '="' + e[n] + '"');
|
|
2311
|
-
return t.length ? " " + t.join(" ") : "";
|
|
2312
|
-
}(t.attrs) : "") + (t.voidElement ? "/>" : ">"), t.voidElement ? e : e + t.children.reduce(a, "") + "</" + t.name + ">";
|
|
2313
|
-
case "comment":
|
|
2314
|
-
return e + "\x3c!--" + t.comment + "--\x3e";
|
|
2392
|
+
const result = [];
|
|
2393
|
+
const arr = [];
|
|
2394
|
+
let current;
|
|
2395
|
+
let level = -1;
|
|
2396
|
+
let inComponent = false;
|
|
2397
|
+
let rawUntil = 0;
|
|
2398
|
+
let htmlLower;
|
|
2399
|
+
if (html.indexOf('<') !== 0) {
|
|
2400
|
+
const end = html.indexOf('<');
|
|
2401
|
+
result.push({
|
|
2402
|
+
type: 'text',
|
|
2403
|
+
content: end === -1 ? html : html.substring(0, end)
|
|
2404
|
+
});
|
|
2315
2405
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2406
|
+
const matches = [];
|
|
2407
|
+
let m;
|
|
2408
|
+
while (m = tagRE.exec(html)) {
|
|
2409
|
+
matches.push(m);
|
|
2410
|
+
}
|
|
2411
|
+
matches.forEach(function (match, i) {
|
|
2412
|
+
const tag = match[0];
|
|
2413
|
+
if (!tag) return;
|
|
2414
|
+
if (tag.startsWith('<!--')) return;
|
|
2415
|
+
let lts = 0;
|
|
2416
|
+
let gts = 0;
|
|
2417
|
+
let secondLt = -1;
|
|
2418
|
+
let quote = null;
|
|
2419
|
+
for (let j = 0; j < tag.length; j++) {
|
|
2420
|
+
const c = tag.charAt(j);
|
|
2421
|
+
if (quote) {
|
|
2422
|
+
if (c === quote) quote = null;
|
|
2423
|
+
} else if (c === '"' || c === "'") {
|
|
2424
|
+
quote = c;
|
|
2425
|
+
} else if (c === '<') {
|
|
2426
|
+
lts++;
|
|
2427
|
+
if (lts === 2) secondLt = j;
|
|
2428
|
+
} else if (c === '>') {
|
|
2429
|
+
gts++;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
const validSplit = secondLt > -1 && /[a-zA-Z0-9\-!/]/.test(tag.charAt(secondLt + 1));
|
|
2433
|
+
if (lts > gts && validSplit) {
|
|
2434
|
+
const firstPart = tag.substring(0, secondLt);
|
|
2435
|
+
const secondPart = tag.substring(firstPart.length);
|
|
2436
|
+
matches[i][0] = secondPart;
|
|
2437
|
+
matches[i].index += firstPart.length;
|
|
2331
2438
|
}
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2439
|
+
});
|
|
2440
|
+
matches.forEach(function (match, i) {
|
|
2441
|
+
const tag = match[0];
|
|
2442
|
+
if (!tag) return;
|
|
2443
|
+
const index = match.index;
|
|
2444
|
+
if (index < rawUntil) return;
|
|
2445
|
+
if (inComponent) {
|
|
2446
|
+
if (tag !== '</' + current.name + '>') {
|
|
2447
|
+
return;
|
|
2448
|
+
} else {
|
|
2449
|
+
inComponent = false;
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
const isOpen = tag.charAt(1) !== '/';
|
|
2453
|
+
const isComment = tag.startsWith('<!--');
|
|
2454
|
+
const start = index + tag.length;
|
|
2455
|
+
const nextChar = html.charAt(start);
|
|
2456
|
+
const nextMatch = matches[i + 1];
|
|
2457
|
+
let isText;
|
|
2458
|
+
if (nextChar === '<' && nextMatch) {
|
|
2459
|
+
const nextTag = html.substring(start, nextMatch.index);
|
|
2460
|
+
isText = nextTag.split('<').length > nextTag.split('>').length;
|
|
2461
|
+
}
|
|
2462
|
+
let parent;
|
|
2463
|
+
if (isComment) {
|
|
2464
|
+
const comment = parseTag(tag);
|
|
2465
|
+
if (level < 0) {
|
|
2466
|
+
result.push(comment);
|
|
2467
|
+
return result;
|
|
2468
|
+
}
|
|
2469
|
+
parent = arr[level];
|
|
2470
|
+
parent.children.push(comment);
|
|
2471
|
+
const text = html.slice(start, nextMatch ? nextMatch.index : undefined);
|
|
2472
|
+
if (text.length > 0) {
|
|
2473
|
+
parent.children.push({
|
|
2474
|
+
type: 'text',
|
|
2475
|
+
content: text
|
|
2356
2476
|
});
|
|
2357
2477
|
}
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2478
|
+
return result;
|
|
2479
|
+
}
|
|
2480
|
+
if (isOpen) {
|
|
2481
|
+
level++;
|
|
2482
|
+
current = parseTag(tag);
|
|
2483
|
+
if (current.type === 'tag' && components[current.name]) {
|
|
2484
|
+
current.type = 'component';
|
|
2485
|
+
inComponent = true;
|
|
2486
|
+
}
|
|
2487
|
+
let isRawText = false;
|
|
2488
|
+
if (!inComponent && !current.voidElement && rawTextRE.test(current.name)) {
|
|
2489
|
+
isRawText = true;
|
|
2490
|
+
htmlLower || (htmlLower = html.toLowerCase());
|
|
2491
|
+
const closeIndex = htmlLower.indexOf('</' + current.name.toLowerCase() + '>', start);
|
|
2492
|
+
const contentEnd = closeIndex === -1 ? html.length : closeIndex;
|
|
2493
|
+
const content = html.slice(start, contentEnd);
|
|
2494
|
+
if (content) {
|
|
2495
|
+
current.children.push({
|
|
2496
|
+
type: 'text',
|
|
2497
|
+
content
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
rawUntil = contentEnd;
|
|
2501
|
+
}
|
|
2502
|
+
if (!current.voidElement && !inComponent && !isRawText && nextChar && nextChar !== '<') {
|
|
2503
|
+
current.children.push({
|
|
2504
|
+
type: 'text',
|
|
2505
|
+
content: html.slice(start, nextMatch ? nextMatch.index : undefined)
|
|
2506
|
+
});
|
|
2507
|
+
}
|
|
2508
|
+
if (level === 0) {
|
|
2509
|
+
result.push(current);
|
|
2510
|
+
}
|
|
2511
|
+
parent = arr[level - 1];
|
|
2512
|
+
if (parent) {
|
|
2513
|
+
parent.children.push(current);
|
|
2514
|
+
}
|
|
2515
|
+
arr[level] = current;
|
|
2516
|
+
}
|
|
2517
|
+
if (!isOpen || current.voidElement) {
|
|
2518
|
+
if (level > -1 && (current.voidElement || current.name === tag.slice(2, -1))) {
|
|
2519
|
+
level--;
|
|
2520
|
+
current = level === -1 ? result : arr[level];
|
|
2521
|
+
}
|
|
2522
|
+
if (!inComponent && (nextChar !== '<' || isText) && nextChar) {
|
|
2523
|
+
parent = level === -1 ? result : arr[level].children;
|
|
2524
|
+
const end = nextMatch ? nextMatch.index : -1;
|
|
2525
|
+
let content = html.slice(start, end === -1 ? undefined : end);
|
|
2526
|
+
if (whitespaceRE.test(content)) {
|
|
2527
|
+
content = ' ';
|
|
2528
|
+
}
|
|
2529
|
+
if (end > -1 && level + parent.length >= 0 || content !== ' ') {
|
|
2530
|
+
parent.push({
|
|
2531
|
+
type: 'text',
|
|
2532
|
+
content
|
|
2533
|
+
});
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
});
|
|
2538
|
+
if (restoreNeeded) {
|
|
2539
|
+
restoreSentinels(result);
|
|
2540
|
+
}
|
|
2541
|
+
return result;
|
|
2542
|
+
}
|
|
2543
|
+
function attrString(attrs) {
|
|
2544
|
+
const buff = [];
|
|
2545
|
+
for (const key in attrs) {
|
|
2546
|
+
if (attrs[key] === null) {
|
|
2547
|
+
buff.push(key);
|
|
2548
|
+
} else {
|
|
2549
|
+
buff.push(key + '="' + String(attrs[key]).replace(/"/g, '"') + '"');
|
|
2550
|
+
}
|
|
2364
2551
|
}
|
|
2552
|
+
if (!buff.length) {
|
|
2553
|
+
return '';
|
|
2554
|
+
}
|
|
2555
|
+
return ' ' + buff.join(' ');
|
|
2556
|
+
}
|
|
2557
|
+
function stringifyNode(buff, doc) {
|
|
2558
|
+
switch (doc.type) {
|
|
2559
|
+
case 'text':
|
|
2560
|
+
return buff + doc.content;
|
|
2561
|
+
case 'tag':
|
|
2562
|
+
{
|
|
2563
|
+
const tagEnd = doc.voidElement && doc.name.toLowerCase() !== '!doctype' ? '/>' : '>';
|
|
2564
|
+
buff += '<' + doc.name + (doc.attrs ? attrString(doc.attrs) : '') + tagEnd;
|
|
2565
|
+
if (doc.voidElement) {
|
|
2566
|
+
return buff;
|
|
2567
|
+
}
|
|
2568
|
+
return buff + doc.children.reduce(stringifyNode, '') + '</' + doc.name + '>';
|
|
2569
|
+
}
|
|
2570
|
+
case 'comment':
|
|
2571
|
+
buff += '<!--' + doc.comment + '-->';
|
|
2572
|
+
return buff;
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
function stringify(doc) {
|
|
2576
|
+
return doc.reduce(function (token, rootEl) {
|
|
2577
|
+
return token + stringifyNode('', rootEl);
|
|
2578
|
+
}, '');
|
|
2579
|
+
}
|
|
2580
|
+
var index = {
|
|
2581
|
+
parse,
|
|
2582
|
+
stringify
|
|
2365
2583
|
};
|
|
2366
2584
|
|
|
2367
2585
|
const warn = (i18n, code, msg, rest) => {
|
|
@@ -2579,46 +2797,6 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
2579
2797
|
});
|
|
2580
2798
|
return stringNode;
|
|
2581
2799
|
};
|
|
2582
|
-
const escapeLiteralLessThan = (str, keepArray = [], knownComponentsMap = {}) => {
|
|
2583
|
-
if (!str) return str;
|
|
2584
|
-
const knownNames = Object.keys(knownComponentsMap);
|
|
2585
|
-
const allValidNames = [...keepArray, ...knownNames];
|
|
2586
|
-
let result = '';
|
|
2587
|
-
let i = 0;
|
|
2588
|
-
while (i < str.length) {
|
|
2589
|
-
if (str[i] === '<') {
|
|
2590
|
-
let isValidTag = false;
|
|
2591
|
-
const closingMatch = str.slice(i).match(/^<\/(\d+|[a-zA-Z][a-zA-Z0-9_-]*)>/);
|
|
2592
|
-
if (closingMatch) {
|
|
2593
|
-
const tagName = closingMatch[1];
|
|
2594
|
-
if (/^\d+$/.test(tagName) || allValidNames.includes(tagName)) {
|
|
2595
|
-
isValidTag = true;
|
|
2596
|
-
result += closingMatch[0];
|
|
2597
|
-
i += closingMatch[0].length;
|
|
2598
|
-
}
|
|
2599
|
-
}
|
|
2600
|
-
if (!isValidTag) {
|
|
2601
|
-
const openingMatch = str.slice(i).match(/^<(\d+|[a-zA-Z][a-zA-Z0-9_-]*)(\s+[\w-]+(?:=(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s*(\/)?>/);
|
|
2602
|
-
if (openingMatch) {
|
|
2603
|
-
const tagName = openingMatch[1];
|
|
2604
|
-
if (/^\d+$/.test(tagName) || allValidNames.includes(tagName)) {
|
|
2605
|
-
isValidTag = true;
|
|
2606
|
-
result += openingMatch[0];
|
|
2607
|
-
i += openingMatch[0].length;
|
|
2608
|
-
}
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
if (!isValidTag) {
|
|
2612
|
-
result += '<';
|
|
2613
|
-
i += 1;
|
|
2614
|
-
}
|
|
2615
|
-
} else {
|
|
2616
|
-
result += str[i];
|
|
2617
|
-
i += 1;
|
|
2618
|
-
}
|
|
2619
|
-
}
|
|
2620
|
-
return result;
|
|
2621
|
-
};
|
|
2622
2800
|
const renderNodes = (children, knownComponentsMap, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) => {
|
|
2623
2801
|
if (targetString === '') return [];
|
|
2624
2802
|
const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || [];
|
|
@@ -2633,8 +2811,11 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
2633
2811
|
});
|
|
2634
2812
|
};
|
|
2635
2813
|
getData(children);
|
|
2636
|
-
const
|
|
2637
|
-
const
|
|
2814
|
+
const knownNames = Object.keys(data);
|
|
2815
|
+
const allowedTags = name => /^\d+$/.test(name) || keepArray.indexOf(name) > -1 || knownNames.indexOf(name) > -1;
|
|
2816
|
+
const ast = index.parse(`<0>${targetString}</0>`, {
|
|
2817
|
+
allowedTags
|
|
2818
|
+
});
|
|
2638
2819
|
const opts = {
|
|
2639
2820
|
...data,
|
|
2640
2821
|
...combinedTOpts
|
|
@@ -3414,7 +3595,7 @@ define(['exports', 'react'], (function (exports, React) { 'use strict';
|
|
|
3414
3595
|
...i18n.options.interpolation.defaultVariables
|
|
3415
3596
|
};
|
|
3416
3597
|
}
|
|
3417
|
-
const translation = t(i18nKey, {
|
|
3598
|
+
const translation = t(i18nKey || defaultTranslation, {
|
|
3418
3599
|
defaultValue: defaultTranslation,
|
|
3419
3600
|
...mergedValues,
|
|
3420
3601
|
ns: namespaces
|