specta_typescript/
js_doc.rs1use std::borrow::Borrow;
2
3use specta::{
4 datatype::{DeprecatedType, GenericType},
5 TypeCollection,
6};
7use typescript::CommentFormatterArgs;
8
9use super::*;
10
11pub fn typedef_named_datatype(
12 cfg: &Typescript,
13 typ: &NamedDataType,
14 type_map: &TypeCollection,
15) -> Output {
16 typedef_named_datatype_inner(
17 &ExportContext {
18 cfg,
19 path: vec![],
20 is_export: false,
22 },
23 typ,
24 type_map,
25 )
26}
27
28fn typedef_named_datatype_inner(
29 ctx: &ExportContext,
30 typ: &NamedDataType,
31 type_map: &TypeCollection,
32) -> Output {
33 let name = typ.name();
34 let docs = typ.docs();
35 let deprecated = typ.deprecated();
36 let item = &typ.inner;
37
38 let ctx = ctx.with(PathItem::Type(name.clone()));
39
40 let name = sanitise_type_name(ctx.clone(), NamedLocation::Type, name)?;
41
42 let mut inline_ts = String::new();
43 datatype_inner(
44 ctx.clone(),
45 &FunctionResultVariant::Value(typ.inner.clone()),
46 type_map,
47 &mut inline_ts,
48 )?;
49
50 let mut builder = super::comments::js_doc_builder(CommentFormatterArgs { docs, deprecated });
51
52 item.generics()
53 .into_iter()
54 .flatten()
55 .for_each(|generic| builder.push_generic(generic));
56
57 builder.push_internal(["@typedef { ", &inline_ts, " } ", &name]);
58
59 Ok(builder.build())
60}
61
62const START: &str = "/**\n";
63
64pub struct Builder {
65 value: String,
66}
67
68impl Builder {
69 pub fn push(&mut self, line: &str) {
70 self.push_internal([line.trim()]);
71 }
72
73 pub(crate) fn push_internal<'a>(&mut self, parts: impl IntoIterator<Item = &'a str>) {
74 self.value.push_str(" * ");
75
76 for part in parts.into_iter() {
77 self.value.push_str(part);
78 }
79
80 self.value.push('\n');
81 }
82
83 pub fn push_deprecated(&mut self, typ: &DeprecatedType) {
84 self.push_internal(
85 ["@deprecated"].into_iter().chain(
86 match typ {
87 DeprecatedType::DeprecatedWithSince {
88 note: message,
89 since,
90 } => Some((since.as_ref(), message)),
91 _ => None,
92 }
93 .map(|(since, message)| {
94 [" ", message.trim()].into_iter().chain(
95 since
96 .map(|since| [" since ", since.trim()])
97 .into_iter()
98 .flatten(),
99 )
100 })
101 .into_iter()
102 .flatten(),
103 ),
104 );
105 }
106
107 pub fn push_generic(&mut self, generic: &GenericType) {
108 self.push_internal(["@template ", generic.borrow()])
109 }
110
111 pub fn build(mut self) -> String {
112 if self.value == START {
113 return String::new();
114 }
115
116 self.value.push_str(" */\n");
117 self.value
118 }
119}
120
121impl Default for Builder {
122 fn default() -> Self {
123 Self {
124 value: START.to_string(),
125 }
126 }
127}
128
129impl<T: AsRef<str>> Extend<T> for Builder {
130 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
131 for item in iter {
132 self.push(item.as_ref());
133 }
134 }
135}