@react-email/tailwind 0.0.13-canary.0 → 0.0.13-canary.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.
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +153 -127
- package/dist/index.mjs +153 -127
- package/package.json +7 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Config } from 'tailwindcss';
|
|
3
3
|
|
|
4
|
+
type TailwindConfig = Omit<Config, "content">;
|
|
4
5
|
interface TailwindProps {
|
|
5
6
|
children: React.ReactNode;
|
|
6
7
|
config?: TailwindConfig;
|
|
7
8
|
}
|
|
8
9
|
declare const Tailwind: React.FC<TailwindProps>;
|
|
9
10
|
|
|
10
|
-
export { Tailwind, TailwindProps };
|
|
11
|
+
export { Tailwind, TailwindConfig, TailwindProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Config } from 'tailwindcss';
|
|
3
3
|
|
|
4
|
+
type TailwindConfig = Omit<Config, "content">;
|
|
4
5
|
interface TailwindProps {
|
|
5
6
|
children: React.ReactNode;
|
|
6
7
|
config?: TailwindConfig;
|
|
7
8
|
}
|
|
8
9
|
declare const Tailwind: React.FC<TailwindProps>;
|
|
9
10
|
|
|
10
|
-
export { Tailwind, TailwindProps };
|
|
11
|
+
export { Tailwind, TailwindConfig, TailwindProps };
|
package/dist/index.js
CHANGED
|
@@ -54,7 +54,6 @@ module.exports = __toCommonJS(src_exports);
|
|
|
54
54
|
// src/tailwind.tsx
|
|
55
55
|
var React = __toESM(require("react"));
|
|
56
56
|
var import_server = require("react-dom/server");
|
|
57
|
-
var import_tw_to_css = require("tw-to-css");
|
|
58
57
|
|
|
59
58
|
// src/utils/css-to-jsx-style.ts
|
|
60
59
|
var camelCase = (string) => string.replace(/-(\w|$)/g, (_, p1) => p1.toUpperCase());
|
|
@@ -68,162 +67,189 @@ var convertPropertyName = (prop) => {
|
|
|
68
67
|
return modifiedProp;
|
|
69
68
|
}
|
|
70
69
|
if (modifiedProp.startsWith("-ms-")) {
|
|
71
|
-
modifiedProp = modifiedProp.
|
|
70
|
+
modifiedProp = modifiedProp.slice(1);
|
|
72
71
|
}
|
|
73
72
|
return camelCase(modifiedProp);
|
|
74
73
|
};
|
|
75
|
-
var
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
capturing = cssText[i];
|
|
84
|
-
} else if (cssText[i] === capturing) {
|
|
85
|
-
capturing = false;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
if (!capturing && cssText[i] === ")") {
|
|
89
|
-
capturing = cssText[i];
|
|
90
|
-
}
|
|
91
|
-
if (cssText[i] === "(" && capturing === ")") {
|
|
92
|
-
capturing = false;
|
|
93
|
-
}
|
|
94
|
-
if (i < 0 || !capturing && cssText[i] === ";") {
|
|
95
|
-
declarations.unshift(cssText.slice(i + 1, last));
|
|
96
|
-
last = i;
|
|
74
|
+
var cssToJsxStyle = (cssText) => {
|
|
75
|
+
const style = {};
|
|
76
|
+
const declarations = cssText.matchAll(
|
|
77
|
+
/([a-zA-Z0-9\-_]+)\s*:\s*('[^']*'[^;]*|"[^"]*"[^;]*|.*?\([^)]*\)[^;]*|[^;]*);?/gm
|
|
78
|
+
);
|
|
79
|
+
for (const [_declaration, property, value] of declarations) {
|
|
80
|
+
if (property.length > 0 && value.trim().length > 0) {
|
|
81
|
+
style[convertPropertyName(property)] = value.trim();
|
|
97
82
|
}
|
|
98
83
|
}
|
|
99
|
-
return
|
|
84
|
+
return style;
|
|
100
85
|
};
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
86
|
+
|
|
87
|
+
// src/utils/get-css-for-markup.ts
|
|
88
|
+
var import_postcss = __toESM(require("postcss"));
|
|
89
|
+
var import_tailwindcss = __toESM(require("tailwindcss"));
|
|
90
|
+
var import_postcss_css_variables = __toESM(require("postcss-css-variables"));
|
|
91
|
+
global.__OXIDE__ = void 0;
|
|
92
|
+
var getCssForMarkup = (markup, config) => {
|
|
93
|
+
const corePlugins = config == null ? void 0 : config.corePlugins;
|
|
94
|
+
const tailwindConfig = __spreadProps(__spreadValues({}, config), {
|
|
95
|
+
corePlugins: __spreadValues({
|
|
96
|
+
preflight: false
|
|
97
|
+
}, corePlugins)
|
|
98
|
+
});
|
|
99
|
+
const processor = (0, import_postcss.default)([
|
|
100
|
+
(0, import_tailwindcss.default)(__spreadProps(__spreadValues({}, tailwindConfig), {
|
|
101
|
+
content: [{ raw: markup, extension: "html" }]
|
|
102
|
+
})),
|
|
103
|
+
(0, import_postcss_css_variables.default)()
|
|
104
|
+
]);
|
|
105
|
+
const result = processor.process(
|
|
106
|
+
String.raw`
|
|
107
|
+
@tailwind base;
|
|
108
|
+
@tailwind components;
|
|
109
|
+
@tailwind utilities;
|
|
110
|
+
`,
|
|
111
|
+
{ from: void 0 }
|
|
112
|
+
// no need to use from since the `content` context is sent into tailwind
|
|
113
|
+
);
|
|
114
|
+
return result.css;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// src/utils/minify-css.ts
|
|
118
|
+
var minifyCss = (css) => {
|
|
119
|
+
return css.replace(/\/\*[\s\S]*?\*\//gm, "").replace(/;\s+/gm, ";").replace(/:\s+/gm, ":").replace(/\)\s*{/gm, "){").replace(/\s+\(/gm, "(").replace(/{\s+/gm, "{").replace(/}\s+/gm, "}").replace(/\s*{/gm, "{").replace(/;?\s*}/gm, "}");
|
|
104
120
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
121
|
+
|
|
122
|
+
// src/utils/get-css-class-properties-map.ts
|
|
123
|
+
var getStylesPerClassMap = (css) => {
|
|
124
|
+
const map = {};
|
|
125
|
+
for (const [_match, className, contents] of css.matchAll(
|
|
126
|
+
/\s*\.([\S]+)\s*{([^}]*)}/gm
|
|
127
|
+
)) {
|
|
128
|
+
map[className.trim()] = contents.replace(/^\n+/, "").replace(/\n+$/, "").trim();
|
|
108
129
|
}
|
|
109
|
-
return
|
|
110
|
-
}
|
|
130
|
+
return map;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/utils/escape-class-name.ts
|
|
134
|
+
var escapeClassName = (className) => {
|
|
135
|
+
return className.replace(
|
|
136
|
+
/* we need this look ahead capturing group to avoid using negative look behinds */
|
|
137
|
+
/([^\\]|^)(?=([^a-zA-Z0-9\-_]))/g,
|
|
138
|
+
(match, prefixCharacter, characterToEscape) => {
|
|
139
|
+
if (prefixCharacter === "" && characterToEscape === "\\")
|
|
140
|
+
return match;
|
|
141
|
+
return `${prefixCharacter}\\`;
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
};
|
|
111
145
|
|
|
112
146
|
// src/tailwind.tsx
|
|
113
147
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
114
|
-
function processElement(element,
|
|
148
|
+
function processElement(element, nonMediaQueryTailwindStylesPerClass) {
|
|
115
149
|
let modifiedElement = element;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
} else if (twi(className, { ignoreMediaQueries: false }).length > 0) {
|
|
129
|
-
const classPieces = className.split(":");
|
|
130
|
-
const mediaQueryParts = classPieces.slice(0, -1);
|
|
131
|
-
const twClass = classPieces[classPieces.length - 1];
|
|
132
|
-
const importantPrefixedClassName = twClass.startsWith("!") ? className : `${mediaQueryParts.join(":")}:!${twClass}`;
|
|
133
|
-
responsiveClassNames.push(importantPrefixedClassName);
|
|
150
|
+
let resultingClassName = modifiedElement.props.className;
|
|
151
|
+
let resultingStyle = modifiedElement.props.style;
|
|
152
|
+
let resultingChildren = [];
|
|
153
|
+
if (modifiedElement.props.className) {
|
|
154
|
+
const fullClassName = modifiedElement.props.className;
|
|
155
|
+
const classNames = fullClassName.split(" ");
|
|
156
|
+
const classNamesToKeep = [];
|
|
157
|
+
const styles = [];
|
|
158
|
+
classNames.forEach((className) => {
|
|
159
|
+
const escapedClassName = escapeClassName(className);
|
|
160
|
+
if (typeof nonMediaQueryTailwindStylesPerClass[escapedClassName] === "undefined") {
|
|
161
|
+
classNamesToKeep.push(className);
|
|
134
162
|
} else {
|
|
135
|
-
|
|
163
|
+
styles.push(
|
|
164
|
+
`${nonMediaQueryTailwindStylesPerClass[escapedClassName]};`
|
|
165
|
+
);
|
|
136
166
|
}
|
|
137
167
|
});
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
merge: false
|
|
141
|
-
});
|
|
142
|
-
headStyles.push(
|
|
143
|
-
convertedResponsiveStyles.replace(/^\n+/, "").replace(/\n+$/, "")
|
|
144
|
-
);
|
|
145
|
-
modifiedElement = React.cloneElement(modifiedElement, __spreadProps(__spreadValues({}, modifiedElement.props), {
|
|
146
|
-
className: customClassNames.length > 0 || responsiveClassNames.length > 0 ? customClassNames.concat(responsiveClassNames).join(" ") : void 0,
|
|
147
|
-
style: __spreadValues(__spreadValues({}, modifiedElement.props.style), cssToJsxStyle(convertedStyles.join(" ")))
|
|
148
|
-
}));
|
|
168
|
+
resultingStyle = __spreadValues(__spreadValues({}, modifiedElement.props.style), cssToJsxStyle(styles.join(" ")));
|
|
169
|
+
resultingClassName = classNamesToKeep.length > 0 ? classNamesToKeep.join(" ") : void 0;
|
|
149
170
|
}
|
|
150
171
|
if (modifiedElement.props.children) {
|
|
151
|
-
|
|
152
|
-
|
|
172
|
+
resultingChildren = React.Children.toArray(
|
|
173
|
+
modifiedElement.props.children
|
|
174
|
+
).map((child) => {
|
|
153
175
|
if (React.isValidElement(child)) {
|
|
154
|
-
return processElement(child,
|
|
176
|
+
return processElement(child, nonMediaQueryTailwindStylesPerClass);
|
|
155
177
|
}
|
|
156
178
|
return child;
|
|
157
179
|
});
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
180
|
+
}
|
|
181
|
+
modifiedElement = React.cloneElement(
|
|
182
|
+
modifiedElement,
|
|
183
|
+
__spreadValues(__spreadProps(__spreadValues({}, modifiedElement.props), {
|
|
184
|
+
className: resultingClassName
|
|
185
|
+
}), typeof resultingStyle === "undefined" ? {} : { style: resultingStyle }),
|
|
186
|
+
...resultingChildren
|
|
187
|
+
);
|
|
188
|
+
if (typeof modifiedElement.type === "function") {
|
|
189
|
+
const component = modifiedElement.type;
|
|
190
|
+
const renderedComponent = component(modifiedElement.props);
|
|
191
|
+
if (React.isValidElement(renderedComponent)) {
|
|
192
|
+
modifiedElement = processElement(
|
|
193
|
+
renderedComponent,
|
|
194
|
+
nonMediaQueryTailwindStylesPerClass
|
|
195
|
+
);
|
|
196
|
+
}
|
|
163
197
|
}
|
|
164
198
|
return modifiedElement;
|
|
165
199
|
}
|
|
166
|
-
function processHead(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
modifiedChild.props,
|
|
175
|
-
...headChildren
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
if (modifiedChild.props.children) {
|
|
179
|
-
const children = React.Children.toArray(modifiedChild.props.children);
|
|
180
|
-
const processedChildren = children.map((processedChild) => {
|
|
181
|
-
if (React.isValidElement(processedChild)) {
|
|
182
|
-
return processHead(processedChild, responsiveStyles);
|
|
183
|
-
}
|
|
184
|
-
return processedChild;
|
|
185
|
-
});
|
|
186
|
-
modifiedChild = React.cloneElement(
|
|
187
|
-
modifiedChild,
|
|
188
|
-
modifiedChild.props,
|
|
189
|
-
...processedChildren
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
return modifiedChild;
|
|
200
|
+
function processHead(headElement, responsiveStyles) {
|
|
201
|
+
const styleElement = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: minifyCss(responsiveStyles.join("")) });
|
|
202
|
+
return React.cloneElement(
|
|
203
|
+
headElement,
|
|
204
|
+
headElement.props,
|
|
205
|
+
...React.Children.toArray(headElement.props.children),
|
|
206
|
+
styleElement
|
|
207
|
+
);
|
|
193
208
|
}
|
|
194
209
|
var Tailwind = ({ children, config }) => {
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
210
|
+
let headStyles = [];
|
|
211
|
+
const markupWithTailwindClasses = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children }));
|
|
212
|
+
const markupCSS = getCssForMarkup(markupWithTailwindClasses, config);
|
|
213
|
+
const nonMediaQueryCSS = markupCSS.replaceAll(
|
|
214
|
+
/@media\s*\(.*\)\s*{\s*\.(.*)\s*{[\s\S]*}\s*}/gm,
|
|
215
|
+
(mediaQuery, _className) => {
|
|
216
|
+
headStyles.push(
|
|
217
|
+
mediaQuery.replace(/[\r\n|\r|\n]+/g, "").replace(/\s+/g, " ").replaceAll(/\s*\.[\S]+\s*{([^}]*)}/gm, (match, content) => {
|
|
218
|
+
return match.replace(
|
|
219
|
+
content,
|
|
220
|
+
content.split(";").map(
|
|
221
|
+
(propertyDeclaration) => propertyDeclaration.endsWith("!important") ? propertyDeclaration.trim() : `${propertyDeclaration.trim()}!important`
|
|
222
|
+
).join(";")
|
|
223
|
+
);
|
|
224
|
+
})
|
|
225
|
+
);
|
|
226
|
+
return "";
|
|
202
227
|
}
|
|
203
|
-
return child;
|
|
204
|
-
});
|
|
205
|
-
if (!childrenWithInlineStyles)
|
|
206
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
|
|
207
|
-
const fullHTML = (0, import_server.renderToStaticMarkup)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: childrenWithInlineStyles }));
|
|
208
|
-
const hasResponsiveStyles = new RegExp("@media[^{]+\\{(?<content>[\\s\\S]+?)\\}\\s*\\}", "gm").test(
|
|
209
|
-
headStyles.join(" ")
|
|
210
228
|
);
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
229
|
+
const nonMediaQueryTailwindStylesPerClass = getStylesPerClassMap(nonMediaQueryCSS);
|
|
230
|
+
const childrenArray = React.Children.toArray(children);
|
|
231
|
+
const validElementsWithIndexes = childrenArray.map((child, i) => [child, i]).filter(([child]) => React.isValidElement(child));
|
|
232
|
+
let headElementIndex = -1;
|
|
233
|
+
validElementsWithIndexes.forEach(([element, i]) => {
|
|
234
|
+
childrenArray[i] = processElement(
|
|
235
|
+
element,
|
|
236
|
+
nonMediaQueryTailwindStylesPerClass
|
|
215
237
|
);
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
childrenWithInlineStyles,
|
|
219
|
-
(child) => {
|
|
220
|
-
if (React.isValidElement(child)) {
|
|
221
|
-
return processHead(child, headStyles);
|
|
222
|
-
}
|
|
223
|
-
return child;
|
|
238
|
+
if (element.type === "head" || typeof element.type === "function" && "name" in element.type && element.type.name === "Head") {
|
|
239
|
+
headElementIndex = i;
|
|
224
240
|
}
|
|
225
|
-
);
|
|
226
|
-
|
|
241
|
+
});
|
|
242
|
+
headStyles = headStyles.filter((style) => style.trim().length > 0);
|
|
243
|
+
if (headStyles.length > 0) {
|
|
244
|
+
if (headElementIndex === -1) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
"Tailwind: To use responsive styles you must have a <head> element as a direct child of the Tailwind component."
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
const [headElement, headAllElementsIndex] = validElementsWithIndexes[headElementIndex];
|
|
250
|
+
childrenArray[headAllElementsIndex] = processHead(headElement, headStyles);
|
|
251
|
+
}
|
|
252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: childrenArray });
|
|
227
253
|
};
|
|
228
254
|
// Annotate the CommonJS export names for ESM import in node:
|
|
229
255
|
0 && (module.exports = {
|
package/dist/index.mjs
CHANGED
|
@@ -21,7 +21,6 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
|
21
21
|
// src/tailwind.tsx
|
|
22
22
|
import * as React from "react";
|
|
23
23
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
24
|
-
import { tailwindToCSS } from "tw-to-css";
|
|
25
24
|
|
|
26
25
|
// src/utils/css-to-jsx-style.ts
|
|
27
26
|
var camelCase = (string) => string.replace(/-(\w|$)/g, (_, p1) => p1.toUpperCase());
|
|
@@ -35,162 +34,189 @@ var convertPropertyName = (prop) => {
|
|
|
35
34
|
return modifiedProp;
|
|
36
35
|
}
|
|
37
36
|
if (modifiedProp.startsWith("-ms-")) {
|
|
38
|
-
modifiedProp = modifiedProp.
|
|
37
|
+
modifiedProp = modifiedProp.slice(1);
|
|
39
38
|
}
|
|
40
39
|
return camelCase(modifiedProp);
|
|
41
40
|
};
|
|
42
|
-
var
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
capturing = cssText[i];
|
|
51
|
-
} else if (cssText[i] === capturing) {
|
|
52
|
-
capturing = false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
if (!capturing && cssText[i] === ")") {
|
|
56
|
-
capturing = cssText[i];
|
|
57
|
-
}
|
|
58
|
-
if (cssText[i] === "(" && capturing === ")") {
|
|
59
|
-
capturing = false;
|
|
60
|
-
}
|
|
61
|
-
if (i < 0 || !capturing && cssText[i] === ";") {
|
|
62
|
-
declarations.unshift(cssText.slice(i + 1, last));
|
|
63
|
-
last = i;
|
|
41
|
+
var cssToJsxStyle = (cssText) => {
|
|
42
|
+
const style = {};
|
|
43
|
+
const declarations = cssText.matchAll(
|
|
44
|
+
/([a-zA-Z0-9\-_]+)\s*:\s*('[^']*'[^;]*|"[^"]*"[^;]*|.*?\([^)]*\)[^;]*|[^;]*);?/gm
|
|
45
|
+
);
|
|
46
|
+
for (const [_declaration, property, value] of declarations) {
|
|
47
|
+
if (property.length > 0 && value.trim().length > 0) {
|
|
48
|
+
style[convertPropertyName(property)] = value.trim();
|
|
64
49
|
}
|
|
65
50
|
}
|
|
66
|
-
return
|
|
51
|
+
return style;
|
|
67
52
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
53
|
+
|
|
54
|
+
// src/utils/get-css-for-markup.ts
|
|
55
|
+
import postcss from "postcss";
|
|
56
|
+
import tailwindcss from "tailwindcss";
|
|
57
|
+
import postcssCssVariables from "postcss-css-variables";
|
|
58
|
+
global.__OXIDE__ = void 0;
|
|
59
|
+
var getCssForMarkup = (markup, config) => {
|
|
60
|
+
const corePlugins = config == null ? void 0 : config.corePlugins;
|
|
61
|
+
const tailwindConfig = __spreadProps(__spreadValues({}, config), {
|
|
62
|
+
corePlugins: __spreadValues({
|
|
63
|
+
preflight: false
|
|
64
|
+
}, corePlugins)
|
|
65
|
+
});
|
|
66
|
+
const processor = postcss([
|
|
67
|
+
tailwindcss(__spreadProps(__spreadValues({}, tailwindConfig), {
|
|
68
|
+
content: [{ raw: markup, extension: "html" }]
|
|
69
|
+
})),
|
|
70
|
+
postcssCssVariables()
|
|
71
|
+
]);
|
|
72
|
+
const result = processor.process(
|
|
73
|
+
String.raw`
|
|
74
|
+
@tailwind base;
|
|
75
|
+
@tailwind components;
|
|
76
|
+
@tailwind utilities;
|
|
77
|
+
`,
|
|
78
|
+
{ from: void 0 }
|
|
79
|
+
// no need to use from since the `content` context is sent into tailwind
|
|
80
|
+
);
|
|
81
|
+
return result.css;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// src/utils/minify-css.ts
|
|
85
|
+
var minifyCss = (css) => {
|
|
86
|
+
return css.replace(/\/\*[\s\S]*?\*\//gm, "").replace(/;\s+/gm, ";").replace(/:\s+/gm, ":").replace(/\)\s*{/gm, "){").replace(/\s+\(/gm, "(").replace(/{\s+/gm, "{").replace(/}\s+/gm, "}").replace(/\s*{/gm, "{").replace(/;?\s*}/gm, "}");
|
|
71
87
|
};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
88
|
+
|
|
89
|
+
// src/utils/get-css-class-properties-map.ts
|
|
90
|
+
var getStylesPerClassMap = (css) => {
|
|
91
|
+
const map = {};
|
|
92
|
+
for (const [_match, className, contents] of css.matchAll(
|
|
93
|
+
/\s*\.([\S]+)\s*{([^}]*)}/gm
|
|
94
|
+
)) {
|
|
95
|
+
map[className.trim()] = contents.replace(/^\n+/, "").replace(/\n+$/, "").trim();
|
|
75
96
|
}
|
|
76
|
-
return
|
|
77
|
-
}
|
|
97
|
+
return map;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// src/utils/escape-class-name.ts
|
|
101
|
+
var escapeClassName = (className) => {
|
|
102
|
+
return className.replace(
|
|
103
|
+
/* we need this look ahead capturing group to avoid using negative look behinds */
|
|
104
|
+
/([^\\]|^)(?=([^a-zA-Z0-9\-_]))/g,
|
|
105
|
+
(match, prefixCharacter, characterToEscape) => {
|
|
106
|
+
if (prefixCharacter === "" && characterToEscape === "\\")
|
|
107
|
+
return match;
|
|
108
|
+
return `${prefixCharacter}\\`;
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
};
|
|
78
112
|
|
|
79
113
|
// src/tailwind.tsx
|
|
80
114
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
81
|
-
function processElement(element,
|
|
115
|
+
function processElement(element, nonMediaQueryTailwindStylesPerClass) {
|
|
82
116
|
let modifiedElement = element;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
} else if (twi(className, { ignoreMediaQueries: false }).length > 0) {
|
|
96
|
-
const classPieces = className.split(":");
|
|
97
|
-
const mediaQueryParts = classPieces.slice(0, -1);
|
|
98
|
-
const twClass = classPieces[classPieces.length - 1];
|
|
99
|
-
const importantPrefixedClassName = twClass.startsWith("!") ? className : `${mediaQueryParts.join(":")}:!${twClass}`;
|
|
100
|
-
responsiveClassNames.push(importantPrefixedClassName);
|
|
117
|
+
let resultingClassName = modifiedElement.props.className;
|
|
118
|
+
let resultingStyle = modifiedElement.props.style;
|
|
119
|
+
let resultingChildren = [];
|
|
120
|
+
if (modifiedElement.props.className) {
|
|
121
|
+
const fullClassName = modifiedElement.props.className;
|
|
122
|
+
const classNames = fullClassName.split(" ");
|
|
123
|
+
const classNamesToKeep = [];
|
|
124
|
+
const styles = [];
|
|
125
|
+
classNames.forEach((className) => {
|
|
126
|
+
const escapedClassName = escapeClassName(className);
|
|
127
|
+
if (typeof nonMediaQueryTailwindStylesPerClass[escapedClassName] === "undefined") {
|
|
128
|
+
classNamesToKeep.push(className);
|
|
101
129
|
} else {
|
|
102
|
-
|
|
130
|
+
styles.push(
|
|
131
|
+
`${nonMediaQueryTailwindStylesPerClass[escapedClassName]};`
|
|
132
|
+
);
|
|
103
133
|
}
|
|
104
134
|
});
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
merge: false
|
|
108
|
-
});
|
|
109
|
-
headStyles.push(
|
|
110
|
-
convertedResponsiveStyles.replace(/^\n+/, "").replace(/\n+$/, "")
|
|
111
|
-
);
|
|
112
|
-
modifiedElement = React.cloneElement(modifiedElement, __spreadProps(__spreadValues({}, modifiedElement.props), {
|
|
113
|
-
className: customClassNames.length > 0 || responsiveClassNames.length > 0 ? customClassNames.concat(responsiveClassNames).join(" ") : void 0,
|
|
114
|
-
style: __spreadValues(__spreadValues({}, modifiedElement.props.style), cssToJsxStyle(convertedStyles.join(" ")))
|
|
115
|
-
}));
|
|
135
|
+
resultingStyle = __spreadValues(__spreadValues({}, modifiedElement.props.style), cssToJsxStyle(styles.join(" ")));
|
|
136
|
+
resultingClassName = classNamesToKeep.length > 0 ? classNamesToKeep.join(" ") : void 0;
|
|
116
137
|
}
|
|
117
138
|
if (modifiedElement.props.children) {
|
|
118
|
-
|
|
119
|
-
|
|
139
|
+
resultingChildren = React.Children.toArray(
|
|
140
|
+
modifiedElement.props.children
|
|
141
|
+
).map((child) => {
|
|
120
142
|
if (React.isValidElement(child)) {
|
|
121
|
-
return processElement(child,
|
|
143
|
+
return processElement(child, nonMediaQueryTailwindStylesPerClass);
|
|
122
144
|
}
|
|
123
145
|
return child;
|
|
124
146
|
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
147
|
+
}
|
|
148
|
+
modifiedElement = React.cloneElement(
|
|
149
|
+
modifiedElement,
|
|
150
|
+
__spreadValues(__spreadProps(__spreadValues({}, modifiedElement.props), {
|
|
151
|
+
className: resultingClassName
|
|
152
|
+
}), typeof resultingStyle === "undefined" ? {} : { style: resultingStyle }),
|
|
153
|
+
...resultingChildren
|
|
154
|
+
);
|
|
155
|
+
if (typeof modifiedElement.type === "function") {
|
|
156
|
+
const component = modifiedElement.type;
|
|
157
|
+
const renderedComponent = component(modifiedElement.props);
|
|
158
|
+
if (React.isValidElement(renderedComponent)) {
|
|
159
|
+
modifiedElement = processElement(
|
|
160
|
+
renderedComponent,
|
|
161
|
+
nonMediaQueryTailwindStylesPerClass
|
|
162
|
+
);
|
|
163
|
+
}
|
|
130
164
|
}
|
|
131
165
|
return modifiedElement;
|
|
132
166
|
}
|
|
133
|
-
function processHead(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
modifiedChild.props,
|
|
142
|
-
...headChildren
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
if (modifiedChild.props.children) {
|
|
146
|
-
const children = React.Children.toArray(modifiedChild.props.children);
|
|
147
|
-
const processedChildren = children.map((processedChild) => {
|
|
148
|
-
if (React.isValidElement(processedChild)) {
|
|
149
|
-
return processHead(processedChild, responsiveStyles);
|
|
150
|
-
}
|
|
151
|
-
return processedChild;
|
|
152
|
-
});
|
|
153
|
-
modifiedChild = React.cloneElement(
|
|
154
|
-
modifiedChild,
|
|
155
|
-
modifiedChild.props,
|
|
156
|
-
...processedChildren
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
return modifiedChild;
|
|
167
|
+
function processHead(headElement, responsiveStyles) {
|
|
168
|
+
const styleElement = /* @__PURE__ */ jsx("style", { children: minifyCss(responsiveStyles.join("")) });
|
|
169
|
+
return React.cloneElement(
|
|
170
|
+
headElement,
|
|
171
|
+
headElement.props,
|
|
172
|
+
...React.Children.toArray(headElement.props.children),
|
|
173
|
+
styleElement
|
|
174
|
+
);
|
|
160
175
|
}
|
|
161
176
|
var Tailwind = ({ children, config }) => {
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
177
|
+
let headStyles = [];
|
|
178
|
+
const markupWithTailwindClasses = renderToStaticMarkup(/* @__PURE__ */ jsx(Fragment, { children }));
|
|
179
|
+
const markupCSS = getCssForMarkup(markupWithTailwindClasses, config);
|
|
180
|
+
const nonMediaQueryCSS = markupCSS.replaceAll(
|
|
181
|
+
/@media\s*\(.*\)\s*{\s*\.(.*)\s*{[\s\S]*}\s*}/gm,
|
|
182
|
+
(mediaQuery, _className) => {
|
|
183
|
+
headStyles.push(
|
|
184
|
+
mediaQuery.replace(/[\r\n|\r|\n]+/g, "").replace(/\s+/g, " ").replaceAll(/\s*\.[\S]+\s*{([^}]*)}/gm, (match, content) => {
|
|
185
|
+
return match.replace(
|
|
186
|
+
content,
|
|
187
|
+
content.split(";").map(
|
|
188
|
+
(propertyDeclaration) => propertyDeclaration.endsWith("!important") ? propertyDeclaration.trim() : `${propertyDeclaration.trim()}!important`
|
|
189
|
+
).join(";")
|
|
190
|
+
);
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
|
+
return "";
|
|
169
194
|
}
|
|
170
|
-
return child;
|
|
171
|
-
});
|
|
172
|
-
if (!childrenWithInlineStyles)
|
|
173
|
-
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
174
|
-
const fullHTML = renderToStaticMarkup(/* @__PURE__ */ jsx(Fragment, { children: childrenWithInlineStyles }));
|
|
175
|
-
const hasResponsiveStyles = new RegExp("@media[^{]+\\{(?<content>[\\s\\S]+?)\\}\\s*\\}", "gm").test(
|
|
176
|
-
headStyles.join(" ")
|
|
177
195
|
);
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
196
|
+
const nonMediaQueryTailwindStylesPerClass = getStylesPerClassMap(nonMediaQueryCSS);
|
|
197
|
+
const childrenArray = React.Children.toArray(children);
|
|
198
|
+
const validElementsWithIndexes = childrenArray.map((child, i) => [child, i]).filter(([child]) => React.isValidElement(child));
|
|
199
|
+
let headElementIndex = -1;
|
|
200
|
+
validElementsWithIndexes.forEach(([element, i]) => {
|
|
201
|
+
childrenArray[i] = processElement(
|
|
202
|
+
element,
|
|
203
|
+
nonMediaQueryTailwindStylesPerClass
|
|
182
204
|
);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
childrenWithInlineStyles,
|
|
186
|
-
(child) => {
|
|
187
|
-
if (React.isValidElement(child)) {
|
|
188
|
-
return processHead(child, headStyles);
|
|
189
|
-
}
|
|
190
|
-
return child;
|
|
205
|
+
if (element.type === "head" || typeof element.type === "function" && "name" in element.type && element.type.name === "Head") {
|
|
206
|
+
headElementIndex = i;
|
|
191
207
|
}
|
|
192
|
-
);
|
|
193
|
-
|
|
208
|
+
});
|
|
209
|
+
headStyles = headStyles.filter((style) => style.trim().length > 0);
|
|
210
|
+
if (headStyles.length > 0) {
|
|
211
|
+
if (headElementIndex === -1) {
|
|
212
|
+
throw new Error(
|
|
213
|
+
"Tailwind: To use responsive styles you must have a <head> element as a direct child of the Tailwind component."
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
const [headElement, headAllElementsIndex] = validElementsWithIndexes[headElementIndex];
|
|
217
|
+
childrenArray[headAllElementsIndex] = processHead(headElement, headStyles);
|
|
218
|
+
}
|
|
219
|
+
return /* @__PURE__ */ jsx(Fragment, { children: childrenArray });
|
|
194
220
|
};
|
|
195
221
|
export {
|
|
196
222
|
Tailwind
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-email/tailwind",
|
|
3
|
-
"version": "0.0.13-canary.
|
|
3
|
+
"version": "0.0.13-canary.1",
|
|
4
4
|
"description": "A React component to wrap emails with Tailwind CSS",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,9 +44,11 @@
|
|
|
44
44
|
"node": ">=18.0.0"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
+
"postcss": "8.4.31",
|
|
48
|
+
"postcss-css-variables": "0.19.0",
|
|
47
49
|
"react": "18.2.0",
|
|
48
50
|
"react-dom": "18.2.0",
|
|
49
|
-
"
|
|
51
|
+
"tailwindcss": "3.3.2"
|
|
50
52
|
},
|
|
51
53
|
"peerDependencies": {
|
|
52
54
|
"react": "18.2.0"
|
|
@@ -54,11 +56,13 @@
|
|
|
54
56
|
"devDependencies": {
|
|
55
57
|
"@babel/core": "7.21.8",
|
|
56
58
|
"@babel/preset-react": "7.22.5",
|
|
57
|
-
"@react-email/hr": "workspace:*",
|
|
58
59
|
"@react-email/head": "workspace:*",
|
|
60
|
+
"@react-email/hr": "workspace:*",
|
|
59
61
|
"@react-email/html": "workspace:*",
|
|
60
62
|
"@testing-library/react": "14.0.0",
|
|
63
|
+
"@types/postcss-css-variables": "0.18.2",
|
|
61
64
|
"eslint-config-custom": "workspace:*",
|
|
65
|
+
"eslint-plugin-regex": "1.10.0",
|
|
62
66
|
"tsconfig": "workspace:*",
|
|
63
67
|
"typescript": "5.1.6"
|
|
64
68
|
},
|