fabric 7.3.1 → 7.4.0

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.
Files changed (314) hide show
  1. package/CHANGELOG.md +40 -27
  2. package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/defineProperty.mjs +1 -1
  3. package/{dist-extensions/_virtual/_@oxc-project_runtime@0.122.0 → dist/_virtual/_@oxc-project_runtime@0.126.0}/helpers/toPrimitive.mjs +1 -1
  4. package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/toPropertyKey.mjs +1 -1
  5. package/{dist-extensions/_virtual/_@oxc-project_runtime@0.122.0 → dist/_virtual/_@oxc-project_runtime@0.126.0}/helpers/typeof.mjs +1 -1
  6. package/dist/index.js +88 -66
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.min.js +35 -35
  9. package/dist/index.min.js.map +1 -1
  10. package/dist/index.min.mjs +37 -37
  11. package/dist/index.min.mjs.map +1 -1
  12. package/dist/index.mjs +88 -66
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/index.node.cjs +83 -62
  15. package/dist/index.node.cjs.map +1 -1
  16. package/dist/index.node.mjs +83 -62
  17. package/dist/index.node.mjs.map +1 -1
  18. package/dist/package.min.mjs +1 -1
  19. package/dist/package.mjs +1 -1
  20. package/dist/src/Collection.min.mjs +1 -1
  21. package/dist/src/Collection.mjs +1 -1
  22. package/dist/src/LayoutManager/LayoutManager.min.mjs +1 -1
  23. package/dist/src/LayoutManager/LayoutManager.mjs +1 -1
  24. package/dist/src/LayoutManager/LayoutStrategies/ClipPathLayout.min.mjs +1 -1
  25. package/dist/src/LayoutManager/LayoutStrategies/ClipPathLayout.mjs +1 -1
  26. package/dist/src/LayoutManager/LayoutStrategies/FitContentLayout.min.mjs +1 -1
  27. package/dist/src/LayoutManager/LayoutStrategies/FitContentLayout.mjs +1 -1
  28. package/dist/src/LayoutManager/LayoutStrategies/FixedLayout.min.mjs +1 -1
  29. package/dist/src/LayoutManager/LayoutStrategies/FixedLayout.mjs +1 -1
  30. package/dist/src/LayoutManager/LayoutStrategies/LayoutStrategy.min.mjs +1 -1
  31. package/dist/src/LayoutManager/LayoutStrategies/LayoutStrategy.mjs +1 -1
  32. package/dist/src/Observable.min.mjs +1 -1
  33. package/dist/src/Observable.mjs +1 -1
  34. package/dist/src/Pattern/Pattern.min.mjs +1 -1
  35. package/dist/src/Pattern/Pattern.mjs +1 -1
  36. package/dist/src/Shadow.min.mjs +1 -1
  37. package/dist/src/Shadow.mjs +1 -1
  38. package/dist/src/brushes/BaseBrush.min.mjs +1 -1
  39. package/dist/src/brushes/BaseBrush.mjs +1 -1
  40. package/dist/src/brushes/CircleBrush.min.mjs +1 -1
  41. package/dist/src/brushes/CircleBrush.mjs +1 -1
  42. package/dist/src/brushes/PencilBrush.min.mjs +1 -1
  43. package/dist/src/brushes/PencilBrush.mjs +1 -1
  44. package/dist/src/brushes/SprayBrush.min.mjs +1 -1
  45. package/dist/src/brushes/SprayBrush.mjs +1 -1
  46. package/dist/src/cache.min.mjs +1 -1
  47. package/dist/src/cache.mjs +1 -1
  48. package/dist/src/canvas/Canvas.min.mjs +1 -1
  49. package/dist/src/canvas/Canvas.mjs +1 -1
  50. package/dist/src/canvas/DOMManagers/CanvasDOMManager.min.mjs +1 -1
  51. package/dist/src/canvas/DOMManagers/CanvasDOMManager.mjs +1 -1
  52. package/dist/src/canvas/DOMManagers/StaticCanvasDOMManager.min.mjs +1 -1
  53. package/dist/src/canvas/DOMManagers/StaticCanvasDOMManager.mjs +1 -1
  54. package/dist/src/canvas/SelectableCanvas.min.mjs +1 -1
  55. package/dist/src/canvas/SelectableCanvas.mjs +1 -1
  56. package/dist/src/canvas/StaticCanvas.d.ts +1 -1
  57. package/dist/src/canvas/StaticCanvas.d.ts.map +1 -1
  58. package/dist/src/canvas/StaticCanvas.min.mjs +5 -5
  59. package/dist/src/canvas/StaticCanvas.min.mjs.map +1 -1
  60. package/dist/src/canvas/StaticCanvas.mjs +4 -4
  61. package/dist/src/canvas/StaticCanvas.mjs.map +1 -1
  62. package/dist/src/canvas/TextEditingManager.min.mjs +1 -1
  63. package/dist/src/canvas/TextEditingManager.mjs +1 -1
  64. package/dist/src/color/Color.min.mjs +1 -1
  65. package/dist/src/color/Color.mjs +1 -1
  66. package/dist/src/config.min.mjs +1 -1
  67. package/dist/src/config.mjs +1 -1
  68. package/dist/src/controls/Control.min.mjs +1 -1
  69. package/dist/src/controls/Control.mjs +1 -1
  70. package/dist/src/filters/BaseFilter.min.mjs +1 -1
  71. package/dist/src/filters/BaseFilter.mjs +1 -1
  72. package/dist/src/filters/BlendColor.min.mjs +1 -1
  73. package/dist/src/filters/BlendColor.mjs +1 -1
  74. package/dist/src/filters/BlendImage.min.mjs +1 -1
  75. package/dist/src/filters/BlendImage.mjs +1 -1
  76. package/dist/src/filters/Blur.min.mjs +1 -1
  77. package/dist/src/filters/Blur.mjs +1 -1
  78. package/dist/src/filters/Brightness.min.mjs +1 -1
  79. package/dist/src/filters/Brightness.mjs +1 -1
  80. package/dist/src/filters/Canvas2dFilterBackend.min.mjs +1 -1
  81. package/dist/src/filters/Canvas2dFilterBackend.mjs +1 -1
  82. package/dist/src/filters/ColorMatrix.min.mjs +1 -1
  83. package/dist/src/filters/ColorMatrix.mjs +1 -1
  84. package/dist/src/filters/ColorMatrixFilters.min.mjs +1 -1
  85. package/dist/src/filters/ColorMatrixFilters.mjs +1 -1
  86. package/dist/src/filters/Composed.min.mjs +1 -1
  87. package/dist/src/filters/Composed.mjs +1 -1
  88. package/dist/src/filters/Contrast.min.mjs +1 -1
  89. package/dist/src/filters/Contrast.mjs +1 -1
  90. package/dist/src/filters/Convolute.min.mjs +1 -1
  91. package/dist/src/filters/Convolute.min.mjs.map +1 -1
  92. package/dist/src/filters/Convolute.mjs +1 -1
  93. package/dist/src/filters/Gamma.min.mjs +1 -1
  94. package/dist/src/filters/Gamma.mjs +1 -1
  95. package/dist/src/filters/Grayscale.min.mjs +1 -1
  96. package/dist/src/filters/Grayscale.mjs +1 -1
  97. package/dist/src/filters/HueRotation.min.mjs +1 -1
  98. package/dist/src/filters/HueRotation.mjs +1 -1
  99. package/dist/src/filters/Invert.min.mjs +1 -1
  100. package/dist/src/filters/Invert.mjs +1 -1
  101. package/dist/src/filters/Noise.min.mjs +1 -1
  102. package/dist/src/filters/Noise.mjs +1 -1
  103. package/dist/src/filters/Pixelate.min.mjs +1 -1
  104. package/dist/src/filters/Pixelate.mjs +1 -1
  105. package/dist/src/filters/RemoveColor.min.mjs +1 -1
  106. package/dist/src/filters/RemoveColor.mjs +1 -1
  107. package/dist/src/filters/Resize.min.mjs +2 -2
  108. package/dist/src/filters/Resize.min.mjs.map +1 -1
  109. package/dist/src/filters/Resize.mjs +2 -2
  110. package/dist/src/filters/Resize.mjs.map +1 -1
  111. package/dist/src/filters/Saturation.min.mjs +1 -1
  112. package/dist/src/filters/Saturation.mjs +1 -1
  113. package/dist/src/filters/Vibrance.min.mjs +1 -1
  114. package/dist/src/filters/Vibrance.mjs +1 -1
  115. package/dist/src/filters/WebGLFilterBackend.min.mjs +1 -1
  116. package/dist/src/filters/WebGLFilterBackend.mjs +1 -1
  117. package/dist/src/gradient/Gradient.d.ts.map +1 -1
  118. package/dist/src/gradient/Gradient.min.mjs +4 -4
  119. package/dist/src/gradient/Gradient.min.mjs.map +1 -1
  120. package/dist/src/gradient/Gradient.mjs +6 -2
  121. package/dist/src/gradient/Gradient.mjs.map +1 -1
  122. package/dist/src/gradient/typedefs.d.ts +7 -7
  123. package/dist/src/parser/applyViewboxTransform.d.ts.map +1 -1
  124. package/dist/src/parser/applyViewboxTransform.min.mjs +1 -1
  125. package/dist/src/parser/applyViewboxTransform.min.mjs.map +1 -1
  126. package/dist/src/parser/applyViewboxTransform.mjs +2 -4
  127. package/dist/src/parser/applyViewboxTransform.mjs.map +1 -1
  128. package/dist/src/shapes/ActiveSelection.min.mjs +1 -1
  129. package/dist/src/shapes/ActiveSelection.mjs +1 -1
  130. package/dist/src/shapes/Circle.min.mjs +2 -2
  131. package/dist/src/shapes/Circle.min.mjs.map +1 -1
  132. package/dist/src/shapes/Circle.mjs +1 -1
  133. package/dist/src/shapes/Ellipse.min.mjs +1 -1
  134. package/dist/src/shapes/Ellipse.mjs +1 -1
  135. package/dist/src/shapes/Group.min.mjs +1 -1
  136. package/dist/src/shapes/Group.mjs +1 -1
  137. package/dist/src/shapes/IText/DraggableTextDelegate.min.mjs +1 -1
  138. package/dist/src/shapes/IText/DraggableTextDelegate.mjs +1 -1
  139. package/dist/src/shapes/IText/IText.d.ts.map +1 -1
  140. package/dist/src/shapes/IText/IText.min.mjs +1 -1
  141. package/dist/src/shapes/IText/IText.min.mjs.map +1 -1
  142. package/dist/src/shapes/IText/IText.mjs +3 -3
  143. package/dist/src/shapes/IText/IText.mjs.map +1 -1
  144. package/dist/src/shapes/IText/ITextBehavior.min.mjs +1 -1
  145. package/dist/src/shapes/IText/ITextBehavior.mjs +1 -1
  146. package/dist/src/shapes/IText/ITextClickBehavior.min.mjs +1 -1
  147. package/dist/src/shapes/IText/ITextClickBehavior.mjs +1 -1
  148. package/dist/src/shapes/Image.min.mjs +1 -1
  149. package/dist/src/shapes/Image.mjs +1 -1
  150. package/dist/src/shapes/Line.min.mjs +1 -1
  151. package/dist/src/shapes/Line.mjs +1 -1
  152. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
  153. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs +2 -2
  154. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.min.mjs.map +1 -1
  155. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs +11 -26
  156. package/dist/src/shapes/Object/FabricObjectSVGExportMixin.mjs.map +1 -1
  157. package/dist/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
  158. package/dist/src/shapes/Object/InteractiveObject.min.mjs +1 -1
  159. package/dist/src/shapes/Object/InteractiveObject.min.mjs.map +1 -1
  160. package/dist/src/shapes/Object/InteractiveObject.mjs +7 -6
  161. package/dist/src/shapes/Object/InteractiveObject.mjs.map +1 -1
  162. package/dist/src/shapes/Object/Object.min.mjs +1 -1
  163. package/dist/src/shapes/Object/Object.mjs +1 -1
  164. package/dist/src/shapes/Object/ObjectGeometry.d.ts.map +1 -1
  165. package/dist/src/shapes/Object/ObjectGeometry.min.mjs +1 -1
  166. package/dist/src/shapes/Object/ObjectGeometry.min.mjs.map +1 -1
  167. package/dist/src/shapes/Object/ObjectGeometry.mjs +6 -2
  168. package/dist/src/shapes/Object/ObjectGeometry.mjs.map +1 -1
  169. package/dist/src/shapes/Object/types/FabricObjectProps.d.ts +1 -1
  170. package/dist/src/shapes/Path.min.mjs +1 -1
  171. package/dist/src/shapes/Path.mjs +1 -1
  172. package/dist/src/shapes/Polygon.min.mjs +1 -1
  173. package/dist/src/shapes/Polygon.mjs +1 -1
  174. package/dist/src/shapes/Polyline.min.mjs +1 -1
  175. package/dist/src/shapes/Polyline.mjs +1 -1
  176. package/dist/src/shapes/Rect.min.mjs +1 -1
  177. package/dist/src/shapes/Rect.mjs +1 -1
  178. package/dist/src/shapes/Text/StyledText.min.mjs +1 -1
  179. package/dist/src/shapes/Text/StyledText.mjs +1 -1
  180. package/dist/src/shapes/Text/Text.d.ts +4 -4
  181. package/dist/src/shapes/Text/Text.min.mjs +1 -1
  182. package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
  183. package/dist/src/shapes/Text/Text.mjs +3 -3
  184. package/dist/src/shapes/Text/Text.mjs.map +1 -1
  185. package/dist/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
  186. package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs +2 -2
  187. package/dist/src/shapes/Text/TextSVGExportMixin.min.mjs.map +1 -1
  188. package/dist/src/shapes/Text/TextSVGExportMixin.mjs +14 -7
  189. package/dist/src/shapes/Text/TextSVGExportMixin.mjs.map +1 -1
  190. package/dist/src/shapes/Textbox.d.ts.map +1 -1
  191. package/dist/src/shapes/Textbox.min.mjs +2 -2
  192. package/dist/src/shapes/Textbox.min.mjs.map +1 -1
  193. package/dist/src/shapes/Textbox.mjs +2 -3
  194. package/dist/src/shapes/Textbox.mjs.map +1 -1
  195. package/dist/src/shapes/Triangle.min.mjs +1 -1
  196. package/dist/src/shapes/Triangle.mjs +1 -1
  197. package/dist/src/util/animation/AnimationBase.min.mjs +1 -1
  198. package/dist/src/util/animation/AnimationBase.mjs +1 -1
  199. package/dist/src/util/animation/easing.min.mjs +1 -1
  200. package/dist/src/util/animation/easing.min.mjs.map +1 -1
  201. package/dist/src/util/animation/easing.mjs +1 -1
  202. package/dist/src/util/animation/easing.mjs.map +1 -1
  203. package/dist/src/util/internals/applyCanvasTransform.d.ts +1 -1
  204. package/dist/src/util/internals/applyCanvasTransform.min.mjs.map +1 -1
  205. package/dist/src/util/internals/applyCanvasTransform.mjs +1 -1
  206. package/dist/src/util/internals/applyCanvasTransform.mjs.map +1 -1
  207. package/dist/src/util/internals/svgExportCheck.d.ts +4 -0
  208. package/dist/src/util/internals/svgExportCheck.d.ts.map +1 -0
  209. package/dist/src/util/internals/svgExportCheck.min.mjs +2 -0
  210. package/dist/src/util/internals/svgExportCheck.min.mjs.map +1 -0
  211. package/dist/src/util/internals/svgExportCheck.mjs +12 -0
  212. package/dist/src/util/internals/svgExportCheck.mjs.map +1 -0
  213. package/dist/src/util/misc/matrix.d.ts +14 -0
  214. package/dist/src/util/misc/matrix.d.ts.map +1 -1
  215. package/dist/src/util/misc/matrix.min.mjs +1 -1
  216. package/dist/src/util/misc/matrix.min.mjs.map +1 -1
  217. package/dist/src/util/misc/matrix.mjs +15 -1
  218. package/dist/src/util/misc/matrix.mjs.map +1 -1
  219. package/dist/src/util/misc/mergeClipPaths.d.ts +1 -1
  220. package/dist/src/util/misc/mergeClipPaths.min.mjs.map +1 -1
  221. package/dist/src/util/misc/mergeClipPaths.mjs +1 -1
  222. package/dist/src/util/misc/mergeClipPaths.mjs.map +1 -1
  223. package/dist/src/util/misc/objectEnlive.min.mjs.map +1 -1
  224. package/dist/src/util/misc/objectEnlive.mjs +1 -1
  225. package/dist/src/util/misc/objectEnlive.mjs.map +1 -1
  226. package/dist/src/util/misc/projectStroke/StrokeLineJoinProjections.min.mjs +1 -1
  227. package/dist/src/util/misc/projectStroke/StrokeLineJoinProjections.min.mjs.map +1 -1
  228. package/dist/src/util/misc/projectStroke/StrokeLineJoinProjections.mjs +1 -1
  229. package/dist/src/util/misc/svgParsing.d.ts +2 -2
  230. package/dist/src/util/misc/svgParsing.d.ts.map +1 -1
  231. package/dist/src/util/misc/svgParsing.min.mjs +1 -1
  232. package/dist/src/util/misc/svgParsing.min.mjs.map +1 -1
  233. package/dist/src/util/misc/svgParsing.mjs +8 -3
  234. package/dist/src/util/misc/svgParsing.mjs.map +1 -1
  235. package/dist/src/util/path/index.d.ts.map +1 -1
  236. package/dist/src/util/path/index.min.mjs +1 -1
  237. package/dist/src/util/path/index.min.mjs.map +1 -1
  238. package/dist/src/util/path/index.mjs +2 -1
  239. package/dist/src/util/path/index.mjs.map +1 -1
  240. package/dist/src/util/path/regex.min.mjs.map +1 -1
  241. package/dist/src/util/path/regex.mjs +1 -1
  242. package/dist/src/util/path/regex.mjs.map +1 -1
  243. package/dist-extensions/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/defineProperty.mjs +1 -1
  244. package/{dist/_virtual/_@oxc-project_runtime@0.122.0 → dist-extensions/_virtual/_@oxc-project_runtime@0.126.0}/helpers/toPrimitive.mjs +1 -1
  245. package/dist-extensions/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/toPropertyKey.mjs +1 -1
  246. package/{dist/_virtual/_@oxc-project_runtime@0.122.0 → dist-extensions/_virtual/_@oxc-project_runtime@0.126.0}/helpers/typeof.mjs +1 -1
  247. package/dist-extensions/aligning_guidelines/index.mjs +1 -1
  248. package/dist-extensions/cropping_controls/croppingHandlers.mjs +1 -7
  249. package/dist-extensions/cropping_controls/croppingHandlers.mjs.map +1 -1
  250. package/dist-extensions/extensions/cropping_controls/croppingHandlers.d.ts.map +1 -1
  251. package/dist-extensions/fabric-extensions.min.js +1 -1
  252. package/dist-extensions/fabric-extensions.min.js.map +1 -1
  253. package/dist-extensions/src/canvas/StaticCanvas.d.ts +1 -1
  254. package/dist-extensions/src/canvas/StaticCanvas.d.ts.map +1 -1
  255. package/dist-extensions/src/gradient/Gradient.d.ts.map +1 -1
  256. package/dist-extensions/src/gradient/typedefs.d.ts +7 -7
  257. package/dist-extensions/src/parser/applyViewboxTransform.d.ts.map +1 -1
  258. package/dist-extensions/src/shapes/IText/IText.d.ts.map +1 -1
  259. package/dist-extensions/src/shapes/Object/FabricObjectSVGExportMixin.d.ts.map +1 -1
  260. package/dist-extensions/src/shapes/Object/InteractiveObject.d.ts.map +1 -1
  261. package/dist-extensions/src/shapes/Object/ObjectGeometry.d.ts.map +1 -1
  262. package/dist-extensions/src/shapes/Object/types/FabricObjectProps.d.ts +1 -1
  263. package/dist-extensions/src/shapes/Text/Text.d.ts +4 -4
  264. package/dist-extensions/src/shapes/Text/TextSVGExportMixin.d.ts.map +1 -1
  265. package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
  266. package/dist-extensions/src/util/internals/applyCanvasTransform.d.ts +1 -1
  267. package/dist-extensions/src/util/internals/svgExportCheck.d.ts +4 -0
  268. package/dist-extensions/src/util/internals/svgExportCheck.d.ts.map +1 -0
  269. package/dist-extensions/src/util/misc/matrix.d.ts +14 -0
  270. package/dist-extensions/src/util/misc/matrix.d.ts.map +1 -1
  271. package/dist-extensions/src/util/misc/mergeClipPaths.d.ts +1 -1
  272. package/dist-extensions/src/util/misc/svgParsing.d.ts +2 -2
  273. package/dist-extensions/src/util/misc/svgParsing.d.ts.map +1 -1
  274. package/dist-extensions/src/util/path/index.d.ts.map +1 -1
  275. package/extensions/cropping_controls/croppingHandlers.ts +13 -19
  276. package/package.json +10 -10
  277. package/src/LayoutManager/README.md +3 -3
  278. package/src/canvas/StaticCanvas.spec.ts +19 -0
  279. package/src/canvas/StaticCanvas.ts +7 -3
  280. package/src/filters/Resize.ts +1 -1
  281. package/src/gradient/Gradient.spec.ts +60 -1
  282. package/src/gradient/Gradient.ts +9 -2
  283. package/src/gradient/typedefs.ts +7 -7
  284. package/src/parser/applyViewboxTransform.ts +2 -4
  285. package/src/shapes/IText/IText.ts +1 -2
  286. package/src/shapes/IText/ITextBehavior.test.ts +6 -6
  287. package/src/shapes/Object/FabricObject.spec.ts +3 -2
  288. package/src/shapes/Object/FabricObjectSVGExportMixin.ts +47 -37
  289. package/src/shapes/Object/InteractiveObject.ts +13 -3
  290. package/src/shapes/Object/Object-interactivity.spec.ts +126 -7
  291. package/src/shapes/Object/ObjectGeometry.spec.ts +10 -1
  292. package/src/shapes/Object/ObjectGeometry.ts +10 -3
  293. package/src/shapes/Object/objectSvgExport.spec.ts +27 -0
  294. package/src/shapes/Object/types/FabricObjectProps.ts +1 -1
  295. package/src/shapes/Text/Text.spec.ts +25 -0
  296. package/src/shapes/Text/Text.ts +5 -5
  297. package/src/shapes/Text/TextSVGExportMixin.ts +25 -11
  298. package/src/shapes/Textbox.ts +1 -2
  299. package/src/util/animation/animations.spec.ts +1 -1
  300. package/src/util/animation/easing.ts +1 -1
  301. package/src/util/internals/applyCanvasTransform.ts +1 -1
  302. package/src/util/internals/svgExportCheck.ts +20 -0
  303. package/src/util/misc/matrix.spec.ts +52 -0
  304. package/src/util/misc/matrix.ts +16 -0
  305. package/src/util/misc/mergeClipPaths.ts +1 -1
  306. package/src/util/misc/objectEnlive.ts +1 -1
  307. package/src/util/misc/svgParsing.ts +22 -10
  308. package/src/util/path/index.ts +3 -2
  309. package/src/util/path/regex.ts +1 -1
  310. package/src/util/typeAssertions.spec.ts +1 -1
  311. /package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/defineProperty.min.mjs +0 -0
  312. /package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/toPrimitive.min.mjs +0 -0
  313. /package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/toPropertyKey.min.mjs +0 -0
  314. /package/dist/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.126.0}/helpers/typeof.min.mjs +0 -0
@@ -1,6 +1,6 @@
1
1
  import { FabricObject } from './FabricObject';
2
2
 
3
- import { describe, expect, it, vi } from 'vitest';
3
+ import { describe, expect, it } from 'vitest';
4
4
 
5
5
  describe('FabricObject', () => {
6
6
  it('setCoords should calculate control coords only if canvas ref is set', () => {
@@ -10,7 +10,8 @@ describe('FabricObject', () => {
10
10
  object.setCoords();
11
11
  expect(object.aCoords).toBeDefined();
12
12
  expect(object.oCoords).toBeUndefined();
13
- object.canvas = vi.fn();
13
+ // @ts-expect-error -- mock canvas
14
+ object.canvas = { getZoom: () => 1 };
14
15
  object.setCoords();
15
16
  expect(object.aCoords).toBeDefined();
16
17
  expect(object.oCoords).toBeDefined();
@@ -1,4 +1,8 @@
1
1
  import type { TSVGReviver } from '../../typedefs';
2
+ import {
3
+ getSafeSvgStyleNumber,
4
+ getSafeSvgStyleToken,
5
+ } from '../../util/internals/svgExportCheck';
2
6
  import { uid } from '../../util/internals/uid';
3
7
  import { colorPropToSVG } from '../../util/misc/svgParsing';
4
8
  import { FILL, NONE, STROKE } from '../../constants';
@@ -24,16 +28,38 @@ export class FabricObjectSVGExportMixin {
24
28
  this: FabricObjectSVGExportMixin & FabricObject,
25
29
  skipShadow?: boolean,
26
30
  ) {
27
- const fillRule = this.fillRule ? this.fillRule : 'nonzero',
28
- strokeWidth = this.strokeWidth ? this.strokeWidth : '0',
29
- strokeDashArray = this.strokeDashArray
30
- ? this.strokeDashArray.join(' ')
31
- : NONE,
32
- strokeDashOffset = this.strokeDashOffset ? this.strokeDashOffset : '0',
33
- strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',
34
- strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',
35
- strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',
36
- opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',
31
+ const fillRule =
32
+ this.fillRule == null ? 'nonzero' : getSafeSvgStyleToken(this.fillRule),
33
+ strokeWidth =
34
+ this.strokeWidth == null
35
+ ? '0'
36
+ : getSafeSvgStyleNumber(this.strokeWidth),
37
+ strokeDashArray =
38
+ this.strokeDashArray == null
39
+ ? NONE
40
+ : this.strokeDashArray.every((value) =>
41
+ Number.isFinite(Number(value)),
42
+ )
43
+ ? this.strokeDashArray.join(' ')
44
+ : '',
45
+ strokeDashOffset =
46
+ this.strokeDashOffset == null
47
+ ? '0'
48
+ : getSafeSvgStyleNumber(this.strokeDashOffset),
49
+ strokeLineCap =
50
+ this.strokeLineCap == null
51
+ ? 'butt'
52
+ : getSafeSvgStyleToken(this.strokeLineCap),
53
+ strokeLineJoin =
54
+ this.strokeLineJoin == null
55
+ ? 'miter'
56
+ : getSafeSvgStyleToken(this.strokeLineJoin),
57
+ strokeMiterLimit =
58
+ this.strokeMiterLimit == null
59
+ ? '4'
60
+ : getSafeSvgStyleNumber(this.strokeMiterLimit),
61
+ opacity =
62
+ this.opacity == null ? '1' : getSafeSvgStyleNumber(this.opacity),
37
63
  visibility = this.visible ? '' : ' visibility: hidden;',
38
64
  filter = skipShadow ? '' : this.getSvgFilter(),
39
65
  fill = colorPropToSVG(FILL, this.fill),
@@ -41,31 +67,15 @@ export class FabricObjectSVGExportMixin {
41
67
 
42
68
  return [
43
69
  stroke,
44
- 'stroke-width: ',
45
- strokeWidth,
46
- '; ',
47
- 'stroke-dasharray: ',
48
- strokeDashArray,
49
- '; ',
50
- 'stroke-linecap: ',
51
- strokeLineCap,
52
- '; ',
53
- 'stroke-dashoffset: ',
54
- strokeDashOffset,
55
- '; ',
56
- 'stroke-linejoin: ',
57
- strokeLineJoin,
58
- '; ',
59
- 'stroke-miterlimit: ',
60
- strokeMiterLimit,
61
- '; ',
70
+ strokeWidth ? `stroke-width: ${strokeWidth}; ` : '',
71
+ strokeDashArray ? `stroke-dasharray: ${strokeDashArray}; ` : '',
72
+ strokeLineCap ? `stroke-linecap: ${strokeLineCap}; ` : '',
73
+ strokeDashOffset ? `stroke-dashoffset: ${strokeDashOffset}; ` : '',
74
+ strokeLineJoin ? `stroke-linejoin: ${strokeLineJoin}; ` : '',
75
+ strokeMiterLimit ? `stroke-miterlimit: ${strokeMiterLimit}; ` : '',
62
76
  fill,
63
- 'fill-rule: ',
64
- fillRule,
65
- '; ',
66
- 'opacity: ',
67
- opacity,
68
- ';',
77
+ fillRule ? `fill-rule: ${fillRule}; ` : '',
78
+ opacity ? `opacity: ${opacity};` : '',
69
79
  filter,
70
80
  visibility,
71
81
  ]
@@ -93,10 +103,10 @@ export class FabricObjectSVGExportMixin {
93
103
  return [
94
104
  this.id ? `id="${escapeXml(String(this.id))}" ` : '',
95
105
  this.clipPath
96
- ? `clip-path="url(#${
106
+ ? `clip-path="url(#${escapeXml(
97
107
  (this.clipPath as FabricObjectSVGExportMixin & FabricObject)
98
- .clipPathId
99
- })" `
108
+ .clipPathId!,
109
+ )})" `
100
110
  : '',
101
111
  ].join('');
102
112
  }
@@ -5,6 +5,9 @@ import { degreesToRadians } from '../../util/misc/radiansDegreesConversion';
5
5
  import type { TQrDecomposeOut } from '../../util/misc/matrix';
6
6
  import {
7
7
  calcDimensionsMatrix,
8
+ calcPlaneRotation,
9
+ calcPlaneZoom,
10
+ calcPlaneScaleY,
8
11
  createRotateMatrix,
9
12
  createTranslateMatrix,
10
13
  multiplyTransformMatrices,
@@ -254,6 +257,8 @@ export class InteractiveFabricObject<
254
257
  */
255
258
  calcOCoords(): Record<string, TOCoord> {
256
259
  const vpt = this.getViewportTransform(),
260
+ vptScaleX = calcPlaneZoom(vpt),
261
+ vptScaleY = calcPlaneScaleY(vpt),
257
262
  center = this.getCenterPoint(),
258
263
  tMatrix = createTranslateMatrix(center.x, center.y),
259
264
  rMatrix = createRotateMatrix({
@@ -262,10 +267,10 @@ export class InteractiveFabricObject<
262
267
  positionMatrix = multiplyTransformMatrices(tMatrix, rMatrix),
263
268
  startMatrix = multiplyTransformMatrices(vpt, positionMatrix),
264
269
  finalMatrix = multiplyTransformMatrices(startMatrix, [
265
- 1 / vpt[0],
270
+ 1 / vptScaleX,
266
271
  0,
267
272
  0,
268
- 1 / vpt[3],
273
+ 1 / vptScaleY,
269
274
  0,
270
275
  0,
271
276
  ]),
@@ -461,7 +466,12 @@ export class InteractiveFabricObject<
461
466
  if (this.flipX) {
462
467
  options.angle -= 180;
463
468
  }
464
- ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));
469
+ const vptAngle = calcPlaneRotation(vpt);
470
+ ctx.rotate(
471
+ this.group
472
+ ? degreesToRadians(options.angle)
473
+ : degreesToRadians(this.angle) + vptAngle,
474
+ );
465
475
  shouldDrawBorders && this.drawBorders(ctx, options, styleOverride);
466
476
  shouldDrawControls && this.drawControls(ctx, styleOverride);
467
477
  ctx.restore();
@@ -1,4 +1,4 @@
1
- import { describe, it, expect } from 'vitest';
1
+ import { describe, it, expect, vi } from 'vitest';
2
2
  import { FabricObject } from './FabricObject';
3
3
  import { Point } from '../../Point';
4
4
 
@@ -211,7 +211,7 @@ describe('ObjectInteractivity', () => {
211
211
  height: 10,
212
212
  strokeWidth: 0,
213
213
  // @ts-expect-error -- mock canvas
214
- canvas: {},
214
+ canvas: { getZoom: () => 1 },
215
215
  });
216
216
  cObj.setCoords();
217
217
 
@@ -337,6 +337,92 @@ describe('ObjectInteractivity', () => {
337
337
  );
338
338
  });
339
339
 
340
+ it('corner coords with a rotated viewport transform', () => {
341
+ const cObj = new FabricObject({
342
+ left: 0,
343
+ top: 0,
344
+ width: 100,
345
+ height: 100,
346
+ strokeWidth: 0,
347
+ });
348
+ // @ts-expect-error -- mock canvas
349
+ cObj.canvas = {
350
+ viewportTransform: [0, 1, -1, 0, 0, 0],
351
+ getZoom: () => 1,
352
+ };
353
+ cObj.setCoords();
354
+
355
+ expect(cObj.oCoords.tl.x, 'tl.x is rotated 90 degrees').toBeCloseTo(50);
356
+ expect(cObj.oCoords.tl.y, 'tl.y is rotated 90 degrees').toBeCloseTo(-50);
357
+ expect(cObj.oCoords.tr.x, 'tr.x is rotated 90 degrees').toBeCloseTo(50);
358
+ expect(cObj.oCoords.tr.y, 'tr.y is rotated 90 degrees').toBeCloseTo(50);
359
+ expect(cObj.oCoords.br.x, 'br.x is rotated 90 degrees').toBeCloseTo(-50);
360
+ expect(cObj.oCoords.br.y, 'br.y is rotated 90 degrees').toBeCloseTo(50);
361
+ expect(cObj.oCoords.bl.x, 'bl.x is rotated 90 degrees').toBeCloseTo(-50);
362
+ expect(cObj.oCoords.bl.y, 'bl.y is rotated 90 degrees').toBeCloseTo(-50);
363
+ });
364
+
365
+ it('corner coords with a non-uniform viewport transform', () => {
366
+ // originX/Y default to 'center', so left=0,top=0 puts the canvas-space center
367
+ // at (0,0). With vpt=[2,0,0,3,0,0] (no translation) the screen center is also
368
+ // at (0,0); controls should span ±(width*scaleX/2) × ±(height*scaleY/2).
369
+ const cObj = new FabricObject({
370
+ left: 0,
371
+ top: 0,
372
+ width: 100,
373
+ height: 100,
374
+ strokeWidth: 0,
375
+ });
376
+ // @ts-expect-error -- mock canvas
377
+ cObj.canvas = {
378
+ viewportTransform: [2, 0, 0, 3, 0, 0],
379
+ getZoom: () => 2,
380
+ };
381
+ cObj.setCoords();
382
+
383
+ expect(
384
+ cObj.oCoords.tl.x,
385
+ 'tl.x: half-width scaled by scaleX=2',
386
+ ).toBeCloseTo(-100);
387
+ expect(
388
+ cObj.oCoords.tl.y,
389
+ 'tl.y: half-height scaled by scaleY=3',
390
+ ).toBeCloseTo(-150);
391
+ expect(
392
+ cObj.oCoords.br.x,
393
+ 'br.x: half-width scaled by scaleX=2',
394
+ ).toBeCloseTo(100);
395
+ expect(
396
+ cObj.oCoords.br.y,
397
+ 'br.y: half-height scaled by scaleY=3',
398
+ ).toBeCloseTo(150);
399
+ });
400
+
401
+ it('_renderControls rotates by the combined viewport and object angle', () => {
402
+ const cObj = new FabricObject({ width: 100, height: 100, strokeWidth: 0 });
403
+ const cos = Math.SQRT1_2,
404
+ sin = Math.SQRT1_2;
405
+ // @ts-expect-error -- mock canvas
406
+ cObj.canvas = {
407
+ viewportTransform: [cos, sin, -sin, cos, 0, 0],
408
+ getZoom: () => 1,
409
+ };
410
+ const rotate = vi.fn();
411
+ const ctx = {
412
+ save: vi.fn(),
413
+ restore: vi.fn(),
414
+ translate: vi.fn(),
415
+ rotate,
416
+ lineWidth: 0,
417
+ globalAlpha: 0,
418
+ };
419
+ // @ts-expect-error -- mock context
420
+ cObj._renderControls(ctx, { hasBorders: false, hasControls: false });
421
+
422
+ expect(rotate).toHaveBeenCalledTimes(1);
423
+ expect(rotate.mock.calls[0][0]).toBeCloseTo(Math.PI / 4);
424
+ });
425
+
340
426
  // set size for bottom left corner and have different results for bl than normal setCornerCoords test
341
427
  it('corner coords: custom control size', () => {
342
428
  //set custom corner size
@@ -352,7 +438,7 @@ describe('ObjectInteractivity', () => {
352
438
  strokeWidth: 0,
353
439
  controls: sharedControls,
354
440
  // @ts-expect-error -- mock canvas
355
- canvas: {},
441
+ canvas: { getZoom: () => 1 },
356
442
  });
357
443
  cObj.setCoords();
358
444
 
@@ -490,7 +576,7 @@ describe('ObjectInteractivity', () => {
490
576
  height: 30,
491
577
  strokeWidth: 0,
492
578
  // @ts-expect-error -- mock canvas
493
- canvas: {},
579
+ canvas: { getZoom: () => 1 },
494
580
  });
495
581
 
496
582
  expect(typeof cObj.findControl, 'findControl should exist').toBe(
@@ -503,6 +589,7 @@ describe('ObjectInteractivity', () => {
503
589
  getActiveObject() {
504
590
  return cObj;
505
591
  },
592
+ getZoom: () => 1,
506
593
  };
507
594
 
508
595
  expect(cObj.findControl(cObj.oCoords.br), 'br control').toEqual({
@@ -561,7 +648,7 @@ describe('ObjectInteractivity', () => {
561
648
  height: 30,
562
649
  strokeWidth: 0,
563
650
  // @ts-expect-error -- mock canvas
564
- canvas: {},
651
+ canvas: { getZoom: () => 1 },
565
652
  });
566
653
 
567
654
  cObj.setCoords();
@@ -570,6 +657,7 @@ describe('ObjectInteractivity', () => {
570
657
  getActiveObject() {
571
658
  return cObj;
572
659
  },
660
+ getZoom: () => 1,
573
661
  };
574
662
 
575
663
  const pointNearBr = new Point({
@@ -609,7 +697,7 @@ describe('ObjectInteractivity', () => {
609
697
  height: 30,
610
698
  strokeWidth: 0,
611
699
  // @ts-expect-error -- mock canvas
612
- canvas: {},
700
+ canvas: { getZoom: () => 1 },
613
701
  });
614
702
 
615
703
  expect(typeof cObj.findControl, 'findControl should exist').toBe(
@@ -622,6 +710,7 @@ describe('ObjectInteractivity', () => {
622
710
  getActiveObject() {
623
711
  return undefined;
624
712
  },
713
+ getZoom: () => 1,
625
714
  };
626
715
 
627
716
  expect(
@@ -638,7 +727,7 @@ describe('ObjectInteractivity', () => {
638
727
  height: 30,
639
728
  strokeWidth: 0,
640
729
  // @ts-expect-error -- mock canvas
641
- canvas: {},
730
+ canvas: { getZoom: () => 1 },
642
731
  });
643
732
 
644
733
  expect(typeof cObj.findControl, 'findControl should exist').toBe(
@@ -651,6 +740,7 @@ describe('ObjectInteractivity', () => {
651
740
  getActiveObject() {
652
741
  return cObj;
653
742
  },
743
+ getZoom: () => 1,
654
744
  };
655
745
 
656
746
  cObj.isControlVisible = () => false;
@@ -717,6 +807,35 @@ describe('ObjectInteractivity', () => {
717
807
  expect(dim.y.toFixed(0), 'height should change with padding').toBe('78');
718
808
  });
719
809
 
810
+ it('_calculateCurrentDimensions with a rotated viewport transform', () => {
811
+ const cObj = new FabricObject({ width: 200, height: 200, strokeWidth: 0 });
812
+ const cos = Math.SQRT1_2,
813
+ sin = Math.SQRT1_2;
814
+ // @ts-expect-error -- mock canvas
815
+ cObj.canvas = {
816
+ viewportTransform: [cos, sin, -sin, cos, 0, 0],
817
+ getZoom: () => 1,
818
+ };
819
+
820
+ const dim = cObj._calculateCurrentDimensions();
821
+
822
+ expect(dim.x, 'width is independent of viewport rotation').toBeCloseTo(200);
823
+ expect(dim.y, 'height is independent of viewport rotation').toBeCloseTo(
824
+ 200,
825
+ );
826
+ });
827
+
828
+ it('_calculateCurrentDimensions with a non-uniform viewport transform', () => {
829
+ const cObj = new FabricObject({ width: 200, height: 100, strokeWidth: 0 });
830
+ // @ts-expect-error -- mock canvas
831
+ cObj.canvas = { viewportTransform: [2, 0, 0, 3, 0, 0], getZoom: () => 2 };
832
+
833
+ const dim = cObj._calculateCurrentDimensions();
834
+
835
+ expect(dim.x, 'width scales by vpt scaleX').toBeCloseTo(400);
836
+ expect(dim.y, 'height scales by vpt scaleY').toBeCloseTo(300);
837
+ });
838
+
720
839
  it('_getTransformedDimensions', () => {
721
840
  const cObj = new FabricObject({ width: 10, height: 15, strokeWidth: 0 });
722
841
 
@@ -365,7 +365,7 @@ describe('fabric.ObjectGeometry', () => {
365
365
  height: 100,
366
366
  strokeWidth: 0,
367
367
  // @ts-expect-error -- fake canvas
368
- canvas: {},
368
+ canvas: { getZoom: () => 1 },
369
369
  });
370
370
  expect(cObj.setCoords).toBeTypeOf('function');
371
371
  cObj.setCoords();
@@ -435,6 +435,7 @@ describe('fabric.ObjectGeometry', () => {
435
435
  // @ts-expect-error -- partial canvas
436
436
  cObj.canvas = {
437
437
  viewportTransform: [2, 0, 0, 2, 0, 0],
438
+ getZoom: () => 2,
438
439
  };
439
440
  cObj.setCoords();
440
441
 
@@ -720,6 +721,7 @@ describe('fabric.ObjectGeometry', () => {
720
721
  // @ts-expect-error -- partial canvas
721
722
  cObj.canvas = {
722
723
  viewportTransform: [2, 0, 0, 2, 0, 0],
724
+ getZoom: () => 2,
723
725
  };
724
726
  cObj.scaleToWidth(100);
725
727
  expect(cObj.getScaledWidth(), 'is not influenced by zoom - width').toBe(
@@ -741,6 +743,7 @@ describe('fabric.ObjectGeometry', () => {
741
743
  // @ts-expect-error -- partial canvas
742
744
  cObj.canvas = {
743
745
  viewportTransform: [2, 0, 0, 2, 0, 0],
746
+ getZoom: () => 2,
744
747
  };
745
748
  cObj.scaleToHeight(100);
746
749
  expect(cObj.getScaledHeight(), 'is not influenced by zoom - height').toBe(
@@ -790,6 +793,7 @@ describe('fabric.ObjectGeometry', () => {
790
793
  // @ts-expect-error -- partial canvas
791
794
  cObj.canvas = {
792
795
  viewportTransform: [2, 0, 0, 2, 0, 0],
796
+ getZoom: () => 2,
793
797
  };
794
798
  cObj.setCoords();
795
799
  boundingRect = cObj.getBoundingRect();
@@ -955,6 +959,7 @@ describe('fabric.ObjectGeometry', () => {
955
959
  // @ts-expect-error -- partial canvas
956
960
  cObj.canvas = {
957
961
  viewportTransform: [2, 0, 0, 2, 35, 35],
962
+ getZoom: () => 2,
958
963
  };
959
964
  const coords = cObj.getCoords();
960
965
  expect(coords[0]).toEqual(new Point(40, 30));
@@ -976,6 +981,7 @@ describe('fabric.ObjectGeometry', () => {
976
981
  // @ts-expect-error -- partial canvas
977
982
  cObj.canvas = {
978
983
  viewportTransform: [2, 0, 0, 2, 35, 25],
984
+ getZoom: () => 2,
979
985
  };
980
986
  const coords = cObj.getCoords();
981
987
  expect(coords).toMatchSnapshot();
@@ -994,6 +1000,7 @@ describe('fabric.ObjectGeometry', () => {
994
1000
  // @ts-expect-error -- partial canvas
995
1001
  cObj.canvas = {
996
1002
  viewportTransform: [2, 0, 0, 2, 35, 25],
1003
+ getZoom: () => 2,
997
1004
  };
998
1005
  const coords = cObj.getCoords();
999
1006
  expect(coords).toMatchInlineSnapshot(`
@@ -1031,6 +1038,7 @@ describe('fabric.ObjectGeometry', () => {
1031
1038
  // @ts-expect-error -- partial canvas
1032
1039
  cObj.canvas = {
1033
1040
  viewportTransform: [2, 0, 0, 2, 35, 25],
1041
+ getZoom: () => 2,
1034
1042
  };
1035
1043
  const coords = cObj.getCoords();
1036
1044
  expect(coords).toMatchInlineSnapshot(`
@@ -1070,6 +1078,7 @@ describe('fabric.ObjectGeometry', () => {
1070
1078
  // @ts-expect-error -- partial canvas
1071
1079
  cObj.canvas = {
1072
1080
  viewportTransform: [2, 0, 0, 2, 35, 25],
1081
+ getZoom: () => 2,
1073
1082
  };
1074
1083
  const coords = cObj.getCoords();
1075
1084
  expect(coords).toMatchInlineSnapshot(`
@@ -18,6 +18,8 @@ import {
18
18
  multiplyTransformMatrices,
19
19
  transformPoint,
20
20
  calcPlaneRotation,
21
+ calcPlaneZoom,
22
+ calcPlaneScaleY,
21
23
  } from '../../util/misc/matrix';
22
24
  import { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';
23
25
  import type { Canvas } from '../../canvas/Canvas';
@@ -553,9 +555,14 @@ export class ObjectGeometry<EventSpec extends ObjectEvents = ObjectEvents>
553
555
  * @returns {Point} dimensions
554
556
  */
555
557
  _calculateCurrentDimensions(options?: any): Point {
556
- return this._getTransformedDimensions(options)
557
- .transform(this.getViewportTransform(), true)
558
- .scalarAdd(2 * this.padding);
558
+ const vpt = this.canvas?.viewportTransform;
559
+ const dim = this._getTransformedDimensions(options);
560
+ if (vpt) {
561
+ return dim
562
+ .multiply(new Point(calcPlaneZoom(vpt), calcPlaneScaleY(vpt)))
563
+ .scalarAdd(2 * this.padding);
564
+ }
565
+ return dim.scalarAdd(2 * this.padding);
559
566
  }
560
567
 
561
568
  // #region Origin
@@ -110,3 +110,30 @@ describe.each([MALICIOUS, MALICIOUS2])(
110
110
  });
111
111
  },
112
112
  );
113
+
114
+ describe('Object SVG style declaration sanitization', () => {
115
+ it('drops unsafe inline style values from object svg styles', () => {
116
+ const rect = new Rect({
117
+ width: 10,
118
+ height: 10,
119
+ fillRule: 'evenodd; filter:url(javascript:alert(1))' as never,
120
+ strokeLineCap: 'round; opacity:0' as never,
121
+ strokeLineJoin: 'bevel; fill:url(#x)' as never,
122
+ strokeDashArray: ['4', '2; fill:url(#x)'] as never,
123
+ strokeDashOffset: '1; opacity:0' as never,
124
+ strokeMiterLimit: '4; opacity:0' as never,
125
+ opacity: '1; visibility:hidden' as never,
126
+ });
127
+
128
+ const svgStyles = rect.getSvgStyles();
129
+ expect(svgStyles).not.toContain('fill-rule:');
130
+ expect(svgStyles).not.toContain('stroke-linecap:');
131
+ expect(svgStyles).not.toContain('stroke-linejoin:');
132
+ expect(svgStyles).not.toContain('stroke-dasharray:');
133
+ expect(svgStyles).not.toContain('stroke-dashoffset:');
134
+ expect(svgStyles).not.toContain('stroke-miterlimit:');
135
+ expect(svgStyles).not.toContain('opacity:');
136
+ expect(svgStyles).not.toContain('javascript:');
137
+ expect(svgStyles).not.toContain('filter:url');
138
+ });
139
+ });
@@ -8,7 +8,7 @@ export interface FabricObjectProps
8
8
  /**
9
9
  * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled
10
10
  * too much and will be redrawn with correct details at the end of scaling.
11
- * this setting is performance and application dependant.
11
+ * this setting is performance and application dependent.
12
12
  * default to true
13
13
  * since 1.7.0
14
14
  * @type Boolean
@@ -967,6 +967,31 @@ describe('FabricText', () => {
967
967
  expect(styleString, 'style is as expected').toBe(expected);
968
968
  });
969
969
 
970
+ it('getSvgSpanStyles drops unsafe style declarations', () => {
971
+ const iText = new IText('test foo bar-baz', {
972
+ textDecorationColor: 'blue; fill:url(#x)' as never,
973
+ });
974
+ // @ts-expect-error -- TODO: this is added by the mixing, can the types be improved here?
975
+ const styleString = iText.getSvgSpanStyles({
976
+ fill: 'red; stroke:url(javascript:alert(1))',
977
+ strokeWidth: '30; opacity:0' as never,
978
+ fontFamily: 'Verdana; font-size:999px',
979
+ fontSize: '25; opacity:0' as never,
980
+ fontStyle: 'italic; fill:url(#x)' as never,
981
+ fontWeight: 'bold; fill:url(#x)' as never,
982
+ underline: true,
983
+ textDecorationColor: 'green; fill:url(#x)' as never,
984
+ });
985
+ expect(styleString).toContain('fill: rgb(0,0,0); ');
986
+ expect(styleString).not.toContain('stroke-width: 30;');
987
+ expect(styleString).not.toContain('font-family:');
988
+ expect(styleString).not.toContain('font-size: 25px;');
989
+ expect(styleString).not.toContain('font-style:');
990
+ expect(styleString).not.toContain('font-weight:');
991
+ expect(styleString).not.toContain('text-decoration-color:');
992
+ expect(styleString).not.toContain('javascript:');
993
+ });
994
+
970
995
  it('getSvgTextDecoration with overline true produces correct output', () => {
971
996
  const iText = new IText('test foo bar-baz');
972
997
  const styleObject = {
@@ -301,11 +301,11 @@ export class FabricText<
301
301
  declare path?: Path;
302
302
 
303
303
  /**
304
- * The text decoration tickness for underline, overline and strikethrough
305
- * The tickness is expressed in thousandths of fontSize ( em ).
304
+ * The text decoration thickness for underline, overline and strikethrough
305
+ * The thickness is expressed in thousandths of fontSize ( em ).
306
306
  * The original value was 1/15 that translates to 66.6667 thousandths.
307
307
  * The choice of unit of measure is to align with charSpacing.
308
- * You can slim the tickness without issues, while large underline or overline may end up
308
+ * You can slim the thickness without issues, while large underline or overline may end up
309
309
  * outside the bounding box of the text. In order to fix that a bigger refactor of the code
310
310
  * is needed and is out of scope for now. If you need such large overline on the first line
311
311
  * of text or large underline on the last line of text, consider disabling caching as a
@@ -1147,7 +1147,7 @@ export class FabricText<
1147
1147
  * @private
1148
1148
  * @param {String} method fillText or strokeText.
1149
1149
  * @param {CanvasRenderingContext2D} ctx Context to render on
1150
- * @param {Array} line Content of the line, splitted in an array by grapheme
1150
+ * @param {Array} line Content of the line, split in an array by grapheme
1151
1151
  * @param {Number} left
1152
1152
  * @param {Number} top
1153
1153
  * @param {Number} lineIndex
@@ -1595,7 +1595,7 @@ export class FabricText<
1595
1595
  TEXT_DECORATION_THICKNESS,
1596
1596
  );
1597
1597
  let currentDecoration = lastDecoration;
1598
- let currentFill = lastFill;
1598
+ let currentFill: typeof lastFill;
1599
1599
  let currentDecorationColor = lastDecorationColor;
1600
1600
  let currentTickness = lastTickness;
1601
1601
  const top = topOffset + maxHeight * (1 - this._fontSizeFraction);
@@ -16,6 +16,11 @@ import { STROKE, FILL } from '../../constants';
16
16
  import { createRotateMatrix } from '../../util/misc/matrix';
17
17
  import { radiansToDegrees } from '../../util/misc/radiansDegreesConversion';
18
18
  import { Point } from '../../Point';
19
+ import {
20
+ getSafeSvgStyleNumber,
21
+ getSafeSvgStyleToken,
22
+ isSafeSvgStyleValue,
23
+ } from '../../util/internals/svgExportCheck';
19
24
  import { matrixToSVG } from '../../util/misc/svgExport';
20
25
 
21
26
  const multipleSpacesRegex = / +/g;
@@ -307,7 +312,9 @@ export class TextSVGExportMixin extends FabricObjectSVGExportMixin {
307
312
  * @return {String}
308
313
  */
309
314
  getSvgStyles(this: TextSVGExportMixin & FabricText, skipShadow?: boolean) {
310
- const objectLevelTextDecorationColor = this[TEXT_DECORATION_COLOR]
315
+ const objectLevelTextDecorationColor = isSafeSvgStyleValue(
316
+ this[TEXT_DECORATION_COLOR],
317
+ )
311
318
  ? ` text-decoration-color: ${escapeXml(this[TEXT_DECORATION_COLOR])};`
312
319
  : '';
313
320
  return `${super.getSvgStyles(skipShadow)} text-decoration-thickness: ${toFixed((this.textDecorationThickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%;${objectLevelTextDecorationColor} white-space: pre;`;
@@ -347,23 +354,30 @@ export class TextSVGExportMixin extends FabricObjectSVGExportMixin {
347
354
  const thickness =
348
355
  textDecorationThickness || this[TEXT_DECORATION_THICKNESS];
349
356
  const decorationColor = textDecorationColor || this[TEXT_DECORATION_COLOR];
357
+ const safeStrokeWidth = getSafeSvgStyleNumber(strokeWidth);
358
+ const safeFontFamily = getSafeSvgStyleToken(fontFamily);
359
+ const safeFontSize = getSafeSvgStyleNumber(fontSize);
360
+ const safeFontStyle = getSafeSvgStyleToken(fontStyle);
361
+ const safeFontWeight =
362
+ getSafeSvgStyleNumber(fontWeight) || getSafeSvgStyleToken(fontWeight);
363
+ const safeDecorationColor = getSafeSvgStyleToken(decorationColor);
350
364
  return [
351
365
  stroke ? colorPropToSVG(STROKE, stroke) : '',
352
- strokeWidth ? `stroke-width: ${escapeXml(strokeWidth)}; ` : '',
353
- fontFamily
366
+ safeStrokeWidth ? `stroke-width: ${escapeXml(safeStrokeWidth)}; ` : '',
367
+ safeFontFamily
354
368
  ? `font-family: ${
355
- !fontFamily.includes("'") && !fontFamily.includes('"')
356
- ? `'${escapeXml(fontFamily)}'`
357
- : escapeXml(fontFamily)
369
+ !safeFontFamily.includes("'") && !safeFontFamily.includes('"')
370
+ ? `'${escapeXml(safeFontFamily)}'`
371
+ : escapeXml(safeFontFamily)
358
372
  }; `
359
373
  : '',
360
- fontSize ? `font-size: ${escapeXml(fontSize)}px; ` : '',
361
- fontStyle ? `font-style: ${escapeXml(fontStyle)}; ` : '',
362
- fontWeight ? `font-weight: ${escapeXml(fontWeight)}; ` : '',
374
+ safeFontSize ? `font-size: ${escapeXml(safeFontSize)}px; ` : '',
375
+ safeFontStyle ? `font-style: ${escapeXml(safeFontStyle)}; ` : '',
376
+ safeFontWeight ? `font-weight: ${escapeXml(safeFontWeight)}; ` : '',
363
377
  textDecoration
364
378
  ? `text-decoration: ${textDecoration}; text-decoration-thickness: ${toFixed((thickness * this.getObjectScaling().y) / 10, config.NUM_FRACTION_DIGITS)}%;${
365
- decorationColor
366
- ? ` text-decoration-color: ${escapeXml(decorationColor)};`
379
+ safeDecorationColor
380
+ ? ` text-decoration-color: ${escapeXml(safeDecorationColor)};`
367
381
  : ''
368
382
  } `
369
383
  : '',