Document text category
This commit is contained in:
parent
15cd273c82
commit
ee732468c7
@ -67,6 +67,10 @@ impl TableNode {
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"columns" => Some(TrackSizing::encode_slice(&self.tracks.x)),
|
||||
"rows" => Some(TrackSizing::encode_slice(&self.tracks.y)),
|
||||
"column-gutter" => Some(TrackSizing::encode_slice(&self.gutter.x)),
|
||||
"row-gutter" => Some(TrackSizing::encode_slice(&self.gutter.y)),
|
||||
"cells" => Some(Value::Array(
|
||||
self.cells.iter().cloned().map(Value::Content).collect(),
|
||||
)),
|
||||
|
@ -65,6 +65,14 @@ impl ColumnsNode {
|
||||
}
|
||||
.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"count" => Some(Value::Int(self.count.get() as i64)),
|
||||
"body" => Some(Value::Content(self.body.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for ColumnsNode {
|
||||
@ -186,6 +194,13 @@ impl ColbreakNode {
|
||||
let weak = args.named("weak")?.unwrap_or(false);
|
||||
Ok(Self { weak }.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"weak" => Some(Value::Bool(self.weak)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Behave for ColbreakNode {
|
||||
|
@ -50,6 +50,13 @@ impl BoxNode {
|
||||
let body = args.eat::<Content>()?.unwrap_or_default();
|
||||
Ok(Self { sizing: Axes::new(width, height), body }.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.body.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for BoxNode {
|
||||
@ -163,6 +170,13 @@ impl BlockNode {
|
||||
args.named("below")?.map(VNode::block_around).or(spacing),
|
||||
);
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.0.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for BlockNode {
|
||||
|
@ -120,6 +120,19 @@ impl GridNode {
|
||||
}
|
||||
.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"columns" => Some(TrackSizing::encode_slice(&self.tracks.x)),
|
||||
"rows" => Some(TrackSizing::encode_slice(&self.tracks.y)),
|
||||
"column-gutter" => Some(TrackSizing::encode_slice(&self.gutter.x)),
|
||||
"row-gutter" => Some(TrackSizing::encode_slice(&self.gutter.y)),
|
||||
"cells" => Some(Value::Array(
|
||||
self.cells.iter().cloned().map(Value::Content).collect(),
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for GridNode {
|
||||
@ -157,6 +170,20 @@ pub enum TrackSizing {
|
||||
Fractional(Fr),
|
||||
}
|
||||
|
||||
impl TrackSizing {
|
||||
pub fn encode(self) -> Value {
|
||||
match self {
|
||||
Self::Auto => Value::Auto,
|
||||
Self::Relative(rel) => Spacing::Relative(rel).encode(),
|
||||
Self::Fractional(fr) => Spacing::Fractional(fr).encode(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_slice(vec: &[TrackSizing]) -> Value {
|
||||
Value::Array(vec.iter().copied().map(Self::encode).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Spacing> for TrackSizing {
|
||||
fn from(spacing: Spacing) -> Self {
|
||||
match spacing {
|
||||
|
@ -30,6 +30,13 @@ impl HideNode {
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
Ok(Self(args.expect("body")?).pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.0.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for HideNode {
|
||||
|
@ -67,6 +67,13 @@ impl PadNode {
|
||||
let padding = Sides::new(left, top, right, bottom);
|
||||
Ok(Self { padding, body }.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.body.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for PadNode {
|
||||
|
@ -64,6 +64,13 @@ impl PageNode {
|
||||
styles.set(Self::HEIGHT, Smart::Custom(paper.height().into()));
|
||||
}
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.0.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PageNode {
|
||||
@ -190,6 +197,13 @@ impl PagebreakNode {
|
||||
let weak = args.named("weak")?.unwrap_or(false);
|
||||
Ok(Self { weak }.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"weak" => Some(Value::Bool(self.weak)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A header, footer, foreground or background definition.
|
||||
|
@ -467,7 +467,7 @@ fn collect<'a>(
|
||||
Segment::Text(c.len_utf8())
|
||||
} else if let Some(node) = child.to::<SmartQuoteNode>() {
|
||||
let prev = full.len();
|
||||
if styles.get(TextNode::SMART_QUOTES) {
|
||||
if styles.get(SmartQuoteNode::ENABLED) {
|
||||
let lang = styles.get(TextNode::LANG);
|
||||
let region = styles.get(TextNode::REGION);
|
||||
let quotes = Quotes::from_lang(lang, region);
|
||||
|
@ -33,6 +33,13 @@ impl PlaceNode {
|
||||
let out_of_flow = aligns.y.is_some();
|
||||
Ok(Self(body.moved(Axes::new(dx, dy)).aligned(aligns), out_of_flow).pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.0.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for PlaceNode {
|
||||
|
@ -19,6 +19,13 @@ impl RepeatNode {
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
Ok(Self(args.expect("body")?).pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.0.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for RepeatNode {
|
||||
|
@ -54,10 +54,18 @@ pub struct HNode {
|
||||
#[node]
|
||||
impl HNode {
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
let amount = args.expect("spacing")?;
|
||||
let amount = args.expect("amount")?;
|
||||
let weak = args.named("weak")?.unwrap_or(false);
|
||||
Ok(Self { amount, weak }.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"amount" => Some(self.amount.encode()),
|
||||
"weak" => Some(Value::Bool(self.weak)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HNode {
|
||||
@ -159,6 +167,14 @@ impl VNode {
|
||||
};
|
||||
Ok(node.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"amount" => Some(self.amount.encode()),
|
||||
"weak" => Some(Value::Bool(self.weakness != 0)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VNode {
|
||||
@ -220,6 +236,22 @@ impl Spacing {
|
||||
pub fn is_fractional(self) -> bool {
|
||||
matches!(self, Self::Fractional(_))
|
||||
}
|
||||
|
||||
/// Encode into a value.
|
||||
pub fn encode(self) -> Value {
|
||||
match self {
|
||||
Self::Relative(rel) => {
|
||||
if rel.rel.is_zero() {
|
||||
Value::Length(rel.abs)
|
||||
} else if rel.abs.is_zero() {
|
||||
Value::Ratio(rel.rel)
|
||||
} else {
|
||||
Value::Relative(rel)
|
||||
}
|
||||
}
|
||||
Self::Fractional(fr) => Value::Fraction(fr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Abs> for Spacing {
|
||||
|
@ -40,6 +40,26 @@ impl StackNode {
|
||||
}
|
||||
.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"dir" => Some(Value::dynamic(self.dir)),
|
||||
"spacing" => Some(match self.spacing {
|
||||
Some(spacing) => spacing.encode(),
|
||||
None => Value::None,
|
||||
}),
|
||||
"items" => Some(Value::Array(
|
||||
self.children
|
||||
.iter()
|
||||
.map(|child| match child {
|
||||
StackChild::Spacing(spacing) => spacing.encode(),
|
||||
StackChild::Block(content) => Value::Content(content.clone()),
|
||||
})
|
||||
.collect(),
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for StackNode {
|
||||
|
@ -31,6 +31,7 @@ use crate::prelude::*;
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// Hello, world!#move(dy: -2pt)[!]#move(dy: 2pt)[!]
|
||||
/// ```
|
||||
///
|
||||
/// - dx: Rel<Length> (named)
|
||||
/// The horizontal displacement of the content.
|
||||
@ -61,6 +62,13 @@ impl MoveNode {
|
||||
}
|
||||
.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.body.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for MoveNode {
|
||||
@ -130,6 +138,13 @@ impl RotateNode {
|
||||
}
|
||||
.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.body.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for RotateNode {
|
||||
@ -209,6 +224,13 @@ impl ScaleNode {
|
||||
}
|
||||
.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => Some(Value::Content(self.body.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout for ScaleNode {
|
||||
|
@ -22,6 +22,15 @@ impl VecNode {
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
Ok(Self(args.all()?).pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"elements" => {
|
||||
Some(Value::Array(self.0.iter().cloned().map(Value::Content).collect()))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Texify for VecNode {
|
||||
@ -89,6 +98,15 @@ impl CasesNode {
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
Ok(Self(args.all()?).pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"branches" => {
|
||||
Some(Value::Array(self.0.iter().cloned().map(Value::Content).collect()))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Texify for CasesNode {
|
||||
|
@ -5,7 +5,9 @@ use crate::text::TextNode;
|
||||
/// Link to a URL or another location in the document.
|
||||
///
|
||||
/// The link function makes its positional `body` argument clickable and links
|
||||
/// it to the destination specified by the `dest` argument.
|
||||
/// it to the destination specified by the `dest` argument. By default, links
|
||||
/// are not styled any different from normal text. However, you can easily apply
|
||||
/// a style of your choice with a show rule.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
@ -85,7 +87,7 @@ impl LinkNode {
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"url" => Some(match &self.dest {
|
||||
"dest" => Some(match &self.dest {
|
||||
Destination::Url(url) => Value::Str(url.clone().into()),
|
||||
Destination::Internal(loc) => Value::Dict(loc.encode()),
|
||||
}),
|
||||
|
@ -27,12 +27,41 @@ impl Behave for SpaceNode {
|
||||
}
|
||||
|
||||
/// # Line Break
|
||||
/// A line break.
|
||||
/// Inserts a line break.
|
||||
///
|
||||
/// Advances the paragraph to the next line. A single trailing linebreak at the
|
||||
/// end of a paragraph is ignored, but more than one creates additional empty
|
||||
/// lines.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// *Date:* 26.12.2022 \
|
||||
/// *Topic:* Infrastructure Test \
|
||||
/// *Severity:* High \
|
||||
/// ```
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax: To insert a linebreak, simply write
|
||||
/// a backslash followed by whitespace. This always creates an unjustified
|
||||
/// break.
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - justify: bool (named)
|
||||
/// Whether to justify the line before the break.
|
||||
///
|
||||
/// This is useful if you found a better line break opportunity in your
|
||||
/// justified text than Typst did.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// #set par(justify: true)
|
||||
/// #let jb = linebreak(justify: true)
|
||||
///
|
||||
/// I have manually tuned the #jb
|
||||
/// linebreaks in this paragraph #jb
|
||||
/// for an _interesting_ result. #jb
|
||||
/// ```
|
||||
///
|
||||
/// ## Category
|
||||
/// text
|
||||
#[func]
|
||||
@ -48,6 +77,13 @@ impl LinebreakNode {
|
||||
let justify = args.named("justify")?.unwrap_or(false);
|
||||
Ok(Self { justify }.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"justify" => Some(Value::Bool(self.justify)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Behave for LinebreakNode {
|
||||
@ -59,6 +95,23 @@ impl Behave for LinebreakNode {
|
||||
/// # Strong Emphasis
|
||||
/// Strongly emphasizes content by increasing the font weight.
|
||||
///
|
||||
/// Increases the current font weight by a given `delta`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// This is *strong.* \
|
||||
/// This is #strong[too.] \
|
||||
///
|
||||
/// #show strong: set text(red)
|
||||
/// And this is *evermore.*
|
||||
/// ```
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax: To strongly emphasize content,
|
||||
/// simply enclose it in stars/asterisks (`*`). Note that this only works at
|
||||
/// word boundaries. To strongly emphasize part of a word, you have to use the
|
||||
/// function.
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - body: Content (positional, required)
|
||||
/// The content to strongly emphasize.
|
||||
@ -73,6 +126,12 @@ pub struct StrongNode(pub Content);
|
||||
#[node]
|
||||
impl StrongNode {
|
||||
/// The delta to apply on the font weight.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set strong(delta: 0)
|
||||
/// No *effect!*
|
||||
/// ```
|
||||
pub const DELTA: i64 = 300;
|
||||
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
@ -111,7 +170,29 @@ impl Fold for Delta {
|
||||
}
|
||||
|
||||
/// # Emphasis
|
||||
/// Emphasizes content by flipping the italicness.
|
||||
/// Emphasizes content by setting it in italics.
|
||||
///
|
||||
/// - If the current [text](@text) style is `{"normal"}`,
|
||||
/// this turns it into `{"italic"}`.
|
||||
/// - If it is already `{"italic"}` or `{"oblique"}`,
|
||||
/// it turns it back to `{"normal"}`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// This is _emphasized._ \
|
||||
/// This is #emph[too.]
|
||||
///
|
||||
/// #show emph: it => {
|
||||
/// text(blue, it.body)
|
||||
/// }
|
||||
///
|
||||
/// This is _emphasized_ differently.
|
||||
/// ```
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax: To emphasize content, simply
|
||||
/// enclose it in underscores (`_`). Note that this only works at word
|
||||
/// boundaries. To emphasize part of a word, you have to use the function.
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - body: Content (positional, required)
|
||||
@ -159,6 +240,13 @@ impl Fold for Toggle {
|
||||
/// # Lowercase
|
||||
/// Convert text or content to lowercase.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// #lower("ABC") \
|
||||
/// #lower[*My Text*] \
|
||||
/// #lower[already low]
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - text: ToCase (positional, required)
|
||||
/// The text to convert to lowercase.
|
||||
@ -173,6 +261,13 @@ pub fn lower(args: &mut Args) -> SourceResult<Value> {
|
||||
/// # Uppercase
|
||||
/// Convert text or content to uppercase.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// #upper("abc") \
|
||||
/// #upper[*my text*] \
|
||||
/// #upper[ALREADY HIGH]
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - text: ToCase (positional, required)
|
||||
/// The text to convert to uppercase.
|
||||
@ -225,6 +320,29 @@ impl Case {
|
||||
/// # Small Capitals
|
||||
/// Display text in small capitals.
|
||||
///
|
||||
/// _Note:_ This enables the OpenType `smcp` feature for the font. Not all fonts
|
||||
/// support this feature (including Typst's current default font,
|
||||
/// unfortunately). Sometimes smallcaps are part of a dedicated font and
|
||||
/// sometimes they are not available at all. In the future, this function will
|
||||
/// support selecting a dedicated smallcaps font as well as synthesizing
|
||||
/// smallcaps from normal letters, but this is not yet implemented.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// #set par(justify: true)
|
||||
/// #set text(family: "Noto Serif")
|
||||
/// #set heading(numbering: "I.")
|
||||
///
|
||||
/// #show heading: it => {
|
||||
/// set block(below: 10pt)
|
||||
/// set text(weight: "regular")
|
||||
/// align(center, smallcaps(it))
|
||||
/// }
|
||||
///
|
||||
/// = Introduction
|
||||
/// #lorem(40)
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - text: Content (positional, required)
|
||||
/// The text to display to small capitals.
|
||||
|
@ -26,14 +26,45 @@ use crate::layout::ParNode;
|
||||
use crate::prelude::*;
|
||||
|
||||
/// # Text
|
||||
/// Stylable text.
|
||||
/// Customize the look and layout of text in a variety of ways.
|
||||
///
|
||||
/// This function is used often, both with set rules and directly. While the set
|
||||
/// rule is often the simpler choice, calling the text function directly can be
|
||||
/// useful when passing text as an argument to another function.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// #set text(18pt)
|
||||
/// With a set rule.
|
||||
///
|
||||
/// #emph(text(blue)[
|
||||
/// With a function call.
|
||||
/// ])
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - family: EcoString (positional, variadic, settable)
|
||||
/// A prioritized sequence of font families.
|
||||
/// - 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.
|
||||
/// When processing text, Typst tries all specified font families in order
|
||||
/// until it finds a font that has the necessary glyphs. In the example below,
|
||||
/// the font `Inria Serif` is preferred, but since it does not contain Arabic
|
||||
/// glyphs, the arabic text uses `Noto Sans Arabic` instead.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// #set text(
|
||||
/// "Inria Serif",
|
||||
/// "Noto Sans Arabic",
|
||||
/// )
|
||||
///
|
||||
/// This is Latin. \
|
||||
/// هذا عربي.
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
/// - body: Content (positional, required) Content in which all text is styled
|
||||
/// according to the other arguments.
|
||||
///
|
||||
/// ## Category
|
||||
/// text
|
||||
@ -54,75 +85,383 @@ impl TextNode {
|
||||
/// A prioritized sequence of font families.
|
||||
#[property(skip, referenced)]
|
||||
pub const FAMILY: FallbackList = FallbackList(vec![FontFamily::new("IBM Plex Sans")]);
|
||||
/// Whether to allow font fallback when the primary font list contains no
|
||||
/// match.
|
||||
|
||||
/// Whether to allow last resort font fallback when the primary font list
|
||||
/// contains no match. This lets Typst search through all available fonts
|
||||
/// for the most similar one that has the necessary glyphs.
|
||||
///
|
||||
/// _Note:_ Currently, there are no warnings when fallback is disabled and
|
||||
/// no glyphs are found. Instead, your text shows up in the form of "tofus":
|
||||
/// Small boxes that indicate the lack of an appropriate glyph. In the
|
||||
/// future, you will be able to instruct Typst to issue warnings so you know
|
||||
/// something is up.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(family: "Inria Serif")
|
||||
/// هذا عربي
|
||||
///
|
||||
/// #set text(fallback: false)
|
||||
/// هذا عربي
|
||||
/// ```
|
||||
pub const FALLBACK: bool = true;
|
||||
|
||||
/// How the font is styled.
|
||||
/// The desired font style.
|
||||
///
|
||||
/// When an italic style is requested and only an oblique one is available,
|
||||
/// it is used. Similarly, the other way around, an italic style can stand
|
||||
/// in for an oblique one. When neither an italic nor an oblique style is
|
||||
/// available, Typst selects the normal style. Since most fonts are only
|
||||
/// available either in an italic or oblique style, the difference between
|
||||
/// italic and oblique style is rarely observable.
|
||||
///
|
||||
/// If you want to emphasize your text, you should do so using the
|
||||
/// [emph](@emph) function instead. This makes it easy to adapt the style
|
||||
/// later if you change your mind about how to signify the emphasis.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #text("IBM Plex Sans", style: "italic")[Italic]
|
||||
/// #text("DejaVu Sans", style: "oblique")[Oblique]
|
||||
/// ```
|
||||
pub const STYLE: FontStyle = FontStyle::Normal;
|
||||
/// The boldness / thickness of the font's glyphs.
|
||||
|
||||
/// The desired thickness of the font's glyphs. Accepts an integer between
|
||||
/// `{100}` and `{900}` or one of the predefined weight names. When the
|
||||
/// desired weight is not available, Typst selects the font from the family
|
||||
/// that is closest in weight.
|
||||
///
|
||||
/// If you want to strongly emphasize your text, you should do so using the
|
||||
/// [strong](@strong) function instead. This makes it easy to adapt the
|
||||
/// style later if you change your mind about how to signify the strong
|
||||
/// emphasis.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #text(weight: "light")[Light] \
|
||||
/// #text(weight: "regular")[Regular] \
|
||||
/// #text(weight: "medium")[Medium] \
|
||||
/// #text(weight: "bold")[Bold]
|
||||
/// ```
|
||||
pub const WEIGHT: FontWeight = FontWeight::REGULAR;
|
||||
/// The width of the glyphs.
|
||||
|
||||
/// The desired width of the glyphs. Accepts a ratio between `{50%}` and
|
||||
/// `{200%}`. When the desired weight is not available, Typst selects the
|
||||
/// font from the family that is closest in stretch.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #text(stretch: 75%)[Condensed] \
|
||||
/// #text(stretch: 100%)[Normal]
|
||||
/// ```
|
||||
pub const STRETCH: FontStretch = FontStretch::NORMAL;
|
||||
|
||||
/// The size of the glyphs.
|
||||
/// The size of the glyphs. This value forms the basis of the `em` unit:
|
||||
/// `{1em}` is equivalent to the font size.
|
||||
///
|
||||
/// You can also give the font size itself in `em` units. Then, it is
|
||||
/// relative to the previous font size.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(size: 20pt)
|
||||
/// very #text(1.5em)[big] text
|
||||
/// ```
|
||||
#[property(shorthand, fold)]
|
||||
pub const SIZE: TextSize = Abs::pt(11.0);
|
||||
|
||||
/// The glyph fill color.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(fill: red)
|
||||
/// This text is red.
|
||||
/// ```
|
||||
#[property(shorthand)]
|
||||
pub const FILL: Paint = Color::BLACK.into();
|
||||
|
||||
/// The amount of space that should be added between characters.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(tracking: 1.5pt)
|
||||
/// Distant text.
|
||||
/// ```
|
||||
#[property(resolve)]
|
||||
pub const TRACKING: Length = Length::zero();
|
||||
/// The width of spaces relative to the font's space width.
|
||||
|
||||
/// The amount of space between words.
|
||||
///
|
||||
/// Can be given as an absolute length, but also relative to the width of
|
||||
/// the space character in the font.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(spacing: 200%)
|
||||
/// Text with distant words.
|
||||
/// ```
|
||||
#[property(resolve)]
|
||||
pub const SPACING: Rel<Length> = Rel::one();
|
||||
/// The offset of the baseline.
|
||||
|
||||
/// An amount to shift the text baseline by.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// A #text(baseline: 3pt)[lowered]
|
||||
/// word.
|
||||
/// ```
|
||||
#[property(resolve)]
|
||||
pub const BASELINE: Length = Length::zero();
|
||||
/// Whether certain glyphs can hang over into the margin.
|
||||
|
||||
/// Whether certain glyphs can hang over into the margin in justified text.
|
||||
/// This can make justification visually more pleasing.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set par(justify: true)
|
||||
/// In this particular text, the
|
||||
/// justification produces a hyphen
|
||||
/// in the first line. Letting this
|
||||
/// hyphen hang slightly into the
|
||||
/// margin makes for a clear
|
||||
/// paragraph edge.
|
||||
///
|
||||
/// #set text(overhang: false)
|
||||
/// In this particular text, the
|
||||
/// justification produces a hyphen
|
||||
/// in the first line. This time the
|
||||
/// hyphen does not hang into the
|
||||
/// margin, making the paragraph's
|
||||
/// edge less clear.
|
||||
/// ```
|
||||
pub const OVERHANG: bool = true;
|
||||
/// The top end of the text bounding box.
|
||||
|
||||
/// The top end of the conceptual frame around the text used for layout and
|
||||
/// positioning. This affects the size of containers that hold text.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(size: 20pt)
|
||||
/// #set text(top-edge: "ascender")
|
||||
/// #rect(fill: aqua)[Typst]
|
||||
///
|
||||
/// #set text(top-edge: "cap-height")
|
||||
/// #rect(fill: aqua)[Typst]
|
||||
/// ```
|
||||
pub const TOP_EDGE: TextEdge = TextEdge::Metric(VerticalFontMetric::CapHeight);
|
||||
/// The bottom end of the text bounding box.
|
||||
|
||||
/// The bottom end of the conceptual frame around the text used for layout
|
||||
/// and positioning. This affects the size of containers that hold text.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(size: 20pt)
|
||||
/// #set text(bottom-edge: "baseline")
|
||||
/// #rect(fill: aqua)[Typst]
|
||||
///
|
||||
/// #set text(bottom-edge: "descender")
|
||||
/// #rect(fill: aqua)[Typst]
|
||||
/// ```
|
||||
pub const BOTTOM_EDGE: TextEdge = TextEdge::Metric(VerticalFontMetric::Baseline);
|
||||
|
||||
/// An ISO 639-1/2/3 language code.
|
||||
/// An [ISO 639-1/2/3 language code.](https://en.wikipedia.org/wiki/ISO_639)
|
||||
///
|
||||
/// Setting the correct language affects various parts of Typst:
|
||||
///
|
||||
/// - The text processing pipeline can make more informed choices.
|
||||
/// - Hyphenation will use the correct patterns for the language.
|
||||
/// - [Smart quotes](@smartquote) turns into the correct quotes for the
|
||||
/// language.
|
||||
/// - And all other things which are language-aware.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(lang: "de")
|
||||
/// #outline()
|
||||
///
|
||||
/// = Einleitung
|
||||
/// In diesem Dokument, ...
|
||||
/// ```
|
||||
pub const LANG: Lang = Lang::ENGLISH;
|
||||
/// An ISO 3166-1 alpha-2 region code.
|
||||
|
||||
/// 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.
|
||||
pub const REGION: Option<Region> = None;
|
||||
/// The direction for text and inline objects. When `auto`, the direction is
|
||||
/// automatically inferred from the language.
|
||||
|
||||
/// The dominant direction for text and inline objects. Possible values are:
|
||||
///
|
||||
/// - `{auto}`: Automatically infer the direction from the `lang` property.
|
||||
/// - `{ltr}`: Layout text from left to right.
|
||||
/// - `{rtl}`: Layout text from right to left.
|
||||
///
|
||||
/// When writing in right-to-left scripts like Arabic or Hebrew, you should
|
||||
/// set the language or direction. While individual runs of text are
|
||||
/// automatically layouted in the correct direction, setting the dominant
|
||||
/// direction gives the bidirectional reordering algorithm the necessary
|
||||
/// information to correctly place punctuation and inline objects.
|
||||
/// Furthermore, setting the direction affects the alignment values `start`
|
||||
/// and `end`, which are equivalent to `left` and `right` in `ltr` text and
|
||||
/// the other way around in `rtl` text.
|
||||
///
|
||||
/// If you set this to `rtl` and experience bugs or in some way bad looking
|
||||
/// output, please do get in touch with us through the [contact
|
||||
/// form](/contact) or our [Discord server](/docs/community/#discord)!
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(dir: rtl)
|
||||
/// هذا عربي.
|
||||
/// ```
|
||||
#[property(resolve)]
|
||||
pub const DIR: HorizontalDir = HorizontalDir(Smart::Auto);
|
||||
/// Whether to hyphenate text to improve line breaking. When `auto`, words
|
||||
/// will will be hyphenated if and only if justification is enabled.
|
||||
|
||||
/// Whether to hyphenate text to improve line breaking. When `{auto}`, text
|
||||
/// will be hyphenated if and only if justification is enabled.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set par(justify: true)
|
||||
/// This text illustrates how
|
||||
/// enabling hyphenation can
|
||||
/// improve justification.
|
||||
///
|
||||
/// #set text(hyphenate: false)
|
||||
/// This text illustrates how
|
||||
/// enabling hyphenation can
|
||||
/// improve justification.
|
||||
/// ```
|
||||
#[property(resolve)]
|
||||
pub const HYPHENATE: Hyphenate = Hyphenate(Smart::Auto);
|
||||
/// Whether to apply smart quotes.
|
||||
pub const SMART_QUOTES: bool = true;
|
||||
|
||||
/// Whether to apply kerning ("kern").
|
||||
/// Whether to apply kerning.
|
||||
///
|
||||
/// When enabled, specific letter pairings move closer together or further
|
||||
/// apart for a more visually pleasing result. The example below
|
||||
/// demonstrates how decreasing the gap between the "T" and "o" results in a
|
||||
/// more natural look. Setting this to `{false}` disables kerning by turning
|
||||
/// off the OpenType `kern` font feature.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(size: 25pt)
|
||||
/// Totally
|
||||
///
|
||||
/// #set text(kerning: false)
|
||||
/// Totally
|
||||
/// ```
|
||||
pub const KERNING: bool = true;
|
||||
/// Whether to apply stylistic alternates. ("salt")
|
||||
|
||||
/// Whether to apply stylistic alternates.
|
||||
///
|
||||
/// Sometimes fonts contain alternative glyphs for the same codepoint.
|
||||
/// Setting this to `{true}` switches to these by enabling the OpenType
|
||||
/// `salt` font feature.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(size: 20pt)
|
||||
/// 0, a, g, ß
|
||||
///
|
||||
/// #set text(alternates: true)
|
||||
/// 0, a, g, ß
|
||||
/// ```
|
||||
pub const ALTERNATES: bool = false;
|
||||
/// Which stylistic set to apply. ("ss01" - "ss20")
|
||||
|
||||
/// Which stylistic set to apply. Font designers can categorize alternative
|
||||
/// glyphs forms into stylistic sets. As this value is highly font-specific,
|
||||
/// you need to consult your font to know which sets are available. When set
|
||||
/// to an integer between `{1}` and `{20}`, enables the corresponding
|
||||
/// OpenType font feature from `ss01`, ..., `ss20`.
|
||||
pub const STYLISTIC_SET: Option<StylisticSet> = None;
|
||||
/// Whether standard ligatures are active. ("liga", "clig")
|
||||
|
||||
/// Whether standard ligatures are active.
|
||||
///
|
||||
/// Certain letter combinations like "fi" are often displayed as a single
|
||||
/// merged glyph called a _ligature._ Setting this to `{false}` disables
|
||||
/// these ligatures by turning off the OpenType `liga` and `clig` font
|
||||
/// features.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(size: 20pt)
|
||||
/// A fine ligature.
|
||||
///
|
||||
/// #set text(ligatures: false)
|
||||
/// A fine ligature.
|
||||
/// ```
|
||||
pub const LIGATURES: bool = true;
|
||||
/// Whether ligatures that should be used sparingly are active. ("dlig")
|
||||
|
||||
/// Whether ligatures that should be used sparingly are active. Setting this
|
||||
/// to `{true}` enables the OpenType `dlig` font feature.
|
||||
pub const DISCRETIONARY_LIGATURES: bool = false;
|
||||
/// Whether historical ligatures are active. ("hlig")
|
||||
|
||||
/// Whether historical ligatures are active. Setting this to `{true}`
|
||||
/// enables the OpenType `hlig` font feature.
|
||||
pub const HISTORICAL_LIGATURES: bool = false;
|
||||
/// Which kind of numbers / figures to select.
|
||||
|
||||
/// Which kind of numbers / figures to select. When set to `{auto}`, the
|
||||
/// default numbers for the font are used.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(20pt, "Noto Sans")
|
||||
/// #set text(number-type: "lining")
|
||||
/// Number 9.
|
||||
///
|
||||
/// #set text(number-type: "old-style")
|
||||
/// Number 9.
|
||||
/// ```
|
||||
pub const NUMBER_TYPE: Smart<NumberType> = Smart::Auto;
|
||||
/// The width of numbers / figures.
|
||||
|
||||
/// The width of numbers / figures. When set to `{auto}`, the default
|
||||
/// numbers for the font are used.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set text(20pt, "Noto Sans")
|
||||
/// #set text(number-width: "proportional")
|
||||
/// A 12 B 34. \
|
||||
/// A 56 B 78.
|
||||
///
|
||||
/// #set text(number-width: "tabular")
|
||||
/// A 12 B 34. \
|
||||
/// A 56 B 78.
|
||||
/// ```
|
||||
pub const NUMBER_WIDTH: Smart<NumberWidth> = Smart::Auto;
|
||||
/// Whether to have a slash through the zero glyph. ("zero")
|
||||
|
||||
/// Whether to have a slash through the zero glyph. Setting this to `{true}`
|
||||
/// enables the OpenType `zero` font feature.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// 0, #text(slashed-zero: true)[0]
|
||||
/// ```
|
||||
pub const SLASHED_ZERO: bool = false;
|
||||
/// Whether to convert fractions. ("frac")
|
||||
|
||||
/// Whether to turns numbers into fractions. Setting this to `{true}`
|
||||
/// enables the OpenType `frac` font feature.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// 1/2 \
|
||||
/// #text(fractions: true)[1/2]
|
||||
/// ```
|
||||
pub const FRACTIONS: bool = false;
|
||||
|
||||
/// Raw OpenType features to apply.
|
||||
///
|
||||
/// - If given an array of strings, sets the features identified by the
|
||||
/// strings to `{1}`.
|
||||
/// - If given a dictionary mapping to numbers, sets the features
|
||||
/// identified by the keys to the values.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// // Enable the `frac` feature manually.
|
||||
/// #set text(features: ("frac",))
|
||||
/// 1/2
|
||||
/// ```
|
||||
#[property(fold)]
|
||||
pub const FEATURES: FontFeatures = FontFeatures(vec![]);
|
||||
|
||||
@ -272,7 +611,7 @@ impl TextEdge {
|
||||
castable! {
|
||||
TextEdge,
|
||||
v: Length => Self::Length(v),
|
||||
/// The distance from the baseline to the ascender.
|
||||
/// The font's ascender, which typically exceeds the height of all glyphs.
|
||||
"ascender" => Self::Metric(VerticalFontMetric::Ascender),
|
||||
/// The approximate height of uppercase letters.
|
||||
"cap-height" => Self::Metric(VerticalFontMetric::CapHeight),
|
||||
@ -280,7 +619,7 @@ castable! {
|
||||
"x-height" => Self::Metric(VerticalFontMetric::XHeight),
|
||||
/// The baseline on which the letters rest.
|
||||
"baseline" => Self::Metric(VerticalFontMetric::Baseline),
|
||||
/// The distance from the baseline to the descender.
|
||||
/// The font's ascender, which typically exceeds the depth of all glyphs.
|
||||
"descender" => Self::Metric(VerticalFontMetric::Descender),
|
||||
}
|
||||
|
||||
@ -364,9 +703,11 @@ pub enum NumberType {
|
||||
|
||||
castable! {
|
||||
NumberType,
|
||||
/// Numbers that fit well with capital text.
|
||||
/// Numbers that fit well with capital text (the OpenType `lnum`
|
||||
/// font feature).
|
||||
"lining" => Self::Lining,
|
||||
/// Numbers that fit well into a flow of upper- and lowercase text.
|
||||
/// Numbers that fit well into a flow of upper- and lowercase text (the
|
||||
/// OpenType `onum` font feature).
|
||||
"old-style" => Self::OldStyle,
|
||||
}
|
||||
|
||||
@ -381,9 +722,9 @@ pub enum NumberWidth {
|
||||
|
||||
castable! {
|
||||
NumberWidth,
|
||||
/// Number widths are glyph specific.
|
||||
/// Numbers with glyph-specific widths (the OpenType `pnum` font feature).
|
||||
"proportional" => Self::Proportional,
|
||||
/// All numbers are of equal width / monospaced.
|
||||
/// Numbers of equal width (the OpenType `tnum` font feature).
|
||||
"tabular" => Self::Tabular,
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,29 @@ use typst::syntax::is_newline;
|
||||
use crate::prelude::*;
|
||||
|
||||
/// # Smart Quote
|
||||
/// A smart quote.
|
||||
/// A language-aware quote that reacts to its context.
|
||||
///
|
||||
/// Automatically turns into an appropriate opening or closing quote based on
|
||||
/// the active [text](@text) language.
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax: The normal quote characters
|
||||
/// (`'` and `"`). Typst automatically makes your quotes smart.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// "This is in quotes."
|
||||
///
|
||||
/// #set text(lang: "de")
|
||||
/// "Das ist in Anführungszeichen."
|
||||
///
|
||||
/// #set text(lang: "fr")
|
||||
/// "C'est entre guillemets."
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - double: bool (named)
|
||||
/// Whether to produce a smart double quote.
|
||||
/// Whether this should be a double quote.
|
||||
///
|
||||
/// ## Category
|
||||
/// text
|
||||
@ -20,10 +38,30 @@ pub struct SmartQuoteNode {
|
||||
|
||||
#[node]
|
||||
impl SmartQuoteNode {
|
||||
/// Whether smart quotes are enabled.
|
||||
///
|
||||
/// To disable smartness for a single quote, you can also escape it with a
|
||||
/// backslash.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #set smartquote(enabled: false)
|
||||
///
|
||||
/// These are "dumb" quotes.
|
||||
/// ```
|
||||
pub const ENABLED: bool = true;
|
||||
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
let double = args.named("double")?.unwrap_or(true);
|
||||
Ok(Self { double }.pack())
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"double" => Some(Value::Bool(self.double)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State machine for smart quote subtitution.
|
||||
|
@ -2,24 +2,93 @@ use once_cell::sync::Lazy;
|
||||
use syntect::highlighting as synt;
|
||||
use typst::syntax::{self, LinkedNode};
|
||||
|
||||
use super::{FontFamily, Hyphenate, LinebreakNode, TextNode};
|
||||
use super::{FontFamily, Hyphenate, LinebreakNode, SmartQuoteNode, TextNode};
|
||||
use crate::layout::BlockNode;
|
||||
use crate::prelude::*;
|
||||
|
||||
/// # Raw Text
|
||||
/// # Raw Text / Code
|
||||
/// Raw text with optional syntax highlighting.
|
||||
///
|
||||
/// Displays the text verbatim and in a monospace font. This is typically used
|
||||
/// to embed computer code into your document.
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax. You can enclose text in 1 or 3+
|
||||
/// backticks (`` ` ``) to make it raw. Two backticks produce empty raw text.
|
||||
/// When you use three or more backticks, you can additionally specify a
|
||||
/// language tag for syntax highlighting directly after the opening backticks.
|
||||
/// Within raw blocks, everything is rendered as is, in particular, there are no
|
||||
/// escape sequences.
|
||||
///
|
||||
/// ## Example
|
||||
/// ````
|
||||
/// Adding `rbx` to `rcx` gives
|
||||
/// the desired result.
|
||||
///
|
||||
/// ```rust
|
||||
/// fn main() {
|
||||
/// println!("Hello World!");
|
||||
/// }
|
||||
/// ```
|
||||
/// ````
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - text: EcoString (positional, required)
|
||||
/// The raw text.
|
||||
///
|
||||
/// You can also use raw blocks creatively to create custom syntaxes for
|
||||
/// your automations.
|
||||
///
|
||||
/// ### Example
|
||||
/// ````
|
||||
/// // Parse numbers in raw blocks with the `mydsl` tag and
|
||||
/// // sum them up.
|
||||
/// #show raw.where(lang: "mydsl"): it => {
|
||||
/// let sum = 0
|
||||
/// for part in it.text.split("+") {
|
||||
/// sum += int(part.trim())
|
||||
/// }
|
||||
/// sum
|
||||
/// }
|
||||
///
|
||||
/// ```mydsl
|
||||
/// 1 + 2 + 3 + 4 + 5
|
||||
/// ```
|
||||
/// ````
|
||||
///
|
||||
/// - block: bool (named)
|
||||
/// Whether the raw text is displayed as a separate block.
|
||||
///
|
||||
/// ### Example
|
||||
/// ````
|
||||
/// // Display inline code in a small box
|
||||
/// // that retains the correct baseline.
|
||||
/// #show raw.where(block: false): rect.with(
|
||||
/// fill: luma(240),
|
||||
/// inset: (x: 3pt),
|
||||
/// outset: (y: 3pt),
|
||||
/// radius: 2pt,
|
||||
/// )
|
||||
///
|
||||
/// // Display block code in a larger box
|
||||
/// // with more padding.
|
||||
/// #show raw.where(block: true): rect.with(
|
||||
/// fill: luma(240),
|
||||
/// inset: 10pt,
|
||||
/// radius: 4pt,
|
||||
/// )
|
||||
///
|
||||
/// With `rg`, you can search through your files quickly.
|
||||
///
|
||||
/// ```bash
|
||||
/// rg "Hello World"
|
||||
/// ```
|
||||
/// ````
|
||||
///
|
||||
/// ## Category
|
||||
/// text
|
||||
#[func]
|
||||
#[capable(Show)]
|
||||
#[capable(Show, Prepare)]
|
||||
#[derive(Debug, Hash)]
|
||||
pub struct RawNode {
|
||||
/// The raw text.
|
||||
@ -31,6 +100,17 @@ pub struct RawNode {
|
||||
#[node]
|
||||
impl RawNode {
|
||||
/// The language to syntax-highlight in.
|
||||
///
|
||||
/// Apart from typical language tags known from Markdown, this supports the
|
||||
/// `{"typ"}` and `{"typc"}` tags for Typst markup and Typst code,
|
||||
/// respectively.
|
||||
///
|
||||
/// # Example
|
||||
/// ````
|
||||
/// ```typ
|
||||
/// This is *Typst!*
|
||||
/// ```
|
||||
/// ````
|
||||
#[property(referenced)]
|
||||
pub const LANG: Option<EcoString> = None;
|
||||
|
||||
@ -121,7 +201,7 @@ impl Show for RawNode {
|
||||
let mut map = StyleMap::new();
|
||||
map.set(TextNode::OVERHANG, false);
|
||||
map.set(TextNode::HYPHENATE, Hyphenate(Smart::Custom(false)));
|
||||
map.set(TextNode::SMART_QUOTES, false);
|
||||
map.set(SmartQuoteNode::ENABLED, false);
|
||||
map.set_family(FontFamily::new("IBM Plex Mono"), styles);
|
||||
|
||||
Ok(realized.styled_with_map(map))
|
||||
|
@ -4,9 +4,49 @@ use crate::text::TextNode;
|
||||
/// # Symbol
|
||||
/// A symbol identified by symmie notation.
|
||||
///
|
||||
/// Symmie is Typst's notation for Unicode symbols. It is based on the idea of
|
||||
/// _modifiers._ Many symbols in Unicode are very similar. In symmie, such
|
||||
/// groups of symbols share a common name. To distinguish between the symbols
|
||||
/// within a group, we use one or multiple modifiers that are separated from the
|
||||
/// name by colons.
|
||||
///
|
||||
/// There is currently no easily viewable list of all names, but in the
|
||||
/// meantime you can rely on the autocompletion in Typst's web editor.
|
||||
///
|
||||
/// ## Syntax
|
||||
/// This function also has dedicated syntax: In markup, you can enclose symmie
|
||||
/// notation within colons to produce a symbol. And in math, you can just write
|
||||
/// the notation directly. There, all letter sequence of length at least two are
|
||||
/// automatically parsed as symbols (unless a variable of that name is defined).
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// // In text, with colons.
|
||||
/// :arrow:l: \
|
||||
/// :arrow:r: \
|
||||
/// :arrow:t: \
|
||||
/// :turtle: \
|
||||
/// :face:halo: \
|
||||
/// :woman:old:
|
||||
///
|
||||
/// // In math, directly.
|
||||
/// $f : NN -> RR$ \
|
||||
/// $A sub:eq B without C$ \
|
||||
/// $a times:div b eq:not c$
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - notation: EcoString (positional, required)
|
||||
/// The symbols symmie notation.
|
||||
/// The symbol's symmie notation.
|
||||
///
|
||||
/// Consists of a name, followed by a number colon-separated modifiers
|
||||
/// in no particular order.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// #symbol("NN") \
|
||||
/// #symbol("face:grin")
|
||||
/// ```
|
||||
///
|
||||
/// ## Category
|
||||
/// text
|
||||
|
@ -94,6 +94,16 @@ impl<const S: ShapeKind> ShapeNode<S> {
|
||||
styles.set_opt(Self::RADIUS, args.named("radius")?);
|
||||
}
|
||||
}
|
||||
|
||||
fn field(&self, name: &str) -> Option<Value> {
|
||||
match name {
|
||||
"body" => match &self.0 {
|
||||
Some(body) => Some(Value::Content(body.clone())),
|
||||
None => Some(Value::None),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const S: ShapeKind> Layout for ShapeNode<S> {
|
||||
|
@ -109,15 +109,13 @@ pub fn section(docs: &mut String, title: &str, level: usize) -> Option<String> {
|
||||
|
||||
/// Parse the example section.
|
||||
pub fn example(docs: &mut String, level: usize) -> Option<String> {
|
||||
Some(
|
||||
section(docs, "Example", level)?
|
||||
.lines()
|
||||
.skip_while(|line| !line.contains("```"))
|
||||
.skip(1)
|
||||
.take_while(|line| !line.contains("```"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
)
|
||||
let section = section(docs, "Example", level)?;
|
||||
let mut s = unscanny::Scanner::new(§ion);
|
||||
let count = s.eat_while('`').len();
|
||||
let term = "`".repeat(count);
|
||||
let text = s.eat_until(term.as_str()).trim();
|
||||
s.expect(term.as_str());
|
||||
Some(text.into())
|
||||
}
|
||||
|
||||
/// Parse the parameter section.
|
||||
|
@ -254,7 +254,7 @@ pub struct LineMetrics {
|
||||
/// Identifies a vertical metric of a font.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum VerticalFontMetric {
|
||||
/// The distance from the baseline to the typographic ascender.
|
||||
/// The typographic ascender.
|
||||
///
|
||||
/// Corresponds to the typographic ascender from the `OS/2` table if present
|
||||
/// and falls back to the ascender from the `hhea` table otherwise.
|
||||
@ -265,7 +265,7 @@ pub enum VerticalFontMetric {
|
||||
XHeight,
|
||||
/// The baseline on which the letters rest.
|
||||
Baseline,
|
||||
/// The distance from the baseline to the typographic descender.
|
||||
/// The typographic descender.
|
||||
///
|
||||
/// Corresponds to the typographic descender from the `OS/2` table if
|
||||
/// present and falls back to the descender from the `hhea` table otherwise.
|
||||
|
@ -32,11 +32,11 @@ impl Debug for FontVariant {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum FontStyle {
|
||||
/// The default style.
|
||||
/// The default, typically upright style.
|
||||
Normal,
|
||||
/// A cursive style.
|
||||
/// A cursive style with custom letterform.
|
||||
Italic,
|
||||
/// A slanted style.
|
||||
/// Just a slanted version of the normal style.
|
||||
Oblique,
|
||||
}
|
||||
|
||||
|
@ -293,11 +293,11 @@ castable! {
|
||||
|
||||
castable! {
|
||||
FontStyle,
|
||||
/// The default style.
|
||||
/// The default, typically upright style.
|
||||
"normal" => Self::Normal,
|
||||
/// A cursive style.
|
||||
/// A cursive style with custom letterform.
|
||||
"italic" => Self::Italic,
|
||||
/// A slanted style.
|
||||
/// Just a slanted version of the normal style.
|
||||
"oblique" => Self::Oblique,
|
||||
}
|
||||
|
||||
|
@ -32,5 +32,5 @@ A #h(1fr) B
|
||||
|
||||
---
|
||||
// Missing spacing.
|
||||
// Error: 11-13 missing argument: spacing
|
||||
// Error: 11-13 missing argument: amount
|
||||
Totally #h() ignored
|
||||
|
@ -43,11 +43,11 @@ The 5\'11\" 'quick\' brown fox jumps over the \"lazy" dog\'s ear.
|
||||
// Test turning smart quotes off.
|
||||
He's told some books contain questionable "example text".
|
||||
|
||||
#set text(smart-quotes: false)
|
||||
#set smartquote(enabled: false)
|
||||
He's told some books contain questionable "example text".
|
||||
|
||||
---
|
||||
// Test changing properties within text.
|
||||
"She suddenly started speaking french: #text(lang: "fr")['Je suis une banane.']" Roman told me.
|
||||
|
||||
Some people's thought on this would be #text(smart-quotes: false)["strange."]
|
||||
Some people's thought on this would be [#set smartquote(enabled: false); "strange."]
|
||||
|
Loading…
x
Reference in New Issue
Block a user