summaryrefslogtreecommitdiff
path: root/library/src/text/raw.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-07-02 19:59:52 +0200
committerLaurenz <laurmaedje@gmail.com>2023-07-02 20:07:43 +0200
commitebfdb1dafa430786db10dad2ef7d5467c1bdbed1 (patch)
tree2bbc24ddb4124c4bb14dec0e536129d4de37b056 /library/src/text/raw.rs
parent3ab19185093d7709f824b95b979060ce125389d8 (diff)
Move everything into `crates/` directory
Diffstat (limited to 'library/src/text/raw.rs')
-rw-r--r--library/src/text/raw.rs398
1 files changed, 0 insertions, 398 deletions
diff --git a/library/src/text/raw.rs b/library/src/text/raw.rs
deleted file mode 100644
index 24f39bb6..00000000
--- a/library/src/text/raw.rs
+++ /dev/null
@@ -1,398 +0,0 @@
-use once_cell::sync::Lazy;
-use syntect::highlighting as synt;
-use typst::syntax::{self, LinkedNode};
-
-use super::{
- FontFamily, FontList, Hyphenate, LinebreakElem, SmartQuoteElem, TextElem, TextSize,
-};
-use crate::layout::BlockElem;
-use crate::meta::{Figurable, LocalName};
-use crate::prelude::*;
-
-/// 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.
-///
-/// ## Example { #example }
-/// ````example
-/// Adding `rbx` to `rcx` gives
-/// the desired result.
-///
-/// ```rust
-/// fn main() {
-/// println!("Hello World!");
-/// }
-/// ```
-/// ````
-///
-/// ## Syntax { #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.
-///
-/// Display: Raw Text / Code
-/// Category: text
-#[element(Synthesize, Show, Finalize, LocalName, Figurable, PlainText)]
-pub struct RawElem {
- /// 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
- /// ```
- /// ````
- #[required]
- pub text: EcoString,
-
- /// Whether the raw text is displayed as a separate block.
- ///
- /// In markup mode, using one-backtick notation makes this `{false}`,
- /// whereas using three-backtick notation makes it `{true}`.
- ///
- /// ````example
- /// // Display inline code in a small box
- /// // that retains the correct baseline.
- /// #show raw.where(block: false): box.with(
- /// fill: luma(240),
- /// inset: (x: 3pt, y: 0pt),
- /// outset: (y: 3pt),
- /// radius: 2pt,
- /// )
- ///
- /// // Display block code in a larger block
- /// // with more padding.
- /// #show raw.where(block: true): block.with(
- /// fill: luma(240),
- /// inset: 10pt,
- /// radius: 4pt,
- /// )
- ///
- /// With `rg`, you can search through your files quickly.
- ///
- /// ```bash
- /// rg "Hello World"
- /// ```
- /// ````
- #[default(false)]
- pub block: bool,
-
- /// 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!*
- /// ```
- /// ````
- pub lang: Option<EcoString>,
-
- /// The horizontal alignment that each line in a raw block should have.
- /// This option is ignored if this is not a raw block (if specified
- /// `block: false` or single backticks were used in markup mode).
- ///
- /// By default, this is set to `{start}`, meaning that raw text is
- /// aligned towards the start of the text direction inside the block
- /// by default, regardless of the current context's alignment (allowing
- /// you to center the raw block itself without centering the text inside
- /// it, for example).
- ///
- /// ````example
- /// #set raw(align: center)
- ///
- /// ```typc
- /// let f(x) = x
- /// code = "centered"
- /// ```
- /// ````
- #[default(HorizontalAlign(GenAlign::Start))]
- pub align: HorizontalAlign,
-}
-
-impl RawElem {
- /// The supported language names and tags.
- pub fn languages() -> Vec<(&'static str, Vec<&'static str>)> {
- SYNTAXES
- .syntaxes()
- .iter()
- .map(|syntax| {
- (
- syntax.name.as_str(),
- syntax.file_extensions.iter().map(|s| s.as_str()).collect(),
- )
- })
- .chain([("Typst", vec!["typ"]), ("Typst (code)", vec!["typc"])])
- .collect()
- }
-}
-
-impl Synthesize for RawElem {
- fn synthesize(&mut self, _vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
- self.push_lang(self.lang(styles));
- Ok(())
- }
-}
-
-impl Show for RawElem {
- #[tracing::instrument(name = "RawElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- let text = self.text();
- let lang = self.lang(styles).as_ref().map(|s| s.to_lowercase());
- let foreground = THEME
- .settings
- .foreground
- .map(to_typst)
- .map_or(Color::BLACK, Color::from);
-
- let mut realized = if matches!(lang.as_deref(), Some("typ" | "typst" | "typc")) {
- let root = match lang.as_deref() {
- Some("typc") => syntax::parse_code(&text),
- _ => syntax::parse(&text),
- };
-
- let mut seq = vec![];
- let highlighter = synt::Highlighter::new(&THEME);
- highlight_themed(
- &LinkedNode::new(&root),
- vec![],
- &highlighter,
- &mut |node, style| {
- seq.push(styled(&text[node.range()], foreground.into(), style));
- },
- );
-
- Content::sequence(seq)
- } else if let Some(syntax) =
- lang.and_then(|token| SYNTAXES.find_syntax_by_token(&token))
- {
- let mut seq = vec![];
- let mut highlighter = syntect::easy::HighlightLines::new(syntax, &THEME);
- for (i, line) in text.lines().enumerate() {
- if i != 0 {
- seq.push(LinebreakElem::new().pack());
- }
-
- for (style, piece) in
- highlighter.highlight_line(line, &SYNTAXES).into_iter().flatten()
- {
- seq.push(styled(piece, foreground.into(), style));
- }
- }
-
- Content::sequence(seq)
- } else {
- TextElem::packed(text)
- };
-
- if self.block(styles) {
- // Align the text before inserting it into the block.
- realized = realized.aligned(Axes::with_x(Some(self.align(styles).into())));
- realized = BlockElem::new().with_body(Some(realized)).pack();
- }
-
- Ok(realized)
- }
-}
-
-impl Finalize for RawElem {
- fn finalize(&self, realized: Content, _: StyleChain) -> Content {
- let mut styles = Styles::new();
- styles.set(TextElem::set_overhang(false));
- styles.set(TextElem::set_hyphenate(Hyphenate(Smart::Custom(false))));
- styles.set(TextElem::set_size(TextSize(Em::new(0.8).into())));
- styles
- .set(TextElem::set_font(FontList(vec![FontFamily::new("DejaVu Sans Mono")])));
- styles.set(SmartQuoteElem::set_enabled(false));
- realized.styled_with_map(styles)
- }
-}
-
-impl LocalName for RawElem {
- fn local_name(&self, lang: Lang, _: Option<Region>) -> &'static str {
- match lang {
- Lang::ALBANIAN => "List",
- Lang::ARABIC => "قائمة",
- Lang::BOKMÅL => "Utskrift",
- Lang::CHINESE => "代码",
- Lang::CZECH => "Seznam",
- Lang::DANISH => "Liste",
- Lang::DUTCH => "Listing",
- Lang::FILIPINO => "Listahan",
- Lang::FRENCH => "Liste",
- Lang::GERMAN => "Listing",
- Lang::ITALIAN => "Codice",
- Lang::NYNORSK => "Utskrift",
- Lang::POLISH => "Program",
- Lang::RUSSIAN => "Листинг",
- Lang::SLOVENIAN => "Program",
- Lang::SWEDISH => "Listing",
- Lang::TURKISH => "Liste",
- Lang::UKRAINIAN => "Лістинг",
- Lang::VIETNAMESE => "Chương trình", // TODO: This may be wrong.
- Lang::ENGLISH | _ => "Listing",
- }
- }
-}
-
-impl Figurable for RawElem {}
-
-impl PlainText for RawElem {
- fn plain_text(&self, text: &mut EcoString) {
- text.push_str(&self.text());
- }
-}
-
-/// Highlight a syntax node in a theme by calling `f` with ranges and their
-/// styles.
-fn highlight_themed<F>(
- node: &LinkedNode,
- scopes: Vec<syntect::parsing::Scope>,
- highlighter: &synt::Highlighter,
- f: &mut F,
-) where
- F: FnMut(&LinkedNode, synt::Style),
-{
- if node.children().len() == 0 {
- let style = highlighter.style_for_stack(&scopes);
- f(node, style);
- return;
- }
-
- for child in node.children() {
- let mut scopes = scopes.clone();
- if let Some(tag) = typst::ide::highlight(&child) {
- scopes.push(syntect::parsing::Scope::new(tag.tm_scope()).unwrap())
- }
- highlight_themed(&child, scopes, highlighter, f);
- }
-}
-
-/// Style a piece of text with a syntect style.
-fn styled(piece: &str, foreground: Paint, style: synt::Style) -> Content {
- let mut body = TextElem::packed(piece);
-
- let paint = to_typst(style.foreground).into();
- if paint != foreground {
- body = body.styled(TextElem::set_fill(paint));
- }
-
- if style.font_style.contains(synt::FontStyle::BOLD) {
- body = body.strong();
- }
-
- if style.font_style.contains(synt::FontStyle::ITALIC) {
- body = body.emph();
- }
-
- if style.font_style.contains(synt::FontStyle::UNDERLINE) {
- body = body.underlined();
- }
-
- body
-}
-
-fn to_typst(synt::Color { r, g, b, a }: synt::Color) -> RgbaColor {
- RgbaColor { r, g, b, a }
-}
-
-fn to_syn(RgbaColor { r, g, b, a }: RgbaColor) -> synt::Color {
- synt::Color { r, g, b, a }
-}
-
-/// The syntect syntax definitions.
-///
-/// Code for syntax set generation is below. The `syntaxes` directory is from
-/// <https://github.com/sharkdp/bat/tree/master/assets/syntaxes>
-///
-/// ```ignore
-/// fn main() {
-/// let mut builder = syntect::parsing::SyntaxSet::load_defaults_nonewlines().into_builder();
-/// builder.add_from_folder("syntaxes/02_Extra", false).unwrap();
-/// syntect::dumps::dump_to_file(&builder.build(), "syntect.bin").unwrap();
-/// }
-/// ```
-///
-/// The following syntaxes are disabled due to compatibility issues:
-/// ```text
-/// syntaxes/02_Extra/Assembly (ARM).sublime-syntax
-/// syntaxes/02_Extra/Elixir/Regular Expressions (Elixir).sublime-syntax
-/// syntaxes/02_Extra/JavaScript (Babel).sublime-syntax
-/// syntaxes/02_Extra/LiveScript.sublime-syntax
-/// syntaxes/02_Extra/PowerShell.sublime-syntax
-/// syntaxes/02_Extra/SCSS_Sass/Syntaxes/Sass.sublime-syntax
-/// syntaxes/02_Extra/SLS/SLS.sublime-syntax
-/// syntaxes/02_Extra/VimHelp.sublime-syntax
-/// syntaxes/02_Extra/cmd-help/syntaxes/cmd-help.sublime-syntax
-/// ```
-pub static SYNTAXES: Lazy<syntect::parsing::SyntaxSet> =
- Lazy::new(|| syntect::dumps::from_binary(include_bytes!("../../assets/syntect.bin")));
-
-/// The default theme used for syntax highlighting.
-pub static THEME: Lazy<synt::Theme> = Lazy::new(|| synt::Theme {
- name: Some("Typst Light".into()),
- author: Some("The Typst Project Developers".into()),
- settings: synt::ThemeSettings::default(),
- scopes: vec![
- item("comment", Some("#8a8a8a"), None),
- item("constant.character.escape", Some("#1d6c76"), None),
- item("markup.bold", None, Some(synt::FontStyle::BOLD)),
- item("markup.italic", None, Some(synt::FontStyle::ITALIC)),
- item("markup.underline", None, Some(synt::FontStyle::UNDERLINE)),
- item("markup.raw", Some("#818181"), None),
- item("string.other.math.typst", None, None),
- item("punctuation.definition.math", Some("#298e0d"), None),
- item("keyword.operator.math", Some("#1d6c76"), None),
- item("markup.heading, entity.name.section", None, Some(synt::FontStyle::BOLD)),
- item(
- "markup.heading.typst",
- None,
- Some(synt::FontStyle::BOLD | synt::FontStyle::UNDERLINE),
- ),
- item("punctuation.definition.list", Some("#8b41b1"), None),
- item("markup.list.term", None, Some(synt::FontStyle::BOLD)),
- item("entity.name.label, markup.other.reference", Some("#1d6c76"), None),
- item("keyword, constant.language, variable.language", Some("#d73a49"), None),
- item("storage.type, storage.modifier", Some("#d73a49"), None),
- item("constant", Some("#b60157"), None),
- item("string", Some("#298e0d"), None),
- item("entity.name, variable.function, support", Some("#4b69c6"), None),
- item("support.macro", Some("#16718d"), None),
- item("meta.annotation", Some("#301414"), None),
- item("entity.other, meta.interpolation", Some("#8b41b1"), None),
- ],
-});
-
-/// Create a syntect theme item.
-fn item(
- scope: &str,
- color: Option<&str>,
- font_style: Option<synt::FontStyle>,
-) -> synt::ThemeItem {
- synt::ThemeItem {
- scope: scope.parse().unwrap(),
- style: synt::StyleModifier {
- foreground: color.map(|s| to_syn(s.parse::<RgbaColor>().unwrap())),
- background: None,
- font_style,
- },
- }
-}