forc_doc/render/util/format/
docstring.rs1use crate::render::util::format::constant::*;
3use comrak::{markdown_to_html, ComrakOptions};
4use std::fmt::Write;
5use sway_core::transform::{AttributeKind, Attributes};
6use sway_lsp::utils::markdown::format_docs;
7
8pub(crate) trait DocStrings {
9 fn to_html_string(&self) -> String;
10 fn to_raw_string(&self) -> String;
11}
12impl DocStrings for Attributes {
14 fn to_html_string(&self) -> String {
15 let docs = self.to_raw_string();
16
17 let mut options = ComrakOptions::default();
18 options.render.hardbreaks = true;
19 options.extension.strikethrough = true;
20 options.extension.table = true;
21 options.extension.autolink = true;
22 options.extension.superscript = true;
23 options.extension.footnotes = true;
24 options.parse.smart = true;
25 options.parse.default_info_string = Some(SWAY_FILEINE.into());
26 markdown_to_html(&format_docs(&docs), &options)
27 }
28 fn to_raw_string(&self) -> String {
29 let mut docs = String::new();
30 for arg in self
32 .of_kind(AttributeKind::DocComment)
33 .flat_map(|attribute| &attribute.args)
34 {
35 writeln!(docs, "{}", arg.name.as_str())
36 .expect("problem appending `arg.name.as_str()` to `docs` with `writeln` macro.");
37 }
38 docs
39 }
40}
41
42pub(crate) fn create_preview(raw_attributes: Option<String>) -> Option<String> {
46 raw_attributes.as_ref().map(|description| {
47 let preview = split_at_markdown_header(description);
48 if preview.chars().count() > MAX_PREVIEW_CHARS && preview.contains(CLOSING_PARAGRAPH_TAG) {
49 let closing_tag_index = preview
50 .find(CLOSING_PARAGRAPH_TAG)
51 .expect("closing tag out of range");
52 let (preview, _) =
55 preview.split_at(closing_tag_index + CLOSING_PARAGRAPH_TAG.len() + 1);
56 if preview.chars().count() > MAX_PREVIEW_CHARS && preview.contains(NEWLINE_CHAR) {
57 let newline_index = preview
58 .find(NEWLINE_CHAR)
59 .expect("new line char out of range");
60 preview.split_at(newline_index).0.to_string()
61 } else {
62 preview.to_string()
63 }
64 } else {
65 preview.to_string()
66 }
67 })
68}
69
70pub(crate) fn split_at_markdown_header(raw_html: &str) -> &str {
73 for header in HTML_HEADERS {
74 if raw_html.contains(header) {
75 let v: Vec<_> = raw_html.split(header).collect();
76 return v.first().expect("expected non-empty &str");
77 }
78 continue;
79 }
80 raw_html
81}