markdown.rs

  1use assets::Assets;
  2use gpui::{prelude::*, rgb, App, KeyBinding, StyleRefinement, View, 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, WindowContext};
 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
 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 = NodeRuntime::unavailable();
106        theme::init(LoadThemes::JustBase, cx);
107
108        let language_registry = LanguageRegistry::new(cx.background_executor().clone());
109        language_registry.set_theme(cx.theme().clone());
110        let language_registry = Arc::new(language_registry);
111        languages::init(language_registry.clone(), node_runtime, cx);
112        Assets.load_fonts(cx).unwrap();
113
114        cx.activate(true);
115        cx.open_window(WindowOptions::default(), |cx| {
116            cx.new_view(|cx| {
117                let markdown_style = MarkdownStyle {
118                    base_text_style: gpui::TextStyle {
119                        font_family: "Zed Plex Sans".into(),
120                        color: cx.theme().colors().terminal_ansi_black,
121                        ..Default::default()
122                    },
123                    code_block: StyleRefinement::default()
124                        .font_family("Zed Plex Mono")
125                        .m(rems(1.))
126                        .bg(rgb(0xAAAAAAA)),
127                    inline_code: gpui::TextStyleRefinement {
128                        font_family: Some("Zed Mono".into()),
129                        color: Some(cx.theme().colors().editor_foreground),
130                        background_color: Some(cx.theme().colors().editor_background),
131                        ..Default::default()
132                    },
133                    rule_color: Color::Muted.color(cx),
134                    block_quote_border_color: Color::Muted.color(cx),
135                    block_quote: gpui::TextStyleRefinement {
136                        color: Some(Color::Muted.color(cx)),
137                        ..Default::default()
138                    },
139                    link: gpui::TextStyleRefinement {
140                        color: Some(Color::Accent.color(cx)),
141                        underline: Some(gpui::UnderlineStyle {
142                            thickness: px(1.),
143                            color: Some(Color::Accent.color(cx)),
144                            wavy: false,
145                        }),
146                        ..Default::default()
147                    },
148                    syntax: cx.theme().syntax().clone(),
149                    selection_background_color: {
150                        let mut selection = cx.theme().players().local().selection;
151                        selection.fade_out(0.7);
152                        selection
153                    },
154                    ..Default::default()
155                };
156
157                MarkdownExample::new(
158                    MARKDOWN_EXAMPLE.to_string(),
159                    markdown_style,
160                    language_registry,
161                    cx,
162                )
163            })
164        })
165        .unwrap();
166    });
167}
168
169struct MarkdownExample {
170    markdown: View<Markdown>,
171}
172
173impl MarkdownExample {
174    pub fn new(
175        text: String,
176        style: MarkdownStyle,
177        language_registry: Arc<LanguageRegistry>,
178        cx: &mut WindowContext,
179    ) -> Self {
180        let markdown =
181            cx.new_view(|cx| Markdown::new(text, style, Some(language_registry), None, cx));
182        Self { markdown }
183    }
184}
185
186impl Render for MarkdownExample {
187    fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
188        div()
189            .id("markdown-example")
190            .debug_selector(|| "foo".into())
191            .relative()
192            .bg(gpui::white())
193            .size_full()
194            .p_4()
195            .overflow_y_scroll()
196            .child(self.markdown.clone())
197    }
198}