slack_blocks/lib.rs
1//! This crate brings Slack's terrific [Block Kit 🔗] to
2//! the Rust ecosystem.
3//!
4//! Inside, you'll find models for all of Slack's Layout Blocks,
5//! Block Elements, and Composition Objects. Each structure has Slack's API
6//! documentation copied in-place so you don't have to leave your editor to
7//! remember the details of the block kit API.
8//!
9//! Every model has builders that leverage Rust's type system
10//! to help you provide every required field, so you can be confident in your app.
11//!
12//! ## Troubleshooting common compiler errors
13//! `Method build not found for ...Builder` - Dig into the error message,
14//! you'll find something like `RequiredMethodNotCalled<method::foo>`,
15//! meaning you need to call `.foo()` before you can call `.build()`!
16//!
17//! # Example
18//! Using an example from Slack's Documentation:
19//! ```json
20//! {
21//! "type": "section",
22//! "text": {
23//! "text": "*Sally* has requested you set the deadline for the Nano launch project",
24//! "type": "mrkdwn"
25//! },
26//! "accessory": {
27//! "type": "datepicker",
28//! "action_id": "datepicker123",
29//! "initial_date": "1990-04-28",
30//! "placeholder": {
31//! "type": "plain_text",
32//! "text": "Select a date"
33//! }
34//! }
35//! }
36//! ```
37//!
38//! You can use raw Builders like so:
39//! ```rust
40//! use slack_blocks::{text::ToSlackMarkdown, blocks::Section, elems::DatePicker};
41//!
42//! let section = Section::builder()
43//! .text("*Sally* has requested you set the deadline for the Nano launch project".markdown())
44//! .accessory(DatePicker::builder()
45//! .action_id("datepicker123")
46//! .initial_date((28, 4, 1990))
47//! .placeholder("Select a date")
48//! .build()
49//! )
50//! .build();
51//! ```
52//!
53//! Or enable the `unstable` feature and use xml macros:
54//! ```rust
55//! use slack_blocks::blox::*;
56//!
57//! let pick_date = blox! {
58//! <date_picker action_id="datepicker123"
59//! placeholder="Select a date"
60//! initial_date=(28, 4, 1990) />
61//! };
62//!
63//! let section = blox! {
64//! <section_block accessory=pick_date>
65//! <text kind=plain>"*Sally* has requested you set the deadline for the Nano launch project"</text>
66//! </section_block>
67//! };
68//! ```
69//!
70//! [Block Kit 🔗]: https://api.slack.com/block-kit
71//! [`cargo-make`]: https://github.com/sagiegurari/cargo-make/
72//! [issues]: https://github.com/cakekindel/slack-blocks-rs/issues/
73//! [Conventional Commits]: https://www.conventionalcommits.org/en/v1.0.0/
74
75#![doc(html_root_url = "https://docs.rs/slack-blocks/0.25.0")]
76#![cfg_attr(docsrs, feature(doc_cfg))]
77// #![feature(doc_cfg)] // for local docs
78#![deny(missing_docs)]
79#![cfg_attr(not(test),
80 forbid(missing_copy_implementations,
81 missing_debug_implementations,
82 unreachable_pub,
83 unsafe_code,
84 unused_crate_dependencies))]
85
86#[macro_use]
87#[cfg(feature = "validation")]
88extern crate validator_derive;
89
90#[cfg(feature = "blox")]
91#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
92pub mod blox;
93
94pub mod blocks;
95pub mod compose;
96pub mod elems;
97
98mod build;
99#[cfg(feature = "validation")]
100mod val_helpr;
101
102#[doc(inline)]
103pub use blocks::Block;
104#[doc(inline)]
105pub use compose::text;
106#[doc(inline)]
107pub use elems::BlockElement;
108
109mod macros {
110 #[macro_export]
111 #[doc(hidden)]
112 macro_rules! convert {
113 (impl From<$source:ty> for $dest:ty => $closure:expr) => {
114 impl From<$source> for $dest {
115 fn from(src: $source) -> Self {
116 $closure(src)
117 }
118 }
119 };
120 (impl<'_> From<$source:ident> for $dest:ident => $closure:expr) => {
121 impl<'a> From<$source<'a>> for $dest<'a> {
122 fn from(src: $source<'a>) -> $dest<'a> {
123 $closure(src)
124 }
125 }
126 };
127 (impl<$lifetime:lifetime> From<$source:ty> for $dest:ty => $closure:expr) => {
128 convert!(impl<$lifetime, > From<$source> for $dest => $closure);
129 };
130 (impl<$lifetime:lifetime, $($ty_var:ident),*> From<$source:ty> for $dest:ty => $closure:expr) => {
131 impl<$lifetime, $($ty_var),*> From<$source> for $dest {
132 fn from(src: $source) -> Self {
133 $closure(src)
134 }
135 }
136 };
137 (impl<$($ty_var:tt),+> From<$source:ty> for $dest:ty => $closure:expr) => {
138 impl<$($ty_var),+> From<$source> for $dest {
139 fn from(src: $source) -> Self {
140 $closure(src)
141 }
142 }
143 };
144 (impl From<impl $trait_:ident<$source:ty>> for $dest:ty => $closure:expr) => {
145 impl<T> From<T> for $dest where T: $trait_<$source>
146 {
147 fn from(src: T) -> Self {
148 $closure(src)
149 }
150 }
151 };
152 (impl<'_> From<impl $trait_:ident<$source:ident>> for $dest:ident => |$param:ident| $body:expr) => {
153 impl<'a, T> From<T> for $dest<'a> where T: $trait_<$source<'a>>
154 {
155 fn from($param: T) -> Self {
156 $body
157 }
158 }
159 };
160 }
161}