mirror of
https://github.com/typst/typst
synced 2025-06-28 00:03:17 +08:00
Basic support for text decoration functions in HTML (#6510)
This commit is contained in:
parent
7420ec972f
commit
9311f6f08e
@ -2,7 +2,10 @@ use smallvec::smallvec;
|
|||||||
|
|
||||||
use crate::diag::SourceResult;
|
use crate::diag::SourceResult;
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
use crate::foundations::{elem, Content, Packed, Show, Smart, StyleChain};
|
use crate::foundations::{
|
||||||
|
elem, Content, NativeElement, Packed, Show, Smart, StyleChain, TargetElem,
|
||||||
|
};
|
||||||
|
use crate::html::{attr, tag, HtmlElem};
|
||||||
use crate::layout::{Abs, Corners, Length, Rel, Sides};
|
use crate::layout::{Abs, Corners, Length, Rel, Sides};
|
||||||
use crate::text::{BottomEdge, BottomEdgeMetric, TextElem, TopEdge, TopEdgeMetric};
|
use crate::text::{BottomEdge, BottomEdgeMetric, TextElem, TopEdge, TopEdgeMetric};
|
||||||
use crate::visualize::{Color, FixedStroke, Paint, Stroke};
|
use crate::visualize::{Color, FixedStroke, Paint, Stroke};
|
||||||
@ -81,6 +84,16 @@ pub struct UnderlineElem {
|
|||||||
impl Show for Packed<UnderlineElem> {
|
impl Show for Packed<UnderlineElem> {
|
||||||
#[typst_macros::time(name = "underline", span = self.span())]
|
#[typst_macros::time(name = "underline", span = self.span())]
|
||||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||||
|
if TargetElem::target_in(styles).is_html() {
|
||||||
|
// Note: In modern HTML, `<u>` is not the underline element, but
|
||||||
|
// rather an "Unarticulated Annotation" element (see HTML spec
|
||||||
|
// 4.5.22). Using `text-decoration` instead is recommended by MDN.
|
||||||
|
return Ok(HtmlElem::new(tag::span)
|
||||||
|
.with_attr(attr::style, "text-decoration: underline")
|
||||||
|
.with_body(Some(self.body.clone()))
|
||||||
|
.pack());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(self.body.clone().styled(TextElem::set_deco(smallvec![Decoration {
|
Ok(self.body.clone().styled(TextElem::set_deco(smallvec![Decoration {
|
||||||
line: DecoLine::Underline {
|
line: DecoLine::Underline {
|
||||||
stroke: self.stroke(styles).unwrap_or_default(),
|
stroke: self.stroke(styles).unwrap_or_default(),
|
||||||
@ -173,6 +186,13 @@ pub struct OverlineElem {
|
|||||||
impl Show for Packed<OverlineElem> {
|
impl Show for Packed<OverlineElem> {
|
||||||
#[typst_macros::time(name = "overline", span = self.span())]
|
#[typst_macros::time(name = "overline", span = self.span())]
|
||||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||||
|
if TargetElem::target_in(styles).is_html() {
|
||||||
|
return Ok(HtmlElem::new(tag::span)
|
||||||
|
.with_attr(attr::style, "text-decoration: overline")
|
||||||
|
.with_body(Some(self.body.clone()))
|
||||||
|
.pack());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(self.body.clone().styled(TextElem::set_deco(smallvec![Decoration {
|
Ok(self.body.clone().styled(TextElem::set_deco(smallvec![Decoration {
|
||||||
line: DecoLine::Overline {
|
line: DecoLine::Overline {
|
||||||
stroke: self.stroke(styles).unwrap_or_default(),
|
stroke: self.stroke(styles).unwrap_or_default(),
|
||||||
@ -250,6 +270,10 @@ pub struct StrikeElem {
|
|||||||
impl Show for Packed<StrikeElem> {
|
impl Show for Packed<StrikeElem> {
|
||||||
#[typst_macros::time(name = "strike", span = self.span())]
|
#[typst_macros::time(name = "strike", span = self.span())]
|
||||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||||
|
if TargetElem::target_in(styles).is_html() {
|
||||||
|
return Ok(HtmlElem::new(tag::s).with_body(Some(self.body.clone())).pack());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(self.body.clone().styled(TextElem::set_deco(smallvec![Decoration {
|
Ok(self.body.clone().styled(TextElem::set_deco(smallvec![Decoration {
|
||||||
// Note that we do not support evade option for strikethrough.
|
// Note that we do not support evade option for strikethrough.
|
||||||
line: DecoLine::Strikethrough {
|
line: DecoLine::Strikethrough {
|
||||||
@ -345,6 +369,12 @@ pub struct HighlightElem {
|
|||||||
impl Show for Packed<HighlightElem> {
|
impl Show for Packed<HighlightElem> {
|
||||||
#[typst_macros::time(name = "highlight", span = self.span())]
|
#[typst_macros::time(name = "highlight", span = self.span())]
|
||||||
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
|
||||||
|
if TargetElem::target_in(styles).is_html() {
|
||||||
|
return Ok(HtmlElem::new(tag::mark)
|
||||||
|
.with_body(Some(self.body.clone()))
|
||||||
|
.pack());
|
||||||
|
}
|
||||||
|
|
||||||
Ok(self.body.clone().styled(TextElem::set_deco(smallvec![Decoration {
|
Ok(self.body.clone().styled(TextElem::set_deco(smallvec![Decoration {
|
||||||
line: DecoLine::Highlight {
|
line: DecoLine::Highlight {
|
||||||
fill: self.fill(styles),
|
fill: self.fill(styles),
|
||||||
|
11
tests/ref/html/html-deco.html
Normal file
11
tests/ref/html/html-deco.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p><s>Struck</s> <mark>Highlighted</mark> <span style="text-decoration: underline">Underlined</span> <span style="text-decoration: overline">Overlined</span></p>
|
||||||
|
<p><span style="text-decoration: overline"><span style="text-decoration: underline"><mark><s>Mixed</s></mark></span></span></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -83,3 +83,11 @@ We can also specify a customized value
|
|||||||
#highlight(stroke: 2pt + blue)[abc]
|
#highlight(stroke: 2pt + blue)[abc]
|
||||||
#highlight(stroke: (top: blue, left: red, bottom: green, right: orange))[abc]
|
#highlight(stroke: (top: blue, left: red, bottom: green, right: orange))[abc]
|
||||||
#highlight(stroke: 1pt, radius: 3pt)[#lorem(5)]
|
#highlight(stroke: 1pt, radius: 3pt)[#lorem(5)]
|
||||||
|
|
||||||
|
--- html-deco html ---
|
||||||
|
#strike[Struck]
|
||||||
|
#highlight[Highlighted]
|
||||||
|
#underline[Underlined]
|
||||||
|
#overline[Overlined]
|
||||||
|
|
||||||
|
#(strike, highlight, underline, overline).fold([Mixed], (it, f) => f(it))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user