@react-email/preview-server 1.0.0-canary.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 (265) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +44 -0
  3. package/.next/app-path-routes-manifest.json +6 -0
  4. package/.next/build-manifest.json +33 -0
  5. package/.next/diagnostics/build-diagnostics.json +6 -0
  6. package/.next/diagnostics/framework.json +1 -0
  7. package/.next/export-marker.json +6 -0
  8. package/.next/images-manifest.json +57 -0
  9. package/.next/next-minimal-server.js.nft.json +1 -0
  10. package/.next/next-server.js.nft.json +1 -0
  11. package/.next/package.json +1 -0
  12. package/.next/prerender-manifest.json +41 -0
  13. package/.next/react-loadable-manifest.json +1 -0
  14. package/.next/required-server-files.json +311 -0
  15. package/.next/routes-manifest.json +64 -0
  16. package/.next/server/app/_not-found/page.js +1 -0
  17. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  18. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  19. package/.next/server/app/favicon.ico/route.js +1 -0
  20. package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
  21. package/.next/server/app/favicon.ico.body +0 -0
  22. package/.next/server/app/favicon.ico.meta +1 -0
  23. package/.next/server/app/page.js +1 -0
  24. package/.next/server/app/page.js.nft.json +1 -0
  25. package/.next/server/app/page_client-reference-manifest.js +1 -0
  26. package/.next/server/app/preview/[...slug]/page.js +321 -0
  27. package/.next/server/app/preview/[...slug]/page.js.nft.json +1 -0
  28. package/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +1 -0
  29. package/.next/server/app-paths-manifest.json +6 -0
  30. package/.next/server/chunks/134.js +6 -0
  31. package/.next/server/chunks/235.js +15 -0
  32. package/.next/server/chunks/278.js +1 -0
  33. package/.next/server/chunks/343.js +20 -0
  34. package/.next/server/chunks/428.js +14 -0
  35. package/.next/server/chunks/963.js +1 -0
  36. package/.next/server/chunks/999.js +1 -0
  37. package/.next/server/functions-config-manifest.json +4 -0
  38. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  39. package/.next/server/middleware-build-manifest.js +1 -0
  40. package/.next/server/middleware-manifest.json +6 -0
  41. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  42. package/.next/server/next-font-manifest.js +1 -0
  43. package/.next/server/next-font-manifest.json +1 -0
  44. package/.next/server/pages/500.html +1 -0
  45. package/.next/server/pages/_app.js +1 -0
  46. package/.next/server/pages/_app.js.nft.json +1 -0
  47. package/.next/server/pages/_document.js +1 -0
  48. package/.next/server/pages/_document.js.nft.json +1 -0
  49. package/.next/server/pages/_error.js +1 -0
  50. package/.next/server/pages/_error.js.nft.json +1 -0
  51. package/.next/server/pages-manifest.json +5 -0
  52. package/.next/server/server-reference-manifest.js +1 -0
  53. package/.next/server/server-reference-manifest.json +1 -0
  54. package/.next/server/webpack-runtime.js +1 -0
  55. package/.next/static/VkyJa9K30jCrKBesOgrQT/_buildManifest.js +1 -0
  56. package/.next/static/VkyJa9K30jCrKBesOgrQT/_ssgManifest.js +1 -0
  57. package/.next/static/chunks/107-3043079e7cb8bcae.js +1 -0
  58. package/.next/static/chunks/293-67391ef0e44ffa4f.js +1 -0
  59. package/.next/static/chunks/3bd82e28-cda2c00a924937c5.js +1 -0
  60. package/.next/static/chunks/45-1021fac82f766268.js +1 -0
  61. package/.next/static/chunks/484-1969fe871b27074e.js +1 -0
  62. package/.next/static/chunks/484-e02de792ff5f9ea5.js +1 -0
  63. package/.next/static/chunks/589-817d8691661d370e.js +1 -0
  64. package/.next/static/chunks/902-c34acb56733e0ce1.js +1 -0
  65. package/.next/static/chunks/app/_not-found/page-4cbc7dce3ad33336.js +1 -0
  66. package/.next/static/chunks/app/layout-74628781c0b7e7bf.js +1 -0
  67. package/.next/static/chunks/app/layout-daeba68330ab58bb.js +1 -0
  68. package/.next/static/chunks/app/page-55cf199b7ca71958.js +1 -0
  69. package/.next/static/chunks/app/preview/[...slug]/page-07dd9a701d0b3e56.js +1 -0
  70. package/.next/static/chunks/app/preview/[...slug]/page-61b0ea70a8d72916.js +1 -0
  71. package/.next/static/chunks/f33a14d2-ec7c5f0b91818561.js +6 -0
  72. package/.next/static/chunks/framework-b887e9fc751a9906.js +1 -0
  73. package/.next/static/chunks/main-9a03e7ba8acb1900.js +1 -0
  74. package/.next/static/chunks/main-app-5bc2d814f500db60.js +1 -0
  75. package/.next/static/chunks/pages/_app-542a93a5a214e1c0.js +1 -0
  76. package/.next/static/chunks/pages/_error-d5fe1b1612642f76.js +1 -0
  77. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  78. package/.next/static/chunks/webpack-31c45daa2bd82a7b.js +1 -0
  79. package/.next/static/css/35e8811589f0962b.css +3 -0
  80. package/.next/static/j4oDiQwPKPQgK5jAoiUTk/_buildManifest.js +1 -0
  81. package/.next/static/j4oDiQwPKPQgK5jAoiUTk/_ssgManifest.js +1 -0
  82. package/.next/static/media/05613964ce6c782e-s.p.otf +0 -0
  83. package/.next/static/media/11c6126b9369e85e-s.p.otf +0 -0
  84. package/.next/static/media/26a46d62cd723877-s.woff2 +0 -0
  85. package/.next/static/media/26cb97734d8cb717-s.p.otf +0 -0
  86. package/.next/static/media/55c55f0601d81cf3-s.woff2 +0 -0
  87. package/.next/static/media/581909926a08bbc8-s.woff2 +0 -0
  88. package/.next/static/media/6d93bde91c0c2823-s.woff2 +0 -0
  89. package/.next/static/media/97e0cb1ae144a2a9-s.woff2 +0 -0
  90. package/.next/static/media/a34f9d1faa5f3315-s.p.woff2 +0 -0
  91. package/.next/static/media/bb6462617151f6b7-s.p.otf +0 -0
  92. package/.next/static/media/cf6daef822ab0142-s.p.otf +0 -0
  93. package/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  94. package/.next/static/media/e4051546b3043204-s.p.otf +0 -0
  95. package/.next/static/media/logo.2ce2a759.png +0 -0
  96. package/.next/trace +27 -0
  97. package/.next/types/app/layout.ts +84 -0
  98. package/.next/types/app/page.ts +84 -0
  99. package/.next/types/app/preview/[...slug]/page.ts +84 -0
  100. package/.next/types/cache-life.d.ts +141 -0
  101. package/.next/types/package.json +1 -0
  102. package/_index.js +4 -0
  103. package/license.md +7 -0
  104. package/module-punycode.d.ts +3 -0
  105. package/next-env.d.ts +5 -0
  106. package/next.config.js +22 -0
  107. package/package.json +82 -0
  108. package/postcss.config.js +8 -0
  109. package/scripts/build-preview-server.mjs +29 -0
  110. package/scripts/fill-caniemail-data.mjs +36 -0
  111. package/src/actions/email-validation/caniemail-data.ts +85993 -0
  112. package/src/actions/email-validation/check-compatibility.ts +333 -0
  113. package/src/actions/email-validation/check-images.spec.tsx +100 -0
  114. package/src/actions/email-validation/check-images.ts +160 -0
  115. package/src/actions/email-validation/check-links.spec.tsx +113 -0
  116. package/src/actions/email-validation/check-links.ts +113 -0
  117. package/src/actions/email-validation/get-code-location-from-ast-element.ts +18 -0
  118. package/src/actions/email-validation/quick-fetch.ts +14 -0
  119. package/src/actions/get-email-path-from-slug.ts +32 -0
  120. package/src/actions/get-emails-directory-metadata-action.ts +19 -0
  121. package/src/actions/render-email-by-path.tsx +121 -0
  122. package/src/animated-icons-data/help.json +1082 -0
  123. package/src/animated-icons-data/link.json +1309 -0
  124. package/src/animated-icons-data/load.json +443 -0
  125. package/src/animated-icons-data/mail.json +1320 -0
  126. package/src/app/env.ts +15 -0
  127. package/src/app/favicon.ico +0 -0
  128. package/src/app/fonts/SFMono/SFMonoBold.otf +0 -0
  129. package/src/app/fonts/SFMono/SFMonoBoldItalic.otf +0 -0
  130. package/src/app/fonts/SFMono/SFMonoHeavy.otf +0 -0
  131. package/src/app/fonts/SFMono/SFMonoHeavyItalic.otf +0 -0
  132. package/src/app/fonts/SFMono/SFMonoLight.otf +0 -0
  133. package/src/app/fonts/SFMono/SFMonoLightItalic.otf +0 -0
  134. package/src/app/fonts/SFMono/SFMonoMedium.otf +0 -0
  135. package/src/app/fonts/SFMono/SFMonoMediumItalic.otf +0 -0
  136. package/src/app/fonts/SFMono/SFMonoRegular.otf +0 -0
  137. package/src/app/fonts/SFMono/SFMonoRegularItalic.otf +0 -0
  138. package/src/app/fonts/SFMono/SFMonoSemibold.otf +0 -0
  139. package/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf +0 -0
  140. package/src/app/fonts.ts +39 -0
  141. package/src/app/globals.css +15 -0
  142. package/src/app/layout.tsx +43 -0
  143. package/src/app/logo.png +0 -0
  144. package/src/app/page.tsx +46 -0
  145. package/src/app/preview/[...slug]/page.tsx +157 -0
  146. package/src/app/preview/[...slug]/preview.tsx +216 -0
  147. package/src/app/preview/[...slug]/rendering-error.tsx +40 -0
  148. package/src/components/button.tsx +101 -0
  149. package/src/components/code-container.tsx +164 -0
  150. package/src/components/code-snippet.tsx +9 -0
  151. package/src/components/code.tsx +184 -0
  152. package/src/components/heading.tsx +113 -0
  153. package/src/components/icons/icon-arrow-down.tsx +16 -0
  154. package/src/components/icons/icon-base.tsx +26 -0
  155. package/src/components/icons/icon-bug.tsx +19 -0
  156. package/src/components/icons/icon-button.tsx +23 -0
  157. package/src/components/icons/icon-check.tsx +19 -0
  158. package/src/components/icons/icon-clipboard.tsx +40 -0
  159. package/src/components/icons/icon-download.tsx +19 -0
  160. package/src/components/icons/icon-email.tsx +18 -0
  161. package/src/components/icons/icon-file.tsx +19 -0
  162. package/src/components/icons/icon-folder-open.tsx +19 -0
  163. package/src/components/icons/icon-folder.tsx +18 -0
  164. package/src/components/icons/icon-hide-sidebar.tsx +23 -0
  165. package/src/components/icons/icon-image.tsx +19 -0
  166. package/src/components/icons/icon-info.tsx +18 -0
  167. package/src/components/icons/icon-link.tsx +14 -0
  168. package/src/components/icons/icon-monitor.tsx +19 -0
  169. package/src/components/icons/icon-phone.tsx +26 -0
  170. package/src/components/icons/icon-reload.tsx +18 -0
  171. package/src/components/icons/icon-source.tsx +19 -0
  172. package/src/components/icons/icon-stamp.tsx +14 -0
  173. package/src/components/icons/icon-warning.tsx +31 -0
  174. package/src/components/index.ts +7 -0
  175. package/src/components/logo.tsx +63 -0
  176. package/src/components/resizable-wrapper.tsx +173 -0
  177. package/src/components/send.tsx +134 -0
  178. package/src/components/shell.tsx +92 -0
  179. package/src/components/sidebar/file-tree-directory-children.tsx +139 -0
  180. package/src/components/sidebar/file-tree-directory.tsx +92 -0
  181. package/src/components/sidebar/file-tree.tsx +31 -0
  182. package/src/components/sidebar/index.ts +1 -0
  183. package/src/components/sidebar/sidebar.tsx +43 -0
  184. package/src/components/text.tsx +99 -0
  185. package/src/components/toolbar/checking-results.tsx +150 -0
  186. package/src/components/toolbar/code-preview-line-link.tsx +40 -0
  187. package/src/components/toolbar/compatibility.tsx +113 -0
  188. package/src/components/toolbar/linter.tsx +278 -0
  189. package/src/components/toolbar/results-table.tsx +0 -0
  190. package/src/components/toolbar/results.tsx +51 -0
  191. package/src/components/toolbar/spam-assassin.tsx +155 -0
  192. package/src/components/toolbar/toolbar-button.tsx +52 -0
  193. package/src/components/toolbar/use-cached-state.ts +33 -0
  194. package/src/components/toolbar.tsx +349 -0
  195. package/src/components/tooltip-content.tsx +31 -0
  196. package/src/components/tooltip.tsx +19 -0
  197. package/src/components/topbar/active-view-toggle-group.tsx +86 -0
  198. package/src/components/topbar/view-size-controls.tsx +247 -0
  199. package/src/components/topbar.tsx +59 -0
  200. package/src/contexts/emails.tsx +59 -0
  201. package/src/contexts/fragment-identifier.tsx +48 -0
  202. package/src/contexts/preview.tsx +79 -0
  203. package/src/hooks/use-clamped-state.ts +24 -0
  204. package/src/hooks/use-email-rendering-result.ts +58 -0
  205. package/src/hooks/use-fragment-identifier.ts +14 -0
  206. package/src/hooks/use-hot-reload.ts +31 -0
  207. package/src/hooks/use-icon-animation.ts +41 -0
  208. package/src/hooks/use-rendering-metadata.ts +36 -0
  209. package/src/utils/__snapshots__/get-email-component.spec.ts.snap +3 -0
  210. package/src/utils/caniemail/all-css-properties.ts +358 -0
  211. package/src/utils/caniemail/ast/__snapshots__/get-object-variables.spec.ts.snap +74 -0
  212. package/src/utils/caniemail/ast/__snapshots__/get-used-style-properties.spec.ts.snap +24 -0
  213. package/src/utils/caniemail/ast/get-object-variables.spec.ts +19 -0
  214. package/src/utils/caniemail/ast/get-object-variables.ts +61 -0
  215. package/src/utils/caniemail/ast/get-used-style-properties.spec.ts +23 -0
  216. package/src/utils/caniemail/ast/get-used-style-properties.ts +91 -0
  217. package/src/utils/caniemail/get-compatibility-stats-for-entry.ts +118 -0
  218. package/src/utils/caniemail/get-css-functions.ts +25 -0
  219. package/src/utils/caniemail/get-css-property-names.ts +32 -0
  220. package/src/utils/caniemail/get-css-property-with-value.ts +14 -0
  221. package/src/utils/caniemail/get-css-unit.ts +3 -0
  222. package/src/utils/caniemail/get-element-attributes.ts +7 -0
  223. package/src/utils/caniemail/get-element-names.ts +20 -0
  224. package/src/utils/caniemail/tailwind/generate-tailwind-rules.ts +30 -0
  225. package/src/utils/caniemail/tailwind/get-tailwind-config.ts +187 -0
  226. package/src/utils/caniemail/tailwind/get-tailwind-metadata.spec.ts +25 -0
  227. package/src/utils/caniemail/tailwind/get-tailwind-metadata.ts +45 -0
  228. package/src/utils/caniemail/tailwind/setup-tailwind-context.ts +15 -0
  229. package/src/utils/cn.ts +6 -0
  230. package/src/utils/constants.ts +6 -0
  231. package/src/utils/contains-email-template.spec.ts +124 -0
  232. package/src/utils/contains-email-template.ts +33 -0
  233. package/src/utils/copy-text-to-clipboard.ts +7 -0
  234. package/src/utils/esbuild/escape-string-for-regex.ts +3 -0
  235. package/src/utils/esbuild/renderring-utilities-exporter.ts +63 -0
  236. package/src/utils/get-email-component.spec.ts +41 -0
  237. package/src/utils/get-email-component.ts +134 -0
  238. package/src/utils/get-emails-directory-metadata.spec.ts +82 -0
  239. package/src/utils/get-emails-directory-metadata.ts +141 -0
  240. package/src/utils/get-line-and-column-from-offset.spec.ts +11 -0
  241. package/src/utils/get-line-and-column-from-offset.ts +11 -0
  242. package/src/utils/improve-error-with-sourcemap.ts +85 -0
  243. package/src/utils/index.ts +6 -0
  244. package/src/utils/js-email-detection.spec.ts +24 -0
  245. package/src/utils/language-map.ts +7 -0
  246. package/src/utils/linting.ts +60 -0
  247. package/src/utils/load-stream.ts +15 -0
  248. package/src/utils/register-spinner-autostopping.ts +28 -0
  249. package/src/utils/result.ts +49 -0
  250. package/src/utils/run-bundled-code.ts +64 -0
  251. package/src/utils/sanitize.ts +6 -0
  252. package/src/utils/static-node-modules-for-vm.ts +93 -0
  253. package/src/utils/testing/js-email-export-default.js +17 -0
  254. package/src/utils/testing/js-email-test.js +18 -0
  255. package/src/utils/testing/mdx-email-test.js +128 -0
  256. package/src/utils/testing/request-response-email.tsx +9 -0
  257. package/src/utils/types/as.ts +26 -0
  258. package/src/utils/types/email-template.ts +8 -0
  259. package/src/utils/types/error-object.ts +11 -0
  260. package/src/utils/types/hot-reload-change.ts +13 -0
  261. package/src/utils/unreachable.ts +8 -0
  262. package/tailwind-internals.d.ts +133 -0
  263. package/tailwind.config.ts +99 -0
  264. package/tsconfig.json +45 -0
  265. package/vitest.config.ts +15 -0
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+ import { useEffect, useRef } from 'react';
3
+ import { io, type Socket } from 'socket.io-client';
4
+ import type { HotReloadChange } from '../utils/types/hot-reload-change';
5
+
6
+ /**
7
+ * Hook that detects any "reload" event sent from the CLI's web socket
8
+ * and calls the received parameter callback
9
+ */
10
+ export const useHotreload = (
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ onShouldReload: (changes: HotReloadChange[]) => any,
13
+ ) => {
14
+ const socketRef = useRef<Socket | null>(null);
15
+
16
+ useEffect(() => {
17
+ if (!socketRef.current) {
18
+ socketRef.current = io();
19
+ }
20
+ const socket = socketRef.current;
21
+
22
+ socket.on('reload', (changes: HotReloadChange[]) => {
23
+ console.debug('Reloading...');
24
+ void onShouldReload(changes);
25
+ });
26
+
27
+ return () => {
28
+ socket.off();
29
+ };
30
+ }, [onShouldReload]);
31
+ };
@@ -0,0 +1,41 @@
1
+ import type { DotLottie } from '@lottiefiles/dotlottie-react';
2
+ import * as React from 'react';
3
+
4
+ const TIMEOUT = 150;
5
+ const THRESHOLD_ANIMATION = 0.9;
6
+
7
+ export const useIconAnimation = () => {
8
+ const ref = React.useRef<DotLottie>(null);
9
+ const timer = React.useRef<NodeJS.Timeout | null>(null);
10
+
11
+ const onMouseLeave = React.useCallback(() => {
12
+ timer.current && clearTimeout(timer.current);
13
+ }, []);
14
+
15
+ const onMouseEnter = React.useCallback(() => {
16
+ if (!ref.current) {
17
+ return;
18
+ }
19
+
20
+ const total = Math.round(ref.current.totalFrames ?? 0);
21
+ const current = Math.round((ref.current.currentFrame ?? 0) + 1);
22
+
23
+ if (current === 1 || current >= total * THRESHOLD_ANIMATION) {
24
+ timer.current = setTimeout(() => {
25
+ if (!ref.current) {
26
+ return;
27
+ }
28
+
29
+ ref.current.stop();
30
+ ref.current.setSpeed(1);
31
+ ref.current.play();
32
+ }, TIMEOUT);
33
+ }
34
+ }, []);
35
+
36
+ return {
37
+ ref,
38
+ onMouseLeave,
39
+ onMouseEnter,
40
+ };
41
+ };
@@ -0,0 +1,36 @@
1
+ import { useEffect } from 'react';
2
+ import type {
3
+ EmailRenderingResult,
4
+ RenderedEmailMetadata,
5
+ } from '../actions/render-email-by-path';
6
+
7
+ const lastRenderingMetadataPerEmailPath = {} as Record<
8
+ string,
9
+ RenderedEmailMetadata
10
+ >;
11
+
12
+ /**
13
+ * Returns the rendering metadata if the given `renderingResult`
14
+ * does not error. If it does error it returns the last value it had for the hook.
15
+ */
16
+ export const useRenderingMetadata = (
17
+ emailPath: string,
18
+ renderingResult: EmailRenderingResult,
19
+ serverRenderingMetadata: EmailRenderingResult,
20
+ ): RenderedEmailMetadata | undefined => {
21
+ useEffect(() => {
22
+ if ('markup' in renderingResult) {
23
+ lastRenderingMetadataPerEmailPath[emailPath] = renderingResult;
24
+ } else if (
25
+ typeof serverRenderingMetadata !== 'undefined' &&
26
+ 'markup' in serverRenderingMetadata &&
27
+ typeof lastRenderingMetadataPerEmailPath[emailPath] === 'undefined'
28
+ ) {
29
+ lastRenderingMetadataPerEmailPath[emailPath] = serverRenderingMetadata;
30
+ }
31
+ }, [renderingResult, emailPath, serverRenderingMetadata]);
32
+
33
+ return 'error' in renderingResult
34
+ ? lastRenderingMetadataPerEmailPath[emailPath]
35
+ : renderingResult;
36
+ };
@@ -0,0 +1,3 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`getEmailComponent() > with a demo email template 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html dir="ltr" lang="en"><head><link rel="preload" as="image" href="/static/vercel-logo.png"/><link rel="preload" as="image" href="/static/vercel-user.png"/><link rel="preload" as="image" href="/static/vercel-arrow.png"/><link rel="preload" as="image" href="/static/vercel-team.png"/><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/><meta name="x-apple-disable-message-reformatting"/><!--$--></head><body style="margin-left:auto;margin-right:auto;margin-top:auto;margin-bottom:auto;background-color:rgb(255,255,255);padding-left:0.5rem;padding-right:0.5rem;font-family:ui-sans-serif, system-ui, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;, &quot;Noto Color Emoji&quot;"><div style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0" data-skip-in-text="true">Join Alan on Vercel<div> ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏</div></div><table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="margin-left:auto;margin-right:auto;margin-top:40px;margin-bottom:40px;max-width:465px;border-radius:0.25rem;border-width:1px;border-color:rgb(234,234,234);border-style:solid;padding:20px"><tbody><tr style="width:100%"><td><table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="margin-top:32px"><tbody><tr><td><img alt="Vercel Logo" height="37" src="/static/vercel-logo.png" style="margin-left:auto;margin-right:auto;margin-top:0px;margin-bottom:0px;display:block;outline:none;border:none;text-decoration:none" width="40"/></td></tr></tbody></table><h1 style="margin-left:0px;margin-right:0px;margin-top:30px;margin-bottom:30px;padding:0px;text-align:center;font-weight:400;font-size:24px;color:rgb(0,0,0)">Join <strong>Enigma</strong> on <strong>Vercel</strong></h1><p style="font-size:14px;color:rgb(0,0,0);line-height:24px;margin-top:16px;margin-bottom:16px">Hello <!-- -->alanturing<!-- -->,</p><p style="font-size:14px;color:rgb(0,0,0);line-height:24px;margin-top:16px;margin-bottom:16px"><strong>Alan</strong> (<a href="mailto:alan.turing@example.com" style="color:rgb(37,99,235);text-decoration-line:none" target="_blank">alan.turing@example.com</a>) has invited you to the <strong>Enigma</strong> team on<!-- --> <strong>Vercel</strong>.</p><table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation"><tbody><tr><td><table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation"><tbody style="width:100%"><tr style="width:100%"><td align="right" data-id="__react-email-column"><img alt="alanturing&#x27;s profile picture" height="64" src="/static/vercel-user.png" style="border-radius:9999px;display:block;outline:none;border:none;text-decoration:none" width="64"/></td><td align="center" data-id="__react-email-column"><img alt="Arrow indicating invitation" height="9" src="/static/vercel-arrow.png" style="display:block;outline:none;border:none;text-decoration:none" width="12"/></td><td align="left" data-id="__react-email-column"><img alt="Enigma team logo" height="64" src="/static/vercel-team.png" style="border-radius:9999px;display:block;outline:none;border:none;text-decoration:none" width="64"/></td></tr></tbody></table></td></tr></tbody></table><table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="margin-top:32px;margin-bottom:32px;text-align:center"><tbody><tr><td><a href="https://vercel.com" style="border-radius:0.25rem;background-color:rgb(0,0,0);padding-left:20px;padding-right:20px;padding-top:12px;padding-bottom:12px;text-align:center;font-weight:600;font-size:12px;color:rgb(255,255,255);text-decoration-line:none;line-height:100%;text-decoration:none;display:inline-block;max-width:100%;mso-padding-alt:0px" target="_blank"><span><!--[if mso]><i style="mso-font-width:500%;mso-text-raise:18" hidden>&#8202;&#8202;</i><![endif]--></span><span style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:9px">Join the team</span><span><!--[if mso]><i style="mso-font-width:500%" hidden>&#8202;&#8202;&#8203;</i><![endif]--></span></a></td></tr></tbody></table><p style="font-size:14px;color:rgb(0,0,0);line-height:24px;margin-top:16px;margin-bottom:16px">or copy and paste this URL into your browser:<!-- --> <a href="https://vercel.com" style="color:rgb(37,99,235);text-decoration-line:none" target="_blank">https://vercel.com</a></p><hr style="margin-left:0px;margin-right:0px;margin-top:26px;margin-bottom:26px;width:100%;border-width:1px;border-color:rgb(234,234,234);border-style:solid;border:none;border-top:1px solid #eaeaea"/><p style="color:rgb(102,102,102);font-size:12px;line-height:24px;margin-top:16px;margin-bottom:16px">This invitation was intended for<!-- --> <span style="color:rgb(0,0,0)">alanturing</span>. This invite was sent from <span style="color:rgb(0,0,0)">204.13.186.218</span> <!-- -->located in<!-- --> <span style="color:rgb(0,0,0)">São Paulo, Brazil</span>. If you were not expecting this invitation, you can ignore this email. If you are concerned about your account&#x27;s safety, please reply to this email to get in touch with us.</p></td></tr></tbody></table><!--/$--></body></html>"`;
@@ -0,0 +1,358 @@
1
+ // taken from https://www.w3schools.com/cssref/index.php
2
+ export const allCssProperties = [
3
+ 'accent-color',
4
+ 'align-content',
5
+ 'align-items',
6
+ 'align-self',
7
+ 'all',
8
+ 'animation',
9
+ 'animation-delay',
10
+ 'animation-direction',
11
+ 'animation-duration',
12
+ 'animation-fill-mode',
13
+ 'animation-iteration-count',
14
+ 'animation-name',
15
+ 'animation-play-state',
16
+ 'animation-timing-function',
17
+ 'aspect-ratio',
18
+ 'backdrop-filter',
19
+ 'backface-visibility',
20
+ 'background',
21
+ 'background-attachment',
22
+ 'background-blend-mode',
23
+ 'background-clip',
24
+ 'background-color',
25
+ 'background-image',
26
+ 'background-origin',
27
+ 'background-position',
28
+ 'background-position-x',
29
+ 'background-position-y',
30
+ 'background-repeat',
31
+ 'background-size',
32
+ 'block-size',
33
+ 'border',
34
+ 'border-block',
35
+ 'border-block-color',
36
+ 'border-block-end',
37
+ 'border-block-end-color',
38
+ 'border-block-end-style',
39
+ 'border-block-end-width',
40
+ 'border-block-start',
41
+ 'border-block-start-color',
42
+ 'border-block-start-style',
43
+ 'border-block-start-width',
44
+ 'border-block-style',
45
+ 'border-block-width',
46
+ 'border-bottom',
47
+ 'border-bottom-color',
48
+ 'border-bottom-left-radius',
49
+ 'border-bottom-right-radius',
50
+ 'border-bottom-style',
51
+ 'border-bottom-width',
52
+ 'border-collapse',
53
+ 'border-color',
54
+ 'border-end-end-radius',
55
+ 'border-end-start-radius',
56
+ 'border-image',
57
+ 'border-image-outset',
58
+ 'border-image-repeat',
59
+ 'border-image-slice',
60
+ 'border-image-source',
61
+ 'border-image-width',
62
+ 'border-inline',
63
+ 'border-inline-color',
64
+ 'border-inline-end',
65
+ 'border-inline-end-color',
66
+ 'border-inline-end-style',
67
+ 'border-inline-end-width',
68
+ 'border-inline-start',
69
+ 'border-inline-start-color',
70
+ 'border-inline-start-style',
71
+ 'border-inline-start-width',
72
+ 'border-inline-style',
73
+ 'border-inline-width',
74
+ 'border-left',
75
+ 'border-left-color',
76
+ 'border-left-style',
77
+ 'border-left-width',
78
+ 'border-radius',
79
+ 'border-right',
80
+ 'border-right-color',
81
+ 'border-right-style',
82
+ 'border-right-width',
83
+ 'border-spacing',
84
+ 'border-start-end-radius',
85
+ 'border-start-start-radius',
86
+ 'border-style',
87
+ 'border-top',
88
+ 'border-top-color',
89
+ 'border-top-left-radius',
90
+ 'border-top-right-radius',
91
+ 'border-top-style',
92
+ 'border-top-width',
93
+ 'border-width',
94
+ 'bottom',
95
+ 'box-decoration-break',
96
+ 'box-reflect',
97
+ 'box-shadow',
98
+ 'box-sizing',
99
+ 'break-after',
100
+ 'break-before',
101
+ 'break-inside',
102
+ 'caption-side',
103
+ 'caret-color',
104
+ '@charset',
105
+ 'clear',
106
+ 'clip',
107
+ 'clip-path',
108
+ 'color',
109
+ 'column-count',
110
+ 'column-fill',
111
+ 'column-gap',
112
+ 'column-rule',
113
+ 'column-rule-color',
114
+ 'column-rule-style',
115
+ 'column-rule-width',
116
+ 'column-span',
117
+ 'column-width',
118
+ 'columns',
119
+ 'content',
120
+ 'counter-increment',
121
+ 'counter-reset',
122
+ 'counter-set',
123
+ 'cursor',
124
+ 'direction',
125
+ 'display',
126
+ 'empty-cells',
127
+ 'filter',
128
+ 'flex',
129
+ 'flex-basis',
130
+ 'flex-direction',
131
+ 'flex-flow',
132
+ 'flex-grow',
133
+ 'flex-shrink',
134
+ 'flex-wrap',
135
+ 'float',
136
+ 'font',
137
+ '@font-face',
138
+ 'font-family',
139
+ 'font-feature-settings',
140
+ '@font-feature-values',
141
+ 'font-kerning',
142
+ 'font-language-override',
143
+ 'font-size',
144
+ 'font-size-adjust',
145
+ 'font-stretch',
146
+ 'font-style',
147
+ 'font-synthesis',
148
+ 'font-variant',
149
+ 'font-variant-alternates',
150
+ 'font-variant-caps',
151
+ 'font-variant-east-asian',
152
+ 'font-variant-ligatures',
153
+ 'font-variant-numeric',
154
+ 'font-variant-position',
155
+ 'font-weight',
156
+ 'gap',
157
+ 'grid',
158
+ 'grid-area',
159
+ 'grid-auto-columns',
160
+ 'grid-auto-flow',
161
+ 'grid-auto-rows',
162
+ 'grid-column',
163
+ 'grid-column-end',
164
+ 'grid-column-gap',
165
+ 'grid-column-start',
166
+ 'grid-gap',
167
+ 'grid-row',
168
+ 'grid-row-end',
169
+ 'grid-row-gap',
170
+ 'grid-row-start',
171
+ 'grid-template',
172
+ 'grid-template-areas',
173
+ 'grid-template-columns',
174
+ 'grid-template-rows',
175
+ 'hanging-punctuation',
176
+ 'height',
177
+ 'hyphens',
178
+ 'hypenate-character',
179
+ 'image-rendering',
180
+ '@import',
181
+ 'inline-size',
182
+ 'inset',
183
+ 'inset-block',
184
+ 'inset-block-end',
185
+ 'inset-block-start',
186
+ 'inset-inline',
187
+ 'inset-inline-end',
188
+ 'inset-inline-start',
189
+ 'isolation',
190
+ 'justify-content',
191
+ 'justify-items',
192
+ 'justify-self',
193
+ '@keyframes',
194
+ 'left',
195
+ 'letter-spacing',
196
+ 'line-break',
197
+ 'line-height',
198
+ 'list-style',
199
+ 'list-style-image',
200
+ 'list-style-position',
201
+ 'list-style-type',
202
+ 'margin',
203
+ 'shape-margin',
204
+ 'margin-block',
205
+ 'margin-block-end',
206
+ 'margin-block-start',
207
+ 'margin-bottom',
208
+ 'margin-inline',
209
+ 'margin-inline-end',
210
+ 'margin-inline-start',
211
+ 'margin-left',
212
+ 'margin-right',
213
+ 'margin-top',
214
+ 'mask',
215
+ 'mask-clip',
216
+ 'mask-composite',
217
+ 'mask-image',
218
+ 'mask-mode',
219
+ 'mask-origin',
220
+ 'mask-position',
221
+ 'mask-repeat',
222
+ 'mask-size',
223
+ 'mask-type',
224
+ 'max-height',
225
+ 'max-width',
226
+ '@media',
227
+ 'max-block-size',
228
+ 'max-inline-size',
229
+ 'min-block-size',
230
+ 'min-inline-size',
231
+ 'min-height',
232
+ 'min-width',
233
+ 'mix-blend-mode',
234
+ 'object-fit',
235
+ 'object-position',
236
+ 'offset',
237
+ 'offset-anchor',
238
+ 'offset-distance',
239
+ 'offset-path',
240
+ 'offset-rotate',
241
+ 'opacity',
242
+ 'order',
243
+ 'orphans',
244
+ 'outline',
245
+ 'outline-color',
246
+ 'outline-offset',
247
+ 'outline-style',
248
+ 'outline-width',
249
+ 'overflow',
250
+ 'overflow-anchor',
251
+ 'overflow-wrap',
252
+ 'overflow-x',
253
+ 'overflow-y',
254
+ 'overscroll-behavior',
255
+ 'overscroll-behavior-block',
256
+ 'overscroll-behavior-inline',
257
+ 'overscroll-behavior-x',
258
+ 'overscroll-behavior-y',
259
+ 'padding',
260
+ 'padding-block',
261
+ 'padding-block-end',
262
+ 'padding-block-start',
263
+ 'padding-bottom',
264
+ 'padding-inline',
265
+ 'padding-inline-end',
266
+ 'padding-inline-start',
267
+ 'padding-left',
268
+ 'padding-right',
269
+ 'padding-top',
270
+ 'page-break-after',
271
+ 'page-break-before',
272
+ 'page-break-inside',
273
+ 'paint-order',
274
+ 'perspective',
275
+ 'perspective-origin',
276
+ 'place-content',
277
+ 'place-items',
278
+ 'place-self',
279
+ 'pointer-events',
280
+ 'position',
281
+ 'quotes',
282
+ 'resize',
283
+ 'right',
284
+ 'rotate',
285
+ 'row-gap',
286
+ 'scale',
287
+ 'scroll-behavior',
288
+ 'scroll-margin',
289
+ 'scroll-margin-block',
290
+ 'scroll-margin-block-end',
291
+ 'scroll-margin-block-start',
292
+ 'scroll-margin-bottom',
293
+ 'scroll-margin-inline',
294
+ 'scroll-margin-inline-end',
295
+ 'scroll-margin-inline-start',
296
+ 'scroll-margin-left',
297
+ 'scroll-margin-right',
298
+ 'scroll-margin-top',
299
+ 'scroll-padding',
300
+ 'scroll-padding-block',
301
+ 'scroll-padding-block-end',
302
+ 'scroll-padding-block-start',
303
+ 'scroll-padding-bottom',
304
+ 'scroll-padding-inline',
305
+ 'scroll-padding-inline-end',
306
+ 'scroll-padding-inline-start',
307
+ 'scroll-padding-left',
308
+ 'scroll-padding-right',
309
+ 'scroll-padding-top',
310
+ 'scroll-snap-align',
311
+ 'scroll-snap-stop',
312
+ 'scroll-snap-type',
313
+ 'scrollbar-color',
314
+ 'tab-size',
315
+ 'table-layout',
316
+ 'text-align',
317
+ 'text-align-last',
318
+ 'text-combine-upright',
319
+ 'text-decoration',
320
+ 'text-decoration-color',
321
+ 'text-decoration-line',
322
+ 'text-decoration-style',
323
+ 'text-decoration-thickness',
324
+ 'text-emphasis',
325
+ 'text-emphasis-color',
326
+ 'text-emphasis-position',
327
+ 'text-emphasis-style',
328
+ 'text-indent',
329
+ 'text-justify',
330
+ 'text-orientation',
331
+ 'text-overflow',
332
+ 'text-shadow',
333
+ 'text-transform',
334
+ 'text-underline-offset',
335
+ 'text-underline-position',
336
+ 'top',
337
+ 'transform',
338
+ 'transform-origin',
339
+ 'transform-style',
340
+ 'transition',
341
+ 'transition-delay',
342
+ 'transition-duration',
343
+ 'transition-property',
344
+ 'transition-timing-function',
345
+ 'translate',
346
+ 'unicode-bidi',
347
+ 'user-select',
348
+ 'vertical-align',
349
+ 'visibility',
350
+ 'white-space',
351
+ 'widows',
352
+ 'width',
353
+ 'word-break',
354
+ 'word-spacing',
355
+ 'word-wrap',
356
+ 'writing-mode',
357
+ 'z-index',
358
+ ];
@@ -0,0 +1,74 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`getObjectVariables() 1`] = `
4
+ {
5
+ "buttonStyle": [
6
+ Node {
7
+ "computed": false,
8
+ "end": 91,
9
+ "key": Node {
10
+ "end": 84,
11
+ "loc": SourceLocation {
12
+ "end": Position {
13
+ "column": 14,
14
+ "index": 84,
15
+ "line": 5,
16
+ },
17
+ "filename": undefined,
18
+ "identifierName": "borderRadius",
19
+ "start": Position {
20
+ "column": 2,
21
+ "index": 72,
22
+ "line": 5,
23
+ },
24
+ },
25
+ "name": "borderRadius",
26
+ "start": 72,
27
+ "type": "Identifier",
28
+ },
29
+ "loc": SourceLocation {
30
+ "end": Position {
31
+ "column": 21,
32
+ "index": 91,
33
+ "line": 5,
34
+ },
35
+ "filename": undefined,
36
+ "identifierName": undefined,
37
+ "start": Position {
38
+ "column": 2,
39
+ "index": 72,
40
+ "line": 5,
41
+ },
42
+ },
43
+ "method": false,
44
+ "shorthand": false,
45
+ "start": 72,
46
+ "type": "ObjectProperty",
47
+ "value": Node {
48
+ "end": 91,
49
+ "extra": {
50
+ "raw": "'5px'",
51
+ "rawValue": "5px",
52
+ },
53
+ "loc": SourceLocation {
54
+ "end": Position {
55
+ "column": 21,
56
+ "index": 91,
57
+ "line": 5,
58
+ },
59
+ "filename": undefined,
60
+ "identifierName": undefined,
61
+ "start": Position {
62
+ "column": 16,
63
+ "index": 86,
64
+ "line": 5,
65
+ },
66
+ },
67
+ "start": 86,
68
+ "type": "StringLiteral",
69
+ "value": "5px",
70
+ },
71
+ },
72
+ ],
73
+ }
74
+ `;
@@ -0,0 +1,24 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`getUsedStyleProperties() 1`] = `
4
+ [
5
+ {
6
+ "location": SourceLocation {
7
+ "end": Position {
8
+ "column": 21,
9
+ "index": 91,
10
+ "line": 5,
11
+ },
12
+ "filename": undefined,
13
+ "identifierName": undefined,
14
+ "start": Position {
15
+ "column": 2,
16
+ "index": 72,
17
+ "line": 5,
18
+ },
19
+ },
20
+ "name": "borderRadius",
21
+ "value": "5px",
22
+ },
23
+ ]
24
+ `;
@@ -0,0 +1,19 @@
1
+ import { parse } from '@babel/parser';
2
+ import { getObjectVariables } from './get-object-variables';
3
+
4
+ test('getObjectVariables()', () => {
5
+ const reactCode = `
6
+ <Button style={buttonStyle}>Click me</Button>
7
+
8
+ const buttonStyle = {
9
+ borderRadius: '5px',
10
+ };
11
+ `;
12
+ const ast = parse(reactCode, {
13
+ strictMode: false,
14
+ errorRecovery: true,
15
+ sourceType: 'unambiguous',
16
+ plugins: ['jsx', 'typescript', 'decorators'],
17
+ });
18
+ expect(getObjectVariables(ast)).toMatchSnapshot();
19
+ });
@@ -0,0 +1,61 @@
1
+ import traverse from '@babel/traverse';
2
+ import type { Node } from '@babel/traverse';
3
+ import type { AST } from '../../../actions/email-validation/check-compatibility';
4
+
5
+ export interface Position {
6
+ line: number;
7
+ column: number;
8
+ index: number;
9
+ }
10
+
11
+ export const convertLocationIntoObject = (
12
+ location: SourceLocation,
13
+ ): SourceLocation => {
14
+ return {
15
+ start: {
16
+ line: location.start.line,
17
+ column: location.start.column,
18
+ index: location.start.index,
19
+ },
20
+ end: {
21
+ line: location.end.line,
22
+ column: location.end.column,
23
+ index: location.end.index,
24
+ },
25
+ filename: location.filename,
26
+ identifierName: location.identifierName,
27
+ };
28
+ };
29
+
30
+ export interface SourceLocation {
31
+ start: Position;
32
+ end: Position;
33
+ filename: string;
34
+ identifierName: string | undefined | null;
35
+ }
36
+
37
+ type ObjectProperty = Node & { type: 'ObjectProperty' };
38
+
39
+ export type ObjectVariables = Record<string, ObjectProperty[]>;
40
+
41
+ export const getObjectVariables = (ast: AST) => {
42
+ const objectVariables: ObjectVariables = {};
43
+ traverse(ast, {
44
+ ObjectExpression(nodePath) {
45
+ if (nodePath.parent.type === 'VariableDeclarator') {
46
+ if (nodePath.parent.id.type === 'Identifier') {
47
+ const variableName = nodePath.parent.id.name;
48
+ const properties: ObjectProperty[] = [];
49
+ for (const property of nodePath.node.properties) {
50
+ if (property.type === 'ObjectProperty') {
51
+ properties.push(property);
52
+ }
53
+ }
54
+ objectVariables[variableName] = properties;
55
+ }
56
+ }
57
+ },
58
+ });
59
+
60
+ return objectVariables;
61
+ };
@@ -0,0 +1,23 @@
1
+ import { parse } from '@babel/parser';
2
+ import { getObjectVariables } from './get-object-variables';
3
+ import { getUsedStyleProperties } from './get-used-style-properties';
4
+
5
+ test('getUsedStyleProperties()', async () => {
6
+ const reactCode = `
7
+ <Button style={buttonStyle}>Click me</Button>
8
+
9
+ const buttonStyle = {
10
+ borderRadius: '5px',
11
+ };
12
+ `;
13
+ const ast = parse(reactCode, {
14
+ strictMode: false,
15
+ errorRecovery: true,
16
+ sourceType: 'unambiguous',
17
+ plugins: ['jsx', 'typescript', 'decorators'],
18
+ });
19
+ const objectVariables = getObjectVariables(ast);
20
+ expect(
21
+ await getUsedStyleProperties(ast, reactCode, '', objectVariables),
22
+ ).toMatchSnapshot();
23
+ });