Skip to content

Commit aee2ec3

Browse files
committed
Deserialize names with label position
1 parent 9f67a83 commit aee2ec3

File tree

1 file changed

+229
-42
lines changed

1 file changed

+229
-42
lines changed

src/lib.rs

+229-42
Original file line numberDiff line numberDiff line change
@@ -1513,7 +1513,7 @@ impl LayoutRenderingElement {
15131513
_ => RendersYearSuffix::No,
15141514
},
15151515
Self::Names(n) => n
1516-
.substitute
1516+
.substitute()
15171517
.as_ref()
15181518
.and_then(|n| {
15191519
n.children
@@ -1959,31 +1959,119 @@ pub struct Names {
19591959
/// The variable whose value is used.
19601960
#[serde(rename = "@variable")]
19611961
pub variable: Vec<NameVariable>,
1962-
/// How the names are formatted.
1962+
/// Child elements.
1963+
#[serde(rename = "$value", default)]
1964+
pub children: Vec<NamesChild>,
1965+
/// Delimiter between names.
1966+
#[serde(rename = "@delimiter")]
19631967
#[serde(skip_serializing_if = "Option::is_none")]
1964-
pub name: Option<Name>,
1965-
/// Configuration of the et al. abbreviation.
1968+
delimiter: Option<String>,
1969+
1970+
/// Delimiter between second-to-last and last name.
1971+
#[serde(rename = "@and")]
19661972
#[serde(skip_serializing_if = "Option::is_none")]
1967-
pub et_al: Option<EtAl>,
1968-
/// Substitutions in case the variable is empty.
1973+
pub and: Option<NameAnd>,
1974+
/// Delimiter before et al.
1975+
#[serde(rename = "@delimiter-precedes-et-al")]
19691976
#[serde(skip_serializing_if = "Option::is_none")]
1970-
pub substitute: Option<Substitute>,
1971-
/// Label for the names.
1977+
pub delimiter_precedes_et_al: Option<DelimiterBehavior>,
1978+
/// Whether to use the delimiter before the last name.
1979+
#[serde(rename = "@delimiter-precedes-last")]
19721980
#[serde(skip_serializing_if = "Option::is_none")]
1973-
pub label: Option<VariablelessLabel>,
1974-
/// Delimiter between names.
1975-
#[serde(rename = "@delimiter")]
1981+
pub delimiter_precedes_last: Option<DelimiterBehavior>,
1982+
/// Minimum number of names to use et al.
1983+
#[serde(rename = "@et-al-min", deserialize_with = "deserialize_u32_option", default)]
19761984
#[serde(skip_serializing_if = "Option::is_none")]
1977-
delimiter: Option<String>,
1978-
/// Options for the names within.
1979-
#[serde(flatten)]
1980-
pub options: InheritableNameOptions,
1981-
/// Override formatting style.
1982-
#[serde(flatten)]
1983-
pub formatting: Formatting,
1984-
/// Add prefix and suffix.
1985-
#[serde(flatten)]
1986-
pub affixes: Affixes,
1985+
pub et_al_min: Option<u32>,
1986+
/// Maximum number of names to use before et al.
1987+
#[serde(
1988+
rename = "@et-al-use-first",
1989+
deserialize_with = "deserialize_u32_option",
1990+
default
1991+
)]
1992+
#[serde(skip_serializing_if = "Option::is_none")]
1993+
pub et_al_use_first: Option<u32>,
1994+
/// Minimum number of names to use et al. for repeated citations.
1995+
#[serde(
1996+
rename = "@et-al-subsequent-min",
1997+
deserialize_with = "deserialize_u32_option",
1998+
default
1999+
)]
2000+
#[serde(skip_serializing_if = "Option::is_none")]
2001+
pub et_al_subsequent_min: Option<u32>,
2002+
/// Maximum number of names to use before et al. for repeated citations.
2003+
#[serde(
2004+
rename = "@et-al-subsequent-use-first",
2005+
deserialize_with = "deserialize_u32_option",
2006+
default
2007+
)]
2008+
#[serde(skip_serializing_if = "Option::is_none")]
2009+
pub et_al_subsequent_use_first: Option<u32>,
2010+
/// Whether to use the last name in the author list when there are at least
2011+
/// `et_al_min` names.
2012+
#[serde(
2013+
rename = "@et-al-use-last",
2014+
deserialize_with = "deserialize_bool_option",
2015+
default
2016+
)]
2017+
#[serde(skip_serializing_if = "Option::is_none")]
2018+
pub et_al_use_last: Option<bool>,
2019+
/// Which name parts to display for personal names.
2020+
#[serde(rename = "@name-form")]
2021+
#[serde(skip_serializing_if = "Option::is_none")]
2022+
pub name_form: Option<NameForm>,
2023+
/// Whether to initialize the first name if `initialize-with` is Some.
2024+
#[serde(
2025+
rename = "@initialize",
2026+
deserialize_with = "deserialize_bool_option",
2027+
default
2028+
)]
2029+
#[serde(skip_serializing_if = "Option::is_none")]
2030+
pub initialize: Option<bool>,
2031+
/// String to initialize the first name with.
2032+
#[serde(rename = "@initialize-with")]
2033+
#[serde(skip_serializing_if = "Option::is_none")]
2034+
pub initialize_with: Option<String>,
2035+
/// Whether to turn the name around.
2036+
#[serde(rename = "@name-as-sort-order")]
2037+
#[serde(skip_serializing_if = "Option::is_none")]
2038+
pub name_as_sort_order: Option<NameAsSortOrder>,
2039+
/// Delimiter between given name and first name. Only used if
2040+
/// `name-as-sort-order` is Some.
2041+
#[serde(rename = "@sort-separator")]
2042+
#[serde(skip_serializing_if = "Option::is_none")]
2043+
pub sort_separator: Option<String>,
2044+
2045+
/// Set the font style.
2046+
#[serde(rename = "@font-style")]
2047+
#[serde(skip_serializing_if = "Option::is_none")]
2048+
pub font_style: Option<FontStyle>,
2049+
/// Choose normal or small caps.
2050+
#[serde(rename = "@font-variant")]
2051+
#[serde(skip_serializing_if = "Option::is_none")]
2052+
pub font_variant: Option<FontVariant>,
2053+
/// Set the font weight.
2054+
#[serde(rename = "@font-weight")]
2055+
#[serde(skip_serializing_if = "Option::is_none")]
2056+
pub font_weight: Option<FontWeight>,
2057+
/// Choose underlining.
2058+
#[serde(rename = "@text-decoration")]
2059+
#[serde(skip_serializing_if = "Option::is_none")]
2060+
pub text_decoration: Option<TextDecoration>,
2061+
/// Choose vertical alignment.
2062+
#[serde(rename = "@vertical-align")]
2063+
#[serde(skip_serializing_if = "Option::is_none")]
2064+
pub vertical_align: Option<VerticalAlign>,
2065+
2066+
/// The prefix.
2067+
#[serde(rename = "@prefix")]
2068+
#[serde(skip_serializing_if = "Option::is_none")]
2069+
pub prefix: Option<String>,
2070+
/// The suffix.
2071+
#[serde(rename = "@suffix")]
2072+
#[serde(skip_serializing_if = "Option::is_none")]
2073+
pub suffix: Option<String>,
2074+
19872075
/// Set layout level.
19882076
#[serde(rename = "@display")]
19892077
#[serde(skip_serializing_if = "Option::is_none")]
@@ -1999,40 +2087,139 @@ impl Names {
19992087
.unwrap_or_default()
20002088
}
20012089

2090+
/// Return the name element.
2091+
pub fn name(&self) -> Option<&Name> {
2092+
self.children.iter().find_map(|c| match c {
2093+
NamesChild::Name(n) => Some(n),
2094+
_ => None,
2095+
})
2096+
}
2097+
2098+
/// Return the et-al element.
2099+
pub fn et_al(&self) -> Option<&EtAl> {
2100+
self.children.iter().find_map(|c| match c {
2101+
NamesChild::EtAl(e) => Some(e),
2102+
_ => None,
2103+
})
2104+
}
2105+
2106+
/// Return the label element.
2107+
pub fn label(&self) -> Option<(&VariablelessLabel, NameLabelPosition)> {
2108+
let mut pos = NameLabelPosition::BeforeName;
2109+
self.children.iter().find_map(|c| match c {
2110+
NamesChild::Label(l) => Some((l, pos)),
2111+
NamesChild::Name(_) => {
2112+
pos = NameLabelPosition::AfterName;
2113+
None
2114+
}
2115+
_ => None,
2116+
})
2117+
}
2118+
2119+
/// Return the substitute element.
2120+
pub fn substitute(&self) -> Option<&Substitute> {
2121+
self.children.iter().find_map(|c| match c {
2122+
NamesChild::Substitute(s) => Some(s),
2123+
_ => None,
2124+
})
2125+
}
2126+
2127+
/// Return the inheritable name options.
2128+
pub fn options(&self) -> InheritableNameOptions {
2129+
InheritableNameOptions {
2130+
and: self.and,
2131+
delimiter_precedes_et_al: self.delimiter_precedes_et_al,
2132+
delimiter_precedes_last: self.delimiter_precedes_last,
2133+
et_al_min: self.et_al_min,
2134+
et_al_use_first: self.et_al_use_first,
2135+
et_al_subsequent_min: self.et_al_subsequent_min,
2136+
et_al_subsequent_use_first: self.et_al_subsequent_use_first,
2137+
et_al_use_last: self.et_al_use_last,
2138+
name_form: self.name_form,
2139+
initialize: self.initialize,
2140+
initialize_with: self.initialize_with.clone(),
2141+
name_as_sort_order: self.name_as_sort_order,
2142+
sort_separator: self.sort_separator.clone(),
2143+
name_delimiter: None,
2144+
names_delimiter: self.delimiter.clone(),
2145+
}
2146+
}
2147+
20022148
/// Convert a [`Names`] within a substitute to a name using the parent element.
20032149
pub fn from_names_substitue(&self, child: &Self) -> Names {
2004-
if child.name.is_some() || child.et_al.is_some() || child.substitute.is_some() {
2150+
if child.name().is_some()
2151+
|| child.et_al().is_some()
2152+
|| child.substitute().is_some()
2153+
{
20052154
return child.clone();
20062155
}
20072156

2157+
let formatting = child.to_formatting().apply(self.to_formatting());
2158+
let options = self.options().apply(&child.options());
2159+
20082160
Names {
20092161
variable: child.variable.clone(),
2010-
name: self.name.clone(),
2011-
et_al: self.et_al,
2012-
substitute: None,
2013-
label: child.label.clone().or_else(|| self.label.clone()),
2162+
children: self
2163+
.children
2164+
.iter()
2165+
.filter(|c| !matches!(c, NamesChild::Substitute(_)))
2166+
.cloned()
2167+
.collect(),
20142168
delimiter: child.delimiter.clone().or_else(|| self.delimiter.clone()),
2015-
options: self.options.apply(&child.options),
2016-
formatting: child.formatting.apply(self.formatting),
2017-
affixes: Affixes {
2018-
prefix: child
2019-
.affixes
2020-
.prefix
2021-
.clone()
2022-
.or_else(|| self.affixes.prefix.clone()),
2023-
suffix: child
2024-
.affixes
2025-
.suffix
2026-
.clone()
2027-
.or_else(|| self.affixes.suffix.clone()),
2028-
},
2169+
2170+
and: options.and,
2171+
delimiter_precedes_et_al: options.delimiter_precedes_et_al,
2172+
delimiter_precedes_last: options.delimiter_precedes_last,
2173+
et_al_min: options.et_al_min,
2174+
et_al_use_first: options.et_al_use_first,
2175+
et_al_subsequent_min: options.et_al_subsequent_min,
2176+
et_al_subsequent_use_first: options.et_al_subsequent_use_first,
2177+
et_al_use_last: options.et_al_use_last,
2178+
name_form: options.name_form,
2179+
initialize: options.initialize,
2180+
initialize_with: options.initialize_with,
2181+
name_as_sort_order: options.name_as_sort_order,
2182+
sort_separator: options.sort_separator,
2183+
2184+
font_style: formatting.font_style,
2185+
font_variant: formatting.font_variant,
2186+
font_weight: formatting.font_weight,
2187+
text_decoration: formatting.text_decoration,
2188+
vertical_align: formatting.vertical_align,
2189+
2190+
prefix: child.prefix.clone().or_else(|| self.prefix.clone()),
2191+
suffix: child.suffix.clone().or_else(|| self.suffix.clone()),
20292192
display: child.display.or(self.display),
20302193
}
20312194
}
20322195
}
20332196

2034-
to_formatting!(Names);
2035-
to_affixes!(Names);
2197+
to_formatting!(Names, self);
2198+
to_affixes!(Names, self);
2199+
2200+
/// Where the `cs:label` element within a `cs:names` element appeared relative
2201+
/// to `cs:name`.
2202+
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
2203+
pub enum NameLabelPosition {
2204+
/// The label appeared after the name element.
2205+
AfterName,
2206+
/// The label appeared before the name element.
2207+
BeforeName,
2208+
}
2209+
2210+
/// Possible children for a `cs:names` element.
2211+
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]
2212+
#[serde(rename_all = "kebab-case")]
2213+
pub enum NamesChild {
2214+
/// A `cs:name` element.
2215+
Name(Name),
2216+
/// A `cs:et-al` element.
2217+
EtAl(EtAl),
2218+
/// A `cs:label` element.
2219+
Label(VariablelessLabel),
2220+
/// A `cs:substitute` element.
2221+
Substitute(Substitute),
2222+
}
20362223

20372224
/// Configuration of how to print names.
20382225
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)]

0 commit comments

Comments
 (0)