@templatical/types
Advanced tools
+51
-1
@@ -622,2 +622,41 @@ //#region src/blocks.d.ts | ||
| declare function resolveHtmlMergeTagLabels(html: string, mergeTags: MergeTag[]): string; | ||
| /** | ||
| * The example value configured for `value`, or `undefined` when the tag is | ||
| * unknown or declares none. Unlike `getMergeTagLabel`, which falls back to the | ||
| * raw token, absence is reported as `undefined` so callers can choose their own | ||
| * fallback — Sample mode falls back to the label, never to a raw token. | ||
| */ | ||
| declare function getMergeTagSample(value: string, mergeTags: MergeTag[]): string | undefined; | ||
| /** | ||
| * Rewrite rich-text HTML for the previews' Sample mode. | ||
| * | ||
| * A tag **with** a sample is replaced by that value as bare text, wrapper and | ||
| * all — dropping the `<span>` is what removes the merge-tag highlight, so the | ||
| * value reads as ordinary content. A tag **without** one keeps its span and | ||
| * shows its label, so it stays visibly dynamic; that difference is deliberate, | ||
| * and it doubles as a signal that a sample is still unset. | ||
| * | ||
| * The unwrapped output is inert — `data-merge-tag` is gone from it — so this | ||
| * result must only ever reach a preview surface, never `getContent()`, an | ||
| * export or a send. | ||
| */ | ||
| declare function substituteHtmlMergeTagSamples(html: string, mergeTags: MergeTag[]): string; | ||
| /** | ||
| * Whether any configured tag declares a `sample`. | ||
| * | ||
| * Gates the whole feature: with no samples anywhere the previews' Sample view | ||
| * would be identical to the Label view, so the editor defaults to Label and | ||
| * renders no toggle. That keeps the feature invisible until a consumer opts in. | ||
| */ | ||
| declare function hasMergeTagSamples(mergeTags: MergeTag[]): boolean; | ||
| /** | ||
| * Replace declared tokens with their sample values in a plain string — used for | ||
| * values that reach no label-resolving component, namely `html` block content | ||
| * and custom-block field values. | ||
| * | ||
| * Matching is on the exact configured `value`, so consumer text cannot | ||
| * false-positive and `href="{{link}}"` resolves correctly. Tags without a | ||
| * sample are left untouched, which is what keeps a missing sample visible. | ||
| */ | ||
| declare function substituteTextMergeTagSamples(text: string, mergeTags: MergeTag[]): string; | ||
| declare function containsMergeTag(value: string, syntax: SyntaxPreset): boolean; | ||
@@ -701,2 +740,13 @@ declare function restoreMergeTagMarkup(html: string, mergeTags: MergeTag[], syntax: SyntaxPreset): string; | ||
| description?: string; | ||
| /** | ||
| * Example value shown in place of this tag on preview surfaces — e.g. | ||
| * `"Ada"` for `{{first_name}}` — so a preview reads like a delivered | ||
| * email instead of a list of field names. | ||
| * | ||
| * Display-only, and only in the previews' Sample mode: never written to | ||
| * the template, never sent, never present in MJML output. Setting it is | ||
| * the whole opt-in; there is no accompanying flag. A tag without a | ||
| * sample keeps showing its `label`. | ||
| */ | ||
| sample?: string; | ||
| } | ||
@@ -1258,3 +1308,3 @@ interface MediaResult { | ||
| //#endregion | ||
| export { type AiChatMessage, type AiConfig, type AiGenerateOptions, type AiScoreOptions, type AiStreamEvent, type ApiError, type ApiResponse, type AuthConfig, type AuthRequestOptions, BUTTON_BLOCK_DEFAULTS, type BaseBlock, type Block, type BlockDefaults, type BlockStyles, type BlockType, type BlockVisibility, type ButtonBlock, COUNTDOWN_BLOCK_DEFAULTS, type CategoryScore, type CollaborationConfig, type Collaborator, type ColorsConfig, type ColumnLayout, type Comment, type CommentEvent, type CommentEventType, type CommentThread, type CountdownBlock, type CreateCommentData, type CustomBlock, type CustomBlockBooleanField, type CustomBlockColorField, type CustomBlockDefinition, type CustomBlockField, type CustomBlockFieldBase, type CustomBlockFieldType, type CustomBlockImageField, type CustomBlockNumberField, type CustomBlockRepeatableField, type CustomBlockSelectField, type CustomBlockTextField, type CustomBlockTextareaField, type CustomFont, DEFAULT_BLOCK_DEFAULTS, DEFAULT_TEMPLATE_DEFAULTS, DIVIDER_BLOCK_DEFAULTS, type DataSourceConfig, type DataSourceFetchContext, type DirectAuthConfig, type DisplayCondition, type DisplayConditionsConfig, type DividerBlock, type EditorState, EventEmitter, type ExportResult, type FindingSeverity, type FontsConfig, HEADING_LEVEL_FONT_SIZE, HTML_BLOCK_DEFAULTS, type HeadingLevel, type HealthCheckResult, type HtmlBlock, IMAGE_BLOCK_DEFAULTS, type ImageBlock, type LogicPair, type LogicTag, type LogicTagsConfig, MENU_BLOCK_DEFAULTS, type McpConfig, type McpOperation, type McpOperationPayload, type MediaResult, type MenuBlock, type MenuItemData, type MergeTag, type MergeTagsConfig, PARAGRAPH_BLOCK_DEFAULTS, type ParagraphBlock, type PlanConfig, type PlanFeatures, type PlanLimits, type ProxyAuthConfig, type RewriteData, SECTION_BLOCK_DEFAULTS, SOCIAL_ICONS_BLOCK_DEFAULTS, SOCIAL_ICON_GLYPHS, SPACER_BLOCK_DEFAULTS, SYNTAX_PRESETS, type SaveResult, type SavedBlock, type SavedBlockInput, type SavedBlockPatch, type SavedBlocksListParams, type SavedBlocksProvider, type ScoringCategory, type ScoringFinding, type ScoringResult, type SdkAuthConfig, SdkError, type SectionBlock, type SectionWrapper, type SelectOption, type SocialIcon, type SocialIconGlyph, type SocialIconSize, type SocialIconStyle, type SocialIconsBlock, type SocialPlatform, type SpacerBlock, type SpacingValue, type SyntaxPreset, type SyntaxPresetName, TABLE_BLOCK_DEFAULTS, TITLE_BLOCK_DEFAULTS, type TableBlock, type TableCellData, type TableRowData, type Template, type TemplateContent, type TemplateDefaults, type TemplateSettings, type TemplateSnapshot, type TestEmailConfig, type TestEmailPayload, type TestEmailProvider, type ThemeOverrides, type TitleBlock, type TokenData, type UiTheme, type UpdateCommentData, type UserConfig, VIDEO_BLOCK_DEFAULTS, type VideoBlock, type ViewportSize, type WebSocketServerConfig, cloneBlock, containsMergeTag, createBlock, createButtonBlock, createCountdownBlock, createCustomBlock, createDefaultTemplateContent, createDividerBlock, createHtmlBlock, createImageBlock, createMenuBlock, createParagraphBlock, createSectionBlock, createSocialIconsBlock, createSpacerBlock, createTableBlock, createTitleBlock, createVideoBlock, deepMergeDefaults, generateId, getLogicMergeTagKeyword, getMergeTagLabel, getSyntaxClosingChar, getSyntaxTriggerChar, isButton, isCountdown, isCustomBlock, isDivider, isHtml, isImage, isLogicMergeTagValue, isMenu, isMergeTagValue, isParagraph, isSection, isSocialIcons, isSpacer, isTable, isTitle, isVideo, resolveHtmlLogicMergeTagLabels, resolveHtmlMergeTagLabels, resolveSyntax, restoreMergeTagMarkup, safeClone }; | ||
| export { type AiChatMessage, type AiConfig, type AiGenerateOptions, type AiScoreOptions, type AiStreamEvent, type ApiError, type ApiResponse, type AuthConfig, type AuthRequestOptions, BUTTON_BLOCK_DEFAULTS, type BaseBlock, type Block, type BlockDefaults, type BlockStyles, type BlockType, type BlockVisibility, type ButtonBlock, COUNTDOWN_BLOCK_DEFAULTS, type CategoryScore, type CollaborationConfig, type Collaborator, type ColorsConfig, type ColumnLayout, type Comment, type CommentEvent, type CommentEventType, type CommentThread, type CountdownBlock, type CreateCommentData, type CustomBlock, type CustomBlockBooleanField, type CustomBlockColorField, type CustomBlockDefinition, type CustomBlockField, type CustomBlockFieldBase, type CustomBlockFieldType, type CustomBlockImageField, type CustomBlockNumberField, type CustomBlockRepeatableField, type CustomBlockSelectField, type CustomBlockTextField, type CustomBlockTextareaField, type CustomFont, DEFAULT_BLOCK_DEFAULTS, DEFAULT_TEMPLATE_DEFAULTS, DIVIDER_BLOCK_DEFAULTS, type DataSourceConfig, type DataSourceFetchContext, type DirectAuthConfig, type DisplayCondition, type DisplayConditionsConfig, type DividerBlock, type EditorState, EventEmitter, type ExportResult, type FindingSeverity, type FontsConfig, HEADING_LEVEL_FONT_SIZE, HTML_BLOCK_DEFAULTS, type HeadingLevel, type HealthCheckResult, type HtmlBlock, IMAGE_BLOCK_DEFAULTS, type ImageBlock, type LogicPair, type LogicTag, type LogicTagsConfig, MENU_BLOCK_DEFAULTS, type McpConfig, type McpOperation, type McpOperationPayload, type MediaResult, type MenuBlock, type MenuItemData, type MergeTag, type MergeTagsConfig, PARAGRAPH_BLOCK_DEFAULTS, type ParagraphBlock, type PlanConfig, type PlanFeatures, type PlanLimits, type ProxyAuthConfig, type RewriteData, SECTION_BLOCK_DEFAULTS, SOCIAL_ICONS_BLOCK_DEFAULTS, SOCIAL_ICON_GLYPHS, SPACER_BLOCK_DEFAULTS, SYNTAX_PRESETS, type SaveResult, type SavedBlock, type SavedBlockInput, type SavedBlockPatch, type SavedBlocksListParams, type SavedBlocksProvider, type ScoringCategory, type ScoringFinding, type ScoringResult, type SdkAuthConfig, SdkError, type SectionBlock, type SectionWrapper, type SelectOption, type SocialIcon, type SocialIconGlyph, type SocialIconSize, type SocialIconStyle, type SocialIconsBlock, type SocialPlatform, type SpacerBlock, type SpacingValue, type SyntaxPreset, type SyntaxPresetName, TABLE_BLOCK_DEFAULTS, TITLE_BLOCK_DEFAULTS, type TableBlock, type TableCellData, type TableRowData, type Template, type TemplateContent, type TemplateDefaults, type TemplateSettings, type TemplateSnapshot, type TestEmailConfig, type TestEmailPayload, type TestEmailProvider, type ThemeOverrides, type TitleBlock, type TokenData, type UiTheme, type UpdateCommentData, type UserConfig, VIDEO_BLOCK_DEFAULTS, type VideoBlock, type ViewportSize, type WebSocketServerConfig, cloneBlock, containsMergeTag, createBlock, createButtonBlock, createCountdownBlock, createCustomBlock, createDefaultTemplateContent, createDividerBlock, createHtmlBlock, createImageBlock, createMenuBlock, createParagraphBlock, createSectionBlock, createSocialIconsBlock, createSpacerBlock, createTableBlock, createTitleBlock, createVideoBlock, deepMergeDefaults, generateId, getLogicMergeTagKeyword, getMergeTagLabel, getMergeTagSample, getSyntaxClosingChar, getSyntaxTriggerChar, hasMergeTagSamples, isButton, isCountdown, isCustomBlock, isDivider, isHtml, isImage, isLogicMergeTagValue, isMenu, isMergeTagValue, isParagraph, isSection, isSocialIcons, isSpacer, isTable, isTitle, isVideo, resolveHtmlLogicMergeTagLabels, resolveHtmlMergeTagLabels, resolveSyntax, restoreMergeTagMarkup, safeClone, substituteHtmlMergeTagSamples, substituteTextMergeTagSamples }; | ||
| //# sourceMappingURL=index.d.ts.map |
+71
-5
@@ -578,2 +578,63 @@ //#region src/blocks.ts | ||
| } | ||
| /** | ||
| * The example value configured for `value`, or `undefined` when the tag is | ||
| * unknown or declares none. Unlike `getMergeTagLabel`, which falls back to the | ||
| * raw token, absence is reported as `undefined` so callers can choose their own | ||
| * fallback — Sample mode falls back to the label, never to a raw token. | ||
| */ | ||
| function getMergeTagSample(value, mergeTags) { | ||
| return mergeTags.find((p) => p.value === value)?.sample; | ||
| } | ||
| /** | ||
| * Rewrite rich-text HTML for the previews' Sample mode. | ||
| * | ||
| * A tag **with** a sample is replaced by that value as bare text, wrapper and | ||
| * all — dropping the `<span>` is what removes the merge-tag highlight, so the | ||
| * value reads as ordinary content. A tag **without** one keeps its span and | ||
| * shows its label, so it stays visibly dynamic; that difference is deliberate, | ||
| * and it doubles as a signal that a sample is still unset. | ||
| * | ||
| * The unwrapped output is inert — `data-merge-tag` is gone from it — so this | ||
| * result must only ever reach a preview surface, never `getContent()`, an | ||
| * export or a send. | ||
| */ | ||
| function substituteHtmlMergeTagSamples(html, mergeTags) { | ||
| return rewriteSpanByAttr(html, "data-merge-tag", (value) => escapeTagText(getMergeTagSample(value, mergeTags) ?? getMergeTagLabel(value, mergeTags)), { unwrap: (value) => getMergeTagSample(value, mergeTags) !== void 0 }); | ||
| } | ||
| /** | ||
| * Whether any configured tag declares a `sample`. | ||
| * | ||
| * Gates the whole feature: with no samples anywhere the previews' Sample view | ||
| * would be identical to the Label view, so the editor defaults to Label and | ||
| * renders no toggle. That keeps the feature invisible until a consumer opts in. | ||
| */ | ||
| function hasMergeTagSamples(mergeTags) { | ||
| return mergeTags.some((tag) => tag.sample !== void 0); | ||
| } | ||
| /** | ||
| * Replace declared tokens with their sample values in a plain string — used for | ||
| * values that reach no label-resolving component, namely `html` block content | ||
| * and custom-block field values. | ||
| * | ||
| * Matching is on the exact configured `value`, so consumer text cannot | ||
| * false-positive and `href="{{link}}"` resolves correctly. Tags without a | ||
| * sample are left untouched, which is what keeps a missing sample visible. | ||
| */ | ||
| function substituteTextMergeTagSamples(text, mergeTags) { | ||
| if (!text) return text; | ||
| let out = text; | ||
| for (const tag of mergeTags) { | ||
| if (tag.sample === void 0) continue; | ||
| out = out.split(tag.value).join(tag.sample); | ||
| } | ||
| return out; | ||
| } | ||
| /** | ||
| * Escape a sample before it is inlined into rich-text HTML. Samples are | ||
| * consumer-authored strings, so `<`, `&` and quotes would otherwise alter the | ||
| * surrounding markup. | ||
| */ | ||
| function escapeTagText(text) { | ||
| return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """); | ||
| } | ||
| function containsMergeTag(value, syntax) { | ||
@@ -621,3 +682,3 @@ if (!value) return false; | ||
| */ | ||
| function rewriteSpanByAttr(html, attrName, relabel) { | ||
| function rewriteSpanByAttr(html, attrName, relabel, options) { | ||
| const attrPattern = new RegExp(`(?:^|\\s)${attrName}="([^"<>]*)"`); | ||
@@ -657,5 +718,10 @@ let out = ""; | ||
| const newLabel = relabel(value); | ||
| out += html.substring(i, openEnd + 1); | ||
| out += newLabel; | ||
| out += "</span>"; | ||
| if (options?.unwrap?.(value)) { | ||
| out += html.substring(i, open); | ||
| out += newLabel; | ||
| } else { | ||
| out += html.substring(i, openEnd + 1); | ||
| out += newLabel; | ||
| out += "</span>"; | ||
| } | ||
| i = closeStart + 7; | ||
@@ -685,4 +751,4 @@ } | ||
| //#endregion | ||
| export { BUTTON_BLOCK_DEFAULTS, COUNTDOWN_BLOCK_DEFAULTS, DEFAULT_BLOCK_DEFAULTS, DEFAULT_TEMPLATE_DEFAULTS, DIVIDER_BLOCK_DEFAULTS, EventEmitter, HEADING_LEVEL_FONT_SIZE, HTML_BLOCK_DEFAULTS, IMAGE_BLOCK_DEFAULTS, MENU_BLOCK_DEFAULTS, PARAGRAPH_BLOCK_DEFAULTS, SECTION_BLOCK_DEFAULTS, SOCIAL_ICONS_BLOCK_DEFAULTS, SOCIAL_ICON_GLYPHS, SPACER_BLOCK_DEFAULTS, SYNTAX_PRESETS, SdkError, TABLE_BLOCK_DEFAULTS, TITLE_BLOCK_DEFAULTS, VIDEO_BLOCK_DEFAULTS, cloneBlock, containsMergeTag, createBlock, createButtonBlock, createCountdownBlock, createCustomBlock, createDefaultTemplateContent, createDividerBlock, createHtmlBlock, createImageBlock, createMenuBlock, createParagraphBlock, createSectionBlock, createSocialIconsBlock, createSpacerBlock, createTableBlock, createTitleBlock, createVideoBlock, deepMergeDefaults, generateId, getLogicMergeTagKeyword, getMergeTagLabel, getSyntaxClosingChar, getSyntaxTriggerChar, isButton, isCountdown, isCustomBlock, isDivider, isHtml, isImage, isLogicMergeTagValue, isMenu, isMergeTagValue, isParagraph, isSection, isSocialIcons, isSpacer, isTable, isTitle, isVideo, resolveHtmlLogicMergeTagLabels, resolveHtmlMergeTagLabels, resolveSyntax, restoreMergeTagMarkup, safeClone }; | ||
| export { BUTTON_BLOCK_DEFAULTS, COUNTDOWN_BLOCK_DEFAULTS, DEFAULT_BLOCK_DEFAULTS, DEFAULT_TEMPLATE_DEFAULTS, DIVIDER_BLOCK_DEFAULTS, EventEmitter, HEADING_LEVEL_FONT_SIZE, HTML_BLOCK_DEFAULTS, IMAGE_BLOCK_DEFAULTS, MENU_BLOCK_DEFAULTS, PARAGRAPH_BLOCK_DEFAULTS, SECTION_BLOCK_DEFAULTS, SOCIAL_ICONS_BLOCK_DEFAULTS, SOCIAL_ICON_GLYPHS, SPACER_BLOCK_DEFAULTS, SYNTAX_PRESETS, SdkError, TABLE_BLOCK_DEFAULTS, TITLE_BLOCK_DEFAULTS, VIDEO_BLOCK_DEFAULTS, cloneBlock, containsMergeTag, createBlock, createButtonBlock, createCountdownBlock, createCustomBlock, createDefaultTemplateContent, createDividerBlock, createHtmlBlock, createImageBlock, createMenuBlock, createParagraphBlock, createSectionBlock, createSocialIconsBlock, createSpacerBlock, createTableBlock, createTitleBlock, createVideoBlock, deepMergeDefaults, generateId, getLogicMergeTagKeyword, getMergeTagLabel, getMergeTagSample, getSyntaxClosingChar, getSyntaxTriggerChar, hasMergeTagSamples, isButton, isCountdown, isCustomBlock, isDivider, isHtml, isImage, isLogicMergeTagValue, isMenu, isMergeTagValue, isParagraph, isSection, isSocialIcons, isSpacer, isTable, isTitle, isVideo, resolveHtmlLogicMergeTagLabels, resolveHtmlMergeTagLabels, resolveSyntax, restoreMergeTagMarkup, safeClone, substituteHtmlMergeTagSamples, substituteTextMergeTagSamples }; | ||
| //# sourceMappingURL=index.js.map |
+2
-2
| { | ||
| "name": "@templatical/types", | ||
| "description": "Shared TypeScript types, block factory functions, and event emitter for Templatical email editor", | ||
| "version": "0.23.0", | ||
| "version": "0.24.0", | ||
| "bugs": "https://github.com/templatical/sdk/issues", | ||
@@ -9,3 +9,3 @@ "devDependencies": { | ||
| "vitest": "^4.1.10", | ||
| "@templatical/media-library": "0.23.0" | ||
| "@templatical/media-library": "0.24.0" | ||
| }, | ||
@@ -12,0 +12,0 @@ "exports": { |
Sorry, the diff of this file is too big to display
163660
6.94%2108
5.88%