Skip to content

Commit 1b74829

Browse files
authored
Merge pull request #299 from gjtorikian/support-plugins-for-nodes
Support plugins when processing node tree
2 parents 2fd0c39 + d44a174 commit 1b74829

File tree

6 files changed

+203
-141
lines changed

6 files changed

+203
-141
lines changed

ext/commonmarker/src/lib.rs

+31-111
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,15 @@
11
extern crate core;
22

3-
use std::path::PathBuf;
4-
5-
use ::syntect::highlighting::ThemeSet;
6-
use comrak::{
7-
adapters::SyntaxHighlighterAdapter,
8-
markdown_to_html, markdown_to_html_with_plugins, parse_document,
9-
plugins::syntect::{SyntectAdapter, SyntectAdapterBuilder},
10-
ComrakOptions, ComrakPlugins,
11-
};
12-
use magnus::{
13-
define_module, exception, function, r_hash::ForEach, scan_args, Error, RHash, Symbol, Value,
14-
};
3+
use comrak::{markdown_to_html_with_plugins, parse_document, ComrakOptions};
4+
use magnus::{define_module, function, r_hash::ForEach, scan_args, Error, RHash, Symbol, Value};
155
use node::CommonmarkerNode;
6+
use plugins::syntax_highlighting::construct_syntax_highlighter_from_plugin;
167

178
mod options;
189
use options::iterate_options_hash;
1910

2011
mod plugins;
21-
use plugins::{
22-
syntax_highlighting::{fetch_syntax_highlighter_path, fetch_syntax_highlighter_theme},
23-
SYNTAX_HIGHLIGHTER_PLUGIN,
24-
};
12+
2513
use typed_arena::Arena;
2614

2715
mod node;
@@ -63,6 +51,32 @@ fn commonmark_to_html(args: &[Value]) -> Result<String, magnus::Error> {
6351
)?;
6452
let (rb_options, rb_plugins) = kwargs.optional;
6553

54+
let comrak_options = match format_options(rb_options) {
55+
Ok(options) => options,
56+
Err(err) => return Err(err),
57+
};
58+
59+
let mut comrak_plugins = comrak::Plugins::default();
60+
61+
let syntect_adapter = match construct_syntax_highlighter_from_plugin(rb_plugins) {
62+
Ok(Some(adapter)) => Some(adapter),
63+
Ok(None) => None,
64+
Err(err) => return Err(err),
65+
};
66+
67+
match syntect_adapter {
68+
Some(ref adapter) => comrak_plugins.render.codefence_syntax_highlighter = Some(adapter),
69+
None => comrak_plugins.render.codefence_syntax_highlighter = None,
70+
}
71+
72+
Ok(markdown_to_html_with_plugins(
73+
&rb_commonmark,
74+
&comrak_options,
75+
&comrak_plugins,
76+
))
77+
}
78+
79+
fn format_options(rb_options: Option<RHash>) -> Result<comrak::Options, magnus::Error> {
6680
let mut comrak_options = ComrakOptions::default();
6781

6882
if let Some(rb_options) = rb_options {
@@ -72,101 +86,7 @@ fn commonmark_to_html(args: &[Value]) -> Result<String, magnus::Error> {
7286
})?;
7387
}
7488

75-
if let Some(rb_plugins) = rb_plugins {
76-
let mut comrak_plugins = ComrakPlugins::default();
77-
78-
let syntax_highlighter: Option<&dyn SyntaxHighlighterAdapter>;
79-
let adapter: SyntectAdapter;
80-
81-
let theme = match rb_plugins.get(Symbol::new(SYNTAX_HIGHLIGHTER_PLUGIN)) {
82-
Some(syntax_highlighter_options) => {
83-
match fetch_syntax_highlighter_theme(syntax_highlighter_options) {
84-
Ok(theme) => theme,
85-
Err(e) => {
86-
return Err(e);
87-
}
88-
}
89-
}
90-
None => None, // no `syntax_highlighter:` defined
91-
};
92-
93-
match theme {
94-
None => syntax_highlighter = None,
95-
Some(theme) => {
96-
if theme.is_empty() {
97-
// no theme? uss css classes
98-
adapter = SyntectAdapter::new(None);
99-
syntax_highlighter = Some(&adapter);
100-
} else {
101-
let path = match rb_plugins.get(Symbol::new(SYNTAX_HIGHLIGHTER_PLUGIN)) {
102-
Some(syntax_highlighter_options) => {
103-
fetch_syntax_highlighter_path(syntax_highlighter_options)?
104-
}
105-
None => PathBuf::from("".to_string()), // no `syntax_highlighter:` defined
106-
};
107-
108-
if path.exists() {
109-
if !path.is_dir() {
110-
return Err(Error::new(
111-
exception::arg_error(),
112-
"`path` needs to be a directory",
113-
));
114-
}
115-
116-
let builder = SyntectAdapterBuilder::new();
117-
let mut ts = ThemeSet::load_defaults();
118-
119-
match ts.add_from_folder(&path) {
120-
Ok(_) => {}
121-
Err(e) => {
122-
return Err(Error::new(
123-
exception::arg_error(),
124-
format!("failed to load theme set from path: {e}"),
125-
));
126-
}
127-
}
128-
129-
// check if the theme exists in the dir
130-
match ts.themes.get(&theme) {
131-
Some(theme) => theme,
132-
None => {
133-
return Err(Error::new(
134-
exception::arg_error(),
135-
format!("theme `{}` does not exist", theme),
136-
));
137-
}
138-
};
139-
140-
adapter = builder.theme_set(ts).theme(&theme).build();
141-
142-
syntax_highlighter = Some(&adapter);
143-
} else {
144-
// no path? default theme lookup
145-
ThemeSet::load_defaults()
146-
.themes
147-
.get(&theme)
148-
.ok_or_else(|| {
149-
Error::new(
150-
exception::arg_error(),
151-
format!("theme `{}` does not exist", theme),
152-
)
153-
})?;
154-
adapter = SyntectAdapter::new(Some(&theme));
155-
syntax_highlighter = Some(&adapter);
156-
}
157-
}
158-
}
159-
}
160-
comrak_plugins.render.codefence_syntax_highlighter = syntax_highlighter;
161-
162-
Ok(markdown_to_html_with_plugins(
163-
&rb_commonmark,
164-
&comrak_options,
165-
&comrak_plugins,
166-
))
167-
} else {
168-
Ok(markdown_to_html(&rb_commonmark, &comrak_options))
169-
}
89+
Ok(comrak_options)
17090
}
17191

17292
#[magnus::init]

ext/commonmarker/src/node.rs

+50-21
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1+
use comrak::arena_tree::Node as ComrakNode;
12
use comrak::nodes::{
23
Ast as ComrakAst, AstNode as ComrakAstNode, ListDelimType, ListType, NodeCode, NodeCodeBlock,
34
NodeDescriptionItem, NodeFootnoteDefinition, NodeFootnoteReference, NodeHeading, NodeHtmlBlock,
45
NodeLink, NodeList, NodeMath, NodeMultilineBlockQuote, NodeShortCode, NodeTable,
56
NodeValue as ComrakNodeValue, NodeWikiLink, TableAlignment,
67
};
7-
use comrak::{arena_tree::Node as ComrakNode, ComrakOptions};
88
use magnus::RArray;
9-
use magnus::{
10-
function, method, r_hash::ForEach, scan_args, Module, Object, RHash, RModule, Symbol, Value,
11-
};
9+
use magnus::{function, method, scan_args, Module, Object, RHash, RModule, Symbol, Value};
1210
use rctree::Node;
1311
use typed_arena::Arena;
1412

1513
use std::cell::RefCell;
1614

17-
use crate::options::iterate_options_hash;
15+
use crate::format_options;
16+
17+
use crate::plugins::syntax_highlighting::construct_syntax_highlighter_from_plugin;
1818

1919
#[derive(Debug, Clone)]
2020
#[magnus::wrap(class = "Commonmarker::Node::Ast", size, mark)]
@@ -905,15 +905,24 @@ impl CommonmarkerNode {
905905
&[],
906906
&["options", "plugins"],
907907
)?;
908-
let (rb_options, _rb_plugins) = kwargs.optional;
908+
let (rb_options, rb_plugins) = kwargs.optional;
909+
910+
let comrak_options = match format_options(rb_options) {
911+
Ok(options) => options,
912+
Err(err) => return Err(err),
913+
};
914+
915+
let mut comrak_plugins = comrak::Plugins::default();
909916

910-
let mut comrak_options = ComrakOptions::default();
917+
let syntect_adapter = match construct_syntax_highlighter_from_plugin(rb_plugins) {
918+
Ok(Some(adapter)) => Some(adapter),
919+
Ok(None) => None,
920+
Err(err) => return Err(err),
921+
};
911922

912-
if let Some(rb_options) = rb_options {
913-
rb_options.foreach(|key: Symbol, value: RHash| {
914-
iterate_options_hash(&mut comrak_options, key, value)?;
915-
Ok(ForEach::Continue)
916-
})?;
923+
match syntect_adapter {
924+
Some(ref adapter) => comrak_plugins.render.codefence_syntax_highlighter = Some(adapter),
925+
None => comrak_plugins.render.codefence_syntax_highlighter = None,
917926
}
918927

919928
let arena: Arena<ComrakAstNode> = Arena::new();
@@ -946,7 +955,12 @@ impl CommonmarkerNode {
946955
}
947956

948957
let mut output = vec![];
949-
match comrak::format_html(&comrak_root_node, &comrak_options, &mut output) {
958+
match comrak::format_html_with_plugins(
959+
&comrak_root_node,
960+
&comrak_options,
961+
&mut output,
962+
&comrak_plugins,
963+
) {
950964
Ok(_) => {}
951965
Err(e) => {
952966
return Err(magnus::Error::new(
@@ -973,15 +987,25 @@ impl CommonmarkerNode {
973987
&[],
974988
&["options", "plugins"],
975989
)?;
976-
let (rb_options, _rb_plugins) = kwargs.optional;
990+
let (rb_options, rb_plugins) = kwargs.optional;
991+
992+
let _comrak_options = format_options(rb_options);
993+
let comrak_options = match format_options(rb_options) {
994+
Ok(options) => options,
995+
Err(err) => return Err(err),
996+
};
977997

978-
let mut comrak_options = ComrakOptions::default();
998+
let mut comrak_plugins = comrak::Plugins::default();
999+
1000+
let syntect_adapter = match construct_syntax_highlighter_from_plugin(rb_plugins) {
1001+
Ok(Some(adapter)) => Some(adapter),
1002+
Ok(None) => None,
1003+
Err(err) => return Err(err),
1004+
};
9791005

980-
if let Some(rb_options) = rb_options {
981-
rb_options.foreach(|key: Symbol, value: RHash| {
982-
iterate_options_hash(&mut comrak_options, key, value)?;
983-
Ok(ForEach::Continue)
984-
})?;
1006+
match syntect_adapter {
1007+
Some(ref adapter) => comrak_plugins.render.codefence_syntax_highlighter = Some(adapter),
1008+
None => comrak_plugins.render.codefence_syntax_highlighter = None,
9851009
}
9861010

9871011
let arena: Arena<ComrakAstNode> = Arena::new();
@@ -1014,7 +1038,12 @@ impl CommonmarkerNode {
10141038
}
10151039

10161040
let mut output = vec![];
1017-
match comrak::format_commonmark(&comrak_root_node, &comrak_options, &mut output) {
1041+
match comrak::format_commonmark_with_plugins(
1042+
&comrak_root_node,
1043+
&comrak_options,
1044+
&mut output,
1045+
&comrak_plugins,
1046+
) {
10181047
Ok(_) => {}
10191048
Err(e) => {
10201049
return Err(magnus::Error::new(

ext/commonmarker/src/plugins.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
pub mod syntax_highlighting;
22

33
pub const SYNTAX_HIGHLIGHTER_PLUGIN: &str = "syntax_highlighter";
4+
5+
pub const SYNTAX_HIGHLIGHTER_PLUGIN_THEME_KEY: &str = "theme";
6+
pub const SYNTAX_HIGHLIGHTER_PLUGIN_PATH_KEY: &str = "path";

0 commit comments

Comments
 (0)