react-email: SyntaxError: Invalid regular expression: invalid group specifier name

Im using react-email in a Remix project and just rendering the emails in the route directory:

// routes/emails/reset-password.tsx
import { Tailwind } from "@react-email/tailwind"


export default function Template(props: { link?: string }) {
  return (
    <Tailwind>
      <h1 className="text-6xl">Reset Password</h1>
      <p>Click below to reset your password</p>
      <a href={props.link}>Reset Password</a>
    </Tailwind>
  )
}

When using the Tailwind component I get a SyntaxError: Invalid regular expression: invalid group specifier name in the console.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 9
  • Comments: 21 (2 by maintainers)

Commits related to this issue

Most upvoted comments

@u3u Dear I can’t do it still… I have not managed to make the fix you suggested at the comment #549 - was hoping the newest PRs would resolve the issue. But it didn’t…

Now I tried to install the @react-email/tailwind package you suggested but it doesn’t help either.

Sorry I really need this fix. Would appreciate your help. Thanks!

The latest version is published, you can try either updating the components if you are importing Tailwind from it, or updating the direct package if you import from (@react-email/tailwind)

It should have no issues when compared to the canaries, if there is any problem please open an issue so I can take a look into getting it fixed for you!

@eminx 🤔 Maybe you can consider rolling back to a previous version until the official stable release is published. Because I have already given up using tailwind, I don’t have time to study it anymore. I think the style attribute is also good 😃

a PR is coming to close this issue for you guys without a patch

Hey everyone!

I just wanted to apologize for my absence over the past few months. Juggling my role as a company leader and caring for my little ones has proven to be quite the challenge. However, I’ll work on some updates and fixes in the upcoming weeks.

I created the tw-to-css package and have been maintaining it solo. Your help in improving it by reporting any bugs has been greatly appreciated. I know it’s not perfect, but it was a challenging feat, and I’m confident we can work together to improve it.

Thank you all so much.

After research, I found that it is because Safari does not support Lookbehind regular expression matching: (?<= ) (https://caniuse.com/js-regexp-lookbehind) The underlying tw-to-css library also has the same problem: https://github.com/vinicoder/tw-to-css/issues/6 /cc @rretlaw @vinicoder

https://github.com/vinicoder/tw-to-css/blob/6eb173e8006817d6a50ad00499274349a2d35c29/src/util/format-css.ts#L18

const blockContentRegex = /(?<=\.)[^{]+\s*\{(?<content>[^{}]*(?:(?<=;)\s*\n\r?[^{}]*)*)\s*\}/gm;

Although we don’t invoke the merge method, stupid Safari will throw an error as long as it is included in the code 😅, so we can simply remove ?<= first.

image

https://github.com/resendlabs/react-email/blob/490e0356685c1a6406c89620687725d0b98ad53b/packages/tailwind/src/tailwind.tsx#L24-L28

Then replace /(?<=.)[:#\!\-[\\\]\/\.%]+/g with /(?!^\.)[:#\!\-[\\\]\/\.%]+/g

I’m not good at regular expressions, I only tested the basic case .my-1{ -> .my_1{, if it causes other problems, you can remove the cleanCss method first.

https://github.com/resendlabs/react-email/blob/490e0356685c1a6406c89620687725d0b98ad53b/packages/tailwind/src/tailwind.tsx#L116-L118

Finally, we can use pnpm patch @react-email/tailwind & pnpm patch tw-to-css & pnpm patch-commit or patch-package to immediately fix it by modifying the regex.

@react-email__tailwind@0.0.8.patch

diff --git a/dist/index.js b/dist/index.js
index 98f14262c946c52495c0c45fb166628996d11e6e..c8f123085476f1e82f4811460bc2b8865bc62a5c 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -100,7 +100,7 @@ var Tailwind = ({ children, config }) => {
 Tailwind.displayName = "Tailwind";
 function cleanCss(css) {
   let newCss = css.replace(/\\/g, "").replace(/[.\!\#\w\d\\:\-\[\]\/\.%\(\))]+(?=\s*?{[^{]*?\})\s*?{/g, (m) => {
-    return m.replace(/(?<=.)[:#\!\-[\\\]\/\.%]+/g, "_");
+    return m.replace(/(?!^\.)[:#\!\-[\\\]\/\.%]+/g, "_");
   }).replace(/font-family(?<value>[^;\r\n]+)/g, (m, value) => {
     return `font-family${value.replace(/['"]+/g, "")}`;
   });
diff --git a/dist/index.mjs b/dist/index.mjs
index 00d5b2bc460d97567ddd5688d24e0a23e034b7b4..393faf0bee94779a29918bced3d3bc927734d4e8 100644
--- a/dist/index.mjs
+++ b/dist/index.mjs
@@ -68,7 +68,7 @@ var Tailwind = ({ children, config }) => {
 Tailwind.displayName = "Tailwind";
 function cleanCss(css) {
   let newCss = css.replace(/\\/g, "").replace(/[.\!\#\w\d\\:\-\[\]\/\.%\(\))]+(?=\s*?{[^{]*?\})\s*?{/g, (m) => {
-    return m.replace(/(?<=.)[:#\!\-[\\\]\/\.%]+/g, "_");
+    return m.replace(/(?!^\.)[:#\!\-[\\\]\/\.%]+/g, "_");
   }).replace(/font-family(?<value>[^;\r\n]+)/g, (m, value) => {
     return `font-family${value.replace(/['"]+/g, "")}`;
   });

tw-to-css@0.0.11.patch

Because the tw-to-css/dist/* file is compressed, the generated patch file is too long, so it will not be released. Search for ?<= and delete it.

By the way, I want to tell @vinicoder that our published npm package does not need to be compressed. It will eventually be compressed by the user’s build tool.

I don’t know how many times I have worked overtime because of garbage Safari. Unfortunately, there are too many iOS users and all Apple platform browsers use Safari as their kernel. Safari === IE6, Apple you’re great 👍

Finally, I just want to say again: Fuck Safari! Safari must go die! 😅

+1 - Having the same issue on Safari.

@eminx Yes, you need to manually modify the source code. Executing the command pnpm patch @react-email/tailwind will create a temporary directory for this module, and you can freely modify the source code of this module in the temporary directory (search for key codes and make corresponding modifications). After completing the modifications, execute the command pnpm patch-commit <temporary directory path> to generate a patch file and automatically apply it to the modules in node_modules. The patch file should be committed to git tracking so that all collaborators can automatically apply the patched modifications when executing pnpm i.