markdown.rs

  1use assets::Assets;
  2use gpui::{prelude::*, rgb, Application, Entity, KeyBinding, StyleRefinement, WindowOptions};
  3use language::{language_settings::AllLanguageSettings, LanguageRegistry};
  4use markdown::{Markdown, MarkdownStyle};
  5use node_runtime::NodeRuntime;
  6use settings::SettingsStore;
  7use std::sync::Arc;
  8use theme::LoadThemes;
  9use ui::prelude::*;
 10use ui::{div, App, Window};
 11
 12const MARKDOWN_EXAMPLE: &str = r#"
 13# Markdown Example Document
 14
 15## Headings
 16Headings are created by adding one or more `#` symbols before your heading text. The number of `#` you use will determine the size of the heading.
 17
 18```rust
 19gpui::window::ViewContext
 20impl<'a, V> ViewContext<'a, V>
 21pub fn on_blur(&mut self, handle: &FocusHandle, listener: impl FnMut(&mut V, &mut iewContext<V>) + 'static) -> Subscription
 22where
 23    // Bounds from impl:
 24    V: 'static,
 25```
 26
 27## Emphasis
 28Emphasis can be added with italics or bold. *This text will be italic*. _This will also be italic_
 29
 30## Lists
 31
 32### Unordered Lists
 33Unordered lists use asterisks `*`, plus `+`, or minus `-` as list markers.
 34
 35* Item 1
 36* Item 2
 37  * Item 2a
 38  * Item 2b
 39
 40### Ordered Lists
 41Ordered lists use numbers followed by a period.
 42
 431. Item 1
 442. Item 2
 453. Item 3
 46   1. Item 3a
 47   2. Item 3b
 48
 49## Links
 50Links are created using the format [http://zed.dev](https://zed.dev).
 51
 52They can also be detected automatically, for example https://zed.dev/blog.
 53
 54They may contain dollar signs:
 55
 56[https://svelte.dev/docs/svelte/$state](https://svelte.dev/docs/svelte/$state)
 57
 58https://svelte.dev/docs/svelte/$state
 59
 60## Images
 61Images are like links, but with an exclamation mark `!` in front.
 62
 63```markdown
 64![This is an image](/images/logo.png)
 65```
 66
 67## Code
 68Inline `code` can be wrapped with backticks `` ` ``.
 69
 70```markdown
 71Inline `code` has `back-ticks around` it.
 72```
 73
 74Code blocks can be created by indenting lines by four spaces or with triple backticks ```.
 75
 76```javascript
 77function test() {
 78  console.log("notice the blank line before this function?");
 79}
 80```
 81
 82## Blockquotes
 83Blockquotes are created with `>`.
 84
 85> This is a blockquote.
 86
 87## Horizontal Rules
 88Horizontal rules are created using three or more asterisks `***`, dashes `---`, or underscores `___`.
 89
 90## Line breaks
 91This is a
 92\
 93line break!
 94
 95---
 96
 97Remember, markdown processors may have slight differences and extensions, so always refer to the specific documentation or guides relevant to your platform or editor for the best practices and additional features.
 98"#;
 99
100pub fn main() {
101    env_logger::init();
102    Application::new().with_assets(Assets).run(|cx| {
103        let store = SettingsStore::test(cx);
104        cx.set_global(store);
105        language::init(cx);
106        SettingsStore::update(cx, |store, cx| {
107            store.update_user_settings::<AllLanguageSettings>(cx, |_| {});
108        });
109        cx.bind_keys([KeyBinding::new("cmd-c", markdown::Copy, None)]);
110
111        let node_runtime = NodeRuntime::unavailable();
112        theme::init(LoadThemes::JustBase, cx);
113
114        let language_registry = LanguageRegistry::new(cx.background_executor().clone());
115        language_registry.set_theme(cx.theme().clone());
116        let language_registry = Arc::new(language_registry);
117        languages::init(language_registry.clone(), node_runtime, cx);
118        Assets.load_fonts(cx).unwrap();
119
120        cx.activate(true);
121        cx.open_window(WindowOptions::default(), |window, cx| {
122            cx.new(|cx| {
123                let markdown_style = MarkdownStyle {
124                    base_text_style: gpui::TextStyle {
125                        font_family: "Zed Plex Sans".into(),
126                        color: cx.theme().colors().terminal_ansi_black,
127                        ..Default::default()
128                    },
129                    code_block: StyleRefinement::default()
130                        .font_family("Zed Plex Mono")
131                        .m(rems(1.))
132                        .bg(rgb(0xAAAAAAA)),
133                    inline_code: gpui::TextStyleRefinement {
134                        font_family: Some("Zed Mono".into()),
135                        color: Some(cx.theme().colors().editor_foreground),
136                        background_color: Some(cx.theme().colors().editor_background),
137                        ..Default::default()
138                    },
139                    rule_color: Color::Muted.color(cx),
140                    block_quote_border_color: Color::Muted.color(cx),
141                    block_quote: gpui::TextStyleRefinement {
142                        color: Some(Color::Muted.color(cx)),
143                        ..Default::default()
144                    },
145                    link: gpui::TextStyleRefinement {
146                        color: Some(Color::Accent.color(cx)),
147                        underline: Some(gpui::UnderlineStyle {
148                            thickness: px(1.),
149                            color: Some(Color::Accent.color(cx)),
150                            wavy: false,
151                        }),
152                        ..Default::default()
153                    },
154                    syntax: cx.theme().syntax().clone(),
155                    selection_background_color: {
156                        let mut selection = cx.theme().players().local().selection;
157                        selection.fade_out(0.7);
158                        selection
159                    },
160                    ..Default::default()
161                };
162
163                MarkdownExample::new(
164                    MARKDOWN_EXAMPLE.to_string(),
165                    markdown_style,
166                    language_registry,
167                    window,
168                    cx,
169                )
170            })
171        })
172        .unwrap();
173    });
174}
175
176struct MarkdownExample {
177    markdown: Entity<Markdown>,
178}
179
180impl MarkdownExample {
181    pub fn new(
182        text: String,
183        style: MarkdownStyle,
184        language_registry: Arc<LanguageRegistry>,
185        window: &mut Window,
186        cx: &mut App,
187    ) -> Self {
188        let markdown =
189            cx.new(|cx| Markdown::new(text, style, Some(language_registry), None, window, cx));
190        Self { markdown }
191    }
192}
193
194impl Render for MarkdownExample {
195    fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
196        div()
197            .id("markdown-example")
198            .debug_selector(|| "foo".into())
199            .relative()
200            .bg(gpui::white())
201            .size_full()
202            .p_4()
203            .overflow_y_scroll()
204            .child(self.markdown.clone())
205    }
206}