sygnal 4.2.0 → 4.2.1

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.
@@ -18,8 +18,33 @@ const fun = (v) => typeof v === 'function';
18
18
 
19
19
  const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
20
20
 
21
- const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
22
- polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
21
+ const svgPropsMap = {
22
+ // Container / structural
23
+ svg: 1, g: 1, defs: 1, symbol: 1, use: 1,
24
+ // Shape
25
+ circle: 1, ellipse: 1, line: 1, path: 1, polygon: 1, polyline: 1, rect: 1,
26
+ // Text (no HTML collision: HTML has no <text>, <tspan>, or <textPath>)
27
+ text: 1, tspan: 1, textPath: 1,
28
+ // Gradient / paint
29
+ linearGradient: 1, radialGradient: 1, stop: 1, pattern: 1,
30
+ // Clipping / masking
31
+ clipPath: 1, mask: 1,
32
+ // Marker
33
+ marker: 1,
34
+ // Filter primitives
35
+ filter: 1, feBlend: 1, feColorMatrix: 1, feComponentTransfer: 1,
36
+ feComposite: 1, feConvolveMatrix: 1, feDiffuseLighting: 1,
37
+ feDisplacementMap: 1, feDropShadow: 1, feFlood: 1, feGaussianBlur: 1,
38
+ feImage: 1, feMerge: 1, feMergeNode: 1, feMorphology: 1, feOffset: 1,
39
+ fePointLight: 1, feSpecularLighting: 1, feSpotLight: 1, feTile: 1,
40
+ feTurbulence: 1, feFuncR: 1, feFuncG: 1, feFuncB: 1, feFuncA: 1,
41
+ // Descriptive (excluding 'title' — collides with HTML <title>)
42
+ desc: 1, metadata: 1,
43
+ // Other (excluding 'a', 'image', 'style', 'script' — collide with HTML)
44
+ foreignObject: 1, switch: 1,
45
+ // Animation
46
+ animate: 1, animateMotion: 1, animateTransform: 1, set: 1, mpath: 1,
47
+ };
23
48
 
24
49
  const svg = (v) => v.sel in svgPropsMap;
25
50
 
@@ -79,17 +104,29 @@ const createTextElement = (text$1) => !text(text$1) ? undefined : {
79
104
  key: undefined
80
105
  };
81
106
 
82
- const considerSvg = (vnode) => !svg(vnode) ? vnode :
83
- assign(vnode,
84
- { data: omit('props', extend(vnode.data,
85
- { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
86
- { class: vnode.data.props ? vnode.data.props.className : undefined }
87
- )) }
107
+ const applySvg = (vnode) => {
108
+ // Skip text vnodes (sel is undefined) and nullish values
109
+ if (!vnode || undefinedv(vnode.sel)) return vnode
110
+
111
+ const data = vnode.data || {};
112
+ const props = data.props || {};
113
+ const propsWithoutClassName = omit('className', props);
114
+ const classAttr = props.className !== undefined ? { class: props.className } : {};
115
+ const mergedAttrs = assign({}, propsWithoutClassName, classAttr, data.attrs || {});
116
+
117
+ return assign(vnode,
118
+ { data: omit('props', assign({}, data,
119
+ { ns: 'http://www.w3.org/2000/svg', attrs: mergedAttrs }
88
120
  )) },
89
- { children: undefinedv(vnode.children) ? undefined :
90
- vnode.children.map((child) => considerSvg(child))
121
+ // foreignObject contains HTML, not SVG — do not recurse into its children
122
+ { children: (!Array.isArray(vnode.children) || vnode.sel === 'foreignObject')
123
+ ? vnode.children
124
+ : vnode.children.map((child) => applySvg(child))
91
125
  }
92
- );
126
+ )
127
+ };
128
+
129
+ const considerSvg = (vnode) => !svg(vnode) ? vnode : applySvg(vnode);
93
130
 
94
131
  const rewrites = {
95
132
  for: 'attrs',
@@ -145,7 +182,7 @@ const applyFocusProps = (data) => {
145
182
  return data
146
183
  };
147
184
 
148
- const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
185
+ const sanitizeData = (data, modules) => applyFocusProps(rewriteModules(deepifyKeys(data, modules), modules));
149
186
 
150
187
  const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
151
188
 
@@ -16,8 +16,33 @@ const fun = (v) => typeof v === 'function';
16
16
 
17
17
  const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
18
18
 
19
- const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
20
- polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
19
+ const svgPropsMap = {
20
+ // Container / structural
21
+ svg: 1, g: 1, defs: 1, symbol: 1, use: 1,
22
+ // Shape
23
+ circle: 1, ellipse: 1, line: 1, path: 1, polygon: 1, polyline: 1, rect: 1,
24
+ // Text (no HTML collision: HTML has no <text>, <tspan>, or <textPath>)
25
+ text: 1, tspan: 1, textPath: 1,
26
+ // Gradient / paint
27
+ linearGradient: 1, radialGradient: 1, stop: 1, pattern: 1,
28
+ // Clipping / masking
29
+ clipPath: 1, mask: 1,
30
+ // Marker
31
+ marker: 1,
32
+ // Filter primitives
33
+ filter: 1, feBlend: 1, feColorMatrix: 1, feComponentTransfer: 1,
34
+ feComposite: 1, feConvolveMatrix: 1, feDiffuseLighting: 1,
35
+ feDisplacementMap: 1, feDropShadow: 1, feFlood: 1, feGaussianBlur: 1,
36
+ feImage: 1, feMerge: 1, feMergeNode: 1, feMorphology: 1, feOffset: 1,
37
+ fePointLight: 1, feSpecularLighting: 1, feSpotLight: 1, feTile: 1,
38
+ feTurbulence: 1, feFuncR: 1, feFuncG: 1, feFuncB: 1, feFuncA: 1,
39
+ // Descriptive (excluding 'title' — collides with HTML <title>)
40
+ desc: 1, metadata: 1,
41
+ // Other (excluding 'a', 'image', 'style', 'script' — collide with HTML)
42
+ foreignObject: 1, switch: 1,
43
+ // Animation
44
+ animate: 1, animateMotion: 1, animateTransform: 1, set: 1, mpath: 1,
45
+ };
21
46
 
22
47
  const svg = (v) => v.sel in svgPropsMap;
23
48
 
@@ -77,17 +102,29 @@ const createTextElement = (text$1) => !text(text$1) ? undefined : {
77
102
  key: undefined
78
103
  };
79
104
 
80
- const considerSvg = (vnode) => !svg(vnode) ? vnode :
81
- assign(vnode,
82
- { data: omit('props', extend(vnode.data,
83
- { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
84
- { class: vnode.data.props ? vnode.data.props.className : undefined }
85
- )) }
105
+ const applySvg = (vnode) => {
106
+ // Skip text vnodes (sel is undefined) and nullish values
107
+ if (!vnode || undefinedv(vnode.sel)) return vnode
108
+
109
+ const data = vnode.data || {};
110
+ const props = data.props || {};
111
+ const propsWithoutClassName = omit('className', props);
112
+ const classAttr = props.className !== undefined ? { class: props.className } : {};
113
+ const mergedAttrs = assign({}, propsWithoutClassName, classAttr, data.attrs || {});
114
+
115
+ return assign(vnode,
116
+ { data: omit('props', assign({}, data,
117
+ { ns: 'http://www.w3.org/2000/svg', attrs: mergedAttrs }
86
118
  )) },
87
- { children: undefinedv(vnode.children) ? undefined :
88
- vnode.children.map((child) => considerSvg(child))
119
+ // foreignObject contains HTML, not SVG — do not recurse into its children
120
+ { children: (!Array.isArray(vnode.children) || vnode.sel === 'foreignObject')
121
+ ? vnode.children
122
+ : vnode.children.map((child) => applySvg(child))
89
123
  }
90
- );
124
+ )
125
+ };
126
+
127
+ const considerSvg = (vnode) => !svg(vnode) ? vnode : applySvg(vnode);
91
128
 
92
129
  const rewrites = {
93
130
  for: 'attrs',
@@ -143,7 +180,7 @@ const applyFocusProps = (data) => {
143
180
  return data
144
181
  };
145
182
 
146
- const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
183
+ const sanitizeData = (data, modules) => applyFocusProps(rewriteModules(deepifyKeys(data, modules), modules));
147
184
 
148
185
  const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
149
186
 
@@ -18,8 +18,33 @@ const fun = (v) => typeof v === 'function';
18
18
 
19
19
  const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
20
20
 
21
- const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
22
- polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
21
+ const svgPropsMap = {
22
+ // Container / structural
23
+ svg: 1, g: 1, defs: 1, symbol: 1, use: 1,
24
+ // Shape
25
+ circle: 1, ellipse: 1, line: 1, path: 1, polygon: 1, polyline: 1, rect: 1,
26
+ // Text (no HTML collision: HTML has no <text>, <tspan>, or <textPath>)
27
+ text: 1, tspan: 1, textPath: 1,
28
+ // Gradient / paint
29
+ linearGradient: 1, radialGradient: 1, stop: 1, pattern: 1,
30
+ // Clipping / masking
31
+ clipPath: 1, mask: 1,
32
+ // Marker
33
+ marker: 1,
34
+ // Filter primitives
35
+ filter: 1, feBlend: 1, feColorMatrix: 1, feComponentTransfer: 1,
36
+ feComposite: 1, feConvolveMatrix: 1, feDiffuseLighting: 1,
37
+ feDisplacementMap: 1, feDropShadow: 1, feFlood: 1, feGaussianBlur: 1,
38
+ feImage: 1, feMerge: 1, feMergeNode: 1, feMorphology: 1, feOffset: 1,
39
+ fePointLight: 1, feSpecularLighting: 1, feSpotLight: 1, feTile: 1,
40
+ feTurbulence: 1, feFuncR: 1, feFuncG: 1, feFuncB: 1, feFuncA: 1,
41
+ // Descriptive (excluding 'title' — collides with HTML <title>)
42
+ desc: 1, metadata: 1,
43
+ // Other (excluding 'a', 'image', 'style', 'script' — collide with HTML)
44
+ foreignObject: 1, switch: 1,
45
+ // Animation
46
+ animate: 1, animateMotion: 1, animateTransform: 1, set: 1, mpath: 1,
47
+ };
23
48
 
24
49
  const svg = (v) => v.sel in svgPropsMap;
25
50
 
@@ -79,17 +104,29 @@ const createTextElement = (text$1) => !text(text$1) ? undefined : {
79
104
  key: undefined
80
105
  };
81
106
 
82
- const considerSvg = (vnode) => !svg(vnode) ? vnode :
83
- assign(vnode,
84
- { data: omit('props', extend(vnode.data,
85
- { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
86
- { class: vnode.data.props ? vnode.data.props.className : undefined }
87
- )) }
107
+ const applySvg = (vnode) => {
108
+ // Skip text vnodes (sel is undefined) and nullish values
109
+ if (!vnode || undefinedv(vnode.sel)) return vnode
110
+
111
+ const data = vnode.data || {};
112
+ const props = data.props || {};
113
+ const propsWithoutClassName = omit('className', props);
114
+ const classAttr = props.className !== undefined ? { class: props.className } : {};
115
+ const mergedAttrs = assign({}, propsWithoutClassName, classAttr, data.attrs || {});
116
+
117
+ return assign(vnode,
118
+ { data: omit('props', assign({}, data,
119
+ { ns: 'http://www.w3.org/2000/svg', attrs: mergedAttrs }
88
120
  )) },
89
- { children: undefinedv(vnode.children) ? undefined :
90
- vnode.children.map((child) => considerSvg(child))
121
+ // foreignObject contains HTML, not SVG — do not recurse into its children
122
+ { children: (!Array.isArray(vnode.children) || vnode.sel === 'foreignObject')
123
+ ? vnode.children
124
+ : vnode.children.map((child) => applySvg(child))
91
125
  }
92
- );
126
+ )
127
+ };
128
+
129
+ const considerSvg = (vnode) => !svg(vnode) ? vnode : applySvg(vnode);
93
130
 
94
131
  const rewrites = {
95
132
  for: 'attrs',
@@ -145,7 +182,7 @@ const applyFocusProps = (data) => {
145
182
  return data
146
183
  };
147
184
 
148
- const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
185
+ const sanitizeData = (data, modules) => applyFocusProps(rewriteModules(deepifyKeys(data, modules), modules));
149
186
 
150
187
  const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
151
188
 
@@ -16,8 +16,33 @@ const fun = (v) => typeof v === 'function';
16
16
 
17
17
  const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
18
18
 
19
- const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
20
- polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
19
+ const svgPropsMap = {
20
+ // Container / structural
21
+ svg: 1, g: 1, defs: 1, symbol: 1, use: 1,
22
+ // Shape
23
+ circle: 1, ellipse: 1, line: 1, path: 1, polygon: 1, polyline: 1, rect: 1,
24
+ // Text (no HTML collision: HTML has no <text>, <tspan>, or <textPath>)
25
+ text: 1, tspan: 1, textPath: 1,
26
+ // Gradient / paint
27
+ linearGradient: 1, radialGradient: 1, stop: 1, pattern: 1,
28
+ // Clipping / masking
29
+ clipPath: 1, mask: 1,
30
+ // Marker
31
+ marker: 1,
32
+ // Filter primitives
33
+ filter: 1, feBlend: 1, feColorMatrix: 1, feComponentTransfer: 1,
34
+ feComposite: 1, feConvolveMatrix: 1, feDiffuseLighting: 1,
35
+ feDisplacementMap: 1, feDropShadow: 1, feFlood: 1, feGaussianBlur: 1,
36
+ feImage: 1, feMerge: 1, feMergeNode: 1, feMorphology: 1, feOffset: 1,
37
+ fePointLight: 1, feSpecularLighting: 1, feSpotLight: 1, feTile: 1,
38
+ feTurbulence: 1, feFuncR: 1, feFuncG: 1, feFuncB: 1, feFuncA: 1,
39
+ // Descriptive (excluding 'title' — collides with HTML <title>)
40
+ desc: 1, metadata: 1,
41
+ // Other (excluding 'a', 'image', 'style', 'script' — collide with HTML)
42
+ foreignObject: 1, switch: 1,
43
+ // Animation
44
+ animate: 1, animateMotion: 1, animateTransform: 1, set: 1, mpath: 1,
45
+ };
21
46
 
22
47
  const svg = (v) => v.sel in svgPropsMap;
23
48
 
@@ -77,17 +102,29 @@ const createTextElement = (text$1) => !text(text$1) ? undefined : {
77
102
  key: undefined
78
103
  };
79
104
 
80
- const considerSvg = (vnode) => !svg(vnode) ? vnode :
81
- assign(vnode,
82
- { data: omit('props', extend(vnode.data,
83
- { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
84
- { class: vnode.data.props ? vnode.data.props.className : undefined }
85
- )) }
105
+ const applySvg = (vnode) => {
106
+ // Skip text vnodes (sel is undefined) and nullish values
107
+ if (!vnode || undefinedv(vnode.sel)) return vnode
108
+
109
+ const data = vnode.data || {};
110
+ const props = data.props || {};
111
+ const propsWithoutClassName = omit('className', props);
112
+ const classAttr = props.className !== undefined ? { class: props.className } : {};
113
+ const mergedAttrs = assign({}, propsWithoutClassName, classAttr, data.attrs || {});
114
+
115
+ return assign(vnode,
116
+ { data: omit('props', assign({}, data,
117
+ { ns: 'http://www.w3.org/2000/svg', attrs: mergedAttrs }
86
118
  )) },
87
- { children: undefinedv(vnode.children) ? undefined :
88
- vnode.children.map((child) => considerSvg(child))
119
+ // foreignObject contains HTML, not SVG — do not recurse into its children
120
+ { children: (!Array.isArray(vnode.children) || vnode.sel === 'foreignObject')
121
+ ? vnode.children
122
+ : vnode.children.map((child) => applySvg(child))
89
123
  }
90
- );
124
+ )
125
+ };
126
+
127
+ const considerSvg = (vnode) => !svg(vnode) ? vnode : applySvg(vnode);
91
128
 
92
129
  const rewrites = {
93
130
  for: 'attrs',
@@ -143,7 +180,7 @@ const applyFocusProps = (data) => {
143
180
  return data
144
181
  };
145
182
 
146
- const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
183
+ const sanitizeData = (data, modules) => applyFocusProps(rewriteModules(deepifyKeys(data, modules), modules));
147
184
 
148
185
  const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
149
186
 
package/dist/jsx.cjs.js CHANGED
@@ -18,8 +18,33 @@ const fun = (v) => typeof v === 'function';
18
18
 
19
19
  const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
20
20
 
21
- const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
22
- polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
21
+ const svgPropsMap = {
22
+ // Container / structural
23
+ svg: 1, g: 1, defs: 1, symbol: 1, use: 1,
24
+ // Shape
25
+ circle: 1, ellipse: 1, line: 1, path: 1, polygon: 1, polyline: 1, rect: 1,
26
+ // Text (no HTML collision: HTML has no <text>, <tspan>, or <textPath>)
27
+ text: 1, tspan: 1, textPath: 1,
28
+ // Gradient / paint
29
+ linearGradient: 1, radialGradient: 1, stop: 1, pattern: 1,
30
+ // Clipping / masking
31
+ clipPath: 1, mask: 1,
32
+ // Marker
33
+ marker: 1,
34
+ // Filter primitives
35
+ filter: 1, feBlend: 1, feColorMatrix: 1, feComponentTransfer: 1,
36
+ feComposite: 1, feConvolveMatrix: 1, feDiffuseLighting: 1,
37
+ feDisplacementMap: 1, feDropShadow: 1, feFlood: 1, feGaussianBlur: 1,
38
+ feImage: 1, feMerge: 1, feMergeNode: 1, feMorphology: 1, feOffset: 1,
39
+ fePointLight: 1, feSpecularLighting: 1, feSpotLight: 1, feTile: 1,
40
+ feTurbulence: 1, feFuncR: 1, feFuncG: 1, feFuncB: 1, feFuncA: 1,
41
+ // Descriptive (excluding 'title' — collides with HTML <title>)
42
+ desc: 1, metadata: 1,
43
+ // Other (excluding 'a', 'image', 'style', 'script' — collide with HTML)
44
+ foreignObject: 1, switch: 1,
45
+ // Animation
46
+ animate: 1, animateMotion: 1, animateTransform: 1, set: 1, mpath: 1,
47
+ };
23
48
 
24
49
  const svg = (v) => v.sel in svgPropsMap;
25
50
 
@@ -79,17 +104,29 @@ const createTextElement = (text$1) => !text(text$1) ? undefined : {
79
104
  key: undefined
80
105
  };
81
106
 
82
- const considerSvg = (vnode) => !svg(vnode) ? vnode :
83
- assign(vnode,
84
- { data: omit('props', extend(vnode.data,
85
- { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
86
- { class: vnode.data.props ? vnode.data.props.className : undefined }
87
- )) }
107
+ const applySvg = (vnode) => {
108
+ // Skip text vnodes (sel is undefined) and nullish values
109
+ if (!vnode || undefinedv(vnode.sel)) return vnode
110
+
111
+ const data = vnode.data || {};
112
+ const props = data.props || {};
113
+ const propsWithoutClassName = omit('className', props);
114
+ const classAttr = props.className !== undefined ? { class: props.className } : {};
115
+ const mergedAttrs = assign({}, propsWithoutClassName, classAttr, data.attrs || {});
116
+
117
+ return assign(vnode,
118
+ { data: omit('props', assign({}, data,
119
+ { ns: 'http://www.w3.org/2000/svg', attrs: mergedAttrs }
88
120
  )) },
89
- { children: undefinedv(vnode.children) ? undefined :
90
- vnode.children.map((child) => considerSvg(child))
121
+ // foreignObject contains HTML, not SVG — do not recurse into its children
122
+ { children: (!Array.isArray(vnode.children) || vnode.sel === 'foreignObject')
123
+ ? vnode.children
124
+ : vnode.children.map((child) => applySvg(child))
91
125
  }
92
- );
126
+ )
127
+ };
128
+
129
+ const considerSvg = (vnode) => !svg(vnode) ? vnode : applySvg(vnode);
93
130
 
94
131
  const rewrites = {
95
132
  for: 'attrs',
@@ -145,7 +182,7 @@ const applyFocusProps = (data) => {
145
182
  return data
146
183
  };
147
184
 
148
- const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
185
+ const sanitizeData = (data, modules) => applyFocusProps(rewriteModules(deepifyKeys(data, modules), modules));
149
186
 
150
187
  const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
151
188
 
package/dist/jsx.esm.js CHANGED
@@ -16,8 +16,33 @@ const fun = (v) => typeof v === 'function';
16
16
 
17
17
  const vnode$1 = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v;
18
18
 
19
- const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
20
- polyline: 1, rect: 1, g: 1, path: 1, text: 1 };
19
+ const svgPropsMap = {
20
+ // Container / structural
21
+ svg: 1, g: 1, defs: 1, symbol: 1, use: 1,
22
+ // Shape
23
+ circle: 1, ellipse: 1, line: 1, path: 1, polygon: 1, polyline: 1, rect: 1,
24
+ // Text (no HTML collision: HTML has no <text>, <tspan>, or <textPath>)
25
+ text: 1, tspan: 1, textPath: 1,
26
+ // Gradient / paint
27
+ linearGradient: 1, radialGradient: 1, stop: 1, pattern: 1,
28
+ // Clipping / masking
29
+ clipPath: 1, mask: 1,
30
+ // Marker
31
+ marker: 1,
32
+ // Filter primitives
33
+ filter: 1, feBlend: 1, feColorMatrix: 1, feComponentTransfer: 1,
34
+ feComposite: 1, feConvolveMatrix: 1, feDiffuseLighting: 1,
35
+ feDisplacementMap: 1, feDropShadow: 1, feFlood: 1, feGaussianBlur: 1,
36
+ feImage: 1, feMerge: 1, feMergeNode: 1, feMorphology: 1, feOffset: 1,
37
+ fePointLight: 1, feSpecularLighting: 1, feSpotLight: 1, feTile: 1,
38
+ feTurbulence: 1, feFuncR: 1, feFuncG: 1, feFuncB: 1, feFuncA: 1,
39
+ // Descriptive (excluding 'title' — collides with HTML <title>)
40
+ desc: 1, metadata: 1,
41
+ // Other (excluding 'a', 'image', 'style', 'script' — collide with HTML)
42
+ foreignObject: 1, switch: 1,
43
+ // Animation
44
+ animate: 1, animateMotion: 1, animateTransform: 1, set: 1, mpath: 1,
45
+ };
21
46
 
22
47
  const svg = (v) => v.sel in svgPropsMap;
23
48
 
@@ -77,17 +102,29 @@ const createTextElement = (text$1) => !text(text$1) ? undefined : {
77
102
  key: undefined
78
103
  };
79
104
 
80
- const considerSvg = (vnode) => !svg(vnode) ? vnode :
81
- assign(vnode,
82
- { data: omit('props', extend(vnode.data,
83
- { ns: 'http://www.w3.org/2000/svg', attrs: omit('className', extend(vnode.data.props,
84
- { class: vnode.data.props ? vnode.data.props.className : undefined }
85
- )) }
105
+ const applySvg = (vnode) => {
106
+ // Skip text vnodes (sel is undefined) and nullish values
107
+ if (!vnode || undefinedv(vnode.sel)) return vnode
108
+
109
+ const data = vnode.data || {};
110
+ const props = data.props || {};
111
+ const propsWithoutClassName = omit('className', props);
112
+ const classAttr = props.className !== undefined ? { class: props.className } : {};
113
+ const mergedAttrs = assign({}, propsWithoutClassName, classAttr, data.attrs || {});
114
+
115
+ return assign(vnode,
116
+ { data: omit('props', assign({}, data,
117
+ { ns: 'http://www.w3.org/2000/svg', attrs: mergedAttrs }
86
118
  )) },
87
- { children: undefinedv(vnode.children) ? undefined :
88
- vnode.children.map((child) => considerSvg(child))
119
+ // foreignObject contains HTML, not SVG — do not recurse into its children
120
+ { children: (!Array.isArray(vnode.children) || vnode.sel === 'foreignObject')
121
+ ? vnode.children
122
+ : vnode.children.map((child) => applySvg(child))
89
123
  }
90
- );
124
+ )
125
+ };
126
+
127
+ const considerSvg = (vnode) => !svg(vnode) ? vnode : applySvg(vnode);
91
128
 
92
129
  const rewrites = {
93
130
  for: 'attrs',
@@ -143,7 +180,7 @@ const applyFocusProps = (data) => {
143
180
  return data
144
181
  };
145
182
 
146
- const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(deepifyKeys(data, modules), modules)));
183
+ const sanitizeData = (data, modules) => applyFocusProps(rewriteModules(deepifyKeys(data, modules), modules));
147
184
 
148
185
  const sanitizeText = (children) => children.length > 1 || !text(children[0]) ? undefined : children[0].toString();
149
186
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sygnal",
3
- "version": "4.2.0",
3
+ "version": "4.2.1",
4
4
  "description": "An intuitive framework for building fast and small components or applications based on Cycle.js",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "types": "./dist/index.d.ts",
@@ -13,17 +13,29 @@ const createTextElement = (text) => !is.text(text) ? undefined : {
13
13
  key: undefined
14
14
  }
15
15
 
16
- const considerSvg = (vnode) => !is.svg(vnode) ? vnode :
17
- fn.assign(vnode,
18
- { data: fn.omit('props', fn.extend(vnode.data,
19
- { ns: 'http://www.w3.org/2000/svg', attrs: fn.omit('className', fn.extend(vnode.data.props,
20
- { class: vnode.data.props ? vnode.data.props.className : undefined }
21
- )) }
16
+ const applySvg = (vnode) => {
17
+ // Skip text vnodes (sel is undefined) and nullish values
18
+ if (!vnode || is.undefinedv(vnode.sel)) return vnode
19
+
20
+ const data = vnode.data || {}
21
+ const props = data.props || {}
22
+ const propsWithoutClassName = fn.omit('className', props)
23
+ const classAttr = props.className !== undefined ? { class: props.className } : {}
24
+ const mergedAttrs = fn.assign({}, propsWithoutClassName, classAttr, data.attrs || {})
25
+
26
+ return fn.assign(vnode,
27
+ { data: fn.omit('props', fn.assign({}, data,
28
+ { ns: 'http://www.w3.org/2000/svg', attrs: mergedAttrs }
22
29
  )) },
23
- { children: is.undefinedv(vnode.children) ? undefined :
24
- vnode.children.map((child) => considerSvg(child))
30
+ // foreignObject contains HTML, not SVG — do not recurse into its children
31
+ { children: (!Array.isArray(vnode.children) || vnode.sel === 'foreignObject')
32
+ ? vnode.children
33
+ : vnode.children.map((child) => applySvg(child))
25
34
  }
26
35
  )
36
+ }
37
+
38
+ const considerSvg = (vnode) => !is.svg(vnode) ? vnode : applySvg(vnode)
27
39
 
28
40
  const rewrites = {
29
41
  for: 'attrs',
@@ -79,7 +91,7 @@ const applyFocusProps = (data) => {
79
91
  return data
80
92
  }
81
93
 
82
- const sanitizeData = (data, modules) => applyFocusProps(considerSvg(rewriteModules(fn.deepifyKeys(data, modules), modules)))
94
+ const sanitizeData = (data, modules) => applyFocusProps(rewriteModules(fn.deepifyKeys(data, modules), modules))
83
95
 
84
96
  const sanitizeText = (children) => children.length > 1 || !is.text(children[0]) ? undefined : children[0].toString()
85
97
 
package/src/pragma/is.js CHANGED
@@ -17,7 +17,32 @@ export const fun = (v) => typeof v === 'function'
17
17
 
18
18
  export const vnode = (v) => object(v) && 'sel' in v && 'data' in v && 'children' in v && 'text' in v
19
19
 
20
- const svgPropsMap = { svg: 1, circle: 1, ellipse: 1, line: 1, polygon: 1,
21
- polyline: 1, rect: 1, g: 1, path: 1, text: 1 }
20
+ const svgPropsMap = {
21
+ // Container / structural
22
+ svg: 1, g: 1, defs: 1, symbol: 1, use: 1,
23
+ // Shape
24
+ circle: 1, ellipse: 1, line: 1, path: 1, polygon: 1, polyline: 1, rect: 1,
25
+ // Text (no HTML collision: HTML has no <text>, <tspan>, or <textPath>)
26
+ text: 1, tspan: 1, textPath: 1,
27
+ // Gradient / paint
28
+ linearGradient: 1, radialGradient: 1, stop: 1, pattern: 1,
29
+ // Clipping / masking
30
+ clipPath: 1, mask: 1,
31
+ // Marker
32
+ marker: 1,
33
+ // Filter primitives
34
+ filter: 1, feBlend: 1, feColorMatrix: 1, feComponentTransfer: 1,
35
+ feComposite: 1, feConvolveMatrix: 1, feDiffuseLighting: 1,
36
+ feDisplacementMap: 1, feDropShadow: 1, feFlood: 1, feGaussianBlur: 1,
37
+ feImage: 1, feMerge: 1, feMergeNode: 1, feMorphology: 1, feOffset: 1,
38
+ fePointLight: 1, feSpecularLighting: 1, feSpotLight: 1, feTile: 1,
39
+ feTurbulence: 1, feFuncR: 1, feFuncG: 1, feFuncB: 1, feFuncA: 1,
40
+ // Descriptive (excluding 'title' — collides with HTML <title>)
41
+ desc: 1, metadata: 1,
42
+ // Other (excluding 'a', 'image', 'style', 'script' — collide with HTML)
43
+ foreignObject: 1, switch: 1,
44
+ // Animation
45
+ animate: 1, animateMotion: 1, animateTransform: 1, set: 1, mpath: 1,
46
+ }
22
47
 
23
48
  export const svg = (v) => v.sel in svgPropsMap