markdown.rs

  1use assets::Assets;
  2use gpui::{Application, Entity, KeyBinding, StyleRefinement, WindowOptions, prelude::*, rgb};
  3use language::{LanguageRegistry, language_settings::AllLanguageSettings};
  4use markdown::{Markdown, MarkdownElement, MarkdownStyle};
  5use node_runtime::NodeRuntime;
  6use settings::SettingsStore;
  7use std::sync::Arc;
  8use theme::LoadThemes;
  9use ui::prelude::*;
 10use ui::{App, Window, div};
 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```
 19function a(b: T) {
 20
 21}
 22```
 23
 24Remember, 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.
 25
 26## Images
 27
 28![Alt Text](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCA1NDAgMzAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIC5ncmVlbi1zaGFwZSB7CiAgICAgIGZpbGw6ICNDNEVFRDA7IC8qIExpZ2h0IG1vZGUgKi8KICAgIH0KCiAgICBAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7CiAgICAgIC5ncmVlbi1zaGFwZSB7CiAgICAgICAgZmlsbDogIzEyNTIyNTsgLyogRGFyayBtb2RlICovCiAgICAgIH0KICAgIH0KICA8L3N0eWxlPgogIDxwYXRoIGQ9Ik00MjAgMzBMMzkwIDYwTDQ4MCAxNTBMMzkwIDI0MEwzMzAgMTgwTDMwMCAyMTBMMzkwIDMwMEw1NDAgMTUwTDQyMCAzMFoiIGNsYXNzPSJncmVlbi1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0xNTAgMEwzMCAxMjBMNjAgMTUwTDE1MCA2MEwyMTAgMTIwTDI0MCA5MEwxNTAgMFoiIGNsYXNzPSJncmVlbi1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0zOTAgMEw0MjAgMzBMMTUwIDMwMEwwIDE1MEwzMCAxMjBMMTUwIDI0MEwzOTAgMFoiIGZpbGw9IiMxRUE0NDYiLz4KPC9zdmc+) item one
 29
 30![other alt text](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCA1NDAgMzAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIC5ncmF5LXNoYXBlIHsKICAgICAgZmlsbDogI0M2QzZDNjsgLyogTGlnaHQgbW9kZSAqLwogICAgfQoKICAgIEBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKICAgICAgLmdyYXktc2hhcGUgewogICAgICAgIGZpbGw6ICM1NjU2NTY7IC8qIERhcmsgbW9kZSAqLwogICAgICB9CiAgICB9CiAgPC9zdHlsZT4KICA8cGF0aCBkPSJNMTUwIDBMMjQwIDkwTDIxMCAxMjBMMTIwIDMwTDE1MCAwWiIgZmlsbD0iI0YwOTQwOSIvPgogIDxwYXRoIGQ9Ik00MjAgMzBMNTQwIDE1MEw0MjAgMjcwTDM5MCAyNDBMNDgwIDE1MEwzOTAgNjBMNDIwIDMwWiIgY2xhc3M9ImdyYXktc2hhcGUiLz4KICA8cGF0aCBkPSJNMzMwIDE4MEwzMDAgMjEwTDM5MCAzMDBMNDIwIDI3MEwzMzAgMTgwWiIgZmlsbD0iI0YwOTQwOSIvPgogIDxwYXRoIGQ9Ik0xMjAgMzBMMTUwIDYwTDYwIDE1MEwxNTAgMjQwTDEyMCAyNzBMMCAxNTBMMTIwIDMwWiIgY2xhc3M9ImdyYXktc2hhcGUiLz4KICA8cGF0aCBkPSJNMzkwIDBMNDIwIDMwTDE1MCAzMDBMMTIwIDI3MEwzOTAgMFoiIGZpbGw9IiNGMDk0MDkiLz4KPC9zdmc+) item two
 31
 32![third alt text](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCA1NDAgMzAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIC5ibHVlLXNoYXBlIHsKICAgICAgZmlsbDogI0E4QzdGQTsgLyogTGlnaHQgbW9kZSAqLwogICAgfQoKICAgIEBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKICAgICAgLmJsdWUtc2hhcGUgewogICAgICAgIGZpbGw6ICMyRDUwOUU7IC8qIERhcmsgbW9kZSAqLwogICAgICB9CiAgICB9CgogICAgLmRhcmtlci1ibHVlLXNoYXBlIHsKICAgICAgICBmaWxsOiAjMUI2RUYzOwogICAgfQoKICAgIEBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKICAgICAgICAuZGFya2VyLWJsdWUtc2hhcGUgewogICAgICAgICAgICBmaWxsOiAjNDE4NUZGOwogICAgICAgIH0KICAgIH0KCiAgPC9zdHlsZT4KICA8cGF0aCBkPSJNMTUwIDBMMTgwIDMwTDE1MCA2MEwxMjAgMzBMMTUwIDBaIiBjbGFzcz0iYmx1ZS1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0yMTAgNjBMMjQwIDkwTDIxMCAxMjBMMTgwIDkwTDIxMCA2MFoiIGNsYXNzPSJibHVlLXNoYXBlIi8+CiAgPHBhdGggZD0iTTQ1MCA2MEw0ODAgOTBMNDUwIDEyMEw0MjAgOTBMNDUwIDYwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNNTEwIDEyMEw1NDAgMTUwTDUxMCAxODBMNDgwIDE1MEw1MTAgMTIwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNNDUwIDE4MEw0ODAgMjEwTDQ1MCAyNDBMNDIwIDIxMEw0NTAgMTgwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNMzkwIDI0MEw0MjAgMjcwTDM5MCAzMDBMMzYwIDI3MEwzOTAgMjQwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNMzMwIDE4MEwzNjAgMjEwTDMzMCAyNDBMMzAwIDIxMEwzMzAgMTgwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNOTAgNjBMMTIwIDkwTDkwIDEyMEw2MCA5MEw5MCA2MFoiIGNsYXNzPSJibHVlLXNoYXBlIi8+CiAgPHBhdGggZD0iTTM5MCAwTDQyMCAzMEwxNTAgMzAwTDAgMTUwTDMwIDEyMEwxNTAgMjQwTDM5MCAwWiIgY2xhc3M9ImRhcmtlci1ibHVlLXNoYXBlIi8+Cjwvc3ZnPg==) item three
 33
 34"#;
 35
 36pub fn main() {
 37    env_logger::init();
 38    Application::new().with_assets(Assets).run(|cx| {
 39        let store = SettingsStore::test(cx);
 40        cx.set_global(store);
 41        language::init(cx);
 42        SettingsStore::update(cx, |store, cx| {
 43            store.update_user_settings::<AllLanguageSettings>(cx, |_| {});
 44        });
 45        cx.bind_keys([KeyBinding::new("cmd-c", markdown::Copy, None)]);
 46
 47        let node_runtime = NodeRuntime::unavailable();
 48        theme::init(LoadThemes::JustBase, cx);
 49
 50        let language_registry = LanguageRegistry::new(cx.background_executor().clone());
 51        language_registry.set_theme(cx.theme().clone());
 52        let language_registry = Arc::new(language_registry);
 53        languages::init(language_registry.clone(), node_runtime, cx);
 54        Assets.load_fonts(cx).unwrap();
 55
 56        cx.activate(true);
 57        cx.open_window(WindowOptions::default(), |_, cx| {
 58            cx.new(|cx| MarkdownExample::new(MARKDOWN_EXAMPLE.into(), language_registry, cx))
 59        })
 60        .unwrap();
 61    });
 62}
 63
 64struct MarkdownExample {
 65    markdown: Entity<Markdown>,
 66}
 67
 68impl MarkdownExample {
 69    pub fn new(text: SharedString, language_registry: Arc<LanguageRegistry>, cx: &mut App) -> Self {
 70        let markdown = cx.new(|cx| {
 71            Markdown::new(
 72                text,
 73                Some(language_registry),
 74                Some("TypeScript".to_string()),
 75                cx,
 76            )
 77        });
 78        Self { markdown }
 79    }
 80}
 81
 82impl Render for MarkdownExample {
 83    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
 84        let markdown_style = MarkdownStyle {
 85            base_text_style: gpui::TextStyle {
 86                font_family: "Zed Plex Sans".into(),
 87                color: cx.theme().colors().terminal_ansi_black,
 88                ..Default::default()
 89            },
 90            code_block: StyleRefinement::default()
 91                .font_family("Zed Plex Mono")
 92                .m(rems(1.))
 93                .bg(rgb(0xAAAAAAA)),
 94            inline_code: gpui::TextStyleRefinement {
 95                font_family: Some("Zed Mono".into()),
 96                color: Some(cx.theme().colors().editor_foreground),
 97                background_color: Some(cx.theme().colors().editor_background),
 98                ..Default::default()
 99            },
100            rule_color: Color::Muted.color(cx),
101            block_quote_border_color: Color::Muted.color(cx),
102            block_quote: gpui::TextStyleRefinement {
103                color: Some(Color::Muted.color(cx)),
104                ..Default::default()
105            },
106            link: gpui::TextStyleRefinement {
107                color: Some(Color::Accent.color(cx)),
108                underline: Some(gpui::UnderlineStyle {
109                    thickness: px(1.),
110                    color: Some(Color::Accent.color(cx)),
111                    wavy: false,
112                }),
113                ..Default::default()
114            },
115            syntax: cx.theme().syntax().clone(),
116            selection_background_color: {
117                let mut selection = cx.theme().players().local().selection;
118                selection.fade_out(0.7);
119                selection
120            },
121            ..Default::default()
122        };
123
124        div()
125            .id("markdown-example")
126            .debug_selector(|| "foo".into())
127            .relative()
128            .bg(gpui::white())
129            .size_full()
130            .p_4()
131            .overflow_y_scroll()
132            .child(MarkdownElement::new(self.markdown.clone(), markdown_style))
133    }
134}