@standhigher/react-email-editor 0.1.0 → 0.2.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/CHANGELOG.md +38 -0
- package/README.md +76 -189
- package/README.zh-CN.md +76 -189
- package/dist/index.d.ts +25 -7
- package/dist/index.js +1983 -1059
- package/dist/styles.css +677 -390
- package/package.json +21 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# 更新日志
|
|
2
|
+
|
|
3
|
+
## 0.2.0 — 2026-10-27
|
|
4
|
+
|
|
5
|
+
### 不兼容变更
|
|
6
|
+
|
|
7
|
+
- 文档格式由 `version: 1` 升为 `version: 2`,旧版本会被拒绝,不提供自动迁移。请使用 `createEmailDocument()` 创建当前版本文档;升级已有数据时,需同时调整区块字段和样式,不能只修改版本号。
|
|
8
|
+
- Heading、Text、Button 的文字格式统一存于 `fields.html`;Button 不再读取 `fields.label` 和 `style.element` 中的文字样式。`EmailElementStyle` 不再继承 `EmailTypographyStyle`。
|
|
9
|
+
- 内置区块按各自能力声明 `styleFields`,不再读取未启用的样式;移除内置区块的 `dimension.height` 和区块级 `typography` 配置。自定义区块仍可显式启用这些字段,`exactStyleFields` 同时约束默认样式、画布和邮件输出。
|
|
10
|
+
- HTML 区块保留源码内部的段落、列表、链接和显式样式,不再注入正文排版;未声明的属性仍可继承全局样式。
|
|
11
|
+
|
|
12
|
+
### 新增与改进
|
|
13
|
+
|
|
14
|
+
- Button 支持画布内富文本编辑,采用单段内容,粘贴多段时以空格连接;邮件输出保留基础行内格式,并只生成一个按钮外层链接。
|
|
15
|
+
- 新增 `BlockInspectorSection`、`inspectorSections`、`RichTextProfile` 和 `inlineEditProfile`,支持自定义检查器分组与富文本编辑能力;独立 `RichText` 支持 `profile`。
|
|
16
|
+
- 统一颜色面板、HEX 输入和颜色重置;链接编辑改为居中弹窗,支持颜色、下划线和打开方式。
|
|
17
|
+
- 优化区块操作栏、拖拽反馈、三栏布局、工具栏换行和预览高度;预览跟随文档内容展示。
|
|
18
|
+
- 按钮默认填充改为黑色,按钮和图片的链接默认为空,空白链接不生成跳转;全局内容、区块、按钮和图片边框默认透明。
|
|
19
|
+
- 精简中英文 README,补充 npm keywords,发布包包含中文 README 和更新日志。
|
|
20
|
+
|
|
21
|
+
### 修复与验证
|
|
22
|
+
|
|
23
|
+
- 修复富文本格式操作后的光标、选区和格式保留,以及列表切换时的间距和缩进保留。
|
|
24
|
+
- 修复按钮导出对模板表达式中引号、比较符、注释和空格的处理。
|
|
25
|
+
- 接入 Oxlint,补充区块配置、富文本、列表、按钮和颜色转换回归测试。
|
|
26
|
+
|
|
27
|
+
## 0.1.0 — 2026-10-27
|
|
28
|
+
|
|
29
|
+
首个正式发布版本(对应提交 `48011d9`)。
|
|
30
|
+
|
|
31
|
+
- 提供 React 18 编辑器、拖拽区块、富文本编辑、检查器及桌面/移动预览。
|
|
32
|
+
- 支持 JSON 文档、全局和区块样式、HTML 源码编辑、自定义区块与 Go template 预览。
|
|
33
|
+
- 提供组件 ref 数据读取、独立 HTML 渲染、ESM、TypeScript 类型和独立 CSS 入口。
|
|
34
|
+
- 提供 Vite playground、构建和本地 link 联调流程。
|
|
35
|
+
|
|
36
|
+
## 0.0.0-stage — 2026-10-27
|
|
37
|
+
|
|
38
|
+
- 发布前的包分发验证版本。
|
package/README.md
CHANGED
|
@@ -2,244 +2,131 @@
|
|
|
2
2
|
|
|
3
3
|
English | [简体中文](./README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
A React email editor with drag-and-drop blocks, inline rich text,
|
|
5
|
+
A React email template editor with drag-and-drop blocks, inline rich text, desktop/mobile previews, JSON storage, and HTML export.
|
|
6
6
|
|
|
7
|
-
## Installation
|
|
7
|
+
## Installation
|
|
8
8
|
|
|
9
|
-
Requires React 18 and React DOM 18.
|
|
9
|
+
Requires React 18 and React DOM 18. Includes ESM and TypeScript declarations.
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
pnpm add @standhigher/react-email-editor
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
Import the stylesheet once in your application and use a ref to read the document and HTML. Your application handles persistence.
|
|
16
18
|
|
|
17
19
|
```tsx
|
|
18
20
|
import { useRef } from "react";
|
|
19
21
|
import {
|
|
22
|
+
BLOCK_TYPES,
|
|
20
23
|
EmailEditor,
|
|
24
|
+
createBlockNode,
|
|
25
|
+
createEmailDocument,
|
|
21
26
|
type EmailEditorHandle,
|
|
27
|
+
type Variable,
|
|
22
28
|
} from "@standhigher/react-email-editor";
|
|
23
29
|
import "@standhigher/react-email-editor/styles.css";
|
|
24
30
|
|
|
31
|
+
const text = createBlockNode(BLOCK_TYPES.text);
|
|
32
|
+
if (text) text.fields.html = "<p>Hello, {{ store_name }}</p>";
|
|
33
|
+
const initialDocument = createEmailDocument(text ? [text] : []);
|
|
34
|
+
const variables: Variable[] = [
|
|
35
|
+
{ name: "{{ store_name }}", description: "Store name", value: "Example Store" },
|
|
36
|
+
];
|
|
37
|
+
|
|
25
38
|
export function EmailPage() {
|
|
26
39
|
const editorRef = useRef<EmailEditorHandle>(null);
|
|
27
40
|
|
|
28
|
-
function
|
|
41
|
+
function save() {
|
|
29
42
|
const data = editorRef.current?.getData();
|
|
30
43
|
if (!data) return;
|
|
31
|
-
//
|
|
32
|
-
// to your application's save or export handler.
|
|
44
|
+
// Persist data.document in your app; use data.html to export the template.
|
|
33
45
|
console.log(data);
|
|
34
46
|
}
|
|
35
47
|
|
|
36
48
|
return (
|
|
37
49
|
<>
|
|
38
|
-
<EmailEditor
|
|
39
|
-
|
|
50
|
+
<EmailEditor
|
|
51
|
+
ref={editorRef}
|
|
52
|
+
initialDocument={initialDocument}
|
|
53
|
+
variables={variables}
|
|
54
|
+
height={720}
|
|
55
|
+
/>
|
|
56
|
+
<button type="button" onClick={save}>Save</button>
|
|
40
57
|
</>
|
|
41
58
|
);
|
|
42
59
|
}
|
|
43
60
|
```
|
|
44
61
|
|
|
45
|
-
|
|
62
|
+
Omit `initialDocument` to start empty. In Next.js App Router, add `"use client"` to the integration component and import CSS from an allowed global stylesheet entry. When using `height="100%"`, give the parent a definite height.
|
|
46
63
|
|
|
47
|
-
##
|
|
48
|
-
|
|
49
|
-
Use pnpm and a current Node.js LTS release; Node.js 22.18+ is recommended for the repository's tooling and TypeScript tests.
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
pnpm install --frozen-lockfile
|
|
53
|
-
pnpm dev
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Open [http://localhost:5173](http://localhost:5173). The playground loads `src/` directly with hot reload; no initial build is needed. It is not included in the published package. Reuse an existing development server when one is already running.
|
|
57
|
-
|
|
58
|
-
| Command | Purpose |
|
|
59
|
-
| --- | --- |
|
|
60
|
-
| `pnpm dev` | Start the local playground on port 5173. |
|
|
61
|
-
| `pnpm build` | Generate ESM, type declarations, and CSS in `dist/`. |
|
|
62
|
-
| `pnpm build:watch` | Rebuild `dist/` when files in `src/` change; does not start a preview server. |
|
|
63
|
-
| `pnpm typecheck` | Type-check the library and playground. |
|
|
64
|
+
## Props
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
All props are optional.
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
{
|
|
69
|
-
"dependencies": {
|
|
70
|
-
"@standhigher/react-email-editor": "link:../react-email-editor"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Run `pnpm build` in this repository first, then keep `pnpm build:watch` running during development. In the consuming project, run `pnpm install` and use its development server. Package imports, including CSS, resolve to `dist/`.
|
|
76
|
-
|
|
77
|
-
Both projects must resolve the same React instance. For Vite consumers, use `resolve.dedupe: ["react", "react-dom"]` if needed. Next.js consumers can use `transpilePackages: ["@standhigher/react-email-editor"]`; when an external link is used with Turbopack, `turbopack.root` must include both projects.
|
|
78
|
-
|
|
79
|
-
## Component props
|
|
80
|
-
|
|
81
|
-
All props are optional. Types are exported from `@standhigher/react-email-editor`.
|
|
82
|
-
|
|
83
|
-
| Prop | Type | Default / behavior |
|
|
68
|
+
| Prop | Type | Behavior |
|
|
84
69
|
| --- | --- | --- |
|
|
85
|
-
| `initialDocument` | `EmailDocument` |
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `variables` | `Variable[]` |
|
|
89
|
-
| `
|
|
90
|
-
| `onChange` | `(document: EmailDocument) => void` | Called
|
|
91
|
-
| `onGlobalChange` | `(global: EmailGlobalSettings) => void` | Called
|
|
92
|
-
|
|
93
|
-
Reset restores the initial document snapshot and reapplies the current `global` overrides. To load a different document, remount with a new React `key`, for example `<EmailEditor key={documentId} initialDocument={document} />`. Changing `initialDocument` alone does not replace the open document. Omitting a previously supplied `global` field does not restore its default.
|
|
70
|
+
| `initialDocument` | `EmailDocument` | Read on first mount only. Remount with a new React `key` to switch documents. |
|
|
71
|
+
| `height` | `number \| string` | Defaults to `"100%"`; numbers are pixels. |
|
|
72
|
+
| `global` | `Partial<EmailGlobalSettings>` | Overrides global styles; later changes merge into the current document. Omitting a field does not restore its default. |
|
|
73
|
+
| `variables` | `Variable[]` | Variables for insertion and preview. Defaults to `[]`; Personalization controls are hidden when empty. |
|
|
74
|
+
| `blocks` | `BlockDefinition[]` | Adds custom blocks; matching types replace built-in definitions. |
|
|
75
|
+
| `onChange` | `(document: EmailDocument) => void` | Called on document changes, including external `global` updates that change document values. |
|
|
76
|
+
| `onGlobalChange` | `(global: EmailGlobalSettings) => void` | Called for global style edits inside the editor, excluding external `global` updates. |
|
|
94
77
|
|
|
95
|
-
|
|
78
|
+
Global style example: `global={{ contentWidth: 640, outerPadding: "24px" }}`. Defaults are exported as `DEFAULT_EMAIL_GLOBAL`.
|
|
96
79
|
|
|
97
|
-
|
|
80
|
+
Built-in blocks: `heading`, `text`, `button`, `image`, `divider`, `spacer`, and `html`, available through `BLOCK_TYPES`.
|
|
98
81
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```tsx
|
|
102
|
-
import {
|
|
103
|
-
BLOCK_TYPES,
|
|
104
|
-
EmailEditor,
|
|
105
|
-
createBlockNode,
|
|
106
|
-
createEmailDocument,
|
|
107
|
-
type Variable,
|
|
108
|
-
} from "@standhigher/react-email-editor";
|
|
82
|
+
## Save and export
|
|
109
83
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
Pass both `initialDocument` and `variables` as shown so the token has a preview value and can gain its missing dot on export. `createBlockNode()` returns `null` for an unknown block type. Built-in types are `heading`, `text`, `button`, `image`, `divider`, `spacer`, and `html`, also available through `BLOCK_TYPES`.
|
|
132
|
-
|
|
133
|
-
| Document field | Type | Description |
|
|
134
|
-
| --- | --- | --- |
|
|
135
|
-
| `version` | `typeof DOCUMENT_VERSION` | Current version: `1`. Set by `createEmailDocument()`. |
|
|
136
|
-
| `subject` | `string` (optional) | Email subject. The editor input is limited to 128 characters. |
|
|
137
|
-
| `global` | `EmailGlobalSettings` | Global email appearance; defaults are populated by the helper. |
|
|
138
|
-
| `blocks` | `EmailBlockNode[]` | Ordered nodes, each with a unique `id`, a `type`, and `fields`, plus optional `style` and preview `defaultData`. |
|
|
139
|
-
|
|
140
|
-
The document format is under development; older block fields are not migrated automatically. See the [document types](./src/types/document.ts) for the full model.
|
|
141
|
-
|
|
142
|
-
### Global styles
|
|
143
|
-
|
|
144
|
-
Pass partial settings through `global`, for example `<EmailEditor global={{ contentWidth: 640, outerPadding: "24px" }} />`. `DEFAULT_EMAIL_GLOBAL` exposes all defaults; `resolveEmailGlobal()` fills missing values and normalizes input.
|
|
145
|
-
|
|
146
|
-
These settings control email content. Editor selection outlines and toolbars are not included in exported HTML.
|
|
147
|
-
|
|
148
|
-
| Parameter | Type / values | Default | Description |
|
|
149
|
-
| --- | --- | --- | --- |
|
|
150
|
-
| `contentWidth` | `number` | `600` | Content width in pixels, rounded and clamped to 320–900. |
|
|
151
|
-
| `contentAlign` | `"left" \| "center" \| "right"` | `"center"` | Horizontal position of the content. |
|
|
152
|
-
| `backgroundColor` | `string` | `"#ffffff"` | Outer email background. |
|
|
153
|
-
| `contentBackgroundColor` | `string` | `"#ffffff"` | Content background. |
|
|
154
|
-
| `contentPadding` | `string` | `"0px"` | Content inner spacing. |
|
|
155
|
-
| `outerPadding` | `string` | `"0px"` | Spacing outside the content. |
|
|
156
|
-
| `blockGap` | `string` | `"4px"` | Gap between blocks. |
|
|
157
|
-
| `textColor` | `string` | `"#000000"` | Default text color. |
|
|
158
|
-
| `textAlign` | `"left" \| "center" \| "right" \| "justify"` | `"left"` | Default text alignment. |
|
|
159
|
-
| `fontFamily` | `string` | `"Arial, Helvetica, sans-serif"` | Default font stack. |
|
|
160
|
-
| `fontWeight` | `"normal" \| "bold"` | `"normal"` | Default font weight. |
|
|
161
|
-
| `defaultFontSize` | `string` | `"16px"` | Default font size. |
|
|
162
|
-
| `defaultLineHeight` | `string` | `"1.5"` | Default line height. |
|
|
163
|
-
| `paragraphSpacing` | `string` | `"6px"` | Gap between adjacent top-level paragraphs. |
|
|
164
|
-
| `listSpacing` | `string` | `"4px"` | Top and bottom margins of the entire list (`ul` / `ol`). |
|
|
165
|
-
| `listIndent` | `string` | `"22px"` | List indentation. |
|
|
166
|
-
| `linkColor` | `string` | `"#005bd3"` | Default link color. |
|
|
167
|
-
| `linkDecoration` | `"underline" \| "none"` | `"underline"` | Default link decoration. |
|
|
168
|
-
| `borderWidth` | `string` | `"0px"` | Content border width. |
|
|
169
|
-
| `borderStyle` | `"none" \| "solid" \| "dashed" \| "dotted"` | `"solid"` | Content border style. |
|
|
170
|
-
| `borderColor` | `string` | `"#000000"` | Content border color. |
|
|
171
|
-
| `borderRadius` | `string` | `"0px"` | One radius or four, ordered top-left, top-right, bottom-right, bottom-left. |
|
|
172
|
-
|
|
173
|
-
Use CSS length strings such as `"16px"` for spacing and sizes. Padding accepts shorthand such as `"12px 24px"`; line height also accepts a unitless value. Desktop canvas and preview follow `contentWidth`; mobile uses a 360px viewport.
|
|
174
|
-
|
|
175
|
-
Global spacing and length settings accept non-negative values in `px`, `em`, `rem`, or `%`; unitless lengths are normalized to px, except for line height. Unsupported values such as negative lengths, `calc()`, `var()`, `vh`, or `vw` fall back to the corresponding global default.
|
|
176
|
-
|
|
177
|
-
### Variables and template data
|
|
178
|
-
|
|
179
|
-
```tsx
|
|
180
|
-
import type { Variable } from "@standhigher/react-email-editor";
|
|
181
|
-
|
|
182
|
-
export const variables: Variable[] = [
|
|
183
|
-
{ name: "{{ store_name }}", description: "Store name", value: "Demo Store" },
|
|
184
|
-
];
|
|
84
|
+
| Ref method | Returns |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `getData()` | `{ document, json, html, renderedHtml }` |
|
|
87
|
+
| `getDocument()` | An independent `EmailDocument` snapshot to persist and pass back as `initialDocument`. |
|
|
88
|
+
| `getJson()` | A formatted document JSON string. |
|
|
89
|
+
| `getHtml()` | A complete email HTML document preserving template expressions. |
|
|
90
|
+
| `getRenderedHtml()` | A complete email HTML document with templates resolved using preview data. |
|
|
91
|
+
|
|
92
|
+
Render a document without mounting the editor:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { documentToHtml } from "@standhigher/react-email-editor";
|
|
96
|
+
|
|
97
|
+
const html = documentToHtml(initialDocument, undefined, { variables });
|
|
98
|
+
const previewHtml = documentToHtml(initialDocument, undefined, {
|
|
99
|
+
variables,
|
|
100
|
+
resolveHtmlTemplates: true,
|
|
101
|
+
});
|
|
185
102
|
```
|
|
186
103
|
|
|
187
|
-
|
|
104
|
+
A variable's `name` is inserted verbatim; `description` and preview `value` are optional. Export adds a missing dot only to tokens matching `variables[].name` exactly, preserving whitespace: `{{ store_name }}` → `{{ .store_name }}`. Other Go template expressions remain unchanged. Preview supports a subset of Go template syntax; data precedence is block `defaultData` > `templateData` (`documentToHtml` option) > `variables`.
|
|
188
105
|
|
|
189
|
-
|
|
190
|
-
| --- | --- | --- |
|
|
191
|
-
| `name` | `string` | Required. Token displayed and inserted as written, including spaces. Example: `{{ store_name }}`. |
|
|
192
|
-
| `description` | `string` (optional) | Secondary text in the variable menu; omitted when empty or absent. |
|
|
193
|
-
| `value` | `string` (optional) | Replacement text used in previews. |
|
|
194
|
-
|
|
195
|
-
Tokens may include a leading dot. Template HTML export preserves spaces and adds a missing dot only when the token exactly matches `variables[].name`, including spaces: `{{ store_name }}` becomes `{{ .store_name }}`. Other Go template actions are left unchanged. Export does not substitute preview values by default.
|
|
196
|
-
|
|
197
|
-
Use a block node's `defaultData: Record<string, unknown>` for structured preview data, including arrays for `{{range .products}}`. Block data overrides variables with the same name. Preview resolution applies to every block's rendered HTML, including custom blocks. Write template expressions directly in an HTML block's `fields.html`; the preview renderer supports a subset of Go template syntax.
|
|
106
|
+
The document format is under development. Only `version: 2` is accepted, with no automatic migration of older documents. Create data with `createEmailDocument()` and `createBlockNode()`. See [CHANGELOG](./CHANGELOG.md) for upgrade notes.
|
|
198
107
|
|
|
199
|
-
|
|
108
|
+
## Custom blocks
|
|
200
109
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
| Style group | Purpose |
|
|
204
|
-
| --- | --- |
|
|
205
|
-
| `style.dimension` | Container `padding`, outer spacing via `margin`, and optional `height` in px. Height acts as a minimum including padding. |
|
|
206
|
-
| `style.decorations` | Container background, border, and corner radius. |
|
|
207
|
-
| `style.typography` | Block text styles overriding global typography. |
|
|
208
|
-
| `style.element` | Element-specific styles for buttons, images, and dividers, such as size and alignment. |
|
|
110
|
+
Pass `BlockDefinition[]` through `blocks`. Required fields are `type`, `title`, and `render(ctx)`, which returns HTML. Use `fields` / `styleFields` for inspector controls and `defaultFields` / `defaultStyle` / `defaultData` for initial values. The render context includes `mode: "canvas" | "email"`.
|
|
209
111
|
|
|
210
|
-
|
|
112
|
+
Built-in text formatting lives in `fields.html`, container styles in `style.dimension` / `style.decorations`, and button, image, and divider element styles in `style.element`. Rendering uses only enabled style fields. See [BlockDefinition](https://github.com/standhigher/react-email-editor/blob/main/src/types/block.ts) and [EmailDocument](https://github.com/standhigher/react-email-editor/blob/main/src/types/document.ts) for full types. When calling `documentToHtml` directly, pass the complete definition list including custom blocks as its second argument.
|
|
211
113
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
```tsx
|
|
215
|
-
import { EmailEditor, type BlockDefinition } from "@standhigher/react-email-editor";
|
|
114
|
+
## Local development
|
|
216
115
|
|
|
217
|
-
|
|
218
|
-
type: "notice",
|
|
219
|
-
title: "Notice",
|
|
220
|
-
defaultStyle: { dimension: { padding: "16px" } },
|
|
221
|
-
render: () => '<p style="margin:0;color:#555555;">Thanks for subscribing.</p>',
|
|
222
|
-
}];
|
|
116
|
+
Node.js 22.18+ and pnpm are recommended:
|
|
223
117
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
118
|
+
```bash
|
|
119
|
+
pnpm install --frozen-lockfile
|
|
120
|
+
pnpm dev
|
|
227
121
|
```
|
|
228
122
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
## Reading and exporting data
|
|
232
|
-
|
|
233
|
-
Call these methods through `useRef<EmailEditorHandle>(null)`:
|
|
123
|
+
Open [http://localhost:5173](http://localhost:5173). The playground loads `src/` directly; reuse an existing server. Validation:
|
|
234
124
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
| `getRenderedHtml()` | `string` | Complete email HTML with templates resolved using variables and block preview data. |
|
|
242
|
-
|
|
243
|
-
Mutating a returned document snapshot does not change the editor. Use `onChange` to subscribe to document changes.
|
|
125
|
+
```bash
|
|
126
|
+
pnpm typecheck
|
|
127
|
+
pnpm lint
|
|
128
|
+
pnpm build
|
|
129
|
+
node --test tests/*.test.mjs tests/*.test.ts
|
|
130
|
+
```
|
|
244
131
|
|
|
245
|
-
For
|
|
132
|
+
For local consumers, use `link:../react-email-editor`, run `pnpm build` first, and keep `pnpm build:watch` running to update `dist/`. Both projects must share one React instance. Vite can use `resolve.dedupe: ["react", "react-dom"]`; Next.js can use `transpilePackages: ["@standhigher/react-email-editor"]`, with Turbopack's `root` covering the linked directory.
|