-
-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #209 from gjtorikian/syntax-highlighting
Implement native syntax highlighting
- Loading branch information
Showing
18 changed files
with
402 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,85 @@ | ||
extern crate core; | ||
|
||
use comrak::{markdown_to_html, ComrakOptions}; | ||
use magnus::{define_module, function, r_hash::ForEach, Error, RHash, Symbol}; | ||
use comrak::{ | ||
adapters::SyntaxHighlighterAdapter, markdown_to_html, markdown_to_html_with_plugins, | ||
plugins::syntect::SyntectAdapter, ComrakOptions, ComrakPlugins, | ||
}; | ||
use magnus::{define_module, function, r_hash::ForEach, scan_args, Error, RHash, Symbol, Value}; | ||
|
||
mod comrak_options; | ||
use comrak_options::iterate_options_hash; | ||
mod options; | ||
use options::iterate_options_hash; | ||
|
||
mod plugins; | ||
use plugins::{ | ||
syntax_highlighting::{ | ||
fetch_syntax_highlighter_theme, SYNTAX_HIGHLIGHTER_PLUGIN_DEFAULT_THEME, | ||
}, | ||
SYNTAX_HIGHLIGHTER_PLUGIN, | ||
}; | ||
|
||
mod utils; | ||
|
||
pub const EMPTY_STR: &str = ""; | ||
|
||
fn commonmark_to_html<'a>(args: &[Value]) -> Result<String, magnus::Error> { | ||
let args = scan_args::scan_args(args)?; | ||
let (rb_commonmark,): (String,) = args.required; | ||
let _: () = args.optional; | ||
let _: () = args.splat; | ||
let _: () = args.trailing; | ||
let _: () = args.block; | ||
|
||
let kwargs = scan_args::get_kwargs::<_, (), (Option<RHash>, Option<RHash>), ()>( | ||
args.keywords, | ||
&[], | ||
&["options", "plugins"], | ||
)?; | ||
let (rb_options, rb_plugins) = kwargs.optional; | ||
|
||
fn commonmark_to_html(rb_commonmark: String, rb_options: magnus::RHash) -> String { | ||
let mut comrak_options = ComrakOptions::default(); | ||
|
||
rb_options | ||
.foreach(|key: Symbol, value: RHash| { | ||
iterate_options_hash(&mut comrak_options, key, value).unwrap(); | ||
if let Some(rb_options) = rb_options { | ||
rb_options.foreach(|key: Symbol, value: RHash| { | ||
iterate_options_hash(&mut comrak_options, key, value)?; | ||
Ok(ForEach::Continue) | ||
}) | ||
.unwrap(); | ||
})?; | ||
} | ||
|
||
if let Some(rb_plugins) = rb_plugins { | ||
let mut comrak_plugins = ComrakPlugins::default(); | ||
|
||
let syntax_highlighter: Option<&dyn SyntaxHighlighterAdapter>; | ||
let adapter: SyntectAdapter; | ||
|
||
let theme = match rb_plugins.get(Symbol::new(SYNTAX_HIGHLIGHTER_PLUGIN)) { | ||
Some(theme_val) => fetch_syntax_highlighter_theme(theme_val)?, | ||
None => SYNTAX_HIGHLIGHTER_PLUGIN_DEFAULT_THEME.to_string(), // no `syntax_highlighter:` defined | ||
}; | ||
|
||
if theme.is_empty() || theme == "none" { | ||
syntax_highlighter = None; | ||
} else { | ||
adapter = SyntectAdapter::new(&theme); | ||
syntax_highlighter = Some(&adapter); | ||
} | ||
|
||
comrak_plugins.render.codefence_syntax_highlighter = syntax_highlighter; | ||
|
||
markdown_to_html(&rb_commonmark, &comrak_options) | ||
Ok(markdown_to_html_with_plugins( | ||
&rb_commonmark, | ||
&comrak_options, | ||
&comrak_plugins, | ||
)) | ||
} else { | ||
Ok(markdown_to_html(&rb_commonmark, &comrak_options)) | ||
} | ||
} | ||
|
||
#[magnus::init] | ||
fn init() -> Result<(), Error> { | ||
let module = define_module("Commonmarker")?; | ||
|
||
module.define_module_function("commonmark_to_html", function!(commonmark_to_html, 2))?; | ||
module.define_module_function("commonmark_to_html", function!(commonmark_to_html, -1))?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// use comrak::ComrakPlugins; | ||
// use magnus::{class, r_hash::ForEach, RHash, Symbol, Value}; | ||
|
||
// use crate::plugins::syntax_highlighting::fetch_syntax_highlighter_theme; | ||
|
||
pub mod syntax_highlighting; | ||
|
||
pub const SYNTAX_HIGHLIGHTER_PLUGIN: &str = "syntax_highlighter"; | ||
|
||
// pub fn iterate_plugins_hash( | ||
// comrak_plugins: &mut ComrakPlugins, | ||
// mut theme: String, | ||
// key: Symbol, | ||
// value: Value, | ||
// ) -> Result<ForEach, magnus::Error> { | ||
// if key.name().unwrap() == SYNTAX_HIGHLIGHTER_PLUGIN { | ||
// theme = fetch_syntax_highlighter_theme(value)?; | ||
// } | ||
|
||
// Ok(ForEach::Continue) | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
use magnus::{RHash, Symbol, Value}; | ||
|
||
use crate::EMPTY_STR; | ||
|
||
pub const SYNTAX_HIGHLIGHTER_PLUGIN_THEME_KEY: &str = "theme"; | ||
pub const SYNTAX_HIGHLIGHTER_PLUGIN_DEFAULT_THEME: &str = "base16-ocean.dark"; | ||
|
||
pub fn fetch_syntax_highlighter_theme(value: Value) -> Result<String, magnus::Error> { | ||
if value.is_nil() { | ||
// `syntax_highlighter: nil` | ||
return Ok(EMPTY_STR.to_string()); | ||
} | ||
|
||
let syntax_highlighter_plugin = value.try_convert::<RHash>()?; | ||
let theme_key = Symbol::new(SYNTAX_HIGHLIGHTER_PLUGIN_THEME_KEY); | ||
|
||
match syntax_highlighter_plugin.get(theme_key) { | ||
Some(theme) => { | ||
if theme.is_nil() { | ||
// `syntax_highlighter: { theme: nil }` | ||
return Ok(EMPTY_STR.to_string()); | ||
} | ||
Ok(theme.try_convert::<String>()?) | ||
} | ||
None => { | ||
// `syntax_highlighter: { }` | ||
Ok(EMPTY_STR.to_string()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
use magnus::Value; | ||
|
||
pub fn try_convert_string(value: Value) -> Option<String> { | ||
match value.try_convert::<String>() { | ||
Ok(s) => Some(s), | ||
Err(_) => None, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# frozen_string_literal: true | ||
|
||
module Commonmarker | ||
module Constants | ||
BOOLS = [true, false].freeze | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.