mirror of
https://github.com/typst/typst
synced 2025-08-19 17:38:32 +08:00
implement title element
This commit is contained in:
parent
bb38a01d06
commit
7e418ad148
@ -20,6 +20,7 @@ mod reference;
|
|||||||
mod strong;
|
mod strong;
|
||||||
mod table;
|
mod table;
|
||||||
mod terms;
|
mod terms;
|
||||||
|
mod title;
|
||||||
|
|
||||||
pub use self::bibliography::*;
|
pub use self::bibliography::*;
|
||||||
pub use self::cite::*;
|
pub use self::cite::*;
|
||||||
@ -39,6 +40,7 @@ pub use self::reference::*;
|
|||||||
pub use self::strong::*;
|
pub use self::strong::*;
|
||||||
pub use self::table::*;
|
pub use self::table::*;
|
||||||
pub use self::terms::*;
|
pub use self::terms::*;
|
||||||
|
pub use self::title::*;
|
||||||
|
|
||||||
use crate::foundations::{category, Category, Scope};
|
use crate::foundations::{category, Category, Scope};
|
||||||
|
|
||||||
@ -57,6 +59,7 @@ pub fn define(global: &mut Scope) {
|
|||||||
global.define_elem::<RefElem>();
|
global.define_elem::<RefElem>();
|
||||||
global.define_elem::<LinkElem>();
|
global.define_elem::<LinkElem>();
|
||||||
global.define_elem::<OutlineElem>();
|
global.define_elem::<OutlineElem>();
|
||||||
|
global.define_elem::<TitleElem>();
|
||||||
global.define_elem::<HeadingElem>();
|
global.define_elem::<HeadingElem>();
|
||||||
global.define_elem::<FigureElem>();
|
global.define_elem::<FigureElem>();
|
||||||
global.define_elem::<FootnoteElem>();
|
global.define_elem::<FootnoteElem>();
|
||||||
|
68
crates/typst-library/src/model/title.rs
Normal file
68
crates/typst-library/src/model/title.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use crate::{
|
||||||
|
diag::SourceResult,
|
||||||
|
engine::Engine,
|
||||||
|
foundations::{
|
||||||
|
elem, Content, NativeElement, Packed, Show, ShowSet, Smart, StyleChain, Styles,
|
||||||
|
TargetElem,
|
||||||
|
},
|
||||||
|
html::{tag, HtmlElem},
|
||||||
|
introspection::Locatable,
|
||||||
|
layout::{AlignElem, Alignment, BlockBody, BlockElem, Em},
|
||||||
|
text::{FontWeight, TextElem, TextSize},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A document title.
|
||||||
|
///
|
||||||
|
/// Should be used to display the main title of the whole document, and should
|
||||||
|
/// occur only once per document.
|
||||||
|
///
|
||||||
|
/// Shows as `h1` in HTML. In contrast, a heading of level 1
|
||||||
|
/// (created with `= Some Heading`) will show as `h2`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```example
|
||||||
|
/// #title[Interstellar Mail Delivery]
|
||||||
|
///
|
||||||
|
/// = Introduction
|
||||||
|
/// In recent years, ...
|
||||||
|
/// ```
|
||||||
|
#[elem(Locatable, Show, ShowSet)]
|
||||||
|
pub struct TitleElem {
|
||||||
|
/// The content of the title.
|
||||||
|
#[required]
|
||||||
|
pub body: Content,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Show for Packed<TitleElem> {
|
||||||
|
#[typst_macros::time(name = "title", span = self.span())]
|
||||||
|
fn show(&self, _engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||||
|
let html = TargetElem::target_in(styles).is_html();
|
||||||
|
|
||||||
|
let span = self.span();
|
||||||
|
let realized = self.body().clone();
|
||||||
|
|
||||||
|
Ok(if html {
|
||||||
|
HtmlElem::new(tag::h1).with_body(Some(realized)).pack().spanned(span)
|
||||||
|
} else {
|
||||||
|
let realized = BlockBody::Content(realized);
|
||||||
|
BlockElem::new().with_body(Some(realized)).pack().spanned(span)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShowSet for Packed<TitleElem> {
|
||||||
|
fn show_set(&self, _styles: StyleChain) -> Styles {
|
||||||
|
const SIZE: Em = Em::new(1.6);
|
||||||
|
const ABOVE: Em = Em::new(1.125);
|
||||||
|
const BELOW: Em = Em::new(0.75);
|
||||||
|
|
||||||
|
let mut out = Styles::new();
|
||||||
|
out.set(TextElem::set_size(TextSize(SIZE.into())));
|
||||||
|
out.set(TextElem::set_weight(FontWeight::BOLD));
|
||||||
|
out.set(BlockElem::set_above(Smart::Custom(ABOVE.into())));
|
||||||
|
out.set(BlockElem::set_below(Smart::Custom(BELOW.into())));
|
||||||
|
out.set(BlockElem::set_sticky(true));
|
||||||
|
out.set(AlignElem::set_alignment(Alignment::CENTER));
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
15
tests/ref/html/title-and-heading.html
Normal file
15
tests/ref/html/title-and-heading.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
A cool title
|
||||||
|
</h1>
|
||||||
|
<h2>
|
||||||
|
Some level one heading
|
||||||
|
</h2>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
tests/ref/html/title-basic.html
Normal file
12
tests/ref/html/title-basic.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
Some Title
|
||||||
|
</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
tests/ref/title-and-heading.png
Normal file
BIN
tests/ref/title-and-heading.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
tests/ref/title-basic.png
Normal file
BIN
tests/ref/title-basic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 679 B |
BIN
tests/ref/title-show-rule.png
Normal file
BIN
tests/ref/title-show-rule.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
12
tests/suite/model/title.typ
Normal file
12
tests/suite/model/title.typ
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Test title element.
|
||||||
|
|
||||||
|
--- title-basic render html ---
|
||||||
|
#title[Some Title]
|
||||||
|
|
||||||
|
--- title-and-heading render html ---
|
||||||
|
#title([A cool title])
|
||||||
|
= Some level one heading
|
||||||
|
|
||||||
|
--- title-show-rule ---
|
||||||
|
#show title: set text(3em)
|
||||||
|
#title[Some Title]
|
Loading…
x
Reference in New Issue
Block a user