Support for raw syntax highlighting in HTML export (#6691)
This commit is contained in:
parent
04b8b3195f
commit
6177c1b22d
|
|
@ -26,7 +26,6 @@ impl Properties {
|
|||
}
|
||||
|
||||
/// Adds a new property in builder-style.
|
||||
#[expect(unused)]
|
||||
pub fn with(mut self, property: &str, value: impl Display) -> Self {
|
||||
self.push(property, value);
|
||||
self
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ mod typed;
|
|||
pub use self::document::html_document;
|
||||
pub use self::dom::*;
|
||||
pub use self::encode::html;
|
||||
pub use self::rules::register;
|
||||
pub use self::rules::{html_span_filled, register};
|
||||
|
||||
use ecow::EcoString;
|
||||
use typst_library::Category;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use typst_library::text::{
|
|||
HighlightElem, LinebreakElem, OverlineElem, RawElem, RawLine, SmallcapsElem,
|
||||
SpaceElem, StrikeElem, SubElem, SuperElem, UnderlineElem,
|
||||
};
|
||||
use typst_library::visualize::ImageElem;
|
||||
use typst_library::visualize::{Color, ImageElem};
|
||||
|
||||
use crate::{FrameElem, HtmlAttrs, HtmlElem, HtmlTag, attr, css, tag};
|
||||
|
||||
|
|
@ -427,6 +427,20 @@ const RAW_RULE: ShowFn<RawElem> = |elem, _, styles| {
|
|||
})
|
||||
};
|
||||
|
||||
/// This is used by `RawElem::synthesize` through a routine.
|
||||
///
|
||||
/// It's a temporary workaround until `TextElem::fill` is supported in HTML
|
||||
/// export.
|
||||
#[doc(hidden)]
|
||||
pub fn html_span_filled(content: Content, color: Color) -> Content {
|
||||
let span = content.span();
|
||||
HtmlElem::new(tag::span)
|
||||
.with_styles(css::Properties::new().with("color", css::color(color)))
|
||||
.with_body(Some(content))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
}
|
||||
|
||||
const RAW_LINE_RULE: ShowFn<RawLine> = |elem, _, _| Ok(elem.body.clone());
|
||||
|
||||
const IMAGE_RULE: ShowFn<ImageElem> = |elem, engine, styles| {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use crate::foundations::{
|
|||
use crate::introspection::{Introspector, Locator, SplitLocator};
|
||||
use crate::layout::{Frame, Region};
|
||||
use crate::model::DocumentInfo;
|
||||
use crate::visualize::Color;
|
||||
|
||||
/// Defines the `Routines` struct.
|
||||
macro_rules! routines {
|
||||
|
|
@ -95,6 +96,12 @@ routines! {
|
|||
|
||||
/// Constructs the `html` module.
|
||||
fn html_module() -> Module
|
||||
|
||||
/// Wraps content in a span with a color.
|
||||
///
|
||||
/// This is a temporary workaround until `TextElem::fill` is supported in
|
||||
/// HTML export.
|
||||
fn html_span_filled(content: Content, color: Color) -> Content
|
||||
}
|
||||
|
||||
/// Defines what kind of realization we are performing.
|
||||
|
|
|
|||
|
|
@ -18,11 +18,12 @@ use crate::diag::{
|
|||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
Bytes, Content, Derived, OneOrMultiple, Packed, PlainText, ShowSet, Smart,
|
||||
StyleChain, Styles, Synthesize, cast, elem, scope,
|
||||
StyleChain, Styles, Synthesize, Target, TargetElem, cast, elem, scope,
|
||||
};
|
||||
use crate::layout::{Em, HAlignment};
|
||||
use crate::loading::{DataSource, Load};
|
||||
use crate::model::{Figurable, ParElem};
|
||||
use crate::routines::Routines;
|
||||
use crate::text::{FontFamily, FontList, LocalName, TextElem, TextSize};
|
||||
use crate::visualize::Color;
|
||||
|
||||
|
|
@ -300,8 +301,12 @@ impl RawElem {
|
|||
}
|
||||
|
||||
impl Synthesize for Packed<RawElem> {
|
||||
fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
|
||||
let seq = self.highlight(styles);
|
||||
fn synthesize(
|
||||
&mut self,
|
||||
engine: &mut Engine,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<()> {
|
||||
let seq = self.highlight(engine.routines, styles);
|
||||
self.lines = Some(seq);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -309,7 +314,7 @@ impl Synthesize for Packed<RawElem> {
|
|||
|
||||
impl Packed<RawElem> {
|
||||
#[comemo::memoize]
|
||||
fn highlight(&self, styles: StyleChain) -> Vec<Packed<RawLine>> {
|
||||
fn highlight(&self, routines: &Routines, styles: StyleChain) -> Vec<Packed<RawLine>> {
|
||||
let elem = self.as_ref();
|
||||
let lines = preprocess(&elem.text, styles, self.span());
|
||||
|
||||
|
|
@ -341,6 +346,7 @@ impl Packed<RawElem> {
|
|||
};
|
||||
|
||||
let foreground = theme.settings.foreground.unwrap_or(synt::Color::BLACK);
|
||||
let target = styles.get(TargetElem::target);
|
||||
|
||||
let mut seq = vec![];
|
||||
if matches!(lang.as_deref(), Some("typ" | "typst" | "typc" | "typm")) {
|
||||
|
|
@ -363,7 +369,15 @@ impl Packed<RawElem> {
|
|||
let span_offset = text[..range.start]
|
||||
.rfind('\n')
|
||||
.map_or(0, |i| range.start - (i + 1));
|
||||
styled(&text[range], foreground, style, span, span_offset)
|
||||
styled(
|
||||
routines,
|
||||
target,
|
||||
&text[range],
|
||||
foreground,
|
||||
style,
|
||||
span,
|
||||
span_offset,
|
||||
)
|
||||
},
|
||||
&mut |i, range, line| {
|
||||
let span = lines.get(i).map_or_else(Span::detached, |l| l.1);
|
||||
|
|
@ -400,6 +414,8 @@ impl Packed<RawElem> {
|
|||
.flatten()
|
||||
{
|
||||
line_content.push(styled(
|
||||
routines,
|
||||
target,
|
||||
piece,
|
||||
foreground,
|
||||
style,
|
||||
|
|
@ -769,6 +785,8 @@ fn preprocess(
|
|||
|
||||
/// Style a piece of text with a syntect style.
|
||||
fn styled(
|
||||
routines: &Routines,
|
||||
target: Target,
|
||||
piece: &str,
|
||||
foreground: synt::Color,
|
||||
style: synt::Style,
|
||||
|
|
@ -782,7 +800,11 @@ fn styled(
|
|||
}
|
||||
|
||||
if style.foreground != foreground {
|
||||
body = body.set(TextElem::fill, to_typst(style.foreground).into());
|
||||
let color = to_typst(style.foreground);
|
||||
body = match target {
|
||||
Target::Html => (routines.html_span_filled)(body, color),
|
||||
Target::Paged => body.set(TextElem::fill, color.into()),
|
||||
};
|
||||
}
|
||||
|
||||
if style.font_style.contains(synt::FontStyle::BOLD) {
|
||||
|
|
|
|||
|
|
@ -358,4 +358,5 @@ pub static ROUTINES: LazyLock<Routines> = LazyLock::new(|| Routines {
|
|||
realize: typst_realize::realize,
|
||||
layout_frame: typst_layout::layout_frame,
|
||||
html_module: typst_html::module,
|
||||
html_span_filled: typst_html::html_span_filled,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<p>This is <code><strong>*</strong><strong>inline</strong><strong>*</strong></code>.</p>
|
||||
<pre><code>#set text(blue)<br><strong>*</strong><strong>Hello</strong><strong>*</strong> <em>_</em><em>world</em><em>_</em>!</code></pre>
|
||||
<pre><code><span style="color: #d73a49">#</span><span style="color: #d73a49">set</span> <span style="color: #4b69c6">text</span>(blue)<br><strong>*</strong><strong>Hello</strong><strong>*</strong> <em>_</em><em>world</em><em>_</em>!</code></pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue