Explorar el Código

Backport PR #12276: Allow linear and radial gradient (#12300)

Co-authored-by: Michał Krassowski <5832902+krassowski@users.noreply.github.com>
MeeseeksMachine hace 3 años
padre
commit
904383dae8
Se han modificado 2 ficheros con 63 adiciones y 4 borrados
  1. 22 4
      packages/apputils/src/sanitizer.ts
  2. 41 0
      packages/apputils/test/sanitizer.spec.ts

+ 22 - 4
packages/apputils/src/sanitizer.ts

@@ -30,7 +30,7 @@ class CssProp {
     number: `[+-]?([0-9]*[.])?[0-9]+(e-?[0-9]*)?`,
     number_pos: `[+]?([0-9]*[.])?[0-9]+(e-?[0-9]*)?`,
     number_zero_hundred: `[+]?(([0-9]|[1-9][0-9])([.][0-9]+)?|100)`,
-    number_zero_one: `[+]?(1([.][0]+)?|0([.][0-9]+)?)`
+    number_zero_one: `[+]?(1([.][0]+)?|0?([.][0-9]+)?)`
   };
 
   /*
@@ -95,6 +95,8 @@ class CssProp {
     border_width: `thin|medium|thick|${CssProp.B.length}`,
     bottom: `${CssProp.B.length}|auto`,
     color: `${CssProp._COLOR.hex}|${CssProp._COLOR.rgb}|${CssProp._COLOR.rgba}|${CssProp._COLOR.name}`,
+    color_stop_length: `(${CssProp.B.len_or_perc}\\s*){1,2}`,
+    linear_color_hint: `${CssProp.B.len_or_perc}`,
     family_name: `${CssProp.B.string}|(${CssProp.B.ident}\\s*)+`,
     image_decl: CssProp.B.url,
     left: `${CssProp.B.length}|auto`,
@@ -111,16 +113,32 @@ class CssProp {
 
   private static readonly _C1 = {
     image_list: `image\\(\\s*(${CssProp.B.url})*\\s*(${CssProp.B.url}|${CssProp._C.color})\\s*\\)`,
+    linear_color_stop: `(${CssProp._C.color})(\\s*${CssProp._C.color_stop_length})?`,
     shadow: `((${CssProp._C.color})\\s+((${CssProp.B.length})\\s*){2,4}(\s+inset)?)|((inset\\s+)?((${CssProp.B.length})\\s*){2,4}\\s*(${CssProp._C.color})?)`
   };
 
   private static readonly _C2 = {
-    bg_image: `(${CssProp.B.url}|${CssProp._C1.image_list})|none`,
-    image: `${CssProp.B.url}|${CssProp._C1.image_list}`,
+    color_stop_list: `((${CssProp._C1.linear_color_stop})(\\s*(${CssProp._C.linear_color_hint}))?\\s*,\\s*)+(${CssProp._C1.linear_color_stop})`,
     shape: `rect\\(\\s*(${CssProp._C.top})\\s*,\\s*(${CssProp._C.right})\\s*,\\s*(${CssProp._C.bottom})\\s*,\\s*(${CssProp._C.left})\\s*\\)`
   };
 
-  private static readonly C = { ...CssProp._C, ...CssProp._C1, ...CssProp._C2 };
+  private static readonly _C3 = {
+    linear_gradient: `linear-gradient\\((((${CssProp.B.angle})|to\\s+(${CssProp.A.side_or_corner}))\\s*,\\s*)?\\s*(${CssProp._C2.color_stop_list})\\s*\\)`,
+    radial_gradient: `radial-gradient\\(((((${CssProp.A.ending_shape})|(${CssProp._C.size}))\\s*)*\\s*(at\\s+${CssProp._C.position})?\\s*,\\s*)?\\s*(${CssProp._C2.color_stop_list})\\s*\\)`
+  };
+
+  private static readonly _C4 = {
+    image: `${CssProp.B.url}|${CssProp._C3.linear_gradient}|${CssProp._C3.radial_gradient}|${CssProp._C1.image_list}`,
+    bg_image: `(${CssProp.B.url}|${CssProp._C3.linear_gradient}|${CssProp._C3.radial_gradient}|${CssProp._C1.image_list})|none`
+  };
+
+  private static readonly C = {
+    ...CssProp._C,
+    ...CssProp._C1,
+    ...CssProp._C2,
+    ...CssProp._C3,
+    ...CssProp._C4
+  };
 
   /*
    * Property value regular expressions not dependant on other sub expressions

+ 41 - 0
packages/apputils/test/sanitizer.spec.ts

@@ -118,6 +118,47 @@ describe('defaultSanitizer', () => {
       expect(defaultSanitizer.sanitize(div)).toBe(div);
     });
 
+    it('should allow abbreviated floats in CSS', () => {
+      const div = '<div style="color:rgba(255,0,0,.8)"></div>';
+      expect(defaultSanitizer.sanitize(div)).toBe(div);
+    });
+
+    it('should allow background CSS line-gradient with directional', () => {
+      const div =
+        '<div style="background:linear-gradient(to left top, blue, red)"></div>';
+      expect(defaultSanitizer.sanitize(div)).toBe(div);
+    });
+
+    it('should allow background CSS line-gradient with angle', () => {
+      const div =
+        '<div style="background:linear-gradient(0deg, blue, green 40%, red)"></div>';
+      expect(defaultSanitizer.sanitize(div)).toBe(div);
+    });
+
+    it('should allow fully specified background CSS line-gradient', () => {
+      const div =
+        '<div style="background:linear-gradient(red 0%, orange 10% 30%, yellow 50% 70%, green 90% 100%)"></div>';
+      expect(defaultSanitizer.sanitize(div)).toBe(div);
+    });
+
+    it('should allow simple background CSS radial-gradient', () => {
+      const div =
+        '<div style="background:radial-gradient(#e66465, #9198e5)"></div>';
+      expect(defaultSanitizer.sanitize(div)).toBe(div);
+    });
+
+    it('should allow fully specified background CSS radial-gradient', () => {
+      const div =
+        '<div style="background:radial-gradient(ellipse farthest-corner at 90% 90%, red, yellow 10%, #1e90ff 50%, beige)"></div>';
+      expect(defaultSanitizer.sanitize(div)).toBe(div);
+    });
+
+    it('strip incorrect CSS line-gradient', () => {
+      const div =
+        '<div style="background:linear-gradient(http://example.com)"></div>';
+      expect(defaultSanitizer.sanitize(div)).toBe('<div></div>');
+    });
+
     it("should strip 'content' properties from inline CSS", () => {
       const div = '<div style="color: green; content: attr(title)"></div>';
       expect(defaultSanitizer.sanitize(div)).toBe(