better-svelte-email 0.1.0 → 0.3.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.
- package/dist/components/Body.svelte +11 -2
- package/dist/components/Button.svelte +2 -4
- package/dist/components/Column.svelte +14 -0
- package/dist/components/Column.svelte.d.ts +7 -0
- package/dist/components/Container.svelte +5 -6
- package/dist/components/Container.svelte.d.ts +2 -2
- package/dist/components/Heading.svelte +34 -0
- package/dist/components/Heading.svelte.d.ts +15 -0
- package/dist/components/Hr.svelte +4 -4
- package/dist/components/Html.svelte +5 -4
- package/dist/components/Html.svelte.d.ts +3 -3
- package/dist/components/Img.svelte +27 -0
- package/dist/components/Img.svelte.d.ts +10 -0
- package/dist/components/Link.svelte +22 -0
- package/dist/components/Link.svelte.d.ts +9 -0
- package/dist/components/Preview.svelte +35 -0
- package/dist/components/Preview.svelte.d.ts +7 -0
- package/dist/components/Row.svelte +26 -0
- package/dist/components/Row.svelte.d.ts +7 -0
- package/dist/components/Section.svelte +11 -3
- package/dist/components/Section.svelte.d.ts +2 -2
- package/dist/components/Text.svelte +4 -6
- package/dist/components/Text.svelte.d.ts +0 -1
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.js +6 -0
- package/dist/emails/apple-receipt.svelte +387 -0
- package/dist/{components/__tests__/test-email.svelte.d.ts → emails/apple-receipt.svelte.d.ts} +6 -14
- package/dist/emails/demo-email.svelte +1 -1
- package/dist/emails/test-email.svelte +4 -2
- package/dist/emails/vercel-invite-user.svelte +136 -0
- package/dist/emails/vercel-invite-user.svelte.d.ts +14 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/preprocessor/index.js +3 -2
- package/dist/preprocessor/transformer.js +3 -3
- package/dist/preview/EmailPreview.svelte +773 -0
- package/dist/preview/EmailPreview.svelte.d.ts +7 -0
- package/dist/preview/index.d.ts +103 -0
- package/dist/preview/index.js +205 -0
- package/dist/utils/index.d.ts +27 -0
- package/dist/utils/index.js +47 -0
- package/package.json +34 -7
- package/dist/components/__tests__/test-email.svelte +0 -13
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PreviewData } from './index.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
emailList: PreviewData;
|
|
4
|
+
};
|
|
5
|
+
declare const EmailPreview: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type EmailPreview = ReturnType<typeof EmailPreview>;
|
|
7
|
+
export default EmailPreview;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { RequestEvent } from '@sveltejs/kit';
|
|
2
|
+
/**
|
|
3
|
+
* Import all Svelte email components file paths.
|
|
4
|
+
* Create a list containing all Svelte email component file names.
|
|
5
|
+
* Return this list to the client.
|
|
6
|
+
*/
|
|
7
|
+
export type PreviewData = {
|
|
8
|
+
files: string[] | null;
|
|
9
|
+
path: string | null;
|
|
10
|
+
};
|
|
11
|
+
type EmailListProps = {
|
|
12
|
+
path?: string;
|
|
13
|
+
root?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Get a list of all email component files in the specified directory.
|
|
17
|
+
*
|
|
18
|
+
* @param options.path - Relative path from root to emails folder (default: '/src/lib/emails')
|
|
19
|
+
* @param options.root - Absolute path to project root (auto-detected if not provided)
|
|
20
|
+
* @returns PreviewData object with list of email files and the path
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* // In a +page.server.ts file
|
|
25
|
+
* import { emailList } from 'better-svelte-email/preview';
|
|
26
|
+
*
|
|
27
|
+
* export function load() {
|
|
28
|
+
* const emails = emailList({
|
|
29
|
+
* root: process.cwd(),
|
|
30
|
+
* path: '/src/lib/emails'
|
|
31
|
+
* });
|
|
32
|
+
* return { emails };
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare const emailList: ({ path: emailPath, root }?: EmailListProps) => PreviewData;
|
|
37
|
+
/**
|
|
38
|
+
* SvelteKit form action to render an email component.
|
|
39
|
+
* Use this with the Preview component to render email templates on demand.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* // +page.server.ts
|
|
44
|
+
* import { createEmail } from 'better-svelte-email/preview';
|
|
45
|
+
*
|
|
46
|
+
* export const actions = createEmail;
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare const createEmail: {
|
|
50
|
+
'create-email': (event: RequestEvent) => Promise<{
|
|
51
|
+
status: number;
|
|
52
|
+
body: {
|
|
53
|
+
error: string;
|
|
54
|
+
};
|
|
55
|
+
error?: undefined;
|
|
56
|
+
} | {
|
|
57
|
+
body: string;
|
|
58
|
+
status?: undefined;
|
|
59
|
+
error?: undefined;
|
|
60
|
+
} | {
|
|
61
|
+
status: number;
|
|
62
|
+
error: {
|
|
63
|
+
message: string;
|
|
64
|
+
};
|
|
65
|
+
body?: undefined;
|
|
66
|
+
}>;
|
|
67
|
+
};
|
|
68
|
+
export declare const SendEmailFunction: ({ from, to, subject, html }: {
|
|
69
|
+
from: string;
|
|
70
|
+
to: string;
|
|
71
|
+
subject: string;
|
|
72
|
+
html: string;
|
|
73
|
+
}, resendApiKey?: string) => Promise<{
|
|
74
|
+
success: boolean;
|
|
75
|
+
error?: any;
|
|
76
|
+
}>;
|
|
77
|
+
/**
|
|
78
|
+
* Sends the email using the submitted form data.
|
|
79
|
+
*
|
|
80
|
+
* @param options.resendApiKey - Your Resend API key (keep this server-side only)
|
|
81
|
+
* @param options.customSendEmailFunction - Optional custom function to send emails
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* // In +page.server.ts
|
|
86
|
+
* import { PRIVATE_RESEND_API_KEY } from '$env/static/private';
|
|
87
|
+
*
|
|
88
|
+
* export const actions = {
|
|
89
|
+
* ...createEmail,
|
|
90
|
+
* ...sendEmail({ resendApiKey: PRIVATE_RESEND_API_KEY })
|
|
91
|
+
* };
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare const sendEmail: ({ customSendEmailFunction, resendApiKey }?: {
|
|
95
|
+
customSendEmailFunction?: typeof SendEmailFunction;
|
|
96
|
+
resendApiKey?: string;
|
|
97
|
+
}) => {
|
|
98
|
+
'send-email': (event: RequestEvent) => Promise<{
|
|
99
|
+
success: boolean;
|
|
100
|
+
error: any;
|
|
101
|
+
}>;
|
|
102
|
+
};
|
|
103
|
+
export { default as EmailPreview } from './EmailPreview.svelte';
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { Resend } from 'resend';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { render } from 'svelte/server';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import prettier from 'prettier/standalone';
|
|
6
|
+
import parserHtml from 'prettier/parser-html';
|
|
7
|
+
/**
|
|
8
|
+
* Get a list of all email component files in the specified directory.
|
|
9
|
+
*
|
|
10
|
+
* @param options.path - Relative path from root to emails folder (default: '/src/lib/emails')
|
|
11
|
+
* @param options.root - Absolute path to project root (auto-detected if not provided)
|
|
12
|
+
* @returns PreviewData object with list of email files and the path
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* // In a +page.server.ts file
|
|
17
|
+
* import { emailList } from 'better-svelte-email/preview';
|
|
18
|
+
*
|
|
19
|
+
* export function load() {
|
|
20
|
+
* const emails = emailList({
|
|
21
|
+
* root: process.cwd(),
|
|
22
|
+
* path: '/src/lib/emails'
|
|
23
|
+
* });
|
|
24
|
+
* return { emails };
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export const emailList = ({ path: emailPath = '/src/lib/emails', root } = {}) => {
|
|
29
|
+
// If root is not provided, try to use process.cwd()
|
|
30
|
+
if (!root) {
|
|
31
|
+
try {
|
|
32
|
+
root = process.cwd();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
throw new Error('Could not determine the root path of your project. Please pass in the root param manually using process.cwd() or an absolute path');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const fullPath = path.join(root, emailPath);
|
|
39
|
+
// Check if directory exists
|
|
40
|
+
if (!fs.existsSync(fullPath)) {
|
|
41
|
+
console.warn(`Email directory not found: ${fullPath}`);
|
|
42
|
+
return { files: null, path: emailPath };
|
|
43
|
+
}
|
|
44
|
+
const files = createEmailComponentList(emailPath, getFiles(fullPath));
|
|
45
|
+
if (!files.length) {
|
|
46
|
+
return { files: null, path: emailPath };
|
|
47
|
+
}
|
|
48
|
+
return { files, path: emailPath };
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* SvelteKit form action to render an email component.
|
|
52
|
+
* Use this with the Preview component to render email templates on demand.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* // +page.server.ts
|
|
57
|
+
* import { createEmail } from 'better-svelte-email/preview';
|
|
58
|
+
*
|
|
59
|
+
* export const actions = createEmail;
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export const createEmail = {
|
|
63
|
+
'create-email': async (event) => {
|
|
64
|
+
try {
|
|
65
|
+
const data = await event.request.formData();
|
|
66
|
+
const file = data.get('file');
|
|
67
|
+
const emailPath = data.get('path');
|
|
68
|
+
if (!file || !emailPath) {
|
|
69
|
+
return {
|
|
70
|
+
status: 400,
|
|
71
|
+
body: { error: 'Missing file or path parameter' }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const getEmailComponent = async () => {
|
|
75
|
+
try {
|
|
76
|
+
// Import the email component dynamically
|
|
77
|
+
return (await import(/* @vite-ignore */ `${emailPath}/${file}.svelte`)).default;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
throw new Error(`Failed to import email component '${file}'. Make sure the file exists and includes the <Head /> component.`);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const emailComponent = await getEmailComponent();
|
|
84
|
+
// Render the component to HTML
|
|
85
|
+
const { body } = render(emailComponent);
|
|
86
|
+
// Remove all HTML comments from the body before formatting
|
|
87
|
+
const bodyWithoutComments = body.replace(/<!--[\s\S]*?-->/g, '');
|
|
88
|
+
const formattedBody = await prettier.format(bodyWithoutComments, {
|
|
89
|
+
parser: 'html',
|
|
90
|
+
plugins: [parserHtml]
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
body: formattedBody
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error('Error rendering email:', error);
|
|
98
|
+
return {
|
|
99
|
+
status: 500,
|
|
100
|
+
error: {
|
|
101
|
+
message: error instanceof Error ? error.message : 'Failed to render email'
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const defaultSendEmailFunction = async ({ from, to, subject, html }, resendApiKey) => {
|
|
108
|
+
// stringify api key to comment out temp
|
|
109
|
+
const resend = new Resend(resendApiKey);
|
|
110
|
+
const email = { from, to, subject, html };
|
|
111
|
+
const resendReq = await resend.emails.send(email);
|
|
112
|
+
if (resendReq.error) {
|
|
113
|
+
return { success: false, error: resendReq.error };
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
return { success: true, error: null };
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Sends the email using the submitted form data.
|
|
121
|
+
*
|
|
122
|
+
* @param options.resendApiKey - Your Resend API key (keep this server-side only)
|
|
123
|
+
* @param options.customSendEmailFunction - Optional custom function to send emails
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* // In +page.server.ts
|
|
128
|
+
* import { PRIVATE_RESEND_API_KEY } from '$env/static/private';
|
|
129
|
+
*
|
|
130
|
+
* export const actions = {
|
|
131
|
+
* ...createEmail,
|
|
132
|
+
* ...sendEmail({ resendApiKey: PRIVATE_RESEND_API_KEY })
|
|
133
|
+
* };
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export const sendEmail = ({ customSendEmailFunction, resendApiKey } = {}) => {
|
|
137
|
+
return {
|
|
138
|
+
'send-email': async (event) => {
|
|
139
|
+
const data = await event.request.formData();
|
|
140
|
+
const email = {
|
|
141
|
+
from: 'svelte-email-tailwind <onboarding@resend.dev>',
|
|
142
|
+
to: `${data.get('to')}`,
|
|
143
|
+
subject: `${data.get('component')} ${data.get('note') ? '| ' + data.get('note') : ''}`,
|
|
144
|
+
html: `${data.get('html')}`
|
|
145
|
+
};
|
|
146
|
+
let sent = { success: false, error: null };
|
|
147
|
+
if (!customSendEmailFunction && resendApiKey) {
|
|
148
|
+
sent = await defaultSendEmailFunction(email, resendApiKey);
|
|
149
|
+
}
|
|
150
|
+
else if (customSendEmailFunction) {
|
|
151
|
+
sent = await customSendEmailFunction(email, resendApiKey);
|
|
152
|
+
}
|
|
153
|
+
else if (!customSendEmailFunction && !resendApiKey) {
|
|
154
|
+
const error = {
|
|
155
|
+
message: 'Resend API key not configured. Please pass your API key to the sendEmail() function in your +page.server.ts file.'
|
|
156
|
+
};
|
|
157
|
+
return { success: false, error };
|
|
158
|
+
}
|
|
159
|
+
if (sent && sent.error) {
|
|
160
|
+
console.log('Error:', sent.error);
|
|
161
|
+
return { success: false, error: sent.error };
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
console.log('Email was sent successfully.');
|
|
165
|
+
return { success: true, error: null };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
// Recursive function to get files
|
|
171
|
+
function getFiles(dir, files = []) {
|
|
172
|
+
// Get an array of all files and directories in the passed directory using fs.readdirSync
|
|
173
|
+
const fileList = fs.readdirSync(dir);
|
|
174
|
+
// Create the full path of the file/directory by concatenating the passed directory and file/directory name
|
|
175
|
+
for (const file of fileList) {
|
|
176
|
+
const name = `${dir}/${file}`;
|
|
177
|
+
// Check if the current file/directory is a directory using fs.statSync
|
|
178
|
+
if (fs.statSync(name).isDirectory()) {
|
|
179
|
+
// If it is a directory, recursively call the getFiles function with the directory path and the files array
|
|
180
|
+
getFiles(name, files);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// If it is a file, push the full path to the files array
|
|
184
|
+
files.push(name);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return files;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Creates an array of names from the record of svelte email component file paths
|
|
191
|
+
*/
|
|
192
|
+
function createEmailComponentList(root, paths) {
|
|
193
|
+
const emailComponentList = [];
|
|
194
|
+
paths.forEach((filePath) => {
|
|
195
|
+
if (filePath.includes(`.svelte`)) {
|
|
196
|
+
const fileName = filePath.substring(filePath.indexOf(root) + root.length + 1, filePath.indexOf('.svelte'));
|
|
197
|
+
emailComponentList.push(fileName);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
return emailComponentList;
|
|
201
|
+
}
|
|
202
|
+
// Export the Preview component
|
|
203
|
+
// Note: The component is available via: import EmailPreview from 'better-svelte-email/preview/EmailPreview.svelte'
|
|
204
|
+
// or: import { EmailPreview } from 'better-svelte-email/preview'
|
|
205
|
+
export { default as EmailPreview } from './EmailPreview.svelte';
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -10,3 +10,30 @@ export declare function styleToString(style: Record<string, string | number | un
|
|
|
10
10
|
* @returns Point value as string
|
|
11
11
|
*/
|
|
12
12
|
export declare function pxToPt(px: string | number): string;
|
|
13
|
+
export type Margin = {
|
|
14
|
+
m?: string;
|
|
15
|
+
mx?: string;
|
|
16
|
+
my?: string;
|
|
17
|
+
mt?: string;
|
|
18
|
+
mr?: string;
|
|
19
|
+
mb?: string;
|
|
20
|
+
ml?: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Convert margin props to a CSS style object
|
|
24
|
+
* @param props - Margin properties object with shorthand notation (m, mx, my, mt, mr, mb, ml)
|
|
25
|
+
* @returns Style object with margin properties in pixels
|
|
26
|
+
*/
|
|
27
|
+
export declare function withMargin(props: Margin): any;
|
|
28
|
+
/**
|
|
29
|
+
* Combine multiple styles into a single string
|
|
30
|
+
* @param styles - Array of style strings
|
|
31
|
+
* @returns Combined style string
|
|
32
|
+
*/
|
|
33
|
+
export declare function combineStyles(...styles: (string | undefined | null)[]): string;
|
|
34
|
+
/**
|
|
35
|
+
* Render HTML as plain text
|
|
36
|
+
* @param markup - HTML string
|
|
37
|
+
* @returns Plain text string
|
|
38
|
+
*/
|
|
39
|
+
export declare const renderAsPlainText: (markup: string) => string;
|
package/dist/utils/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { convert } from 'html-to-text';
|
|
1
2
|
/**
|
|
2
3
|
* Convert a style object to a CSS string
|
|
3
4
|
* @param style - Object containing CSS properties
|
|
@@ -22,3 +23,49 @@ export function pxToPt(px) {
|
|
|
22
23
|
const value = typeof px === 'string' ? parseFloat(px) : px;
|
|
23
24
|
return `${Math.round(value * 0.75)}pt`;
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Convert margin props to a CSS style object
|
|
28
|
+
* @param props - Margin properties object with shorthand notation (m, mx, my, mt, mr, mb, ml)
|
|
29
|
+
* @returns Style object with margin properties in pixels
|
|
30
|
+
*/
|
|
31
|
+
export function withMargin(props) {
|
|
32
|
+
const margins = [
|
|
33
|
+
withSpace(props.m, ['margin']),
|
|
34
|
+
withSpace(props.mx, ['marginLeft', 'marginRight']),
|
|
35
|
+
withSpace(props.my, ['marginTop', 'marginBottom']),
|
|
36
|
+
withSpace(props.mt, ['marginTop']),
|
|
37
|
+
withSpace(props.mr, ['marginRight']),
|
|
38
|
+
withSpace(props.mb, ['marginBottom']),
|
|
39
|
+
withSpace(props.ml, ['marginLeft'])
|
|
40
|
+
];
|
|
41
|
+
return Object.assign({}, ...margins);
|
|
42
|
+
}
|
|
43
|
+
function withSpace(value, properties) {
|
|
44
|
+
return properties.reduce((styles, property) => {
|
|
45
|
+
if (value) {
|
|
46
|
+
return { ...styles, [property]: `${value}px` };
|
|
47
|
+
}
|
|
48
|
+
return styles;
|
|
49
|
+
}, {});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Combine multiple styles into a single string
|
|
53
|
+
* @param styles - Array of style strings
|
|
54
|
+
* @returns Combined style string
|
|
55
|
+
*/
|
|
56
|
+
export function combineStyles(...styles) {
|
|
57
|
+
return styles.filter((style) => style !== '' && style !== undefined && style !== null).join(';');
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Render HTML as plain text
|
|
61
|
+
* @param markup - HTML string
|
|
62
|
+
* @returns Plain text string
|
|
63
|
+
*/
|
|
64
|
+
export const renderAsPlainText = (markup) => {
|
|
65
|
+
return convert(markup, {
|
|
66
|
+
selectors: [
|
|
67
|
+
{ selector: 'img', format: 'skip' },
|
|
68
|
+
{ selector: '#__better-svelte-email-preview', format: 'skip' }
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
};
|
package/package.json
CHANGED
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-svelte-email",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"author": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"author": "Konixy",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/Konixy/better-svelte-email.git"
|
|
8
8
|
},
|
|
9
9
|
"peerDependencies": {
|
|
10
|
-
"svelte": "^5.14.3"
|
|
10
|
+
"svelte": "^5.14.3",
|
|
11
|
+
"@sveltejs/kit": "^2.0.0"
|
|
12
|
+
},
|
|
13
|
+
"peerDependenciesMeta": {
|
|
14
|
+
"@sveltejs/kit": {
|
|
15
|
+
"optional": true
|
|
16
|
+
}
|
|
11
17
|
},
|
|
12
18
|
"dependencies": {
|
|
19
|
+
"html-to-text": "^9.0.5",
|
|
13
20
|
"magic-string": "^0.30.19",
|
|
21
|
+
"svelte-highlight": "^7.8.4",
|
|
14
22
|
"tw-to-css": "^0.0.12"
|
|
15
23
|
},
|
|
24
|
+
"optionalDependencies": {
|
|
25
|
+
"prettier": "^3.6.2",
|
|
26
|
+
"resend": "^6.1.2"
|
|
27
|
+
},
|
|
16
28
|
"devDependencies": {
|
|
17
29
|
"@eslint/compat": "^1.4.0",
|
|
18
30
|
"@eslint/js": "^9.37.0",
|
|
19
31
|
"@sveltejs/adapter-auto": "^6.1.1",
|
|
32
|
+
"@sveltejs/adapter-vercel": "^5.10.3",
|
|
20
33
|
"@sveltejs/kit": "^2.43.8",
|
|
21
34
|
"@sveltejs/package": "^2.5.4",
|
|
22
35
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
23
36
|
"@tailwindcss/vite": "^4.1.14",
|
|
37
|
+
"@types/html-to-text": "^9.0.4",
|
|
24
38
|
"@types/node": "^24",
|
|
25
39
|
"@vitest/browser": "^3.2.4",
|
|
26
40
|
"eslint": "^9.37.0",
|
|
@@ -28,11 +42,9 @@
|
|
|
28
42
|
"eslint-plugin-svelte": "^3.12.4",
|
|
29
43
|
"globals": "^16.4.0",
|
|
30
44
|
"playwright": "^1.55.1",
|
|
31
|
-
"prettier": "^3.6.2",
|
|
32
45
|
"prettier-plugin-svelte": "^3.4.0",
|
|
33
46
|
"prettier-plugin-tailwindcss": "^0.6.14",
|
|
34
47
|
"publint": "^0.3.13",
|
|
35
|
-
"resend": "^6.1.2",
|
|
36
48
|
"svelte": "^5.39.8",
|
|
37
49
|
"svelte-check": "^4.3.2",
|
|
38
50
|
"tailwindcss": "^4.1.14",
|
|
@@ -58,9 +70,23 @@
|
|
|
58
70
|
"types": "./dist/components/*.svelte.d.ts",
|
|
59
71
|
"svelte": "./dist/components/*.svelte"
|
|
60
72
|
},
|
|
73
|
+
"./preview": {
|
|
74
|
+
"types": "./dist/preview/index.d.ts",
|
|
75
|
+
"import": "./dist/preview/index.js",
|
|
76
|
+
"default": "./dist/preview/index.js"
|
|
77
|
+
},
|
|
78
|
+
"./preview/EmailPreview.svelte": {
|
|
79
|
+
"types": "./dist/preview/EmailPreview.svelte.d.ts",
|
|
80
|
+
"svelte": "./dist/preview/EmailPreview.svelte"
|
|
81
|
+
},
|
|
82
|
+
"./utils": {
|
|
83
|
+
"types": "./dist/utils/index.d.ts",
|
|
84
|
+
"import": "./dist/utils/index.js",
|
|
85
|
+
"default": "./dist/utils/index.js"
|
|
86
|
+
},
|
|
61
87
|
"./package.json": "./package.json"
|
|
62
88
|
},
|
|
63
|
-
"description": "
|
|
89
|
+
"description": "Svelte email renderer with Tailwind support",
|
|
64
90
|
"files": [
|
|
65
91
|
"dist",
|
|
66
92
|
"!dist/**/*.test.*",
|
|
@@ -81,8 +107,9 @@
|
|
|
81
107
|
"license": "MIT",
|
|
82
108
|
"scripts": {
|
|
83
109
|
"dev": "vite dev",
|
|
84
|
-
"build": "
|
|
110
|
+
"build": "bun run prepack && vite build",
|
|
85
111
|
"preview": "vite preview",
|
|
112
|
+
"package": "svelte-package",
|
|
86
113
|
"prepare": "svelte-kit sync || echo ''",
|
|
87
114
|
"prepack": "svelte-kit sync && svelte-package && publint",
|
|
88
115
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { Html, Head, Text, Button, Container } from '../index.js';
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<Html>
|
|
6
|
-
<Head />
|
|
7
|
-
<Container class="bg-gray-100 p-8">
|
|
8
|
-
<Text class="text-lg font-bold text-blue-600">Hello World</Text>
|
|
9
|
-
<Button class="rounded bg-blue-500 px-4 py-2 text-white" href="https://example.com">
|
|
10
|
-
Click Me
|
|
11
|
-
</Button>
|
|
12
|
-
</Container>
|
|
13
|
-
</Html>
|