diff --git a/cli/src/main.rs b/cli/src/main.rs index 7b9611830..397699684 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -664,7 +664,7 @@ impl FontSearcher { let path = path.as_ref(); if let Ok(file) = File::open(path) { if let Ok(mmap) = unsafe { Mmap::map(&file) } { - for (i, info) in FontInfo::from_data(&mmap).enumerate() { + for (i, info) in FontInfo::iter(&mmap).enumerate() { self.book.push(info); self.fonts.push(FontSlot { path: path.into(), diff --git a/library/src/basics/heading.rs b/library/src/basics/heading.rs index 2781034eb..b7d8c72c3 100644 --- a/library/src/basics/heading.rs +++ b/library/src/basics/heading.rs @@ -7,9 +7,23 @@ use crate::text::{SpaceNode, TextNode, TextSize}; /// A section heading. /// +/// # Example +/// ``` +/// #set heading(numbering: "I.") +/// +/// = Introduction +/// In recent years, ... +/// ``` +/// +/// # Syntax +/// Headings can be created by starting a line with one or multiple equals +/// signs. The number of equals signs determines the heading's logical nesting +/// depth. +/// /// # Parameters /// - body: Content (positional, required) /// The heading's contents. +/// /// - level: NonZeroUsize (named) /// The logical nesting depth of the heading, starting from one. /// @@ -29,10 +43,31 @@ pub struct HeadingNode { #[node] impl HeadingNode { /// How to number the heading. + /// + /// # Example + /// ``` + /// #set heading(numbering: "1.a.") + /// + /// = A section + /// == A subsection + /// === A sub-subsection + /// ``` #[property(referenced)] pub const NUMBERING: Option = None; /// Whether the heading should appear in the outline. + /// + /// # Example + /// ``` + /// #outline() + /// + /// #heading[Normal] + /// This is a normal heading. + /// + /// #heading(outlined: false)[Hidden] + /// This heading does not appear + /// in the outline. + /// ``` pub const OUTLINED: bool = true; fn construct(_: &Vm, args: &mut Args) -> SourceResult { diff --git a/library/src/basics/list.rs b/library/src/basics/list.rs index c9215a507..15b26169d 100644 --- a/library/src/basics/list.rs +++ b/library/src/basics/list.rs @@ -8,12 +8,22 @@ use crate::text::{SpaceNode, TextNode}; /// # Parameters /// - items: Content (positional, variadic) /// The contents of the list items. +/// /// - start: NonZeroUsize (named) /// Which number to start the enumeration with. +/// /// - tight: bool (named) /// Makes the list more compact, if enabled. This looks better if the items /// fit into a single line each. /// +/// # Example +/// ``` +/// #show columns.with(2) +/// #list(tight: true)[Tight][List] +/// #colbreak() +/// #list(tight: false)[Wide][List] +/// ``` +/// /// # Tags /// - basics #[func] diff --git a/library/src/basics/table.rs b/library/src/basics/table.rs index d7e2e08fb..05f2ffff8 100644 --- a/library/src/basics/table.rs +++ b/library/src/basics/table.rs @@ -6,14 +6,19 @@ use crate::prelude::*; /// # Parameters /// - cells: Content (positional, variadic) /// The contents of the table cells. +/// /// - rows: TrackSizings (named) /// Defines the row sizes. +/// /// - columns: TrackSizings (named) /// Defines the column sizes. +/// /// - gutter: TrackSizings (named) /// Defines the gaps between rows & columns. +/// /// - column-gutter: TrackSizings (named) /// Defines the gaps between columns. Takes precedence over `gutter`. +/// /// - row-gutter: TrackSizings (named) /// Defines the gaps between rows. Takes precedence over `gutter`. /// diff --git a/library/src/compute/calc.rs b/library/src/compute/calc.rs index eccc45315..1984d5ef6 100644 --- a/library/src/compute/calc.rs +++ b/library/src/compute/calc.rs @@ -105,6 +105,7 @@ pub fn odd(args: &mut Args) -> SourceResult { /// # Parameters /// - dividend: ToMod (positional, required) /// The dividend of the modulus. +/// /// - divisor: ToMod (positional, required) /// The divisor of the modulus. /// diff --git a/library/src/compute/create.rs b/library/src/compute/create.rs index e3733d60a..cb693a1c3 100644 --- a/library/src/compute/create.rs +++ b/library/src/compute/create.rs @@ -77,12 +77,21 @@ pub fn luma(args: &mut Args) -> SourceResult { /// /// If this string is given, the individual components should not be given. /// +/// # Example +/// ``` +/// #let color = rgb("#239dad") +/// #text(16pt, color)[*Typst*] +/// ``` +/// /// - red: Component (positional) /// The red component. +/// /// - green: Component (positional) /// The green component. +/// /// - blue: Component (positional) /// The blue component. +/// /// - alpha: Component (positional) /// The alpha component. /// @@ -125,10 +134,13 @@ castable! { /// # Parameters /// - cyan: RatioComponent (positional, required) /// The cyan component. +/// /// - magenta: RatioComponent (positional, required) /// The magenta component. +/// /// - yellow: RatioComponent (positional, required) /// The yellow component. +/// /// - key: RatioComponent (positional, required) /// The key component. /// diff --git a/library/src/compute/utility.rs b/library/src/compute/utility.rs index bdad96185..ffad740e8 100644 --- a/library/src/compute/utility.rs +++ b/library/src/compute/utility.rs @@ -22,6 +22,7 @@ pub fn lorem(args: &mut Args) -> SourceResult { /// # Parameters /// - pattern: NumberingPattern (positional, required) /// A string that defines how the numbering works. +/// /// - numbers: NonZeroUsize (positional, variadic) /// The numbers to apply the pattern to. /// diff --git a/library/src/layout/align.rs b/library/src/layout/align.rs index 7853d84df..5426f5e28 100644 --- a/library/src/layout/align.rs +++ b/library/src/layout/align.rs @@ -5,6 +5,7 @@ use crate::prelude::*; /// # Parameters /// - body: Content (positional, required) /// The content to align. +/// /// - alignment: Axes> (positional, settable) /// The alignment along both axes. /// diff --git a/library/src/layout/columns.rs b/library/src/layout/columns.rs index b31b0a6d5..6154cd142 100644 --- a/library/src/layout/columns.rs +++ b/library/src/layout/columns.rs @@ -6,6 +6,7 @@ use crate::text::TextNode; /// # Parameters /// - count: usize (positional, required) /// The number of columns. +/// /// - body: Content (positional, required) /// The content that should be layouted into the columns. /// diff --git a/library/src/layout/container.rs b/library/src/layout/container.rs index 4b58434b8..5df6b2dc3 100644 --- a/library/src/layout/container.rs +++ b/library/src/layout/container.rs @@ -7,8 +7,10 @@ use crate::prelude::*; /// # Parameters /// - body: Content (positional) /// The contents of the box. +/// /// - width: Rel (named) /// The width of the box. +/// /// - height: Rel (named) /// The height of the box. /// @@ -78,11 +80,14 @@ impl Inline for BoxNode {} /// # Parameters /// - body: Content (positional) /// The contents of the block. +/// /// - spacing: Spacing (named, settable) /// The spacing around this block. +/// /// - above: Spacing (named, settable) /// The spacing between the previous and this block. Takes precedence over /// `spacing`. +/// /// - below: Spacing (named, settable) /// The spacing between this block and the following one. Takes precedence /// over `spacing`. diff --git a/library/src/layout/grid.rs b/library/src/layout/grid.rs index 8aaffe084..1cf950011 100644 --- a/library/src/layout/grid.rs +++ b/library/src/layout/grid.rs @@ -7,14 +7,19 @@ use super::Spacing; /// # Parameters /// - cells: Content (positional, variadic) /// The contents of the table cells. +/// /// - rows: TrackSizings (named) /// Defines the row sizes. +/// /// - columns: TrackSizings (named) /// Defines the column sizes. +/// /// - gutter: TrackSizings (named) /// Defines the gaps between rows & columns. +/// /// - column-gutter: TrackSizings (named) /// Defines the gaps between columns. Takes precedence over `gutter`. +/// /// - row-gutter: TrackSizings (named) /// Defines the gaps between rows. Takes precedence over `gutter`. /// diff --git a/library/src/layout/pad.rs b/library/src/layout/pad.rs index 94492f834..1326ae22a 100644 --- a/library/src/layout/pad.rs +++ b/library/src/layout/pad.rs @@ -5,18 +5,25 @@ use crate::prelude::*; /// # Parameters /// - body: Content (positional, required) /// The content to pad at the sides. +/// /// - left: Rel (named) /// The padding at the left side. +/// /// - right: Rel (named) /// The padding at the right side. +/// /// - top: Rel (named) /// The padding at the top side. +/// /// - bottom: Rel (named) /// The padding at the bottom side. +/// /// - x: Rel (named) /// The horizontal padding. Both `left` and `right` take precedence over this. +/// /// - y: Rel (named) /// The vertical padding. Both `top` and `bottom` take precedence over this. +/// /// - rest: Rel (named) /// The padding for all sides. All other parameters take precedence over this. /// diff --git a/library/src/layout/page.rs b/library/src/layout/page.rs index 8782ed08d..a2548c025 100644 --- a/library/src/layout/page.rs +++ b/library/src/layout/page.rs @@ -9,6 +9,7 @@ use crate::text::TextNode; /// # Parameters /// - body: Content (positional, required) /// The contents of the page(s). +/// /// - paper: Paper (positional, settable) /// The paper size. /// diff --git a/library/src/layout/place.rs b/library/src/layout/place.rs index 890480a71..8baf69afc 100644 --- a/library/src/layout/place.rs +++ b/library/src/layout/place.rs @@ -5,10 +5,13 @@ use crate::prelude::*; /// # Parameters /// - alignment: Axes> (positional) /// Relative to which position in the parent container to place the content. +/// /// - body: Content (positional, required) /// The content to place. +/// /// - dx: Rel (named) /// The horizontal displacement of the placed content. +/// /// - dy: Rel (named) /// The vertical displacement of the placed content. /// diff --git a/library/src/layout/spacing.rs b/library/src/layout/spacing.rs index ef69c0709..092d2c0ab 100644 --- a/library/src/layout/spacing.rs +++ b/library/src/layout/spacing.rs @@ -7,6 +7,7 @@ use crate::prelude::*; /// # Parameters /// - amount: Spacing (positional, required) /// How much spacing to insert. +/// /// - weak: bool (named) /// If true, the spacing collapses at the start or end of a paragraph. /// Moreover, from multiple adjacent weak spacings all but the largest one @@ -67,6 +68,7 @@ impl Behave for HNode { /// # Parameters /// - amount: Spacing (positional, required) /// How much spacing to insert. +/// /// - weak: bool (named) /// If true, the spacing collapses at the start or end of a flow. /// Moreover, from multiple adjacent weak spacings all but the largest one diff --git a/library/src/layout/stack.rs b/library/src/layout/stack.rs index deb565b61..2683175a3 100644 --- a/library/src/layout/stack.rs +++ b/library/src/layout/stack.rs @@ -8,8 +8,10 @@ use crate::prelude::*; /// # Parameters /// - items: StackChild (positional, variadic) /// The items to stack along an axis. +/// /// - dir: Dir (named) /// The direction along which the items are stacked. +/// /// - spacing: Spacing (named) /// Spacing to insert between items where no explicit spacing was provided. /// diff --git a/library/src/layout/transform.rs b/library/src/layout/transform.rs index 3af44ca06..b509607d4 100644 --- a/library/src/layout/transform.rs +++ b/library/src/layout/transform.rs @@ -7,8 +7,10 @@ use crate::prelude::*; /// # Parameters /// - body: Content (positional, required) /// The content to move. +/// /// - dx: Rel (named) /// The horizontal displacement of the content. +/// /// - dy: Rel (named) /// The vertical displacement of the content. /// @@ -61,10 +63,13 @@ impl Inline for MoveNode {} /// # Parameters /// - body: Content (positional, required) /// The content to transform. +/// /// - angle: Angle (named) /// The amount of rotation. +/// /// - x: Ratio (named) /// The horizontal scaling factor. +/// /// - y: Ratio (named) /// The vertical scaling factor. /// diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs index 3bd7b2e34..5342a954f 100644 --- a/library/src/math/mod.rs +++ b/library/src/math/mod.rs @@ -19,6 +19,7 @@ use crate::text::{FontFamily, LinebreakNode, SpaceNode, SymbolNode, TextNode}; /// # Parameters /// - items: Content (positional, variadic) /// The individual parts of the formula. +/// /// - block: bool (named) /// Whether the formula is displayed as a separate block. /// @@ -309,6 +310,7 @@ impl Texify for AtomNode { /// # Parameters /// - base: Content (positional, required) /// The base to which the accent is applied. +/// /// - accent: Content (positional, required) /// The accent to apply to the base. /// @@ -393,6 +395,7 @@ impl Texify for AccNode { /// # Parameters /// - num: Content (positional, required) /// The fraction's numerator. +/// /// - denom: Content (positional, required) /// The fraction's denominator. /// @@ -433,6 +436,7 @@ impl Texify for FracNode { /// # Parameters /// - upper: Content (positional, required) /// The binomial's upper index. +/// /// - lower: Content (positional, required) /// The binomial's lower index. /// @@ -473,8 +477,10 @@ impl Texify for BinomNode { /// # Parameters /// - base: Content (positional, required) /// The base to which the applies the sub- and/or superscript. +/// /// - sub: Content (named) /// The subscript. +/// /// - sup: Content (named) /// The superscript. /// diff --git a/library/src/meta/link.rs b/library/src/meta/link.rs index 27294a8d1..6a2f66dfe 100644 --- a/library/src/meta/link.rs +++ b/library/src/meta/link.rs @@ -6,6 +6,7 @@ use crate::text::TextNode; /// # Parameters /// - dest: Destination (positional, required) /// The destination the link points to. +/// /// - body: Content (positional) /// How the link is represented. Defaults to the destination if it is a link. /// diff --git a/library/src/text/mod.rs b/library/src/text/mod.rs index 21dea8af0..315de95db 100644 --- a/library/src/text/mod.rs +++ b/library/src/text/mod.rs @@ -30,6 +30,7 @@ use crate::prelude::*; /// # Parameters /// - family: EcoString (positional, variadic, settable) /// A prioritized sequence of font families. +/// /// - body: Content (positional, required) /// Content in which all text is styled according to the other arguments. /// diff --git a/library/src/text/raw.rs b/library/src/text/raw.rs index 746265885..55c292989 100644 --- a/library/src/text/raw.rs +++ b/library/src/text/raw.rs @@ -11,6 +11,7 @@ use crate::prelude::*; /// # Parameters /// - text: EcoString (positional, required) /// The raw text. +/// /// - block: bool (named) /// Whether the raw text is displayed as a separate block. /// diff --git a/library/src/visualize/line.rs b/library/src/visualize/line.rs index 5c8c96444..6c60ef4e5 100644 --- a/library/src/visualize/line.rs +++ b/library/src/visualize/line.rs @@ -7,10 +7,13 @@ use crate::prelude::*; /// # Parameters /// - origin: Axes> (named) /// The start point of the line. +/// /// - to: Axes> (named) /// The end point of the line. +/// /// - length: Rel (named) /// The line's length. +/// /// - angle: Angle (named) /// The angle at which the line points away from the origin. /// diff --git a/library/src/visualize/shape.rs b/library/src/visualize/shape.rs index be80b4fbc..9c66e8671 100644 --- a/library/src/visualize/shape.rs +++ b/library/src/visualize/shape.rs @@ -7,14 +7,19 @@ use crate::prelude::*; /// # Parameters /// - body: Content (positional) /// The content to place into the shape. +/// /// - width: Rel (named) /// The shape's width. +/// /// - height: Rel (named) /// The shape's height. +/// /// - size: Length (named) /// The square's side length. +/// /// - radius: Length (named) /// The circle's radius. +/// /// - stroke: Smart>> (named) /// How to stroke the shape. /// diff --git a/macros/src/func.rs b/macros/src/func.rs index 98fca6a43..62fbfd72e 100644 --- a/macros/src/func.rs +++ b/macros/src/func.rs @@ -1,4 +1,3 @@ -use proc_macro2::Span; use unscanny::Scanner; use super::*; @@ -14,12 +13,21 @@ pub fn func(item: syn::Item) -> Result { let tags = tags(&mut docs); let params = params(&mut docs)?; + let example = quote_option(example(&mut docs)); + let syntax = quote_option(section(&mut docs, "Syntax")); + let docs = docs.trim(); + if docs.contains("# ") { + bail!(item, "Documentation heading not recognized"); + } + let info = quote! { ::typst::model::FuncInfo { name, - docs: #docs, tags: &[#(#tags),*], + docs: #docs, + example: #example, + syntax: #syntax, params: ::std::vec![#(#params),*], } }; @@ -76,18 +84,18 @@ pub fn func(item: syn::Item) -> Result { /// Extract a section. pub fn section(docs: &mut String, title: &str) -> Option { - let needle = format!("# {title}\n"); + let needle = format!("\n# {title}\n"); let start = docs.find(&needle)?; let rest = &docs[start..]; - let len = rest[1..].find('#').map(|x| 1 + x).unwrap_or(rest.len()); + let len = rest[1..].find("\n# ").map(|x| 1 + x).unwrap_or(rest.len()); let end = start + len; - let section = docs[start + needle.len()..].to_owned(); + let section = docs[start + needle.len()..end].trim().to_owned(); docs.replace_range(start..end, ""); Some(section) } /// Parse the tag section. -pub fn tags(docs: &mut String) -> Vec { +fn tags(docs: &mut String) -> Vec { section(docs, "Tags") .unwrap_or_default() .lines() @@ -96,24 +104,40 @@ pub fn tags(docs: &mut String) -> Vec { .collect() } +/// Parse the example section. +pub fn example(docs: &mut String) -> Option { + Some( + section(docs, "Example")? + .lines() + .skip_while(|line| !line.contains("```")) + .skip(1) + .take_while(|line| !line.contains("```")) + .map(|s| s.trim()) + .collect::>() + .join("\n"), + ) +} + /// Parse the parameter section. -pub fn params(docs: &mut String) -> Result> { +fn params(docs: &mut String) -> Result> { let Some(section) = section(docs, "Parameters") else { return Ok(vec![]) }; let mut s = Scanner::new(§ion); let mut infos = vec![]; while s.eat_if('-') { - s.eat_whitespace(); - let name = s.eat_until(':'); - s.expect(": "); - let ty: syn::Type = syn::parse_str(s.eat_until(char::is_whitespace))?; - s.eat_whitespace(); let mut named = false; let mut positional = false; let mut required = false; let mut variadic = false; let mut settable = false; + + s.eat_whitespace(); + let name = s.eat_until(':'); + s.expect(": "); + let ty: syn::Type = syn::parse_str(s.eat_until(char::is_whitespace))?; + s.eat_whitespace(); s.expect('('); + for part in s.eat_until(')').split(',').map(str::trim).filter(|s| !s.is_empty()) { match part { "named" => named = true, @@ -121,12 +145,7 @@ pub fn params(docs: &mut String) -> Result> { "required" => required = true, "variadic" => variadic = true, "settable" => settable = true, - _ => { - return Err(syn::Error::new( - Span::call_site(), - format!("unknown parameter flag {:?}", part), - )) - } + _ => bail!(callsite, "unknown parameter flag {:?}", part), } } @@ -135,18 +154,20 @@ pub fn params(docs: &mut String) -> Result> { || (named && variadic) || (required && variadic) { - return Err(syn::Error::new( - Span::call_site(), - "invalid combination of parameter flags", - )); + bail!(callsite, "invalid combination of parameter flags"); } s.expect(')'); - let docs = dedent(s.eat_until("\n-").trim()); + + let mut docs = dedent(s.eat_until("\n-").trim()); + let example = quote_option(example(&mut docs)); + let docs = docs.trim(); + infos.push(quote! { ::typst::model::ParamInfo { name: #name, docs: #docs, + example: #example, cast: <#ty as ::typst::model::Cast< ::typst::syntax::Spanned<::typst::model::Value> >>::describe(), diff --git a/macros/src/lib.rs b/macros/src/lib.rs index a03dc30e4..23b03712e 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -4,12 +4,18 @@ extern crate proc_macro; /// Return an error at the given item. macro_rules! bail { + (callsite, $fmt:literal $($tts:tt)*) => { + return Err(syn::Error::new( + proc_macro2::Span::call_site(), + format!(concat!("typst: ", $fmt) $($tts)*) + )) + }; ($item:expr, $fmt:literal $($tts:tt)*) => { - return Err(Error::new_spanned( + return Err(syn::Error::new_spanned( &$item, format!(concat!("typst: ", $fmt) $($tts)*) )) - } + }; } mod capable; @@ -19,9 +25,8 @@ mod node; use proc_macro::TokenStream as BoundaryStream; use proc_macro2::{TokenStream, TokenTree}; -use quote::{quote, quote_spanned}; -use syn::parse_quote; -use syn::{Error, Ident, Result}; +use quote::{quote, quote_spanned, ToTokens}; +use syn::{parse_quote, Ident, Result}; /// Implement `FuncType` for a type or function. #[proc_macro_attribute] @@ -88,3 +93,11 @@ fn documentation(attrs: &[syn::Attribute]) -> String { fn dedent(text: &str) -> String { text.lines().map(str::trim).collect::>().join("\n") } + +/// Quote an optional value. +fn quote_option(option: Option) -> TokenStream { + match option { + Some(value) => quote! { Some(#value) }, + None => quote! { None }, + } +} diff --git a/macros/src/node.rs b/macros/src/node.rs index 1e03c4414..5f9573f95 100644 --- a/macros/src/node.rs +++ b/macros/src/node.rs @@ -333,13 +333,18 @@ fn create_node_set_func(node: &Node) -> syn::ImplItemMethod { fn create_node_properties_func(node: &Node) -> syn::ImplItemMethod { let infos = node.properties.iter().filter(|p| !p.skip).map(|property| { let name = property.name.to_string().replace('_', "-").to_lowercase(); - let docs = documentation(&property.attrs); let value_ty = &property.value_ty; let shorthand = matches!(property.shorthand, Some(Shorthand::Positional)); + + let mut docs = documentation(&property.attrs); + let example = quote_option(super::func::example(&mut docs)); + let docs = docs.trim(); + quote! { ::typst::model::ParamInfo { name: #name, docs: #docs, + example: #example, cast: <#value_ty as ::typst::model::Cast< ::typst::syntax::Spanned<::typst::model::Value> >>::describe(), diff --git a/src/font/book.rs b/src/font/book.rs index 2ad30f1d2..38dfee1da 100644 --- a/src/font/book.rs +++ b/src/font/book.rs @@ -170,7 +170,7 @@ bitflags::bitflags! { impl FontInfo { /// Compute metadata for all fonts in the given data. - pub fn from_data(data: &[u8]) -> impl Iterator + '_ { + pub fn iter(data: &[u8]) -> impl Iterator + '_ { let count = ttf_parser::fonts_in_collection(data).unwrap_or(1); (0..count).filter_map(move |index| { let ttf = ttf_parser::Face::parse(data, index).ok()?; @@ -179,7 +179,7 @@ impl FontInfo { } /// Compute metadata for a single ttf-parser face. - pub fn from_ttf(ttf: &ttf_parser::Face) -> Option { + pub(super) fn from_ttf(ttf: &ttf_parser::Face) -> Option { // We cannot use Name ID 16 "Typographic Family", because for some // fonts it groups together more than just Style / Weight / Stretch // variants (e.g. Display variants of Noto fonts) and then some diff --git a/src/font/mod.rs b/src/font/mod.rs index 98875d8f9..13189b6d0 100644 --- a/src/font/mod.rs +++ b/src/font/mod.rs @@ -69,6 +69,12 @@ impl Font { }))) } + /// Parse all fonts in the given data. + pub fn iter(data: Buffer) -> impl Iterator { + let count = ttf_parser::fonts_in_collection(&data).unwrap_or(1); + (0..count).filter_map(move |index| Self::new(data.clone(), index)) + } + /// The underlying buffer. pub fn data(&self) -> &Buffer { &self.0.data diff --git a/src/model/func.rs b/src/model/func.rs index 46befd777..fb8b3dd0e 100644 --- a/src/model/func.rs +++ b/src/model/func.rs @@ -214,6 +214,10 @@ pub struct FuncInfo { pub tags: &'static [&'static str], /// Documentation for the function. pub docs: &'static str, + /// The source code of an example, if any. + pub example: Option<&'static str>, + /// Documentation about this function's syntax, if it has syntax. + pub syntax: Option<&'static str>, /// Details about the function's parameters. pub params: Vec, } @@ -232,6 +236,8 @@ pub struct ParamInfo { pub name: &'static str, /// Documentation for the parameter. pub docs: &'static str, + /// The source code of an example, if any. + pub example: Option<&'static str>, /// Valid values for the parameter. pub cast: CastInfo, /// Is the parameter positional? diff --git a/src/model/library.rs b/src/model/library.rs index 83310610d..8b767b0e3 100644 --- a/src/model/library.rs +++ b/src/model/library.rs @@ -122,7 +122,7 @@ pub static LANG_ITEMS: OnceCell = OnceCell::new(); /// break incremental, but only when different sets of lang items are used in /// the same program. For this reason, if this function is called multiple /// times, the items must be the same. -pub(crate) fn set_lang_items(items: LangItems) { +pub fn set_lang_items(items: LangItems) { if let Err(items) = LANG_ITEMS.set(items) { let first = hash128(LANG_ITEMS.get().unwrap()); let second = hash128(&items); diff --git a/tests/src/tests.rs b/tests/src/tests.rs index 7c1e39b72..7316ed115 100644 --- a/tests/src/tests.rs +++ b/tests/src/tests.rs @@ -213,10 +213,8 @@ impl TestWorld { .filter_map(|e| e.ok()) .filter(|entry| entry.file_type().is_file()) { - let buffer: Buffer = fs::read(entry.path()).unwrap().into(); - for index in 0..ttf_parser::fonts_in_collection(&buffer).unwrap_or(1) { - fonts.push(Font::new(buffer.clone(), index).unwrap()) - } + let data = std::fs::read(entry.path()).unwrap(); + fonts.extend(Font::iter(data.into())); } Self {