mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Transform high level headings to HTML (#5525)
This commit is contained in:
parent
8b1e0d3a23
commit
75273937f7
@ -122,8 +122,8 @@ impl HtmlTag {
|
||||
let bytes = string.as_bytes();
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
if !bytes[i].is_ascii_alphanumeric() {
|
||||
panic!("constant tag name must be ASCII alphanumeric");
|
||||
if !bytes[i].is_ascii() || !charsets::is_valid_in_tag_name(bytes[i] as char) {
|
||||
panic!("not all characters are valid in a tag name");
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
@ -220,8 +220,10 @@ impl HtmlAttr {
|
||||
let bytes = string.as_bytes();
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
if !bytes[i].is_ascii_alphanumeric() {
|
||||
panic!("constant attribute name must be ASCII alphanumeric");
|
||||
if !bytes[i].is_ascii()
|
||||
|| !charsets::is_valid_in_attribute_name(bytes[i] as char)
|
||||
{
|
||||
panic!("not all characters are valid in an attribute name");
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
@ -621,5 +623,9 @@ pub mod attr {
|
||||
href
|
||||
name
|
||||
value
|
||||
role
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const aria_level: HtmlAttr = HtmlAttr::constant("aria-level");
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use ecow::eco_format;
|
||||
use typst_utils::NonZeroExt;
|
||||
|
||||
use crate::diag::SourceResult;
|
||||
use crate::diag::{warning, SourceResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
elem, Content, NativeElement, Packed, Resolve, Show, ShowSet, Smart, StyleChain,
|
||||
Styles, Synthesize, TargetElem,
|
||||
};
|
||||
use crate::html::{tag, HtmlElem};
|
||||
use crate::html::{attr, tag, HtmlElem};
|
||||
use crate::introspection::{
|
||||
Count, Counter, CounterUpdate, Locatable, Locator, LocatorLink,
|
||||
};
|
||||
@ -272,9 +273,26 @@ impl Show for Packed<HeadingElem> {
|
||||
// Meanwhile, a level 1 Typst heading is a section heading. For this
|
||||
// reason, levels are offset by one: A Typst level 1 heading becomes
|
||||
// a `<h2>`.
|
||||
let level = self.resolve_level(styles);
|
||||
let t = [tag::h2, tag::h3, tag::h4, tag::h5, tag::h6][level.get().min(5) - 1];
|
||||
HtmlElem::new(t).with_body(Some(realized)).pack().spanned(span)
|
||||
let level = self.resolve_level(styles).get();
|
||||
if level >= 6 {
|
||||
engine.sink.warn(warning!(span,
|
||||
"heading of level {} was transformed to \
|
||||
<div role=\"heading\" aria-level=\"{}\">, which is not \
|
||||
supported by all assistive technology",
|
||||
level, level + 1;
|
||||
hint: "HTML only supports <h1> to <h6>, not <h{}>", level + 1;
|
||||
hint: "you may want to restructure your document so that \
|
||||
it doesn't contain deep headings"));
|
||||
HtmlElem::new(tag::div)
|
||||
.with_body(Some(realized))
|
||||
.with_attr(attr::role, "heading")
|
||||
.with_attr(attr::aria_level, eco_format!("{}", level + 1))
|
||||
.pack()
|
||||
.spanned(span)
|
||||
} else {
|
||||
let t = [tag::h2, tag::h3, tag::h4, tag::h5, tag::h6][level - 1];
|
||||
HtmlElem::new(t).with_body(Some(realized)).pack().spanned(span)
|
||||
}
|
||||
} else {
|
||||
let realized = BlockBody::Content(realized);
|
||||
BlockElem::new().with_body(Some(realized)).pack().spanned(span)
|
||||
|
Loading…
x
Reference in New Issue
Block a user