slack_blocks/compose/text/mrkdwn.rs
1//! ## Markdown text
2//! [_for more info, check out the slack api docs 🔗_](https://api.slack.com/reference/surfaces/formatting)
3
4use serde::{Deserialize, Serialize};
5
6/// ## Markdown text
7/// [_for more info, check out the slack api docs 🔗_](https://api.slack.com/reference/surfaces/formatting)
8///
9/// ### Reserved Characters
10///
11/// Slack uses the following special characters,
12/// and recommends you HTML escape them like so:
13///
14/// <details>
15/// <summary><b>➤ Click to expand</b></summary>
16///
17/// |character|how to escape|
18/// |--- |--- |
19/// |`&` |`&` |
20/// |`<` |`<` |
21/// |`>` |`>` |
22/// </details>
23///
24/// ### Basic Formatting
25///
26/// NOTE: This is **not** an exhaustive list
27///
28/// This should, however, capture most basic
29/// use cases without requiring that you check with
30/// the Slack documentation.
31///
32/// For more info, please visit
33/// [Slack's docs for markdown formatting 🔗](https://api.slack.com/reference/surfaces/formatting)
34///
35/// <details>
36/// <summary><b>➤ Click to expand</b></summary>
37///
38/// <!-- wow - markdown tables strike again! -->
39/// |slack markdown |formatted result |
40/// |--- |--- |
41/// |`_italic_` |_italic_ |
42/// |`*bold*` |**bold** |
43/// |`~strike~` |<del>strike</del> |
44/// |`\n` |line break |
45/// |`> a block quote` | <blockquote> a block quote </blockquote> |
46/// |`` `some code!` ``| `some code!` |
47/// |`` ```multiline code\n2 lines!``` `` | <code>multiline code<br> 2 lines!</code> |
48/// |` - li \n - li ` | <ul><li>li</li><li>li</li></ul> |
49/// |<code><<http://www.foo.com>|link name></code>| [link name](http://www.foo.com) |
50/// |`:joy:` (list from [iamcal/emoji-data 🔗](https://github.com/iamcal/emoji-data)) | 😂 |
51/// | link to #channel: `<#Cxxxxxx>` | [#channel](https://work.slack.com/some-public-channel) |
52/// | link to @user: `<@Uxxxxxx>` | [@user](https://work.slack.com/some-user) |
53/// | link to @user_group: `<!subteam^xxxxxx>` | [@user_group](https://work.slack.com/some-user-group) |
54/// </details>
55#[derive(Clone, Debug, Default, Deserialize, Hash, PartialEq, Serialize)]
56pub struct Contents {
57 pub(super) text: String,
58
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub(super) verbatim: Option<bool>,
61}
62
63impl Contents {
64 /// Construct some markdown text from a string or string-like
65 /// value
66 ///
67 /// # Arguments
68 /// - `text` - The text contents to render for this `Text` object.
69 /// For some basic formatting examples, see the docs above for
70 /// the Contents struct itself, or [Slack's markdown docs 🔗].
71 /// There are no intrinsic length limits on this, those are usually
72 /// requirements of the context the text will be used in.
73 ///
74 /// [Slack's markdown docs 🔗]: https://api.slack.com/reference/surfaces/formatting
75 ///
76 /// # Example
77 /// ```
78 /// use slack_blocks::compose::text::{mrkdwn, Text};
79 ///
80 /// let text = mrkdwn::Contents::from_text("This link doesn't work! :tada: https://www.cheese.com")
81 /// .with_verbatim(true);
82 /// ```
83 pub fn from_text(text: impl ToString) -> Self {
84 Into::<Self>::into(text.to_string())
85 }
86
87 /// Sets the `verbatim` flag
88 ///
89 /// # Arguments
90 /// - `verbatim` - When set to false (as is default)
91 /// URLs will be auto-converted into links,
92 /// conversation names will be link-ified,
93 /// and certain mentions will be automatically parsed.
94 /// Using a value of true will skip any preprocessing
95 /// of this nature, although you can
96 /// still include manual parsing strings.
97 ///
98 /// # Example
99 /// ```
100 /// use slack_blocks::compose::text::{mrkdwn, Text};
101 ///
102 /// let text = mrkdwn::Contents::from_text("This link doesn't work! :tada: https://www.cheese.com")
103 /// .with_verbatim(true);
104 /// ```
105 pub fn with_verbatim(mut self, verbatim: bool) -> Self {
106 self.verbatim = Some(verbatim);
107 self
108 }
109}
110
111impl AsRef<str> for Contents {
112 fn as_ref(&self) -> &str {
113 &self.text
114 }
115}
116
117impl From<String> for Contents {
118 fn from(text: String) -> Self {
119 Self { text,
120 verbatim: None }
121 }
122}
123
124impl From<&str> for Contents {
125 fn from(text: &str) -> Self {
126 Self::from_text(text)
127 }
128}