@botfather/units-slack-block-kit
v0.2.1
Published
Convert Units DSL or AST into Slack Block Kit payloads.
Readme
@botfather/units-slack-block-kit
Convert Units DSL, Units AST, or a rendered Units tree into Slack Block Kit payloads.
Install
npm install @botfather/units @botfather/units-slack-block-kitUsage
import { unitsToSlackBlockKit } from "@botfather/units-slack-block-kit";
const payload = unitsToSlackBlockKit(`
SlackMessage (channel:'C123', name:'Release request') {
Section (blockId:'summary') {
Strong { 'Release:' }
' ready for approval by '
Mention (userId:'U012AB3CD')
}
Actions {
Button (name:'Approve', actionId:'approve', style:'primary')
Button (name:'Reject', actionId:'reject', style:'danger')
}
}
`);
console.log(payload.blocks);Use compileUnitsToSlackBlockKit when you want diagnostics:
import { compileUnitsToSlackBlockKit } from "@botfather/units-slack-block-kit";
const result = compileUnitsToSlackBlockKit(source, {
scope: { approvers },
strict: true,
});
console.log(result.payload);
console.log(result.warnings);The adapter evaluates Units directives and expressions through createUnitsRenderer, so #if, #for, expression props, slots, and text interpolation are resolved before Slack serialization.
Supported Units Tags
Block tags:
SlackMessage,MessageSection,MarkdownHeader,HeadingContextActions,GroupDivider,SeparatorImageInputFile,Video,RichTextBlock,RawBlock,SlackBlockwithtype/slackType/payload
Element tags:
Button,WorkflowButtonImageOverflowDatePicker,TimePicker,DateTimePickerPlainTextInput,EmailInput,UrlInput,NumberInput,RichTextInputStaticSelect,ExternalSelect,UsersSelect,ConversationsSelect,ChannelsSelectMultiStaticSelect,MultiExternalSelect,MultiUsersSelect,MultiConversationsSelect,MultiChannelsSelectCheckboxes,RadioButtonsElement,RawElement,SlackElementwithtype/slackType/payload
Inline mrkdwn tags:
Strong,Emphasis,StrikeCode,PreBlockquoteLinkMention,Channel,UserGroup,SpecialMentionDateEmojiField,Label,Hint
Camel-case Slack props are converted to Slack snake-case fields where useful, for example blockId -> block_id, actionId -> action_id, src -> image_url, and alt -> alt_text.
LLM Structured Output
For model-generated messages, prefer schema-constrained structured output over free-form DSL. The emitter can only render valid input; it cannot make a model produce valid .ui syntax.
import {
SLACK_UNITS_STRUCTURED_OUTPUT_SCHEMA,
compileStructuredSlackToBlockKit,
} from "@botfather/units-slack-block-kit";
// Pass SLACK_UNITS_STRUCTURED_OUTPUT_SCHEMA to your model provider as the
// required JSON schema. Then validate and render the returned object.
const result = compileStructuredSlackToBlockKit(modelJson, {
strict: true,
});
console.log(result.payload);Structured output shape:
{
"type": "SlackMessage",
"channel": "C123",
"text": "Release request",
"blocks": [
{
"type": "Section",
"blockId": "summary",
"children": [
{ "type": "Strong", "text": "Release:" },
" ready for approval by ",
{ "type": "Mention", "userId": "U012AB3CD" }
],
"accessory": {
"type": "Button",
"name": "Open request",
"actionId": "open",
"href": "https://example.com/release"
}
}
]
}Use validateStructuredSlack(modelJson) if you want validation without rendering. Keep compileUnitsToSlackBlockKit(source, { strict: true }) for human-authored DSL, migrations, tests, or fallback repair flows:
const { payload, warnings } = compileUnitsToSlackBlockKit(source, {
strict: true,
});