Added ghost
attr to elem
macro (#2718)
This commit is contained in:
parent
b479be8e9e
commit
9b5b3b2557
@ -42,6 +42,7 @@ use crate::text::{
|
|||||||
pub struct ParElem {
|
pub struct ParElem {
|
||||||
/// The spacing between lines.
|
/// The spacing between lines.
|
||||||
#[resolve]
|
#[resolve]
|
||||||
|
#[ghost]
|
||||||
#[default(Em::new(0.65).into())]
|
#[default(Em::new(0.65).into())]
|
||||||
pub leading: Length,
|
pub leading: Length,
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ pub struct ParElem {
|
|||||||
/// Note that the current [alignment]($align) still has an effect on the
|
/// Note that the current [alignment]($align) still has an effect on the
|
||||||
/// placement of the last line except if it ends with a
|
/// placement of the last line except if it ends with a
|
||||||
/// [justified line break]($linebreak.justify).
|
/// [justified line break]($linebreak.justify).
|
||||||
|
#[ghost]
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
pub justify: bool,
|
pub justify: bool,
|
||||||
|
|
||||||
@ -78,6 +80,7 @@ pub struct ParElem {
|
|||||||
/// challenging to break in a visually
|
/// challenging to break in a visually
|
||||||
/// pleasing way.
|
/// pleasing way.
|
||||||
/// ```
|
/// ```
|
||||||
|
#[ghost]
|
||||||
pub linebreaks: Smart<Linebreaks>,
|
pub linebreaks: Smart<Linebreaks>,
|
||||||
|
|
||||||
/// The indent the first line of a paragraph should have.
|
/// The indent the first line of a paragraph should have.
|
||||||
@ -90,9 +93,11 @@ pub struct ParElem {
|
|||||||
/// the [paragraph spacing]($block.spacing) to the [`leading`] when
|
/// the [paragraph spacing]($block.spacing) to the [`leading`] when
|
||||||
/// using this property (e.g. using
|
/// using this property (e.g. using
|
||||||
/// `[#show par: set block(spacing: 0.65em)]`).
|
/// `[#show par: set block(spacing: 0.65em)]`).
|
||||||
|
#[ghost]
|
||||||
pub first_line_indent: Length,
|
pub first_line_indent: Length,
|
||||||
|
|
||||||
/// The indent all but the first line of a paragraph should have.
|
/// The indent all but the first line of a paragraph should have.
|
||||||
|
#[ghost]
|
||||||
#[resolve]
|
#[resolve]
|
||||||
pub hanging_indent: Length,
|
pub hanging_indent: Length,
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ pub struct TextElem {
|
|||||||
/// ```
|
/// ```
|
||||||
#[default(FontList(vec![FontFamily::new("Linux Libertine")]))]
|
#[default(FontList(vec![FontFamily::new("Linux Libertine")]))]
|
||||||
#[borrowed]
|
#[borrowed]
|
||||||
|
#[ghost]
|
||||||
pub font: FontList,
|
pub font: FontList,
|
||||||
|
|
||||||
/// Whether to allow last resort font fallback when the primary font list
|
/// Whether to allow last resort font fallback when the primary font list
|
||||||
@ -118,6 +119,7 @@ pub struct TextElem {
|
|||||||
/// هذا عربي
|
/// هذا عربي
|
||||||
/// ```
|
/// ```
|
||||||
#[default(true)]
|
#[default(true)]
|
||||||
|
#[ghost]
|
||||||
pub fallback: bool,
|
pub fallback: bool,
|
||||||
|
|
||||||
/// The desired font style.
|
/// The desired font style.
|
||||||
@ -137,6 +139,7 @@ pub struct TextElem {
|
|||||||
/// #text(font: "Linux Libertine", style: "italic")[Italic]
|
/// #text(font: "Linux Libertine", style: "italic")[Italic]
|
||||||
/// #text(font: "DejaVu Sans", style: "oblique")[Oblique]
|
/// #text(font: "DejaVu Sans", style: "oblique")[Oblique]
|
||||||
/// ```
|
/// ```
|
||||||
|
#[ghost]
|
||||||
pub style: FontStyle,
|
pub style: FontStyle,
|
||||||
|
|
||||||
/// The desired thickness of the font's glyphs. Accepts an integer between
|
/// The desired thickness of the font's glyphs. Accepts an integer between
|
||||||
@ -158,6 +161,7 @@ pub struct TextElem {
|
|||||||
/// #text(weight: 500)[Medium] \
|
/// #text(weight: 500)[Medium] \
|
||||||
/// #text(weight: "bold")[Bold]
|
/// #text(weight: "bold")[Bold]
|
||||||
/// ```
|
/// ```
|
||||||
|
#[ghost]
|
||||||
pub weight: FontWeight,
|
pub weight: FontWeight,
|
||||||
|
|
||||||
/// The desired width of the glyphs. Accepts a ratio between `{50%}` and
|
/// The desired width of the glyphs. Accepts a ratio between `{50%}` and
|
||||||
@ -173,6 +177,7 @@ pub struct TextElem {
|
|||||||
/// #text(stretch: 75%)[Condensed] \
|
/// #text(stretch: 75%)[Condensed] \
|
||||||
/// #text(stretch: 100%)[Normal]
|
/// #text(stretch: 100%)[Normal]
|
||||||
/// ```
|
/// ```
|
||||||
|
#[ghost]
|
||||||
pub stretch: FontStretch,
|
pub stretch: FontStretch,
|
||||||
|
|
||||||
/// The size of the glyphs. This value forms the basis of the `em` unit:
|
/// The size of the glyphs. This value forms the basis of the `em` unit:
|
||||||
@ -188,6 +193,7 @@ pub struct TextElem {
|
|||||||
#[parse(args.named_or_find("size")?)]
|
#[parse(args.named_or_find("size")?)]
|
||||||
#[fold]
|
#[fold]
|
||||||
#[default(Abs::pt(11.0))]
|
#[default(Abs::pt(11.0))]
|
||||||
|
#[ghost]
|
||||||
pub size: TextSize,
|
pub size: TextSize,
|
||||||
|
|
||||||
/// The glyph fill paint.
|
/// The glyph fill paint.
|
||||||
@ -214,6 +220,7 @@ pub struct TextElem {
|
|||||||
paint.map(|paint| paint.v)
|
paint.map(|paint| paint.v)
|
||||||
})]
|
})]
|
||||||
#[default(Color::BLACK.into())]
|
#[default(Color::BLACK.into())]
|
||||||
|
#[ghost]
|
||||||
pub fill: Paint,
|
pub fill: Paint,
|
||||||
|
|
||||||
/// The amount of space that should be added between characters.
|
/// The amount of space that should be added between characters.
|
||||||
@ -223,6 +230,7 @@ pub struct TextElem {
|
|||||||
/// Distant text.
|
/// Distant text.
|
||||||
/// ```
|
/// ```
|
||||||
#[resolve]
|
#[resolve]
|
||||||
|
#[ghost]
|
||||||
pub tracking: Length,
|
pub tracking: Length,
|
||||||
|
|
||||||
/// The amount of space between words.
|
/// The amount of space between words.
|
||||||
@ -239,6 +247,7 @@ pub struct TextElem {
|
|||||||
/// ```
|
/// ```
|
||||||
#[resolve]
|
#[resolve]
|
||||||
#[default(Rel::one())]
|
#[default(Rel::one())]
|
||||||
|
#[ghost]
|
||||||
pub spacing: Rel<Length>,
|
pub spacing: Rel<Length>,
|
||||||
|
|
||||||
/// Whether to automatically insert spacing between CJK and Latin characters.
|
/// Whether to automatically insert spacing between CJK and Latin characters.
|
||||||
@ -250,6 +259,7 @@ pub struct TextElem {
|
|||||||
/// #set text(cjk-latin-spacing: none)
|
/// #set text(cjk-latin-spacing: none)
|
||||||
/// 第4章介绍了基本的API。
|
/// 第4章介绍了基本的API。
|
||||||
/// ```
|
/// ```
|
||||||
|
#[ghost]
|
||||||
pub cjk_latin_spacing: Smart<Option<Never>>,
|
pub cjk_latin_spacing: Smart<Option<Never>>,
|
||||||
|
|
||||||
/// An amount to shift the text baseline by.
|
/// An amount to shift the text baseline by.
|
||||||
@ -259,6 +269,7 @@ pub struct TextElem {
|
|||||||
/// word.
|
/// word.
|
||||||
/// ```
|
/// ```
|
||||||
#[resolve]
|
#[resolve]
|
||||||
|
#[ghost]
|
||||||
pub baseline: Length,
|
pub baseline: Length,
|
||||||
|
|
||||||
/// Whether certain glyphs can hang over into the margin in justified text.
|
/// Whether certain glyphs can hang over into the margin in justified text.
|
||||||
@ -278,6 +289,7 @@ pub struct TextElem {
|
|||||||
/// results in a clearer paragraph edge.
|
/// results in a clearer paragraph edge.
|
||||||
/// ```
|
/// ```
|
||||||
#[default(true)]
|
#[default(true)]
|
||||||
|
#[ghost]
|
||||||
pub overhang: bool,
|
pub overhang: bool,
|
||||||
|
|
||||||
/// The top end of the conceptual frame around the text used for layout and
|
/// The top end of the conceptual frame around the text used for layout and
|
||||||
@ -294,6 +306,7 @@ pub struct TextElem {
|
|||||||
/// #rect(fill: aqua)[Typst]
|
/// #rect(fill: aqua)[Typst]
|
||||||
/// ```
|
/// ```
|
||||||
#[default(TopEdge::Metric(TopEdgeMetric::CapHeight))]
|
#[default(TopEdge::Metric(TopEdgeMetric::CapHeight))]
|
||||||
|
#[ghost]
|
||||||
pub top_edge: TopEdge,
|
pub top_edge: TopEdge,
|
||||||
|
|
||||||
/// The bottom end of the conceptual frame around the text used for layout
|
/// The bottom end of the conceptual frame around the text used for layout
|
||||||
@ -310,6 +323,7 @@ pub struct TextElem {
|
|||||||
/// #rect(fill: aqua)[Typst]
|
/// #rect(fill: aqua)[Typst]
|
||||||
/// ```
|
/// ```
|
||||||
#[default(BottomEdge::Metric(BottomEdgeMetric::Baseline))]
|
#[default(BottomEdge::Metric(BottomEdgeMetric::Baseline))]
|
||||||
|
#[ghost]
|
||||||
pub bottom_edge: BottomEdge,
|
pub bottom_edge: BottomEdge,
|
||||||
|
|
||||||
/// An [ISO 639-1/2/3 language code.](https://en.wikipedia.org/wiki/ISO_639)
|
/// An [ISO 639-1/2/3 language code.](https://en.wikipedia.org/wiki/ISO_639)
|
||||||
@ -330,11 +344,13 @@ pub struct TextElem {
|
|||||||
/// In diesem Dokument, ...
|
/// In diesem Dokument, ...
|
||||||
/// ```
|
/// ```
|
||||||
#[default(Lang::ENGLISH)]
|
#[default(Lang::ENGLISH)]
|
||||||
|
#[ghost]
|
||||||
pub lang: Lang,
|
pub lang: Lang,
|
||||||
|
|
||||||
/// An [ISO 3166-1 alpha-2 region code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
|
/// An [ISO 3166-1 alpha-2 region code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
|
||||||
///
|
///
|
||||||
/// This lets the text processing pipeline make more informed choices.
|
/// This lets the text processing pipeline make more informed choices.
|
||||||
|
#[ghost]
|
||||||
pub region: Option<Region>,
|
pub region: Option<Region>,
|
||||||
|
|
||||||
/// The OpenType writing script.
|
/// The OpenType writing script.
|
||||||
@ -364,6 +380,7 @@ pub struct TextElem {
|
|||||||
/// #set text(lang: "ro", script: "grek")
|
/// #set text(lang: "ro", script: "grek")
|
||||||
/// #scedilla // S with a cedilla
|
/// #scedilla // S with a cedilla
|
||||||
/// ```
|
/// ```
|
||||||
|
#[ghost]
|
||||||
pub script: Smart<WritingScript>,
|
pub script: Smart<WritingScript>,
|
||||||
|
|
||||||
/// The dominant direction for text and inline objects. Possible values are:
|
/// The dominant direction for text and inline objects. Possible values are:
|
||||||
@ -391,6 +408,7 @@ pub struct TextElem {
|
|||||||
/// هذا عربي.
|
/// هذا عربي.
|
||||||
/// ```
|
/// ```
|
||||||
#[resolve]
|
#[resolve]
|
||||||
|
#[ghost]
|
||||||
pub dir: TextDir,
|
pub dir: TextDir,
|
||||||
|
|
||||||
/// Whether to hyphenate text to improve line breaking. When `{auto}`, text
|
/// Whether to hyphenate text to improve line breaking. When `{auto}`, text
|
||||||
@ -413,6 +431,7 @@ pub struct TextElem {
|
|||||||
/// improve justification.
|
/// improve justification.
|
||||||
/// ```
|
/// ```
|
||||||
#[resolve]
|
#[resolve]
|
||||||
|
#[ghost]
|
||||||
pub hyphenate: Hyphenate,
|
pub hyphenate: Hyphenate,
|
||||||
|
|
||||||
/// Whether to apply kerning.
|
/// Whether to apply kerning.
|
||||||
@ -431,6 +450,7 @@ pub struct TextElem {
|
|||||||
/// Totally
|
/// Totally
|
||||||
/// ```
|
/// ```
|
||||||
#[default(true)]
|
#[default(true)]
|
||||||
|
#[ghost]
|
||||||
pub kerning: bool,
|
pub kerning: bool,
|
||||||
|
|
||||||
/// Whether to apply stylistic alternates.
|
/// Whether to apply stylistic alternates.
|
||||||
@ -451,6 +471,7 @@ pub struct TextElem {
|
|||||||
/// 0, a, g, ß
|
/// 0, a, g, ß
|
||||||
/// ```
|
/// ```
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
|
#[ghost]
|
||||||
pub alternates: bool,
|
pub alternates: bool,
|
||||||
|
|
||||||
/// Which stylistic set to apply. Font designers can categorize alternative
|
/// Which stylistic set to apply. Font designers can categorize alternative
|
||||||
@ -458,6 +479,7 @@ pub struct TextElem {
|
|||||||
/// you need to consult your font to know which sets are available. When set
|
/// you need to consult your font to know which sets are available. When set
|
||||||
/// to an integer between `{1}` and `{20}`, enables the corresponding
|
/// to an integer between `{1}` and `{20}`, enables the corresponding
|
||||||
/// OpenType font feature from `ss01`, ..., `ss20`.
|
/// OpenType font feature from `ss01`, ..., `ss20`.
|
||||||
|
#[ghost]
|
||||||
pub stylistic_set: Option<StylisticSet>,
|
pub stylistic_set: Option<StylisticSet>,
|
||||||
|
|
||||||
/// Whether standard ligatures are active.
|
/// Whether standard ligatures are active.
|
||||||
@ -475,16 +497,19 @@ pub struct TextElem {
|
|||||||
/// A fine ligature.
|
/// A fine ligature.
|
||||||
/// ```
|
/// ```
|
||||||
#[default(true)]
|
#[default(true)]
|
||||||
|
#[ghost]
|
||||||
pub ligatures: bool,
|
pub ligatures: bool,
|
||||||
|
|
||||||
/// Whether ligatures that should be used sparingly are active. Setting this
|
/// Whether ligatures that should be used sparingly are active. Setting this
|
||||||
/// to `{true}` enables the OpenType `dlig` font feature.
|
/// to `{true}` enables the OpenType `dlig` font feature.
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
|
#[ghost]
|
||||||
pub discretionary_ligatures: bool,
|
pub discretionary_ligatures: bool,
|
||||||
|
|
||||||
/// Whether historical ligatures are active. Setting this to `{true}`
|
/// Whether historical ligatures are active. Setting this to `{true}`
|
||||||
/// enables the OpenType `hlig` font feature.
|
/// enables the OpenType `hlig` font feature.
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
|
#[ghost]
|
||||||
pub historical_ligatures: bool,
|
pub historical_ligatures: bool,
|
||||||
|
|
||||||
/// Which kind of numbers / figures to select. When set to `{auto}`, the
|
/// Which kind of numbers / figures to select. When set to `{auto}`, the
|
||||||
@ -498,6 +523,7 @@ pub struct TextElem {
|
|||||||
/// #set text(number-type: "old-style")
|
/// #set text(number-type: "old-style")
|
||||||
/// Number 9.
|
/// Number 9.
|
||||||
/// ```
|
/// ```
|
||||||
|
#[ghost]
|
||||||
pub number_type: Smart<NumberType>,
|
pub number_type: Smart<NumberType>,
|
||||||
|
|
||||||
/// The width of numbers / figures. When set to `{auto}`, the default
|
/// The width of numbers / figures. When set to `{auto}`, the default
|
||||||
@ -513,6 +539,7 @@ pub struct TextElem {
|
|||||||
/// A 12 B 34. \
|
/// A 12 B 34. \
|
||||||
/// A 56 B 78.
|
/// A 56 B 78.
|
||||||
/// ```
|
/// ```
|
||||||
|
#[ghost]
|
||||||
pub number_width: Smart<NumberWidth>,
|
pub number_width: Smart<NumberWidth>,
|
||||||
|
|
||||||
/// Whether to have a slash through the zero glyph. Setting this to `{true}`
|
/// Whether to have a slash through the zero glyph. Setting this to `{true}`
|
||||||
@ -522,6 +549,7 @@ pub struct TextElem {
|
|||||||
/// 0, #text(slashed-zero: true)[0]
|
/// 0, #text(slashed-zero: true)[0]
|
||||||
/// ```
|
/// ```
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
|
#[ghost]
|
||||||
pub slashed_zero: bool,
|
pub slashed_zero: bool,
|
||||||
|
|
||||||
/// Whether to turn numbers into fractions. Setting this to `{true}`
|
/// Whether to turn numbers into fractions. Setting this to `{true}`
|
||||||
@ -536,6 +564,7 @@ pub struct TextElem {
|
|||||||
/// #text(fractions: true)[1/2]
|
/// #text(fractions: true)[1/2]
|
||||||
/// ```
|
/// ```
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
|
#[ghost]
|
||||||
pub fractions: bool,
|
pub fractions: bool,
|
||||||
|
|
||||||
/// Raw OpenType features to apply.
|
/// Raw OpenType features to apply.
|
||||||
@ -551,6 +580,7 @@ pub struct TextElem {
|
|||||||
/// 1/2
|
/// 1/2
|
||||||
/// ```
|
/// ```
|
||||||
#[fold]
|
#[fold]
|
||||||
|
#[ghost]
|
||||||
pub features: FontFeatures,
|
pub features: FontFeatures,
|
||||||
|
|
||||||
/// Content in which all text is styled according to the other arguments.
|
/// Content in which all text is styled according to the other arguments.
|
||||||
@ -566,26 +596,31 @@ pub struct TextElem {
|
|||||||
/// A delta to apply on the font weight.
|
/// A delta to apply on the font weight.
|
||||||
#[internal]
|
#[internal]
|
||||||
#[fold]
|
#[fold]
|
||||||
|
#[ghost]
|
||||||
pub delta: Delta,
|
pub delta: Delta,
|
||||||
|
|
||||||
/// Whether the font style should be inverted.
|
/// Whether the font style should be inverted.
|
||||||
#[internal]
|
#[internal]
|
||||||
#[fold]
|
#[fold]
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
|
#[ghost]
|
||||||
pub emph: Toggle,
|
pub emph: Toggle,
|
||||||
|
|
||||||
/// Decorative lines.
|
/// Decorative lines.
|
||||||
#[internal]
|
#[internal]
|
||||||
#[fold]
|
#[fold]
|
||||||
|
#[ghost]
|
||||||
pub deco: Decoration,
|
pub deco: Decoration,
|
||||||
|
|
||||||
/// A case transformation that should be applied to the text.
|
/// A case transformation that should be applied to the text.
|
||||||
#[internal]
|
#[internal]
|
||||||
|
#[ghost]
|
||||||
pub case: Option<Case>,
|
pub case: Option<Case>,
|
||||||
|
|
||||||
/// Whether small capital glyphs should be used. ("smcp")
|
/// Whether small capital glyphs should be used. ("smcp")
|
||||||
#[internal]
|
#[internal]
|
||||||
#[default(false)]
|
#[default(false)]
|
||||||
|
#[ghost]
|
||||||
pub smallcaps: bool,
|
pub smallcaps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use super::*;
|
|||||||
/// Expand the `#[elem]` macro.
|
/// Expand the `#[elem]` macro.
|
||||||
pub fn elem(stream: TokenStream, body: syn::ItemStruct) -> Result<TokenStream> {
|
pub fn elem(stream: TokenStream, body: syn::ItemStruct) -> Result<TokenStream> {
|
||||||
let element = parse(stream, &body)?;
|
let element = parse(stream, &body)?;
|
||||||
Ok(create(&element))
|
create(&element)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Details about an element.
|
/// Details about an element.
|
||||||
@ -51,10 +51,20 @@ impl Elem {
|
|||||||
///
|
///
|
||||||
/// This includes:
|
/// This includes:
|
||||||
/// - Fields that are not external and therefore present in the struct.
|
/// - Fields that are not external and therefore present in the struct.
|
||||||
|
/// - Fields that are ghost fields.
|
||||||
fn real_fields(&self) -> impl Iterator<Item = &Field> + Clone {
|
fn real_fields(&self) -> impl Iterator<Item = &Field> + Clone {
|
||||||
self.fields.iter().filter(|field| !field.external)
|
self.fields.iter().filter(|field| !field.external)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fields that are present in the struct.
|
||||||
|
///
|
||||||
|
/// This includes:
|
||||||
|
/// - Fields that are not external and therefore present in the struct.
|
||||||
|
/// - Fields that are not ghost fields.
|
||||||
|
fn present_fields(&self) -> impl Iterator<Item = &Field> + Clone {
|
||||||
|
self.real_fields().filter(|field| !field.ghost)
|
||||||
|
}
|
||||||
|
|
||||||
/// Fields that are inherent to the element.
|
/// Fields that are inherent to the element.
|
||||||
fn inherent_fields(&self) -> impl Iterator<Item = &Field> + Clone {
|
fn inherent_fields(&self) -> impl Iterator<Item = &Field> + Clone {
|
||||||
self.real_fields().filter(|field| field.inherent())
|
self.real_fields().filter(|field| field.inherent())
|
||||||
@ -91,7 +101,7 @@ impl Elem {
|
|||||||
/// This includes:
|
/// This includes:
|
||||||
/// - Fields that are not synthesized (guarantees equality before and after synthesis).
|
/// - Fields that are not synthesized (guarantees equality before and after synthesis).
|
||||||
fn eq_fields(&self) -> impl Iterator<Item = &Field> + Clone {
|
fn eq_fields(&self) -> impl Iterator<Item = &Field> + Clone {
|
||||||
self.real_fields().filter(|field| !field.synthesized)
|
self.present_fields().filter(|field| !field.synthesized)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fields that are relevant for `Construct` impl.
|
/// Fields that are relevant for `Construct` impl.
|
||||||
@ -125,6 +135,7 @@ struct Field {
|
|||||||
external: bool,
|
external: bool,
|
||||||
synthesized: bool,
|
synthesized: bool,
|
||||||
borrowed: bool,
|
borrowed: bool,
|
||||||
|
ghost: bool,
|
||||||
forced_variant: Option<usize>,
|
forced_variant: Option<usize>,
|
||||||
parse: Option<BlockWithReturn>,
|
parse: Option<BlockWithReturn>,
|
||||||
default: Option<syn::Expr>,
|
default: Option<syn::Expr>,
|
||||||
@ -133,7 +144,7 @@ struct Field {
|
|||||||
impl Field {
|
impl Field {
|
||||||
/// Whether the field is present on every instance of the element.
|
/// Whether the field is present on every instance of the element.
|
||||||
fn inherent(&self) -> bool {
|
fn inherent(&self) -> bool {
|
||||||
self.required || self.variadic
|
(self.required || self.variadic) && !self.ghost
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the field can be used with set rules.
|
/// Whether the field can be used with set rules.
|
||||||
@ -226,6 +237,7 @@ fn parse_field(field: &syn::Field) -> Result<Field> {
|
|||||||
synthesized: has_attr(&mut attrs, "synthesized"),
|
synthesized: has_attr(&mut attrs, "synthesized"),
|
||||||
fold: has_attr(&mut attrs, "fold"),
|
fold: has_attr(&mut attrs, "fold"),
|
||||||
resolve: has_attr(&mut attrs, "resolve"),
|
resolve: has_attr(&mut attrs, "resolve"),
|
||||||
|
ghost: has_attr(&mut attrs, "ghost"),
|
||||||
parse: parse_attr(&mut attrs, "parse")?.flatten(),
|
parse: parse_attr(&mut attrs, "parse")?.flatten(),
|
||||||
default: parse_attr::<syn::Expr>(&mut attrs, "default")?.flatten(),
|
default: parse_attr::<syn::Expr>(&mut attrs, "default")?.flatten(),
|
||||||
vis: field.vis.clone(),
|
vis: field.vis.clone(),
|
||||||
@ -264,20 +276,31 @@ fn parse_field(field: &syn::Field) -> Result<Field> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Produce the element's definition.
|
/// Produce the element's definition.
|
||||||
fn create(element: &Elem) -> TokenStream {
|
fn create(element: &Elem) -> Result<TokenStream> {
|
||||||
let Elem { vis, ident, docs, .. } = element;
|
let Elem { vis, ident, docs, .. } = element;
|
||||||
|
|
||||||
|
if element.fields.iter().any(|field| field.ghost)
|
||||||
|
&& element
|
||||||
|
.capabilities
|
||||||
|
.iter()
|
||||||
|
.all(|capability| capability != "Construct")
|
||||||
|
{
|
||||||
|
bail!(ident, "cannot have ghost fields and have `Construct` auto generated");
|
||||||
|
}
|
||||||
|
|
||||||
let all = element.real_fields();
|
let all = element.real_fields();
|
||||||
|
let present = element.present_fields();
|
||||||
let settable = all.clone().filter(|field| !field.synthesized && field.settable());
|
let settable = all.clone().filter(|field| !field.synthesized && field.settable());
|
||||||
|
|
||||||
let fields = all.clone().map(create_field);
|
let fields = present.clone().map(create_field);
|
||||||
let fields_enum = create_fields_enum(element);
|
let fields_enum = create_fields_enum(element);
|
||||||
|
|
||||||
let new = create_new_func(element);
|
let new = create_new_func(element);
|
||||||
let field_methods = all.clone().map(|field| create_field_method(element, field));
|
let field_methods = all.clone().map(|field| create_field_method(element, field));
|
||||||
let field_in_methods =
|
let field_in_methods =
|
||||||
settable.clone().map(|field| create_field_in_method(element, field));
|
settable.clone().map(|field| create_field_in_method(element, field));
|
||||||
let with_field_methods = all.clone().map(create_with_field_method);
|
let with_field_methods = present.clone().map(create_with_field_method);
|
||||||
let push_field_methods = all.clone().map(create_push_field_method);
|
let push_field_methods = present.clone().map(create_push_field_method);
|
||||||
let field_style_methods =
|
let field_style_methods =
|
||||||
settable.clone().map(|field| create_set_field_method(element, field));
|
settable.clone().map(|field| create_set_field_method(element, field));
|
||||||
|
|
||||||
@ -300,7 +323,7 @@ fn create(element: &Elem) -> TokenStream {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
Ok(quote! {
|
||||||
#[doc = #docs]
|
#[doc = #docs]
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||||
@ -335,7 +358,7 @@ fn create(element: &Elem) -> TokenStream {
|
|||||||
::typst::eval::Value::Content(::typst::model::Content::new(self))
|
::typst::eval::Value::Content(::typst::model::Content::new(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a field declaration.
|
/// Create a field declaration.
|
||||||
@ -459,12 +482,14 @@ fn create_new_func(element: &Elem) -> TokenStream {
|
|||||||
let defaults = element
|
let defaults = element
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|field| !field.external && !field.inherent() && !field.synthesized)
|
.filter(|field| {
|
||||||
|
!field.external && !field.inherent() && !field.synthesized && !field.ghost
|
||||||
|
})
|
||||||
.map(|Field { ident, .. }| quote! { #ident: None });
|
.map(|Field { ident, .. }| quote! { #ident: None });
|
||||||
let default_synthesized = element
|
let default_synthesized = element
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|field| !field.external && field.synthesized)
|
.filter(|field| !field.external && field.synthesized && !field.ghost)
|
||||||
.map(|Field { ident, default, .. }| {
|
.map(|Field { ident, default, .. }| {
|
||||||
if let Some(expr) = default {
|
if let Some(expr) = default {
|
||||||
quote! { #ident: #expr }
|
quote! { #ident: #expr }
|
||||||
@ -591,7 +616,14 @@ fn create_field_in_method(element: &Elem, field: &Field) -> TokenStream {
|
|||||||
|
|
||||||
/// Create an accessor methods for a field.
|
/// Create an accessor methods for a field.
|
||||||
fn create_field_method(element: &Elem, field: &Field) -> TokenStream {
|
fn create_field_method(element: &Elem, field: &Field) -> TokenStream {
|
||||||
let Field { vis, docs, ident, output, .. } = field;
|
let Field { vis, docs, ident, output, ghost, .. } = field;
|
||||||
|
|
||||||
|
let inherent = if *ghost {
|
||||||
|
quote! { None }
|
||||||
|
} else {
|
||||||
|
quote! { self.#ident.as_ref() }
|
||||||
|
};
|
||||||
|
|
||||||
if (field.inherent() && !field.synthesized)
|
if (field.inherent() && !field.synthesized)
|
||||||
|| (field.synthesized && field.default.is_some())
|
|| (field.synthesized && field.default.is_some())
|
||||||
{
|
{
|
||||||
@ -610,8 +642,7 @@ fn create_field_method(element: &Elem, field: &Field) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if field.borrowed {
|
} else if field.borrowed {
|
||||||
let access =
|
let access = create_style_chain_access(element, field, inherent);
|
||||||
create_style_chain_access(element, field, quote! { self.#ident.as_ref() });
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #docs]
|
#[doc = #docs]
|
||||||
@ -620,8 +651,7 @@ fn create_field_method(element: &Elem, field: &Field) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let access =
|
let access = create_style_chain_access(element, field, inherent);
|
||||||
create_style_chain_access(element, field, quote! { self.#ident.as_ref() });
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #docs]
|
#[doc = #docs]
|
||||||
@ -697,16 +727,22 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
|
|||||||
let name = &field.enum_ident;
|
let name = &field.enum_ident;
|
||||||
let field_ident = &field.ident;
|
let field_ident = &field.ident;
|
||||||
|
|
||||||
quote! {
|
if field.ghost {
|
||||||
<#elem as #model::ElementFields>::Fields::#name => Some(
|
quote! {
|
||||||
::typst::eval::IntoValue::into_value(self.#field_ident.clone())
|
<#elem as #model::ElementFields>::Fields::#name => None,
|
||||||
),
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
<#elem as #model::ElementFields>::Fields::#name => Some(
|
||||||
|
::typst::eval::IntoValue::into_value(self.#field_ident.clone())
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fields that can be set using the `set_field` method.
|
// Fields that can be set using the `set_field` method.
|
||||||
let field_set_matches = element.visible_fields()
|
let field_set_matches = element.visible_fields()
|
||||||
.filter(|field| field.settable() && !field.synthesized).map(|field| {
|
.filter(|field| field.settable() && !field.synthesized && !field.ghost).map(|field| {
|
||||||
let elem = &element.ident;
|
let elem = &element.ident;
|
||||||
let name = &field.enum_ident;
|
let name = &field.enum_ident;
|
||||||
let field_ident = &field.ident;
|
let field_ident = &field.ident;
|
||||||
@ -722,7 +758,7 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
|
|||||||
// Fields that are inherent.
|
// Fields that are inherent.
|
||||||
let field_inherent_matches = element
|
let field_inherent_matches = element
|
||||||
.visible_fields()
|
.visible_fields()
|
||||||
.filter(|field| field.inherent())
|
.filter(|field| field.inherent() && !field.ghost)
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let elem = &element.ident;
|
let elem = &element.ident;
|
||||||
let name = &field.enum_ident;
|
let name = &field.enum_ident;
|
||||||
@ -739,7 +775,7 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
|
|||||||
// Fields that cannot be set or are internal create an error.
|
// Fields that cannot be set or are internal create an error.
|
||||||
let field_not_set_matches = element
|
let field_not_set_matches = element
|
||||||
.real_fields()
|
.real_fields()
|
||||||
.filter(|field| field.internal || field.synthesized)
|
.filter(|field| field.internal || field.synthesized || field.ghost)
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let elem = &element.ident;
|
let elem = &element.ident;
|
||||||
let ident = &field.enum_ident;
|
let ident = &field.enum_ident;
|
||||||
@ -798,7 +834,7 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
|
|||||||
// Creation of the fields dictionary for optional fields.
|
// Creation of the fields dictionary for optional fields.
|
||||||
let field_opt_dict = element
|
let field_opt_dict = element
|
||||||
.visible_fields()
|
.visible_fields()
|
||||||
.filter(|field| !field.inherent())
|
.filter(|field| !field.inherent() && !field.ghost)
|
||||||
.clone()
|
.clone()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let name = &field.name;
|
let name = &field.name;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user