Skip to content

Commit

Permalink
Added a syntax highlighting example
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko committed Jun 17, 2024
1 parent ab41e94 commit 9495cda
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 0 deletions.
93 changes: 93 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions examples/syntax-highlighting/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "syntax-highlighting"
version = "0.1.0"
edition = "2018"
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
minijinja = { path = "../../minijinja" }
syntect = { version = "5.2.0", default-features = false, features = ["default-fancy", "default-syntaxes"] }
7 changes: 7 additions & 0 deletions examples/syntax-highlighting/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# syntax-highlighting

An example that shows how to register a function for syntax highlighting wiht syntect.

```console
$ cargo run
```
9 changes: 9 additions & 0 deletions examples/syntax-highlighting/src/example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!doctype html>
<title>Syntax Highlight Example</title>
<h1>Syntax Highlight Example</h1>
{% do highlight.set_theme("base16-ocean.light") %}
{% call highlight('rust') %}
fn main() {
println!("Hello World!");
}
{% endcall %}
92 changes: 92 additions & 0 deletions examples/syntax-highlighting/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use std::sync::{Arc, Mutex};

use minijinja::value::{from_args, Kwargs, Object};
use minijinja::{args, Environment, Error, ErrorKind, State, Value};
use syntect::highlighting::ThemeSet;
use syntect::html::highlighted_html_for_string;
use syntect::parsing::SyntaxSet;

#[derive(Debug)]
struct Highlighter {
ss: SyntaxSet,
ts: ThemeSet,
theme: Arc<Mutex<String>>,
}

impl Highlighter {
pub fn new() -> Highlighter {
let ss = SyntaxSet::load_defaults_newlines();
let ts = ThemeSet::load_defaults();
Highlighter {
ss,
ts,
theme: Mutex::new("InspiredGitHub".to_string()).into(),
}
}
}

impl Object for Highlighter {
fn call(self: &Arc<Self>, state: &State<'_, '_>, args: &[Value]) -> Result<Value, Error> {
let (lang, kwargs): (&str, Kwargs) = from_args(args)?;
let caller: Value = kwargs.get("caller")?;
let content = caller.call(state, args!())?;
let mut content_str = content.as_str().ok_or_else(|| {
Error::new(
ErrorKind::InvalidOperation,
"call block did not return a string",
)
})?;
if let Some(rest) = content_str.strip_prefix('\n') {
content_str = rest;
}
let syntax = self.ss.find_syntax_by_token(lang).ok_or_else(|| {
Error::new(
ErrorKind::InvalidOperation,
format!("unknown language {}", lang),
)
})?;
kwargs.assert_all_used()?;
let theme = self.theme.lock().unwrap();
let rv = highlighted_html_for_string(
content_str,
&self.ss,
syntax,
&self.ts.themes[&theme as &str],
)
.map_err(|err| {
Error::new(ErrorKind::InvalidOperation, "failed to syntax highlight").with_source(err)
})?;
Ok(Value::from_safe_string(rv))
}

fn call_method(
self: &Arc<Self>,
_state: &State<'_, '_>,
method: &str,
args: &[Value],
) -> Result<Value, Error> {
match method {
"set_theme" => {
let (name,): (String,) = from_args(args)?;
if !self.ts.themes.contains_key(&name) {
return Err(Error::new(
ErrorKind::InvalidOperation,
format!("unknown theme {}", name),
));
}
*self.theme.lock().unwrap() = name;
Ok(Value::UNDEFINED)
}
_ => Err(Error::from(ErrorKind::UnknownMethod)),
}
}
}

fn main() {
let mut env = Environment::new();
env.add_global("highlight", Value::from_object(Highlighter::new()));
env.add_template("example.html", include_str!("example.html"))
.unwrap();
let template = env.get_template("example.html").unwrap();
println!("{}", template.render(()).unwrap());
}
10 changes: 10 additions & 0 deletions examples/syntax-highlighting/test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!doctype html>
<title>Syntax Highlight Example</title>
<h1>Syntax Highlight Example</h1>

<pre style="background-color:#eff1f5;">
<span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">main</span><span style="color:#4f5b66;">() {
</span><span style="color:#4f5b66;"> println!(&quot;</span><span style="color:#a3be8c;">Hello World!</span><span style="color:#4f5b66;">&quot;);
</span><span style="color:#4f5b66;">}
</span></pre>

0 comments on commit 9495cda

Please sign in to comment.