markdown.rs

  1use assets::Assets;
  2use gpui::{prelude::*, rgb, App, KeyBinding, StyleRefinement, Task, View, WindowOptions};
  3use language::{language_settings::AllLanguageSettings, LanguageRegistry};
  4use markdown::{Markdown, MarkdownStyle};
  5use node_runtime::FakeNodeRuntime;
  6use settings::SettingsStore;
  7use std::sync::Arc;
  8use theme::LoadThemes;
  9use ui::prelude::*;
 10use ui::{div, WindowContext};
 11
 12const MARKDOWN_EXAMPLE: &'static 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
 54## Images
 55Images are like links, but with an exclamation mark `!` in front.
 56
 57```todo!
 58![This is an image](/images/logo.png)
 59```
 60
 61## Code
 62Inline `code` can be wrapped with backticks `` ` ``.
 63
 64```markdown
 65Inline `code` has `back-ticks around` it.
 66```
 67
 68Code blocks can be created by indenting lines by four spaces or with triple backticks ```.
 69
 70```javascript
 71function test() {
 72  console.log("notice the blank line before this function?");
 73}
 74```
 75
 76## Blockquotes
 77Blockquotes are created with `>`.
 78
 79> This is a blockquote.
 80
 81## Horizontal Rules
 82Horizontal rules are created using three or more asterisks `***`, dashes `---`, or underscores `___`.
 83
 84## Line breaks
 85This is a
 86\
 87line break!
 88
 89---
 90
 91Remember, 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.
 92"#;
 93
 94pub fn main() {
 95    env_logger::init();
 96    App::new().with_assets(Assets).run(|cx| {
 97        let store = SettingsStore::test(cx);
 98        cx.set_global(store);
 99        language::init(cx);
100        SettingsStore::update(cx, |store, cx| {
101            store.update_user_settings::<AllLanguageSettings>(cx, |_| {});
102        });
103        cx.bind_keys([KeyBinding::new("cmd-c", markdown::Copy, None)]);
104
105        let node_runtime = FakeNodeRuntime::new();
106        theme::init(LoadThemes::JustBase, cx);
107
108        let language_registry =
109            LanguageRegistry::new(Task::ready(()), cx.background_executor().clone());
110        language_registry.set_theme(cx.theme().clone());
111        let language_registry = Arc::new(language_registry);
112        languages::init(language_registry.clone(), node_runtime, cx);
113        Assets.load_fonts(cx).unwrap();
114
115        cx.activate(true);
116        cx.open_window(WindowOptions::default(), |cx| {
117            cx.new_view(|cx| {
118                let markdown_style = MarkdownStyle {
119                    base_text_style: gpui::TextStyle {
120                        font_family: "Zed Plex Sans".into(),
121                        color: cx.theme().colors().terminal_ansi_black,
122                        ..Default::default()
123                    },
124                    code_block: StyleRefinement::default()
125                        .font_family("Zed Plex Mono")
126                        .m(rems(1.))
127                        .bg(rgb(0xAAAAAAA)),
128                    inline_code: gpui::TextStyleRefinement {
129                        font_family: Some("Zed Mono".into()),
130                        color: Some(cx.theme().colors().editor_foreground),
131                        background_color: Some(cx.theme().colors().editor_background),
132                        ..Default::default()
133                    },
134                    rule_color: Color::Muted.color(cx),
135                    block_quote_border_color: Color::Muted.color(cx),
136                    block_quote: gpui::TextStyleRefinement {
137                        color: Some(Color::Muted.color(cx)),
138                        ..Default::default()
139                    },
140                    link: gpui::TextStyleRefinement {
141                        color: Some(Color::Accent.color(cx)),
142                        underline: Some(gpui::UnderlineStyle {
143                            thickness: px(1.),
144                            color: Some(Color::Accent.color(cx)),
145                            wavy: false,
146                        }),
147                        ..Default::default()
148                    },
149                    syntax: cx.theme().syntax().clone(),
150                    selection_background_color: {
151                        let mut selection = cx.theme().players().local().selection;
152                        selection.fade_out(0.7);
153                        selection
154                    },
155                    ..Default::default()
156                };
157
158                MarkdownExample::new(
159                    MARKDOWN_EXAMPLE.to_string(),
160                    markdown_style,
161                    language_registry,
162                    cx,
163                )
164            })
165        })
166        .unwrap();
167    });
168}
169
170struct MarkdownExample {
171    markdown: View<Markdown>,
172}
173
174impl MarkdownExample {
175    pub fn new(
176        text: String,
177        style: MarkdownStyle,
178        language_registry: Arc<LanguageRegistry>,
179        cx: &mut WindowContext,
180    ) -> Self {
181        let markdown =
182            cx.new_view(|cx| Markdown::new(text, style, Some(language_registry), cx, None));
183        Self { markdown }
184    }
185}
186
187impl Render for MarkdownExample {
188    fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
189        div()
190            .id("markdown-example")
191            .debug_selector(|| "foo".into())
192            .relative()
193            .bg(gpui::white())
194            .size_full()
195            .p_4()
196            .overflow_y_scroll()
197            .child(self.markdown.clone())
198    }
199}