mail-editor-pancake 0.2.0 → 0.2.2
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/README.md +177 -17
- package/package.json +1 -1
- package/packages/blocks/dist/index.js +168 -154
- package/packages/blocks/dist/index.js.map +1 -1
- package/packages/blocks/src/i18n.ts +31 -1
- package/packages/core/dist/index.d.ts +59 -4
- package/packages/core/dist/index.js +1517 -1470
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/style.css +1 -1
- package/packages/core/src/editor/Editor.ts +1 -1
- package/packages/core/src/editor/ImageGalleryModal.ts +135 -83
- package/packages/core/src/editor/RightPanel.ts +30 -15
- package/packages/core/src/editor/imageAssets.ts +65 -3
- package/packages/core/src/editor/styles.css +15 -0
- package/packages/core/src/i18n/index.ts +10 -2
- package/packages/core/src/index.ts +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/icons.ts","../src/button.ts","../src/divider.ts","../src/footer.ts","../src/hero.ts","../src/html.ts","../src/image.ts","../src/logo.ts","../src/socialShared.ts","../src/social.ts","../src/socialGroup.ts","../src/spacer.ts","../src/text.ts","../src/i18n.ts","../src/index.ts"],"sourcesContent":["/** 24x24 viewBox 的内置组件图标。集中放,避免散落到各 block 文件。 */\nexport const icons = {\n html: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\"><rect x=\"3.5\" y=\"4\" width=\"17\" height=\"16\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><path d=\"M8 8.5l3 3.5-3 3.5M16 8.5l-3 3.5 3 3.5\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`,\n text: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M5 6h14M5 10h14M5 14h10M5 18h8\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" fill=\"none\"/></svg>`,\n image: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><rect x=\"3.5\" y=\"5\" width=\"17\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\"/><circle cx=\"9\" cy=\"10\" r=\"1.5\" fill=\"currentColor\"/><path d=\"M4 18l5-5 4 4 3-3 4 4\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`,\n hero: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"6\" width=\"18\" height=\"12\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><path d=\"M6 14h5M6 17h8\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/></svg>`,\n button: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"8\" rx=\"4\" fill=\"currentColor\" opacity=\"0.75\"/></svg>`,\n divider: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M3 12h18\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/></svg>`,\n spacer: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M5 8h14M5 16h14\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/><path d=\"M12 9v6\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/><path d=\"M9 12l3-3 3 3M9 12l3 3 3-3\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linejoin=\"round\"/></svg>`,\n logo: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M5 18V6l7 6 7-6v12\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linejoin=\"round\"/></svg>`,\n social: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><circle cx=\"6\" cy=\"12\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><circle cx=\"18\" cy=\"12\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/></svg>`,\n footer: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><rect x=\"3.5\" y=\"5\" width=\"17\" height=\"10\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><path d=\"M5 18h14\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/></svg>`,\n socialGroup: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/><circle cx=\"8\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.4\"/><circle cx=\"12\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.4\"/><circle cx=\"16\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.4\"/></svg>`,\n};\n","import { defineBlock, blockButtonWidthCss } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface ButtonProps {\n text: string;\n href: string;\n backgroundColor: string;\n color: string;\n borderRadius: number;\n align: 'left' | 'center' | 'right';\n /** 留空或 auto 为自适应;可填 200px、80% 等 */\n width: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n innerPaddingV: number;\n innerPaddingH: number;\n fontSize: string;\n}\n\nconst escapeAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const buttonBlock = defineBlock<ButtonProps>({\n type: 'button',\n name: '按钮',\n category: 'content',\n icon: icons.button,\n defaultProps: {\n text: '立即查看',\n href: 'https://example.com',\n backgroundColor: '#4f46e5',\n color: '#ffffff',\n borderRadius: 6,\n align: 'center',\n width: '',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n innerPaddingV: 12,\n innerPaddingH: 24,\n fontSize: '14px',\n },\n schema: [\n { key: 'text', label: '文字', type: 'text' },\n { key: 'href', label: '链接', type: 'url' },\n { key: 'backgroundColor', label: '背景色', type: 'color' },\n { key: 'color', label: '文字颜色', type: 'color' },\n { key: 'borderRadius', label: '圆角 (px)', type: 'number', min: 0, max: 40 },\n { key: 'fontSize', label: '字号', type: 'text' },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n {\n key: 'width',\n label: '宽度',\n type: 'text',\n placeholder: '留空=自适应,如 280px、100%',\n help: '支持纯数字(按 px)、带 px 或百分比',\n },\n { key: 'innerPaddingV', label: '按钮内上下边距', type: 'number', min: 0, max: 40 },\n { key: 'innerPaddingH', label: '按钮内左右边距', type: 'number', min: 0, max: 60 },\n { key: 'paddingTop', label: '外边距', type: 'spacing' },\n ],\n inlineEditable: {\n selector: '.sm-button-text',\n mode: 'plain',\n multiline: false,\n propKey: 'text',\n placeholder: '按钮文字',\n },\n toMjml: (p) => {\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const innerPadding = `${p.innerPaddingV}px ${p.innerPaddingH}px`;\n const bw = blockButtonWidthCss(p.width);\n const widthAttr = bw ? ` width=\"${escapeAttr(bw)}\"` : '';\n return `<mj-button href=\"${escapeAttr(p.href)}\" background-color=\"${escapeAttr(\n p.backgroundColor,\n )}\" color=\"${escapeAttr(p.color)}\" border-radius=\"${p.borderRadius}px\" font-size=\"${escapeAttr(\n p.fontSize,\n )}\" align=\"${p.align}\" padding=\"${padding}\" inner-padding=\"${innerPadding}\"${widthAttr}>${escapeAttr(\n p.text,\n )}</mj-button>`;\n },\n renderPreview: (p) => {\n const bw = blockButtonWidthCss(p.width);\n const wst = bw ? `width:${bw};max-width:100%;box-sizing:border-box;` : '';\n /* 画布对 .sm-canvas a 设置了带 !important 的链接色,文字颜色必须写在子节点上才能生效 */\n return `<div style=\"padding:${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px;text-align:${p.align};\">\n <a href=\"${escapeAttr(p.href)}\" style=\"display:inline-block;background:${\n p.backgroundColor\n };border-radius:${p.borderRadius}px;padding:${p.innerPaddingV}px ${\n p.innerPaddingH\n }px;text-decoration:none;font-size:${p.fontSize};line-height:1.2;${wst}\"><span class=\"sm-button-text\" style=\"color:${\n p.color\n }\">${escapeAttr(p.text)}</span></a>\n </div>`;\n },\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface DividerProps {\n color: string;\n width: string;\n thickness: number;\n paddingTop: number;\n paddingBottom: number;\n}\n\nconst esc = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const dividerBlock = defineBlock<DividerProps>({\n type: 'divider',\n name: '分隔线',\n category: 'content',\n icon: icons.divider,\n defaultProps: {\n color: '#e6e8ec',\n width: '100%',\n thickness: 1,\n paddingTop: 8,\n paddingBottom: 8,\n },\n schema: [\n { key: 'color', label: '颜色', type: 'color' },\n { key: 'width', label: '宽度 (% 或 px)', type: 'text' },\n { key: 'thickness', label: '粗细 (px)', type: 'number', min: 1, max: 10 },\n { key: 'paddingTop', label: '上边距', type: 'number', min: 0, max: 80 },\n { key: 'paddingBottom', label: '下边距', type: 'number', min: 0, max: 80 },\n ],\n toMjml: (p) =>\n `<mj-divider border-color=\"${esc(p.color)}\" border-width=\"${p.thickness}px\" width=\"${esc(\n p.width,\n )}\" padding=\"${p.paddingTop}px 0px ${p.paddingBottom}px 0px\" />`,\n renderPreview: (p) =>\n `<div style=\"padding:${p.paddingTop}px 0 ${p.paddingBottom}px 0;\"><div style=\"border-top:${p.thickness}px solid ${p.color};width:${p.width};margin:0 auto;\"></div></div>`,\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface FooterProps {\n companyName: string;\n address: string;\n unsubscribeText: string;\n unsubscribeHref: string;\n textColor: string;\n}\n\nconst esc = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const footerBlock = defineBlock<FooterProps>({\n type: 'custom:footer',\n name: '页脚',\n category: 'custom',\n icon: icons.footer,\n defaultProps: {\n companyName: '你的公司',\n address: '上海市某区某路某号',\n unsubscribeText: '退订邮件',\n unsubscribeHref: '{{unsubscribeUrl}}',\n textColor: '#9aa0a6',\n },\n schema: [\n { key: 'companyName', label: '公司名称', type: 'text' },\n { key: 'address', label: '地址', type: 'text' },\n { key: 'unsubscribeText', label: '退订文案', type: 'text' },\n { key: 'unsubscribeHref', label: '退订链接', type: 'url' },\n { key: 'textColor', label: '文字颜色', type: 'color' },\n ],\n toMjml: (p) => {\n return `<mj-text align=\"center\" color=\"${esc(p.textColor)}\" font-size=\"12px\" line-height=\"1.6\" padding=\"8px 0px 8px 0px\">\n ${esc(p.companyName)}<br />\n ${esc(p.address)}<br />\n <a href=\"${esc(p.unsubscribeHref)}\" style=\"color:${esc(p.textColor)};\">${esc(p.unsubscribeText)}</a>\n</mj-text>`;\n },\n renderPreview: (p) => {\n return `<div style=\"padding:8px 0;text-align:center;font-size:12px;line-height:1.6;color:${p.textColor};\">\n ${esc(p.companyName)}<br/>\n ${esc(p.address)}<br/>\n <a href=\"${esc(p.unsubscribeHref)}\" style=\"color:${p.textColor};\">${esc(p.unsubscribeText)}</a>\n </div>`;\n },\n});\n","import { defineBlock, docContentWidthCss } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface HeroProps {\n backgroundUrl: string;\n backgroundColor: string;\n height: number;\n content: string;\n textAlign: 'left' | 'center' | 'right';\n textColor: string;\n verticalAlign: 'top' | 'middle' | 'bottom';\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nconst escapeAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const heroBlock = defineBlock<HeroProps>({\n type: 'hero',\n name: 'Hero 大图',\n category: 'content',\n icon: icons.hero,\n defaultProps: {\n backgroundUrl:\n 'https://placehold.co/600x320/312e81/c4b5fd/png?text=Hero+Background',\n backgroundColor: '#1e1b4b',\n height: 320,\n content:\n '<p style=\"margin:0;font-size:28px;font-weight:700;line-height:1.25;\">主标题落在大图上</p><p style=\"margin:12px 0 0;font-size:16px;font-weight:400;opacity:0.95;line-height:1.5;\">支援变量与 <strong>双击编辑</strong>,与正文组件一致。</p>',\n textAlign: 'center',\n textColor: '#ffffff',\n verticalAlign: 'middle',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n { key: 'backgroundUrl', label: '背景图', type: 'image' },\n { key: 'backgroundColor', label: '背景占位色', type: 'color', help: '图片加载失败时的底色' },\n { key: 'height', label: '区域高度 (px)', type: 'number', min: 120, max: 1200, step: 1 },\n {\n key: 'verticalAlign',\n label: '文字垂直位置',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '靠上', value: 'top' },\n { label: '居中', value: 'middle' },\n { label: '靠下', value: 'bottom' },\n ],\n },\n {\n key: 'textAlign',\n label: '文字水平对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'textColor', label: '文字颜色', type: 'color' },\n { key: 'paddingTop', label: '内边距', type: 'spacing' },\n {\n key: 'content',\n label: '正文(HTML)',\n type: 'textarea',\n help: '建议在画布内双击编辑;此处供高级修改。',\n },\n ],\n inlineEditable: {\n selector: '.sm-hero-content',\n mode: 'rich',\n multiline: true,\n propKey: 'content',\n placeholder: '编写覆盖在图片上的文案…',\n },\n toMjml: (p, ctx) => {\n const w = docContentWidthCss(ctx.doc.meta.width);\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const h = `${p.height}px`;\n return `<mj-hero\n mode=\"fixed-height\"\n height=\"${h}\"\n background-width=\"${w}\"\n background-height=\"${h}\"\n background-url=\"${escapeAttr(p.backgroundUrl)}\"\n background-color=\"${escapeAttr(p.backgroundColor)}\"\n padding=\"${padding}\"\n vertical-align=\"${p.verticalAlign}\"\n >\n <mj-text\n align=\"${p.textAlign}\"\n color=\"${escapeAttr(p.textColor)}\"\n padding=\"0\"\n >${p.content}</mj-text>\n </mj-hero>`;\n },\n renderPreview: (p, ctx) => {\n const w = docContentWidthCss(ctx.doc.meta.width);\n const flexAlign =\n p.verticalAlign === 'top' ? 'flex-start' : p.verticalAlign === 'bottom' ? 'flex-end' : 'center';\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const url = escapeAttr(p.backgroundUrl);\n return `<div\n style=\"\n box-sizing:border-box;\n width:100%;\n max-width:${w};\n min-height:${p.height}px;\n margin:0 auto;\n background-image:linear-gradient(to bottom,rgba(0,0,0,0.25),rgba(0,0,0,0.35)),url(${url});\n background-size:cover;\n background-position:center;\n background-color:${p.backgroundColor};\n display:flex;\n align-items:${flexAlign};\n justify-content:${p.textAlign === 'right' ? 'flex-end' : p.textAlign === 'center' ? 'center' : 'flex-start'};\n padding:${padding};\n color:${escapeAttr(p.textColor)};\n overflow:hidden;\n border-radius:2px;\n \"\n >\n <div\n class=\"sm-hero-content\"\n style=\"\n width:100%;\n text-align:${p.textAlign};\n color:${escapeAttr(p.textColor)};\n text-shadow:0 1px 2px rgba(0,0,0,0.45);\n \"\n >${p.content}</div>\n </div>`;\n },\n});\n","import {\n defineBlock,\n htmlContainsMjmlTags,\n mjRawCellTypographyFromStyles,\n mjRawEmailTableWrap,\n} from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface HtmlBlockProps {\n html: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nexport const htmlBlock = defineBlock<HtmlBlockProps>({\n type: 'html',\n name: 'HTML',\n category: 'content',\n icon: icons.html,\n defaultProps: {\n html: '<p style=\"margin:0;\">在此写入任意 HTML,将经 <strong>mj-raw</strong> 原样输出到邮件。支持变量 {{user.name}}</p>',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n {\n key: 'html',\n label: 'HTML',\n type: 'textarea',\n help: '只写 HTML(如 <a>、<table>),不要写 <mj-text> 等 MJML 标签;MJML 标签在 mj-raw 内不会被编译。简单链接建议用「文本」块。',\n },\n { key: 'paddingTop', label: '内边距', type: 'spacing' },\n ],\n inlineEditable: {\n selector: '.sm-html-content',\n mode: 'html',\n multiline: true,\n propKey: 'html',\n placeholder: '输入 HTML…',\n },\n toMjml: (p, ctx) => {\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n return mjRawEmailTableWrap(padding, p.html, mjRawCellTypographyFromStyles(ctx.doc.styles));\n },\n renderPreview: (p) => {\n const pad = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const warn = htmlContainsMjmlTags(p.html)\n ? '<div class=\"sm-html-mjml-warn\">检测到 MJML 标签,此处应只写 HTML,预览可能显示异常。</div>'\n : '';\n return `<div class=\"sm-html-content\" style=\"padding:${pad};min-height:1em;\">${warn}${p.html}</div>`;\n },\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface ImageProps {\n src: string;\n alt: string;\n href: string;\n width: number;\n /** 0 表示不限制高度,按原图比例自适应(推荐邮件场景) */\n height: number;\n align: 'left' | 'center' | 'right';\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nconst escapeAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const imageBlock = defineBlock<ImageProps>({\n type: 'image',\n name: '图片',\n category: 'content',\n icon: icons.image,\n defaultProps: {\n src: 'https://placehold.co/600x240/EEF2FF/4F46E5/png?text=600x240',\n alt: '',\n href: '',\n width: 480,\n height: 0,\n align: 'center',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n { key: 'src', label: '图片地址', type: 'image' },\n { key: 'alt', label: '替代文本', type: 'text', placeholder: '图片描述' },\n { key: 'href', label: '点击跳转', type: 'url', placeholder: 'https://...' },\n { key: 'width', label: '宽度 (px)', type: 'number', min: 40, max: 600 },\n {\n key: 'height',\n label: '高度 (px)(0 为自适应)',\n type: 'number',\n min: 0,\n max: 1200,\n help: '0 为自适应高度;填写固定值时画布与 MJML 会限制显示高度(预览可用 object-fit: cover)',\n },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'paddingTop', label: '内边距', type: 'spacing' },\n ],\n toMjml: (p) => {\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const href = p.href ? ` href=\"${escapeAttr(p.href)}\"` : '';\n const alt = ` alt=\"${escapeAttr(p.alt || '')}\"`;\n const h = p.height != null && p.height > 0 ? ` height=\"${p.height}px\"` : '';\n return `<mj-image src=\"${escapeAttr(p.src)}\"${alt}${href} width=\"${p.width}px\"${h} align=\"${p.align}\" padding=\"${padding}\" />`;\n },\n renderPreview: (p) => {\n const align = p.align === 'center' ? 'margin:0 auto;' : p.align === 'right' ? 'margin-left:auto;' : '';\n const fixedH = p.height != null && p.height > 0 ? p.height : 0;\n const sizeStyle =\n fixedH > 0\n ? `width:${p.width}px;height:${fixedH}px;object-fit:cover;object-position:center;`\n : `width:${p.width}px;height:auto;`;\n return `<div style=\"padding:${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px;text-align:${p.align};\"><img src=\"${escapeAttr(\n p.src,\n )}\" alt=\"${escapeAttr(p.alt)}\" style=\"display:block;${align}max-width:100%;${sizeStyle}border:0;outline:none;\" /></div>`;\n },\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\n/** 公司 Logo —— 一个语义化的\"图片+链接\"封装,便于运营快速放置品牌资产。 */\ninterface LogoProps {\n src: string;\n href: string;\n width: number;\n align: 'left' | 'center' | 'right';\n}\n\nconst esc = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const logoBlock = defineBlock<LogoProps>({\n type: 'custom:logo',\n name: '公司 Logo',\n category: 'custom',\n icon: icons.logo,\n defaultProps: {\n src: 'https://placehold.co/240x60/1f2328/ffffff/png?text=YOUR+LOGO',\n href: 'https://example.com',\n width: 160,\n align: 'center',\n },\n schema: [\n { key: 'src', label: 'Logo 图片', type: 'image' },\n { key: 'href', label: '官网链接', type: 'url' },\n { key: 'width', label: '宽度 (px)', type: 'number', min: 60, max: 400 },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n ],\n toMjml: (p) =>\n `<mj-image src=\"${esc(p.src)}\" href=\"${esc(p.href)}\" width=\"${p.width}px\" align=\"${p.align}\" alt=\"logo\" padding=\"8px 0px 8px 0px\" />`,\n renderPreview: (p) => {\n const m =\n p.align === 'center' ? 'margin:0 auto;' : p.align === 'right' ? 'margin-left:auto;' : '';\n return `<div style=\"padding:8px 0;text-align:${p.align};\"><img src=\"${esc(\n p.src,\n )}\" alt=\"logo\" style=\"display:block;${m}width:${p.width}px;max-width:100%;height:auto;\" /></div>`;\n },\n});\n","import { normalizeFontWeightStep } from '@simple-mail/core';\n\n/** 生成 mj-social-element 的 name 属性(与 MJML 内置图标对齐;未知平台退化为 web)。 */\nexport function mjSocialElementName(network: string): string {\n const n = network.trim();\n if (n === 'ig') return 'instagram';\n if (n === 'rabbit' || n === 'tiktok' || n === 'reddit') return 'web';\n return n;\n}\n\n/** 业务示例:固定海外/垂类五平台(与 custom:social 块配套)。 */\nexport const BIZ_SOCIAL_NETWORK_OPTIONS: { label: string; value: string }[] = [\n { label: 'X', value: 'x' },\n { label: 'Rabbit', value: 'rabbit' },\n { label: 'Facebook', value: 'facebook' },\n { label: 'TikTok', value: 'tiktok' },\n { label: 'Instagram', value: 'ig' },\n];\n\n/** 社交平台与 MJML mj-social-element 的 name 对齐(含常用内置名)。 */\nexport const SOCIAL_NETWORK_OPTIONS: { label: string; value: string }[] = [\n { label: '微信', value: 'wechat' },\n { label: '微博', value: 'weibo' },\n { label: 'X', value: 'x' },\n { label: 'LinkedIn', value: 'linkedin' },\n { label: 'GitHub', value: 'github' },\n { label: 'Facebook', value: 'facebook' },\n { label: 'Instagram', value: 'instagram' },\n { label: 'YouTube', value: 'youtube' },\n { label: 'Reddit', value: 'reddit' },\n { label: '网页', value: 'web' },\n];\n\nconst NETWORK_META: Record<string, { color: string; preview: string }> = {\n wechat: { color: '#1AAD19', preview: '信' },\n weibo: { color: '#E6162D', preview: '微' },\n x: { color: '#000000', preview: 'X' },\n linkedin: { color: '#0A66C2', preview: 'in' },\n github: { color: '#181717', preview: 'GH' },\n facebook: { color: '#1877F2', preview: 'f' },\n instagram: { color: '#E4405F', preview: '◎' },\n ig: { color: '#E4405F', preview: '◎' },\n youtube: { color: '#FF0000', preview: '▶' },\n reddit: { color: '#FF4500', preview: 'r' },\n tiktok: { color: '#000000', preview: '♪' },\n rabbit: { color: '#FF2442', preview: 'R' },\n website: { color: '#6b7280', preview: '◇' },\n web: { color: '#6b7280', preview: '◇' },\n};\n\nexport const escAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\n/** mj-social-element 体内文本转义(非属性) */\nexport const escMjmlText = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n\nexport interface SocialLinkItem {\n network: string;\n href: string;\n /** 图标旁文字,对应 mj-social-element 子内容 */\n label?: string;\n /** 自定义图标 URL,对应 mj-social-element src */\n iconSrc?: string;\n /** 图标区域背景色;未设则用平台预设 */\n backgroundColor?: string;\n}\n\n/** 社交组块级:所有带标签的链接共用同一套标签文字样式 */\nexport interface SocialGroupLabelStyle {\n labelFontSize: number;\n labelFontWeight: string;\n labelColor: string;\n}\n\nexport function socialMeta(network: string): { color: string; preview: string } {\n return NETWORK_META[network] ?? { color: '#6b7280', preview: '·' };\n}\n\n/** MJML 内置社交图标 CDN(与 mjml-browser 4.x 一致) */\nexport const MJML_SOCIAL_ICON_BASE =\n 'https://www.mailjet.com/images/theme/v1/icons/ico-social/';\n\n/** MJML `mj-social-element` name → 图标文件名 */\nconst MJML_SOCIAL_ICON_FILES: Record<string, string> = {\n facebook: 'facebook.png',\n twitter: 'twitter.png',\n x: 'twitter-x.png',\n google: 'google-plus.png',\n pinterest: 'pinterest.png',\n linkedin: 'linkedin.png',\n instagram: 'instagram.png',\n web: 'web.png',\n snapchat: 'snapchat.png',\n youtube: 'youtube.png',\n tumblr: 'tumblr.png',\n github: 'github.png',\n xing: 'xing.png',\n vimeo: 'vimeo.png',\n medium: 'medium.png',\n soundcloud: 'soundcloud.png',\n dribbble: 'dribbble.png',\n};\n\n/** 画布预览用默认图标 URL(与 MJML `name` 映射一致;无内置图时返回 null) */\nexport function mjSocialDefaultIconSrc(network: string): string | null {\n const file = MJML_SOCIAL_ICON_FILES[mjSocialElementName(network)];\n return file ? `${MJML_SOCIAL_ICON_BASE}${file}` : null;\n}\n\n/** 画布 / renderPreview 社交图标 HTML(优先自定义 URL,其次 MJML 内置图,最后文字占位) */\nexport function renderSocialIconPreviewHtml(opts: {\n network: string;\n iconSize: number;\n iconBorderRadius: number;\n iconSrc?: string;\n backgroundColor?: string;\n}): string {\n const { network, iconSize, iconBorderRadius, iconSrc, backgroundColor } = opts;\n const radiusCss = socialIconBorderRadiusCss(iconSize, iconBorderRadius);\n const meta = socialMeta(network);\n const bg = backgroundColor?.trim() || meta.color;\n const src = iconSrc?.trim() || mjSocialDefaultIconSrc(network);\n if (src) {\n return `<span style=\"display:inline-flex;width:${iconSize}px;height:${iconSize}px;border-radius:${radiusCss};background:${bg};overflow:hidden;align-items:center;justify-content:center;flex-shrink:0;line-height:0;\"><img src=\"${escAttr(src)}\" alt=\"\" width=\"${iconSize}\" height=\"${iconSize}\" style=\"display:block;width:${iconSize}px;height:${iconSize}px;border-radius:${radiusCss};\" /></span>`;\n }\n return `<span style=\"display:inline-flex;width:${iconSize}px;height:${iconSize}px;border-radius:${radiusCss};background:${bg};color:#fff;align-items:center;justify-content:center;font-size:${Math.round(\n iconSize / 2,\n )}px;font-weight:600;flex-shrink:0;overflow:hidden;\">${meta.preview}</span>`;\n}\n\nexport function paddingQuad(p: {\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}): string {\n return `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n}\n\n/** mj-social `border-radius`:0 直角;≥999 或 ≥图标半边 → 圆形裁切(999px) */\nexport function socialIconBorderRadiusMjml(iconSize: number, radiusPx: unknown): string {\n const size = Math.max(1, Number(iconSize) || 28);\n const r = Number(radiusPx);\n if (!Number.isFinite(r) || r <= 0) return '0px';\n const half = size / 2;\n if (r >= 999 || r >= half) return '999px';\n return `${Math.min(r, size)}px`;\n}\n\n/** 画布预览用图标圆角 CSS(与 {@link socialIconBorderRadiusMjml} 语义一致) */\nexport function socialIconBorderRadiusCss(iconSize: number, radiusPx: unknown): string {\n const size = Math.max(1, Number(iconSize) || 28);\n const r = Number(radiusPx);\n if (!Number.isFinite(r) || r <= 0) return '0';\n const half = size / 2;\n if (r >= 999 || r >= half) return '50%';\n return `${Math.min(r, size)}px`;\n}\n\n/** mj-social `inner-padding`,控制图标之间的可视间距 */\nexport function socialIconSpacingPx(spacing: unknown, fallback = 10): number {\n const n = Number(spacing);\n if (!Number.isFinite(n) || n < 0) return fallback;\n return Math.min(64, Math.round(n));\n}\n\nexport function flexJustifyFromAlign(align: 'left' | 'center' | 'right'): string {\n if (align === 'right') return 'flex-end';\n if (align === 'left') return 'flex-start';\n return 'center';\n}\n\nexport function mjSocialElementsLines(\n links: SocialLinkItem[],\n labelStyle: SocialGroupLabelStyle,\n): string {\n const fontSizeRaw = labelStyle.labelFontSize > 0 ? labelStyle.labelFontSize : 13;\n const fontSize = Math.max(8, Math.min(48, fontSizeRaw));\n const fontWeight = normalizeFontWeightStep(labelStyle.labelFontWeight);\n const textColor = labelStyle.labelColor?.trim() || '#333333';\n const fwEsc = escAttr(fontWeight);\n return links\n .map((l) => {\n const meta = socialMeta(l.network);\n const bgColor = l.backgroundColor?.trim() || meta.color;\n const attrs = [\n `name=\"${escAttr(mjSocialElementName(l.network))}\"`,\n `href=\"${escAttr(l.href)}\"`,\n `background-color=\"${escAttr(bgColor)}\"`,\n `color=\"${escAttr(textColor)}\"`,\n `font-size=\"${fontSize}px\"`,\n `font-weight=\"${fwEsc}\"`,\n ];\n const attrStr = attrs.join(' ');\n const src = l.iconSrc?.trim();\n const withSrc = src ? `${attrStr} src=\"${escAttr(src)}\"` : attrStr;\n const label = l.label?.trim() ?? '';\n if (!label) {\n return ` <mj-social-element ${withSrc} />`;\n }\n return ` <mj-social-element ${withSrc}>\\n ${escMjmlText(label)}\\n </mj-social-element>`;\n })\n .join('\\n');\n}\n","import { defineBlock, FONT_WEIGHT_STEP_OPTIONS, normalizeFontWeightStep } from '@simple-mail/core';\nimport { icons } from './icons';\nimport {\n BIZ_SOCIAL_NETWORK_OPTIONS,\n escAttr,\n flexJustifyFromAlign,\n mjSocialElementsLines,\n paddingQuad,\n socialIconBorderRadiusMjml,\n renderSocialIconPreviewHtml,\n socialIconSpacingPx,\n type SocialLinkItem,\n} from './socialShared';\n\n/** 与社交组一致,仅平台选项收窄为业务五件套 */\ninterface SocialBizProps {\n elements: SocialLinkItem[];\n align: 'left' | 'center' | 'right';\n iconSize: number;\n iconBorderRadius: number;\n iconSpacing: number;\n labelFontSize: number;\n labelFontWeight: string;\n labelColor: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n /** 旧版自定义块:`links` + textarea,仅用于兼容读入 */\n links?: { network: string; href: string }[];\n}\n\nconst DEFAULT_BIZ_ELEMENTS: SocialLinkItem[] = [\n { network: 'x', href: 'https://x.com/' },\n { network: 'rabbit', href: 'https://example.com' },\n { network: 'facebook', href: 'https://facebook.com/' },\n { network: 'tiktok', href: 'https://www.tiktok.com/' },\n { network: 'ig', href: 'https://instagram.com/' },\n];\n\nfunction normalizeElements(p: SocialBizProps): SocialLinkItem[] {\n if (p.elements?.length) return p.elements;\n const legacy = p.links;\n if (Array.isArray(legacy) && legacy.length)\n return legacy.map((l) => ({\n network: String(l.network ?? 'web'),\n href: String(l.href ?? ''),\n }));\n return DEFAULT_BIZ_ELEMENTS;\n}\n\nexport const socialBlock = defineBlock<SocialBizProps>({\n type: 'custom:social',\n name: '社交链接',\n category: 'custom',\n icon: icons.social,\n defaultProps: {\n elements: DEFAULT_BIZ_ELEMENTS,\n align: 'center',\n iconSize: 28,\n iconBorderRadius: 999,\n iconSpacing: 10,\n labelFontSize: 13,\n labelFontWeight: '400',\n labelColor: '#333333',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n {\n key: 'elements',\n label: '社交链接',\n type: 'socialLinkList',\n options: BIZ_SOCIAL_NETWORK_OPTIONS,\n help: '平台:X、Rabbit、Facebook、TikTok、Instagram (ig)。可填标签、自定义图标 URL。MJML 侧 Rabbit/TikTok 使用 web 占位图标,需要品牌图时请填「图标 URL」。',\n },\n {\n key: 'labelFontSize',\n label: '标签字号 (px)',\n type: 'number',\n min: 8,\n max: 48,\n step: 1,\n },\n {\n key: 'labelFontWeight',\n label: '标签字重',\n type: 'select',\n selectVariant: 'segmented',\n options: [...FONT_WEIGHT_STEP_OPTIONS],\n },\n { key: 'labelColor', label: '标签颜色', type: 'color' },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'iconSize', label: '图标尺寸 (px)', type: 'number', min: 16, max: 64 },\n {\n key: 'iconBorderRadius',\n label: '图标圆角 (px)',\n type: 'number',\n min: 0,\n max: 999,\n step: 1,\n help: '0 为方形直角;较大值(如 999)为圆形(默认)。',\n },\n {\n key: 'iconSpacing',\n label: '图标间距 (px)',\n type: 'number',\n min: 0,\n max: 64,\n step: 1,\n help: '图标之间的间隔(MJML inner-padding)。',\n },\n { key: 'paddingTop', label: '外边距', type: 'spacing' },\n ],\n toMjml: (p) => {\n const pad = paddingQuad(p);\n const br = socialIconBorderRadiusMjml(p.iconSize, p.iconBorderRadius ?? 999);\n const gap = socialIconSpacingPx(p.iconSpacing, 10);\n const socAttrs = `align=\"${p.align}\" icon-size=\"${p.iconSize}px\" mode=\"horizontal\" border-radius=\"${br}\" inner-padding=\"${gap}px\" padding=\"${pad}\"`;\n const els = normalizeElements(p).filter((e) => e.href?.trim());\n const labelStyle = {\n labelFontSize: Number(p.labelFontSize ?? 13),\n labelFontWeight: normalizeFontWeightStep(String(p.labelFontWeight ?? '400')),\n labelColor: String(p.labelColor ?? '#333333'),\n };\n const inner = mjSocialElementsLines(els, labelStyle);\n if (!inner.trim()) {\n return `<mj-social ${socAttrs}></mj-social>`;\n }\n return `<mj-social ${socAttrs}>\n${inner}\n</mj-social>`;\n },\n renderPreview: (p) => {\n const fsRaw = p.labelFontSize != null && p.labelFontSize > 0 ? p.labelFontSize : 13;\n const fs = Math.max(8, Math.min(48, fsRaw));\n const fw = normalizeFontWeightStep(p.labelFontWeight);\n const textColor = p.labelColor?.trim() || '#333333';\n const gap = socialIconSpacingPx(p.iconSpacing, 10);\n const jc = flexJustifyFromAlign(p.align);\n const items = normalizeElements(p)\n .filter((l) => l.href?.trim())\n .map((l) => {\n const label = l.label?.trim() ?? '';\n const iconHtml = renderSocialIconPreviewHtml({\n network: l.network,\n iconSize: p.iconSize,\n iconBorderRadius: p.iconBorderRadius ?? 999,\n iconSrc: l.iconSrc,\n backgroundColor: l.backgroundColor,\n });\n const textHtml = label\n ? `<span style=\"font-size:${fs}px !important;font-weight:${fw};color:${escAttr(\n textColor,\n )} !important;line-height:1.2;\">${escAttr(label)}</span>`\n : '';\n return `<span style=\"display:inline-flex;align-items:center;gap:6px;\"><a href=\"${escAttr(\n l.href,\n )}\" style=\"display:inline-flex;align-items:center;text-decoration:none;line-height:0;\">${iconHtml}</a>${textHtml}</span>`;\n })\n .join('');\n const pad = paddingQuad(p);\n return `<div style=\"display:flex;flex-wrap:wrap;justify-content:${jc};align-items:center;gap:${gap}px;padding:${pad};\">${items || '<span style=\"color:#9ca3af;font-size:12px;\">请填写链接 URL</span>'}</div>`;\n },\n});\n","import { defineBlock, FONT_WEIGHT_STEP_OPTIONS, normalizeFontWeightStep } from '@simple-mail/core';\nimport { icons } from './icons';\nimport {\n escAttr,\n flexJustifyFromAlign,\n mjSocialElementsLines,\n paddingQuad,\n socialIconBorderRadiusMjml,\n renderSocialIconPreviewHtml,\n socialIconSpacingPx,\n SOCIAL_NETWORK_OPTIONS,\n type SocialLinkItem,\n} from './socialShared';\n\ninterface SocialGroupProps {\n elements: SocialLinkItem[];\n align: 'left' | 'center' | 'right';\n iconSize: number;\n /** 图标圆角 (px)。0 为方形;≥999 或不少于图标半边时为圆形(默认 999) */\n iconBorderRadius: number;\n /** 图标之间的间距 (px),对应 mj-social inner-padding */\n iconSpacing: number;\n /** 标签文字字号(整组统一) */\n labelFontSize: number;\n labelFontWeight: string;\n labelColor: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nexport const socialGroupBlock = defineBlock<SocialGroupProps>({\n type: 'social-group',\n name: '社交组',\n category: 'content',\n icon: icons.socialGroup,\n defaultProps: {\n elements: [\n { network: 'weibo', href: 'https://weibo.com' },\n { network: 'wechat', href: 'https://example.com' },\n ],\n align: 'center',\n iconSize: 28,\n iconBorderRadius: 999,\n iconSpacing: 10,\n labelFontSize: 13,\n labelFontWeight: '400',\n labelColor: '#333333',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n {\n key: 'elements',\n label: '社交链接',\n type: 'socialLinkList',\n options: SOCIAL_NETWORK_OPTIONS,\n help: '每行:平台、链接、可选标签文字、自定义图标 URL、图标背景色。标签的字号/字重/颜色在下方统一设置。',\n },\n {\n key: 'labelFontSize',\n label: '标签字号 (px)',\n type: 'number',\n min: 8,\n max: 48,\n step: 1,\n },\n {\n key: 'labelFontWeight',\n label: '标签字重',\n type: 'select',\n selectVariant: 'segmented',\n options: [...FONT_WEIGHT_STEP_OPTIONS],\n },\n { key: 'labelColor', label: '标签颜色', type: 'color' },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'iconSize', label: '图标尺寸 (px)', type: 'number', min: 16, max: 64 },\n {\n key: 'iconBorderRadius',\n label: '图标圆角 (px)',\n type: 'number',\n min: 0,\n max: 999,\n step: 1,\n help: '0 为方形直角;填较大值(如 999)或与尺寸一半相当时为圆形(默认圆形)。',\n },\n {\n key: 'iconSpacing',\n label: '图标间距 (px)',\n type: 'number',\n min: 0,\n max: 64,\n step: 1,\n help: '每个图标周围的留白,横向即图标之间的间隔(MJML inner-padding)。',\n },\n { key: 'paddingTop', label: '外边距', type: 'spacing' },\n ],\n toMjml: (p) => {\n const pad = paddingQuad(p);\n const br = socialIconBorderRadiusMjml(p.iconSize, p.iconBorderRadius ?? 999);\n const gap = socialIconSpacingPx(p.iconSpacing, 10);\n const socAttrs = `align=\"${p.align}\" icon-size=\"${p.iconSize}px\" mode=\"horizontal\" border-radius=\"${br}\" inner-padding=\"${gap}px\" padding=\"${pad}\"`;\n const filtered = p.elements.filter((e) => e.href?.trim());\n const labelStyle = {\n labelFontSize: Number(p.labelFontSize ?? 13),\n labelFontWeight: normalizeFontWeightStep(String(p.labelFontWeight ?? '400')),\n labelColor: String(p.labelColor ?? '#333333'),\n };\n const inner = mjSocialElementsLines(filtered, labelStyle);\n if (!inner.trim()) {\n return `<mj-social ${socAttrs}></mj-social>`;\n }\n return `<mj-social ${socAttrs}>\n${inner}\n</mj-social>`;\n },\n renderPreview: (p) => {\n const fsRaw = p.labelFontSize != null && p.labelFontSize > 0 ? p.labelFontSize : 13;\n const fs = Math.max(8, Math.min(48, fsRaw));\n const fw = normalizeFontWeightStep(p.labelFontWeight);\n const textColor = p.labelColor?.trim() || '#333333';\n const gap = socialIconSpacingPx(p.iconSpacing, 10);\n const jc = flexJustifyFromAlign(p.align);\n const items = p.elements\n .filter((l) => l.href?.trim())\n .map((l) => {\n const label = l.label?.trim() ?? '';\n const iconHtml = renderSocialIconPreviewHtml({\n network: l.network,\n iconSize: p.iconSize,\n iconBorderRadius: p.iconBorderRadius ?? 999,\n iconSrc: l.iconSrc,\n backgroundColor: l.backgroundColor,\n });\n const textHtml = label\n ? `<span style=\"font-size:${fs}px !important;font-weight:${fw};color:${escAttr(\n textColor,\n )} !important;line-height:1.2;\">${escAttr(label)}</span>`\n : '';\n return `<span style=\"display:inline-flex;align-items:center;gap:6px;\"><a href=\"${escAttr(\n l.href,\n )}\" style=\"display:inline-flex;align-items:center;text-decoration:none;line-height:0;\">${iconHtml}</a>${textHtml}</span>`;\n })\n .join('');\n const pad = paddingQuad(p);\n return `<div style=\"display:flex;flex-wrap:wrap;justify-content:${jc};align-items:center;gap:${gap}px;padding:${pad};\">${items || '<span style=\"color:#9ca3af;font-size:12px;\">请添加社交链接</span>'}</div>`;\n },\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface SpacerProps {\n height: number;\n}\n\nexport const spacerBlock = defineBlock<SpacerProps>({\n type: 'spacer',\n name: '间距',\n category: 'content',\n icon: icons.spacer,\n defaultProps: { height: 24 },\n schema: [{ key: 'height', label: '高度 (px)', type: 'number', min: 1, max: 200 }],\n toMjml: (p) => `<mj-spacer height=\"${p.height}px\" />`,\n renderPreview: (p) => `<div style=\"height:${p.height}px;line-height:${p.height}px;\"></div>`,\n});\n","import { defineBlock, FONT_WEIGHT_STEP_OPTIONS, isRichHtmlEffectivelyEmpty, normalizeFontWeightStep } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface TextProps {\n content: string;\n align: 'left' | 'center' | 'right';\n color: string;\n fontSize: string;\n fontFamily: string;\n fontWeight: string;\n /** 空字符串:与邮件全局行距(mj-head)一致 */\n lineHeight: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nconst escapeAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nconst TEXT_PLACEHOLDER = '输入文本…';\n\nexport const textBlock = defineBlock<TextProps>({\n type: 'text',\n name: '文本',\n category: 'content',\n icon: icons.text,\n defaultProps: {\n content:\n '<p style=\"margin:0;\">在此处输入文本。<strong>双击</strong>进入编辑模式,<em>选中文字</em>会出现工具条;支持变量 {{user.name}}</p>',\n align: 'left',\n color: '',\n fontSize: '',\n fontFamily: '',\n fontWeight: '',\n lineHeight: '',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'color', label: '颜色', type: 'color', placeholder: '继承全局' },\n { key: 'fontSize', label: '字号', type: 'text', inheritGlobal: true },\n { key: 'fontFamily', label: '字体', type: 'text', placeholder: '继承全局' },\n {\n key: 'fontWeight',\n label: '字重',\n type: 'select',\n selectVariant: 'segmented',\n inheritGlobal: true,\n options: [...FONT_WEIGHT_STEP_OPTIONS],\n },\n {\n key: 'lineHeight',\n label: '行高',\n type: 'select',\n help: '留空则使用邮件设置里的全局行距',\n options: [\n { label: '继承全局', value: '' },\n { label: '1.0', value: '1' },\n { label: '1.15', value: '1.15' },\n { label: '1.25', value: '1.25' },\n { label: '1.4', value: '1.4' },\n { label: '1.5', value: '1.5' },\n { label: '1.75', value: '1.75' },\n { label: '2.0', value: '2' },\n { label: '22px', value: '22px' },\n { label: '24px', value: '24px' },\n { label: '28px', value: '28px' },\n { label: '32px', value: '32px' },\n ],\n },\n { key: 'paddingTop', label: '内边距', type: 'spacing' },\n {\n key: 'content',\n label: '内容(HTML,备用)',\n type: 'textarea',\n help: '建议直接在画布双击编辑;这里保留为高级编辑入口。',\n },\n ],\n inlineEditable: {\n selector: '.sm-text-content',\n mode: 'rich',\n multiline: true,\n propKey: 'content',\n placeholder: TEXT_PLACEHOLDER,\n },\n toMjml: (p) => {\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const ff = p.fontFamily ? ` font-family=\"${escapeAttr(p.fontFamily)}\"` : '';\n const fwRaw = String(p.fontWeight ?? '').trim();\n const fw = fwRaw ? ` font-weight=\"${escapeAttr(normalizeFontWeightStep(fwRaw))}\"` : '';\n const lh = String(p.lineHeight ?? '').trim();\n const lhAttr = lh ? ` line-height=\"${escapeAttr(lh)}\"` : '';\n const colorRaw = String(p.color ?? '').trim();\n const colorAttr = colorRaw ? ` color=\"${escapeAttr(colorRaw)}\"` : '';\n const fsRaw = String(p.fontSize ?? '').trim();\n const fsAttr = fsRaw ? ` font-size=\"${escapeAttr(fsRaw)}\"` : '';\n return `<mj-text align=\"${p.align}\"${colorAttr}${fsAttr}${lhAttr}${ff}${fw} padding=\"${padding}\">${p.content}</mj-text>`;\n },\n renderPreview: (p) => {\n const ff = p.fontFamily ? `font-family:${p.fontFamily};` : '';\n const fwRaw = String(p.fontWeight ?? '').trim();\n const fwCss = fwRaw ? `font-weight:${normalizeFontWeightStep(fwRaw)};` : '';\n const lhRaw = String(p.lineHeight ?? '').trim();\n const lh = lhRaw ? `line-height:${lhRaw};` : 'line-height:normal;';\n const colorRaw = String(p.color ?? '').trim();\n const colorCss = colorRaw ? `color:${colorRaw};` : '';\n const fsRaw = String(p.fontSize ?? '').trim();\n const fsCss = fsRaw ? `font-size:${fsRaw};` : '';\n const empty = isRichHtmlEffectivelyEmpty(p.content);\n const emptyClass = empty ? ' is-empty' : '';\n const placeholderAttr = empty ? ` data-placeholder=\"${TEXT_PLACEHOLDER}\"` : '';\n return `<div class=\"sm-text-content${emptyClass}\"${placeholderAttr} style=\"text-align:${p.align};${colorCss}${fsCss}${fwCss}${lh}${ff}padding:${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px;\">${p.content}</div>`;\n },\n});\n","import type { BlockDefinition, BlockSchemaField, SimpleMailT } from '@simple-mail/core';\n\ntype AnyBlock = BlockDefinition<any>;\n\nconst FIELD_LABEL_KEYS: Record<string, string> = {\n align: 'blocks.field.align',\n textAlign: 'blocks.field.textAlign',\n verticalAlign: 'blocks.field.verticalAlign',\n color: 'blocks.field.color',\n textColor: 'blocks.field.textColor',\n backgroundColor: 'blocks.field.backgroundColor',\n backgroundUrl: 'blocks.field.backgroundUrl',\n height: 'blocks.field.heightPx',\n width: 'blocks.field.width',\n thickness: 'blocks.field.thicknessPx',\n paddingTop: 'blocks.field.padding',\n text: 'blocks.field.text',\n href: 'blocks.field.link',\n src: 'blocks.field.imageUrl',\n alt: 'blocks.field.alt',\n fontSize: 'blocks.field.fontSize',\n fontFamily: 'blocks.field.fontFamily',\n fontWeight: 'blocks.field.fontWeight',\n lineHeight: 'blocks.field.lineHeight',\n html: 'blocks.field.html',\n borderRadius: 'blocks.field.borderRadius',\n innerPaddingV: 'blocks.field.buttonInnerPaddingV',\n innerPaddingH: 'blocks.field.buttonInnerPaddingH',\n elements: 'blocks.field.socialLinks',\n labelFontSize: 'blocks.field.labelFontSize',\n labelFontWeight: 'blocks.field.labelFontWeight',\n labelColor: 'blocks.field.labelColor',\n iconSize: 'blocks.field.iconSize',\n iconBorderRadius: 'blocks.field.iconRadius',\n iconSpacing: 'blocks.field.iconSpacing',\n companyName: 'blocks.field.companyName',\n address: 'blocks.field.address',\n unsubscribeText: 'blocks.field.unsubscribeText',\n unsubscribeHref: 'blocks.field.unsubscribeLink',\n};\n\nconst BLOCK_FIELD_LABEL_KEYS: Record<string, Record<string, string>> = {\n button: {\n backgroundColor: 'blocks.field.backgroundColor',\n color: 'blocks.field.textColor',\n width: 'blocks.field.width',\n },\n divider: {\n width: 'blocks.field.widthPercentOrPx',\n paddingTop: 'blocks.field.topMargin',\n paddingBottom: 'blocks.field.bottomMargin',\n },\n hero: {\n backgroundColor: 'blocks.field.backgroundPlaceholderColor',\n height: 'blocks.field.areaHeightPx',\n content: 'blocks.field.bodyHtml',\n },\n html: {\n paddingTop: 'blocks.field.padding',\n },\n image: {\n href: 'blocks.field.href',\n width: 'blocks.field.widthPx',\n },\n logo: {\n src: 'blocks.field.logoImage',\n href: 'blocks.field.websiteLink',\n width: 'blocks.field.widthPx',\n },\n text: {\n content: 'blocks.field.contentHtml',\n },\n};\n\nconst HELP_KEYS: Record<string, Record<string, string>> = {\n button: { width: 'blocks.help.buttonWidth' },\n hero: {\n backgroundColor: 'blocks.help.imageFallbackColor',\n content: 'blocks.help.canvasEditRecommendedShort',\n },\n html: { html: 'blocks.help.htmlOnly' },\n image: { height: 'blocks.help.imageAutoHeight' },\n 'social-group': {\n elements: 'blocks.help.socialLinks',\n iconBorderRadius: 'blocks.help.iconRadius',\n iconSpacing: 'blocks.help.iconSpacing',\n },\n social: {\n elements: 'blocks.help.bizSocialLinks',\n iconBorderRadius: 'blocks.help.iconRadius',\n iconSpacing: 'blocks.help.bizIconSpacing',\n },\n text: {\n content: 'blocks.help.canvasEditRecommended',\n lineHeight: 'blocks.help.globalLineHeight',\n },\n};\n\nconst PLACEHOLDER_KEYS: Record<string, Record<string, string>> = {\n button: { width: 'blocks.placeholder.buttonWidth' },\n image: { alt: 'blocks.field.imageDescription' },\n text: {\n color: 'blocks.field.inheritGlobalPlaceholder',\n fontFamily: 'blocks.field.inheritGlobalPlaceholder',\n },\n};\n\nconst INLINE_PLACEHOLDER_KEYS: Record<string, string> = {\n button: 'blocks.field.buttonTextPlaceholder',\n hero: 'blocks.field.heroPlaceholder',\n html: 'blocks.field.htmlPlaceholder',\n text: 'blocks.field.textPlaceholder',\n};\n\nconst DEFAULT_PROP_KEYS: Record<string, Record<string, string>> = {\n button: { text: 'blocks.button.defaultText' },\n hero: { content: 'blocks.hero.defaultContent' },\n html: { html: 'blocks.html.defaultHtml' },\n text: { content: 'blocks.text.defaultContent' },\n footer: {\n companyName: 'blocks.footer.defaultCompanyName',\n address: 'blocks.footer.defaultAddress',\n unsubscribeText: 'blocks.footer.defaultUnsubscribeText',\n },\n};\n\nexport function localizeBlockDefinitions(blocks: AnyBlock[], t: SimpleMailT): AnyBlock[] {\n return blocks.map((block) => localizeBlockDefinition(block, t));\n}\n\nexport function localizeBlockDefinition(block: AnyBlock, t: SimpleMailT): AnyBlock {\n const blockKey = blockMessageId(block.type);\n const nameKey = `blocks.${blockKey}.name`;\n const translatedName = t(nameKey);\n return {\n ...block,\n name: translatedName === nameKey ? block.name : translatedName,\n defaultProps: localizeDefaultProps(block, t),\n schema: block.schema.map((field) => localizeField(blockKey, field, t)),\n inlineEditable: block.inlineEditable\n ? {\n ...block.inlineEditable,\n placeholder: inlinePlaceholder(blockKey, block, t),\n }\n : undefined,\n };\n}\n\nfunction localizeDefaultProps(block: AnyBlock, t: SimpleMailT): Record<string, unknown> {\n const props = { ...(block.defaultProps as Record<string, unknown>) };\n const propKeys = DEFAULT_PROP_KEYS[blockMessageId(block.type)] ?? {};\n for (const [prop, key] of Object.entries(propKeys)) {\n props[prop] = t(key);\n }\n return props;\n}\n\nfunction localizeField(blockType: string, field: BlockSchemaField, t: SimpleMailT): BlockSchemaField {\n const labelKey = BLOCK_FIELD_LABEL_KEYS[blockType]?.[field.key] ?? FIELD_LABEL_KEYS[field.key];\n return {\n ...field,\n label: labelKey ? t(labelKey) : field.label,\n placeholder: PLACEHOLDER_KEYS[blockType]?.[field.key]\n ? t(PLACEHOLDER_KEYS[blockType][field.key])\n : field.placeholder,\n help: HELP_KEYS[blockType]?.[field.key] ? t(HELP_KEYS[blockType][field.key]) : field.help,\n options: field.options?.map((option) => ({\n ...option,\n label: localizeOptionLabel(option, t),\n })),\n };\n}\n\nfunction localizeOptionLabel(\n option: { label: string; value: string },\n t: SimpleMailT,\n): string {\n if (option.value === 'left') return t('common.left');\n if (option.value === 'center') return t('common.center');\n if (option.value === 'right') return t('common.right');\n if (option.value === 'top') return t('blocks.option.top');\n if (option.value === 'middle') return t('blocks.option.middle');\n if (option.value === 'bottom') return t('blocks.option.bottom');\n if (option.value === '') return t('common.inheritGlobal');\n return option.label;\n}\n\nfunction inlinePlaceholder(blockType: string, block: AnyBlock, t: SimpleMailT): string | undefined {\n const key = INLINE_PLACEHOLDER_KEYS[blockType];\n return key ? t(key) : block.inlineEditable?.placeholder;\n}\n\nfunction blockMessageId(type: string): string {\n return type.startsWith('custom:') ? type.slice('custom:'.length) : type;\n}\n","import {\n createI18nContext,\n type BlockDefinition,\n type SimpleMailI18nOptions,\n type SimpleMailT,\n} from '@simple-mail/core';\nimport { buttonBlock } from './button';\nimport { dividerBlock } from './divider';\nimport { footerBlock } from './footer';\nimport { heroBlock } from './hero';\nimport { htmlBlock } from './html';\nimport { imageBlock } from './image';\nimport { logoBlock } from './logo';\nimport { socialBlock } from './social';\nimport { socialGroupBlock } from './socialGroup';\nimport { spacerBlock } from './spacer';\nimport { textBlock } from './text';\nimport { localizeBlockDefinitions } from './i18n';\n\nexport {\n buttonBlock,\n dividerBlock,\n footerBlock,\n heroBlock,\n htmlBlock,\n imageBlock,\n logoBlock,\n socialBlock,\n socialGroupBlock,\n spacerBlock,\n textBlock,\n};\n\nexport { localizeBlockDefinition, localizeBlockDefinitions } from './i18n';\n\n/** 宿主拼装「社交组」类 block 时可复用(mj-social 序列化、侧栏 socialLinkList)。 */\nexport {\n escAttr,\n escMjmlText,\n flexJustifyFromAlign,\n mjSocialElementName,\n mjSocialDefaultIconSrc,\n mjSocialElementsLines,\n paddingQuad,\n renderSocialIconPreviewHtml,\n socialIconBorderRadiusCss,\n socialIconBorderRadiusMjml,\n socialIconSpacingPx,\n socialMeta,\n SOCIAL_NETWORK_OPTIONS,\n type SocialGroupLabelStyle,\n type SocialLinkItem,\n} from './socialShared';\n\nconst baseBuiltinBlocks: BlockDefinition<any>[] = [\n textBlock,\n htmlBlock,\n imageBlock,\n socialGroupBlock,\n heroBlock,\n buttonBlock,\n dividerBlock,\n spacerBlock,\n];\n\nconst baseExampleCustomBlocks: BlockDefinition<any>[] = [logoBlock, socialBlock, footerBlock];\n\nexport interface CreateBlocksOptions extends SimpleMailI18nOptions {\n t?: SimpleMailT;\n}\n\nfunction resolveBlocksT(options: CreateBlocksOptions = {}): SimpleMailT {\n return options.t ?? createI18nContext(options).t;\n}\n\n/** 内置组件(content 类)。可直接传给 MailEditor.blocks。 */\nexport function createBuiltinBlocks(options: CreateBlocksOptions = {}): BlockDefinition<any>[] {\n return localizeBlockDefinitions(baseBuiltinBlocks, resolveBlocksT(options));\n}\n\n/** 业务示例的“自定义”组件。可作为参考或直接使用;正式业务块应由宿主应用注册。 */\nexport function createExampleCustomBlocks(options: CreateBlocksOptions = {}): BlockDefinition<any>[] {\n return localizeBlockDefinitions(baseExampleCustomBlocks, resolveBlocksT(options));\n}\n\n/** 全部组件(内置 + 示例自定义)。业务相关块请在使用侧与 `allBlocks` 合并后传入 MailEditor。 */\nexport function createAllBlocks(options: CreateBlocksOptions = {}): BlockDefinition<any>[] {\n const t = resolveBlocksT(options);\n return [\n ...localizeBlockDefinitions(baseBuiltinBlocks, t),\n ...localizeBlockDefinitions(baseExampleCustomBlocks, t),\n ];\n}\n\n/** 内置组件(content 类)。保留兼容:默认中文。 */\nexport const builtinBlocks: BlockDefinition<any>[] = createBuiltinBlocks();\n\n/** 业务示例的“自定义”组件。保留兼容:默认中文。 */\nexport const exampleCustomBlocks: BlockDefinition<any>[] = createExampleCustomBlocks();\n\n/** 全部组件(内置 + 示例自定义)。保留兼容:默认中文。 */\nexport const allBlocks: BlockDefinition<any>[] = createAllBlocks();\n"],"names":["icons","escapeAttr","s","buttonBlock","defineBlock","p","padding","innerPadding","bw","blockButtonWidthCss","widthAttr","wst","esc","dividerBlock","footerBlock","heroBlock","ctx","w","docContentWidthCss","h","flexAlign","url","htmlBlock","mjRawEmailTableWrap","mjRawCellTypographyFromStyles","pad","warn","htmlContainsMjmlTags","imageBlock","href","alt","align","fixedH","sizeStyle","logoBlock","m","mjSocialElementName","network","n","BIZ_SOCIAL_NETWORK_OPTIONS","SOCIAL_NETWORK_OPTIONS","NETWORK_META","escAttr","escMjmlText","socialMeta","MJML_SOCIAL_ICON_BASE","MJML_SOCIAL_ICON_FILES","mjSocialDefaultIconSrc","file","renderSocialIconPreviewHtml","opts","iconSize","iconBorderRadius","iconSrc","backgroundColor","radiusCss","socialIconBorderRadiusCss","meta","bg","src","paddingQuad","socialIconBorderRadiusMjml","radiusPx","size","r","half","socialIconSpacingPx","spacing","fallback","flexJustifyFromAlign","mjSocialElementsLines","links","labelStyle","fontSizeRaw","fontSize","fontWeight","normalizeFontWeightStep","textColor","_a","fwEsc","l","bgColor","attrStr","_b","withSrc","label","_c","DEFAULT_BIZ_ELEMENTS","normalizeElements","legacy","socialBlock","FONT_WEIGHT_STEP_OPTIONS","br","gap","socAttrs","els","e","inner","fsRaw","fs","fw","jc","items","iconHtml","textHtml","socialGroupBlock","filtered","spacerBlock","TEXT_PLACEHOLDER","textBlock","ff","fwRaw","lh","lhAttr","colorRaw","colorAttr","fsAttr","fwCss","lhRaw","colorCss","fsCss","empty","isRichHtmlEffectivelyEmpty","emptyClass","placeholderAttr","FIELD_LABEL_KEYS","BLOCK_FIELD_LABEL_KEYS","HELP_KEYS","PLACEHOLDER_KEYS","INLINE_PLACEHOLDER_KEYS","DEFAULT_PROP_KEYS","localizeBlockDefinitions","blocks","block","localizeBlockDefinition","blockKey","blockMessageId","nameKey","translatedName","localizeDefaultProps","field","localizeField","inlinePlaceholder","props","propKeys","prop","key","blockType","t","labelKey","_d","option","localizeOptionLabel","type","baseBuiltinBlocks","baseExampleCustomBlocks","resolveBlocksT","options","createI18nContext","createBuiltinBlocks","createExampleCustomBlocks","createAllBlocks","builtinBlocks","exampleCustomBlocks","allBlocks"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/icons.ts","../src/button.ts","../src/divider.ts","../src/footer.ts","../src/hero.ts","../src/html.ts","../src/image.ts","../src/logo.ts","../src/socialShared.ts","../src/social.ts","../src/socialGroup.ts","../src/spacer.ts","../src/text.ts","../src/i18n.ts","../src/index.ts"],"sourcesContent":["/** 24x24 viewBox 的内置组件图标。集中放,避免散落到各 block 文件。 */\nexport const icons = {\n html: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\"><rect x=\"3.5\" y=\"4\" width=\"17\" height=\"16\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><path d=\"M8 8.5l3 3.5-3 3.5M16 8.5l-3 3.5 3 3.5\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`,\n text: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M5 6h14M5 10h14M5 14h10M5 18h8\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" fill=\"none\"/></svg>`,\n image: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><rect x=\"3.5\" y=\"5\" width=\"17\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\"/><circle cx=\"9\" cy=\"10\" r=\"1.5\" fill=\"currentColor\"/><path d=\"M4 18l5-5 4 4 3-3 4 4\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`,\n hero: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"6\" width=\"18\" height=\"12\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><path d=\"M6 14h5M6 17h8\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/></svg>`,\n button: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"8\" rx=\"4\" fill=\"currentColor\" opacity=\"0.75\"/></svg>`,\n divider: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M3 12h18\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/></svg>`,\n spacer: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M5 8h14M5 16h14\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/><path d=\"M12 9v6\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/><path d=\"M9 12l3-3 3 3M9 12l3 3 3-3\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linejoin=\"round\"/></svg>`,\n logo: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M5 18V6l7 6 7-6v12\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linejoin=\"round\"/></svg>`,\n social: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><circle cx=\"6\" cy=\"12\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><circle cx=\"18\" cy=\"12\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/></svg>`,\n footer: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><rect x=\"3.5\" y=\"5\" width=\"17\" height=\"10\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><path d=\"M5 18h14\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/></svg>`,\n socialGroup: `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/><circle cx=\"8\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.4\"/><circle cx=\"12\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.4\"/><circle cx=\"16\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.4\"/></svg>`,\n};\n","import { defineBlock, blockButtonWidthCss } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface ButtonProps {\n text: string;\n href: string;\n backgroundColor: string;\n color: string;\n borderRadius: number;\n align: 'left' | 'center' | 'right';\n /** 留空或 auto 为自适应;可填 200px、80% 等 */\n width: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n innerPaddingV: number;\n innerPaddingH: number;\n fontSize: string;\n}\n\nconst escapeAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const buttonBlock = defineBlock<ButtonProps>({\n type: 'button',\n name: '按钮',\n category: 'content',\n icon: icons.button,\n defaultProps: {\n text: '立即查看',\n href: 'https://example.com',\n backgroundColor: '#4f46e5',\n color: '#ffffff',\n borderRadius: 6,\n align: 'center',\n width: '',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n innerPaddingV: 12,\n innerPaddingH: 24,\n fontSize: '14px',\n },\n schema: [\n { key: 'text', label: '文字', type: 'text' },\n { key: 'href', label: '链接', type: 'url' },\n { key: 'backgroundColor', label: '背景色', type: 'color' },\n { key: 'color', label: '文字颜色', type: 'color' },\n { key: 'borderRadius', label: '圆角 (px)', type: 'number', min: 0, max: 40 },\n { key: 'fontSize', label: '字号', type: 'text' },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n {\n key: 'width',\n label: '宽度',\n type: 'text',\n placeholder: '留空=自适应,如 280px、100%',\n help: '支持纯数字(按 px)、带 px 或百分比',\n },\n { key: 'innerPaddingV', label: '按钮内上下边距', type: 'number', min: 0, max: 40 },\n { key: 'innerPaddingH', label: '按钮内左右边距', type: 'number', min: 0, max: 60 },\n { key: 'paddingTop', label: '外边距', type: 'spacing' },\n ],\n inlineEditable: {\n selector: '.sm-button-text',\n mode: 'plain',\n multiline: false,\n propKey: 'text',\n placeholder: '按钮文字',\n },\n toMjml: (p) => {\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const innerPadding = `${p.innerPaddingV}px ${p.innerPaddingH}px`;\n const bw = blockButtonWidthCss(p.width);\n const widthAttr = bw ? ` width=\"${escapeAttr(bw)}\"` : '';\n return `<mj-button href=\"${escapeAttr(p.href)}\" background-color=\"${escapeAttr(\n p.backgroundColor,\n )}\" color=\"${escapeAttr(p.color)}\" border-radius=\"${p.borderRadius}px\" font-size=\"${escapeAttr(\n p.fontSize,\n )}\" align=\"${p.align}\" padding=\"${padding}\" inner-padding=\"${innerPadding}\"${widthAttr}>${escapeAttr(\n p.text,\n )}</mj-button>`;\n },\n renderPreview: (p) => {\n const bw = blockButtonWidthCss(p.width);\n const wst = bw ? `width:${bw};max-width:100%;box-sizing:border-box;` : '';\n /* 画布对 .sm-canvas a 设置了带 !important 的链接色,文字颜色必须写在子节点上才能生效 */\n return `<div style=\"padding:${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px;text-align:${p.align};\">\n <a href=\"${escapeAttr(p.href)}\" style=\"display:inline-block;background:${\n p.backgroundColor\n };border-radius:${p.borderRadius}px;padding:${p.innerPaddingV}px ${\n p.innerPaddingH\n }px;text-decoration:none;font-size:${p.fontSize};line-height:1.2;${wst}\"><span class=\"sm-button-text\" style=\"color:${\n p.color\n }\">${escapeAttr(p.text)}</span></a>\n </div>`;\n },\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface DividerProps {\n color: string;\n width: string;\n thickness: number;\n paddingTop: number;\n paddingBottom: number;\n}\n\nconst esc = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const dividerBlock = defineBlock<DividerProps>({\n type: 'divider',\n name: '分隔线',\n category: 'content',\n icon: icons.divider,\n defaultProps: {\n color: '#e6e8ec',\n width: '100%',\n thickness: 1,\n paddingTop: 8,\n paddingBottom: 8,\n },\n schema: [\n { key: 'color', label: '颜色', type: 'color' },\n { key: 'width', label: '宽度 (% 或 px)', type: 'text' },\n { key: 'thickness', label: '粗细 (px)', type: 'number', min: 1, max: 10 },\n { key: 'paddingTop', label: '上边距', type: 'number', min: 0, max: 80 },\n { key: 'paddingBottom', label: '下边距', type: 'number', min: 0, max: 80 },\n ],\n toMjml: (p) =>\n `<mj-divider border-color=\"${esc(p.color)}\" border-width=\"${p.thickness}px\" width=\"${esc(\n p.width,\n )}\" padding=\"${p.paddingTop}px 0px ${p.paddingBottom}px 0px\" />`,\n renderPreview: (p) =>\n `<div style=\"padding:${p.paddingTop}px 0 ${p.paddingBottom}px 0;\"><div style=\"border-top:${p.thickness}px solid ${p.color};width:${p.width};margin:0 auto;\"></div></div>`,\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface FooterProps {\n companyName: string;\n address: string;\n unsubscribeText: string;\n unsubscribeHref: string;\n textColor: string;\n}\n\nconst esc = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const footerBlock = defineBlock<FooterProps>({\n type: 'custom:footer',\n name: '页脚',\n category: 'custom',\n icon: icons.footer,\n defaultProps: {\n companyName: '你的公司',\n address: '上海市某区某路某号',\n unsubscribeText: '退订邮件',\n unsubscribeHref: '{{unsubscribeUrl}}',\n textColor: '#9aa0a6',\n },\n schema: [\n { key: 'companyName', label: '公司名称', type: 'text' },\n { key: 'address', label: '地址', type: 'text' },\n { key: 'unsubscribeText', label: '退订文案', type: 'text' },\n { key: 'unsubscribeHref', label: '退订链接', type: 'url' },\n { key: 'textColor', label: '文字颜色', type: 'color' },\n ],\n toMjml: (p) => {\n return `<mj-text align=\"center\" color=\"${esc(p.textColor)}\" font-size=\"12px\" line-height=\"1.6\" padding=\"8px 0px 8px 0px\">\n ${esc(p.companyName)}<br />\n ${esc(p.address)}<br />\n <a href=\"${esc(p.unsubscribeHref)}\" style=\"color:${esc(p.textColor)};\">${esc(p.unsubscribeText)}</a>\n</mj-text>`;\n },\n renderPreview: (p) => {\n return `<div style=\"padding:8px 0;text-align:center;font-size:12px;line-height:1.6;color:${p.textColor};\">\n ${esc(p.companyName)}<br/>\n ${esc(p.address)}<br/>\n <a href=\"${esc(p.unsubscribeHref)}\" style=\"color:${p.textColor};\">${esc(p.unsubscribeText)}</a>\n </div>`;\n },\n});\n","import { defineBlock, docContentWidthCss } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface HeroProps {\n backgroundUrl: string;\n backgroundColor: string;\n height: number;\n content: string;\n textAlign: 'left' | 'center' | 'right';\n textColor: string;\n verticalAlign: 'top' | 'middle' | 'bottom';\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nconst escapeAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const heroBlock = defineBlock<HeroProps>({\n type: 'hero',\n name: 'Hero 大图',\n category: 'content',\n icon: icons.hero,\n defaultProps: {\n backgroundUrl:\n 'https://placehold.co/600x320/312e81/c4b5fd/png?text=Hero+Background',\n backgroundColor: '#1e1b4b',\n height: 320,\n content:\n '<p style=\"margin:0;font-size:28px;font-weight:700;line-height:1.25;\">主标题落在大图上</p><p style=\"margin:12px 0 0;font-size:16px;font-weight:400;opacity:0.95;line-height:1.5;\">支援变量与 <strong>双击编辑</strong>,与正文组件一致。</p>',\n textAlign: 'center',\n textColor: '#ffffff',\n verticalAlign: 'middle',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n { key: 'backgroundUrl', label: '背景图', type: 'image' },\n { key: 'backgroundColor', label: '背景占位色', type: 'color', help: '图片加载失败时的底色' },\n { key: 'height', label: '区域高度 (px)', type: 'number', min: 120, max: 1200, step: 1 },\n {\n key: 'verticalAlign',\n label: '文字垂直位置',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '靠上', value: 'top' },\n { label: '居中', value: 'middle' },\n { label: '靠下', value: 'bottom' },\n ],\n },\n {\n key: 'textAlign',\n label: '文字水平对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'textColor', label: '文字颜色', type: 'color' },\n { key: 'paddingTop', label: '内边距', type: 'spacing' },\n {\n key: 'content',\n label: '正文(HTML)',\n type: 'textarea',\n help: '建议在画布内双击编辑;此处供高级修改。',\n },\n ],\n inlineEditable: {\n selector: '.sm-hero-content',\n mode: 'rich',\n multiline: true,\n propKey: 'content',\n placeholder: '编写覆盖在图片上的文案…',\n },\n toMjml: (p, ctx) => {\n const w = docContentWidthCss(ctx.doc.meta.width);\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const h = `${p.height}px`;\n return `<mj-hero\n mode=\"fixed-height\"\n height=\"${h}\"\n background-width=\"${w}\"\n background-height=\"${h}\"\n background-url=\"${escapeAttr(p.backgroundUrl)}\"\n background-color=\"${escapeAttr(p.backgroundColor)}\"\n padding=\"${padding}\"\n vertical-align=\"${p.verticalAlign}\"\n >\n <mj-text\n align=\"${p.textAlign}\"\n color=\"${escapeAttr(p.textColor)}\"\n padding=\"0\"\n >${p.content}</mj-text>\n </mj-hero>`;\n },\n renderPreview: (p, ctx) => {\n const w = docContentWidthCss(ctx.doc.meta.width);\n const flexAlign =\n p.verticalAlign === 'top' ? 'flex-start' : p.verticalAlign === 'bottom' ? 'flex-end' : 'center';\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const url = escapeAttr(p.backgroundUrl);\n return `<div\n style=\"\n box-sizing:border-box;\n width:100%;\n max-width:${w};\n min-height:${p.height}px;\n margin:0 auto;\n background-image:linear-gradient(to bottom,rgba(0,0,0,0.25),rgba(0,0,0,0.35)),url(${url});\n background-size:cover;\n background-position:center;\n background-color:${p.backgroundColor};\n display:flex;\n align-items:${flexAlign};\n justify-content:${p.textAlign === 'right' ? 'flex-end' : p.textAlign === 'center' ? 'center' : 'flex-start'};\n padding:${padding};\n color:${escapeAttr(p.textColor)};\n overflow:hidden;\n border-radius:2px;\n \"\n >\n <div\n class=\"sm-hero-content\"\n style=\"\n width:100%;\n text-align:${p.textAlign};\n color:${escapeAttr(p.textColor)};\n text-shadow:0 1px 2px rgba(0,0,0,0.45);\n \"\n >${p.content}</div>\n </div>`;\n },\n});\n","import {\n defineBlock,\n htmlContainsMjmlTags,\n mjRawCellTypographyFromStyles,\n mjRawEmailTableWrap,\n} from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface HtmlBlockProps {\n html: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nexport const htmlBlock = defineBlock<HtmlBlockProps>({\n type: 'html',\n name: 'HTML',\n category: 'content',\n icon: icons.html,\n defaultProps: {\n html: '<p style=\"margin:0;\">在此写入任意 HTML,将经 <strong>mj-raw</strong> 原样输出到邮件。支持变量 {{user.name}}</p>',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n {\n key: 'html',\n label: 'HTML',\n type: 'textarea',\n help: '只写 HTML(如 <a>、<table>),不要写 <mj-text> 等 MJML 标签;MJML 标签在 mj-raw 内不会被编译。简单链接建议用「文本」块。',\n },\n { key: 'paddingTop', label: '内边距', type: 'spacing' },\n ],\n inlineEditable: {\n selector: '.sm-html-content',\n mode: 'html',\n multiline: true,\n propKey: 'html',\n placeholder: '输入 HTML…',\n },\n toMjml: (p, ctx) => {\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n return mjRawEmailTableWrap(padding, p.html, mjRawCellTypographyFromStyles(ctx.doc.styles));\n },\n renderPreview: (p) => {\n const pad = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const warn = htmlContainsMjmlTags(p.html)\n ? '<div class=\"sm-html-mjml-warn\">检测到 MJML 标签,此处应只写 HTML,预览可能显示异常。</div>'\n : '';\n return `<div class=\"sm-html-content\" style=\"padding:${pad};min-height:1em;\">${warn}${p.html}</div>`;\n },\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface ImageProps {\n src: string;\n alt: string;\n href: string;\n width: number;\n /** 0 表示不限制高度,按原图比例自适应(推荐邮件场景) */\n height: number;\n align: 'left' | 'center' | 'right';\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nconst escapeAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const imageBlock = defineBlock<ImageProps>({\n type: 'image',\n name: '图片',\n category: 'content',\n icon: icons.image,\n defaultProps: {\n src: 'https://placehold.co/600x240/EEF2FF/4F46E5/png?text=600x240',\n alt: '',\n href: '',\n width: 480,\n height: 0,\n align: 'center',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n { key: 'src', label: '图片地址', type: 'image' },\n { key: 'alt', label: '替代文本', type: 'text', placeholder: '图片描述' },\n { key: 'href', label: '点击跳转', type: 'url', placeholder: 'https://...' },\n { key: 'width', label: '宽度 (px)', type: 'number', min: 40, max: 600 },\n {\n key: 'height',\n label: '高度 (px)(0 为自适应)',\n type: 'number',\n min: 0,\n max: 1200,\n help: '0 为自适应高度;填写固定值时画布与 MJML 会限制显示高度(预览可用 object-fit: cover)',\n },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'paddingTop', label: '内边距', type: 'spacing' },\n ],\n toMjml: (p) => {\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const href = p.href ? ` href=\"${escapeAttr(p.href)}\"` : '';\n const alt = ` alt=\"${escapeAttr(p.alt || '')}\"`;\n const h = p.height != null && p.height > 0 ? ` height=\"${p.height}px\"` : '';\n return `<mj-image src=\"${escapeAttr(p.src)}\"${alt}${href} width=\"${p.width}px\"${h} align=\"${p.align}\" padding=\"${padding}\" />`;\n },\n renderPreview: (p) => {\n const align = p.align === 'center' ? 'margin:0 auto;' : p.align === 'right' ? 'margin-left:auto;' : '';\n const fixedH = p.height != null && p.height > 0 ? p.height : 0;\n const sizeStyle =\n fixedH > 0\n ? `width:${p.width}px;height:${fixedH}px;object-fit:cover;object-position:center;`\n : `width:${p.width}px;height:auto;`;\n return `<div style=\"padding:${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px;text-align:${p.align};\"><img src=\"${escapeAttr(\n p.src,\n )}\" alt=\"${escapeAttr(p.alt)}\" style=\"display:block;${align}max-width:100%;${sizeStyle}border:0;outline:none;\" /></div>`;\n },\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\n/** 公司 Logo —— 一个语义化的\"图片+链接\"封装,便于运营快速放置品牌资产。 */\ninterface LogoProps {\n src: string;\n href: string;\n width: number;\n align: 'left' | 'center' | 'right';\n}\n\nconst esc = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nexport const logoBlock = defineBlock<LogoProps>({\n type: 'custom:logo',\n name: '公司 Logo',\n category: 'custom',\n icon: icons.logo,\n defaultProps: {\n src: 'https://placehold.co/240x60/1f2328/ffffff/png?text=YOUR+LOGO',\n href: 'https://example.com',\n width: 160,\n align: 'center',\n },\n schema: [\n { key: 'src', label: 'Logo 图片', type: 'image' },\n { key: 'href', label: '官网链接', type: 'url' },\n { key: 'width', label: '宽度 (px)', type: 'number', min: 60, max: 400 },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n ],\n toMjml: (p) =>\n `<mj-image src=\"${esc(p.src)}\" href=\"${esc(p.href)}\" width=\"${p.width}px\" align=\"${p.align}\" alt=\"logo\" padding=\"8px 0px 8px 0px\" />`,\n renderPreview: (p) => {\n const m =\n p.align === 'center' ? 'margin:0 auto;' : p.align === 'right' ? 'margin-left:auto;' : '';\n return `<div style=\"padding:8px 0;text-align:${p.align};\"><img src=\"${esc(\n p.src,\n )}\" alt=\"logo\" style=\"display:block;${m}width:${p.width}px;max-width:100%;height:auto;\" /></div>`;\n },\n});\n","import { normalizeFontWeightStep } from '@simple-mail/core';\n\n/** 生成 mj-social-element 的 name 属性(与 MJML 内置图标对齐;未知平台退化为 web)。 */\nexport function mjSocialElementName(network: string): string {\n const n = network.trim();\n if (n === 'ig') return 'instagram';\n if (n === 'rabbit' || n === 'tiktok' || n === 'reddit') return 'web';\n return n;\n}\n\n/** 业务示例:固定海外/垂类五平台(与 custom:social 块配套)。 */\nexport const BIZ_SOCIAL_NETWORK_OPTIONS: { label: string; value: string }[] = [\n { label: 'X', value: 'x' },\n { label: 'Rabbit', value: 'rabbit' },\n { label: 'Facebook', value: 'facebook' },\n { label: 'TikTok', value: 'tiktok' },\n { label: 'Instagram', value: 'ig' },\n];\n\n/** 社交平台与 MJML mj-social-element 的 name 对齐(含常用内置名)。 */\nexport const SOCIAL_NETWORK_OPTIONS: { label: string; value: string }[] = [\n { label: '微信', value: 'wechat' },\n { label: '微博', value: 'weibo' },\n { label: 'X', value: 'x' },\n { label: 'LinkedIn', value: 'linkedin' },\n { label: 'GitHub', value: 'github' },\n { label: 'Facebook', value: 'facebook' },\n { label: 'Instagram', value: 'instagram' },\n { label: 'YouTube', value: 'youtube' },\n { label: 'Reddit', value: 'reddit' },\n { label: '网页', value: 'web' },\n];\n\nconst NETWORK_META: Record<string, { color: string; preview: string }> = {\n wechat: { color: '#1AAD19', preview: '信' },\n weibo: { color: '#E6162D', preview: '微' },\n x: { color: '#000000', preview: 'X' },\n linkedin: { color: '#0A66C2', preview: 'in' },\n github: { color: '#181717', preview: 'GH' },\n facebook: { color: '#1877F2', preview: 'f' },\n instagram: { color: '#E4405F', preview: '◎' },\n ig: { color: '#E4405F', preview: '◎' },\n youtube: { color: '#FF0000', preview: '▶' },\n reddit: { color: '#FF4500', preview: 'r' },\n tiktok: { color: '#000000', preview: '♪' },\n rabbit: { color: '#FF2442', preview: 'R' },\n website: { color: '#6b7280', preview: '◇' },\n web: { color: '#6b7280', preview: '◇' },\n};\n\nexport const escAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\n/** mj-social-element 体内文本转义(非属性) */\nexport const escMjmlText = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n\nexport interface SocialLinkItem {\n network: string;\n href: string;\n /** 图标旁文字,对应 mj-social-element 子内容 */\n label?: string;\n /** 自定义图标 URL,对应 mj-social-element src */\n iconSrc?: string;\n /** 图标区域背景色;未设则用平台预设 */\n backgroundColor?: string;\n}\n\n/** 社交组块级:所有带标签的链接共用同一套标签文字样式 */\nexport interface SocialGroupLabelStyle {\n labelFontSize: number;\n labelFontWeight: string;\n labelColor: string;\n}\n\nexport function socialMeta(network: string): { color: string; preview: string } {\n return NETWORK_META[network] ?? { color: '#6b7280', preview: '·' };\n}\n\n/** MJML 内置社交图标 CDN(与 mjml-browser 4.x 一致) */\nexport const MJML_SOCIAL_ICON_BASE =\n 'https://www.mailjet.com/images/theme/v1/icons/ico-social/';\n\n/** MJML `mj-social-element` name → 图标文件名 */\nconst MJML_SOCIAL_ICON_FILES: Record<string, string> = {\n facebook: 'facebook.png',\n twitter: 'twitter.png',\n x: 'twitter-x.png',\n google: 'google-plus.png',\n pinterest: 'pinterest.png',\n linkedin: 'linkedin.png',\n instagram: 'instagram.png',\n web: 'web.png',\n snapchat: 'snapchat.png',\n youtube: 'youtube.png',\n tumblr: 'tumblr.png',\n github: 'github.png',\n xing: 'xing.png',\n vimeo: 'vimeo.png',\n medium: 'medium.png',\n soundcloud: 'soundcloud.png',\n dribbble: 'dribbble.png',\n};\n\n/** 画布预览用默认图标 URL(与 MJML `name` 映射一致;无内置图时返回 null) */\nexport function mjSocialDefaultIconSrc(network: string): string | null {\n const file = MJML_SOCIAL_ICON_FILES[mjSocialElementName(network)];\n return file ? `${MJML_SOCIAL_ICON_BASE}${file}` : null;\n}\n\n/** 画布 / renderPreview 社交图标 HTML(优先自定义 URL,其次 MJML 内置图,最后文字占位) */\nexport function renderSocialIconPreviewHtml(opts: {\n network: string;\n iconSize: number;\n iconBorderRadius: number;\n iconSrc?: string;\n backgroundColor?: string;\n}): string {\n const { network, iconSize, iconBorderRadius, iconSrc, backgroundColor } = opts;\n const radiusCss = socialIconBorderRadiusCss(iconSize, iconBorderRadius);\n const meta = socialMeta(network);\n const bg = backgroundColor?.trim() || meta.color;\n const src = iconSrc?.trim() || mjSocialDefaultIconSrc(network);\n if (src) {\n return `<span style=\"display:inline-flex;width:${iconSize}px;height:${iconSize}px;border-radius:${radiusCss};background:${bg};overflow:hidden;align-items:center;justify-content:center;flex-shrink:0;line-height:0;\"><img src=\"${escAttr(src)}\" alt=\"\" width=\"${iconSize}\" height=\"${iconSize}\" style=\"display:block;width:${iconSize}px;height:${iconSize}px;border-radius:${radiusCss};\" /></span>`;\n }\n return `<span style=\"display:inline-flex;width:${iconSize}px;height:${iconSize}px;border-radius:${radiusCss};background:${bg};color:#fff;align-items:center;justify-content:center;font-size:${Math.round(\n iconSize / 2,\n )}px;font-weight:600;flex-shrink:0;overflow:hidden;\">${meta.preview}</span>`;\n}\n\nexport function paddingQuad(p: {\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}): string {\n return `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n}\n\n/** mj-social `border-radius`:0 直角;≥999 或 ≥图标半边 → 圆形裁切(999px) */\nexport function socialIconBorderRadiusMjml(iconSize: number, radiusPx: unknown): string {\n const size = Math.max(1, Number(iconSize) || 28);\n const r = Number(radiusPx);\n if (!Number.isFinite(r) || r <= 0) return '0px';\n const half = size / 2;\n if (r >= 999 || r >= half) return '999px';\n return `${Math.min(r, size)}px`;\n}\n\n/** 画布预览用图标圆角 CSS(与 {@link socialIconBorderRadiusMjml} 语义一致) */\nexport function socialIconBorderRadiusCss(iconSize: number, radiusPx: unknown): string {\n const size = Math.max(1, Number(iconSize) || 28);\n const r = Number(radiusPx);\n if (!Number.isFinite(r) || r <= 0) return '0';\n const half = size / 2;\n if (r >= 999 || r >= half) return '50%';\n return `${Math.min(r, size)}px`;\n}\n\n/** mj-social `inner-padding`,控制图标之间的可视间距 */\nexport function socialIconSpacingPx(spacing: unknown, fallback = 10): number {\n const n = Number(spacing);\n if (!Number.isFinite(n) || n < 0) return fallback;\n return Math.min(64, Math.round(n));\n}\n\nexport function flexJustifyFromAlign(align: 'left' | 'center' | 'right'): string {\n if (align === 'right') return 'flex-end';\n if (align === 'left') return 'flex-start';\n return 'center';\n}\n\nexport function mjSocialElementsLines(\n links: SocialLinkItem[],\n labelStyle: SocialGroupLabelStyle,\n): string {\n const fontSizeRaw = labelStyle.labelFontSize > 0 ? labelStyle.labelFontSize : 13;\n const fontSize = Math.max(8, Math.min(48, fontSizeRaw));\n const fontWeight = normalizeFontWeightStep(labelStyle.labelFontWeight);\n const textColor = labelStyle.labelColor?.trim() || '#333333';\n const fwEsc = escAttr(fontWeight);\n return links\n .map((l) => {\n const meta = socialMeta(l.network);\n const bgColor = l.backgroundColor?.trim() || meta.color;\n const attrs = [\n `name=\"${escAttr(mjSocialElementName(l.network))}\"`,\n `href=\"${escAttr(l.href)}\"`,\n `background-color=\"${escAttr(bgColor)}\"`,\n `color=\"${escAttr(textColor)}\"`,\n `font-size=\"${fontSize}px\"`,\n `font-weight=\"${fwEsc}\"`,\n ];\n const attrStr = attrs.join(' ');\n const src = l.iconSrc?.trim();\n const withSrc = src ? `${attrStr} src=\"${escAttr(src)}\"` : attrStr;\n const label = l.label?.trim() ?? '';\n if (!label) {\n return ` <mj-social-element ${withSrc} />`;\n }\n return ` <mj-social-element ${withSrc}>\\n ${escMjmlText(label)}\\n </mj-social-element>`;\n })\n .join('\\n');\n}\n","import { defineBlock, FONT_WEIGHT_STEP_OPTIONS, normalizeFontWeightStep } from '@simple-mail/core';\nimport { icons } from './icons';\nimport {\n BIZ_SOCIAL_NETWORK_OPTIONS,\n escAttr,\n flexJustifyFromAlign,\n mjSocialElementsLines,\n paddingQuad,\n socialIconBorderRadiusMjml,\n renderSocialIconPreviewHtml,\n socialIconSpacingPx,\n type SocialLinkItem,\n} from './socialShared';\n\n/** 与社交组一致,仅平台选项收窄为业务五件套 */\ninterface SocialBizProps {\n elements: SocialLinkItem[];\n align: 'left' | 'center' | 'right';\n iconSize: number;\n iconBorderRadius: number;\n iconSpacing: number;\n labelFontSize: number;\n labelFontWeight: string;\n labelColor: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n /** 旧版自定义块:`links` + textarea,仅用于兼容读入 */\n links?: { network: string; href: string }[];\n}\n\nconst DEFAULT_BIZ_ELEMENTS: SocialLinkItem[] = [\n { network: 'x', href: 'https://x.com/' },\n { network: 'rabbit', href: 'https://example.com' },\n { network: 'facebook', href: 'https://facebook.com/' },\n { network: 'tiktok', href: 'https://www.tiktok.com/' },\n { network: 'ig', href: 'https://instagram.com/' },\n];\n\nfunction normalizeElements(p: SocialBizProps): SocialLinkItem[] {\n if (p.elements?.length) return p.elements;\n const legacy = p.links;\n if (Array.isArray(legacy) && legacy.length)\n return legacy.map((l) => ({\n network: String(l.network ?? 'web'),\n href: String(l.href ?? ''),\n }));\n return DEFAULT_BIZ_ELEMENTS;\n}\n\nexport const socialBlock = defineBlock<SocialBizProps>({\n type: 'custom:social',\n name: '社交链接',\n category: 'custom',\n icon: icons.social,\n defaultProps: {\n elements: DEFAULT_BIZ_ELEMENTS,\n align: 'center',\n iconSize: 28,\n iconBorderRadius: 999,\n iconSpacing: 10,\n labelFontSize: 13,\n labelFontWeight: '400',\n labelColor: '#333333',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n {\n key: 'elements',\n label: '社交链接',\n type: 'socialLinkList',\n options: BIZ_SOCIAL_NETWORK_OPTIONS,\n help: '平台:X、Rabbit、Facebook、TikTok、Instagram (ig)。可填标签、自定义图标 URL。MJML 侧 Rabbit/TikTok 使用 web 占位图标,需要品牌图时请填「图标 URL」。',\n },\n {\n key: 'labelFontSize',\n label: '标签字号 (px)',\n type: 'number',\n min: 8,\n max: 48,\n step: 1,\n },\n {\n key: 'labelFontWeight',\n label: '标签字重',\n type: 'select',\n selectVariant: 'segmented',\n options: [...FONT_WEIGHT_STEP_OPTIONS],\n },\n { key: 'labelColor', label: '标签颜色', type: 'color' },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'iconSize', label: '图标尺寸 (px)', type: 'number', min: 16, max: 64 },\n {\n key: 'iconBorderRadius',\n label: '图标圆角 (px)',\n type: 'number',\n min: 0,\n max: 999,\n step: 1,\n help: '0 为方形直角;较大值(如 999)为圆形(默认)。',\n },\n {\n key: 'iconSpacing',\n label: '图标间距 (px)',\n type: 'number',\n min: 0,\n max: 64,\n step: 1,\n help: '图标之间的间隔(MJML inner-padding)。',\n },\n { key: 'paddingTop', label: '外边距', type: 'spacing' },\n ],\n toMjml: (p) => {\n const pad = paddingQuad(p);\n const br = socialIconBorderRadiusMjml(p.iconSize, p.iconBorderRadius ?? 999);\n const gap = socialIconSpacingPx(p.iconSpacing, 10);\n const socAttrs = `align=\"${p.align}\" icon-size=\"${p.iconSize}px\" mode=\"horizontal\" border-radius=\"${br}\" inner-padding=\"${gap}px\" padding=\"${pad}\"`;\n const els = normalizeElements(p).filter((e) => e.href?.trim());\n const labelStyle = {\n labelFontSize: Number(p.labelFontSize ?? 13),\n labelFontWeight: normalizeFontWeightStep(String(p.labelFontWeight ?? '400')),\n labelColor: String(p.labelColor ?? '#333333'),\n };\n const inner = mjSocialElementsLines(els, labelStyle);\n if (!inner.trim()) {\n return `<mj-social ${socAttrs}></mj-social>`;\n }\n return `<mj-social ${socAttrs}>\n${inner}\n</mj-social>`;\n },\n renderPreview: (p) => {\n const fsRaw = p.labelFontSize != null && p.labelFontSize > 0 ? p.labelFontSize : 13;\n const fs = Math.max(8, Math.min(48, fsRaw));\n const fw = normalizeFontWeightStep(p.labelFontWeight);\n const textColor = p.labelColor?.trim() || '#333333';\n const gap = socialIconSpacingPx(p.iconSpacing, 10);\n const jc = flexJustifyFromAlign(p.align);\n const items = normalizeElements(p)\n .filter((l) => l.href?.trim())\n .map((l) => {\n const label = l.label?.trim() ?? '';\n const iconHtml = renderSocialIconPreviewHtml({\n network: l.network,\n iconSize: p.iconSize,\n iconBorderRadius: p.iconBorderRadius ?? 999,\n iconSrc: l.iconSrc,\n backgroundColor: l.backgroundColor,\n });\n const textHtml = label\n ? `<span style=\"font-size:${fs}px !important;font-weight:${fw};color:${escAttr(\n textColor,\n )} !important;line-height:1.2;\">${escAttr(label)}</span>`\n : '';\n return `<span style=\"display:inline-flex;align-items:center;gap:6px;\"><a href=\"${escAttr(\n l.href,\n )}\" style=\"display:inline-flex;align-items:center;text-decoration:none;line-height:0;\">${iconHtml}</a>${textHtml}</span>`;\n })\n .join('');\n const pad = paddingQuad(p);\n return `<div style=\"display:flex;flex-wrap:wrap;justify-content:${jc};align-items:center;gap:${gap}px;padding:${pad};\">${items || '<span style=\"color:#9ca3af;font-size:12px;\">请填写链接 URL</span>'}</div>`;\n },\n});\n","import { defineBlock, FONT_WEIGHT_STEP_OPTIONS, normalizeFontWeightStep } from '@simple-mail/core';\nimport { icons } from './icons';\nimport {\n escAttr,\n flexJustifyFromAlign,\n mjSocialElementsLines,\n paddingQuad,\n socialIconBorderRadiusMjml,\n renderSocialIconPreviewHtml,\n socialIconSpacingPx,\n SOCIAL_NETWORK_OPTIONS,\n type SocialLinkItem,\n} from './socialShared';\n\ninterface SocialGroupProps {\n elements: SocialLinkItem[];\n align: 'left' | 'center' | 'right';\n iconSize: number;\n /** 图标圆角 (px)。0 为方形;≥999 或不少于图标半边时为圆形(默认 999) */\n iconBorderRadius: number;\n /** 图标之间的间距 (px),对应 mj-social inner-padding */\n iconSpacing: number;\n /** 标签文字字号(整组统一) */\n labelFontSize: number;\n labelFontWeight: string;\n labelColor: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nexport const socialGroupBlock = defineBlock<SocialGroupProps>({\n type: 'social-group',\n name: '社交组',\n category: 'content',\n icon: icons.socialGroup,\n defaultProps: {\n elements: [\n { network: 'weibo', href: 'https://weibo.com' },\n { network: 'wechat', href: 'https://example.com' },\n ],\n align: 'center',\n iconSize: 28,\n iconBorderRadius: 999,\n iconSpacing: 10,\n labelFontSize: 13,\n labelFontWeight: '400',\n labelColor: '#333333',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n {\n key: 'elements',\n label: '社交链接',\n type: 'socialLinkList',\n options: SOCIAL_NETWORK_OPTIONS,\n help: '每行:平台、链接、可选标签文字、自定义图标 URL、图标背景色。标签的字号/字重/颜色在下方统一设置。',\n },\n {\n key: 'labelFontSize',\n label: '标签字号 (px)',\n type: 'number',\n min: 8,\n max: 48,\n step: 1,\n },\n {\n key: 'labelFontWeight',\n label: '标签字重',\n type: 'select',\n selectVariant: 'segmented',\n options: [...FONT_WEIGHT_STEP_OPTIONS],\n },\n { key: 'labelColor', label: '标签颜色', type: 'color' },\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'iconSize', label: '图标尺寸 (px)', type: 'number', min: 16, max: 64 },\n {\n key: 'iconBorderRadius',\n label: '图标圆角 (px)',\n type: 'number',\n min: 0,\n max: 999,\n step: 1,\n help: '0 为方形直角;填较大值(如 999)或与尺寸一半相当时为圆形(默认圆形)。',\n },\n {\n key: 'iconSpacing',\n label: '图标间距 (px)',\n type: 'number',\n min: 0,\n max: 64,\n step: 1,\n help: '每个图标周围的留白,横向即图标之间的间隔(MJML inner-padding)。',\n },\n { key: 'paddingTop', label: '外边距', type: 'spacing' },\n ],\n toMjml: (p) => {\n const pad = paddingQuad(p);\n const br = socialIconBorderRadiusMjml(p.iconSize, p.iconBorderRadius ?? 999);\n const gap = socialIconSpacingPx(p.iconSpacing, 10);\n const socAttrs = `align=\"${p.align}\" icon-size=\"${p.iconSize}px\" mode=\"horizontal\" border-radius=\"${br}\" inner-padding=\"${gap}px\" padding=\"${pad}\"`;\n const filtered = p.elements.filter((e) => e.href?.trim());\n const labelStyle = {\n labelFontSize: Number(p.labelFontSize ?? 13),\n labelFontWeight: normalizeFontWeightStep(String(p.labelFontWeight ?? '400')),\n labelColor: String(p.labelColor ?? '#333333'),\n };\n const inner = mjSocialElementsLines(filtered, labelStyle);\n if (!inner.trim()) {\n return `<mj-social ${socAttrs}></mj-social>`;\n }\n return `<mj-social ${socAttrs}>\n${inner}\n</mj-social>`;\n },\n renderPreview: (p) => {\n const fsRaw = p.labelFontSize != null && p.labelFontSize > 0 ? p.labelFontSize : 13;\n const fs = Math.max(8, Math.min(48, fsRaw));\n const fw = normalizeFontWeightStep(p.labelFontWeight);\n const textColor = p.labelColor?.trim() || '#333333';\n const gap = socialIconSpacingPx(p.iconSpacing, 10);\n const jc = flexJustifyFromAlign(p.align);\n const items = p.elements\n .filter((l) => l.href?.trim())\n .map((l) => {\n const label = l.label?.trim() ?? '';\n const iconHtml = renderSocialIconPreviewHtml({\n network: l.network,\n iconSize: p.iconSize,\n iconBorderRadius: p.iconBorderRadius ?? 999,\n iconSrc: l.iconSrc,\n backgroundColor: l.backgroundColor,\n });\n const textHtml = label\n ? `<span style=\"font-size:${fs}px !important;font-weight:${fw};color:${escAttr(\n textColor,\n )} !important;line-height:1.2;\">${escAttr(label)}</span>`\n : '';\n return `<span style=\"display:inline-flex;align-items:center;gap:6px;\"><a href=\"${escAttr(\n l.href,\n )}\" style=\"display:inline-flex;align-items:center;text-decoration:none;line-height:0;\">${iconHtml}</a>${textHtml}</span>`;\n })\n .join('');\n const pad = paddingQuad(p);\n return `<div style=\"display:flex;flex-wrap:wrap;justify-content:${jc};align-items:center;gap:${gap}px;padding:${pad};\">${items || '<span style=\"color:#9ca3af;font-size:12px;\">请添加社交链接</span>'}</div>`;\n },\n});\n","import { defineBlock } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface SpacerProps {\n height: number;\n}\n\nexport const spacerBlock = defineBlock<SpacerProps>({\n type: 'spacer',\n name: '间距',\n category: 'content',\n icon: icons.spacer,\n defaultProps: { height: 24 },\n schema: [{ key: 'height', label: '高度 (px)', type: 'number', min: 1, max: 200 }],\n toMjml: (p) => `<mj-spacer height=\"${p.height}px\" />`,\n renderPreview: (p) => `<div style=\"height:${p.height}px;line-height:${p.height}px;\"></div>`,\n});\n","import { defineBlock, FONT_WEIGHT_STEP_OPTIONS, isRichHtmlEffectivelyEmpty, normalizeFontWeightStep } from '@simple-mail/core';\nimport { icons } from './icons';\n\ninterface TextProps {\n content: string;\n align: 'left' | 'center' | 'right';\n color: string;\n fontSize: string;\n fontFamily: string;\n fontWeight: string;\n /** 空字符串:与邮件全局行距(mj-head)一致 */\n lineHeight: string;\n paddingTop: number;\n paddingRight: number;\n paddingBottom: number;\n paddingLeft: number;\n}\n\nconst escapeAttr = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n\nconst TEXT_PLACEHOLDER = '输入文本…';\n\nexport const textBlock = defineBlock<TextProps>({\n type: 'text',\n name: '文本',\n category: 'content',\n icon: icons.text,\n defaultProps: {\n content:\n '<p style=\"margin:0;\">在此处输入文本。<strong>双击</strong>进入编辑模式,<em>选中文字</em>会出现工具条;支持变量 {{user.name}}</p>',\n align: 'left',\n color: '',\n fontSize: '',\n fontFamily: '',\n fontWeight: '',\n lineHeight: '',\n paddingTop: 8,\n paddingRight: 0,\n paddingBottom: 8,\n paddingLeft: 0,\n },\n schema: [\n {\n key: 'align',\n label: '对齐',\n type: 'select',\n selectVariant: 'segmented',\n options: [\n { label: '左', value: 'left' },\n { label: '居中', value: 'center' },\n { label: '右', value: 'right' },\n ],\n },\n { key: 'color', label: '颜色', type: 'color', placeholder: '继承全局' },\n { key: 'fontSize', label: '字号', type: 'text', inheritGlobal: true },\n { key: 'fontFamily', label: '字体', type: 'text', placeholder: '继承全局' },\n {\n key: 'fontWeight',\n label: '字重',\n type: 'select',\n selectVariant: 'segmented',\n inheritGlobal: true,\n options: [...FONT_WEIGHT_STEP_OPTIONS],\n },\n {\n key: 'lineHeight',\n label: '行高',\n type: 'select',\n help: '留空则使用邮件设置里的全局行距',\n options: [\n { label: '继承全局', value: '' },\n { label: '1.0', value: '1' },\n { label: '1.15', value: '1.15' },\n { label: '1.25', value: '1.25' },\n { label: '1.4', value: '1.4' },\n { label: '1.5', value: '1.5' },\n { label: '1.75', value: '1.75' },\n { label: '2.0', value: '2' },\n { label: '22px', value: '22px' },\n { label: '24px', value: '24px' },\n { label: '28px', value: '28px' },\n { label: '32px', value: '32px' },\n ],\n },\n { key: 'paddingTop', label: '内边距', type: 'spacing' },\n {\n key: 'content',\n label: '内容(HTML,备用)',\n type: 'textarea',\n help: '建议直接在画布双击编辑;这里保留为高级编辑入口。',\n },\n ],\n inlineEditable: {\n selector: '.sm-text-content',\n mode: 'rich',\n multiline: true,\n propKey: 'content',\n placeholder: TEXT_PLACEHOLDER,\n },\n toMjml: (p) => {\n const padding = `${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px`;\n const ff = p.fontFamily ? ` font-family=\"${escapeAttr(p.fontFamily)}\"` : '';\n const fwRaw = String(p.fontWeight ?? '').trim();\n const fw = fwRaw ? ` font-weight=\"${escapeAttr(normalizeFontWeightStep(fwRaw))}\"` : '';\n const lh = String(p.lineHeight ?? '').trim();\n const lhAttr = lh ? ` line-height=\"${escapeAttr(lh)}\"` : '';\n const colorRaw = String(p.color ?? '').trim();\n const colorAttr = colorRaw ? ` color=\"${escapeAttr(colorRaw)}\"` : '';\n const fsRaw = String(p.fontSize ?? '').trim();\n const fsAttr = fsRaw ? ` font-size=\"${escapeAttr(fsRaw)}\"` : '';\n return `<mj-text align=\"${p.align}\"${colorAttr}${fsAttr}${lhAttr}${ff}${fw} padding=\"${padding}\">${p.content}</mj-text>`;\n },\n renderPreview: (p) => {\n const ff = p.fontFamily ? `font-family:${p.fontFamily};` : '';\n const fwRaw = String(p.fontWeight ?? '').trim();\n const fwCss = fwRaw ? `font-weight:${normalizeFontWeightStep(fwRaw)};` : '';\n const lhRaw = String(p.lineHeight ?? '').trim();\n const lh = lhRaw ? `line-height:${lhRaw};` : 'line-height:normal;';\n const colorRaw = String(p.color ?? '').trim();\n const colorCss = colorRaw ? `color:${colorRaw};` : '';\n const fsRaw = String(p.fontSize ?? '').trim();\n const fsCss = fsRaw ? `font-size:${fsRaw};` : '';\n const empty = isRichHtmlEffectivelyEmpty(p.content);\n const emptyClass = empty ? ' is-empty' : '';\n const placeholderAttr = empty ? ` data-placeholder=\"${TEXT_PLACEHOLDER}\"` : '';\n return `<div class=\"sm-text-content${emptyClass}\"${placeholderAttr} style=\"text-align:${p.align};${colorCss}${fsCss}${fwCss}${lh}${ff}padding:${p.paddingTop}px ${p.paddingRight}px ${p.paddingBottom}px ${p.paddingLeft}px;\">${p.content}</div>`;\n },\n});\n","import type { BlockDefinition, BlockSchemaField, SimpleMailT } from '@simple-mail/core';\n\ntype AnyBlock = BlockDefinition<any>;\n\nconst FIELD_LABEL_KEYS: Record<string, string> = {\n align: 'blocks.field.align',\n textAlign: 'blocks.field.textAlign',\n verticalAlign: 'blocks.field.verticalAlign',\n color: 'blocks.field.color',\n textColor: 'blocks.field.textColor',\n backgroundColor: 'blocks.field.backgroundColor',\n backgroundUrl: 'blocks.field.backgroundUrl',\n height: 'blocks.field.heightPx',\n width: 'blocks.field.width',\n thickness: 'blocks.field.thicknessPx',\n paddingTop: 'blocks.field.padding',\n text: 'blocks.field.text',\n href: 'blocks.field.link',\n src: 'blocks.field.imageUrl',\n alt: 'blocks.field.alt',\n fontSize: 'blocks.field.fontSize',\n fontFamily: 'blocks.field.fontFamily',\n fontWeight: 'blocks.field.fontWeight',\n lineHeight: 'blocks.field.lineHeight',\n html: 'blocks.field.html',\n borderRadius: 'blocks.field.borderRadius',\n innerPaddingV: 'blocks.field.buttonInnerPaddingV',\n innerPaddingH: 'blocks.field.buttonInnerPaddingH',\n elements: 'blocks.field.socialLinks',\n labelFontSize: 'blocks.field.labelFontSize',\n labelFontWeight: 'blocks.field.labelFontWeight',\n labelColor: 'blocks.field.labelColor',\n iconSize: 'blocks.field.iconSize',\n iconBorderRadius: 'blocks.field.iconRadius',\n iconSpacing: 'blocks.field.iconSpacing',\n companyName: 'blocks.field.companyName',\n address: 'blocks.field.address',\n unsubscribeText: 'blocks.field.unsubscribeText',\n unsubscribeHref: 'blocks.field.unsubscribeLink',\n};\n\nconst BLOCK_FIELD_LABEL_KEYS: Record<string, Record<string, string>> = {\n button: {\n backgroundColor: 'blocks.field.backgroundColor',\n color: 'blocks.field.textColor',\n width: 'blocks.field.width',\n },\n divider: {\n width: 'blocks.field.widthPercentOrPx',\n paddingTop: 'blocks.field.topMargin',\n paddingBottom: 'blocks.field.bottomMargin',\n },\n hero: {\n backgroundColor: 'blocks.field.backgroundPlaceholderColor',\n height: 'blocks.field.areaHeightPx',\n content: 'blocks.field.bodyHtml',\n },\n html: {\n paddingTop: 'blocks.field.padding',\n },\n image: {\n href: 'blocks.field.href',\n width: 'blocks.field.widthPx',\n },\n logo: {\n src: 'blocks.field.logoImage',\n href: 'blocks.field.websiteLink',\n width: 'blocks.field.widthPx',\n },\n text: {\n content: 'blocks.field.contentHtml',\n },\n};\n\nconst HELP_KEYS: Record<string, Record<string, string>> = {\n button: { width: 'blocks.help.buttonWidth' },\n hero: {\n backgroundColor: 'blocks.help.imageFallbackColor',\n content: 'blocks.help.canvasEditRecommendedShort',\n },\n html: { html: 'blocks.help.htmlOnly' },\n image: { height: 'blocks.help.imageAutoHeight' },\n 'social-group': {\n elements: 'blocks.help.socialLinks',\n iconBorderRadius: 'blocks.help.iconRadius',\n iconSpacing: 'blocks.help.iconSpacing',\n },\n social: {\n elements: 'blocks.help.bizSocialLinks',\n iconBorderRadius: 'blocks.help.iconRadius',\n iconSpacing: 'blocks.help.bizIconSpacing',\n },\n text: {\n content: 'blocks.help.canvasEditRecommended',\n lineHeight: 'blocks.help.globalLineHeight',\n },\n};\n\nconst PLACEHOLDER_KEYS: Record<string, Record<string, string>> = {\n button: { width: 'blocks.placeholder.buttonWidth' },\n image: { alt: 'blocks.field.imageDescription' },\n text: {\n color: 'blocks.field.inheritGlobalPlaceholder',\n fontFamily: 'blocks.field.inheritGlobalPlaceholder',\n },\n};\n\nconst INLINE_PLACEHOLDER_KEYS: Record<string, string> = {\n button: 'blocks.field.buttonTextPlaceholder',\n hero: 'blocks.field.heroPlaceholder',\n html: 'blocks.field.htmlPlaceholder',\n text: 'blocks.field.textPlaceholder',\n};\n\nconst DEFAULT_PROP_KEYS: Record<string, Record<string, string>> = {\n button: { text: 'blocks.button.defaultText' },\n hero: { content: 'blocks.hero.defaultContent' },\n html: { html: 'blocks.html.defaultHtml' },\n text: { content: 'blocks.text.defaultContent' },\n footer: {\n companyName: 'blocks.footer.defaultCompanyName',\n address: 'blocks.footer.defaultAddress',\n unsubscribeText: 'blocks.footer.defaultUnsubscribeText',\n },\n};\n\nexport function localizeBlockDefinitions(blocks: AnyBlock[], t: SimpleMailT): AnyBlock[] {\n return blocks.map((block) => localizeBlockDefinition(block, t));\n}\n\nexport function localizeBlockDefinition(block: AnyBlock, t: SimpleMailT): AnyBlock {\n const blockKey = blockMessageId(block.type);\n const nameKey = `blocks.${blockKey}.name`;\n const translatedName = t(nameKey);\n const inlinePlaceholderText = inlinePlaceholder(blockKey, block, t);\n return {\n ...block,\n name: translatedName === nameKey ? block.name : translatedName,\n defaultProps: localizeDefaultProps(block, t),\n schema: block.schema.map((field) => localizeField(blockKey, field, t)),\n renderPreview: localizeRenderPreview(block, inlinePlaceholderText),\n inlineEditable: block.inlineEditable\n ? {\n ...block.inlineEditable,\n placeholder: inlinePlaceholderText,\n }\n : undefined,\n };\n}\n\nfunction localizeDefaultProps(block: AnyBlock, t: SimpleMailT): Record<string, unknown> {\n const props = { ...(block.defaultProps as Record<string, unknown>) };\n const propKeys = DEFAULT_PROP_KEYS[blockMessageId(block.type)] ?? {};\n for (const [prop, key] of Object.entries(propKeys)) {\n props[prop] = t(key);\n }\n return props;\n}\n\nfunction localizeField(blockType: string, field: BlockSchemaField, t: SimpleMailT): BlockSchemaField {\n const labelKey = BLOCK_FIELD_LABEL_KEYS[blockType]?.[field.key] ?? FIELD_LABEL_KEYS[field.key];\n return {\n ...field,\n label: labelKey ? t(labelKey) : field.label,\n placeholder: PLACEHOLDER_KEYS[blockType]?.[field.key]\n ? t(PLACEHOLDER_KEYS[blockType][field.key])\n : field.placeholder,\n help: HELP_KEYS[blockType]?.[field.key] ? t(HELP_KEYS[blockType][field.key]) : field.help,\n options: field.options?.map((option) => ({\n ...option,\n label: localizeOptionLabel(option, t),\n })),\n };\n}\n\nfunction localizeOptionLabel(\n option: { label: string; value: string },\n t: SimpleMailT,\n): string {\n if (option.value === 'left') return t('common.left');\n if (option.value === 'center') return t('common.center');\n if (option.value === 'right') return t('common.right');\n if (option.value === 'top') return t('blocks.option.top');\n if (option.value === 'middle') return t('blocks.option.middle');\n if (option.value === 'bottom') return t('blocks.option.bottom');\n if (option.value === '') return t('common.inheritGlobal');\n return option.label;\n}\n\nfunction inlinePlaceholder(blockType: string, block: AnyBlock, t: SimpleMailT): string | undefined {\n const key = INLINE_PLACEHOLDER_KEYS[blockType];\n return key ? t(key) : block.inlineEditable?.placeholder;\n}\n\nfunction localizeRenderPreview(\n block: AnyBlock,\n inlinePlaceholderText: string | undefined,\n): AnyBlock['renderPreview'] {\n if (!block.renderPreview || !block.inlineEditable?.placeholder || !inlinePlaceholderText) {\n return block.renderPreview;\n }\n\n const sourcePlaceholder = escapeAttr(block.inlineEditable.placeholder);\n const localizedPlaceholder = escapeAttr(inlinePlaceholderText);\n\n return (props, ctx) =>\n block\n .renderPreview!(props, ctx)\n .replaceAll(\n `data-placeholder=\"${sourcePlaceholder}\"`,\n `data-placeholder=\"${localizedPlaceholder}\"`,\n );\n}\n\nfunction escapeAttr(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\nfunction blockMessageId(type: string): string {\n return type.startsWith('custom:') ? type.slice('custom:'.length) : type;\n}\n","import {\n createI18nContext,\n type BlockDefinition,\n type SimpleMailI18nOptions,\n type SimpleMailT,\n} from '@simple-mail/core';\nimport { buttonBlock } from './button';\nimport { dividerBlock } from './divider';\nimport { footerBlock } from './footer';\nimport { heroBlock } from './hero';\nimport { htmlBlock } from './html';\nimport { imageBlock } from './image';\nimport { logoBlock } from './logo';\nimport { socialBlock } from './social';\nimport { socialGroupBlock } from './socialGroup';\nimport { spacerBlock } from './spacer';\nimport { textBlock } from './text';\nimport { localizeBlockDefinitions } from './i18n';\n\nexport {\n buttonBlock,\n dividerBlock,\n footerBlock,\n heroBlock,\n htmlBlock,\n imageBlock,\n logoBlock,\n socialBlock,\n socialGroupBlock,\n spacerBlock,\n textBlock,\n};\n\nexport { localizeBlockDefinition, localizeBlockDefinitions } from './i18n';\n\n/** 宿主拼装「社交组」类 block 时可复用(mj-social 序列化、侧栏 socialLinkList)。 */\nexport {\n escAttr,\n escMjmlText,\n flexJustifyFromAlign,\n mjSocialElementName,\n mjSocialDefaultIconSrc,\n mjSocialElementsLines,\n paddingQuad,\n renderSocialIconPreviewHtml,\n socialIconBorderRadiusCss,\n socialIconBorderRadiusMjml,\n socialIconSpacingPx,\n socialMeta,\n SOCIAL_NETWORK_OPTIONS,\n type SocialGroupLabelStyle,\n type SocialLinkItem,\n} from './socialShared';\n\nconst baseBuiltinBlocks: BlockDefinition<any>[] = [\n textBlock,\n htmlBlock,\n imageBlock,\n socialGroupBlock,\n heroBlock,\n buttonBlock,\n dividerBlock,\n spacerBlock,\n];\n\nconst baseExampleCustomBlocks: BlockDefinition<any>[] = [logoBlock, socialBlock, footerBlock];\n\nexport interface CreateBlocksOptions extends SimpleMailI18nOptions {\n t?: SimpleMailT;\n}\n\nfunction resolveBlocksT(options: CreateBlocksOptions = {}): SimpleMailT {\n return options.t ?? createI18nContext(options).t;\n}\n\n/** 内置组件(content 类)。可直接传给 MailEditor.blocks。 */\nexport function createBuiltinBlocks(options: CreateBlocksOptions = {}): BlockDefinition<any>[] {\n return localizeBlockDefinitions(baseBuiltinBlocks, resolveBlocksT(options));\n}\n\n/** 业务示例的“自定义”组件。可作为参考或直接使用;正式业务块应由宿主应用注册。 */\nexport function createExampleCustomBlocks(options: CreateBlocksOptions = {}): BlockDefinition<any>[] {\n return localizeBlockDefinitions(baseExampleCustomBlocks, resolveBlocksT(options));\n}\n\n/** 全部组件(内置 + 示例自定义)。业务相关块请在使用侧与 `allBlocks` 合并后传入 MailEditor。 */\nexport function createAllBlocks(options: CreateBlocksOptions = {}): BlockDefinition<any>[] {\n const t = resolveBlocksT(options);\n return [\n ...localizeBlockDefinitions(baseBuiltinBlocks, t),\n ...localizeBlockDefinitions(baseExampleCustomBlocks, t),\n ];\n}\n\n/** 内置组件(content 类)。保留兼容:默认中文。 */\nexport const builtinBlocks: BlockDefinition<any>[] = createBuiltinBlocks();\n\n/** 业务示例的“自定义”组件。保留兼容:默认中文。 */\nexport const exampleCustomBlocks: BlockDefinition<any>[] = createExampleCustomBlocks();\n\n/** 全部组件(内置 + 示例自定义)。保留兼容:默认中文。 */\nexport const allBlocks: BlockDefinition<any>[] = createAllBlocks();\n"],"names":["icons","escapeAttr","s","buttonBlock","defineBlock","p","padding","innerPadding","bw","blockButtonWidthCss","widthAttr","wst","esc","dividerBlock","footerBlock","heroBlock","ctx","w","docContentWidthCss","h","flexAlign","url","htmlBlock","mjRawEmailTableWrap","mjRawCellTypographyFromStyles","pad","warn","htmlContainsMjmlTags","imageBlock","href","alt","align","fixedH","sizeStyle","logoBlock","m","mjSocialElementName","network","n","BIZ_SOCIAL_NETWORK_OPTIONS","SOCIAL_NETWORK_OPTIONS","NETWORK_META","escAttr","escMjmlText","socialMeta","MJML_SOCIAL_ICON_BASE","MJML_SOCIAL_ICON_FILES","mjSocialDefaultIconSrc","file","renderSocialIconPreviewHtml","opts","iconSize","iconBorderRadius","iconSrc","backgroundColor","radiusCss","socialIconBorderRadiusCss","meta","bg","src","paddingQuad","socialIconBorderRadiusMjml","radiusPx","size","r","half","socialIconSpacingPx","spacing","fallback","flexJustifyFromAlign","mjSocialElementsLines","links","labelStyle","fontSizeRaw","fontSize","fontWeight","normalizeFontWeightStep","textColor","_a","fwEsc","l","bgColor","attrStr","_b","withSrc","label","_c","DEFAULT_BIZ_ELEMENTS","normalizeElements","legacy","socialBlock","FONT_WEIGHT_STEP_OPTIONS","br","gap","socAttrs","els","e","inner","fsRaw","fs","fw","jc","items","iconHtml","textHtml","socialGroupBlock","filtered","spacerBlock","TEXT_PLACEHOLDER","textBlock","ff","fwRaw","lh","lhAttr","colorRaw","colorAttr","fsAttr","fwCss","lhRaw","colorCss","fsCss","empty","isRichHtmlEffectivelyEmpty","emptyClass","placeholderAttr","FIELD_LABEL_KEYS","BLOCK_FIELD_LABEL_KEYS","HELP_KEYS","PLACEHOLDER_KEYS","INLINE_PLACEHOLDER_KEYS","DEFAULT_PROP_KEYS","localizeBlockDefinitions","blocks","block","localizeBlockDefinition","blockKey","blockMessageId","nameKey","translatedName","inlinePlaceholderText","inlinePlaceholder","localizeDefaultProps","field","localizeField","localizeRenderPreview","props","propKeys","prop","key","blockType","t","labelKey","_d","option","localizeOptionLabel","sourcePlaceholder","localizedPlaceholder","value","type","baseBuiltinBlocks","baseExampleCustomBlocks","resolveBlocksT","options","createI18nContext","createBuiltinBlocks","createExampleCustomBlocks","createAllBlocks","builtinBlocks","exampleCustomBlocks","allBlocks"],"mappings":"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"}
|
|
@@ -132,15 +132,17 @@ export function localizeBlockDefinition(block: AnyBlock, t: SimpleMailT): AnyBlo
|
|
|
132
132
|
const blockKey = blockMessageId(block.type);
|
|
133
133
|
const nameKey = `blocks.${blockKey}.name`;
|
|
134
134
|
const translatedName = t(nameKey);
|
|
135
|
+
const inlinePlaceholderText = inlinePlaceholder(blockKey, block, t);
|
|
135
136
|
return {
|
|
136
137
|
...block,
|
|
137
138
|
name: translatedName === nameKey ? block.name : translatedName,
|
|
138
139
|
defaultProps: localizeDefaultProps(block, t),
|
|
139
140
|
schema: block.schema.map((field) => localizeField(blockKey, field, t)),
|
|
141
|
+
renderPreview: localizeRenderPreview(block, inlinePlaceholderText),
|
|
140
142
|
inlineEditable: block.inlineEditable
|
|
141
143
|
? {
|
|
142
144
|
...block.inlineEditable,
|
|
143
|
-
placeholder:
|
|
145
|
+
placeholder: inlinePlaceholderText,
|
|
144
146
|
}
|
|
145
147
|
: undefined,
|
|
146
148
|
};
|
|
@@ -190,6 +192,34 @@ function inlinePlaceholder(blockType: string, block: AnyBlock, t: SimpleMailT):
|
|
|
190
192
|
return key ? t(key) : block.inlineEditable?.placeholder;
|
|
191
193
|
}
|
|
192
194
|
|
|
195
|
+
function localizeRenderPreview(
|
|
196
|
+
block: AnyBlock,
|
|
197
|
+
inlinePlaceholderText: string | undefined,
|
|
198
|
+
): AnyBlock['renderPreview'] {
|
|
199
|
+
if (!block.renderPreview || !block.inlineEditable?.placeholder || !inlinePlaceholderText) {
|
|
200
|
+
return block.renderPreview;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const sourcePlaceholder = escapeAttr(block.inlineEditable.placeholder);
|
|
204
|
+
const localizedPlaceholder = escapeAttr(inlinePlaceholderText);
|
|
205
|
+
|
|
206
|
+
return (props, ctx) =>
|
|
207
|
+
block
|
|
208
|
+
.renderPreview!(props, ctx)
|
|
209
|
+
.replaceAll(
|
|
210
|
+
`data-placeholder="${sourcePlaceholder}"`,
|
|
211
|
+
`data-placeholder="${localizedPlaceholder}"`,
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function escapeAttr(value: string): string {
|
|
216
|
+
return value
|
|
217
|
+
.replace(/&/g, '&')
|
|
218
|
+
.replace(/</g, '<')
|
|
219
|
+
.replace(/>/g, '>')
|
|
220
|
+
.replace(/"/g, '"');
|
|
221
|
+
}
|
|
222
|
+
|
|
193
223
|
function blockMessageId(type: string): string {
|
|
194
224
|
return type.startsWith('custom:') ? type.slice('custom:'.length) : type;
|
|
195
225
|
}
|