babel-plugin-jsx-dom-expressions 0.40.11 → 0.40.14
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/index.js +151 -37
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -321,6 +321,49 @@ const SVGElements = /*#__PURE__*/new Set([
|
|
|
321
321
|
"vkern"]);
|
|
322
322
|
|
|
323
323
|
|
|
324
|
+
const MathMLElements = /*#__PURE__*/new Set([
|
|
325
|
+
"annotation",
|
|
326
|
+
"annotation-xml",
|
|
327
|
+
"maction",
|
|
328
|
+
"math",
|
|
329
|
+
"menclose",
|
|
330
|
+
"merror",
|
|
331
|
+
"mfenced",
|
|
332
|
+
"mfrac",
|
|
333
|
+
"mi",
|
|
334
|
+
"mmultiscripts",
|
|
335
|
+
"mn",
|
|
336
|
+
"mo",
|
|
337
|
+
"mover",
|
|
338
|
+
"mpadded",
|
|
339
|
+
"mphantom",
|
|
340
|
+
"mprescripts",
|
|
341
|
+
"mroot",
|
|
342
|
+
"mrow",
|
|
343
|
+
"ms",
|
|
344
|
+
"mspace",
|
|
345
|
+
"msqrt",
|
|
346
|
+
"mstyle",
|
|
347
|
+
"msub",
|
|
348
|
+
"msubsup",
|
|
349
|
+
"msup",
|
|
350
|
+
"mtable",
|
|
351
|
+
"mtd",
|
|
352
|
+
"mtext",
|
|
353
|
+
"mtr",
|
|
354
|
+
"munder",
|
|
355
|
+
"munderover",
|
|
356
|
+
"semantics"]);
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
const MathMLTextIntegrationPoints = /*#__PURE__*/new Set([
|
|
360
|
+
"mi",
|
|
361
|
+
"mo",
|
|
362
|
+
"mn",
|
|
363
|
+
"ms",
|
|
364
|
+
"mtext"]);
|
|
365
|
+
|
|
366
|
+
|
|
324
367
|
const SVGNamespace = {
|
|
325
368
|
xlink: "http://www.w3.org/1999/xlink",
|
|
326
369
|
xml: "http://www.w3.org/XML/1998/namespace"
|
|
@@ -409,23 +452,56 @@ function isComponent(tagName) {
|
|
|
409
452
|
|
|
410
453
|
}
|
|
411
454
|
|
|
412
|
-
// <
|
|
413
|
-
//
|
|
455
|
+
// <annotation-xml> is a MathML HTML integration point only when its encoding
|
|
456
|
+
// is text/html or application/xhtml+xml
|
|
457
|
+
function isHTMLEncodingAnnotationXML(node) {
|
|
458
|
+
const encoding = node.openingElement.attributes.find(
|
|
459
|
+
(attr) => t__namespace.isJSXAttribute(attr) && t__namespace.isJSXIdentifier(attr.name) && attr.name.name === "encoding");
|
|
460
|
+
|
|
461
|
+
return (
|
|
462
|
+
t__namespace.isStringLiteral(encoding?.value) &&
|
|
463
|
+
/^(?:text\/html|application\/xhtml\+xml)$/i.test(encoding.value.value));
|
|
464
|
+
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// <script> and <style> are only raw text in HTML. Inside SVG or MathML the
|
|
468
|
+
// parser decodes entities and treats `<` as markup, so their children still
|
|
469
|
+
// need escaping. Integration points (<foreignObject> in SVG; the MathML text
|
|
470
|
+
// integration points and <annotation-xml> with an HTML encoding in MathML)
|
|
471
|
+
// switch their content back to HTML parsing.
|
|
414
472
|
function isRawTextElement(path) {
|
|
415
473
|
const tagName = getTagName(path.node);
|
|
416
474
|
if (tagName !== "script" && tagName !== "style") return false;
|
|
417
|
-
|
|
418
|
-
|
|
475
|
+
const ancestors = [];
|
|
476
|
+
let parent = path.parentPath;
|
|
419
477
|
while (t__namespace.isJSXElement(parent.node)) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (parentTag === "foreignObject") return true;
|
|
423
|
-
if (parentTag === "svg") return false;
|
|
424
|
-
rootTag = parentTag;
|
|
478
|
+
if (isComponent(getTagName(parent.node))) break;
|
|
479
|
+
ancestors.push(parent.node);
|
|
425
480
|
parent = parent.parentPath;
|
|
426
481
|
}
|
|
427
|
-
|
|
428
|
-
|
|
482
|
+
const rootTag = ancestors.length ? getTagName(ancestors[ancestors.length - 1]) : undefined;
|
|
483
|
+
// a top-level SVG element is parsed inside an <svg> wrapper and a top-level
|
|
484
|
+
// MathML element inside a MathML template
|
|
485
|
+
let namespace = SVGElements.has(rootTag) ?
|
|
486
|
+
"svg" :
|
|
487
|
+
MathMLElements.has(rootTag) ?
|
|
488
|
+
"math" :
|
|
489
|
+
"html";
|
|
490
|
+
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
491
|
+
const parentTag = getTagName(ancestors[i]);
|
|
492
|
+
if (namespace === "html") {
|
|
493
|
+
if (parentTag === "svg") namespace = "svg";else
|
|
494
|
+
if (parentTag === "math") namespace = "math";
|
|
495
|
+
} else if (namespace === "svg") {
|
|
496
|
+
if (parentTag === "foreignObject") namespace = "html";
|
|
497
|
+
} else if (
|
|
498
|
+
MathMLTextIntegrationPoints.has(parentTag) ||
|
|
499
|
+
parentTag === "annotation-xml" && isHTMLEncodingAnnotationXML(ancestors[i]))
|
|
500
|
+
{
|
|
501
|
+
namespace = "html";
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return namespace === "html";
|
|
429
505
|
}
|
|
430
506
|
|
|
431
507
|
function hasStaticMarker(object, path) {
|
|
@@ -2646,26 +2722,38 @@ function setAttr$1(attribute, results, name, value, isSVG) {
|
|
|
2646
2722
|
}
|
|
2647
2723
|
}
|
|
2648
2724
|
|
|
2649
|
-
|
|
2725
|
+
/**
|
|
2726
|
+
* How `escapeExpression` treats a string literal it reaches.
|
|
2727
|
+
* - `undefined`: the hole itself. The caller escapes a literal when it
|
|
2728
|
+
* inlines it into the template, so it stays as written here.
|
|
2729
|
+
* - `"escape"`: a position whose value the runtime writes as is.
|
|
2730
|
+
* - `"keep"`: inside a function value in an attribute. `ssrAttribute`
|
|
2731
|
+
* stringifies the function's source, so literals stay as written.
|
|
2732
|
+
*/
|
|
2733
|
+
function escapeExpression(path, expression, attr, literals) {
|
|
2734
|
+
if (!expression) return expression;
|
|
2735
|
+
// A literal in a branch is the hole's value, which `ssr` and
|
|
2736
|
+
// `ssrAttribute` write as is, so branches escape literals.
|
|
2737
|
+
const branch = literals === "keep" ? "keep" : "escape";
|
|
2738
|
+
// A function's returns escape like branches, except for a function value in
|
|
2739
|
+
// an attribute: `ssrAttribute` stringifies its source, so its literals stay
|
|
2740
|
+
// as written at every depth.
|
|
2741
|
+
const returns = literals === undefined && attr ? "keep" : branch;
|
|
2650
2742
|
if (
|
|
2651
2743
|
t__namespace.isStringLiteral(expression) ||
|
|
2652
2744
|
t__namespace.isNumericLiteral(expression) ||
|
|
2653
2745
|
t__namespace.isTemplateLiteral(expression) && expression.expressions.length === 0)
|
|
2654
2746
|
{
|
|
2655
|
-
if (
|
|
2747
|
+
if (literals === "escape") {
|
|
2656
2748
|
if (t__namespace.isStringLiteral(expression)) return t__namespace.stringLiteral(escapeHTML(expression.value, attr));else
|
|
2657
2749
|
if (t__namespace.isTemplateLiteral(expression))
|
|
2658
|
-
return t__namespace.stringLiteral(
|
|
2750
|
+
return t__namespace.stringLiteral(
|
|
2751
|
+
escapeHTML(expression.quasis[0].value.cooked ?? expression.quasis[0].value.raw, attr));
|
|
2752
|
+
|
|
2659
2753
|
}
|
|
2660
2754
|
return expression;
|
|
2661
2755
|
} else if (t__namespace.isFunction(expression)) {
|
|
2662
|
-
|
|
2663
|
-
expression.body.body = expression.body.body.map((e) => {
|
|
2664
|
-
if (t__namespace.isReturnStatement(e))
|
|
2665
|
-
e.argument = escapeExpression(path, e.argument, attr, escapeLiterals);
|
|
2666
|
-
return e;
|
|
2667
|
-
});
|
|
2668
|
-
} else expression.body = escapeExpression(path, expression.body, attr, escapeLiterals);
|
|
2756
|
+
escapeFunctionResult(path, expression, attr, returns);
|
|
2669
2757
|
return expression;
|
|
2670
2758
|
} else if (t__namespace.isTemplateLiteral(expression)) {
|
|
2671
2759
|
// Interpolations are escaped recursively. The static quasis are not —
|
|
@@ -2673,35 +2761,30 @@ function escapeExpression(path, expression, attr, escapeLiterals) {
|
|
|
2673
2761
|
// attr="...", which HTML parses as attribute injection.
|
|
2674
2762
|
if (attr) escapeTemplateQuasis(expression, true);
|
|
2675
2763
|
expression.expressions = expression.expressions.map((e) =>
|
|
2676
|
-
escapeExpression(path, e, attr,
|
|
2764
|
+
escapeExpression(path, e, attr, literals));
|
|
2677
2765
|
|
|
2678
2766
|
return expression;
|
|
2679
2767
|
} else if (t__namespace.isUnaryExpression(expression)) {
|
|
2680
2768
|
return expression;
|
|
2681
2769
|
} else if (t__namespace.isBinaryExpression(expression)) {
|
|
2682
|
-
expression.left = escapeExpression(path, expression.left, attr,
|
|
2683
|
-
expression.right = escapeExpression(path, expression.right, attr,
|
|
2770
|
+
expression.left = escapeExpression(path, expression.left, attr, literals);
|
|
2771
|
+
expression.right = escapeExpression(path, expression.right, attr, literals);
|
|
2684
2772
|
return expression;
|
|
2685
2773
|
} else if (t__namespace.isConditionalExpression(expression)) {
|
|
2686
|
-
expression.consequent = escapeExpression(path, expression.consequent, attr,
|
|
2687
|
-
expression.alternate = escapeExpression(path, expression.alternate, attr,
|
|
2774
|
+
expression.consequent = escapeExpression(path, expression.consequent, attr, branch);
|
|
2775
|
+
expression.alternate = escapeExpression(path, expression.alternate, attr, branch);
|
|
2688
2776
|
return expression;
|
|
2689
2777
|
} else if (t__namespace.isLogicalExpression(expression)) {
|
|
2690
2778
|
// Preserve the old short-circuit shape for && while still escaping the
|
|
2691
2779
|
// selected result of || and ?? as a whole.
|
|
2692
2780
|
if (expression.operator === "&&") {
|
|
2693
|
-
expression.right = escapeExpression(path, expression.right, attr,
|
|
2781
|
+
expression.right = escapeExpression(path, expression.right, attr, branch);
|
|
2694
2782
|
return expression;
|
|
2695
2783
|
}
|
|
2696
2784
|
} else if (t__namespace.isCallExpression(expression) && t__namespace.isFunction(expression.callee)) {
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
e.argument = escapeExpression(path, e.argument, attr, escapeLiterals);
|
|
2701
|
-
return e;
|
|
2702
|
-
});
|
|
2703
|
-
} else
|
|
2704
|
-
expression.callee.body = escapeExpression(path, expression.callee.body, attr, escapeLiterals);
|
|
2785
|
+
// The call's result is the hole's value, so its returns escape like
|
|
2786
|
+
// branches.
|
|
2787
|
+
escapeFunctionResult(path, expression.callee, attr, branch);
|
|
2705
2788
|
return expression;
|
|
2706
2789
|
} else if (t__namespace.isJSXElement(expression) && !isComponent(getTagName(expression))) {
|
|
2707
2790
|
expression.wontEscape = true;
|
|
@@ -2714,6 +2797,37 @@ function escapeExpression(path, expression, attr, escapeLiterals) {
|
|
|
2714
2797
|
|
|
2715
2798
|
}
|
|
2716
2799
|
|
|
2800
|
+
/** Escapes a function's expression body or its `return` arguments. */
|
|
2801
|
+
function escapeFunctionResult(path, fn, attr, literals) {
|
|
2802
|
+
if (t__namespace.isBlockStatement(fn.body)) escapeReturns(path, fn.body, attr, literals);else
|
|
2803
|
+
fn.body = escapeExpression(path, fn.body, attr, literals);
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2806
|
+
/**
|
|
2807
|
+
* Escapes the `return` arguments in a statement at any depth, without
|
|
2808
|
+
* entering nested functions or classes.
|
|
2809
|
+
*/
|
|
2810
|
+
function escapeReturns(path, statement, attr, literals) {
|
|
2811
|
+
if (!statement) return;
|
|
2812
|
+
if (t__namespace.isReturnStatement(statement)) {
|
|
2813
|
+
statement.argument = escapeExpression(path, statement.argument, attr, literals);
|
|
2814
|
+
} else if (t__namespace.isBlockStatement(statement)) {
|
|
2815
|
+
for (const child of statement.body) escapeReturns(path, child, attr, literals);
|
|
2816
|
+
} else if (t__namespace.isIfStatement(statement)) {
|
|
2817
|
+
escapeReturns(path, statement.consequent, attr, literals);
|
|
2818
|
+
escapeReturns(path, statement.alternate, attr, literals);
|
|
2819
|
+
} else if (t__namespace.isSwitchStatement(statement)) {
|
|
2820
|
+
for (const switchCase of statement.cases)
|
|
2821
|
+
for (const child of switchCase.consequent) escapeReturns(path, child, attr, literals);
|
|
2822
|
+
} else if (t__namespace.isTryStatement(statement)) {
|
|
2823
|
+
escapeReturns(path, statement.block, attr, literals);
|
|
2824
|
+
escapeReturns(path, statement.handler && statement.handler.body, attr, literals);
|
|
2825
|
+
escapeReturns(path, statement.finalizer, attr, literals);
|
|
2826
|
+
} else if (t__namespace.isLoop(statement) || t__namespace.isLabeledStatement(statement) || t__namespace.isWithStatement(statement)) {
|
|
2827
|
+
escapeReturns(path, statement.body, attr, literals);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2717
2831
|
function escapeTemplateQuasis(expression, attr) {
|
|
2718
2832
|
for (const quasi of expression.quasis) {
|
|
2719
2833
|
const src = quasi.value.cooked != null ? quasi.value.cooked : quasi.value.raw;
|
|
@@ -2889,14 +3003,14 @@ function transformAttributes$1(path, results, info) {
|
|
|
2889
3003
|
if (p.computed) {
|
|
2890
3004
|
return t__namespace.callExpression(registerImportMethod(path, "ssrStyleProperty"), [
|
|
2891
3005
|
t__namespace.binaryExpression("+", p.key, t__namespace.stringLiteral(":")),
|
|
2892
|
-
escapeExpression(path, p.value, true,
|
|
3006
|
+
escapeExpression(path, p.value, true, "escape")]);
|
|
2893
3007
|
|
|
2894
3008
|
}
|
|
2895
3009
|
return t__namespace.callExpression(registerImportMethod(path, "ssrStyleProperty"), [
|
|
2896
3010
|
t__namespace.stringLiteral(
|
|
2897
3011
|
(i ? ";" : "") + (t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value) + ":"),
|
|
2898
3012
|
|
|
2899
|
-
escapeExpression(path, p.value, true,
|
|
3013
|
+
escapeExpression(path, p.value, true, "escape")]);
|
|
2900
3014
|
|
|
2901
3015
|
});
|
|
2902
3016
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babel-plugin-jsx-dom-expressions",
|
|
3
3
|
"description": "A JSX to DOM plugin that wraps expressions for fine grained change detection",
|
|
4
|
-
"version": "0.40.
|
|
4
|
+
"version": "0.40.14",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"@rollup/plugin-babel": "6.0.3",
|
|
34
34
|
"@types/babel__core": "^7.20.5"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "f6fecdf9e455d03cfa90aaba0323ea3d4686ada6"
|
|
37
37
|
}
|