commonmarker 2.9.0 → 2.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +83 -40
- data/README.md +35 -17
- data/ext/commonmarker/Cargo.toml +3 -4
- data/ext/commonmarker/src/lib.rs +12 -2
- data/ext/commonmarker/src/nesting.rs +71 -0
- data/ext/commonmarker/src/node.rs +178 -87
- data/ext/commonmarker/src/options.rs +0 -4
- data/ext/commonmarker/src/plugins/syntax_highlighting.rs +9 -5
- data/ext/commonmarker/src/rctree.rs +841 -0
- data/lib/commonmarker/config.rb +3 -3
- data/lib/commonmarker/errors.rb +7 -0
- data/lib/commonmarker/node/inspect.rb +2 -4
- data/lib/commonmarker/node.rb +29 -4
- data/lib/commonmarker/version.rb +1 -1
- data/lib/commonmarker.rb +1 -0
- metadata +5 -30
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use crate::rctree::Node;
|
|
1
2
|
use comrak::arena_tree::Node as ComrakNode;
|
|
2
3
|
use comrak::nodes::{
|
|
3
4
|
AlertType, Ast as ComrakAst, AstNode as ComrakAstNode, ListDelimType, ListType, NodeAlert,
|
|
@@ -8,7 +9,6 @@ use comrak::nodes::{
|
|
|
8
9
|
};
|
|
9
10
|
use magnus::{function, method, scan_args, Module, Object, RHash, RModule, Symbol, Value};
|
|
10
11
|
use magnus::{RArray, Ruby};
|
|
11
|
-
use rctree::Node;
|
|
12
12
|
use typed_arena::Arena;
|
|
13
13
|
|
|
14
14
|
use std::cell::RefCell;
|
|
@@ -31,6 +31,39 @@ pub struct CommonmarkerNode {
|
|
|
31
31
|
/// SAFETY: This is safe because we only access this data when the GVL is held.
|
|
32
32
|
unsafe impl Send for CommonmarkerNode {}
|
|
33
33
|
|
|
34
|
+
/// Reports whether a node value supports a given property, where "property" is
|
|
35
|
+
/// a method name with any trailing `=` or `?` removed.
|
|
36
|
+
///
|
|
37
|
+
/// `None` means the property is not type-dependent at all
|
|
38
|
+
/// (`walk`, `type`, `delete`, ...).
|
|
39
|
+
fn value_supports(value: &ComrakNodeValue, property: &str) -> Option<bool> {
|
|
40
|
+
let supported = match property {
|
|
41
|
+
"string_content" => matches!(
|
|
42
|
+
value,
|
|
43
|
+
ComrakNodeValue::Text(_) | ComrakNodeValue::Code(_) | ComrakNodeValue::CodeBlock(_)
|
|
44
|
+
),
|
|
45
|
+
"literal" => matches!(
|
|
46
|
+
value,
|
|
47
|
+
ComrakNodeValue::Text(_)
|
|
48
|
+
| ComrakNodeValue::Code(_)
|
|
49
|
+
| ComrakNodeValue::CodeBlock(_)
|
|
50
|
+
| ComrakNodeValue::HtmlBlock(_)
|
|
51
|
+
| ComrakNodeValue::HtmlInline(_)
|
|
52
|
+
| ComrakNodeValue::Raw(_)
|
|
53
|
+
| ComrakNodeValue::Math(_)
|
|
54
|
+
| ComrakNodeValue::FrontMatter(_)
|
|
55
|
+
),
|
|
56
|
+
"url" | "title" => matches!(value, ComrakNodeValue::Link(_) | ComrakNodeValue::Image(_)),
|
|
57
|
+
"header_level" => matches!(value, ComrakNodeValue::Heading(_)),
|
|
58
|
+
"list_type" | "list_start" | "list_tight" => matches!(value, ComrakNodeValue::List(_)),
|
|
59
|
+
"fenced" | "fence_info" => matches!(value, ComrakNodeValue::CodeBlock(_)),
|
|
60
|
+
"alert_type" => matches!(value, ComrakNodeValue::Alert(_)),
|
|
61
|
+
_ => return None,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
Some(supported)
|
|
65
|
+
}
|
|
66
|
+
|
|
34
67
|
impl CommonmarkerNode {
|
|
35
68
|
pub fn new(ruby: &Ruby, args: &[Value]) -> Result<Self, magnus::Error> {
|
|
36
69
|
let args = scan_args::scan_args::<_, (), (), (), _, ()>(args)?;
|
|
@@ -566,42 +599,50 @@ impl CommonmarkerNode {
|
|
|
566
599
|
})
|
|
567
600
|
}
|
|
568
601
|
|
|
602
|
+
/// Copies a comrak tree into a Ruby-visible tree, failing if any node sits
|
|
603
|
+
/// more than `max_nesting_depth` levels below the root.
|
|
569
604
|
pub fn new_from_comrak_node<'a>(
|
|
605
|
+
ruby: &Ruby,
|
|
570
606
|
comrak_root_node: &'a ComrakAstNode<'a>,
|
|
607
|
+
max_nesting_depth: usize,
|
|
571
608
|
) -> Result<CommonmarkerNode, magnus::Error> {
|
|
572
|
-
let
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
609
|
+
let commonmarker_root_node = Node::new(CommonmarkerAst {
|
|
610
|
+
data: comrak_root_node.data.borrow().clone(),
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
// Depth-first walk with an explicit stack instead of recursion, so that
|
|
614
|
+
// deeply nested input (e.g. thousands of nested blockquotes) cannot
|
|
615
|
+
// overflow the native stack. Each entry pairs an iterator over a comrak
|
|
616
|
+
// node's remaining children with the copy of that node the children get
|
|
617
|
+
// appended to.
|
|
618
|
+
let mut stack = vec![(comrak_root_node.children(), commonmarker_root_node.clone())];
|
|
619
|
+
|
|
620
|
+
loop {
|
|
621
|
+
// The stack holds one entry per ancestor, so its length is the
|
|
622
|
+
// depth of the next child produced.
|
|
623
|
+
let depth = stack.len();
|
|
624
|
+
let Some((children, parent)) = stack.last_mut() else {
|
|
625
|
+
break;
|
|
626
|
+
};
|
|
627
|
+
let Some(comrak_child) = children.next() else {
|
|
628
|
+
stack.pop();
|
|
629
|
+
continue;
|
|
580
630
|
};
|
|
581
631
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
Ok(_) => {}
|
|
585
|
-
Err(e) => {
|
|
586
|
-
panic!("cannot append node: {}", e);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
632
|
+
if depth > max_nesting_depth {
|
|
633
|
+
return Err(crate::nesting::exceeded_error(ruby, max_nesting_depth));
|
|
589
634
|
}
|
|
590
635
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
for child in comrak_root_node.children() {
|
|
599
|
-
let new_child = iter_nodes(child);
|
|
600
|
-
|
|
601
|
-
commonmarker_root_node.append_child_node(&new_child)?;
|
|
636
|
+
let node = Node::new(CommonmarkerAst {
|
|
637
|
+
data: comrak_child.data.borrow().clone(),
|
|
638
|
+
});
|
|
639
|
+
parent.append(node.clone());
|
|
640
|
+
stack.push((comrak_child.children(), node));
|
|
602
641
|
}
|
|
603
642
|
|
|
604
|
-
Ok(
|
|
643
|
+
Ok(CommonmarkerNode {
|
|
644
|
+
inner: commonmarker_root_node,
|
|
645
|
+
})
|
|
605
646
|
}
|
|
606
647
|
|
|
607
648
|
fn type_to_symbol(ruby: &Ruby, rb_self: &Self) -> Symbol {
|
|
@@ -784,6 +825,63 @@ impl CommonmarkerNode {
|
|
|
784
825
|
}
|
|
785
826
|
}
|
|
786
827
|
|
|
828
|
+
/// Returns `true` or `false` if the given method is only available for
|
|
829
|
+
/// certain node types, and `nil` if its availability does not depend on
|
|
830
|
+
/// the node's type. Backs `Node#respond_to?`.
|
|
831
|
+
fn supports_method(rb_self: &Self, name: Symbol) -> Option<bool> {
|
|
832
|
+
let node = rb_self.inner.borrow();
|
|
833
|
+
let name = name.to_string();
|
|
834
|
+
let property = name.trim_end_matches('=').trim_end_matches('?');
|
|
835
|
+
|
|
836
|
+
value_supports(&node.data.value, property)
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
fn get_literal(ruby: &Ruby, rb_self: &Self) -> Result<String, magnus::Error> {
|
|
840
|
+
let node = rb_self.inner.borrow();
|
|
841
|
+
|
|
842
|
+
match &node.data.value {
|
|
843
|
+
ComrakNodeValue::Text(text) => Ok(text.to_string()),
|
|
844
|
+
ComrakNodeValue::Code(code) => Ok(code.literal.to_string()),
|
|
845
|
+
ComrakNodeValue::CodeBlock(code_block) => Ok(code_block.literal.to_string()),
|
|
846
|
+
ComrakNodeValue::HtmlBlock(html_block) => Ok(html_block.literal.to_string()),
|
|
847
|
+
ComrakNodeValue::HtmlInline(html_inline) => Ok(html_inline.to_string()),
|
|
848
|
+
ComrakNodeValue::Raw(raw) => Ok(raw.to_string()),
|
|
849
|
+
ComrakNodeValue::Math(math) => Ok(math.literal.to_string()),
|
|
850
|
+
ComrakNodeValue::FrontMatter(front_matter) => Ok(front_matter.to_string()),
|
|
851
|
+
_ => Err(magnus::Error::new(
|
|
852
|
+
ruby.exception_type_error(),
|
|
853
|
+
"node does not have a literal",
|
|
854
|
+
)),
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
fn set_literal(
|
|
859
|
+
ruby: &Ruby,
|
|
860
|
+
rb_self: &Self,
|
|
861
|
+
new_literal: String,
|
|
862
|
+
) -> Result<bool, magnus::Error> {
|
|
863
|
+
let mut node = rb_self.inner.borrow_mut();
|
|
864
|
+
|
|
865
|
+
match node.data.value {
|
|
866
|
+
ComrakNodeValue::Text(ref mut text) => *text = new_literal.into(),
|
|
867
|
+
ComrakNodeValue::Code(ref mut code) => code.literal = new_literal,
|
|
868
|
+
ComrakNodeValue::CodeBlock(ref mut code_block) => code_block.literal = new_literal,
|
|
869
|
+
ComrakNodeValue::HtmlBlock(ref mut html_block) => html_block.literal = new_literal,
|
|
870
|
+
ComrakNodeValue::HtmlInline(ref mut html_inline) => *html_inline = new_literal,
|
|
871
|
+
ComrakNodeValue::Raw(ref mut raw) => *raw = new_literal,
|
|
872
|
+
ComrakNodeValue::Math(ref mut math) => math.literal = new_literal,
|
|
873
|
+
ComrakNodeValue::FrontMatter(ref mut front_matter) => *front_matter = new_literal,
|
|
874
|
+
_ => {
|
|
875
|
+
return Err(magnus::Error::new(
|
|
876
|
+
ruby.exception_type_error(),
|
|
877
|
+
"node does not have a literal",
|
|
878
|
+
))
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
Ok(true)
|
|
883
|
+
}
|
|
884
|
+
|
|
787
885
|
fn get_title(ruby: &Ruby, rb_self: &Self) -> Result<String, magnus::Error> {
|
|
788
886
|
let node = rb_self.inner.borrow();
|
|
789
887
|
|
|
@@ -1037,6 +1135,39 @@ impl CommonmarkerNode {
|
|
|
1037
1135
|
}
|
|
1038
1136
|
}
|
|
1039
1137
|
|
|
1138
|
+
/// Copies this node and its descendants into `arena` as a comrak tree so that
|
|
1139
|
+
/// comrak's formatters can render it.
|
|
1140
|
+
///
|
|
1141
|
+
/// Depth-first walk with an explicit stack instead of recursion, so that
|
|
1142
|
+
/// deeply nested input cannot overflow the native stack. Each entry pairs an
|
|
1143
|
+
/// iterator over a node's remaining children with the copy of that node the
|
|
1144
|
+
/// children get appended to.
|
|
1145
|
+
fn to_comrak_node<'a>(&self, arena: &'a Arena<ComrakAstNode<'a>>) -> &'a ComrakAstNode<'a> {
|
|
1146
|
+
let comrak_root_node: &'a ComrakAstNode<'a> = arena.alloc(ComrakNode::new(RefCell::new(
|
|
1147
|
+
self.inner.borrow().data.clone(),
|
|
1148
|
+
)));
|
|
1149
|
+
|
|
1150
|
+
let mut stack = vec![(self.inner.children(), comrak_root_node)];
|
|
1151
|
+
|
|
1152
|
+
loop {
|
|
1153
|
+
let Some((children, parent)) = stack.last_mut() else {
|
|
1154
|
+
break;
|
|
1155
|
+
};
|
|
1156
|
+
let parent: &'a ComrakAstNode<'a> = parent;
|
|
1157
|
+
let Some(child) = children.next() else {
|
|
1158
|
+
stack.pop();
|
|
1159
|
+
continue;
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
let comrak_node: &'a ComrakAstNode<'a> =
|
|
1163
|
+
arena.alloc(ComrakNode::new(RefCell::new(child.borrow().data.clone())));
|
|
1164
|
+
parent.append(comrak_node);
|
|
1165
|
+
stack.push((child.children(), comrak_node));
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
comrak_root_node
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1040
1171
|
fn to_html(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<String, magnus::Error> {
|
|
1041
1172
|
let args = scan_args::scan_args::<(), (), (), (), _, ()>(args)?;
|
|
1042
1173
|
|
|
@@ -1081,42 +1212,18 @@ impl CommonmarkerNode {
|
|
|
1081
1212
|
};
|
|
1082
1213
|
|
|
1083
1214
|
match syntect_adapter {
|
|
1084
|
-
Some(ref adapter) =>
|
|
1215
|
+
Some(ref adapter) => {
|
|
1216
|
+
comrak_plugins.render.codefence_syntax_highlighter = Some(adapter.as_ref())
|
|
1217
|
+
}
|
|
1085
1218
|
None => comrak_plugins.render.codefence_syntax_highlighter = None,
|
|
1086
1219
|
}
|
|
1087
1220
|
|
|
1088
1221
|
let arena: Arena<ComrakAstNode> = Arena::new();
|
|
1089
|
-
|
|
1090
|
-
arena: &'a Arena<comrak::arena_tree::Node<'a, RefCell<ComrakAst>>>,
|
|
1091
|
-
node: &CommonmarkerNode,
|
|
1092
|
-
) -> &'a comrak::arena_tree::Node<'a, std::cell::RefCell<comrak::nodes::Ast>> {
|
|
1093
|
-
let comrak_node: &'a mut ComrakAstNode = arena.alloc(ComrakNode::new(RefCell::new(
|
|
1094
|
-
node.inner.borrow().data.clone(),
|
|
1095
|
-
)));
|
|
1096
|
-
|
|
1097
|
-
for c in node.inner.children() {
|
|
1098
|
-
let child = CommonmarkerNode { inner: c };
|
|
1099
|
-
let child_node = iter_nodes(arena, &child);
|
|
1100
|
-
comrak_node.append(child_node);
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
comrak_node
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
let comrak_root_node: ComrakNode<RefCell<ComrakAst>> =
|
|
1107
|
-
ComrakNode::new(RefCell::new(rb_self.inner.borrow().data.clone()));
|
|
1108
|
-
|
|
1109
|
-
for c in rb_self.inner.children() {
|
|
1110
|
-
let child = CommonmarkerNode { inner: c };
|
|
1111
|
-
|
|
1112
|
-
let new_child = iter_nodes(&arena, &child);
|
|
1113
|
-
|
|
1114
|
-
comrak_root_node.append(new_child);
|
|
1115
|
-
}
|
|
1222
|
+
let comrak_root_node = rb_self.to_comrak_node(&arena);
|
|
1116
1223
|
|
|
1117
1224
|
let mut output = String::new();
|
|
1118
1225
|
match comrak::format_html_with_plugins(
|
|
1119
|
-
|
|
1226
|
+
comrak_root_node,
|
|
1120
1227
|
&comrak_options,
|
|
1121
1228
|
&mut output,
|
|
1122
1229
|
&comrak_plugins,
|
|
@@ -1177,42 +1284,18 @@ impl CommonmarkerNode {
|
|
|
1177
1284
|
};
|
|
1178
1285
|
|
|
1179
1286
|
match syntect_adapter {
|
|
1180
|
-
Some(ref adapter) =>
|
|
1287
|
+
Some(ref adapter) => {
|
|
1288
|
+
comrak_plugins.render.codefence_syntax_highlighter = Some(adapter.as_ref())
|
|
1289
|
+
}
|
|
1181
1290
|
None => comrak_plugins.render.codefence_syntax_highlighter = None,
|
|
1182
1291
|
}
|
|
1183
1292
|
|
|
1184
1293
|
let arena: Arena<ComrakAstNode> = Arena::new();
|
|
1185
|
-
|
|
1186
|
-
arena: &'a Arena<comrak::arena_tree::Node<'a, RefCell<ComrakAst>>>,
|
|
1187
|
-
node: &CommonmarkerNode,
|
|
1188
|
-
) -> &'a comrak::arena_tree::Node<'a, std::cell::RefCell<comrak::nodes::Ast>> {
|
|
1189
|
-
let comrak_node: &'a mut ComrakAstNode = arena.alloc(ComrakNode::new(RefCell::new(
|
|
1190
|
-
node.inner.borrow().data.clone(),
|
|
1191
|
-
)));
|
|
1192
|
-
|
|
1193
|
-
for c in node.inner.children() {
|
|
1194
|
-
let child = CommonmarkerNode { inner: c };
|
|
1195
|
-
let child_node = iter_nodes(arena, &child);
|
|
1196
|
-
comrak_node.append(child_node);
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
comrak_node
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
let comrak_root_node: ComrakNode<RefCell<ComrakAst>> =
|
|
1203
|
-
ComrakNode::new(RefCell::new(rb_self.inner.borrow().data.clone()));
|
|
1204
|
-
|
|
1205
|
-
for c in rb_self.inner.children() {
|
|
1206
|
-
let child = CommonmarkerNode { inner: c };
|
|
1207
|
-
|
|
1208
|
-
let new_child = iter_nodes(&arena, &child);
|
|
1209
|
-
|
|
1210
|
-
comrak_root_node.append(new_child);
|
|
1211
|
-
}
|
|
1294
|
+
let comrak_root_node = rb_self.to_comrak_node(&arena);
|
|
1212
1295
|
|
|
1213
1296
|
let mut output = String::new();
|
|
1214
1297
|
match comrak::format_commonmark_with_plugins(
|
|
1215
|
-
|
|
1298
|
+
comrak_root_node,
|
|
1216
1299
|
&comrak_options,
|
|
1217
1300
|
&mut output,
|
|
1218
1301
|
&comrak_plugins,
|
|
@@ -1221,7 +1304,7 @@ impl CommonmarkerNode {
|
|
|
1221
1304
|
Err(e) => {
|
|
1222
1305
|
return Err(magnus::Error::new(
|
|
1223
1306
|
ruby.exception_runtime_error(),
|
|
1224
|
-
format!("cannot convert into
|
|
1307
|
+
format!("cannot convert into commonmark: {}", e),
|
|
1225
1308
|
));
|
|
1226
1309
|
}
|
|
1227
1310
|
}
|
|
@@ -1292,6 +1375,14 @@ pub fn init(ruby: &Ruby, m_commonmarker: RModule) -> Result<(), magnus::Error> {
|
|
|
1292
1375
|
method!(CommonmarkerNode::set_string_content, 1),
|
|
1293
1376
|
)?;
|
|
1294
1377
|
|
|
1378
|
+
c_node.define_method("literal", method!(CommonmarkerNode::get_literal, 0))?;
|
|
1379
|
+
c_node.define_method("literal=", method!(CommonmarkerNode::set_literal, 1))?;
|
|
1380
|
+
|
|
1381
|
+
c_node.define_method(
|
|
1382
|
+
"node_supports?",
|
|
1383
|
+
method!(CommonmarkerNode::supports_method, 1),
|
|
1384
|
+
)?;
|
|
1385
|
+
|
|
1295
1386
|
c_node.define_method("url", method!(CommonmarkerNode::get_url, 0))?;
|
|
1296
1387
|
c_node.define_method("url=", method!(CommonmarkerNode::set_url, 1))?;
|
|
1297
1388
|
c_node.define_method("title", method!(CommonmarkerNode::get_title, 0))?;
|
|
@@ -117,7 +117,6 @@ pub fn iterate_render_options(comrak_options: &mut comrak::options::Render, opti
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
const EXTENSION_STRIKETHROUGH: &str = "strikethrough";
|
|
120
|
-
const EXTENSION_TAGFILTER: &str = "tagfilter";
|
|
121
120
|
const EXTENSION_TABLE: &str = "table";
|
|
122
121
|
const EXTENSION_AUTOLINK: &str = "autolink";
|
|
123
122
|
const EXTENSION_TASKLIST: &str = "tasklist";
|
|
@@ -156,9 +155,6 @@ pub fn iterate_extension_options(
|
|
|
156
155
|
Cow::Borrowed(EXTENSION_STRIKETHROUGH) => {
|
|
157
156
|
comrak_options.strikethrough = TryConvert::try_convert(value)?;
|
|
158
157
|
}
|
|
159
|
-
Cow::Borrowed(EXTENSION_TAGFILTER) => {
|
|
160
|
-
comrak_options.tagfilter = TryConvert::try_convert(value)?;
|
|
161
|
-
}
|
|
162
158
|
Cow::Borrowed(EXTENSION_TABLE) => {
|
|
163
159
|
comrak_options.table = TryConvert::try_convert(value)?;
|
|
164
160
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
use std::path::PathBuf;
|
|
2
|
+
use std::sync::{Arc, OnceLock};
|
|
2
3
|
|
|
3
4
|
use comrak::plugins::syntect::{SyntectAdapter, SyntectAdapterBuilder};
|
|
4
5
|
|
|
@@ -11,7 +12,7 @@ use crate::EMPTY_STR;
|
|
|
11
12
|
pub fn construct_syntax_highlighter_from_plugin(
|
|
12
13
|
ruby: &Ruby,
|
|
13
14
|
rb_plugins: Option<RHash>,
|
|
14
|
-
) -> Result<Option<SyntectAdapter
|
|
15
|
+
) -> Result<Option<Arc<SyntectAdapter>>, magnus::Error> {
|
|
15
16
|
match rb_plugins {
|
|
16
17
|
None => Ok(None),
|
|
17
18
|
Some(rb_plugins) => {
|
|
@@ -34,8 +35,11 @@ pub fn construct_syntax_highlighter_from_plugin(
|
|
|
34
35
|
Some(theme) => {
|
|
35
36
|
if theme.is_empty() {
|
|
36
37
|
// no theme? uss css classes
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
// Avoid reloading syntax sets and recompiling regexes for every CSS-mode render.
|
|
39
|
+
static CSS_ADAPTER: OnceLock<Arc<SyntectAdapter>> = OnceLock::new();
|
|
40
|
+
Ok(Some(Arc::clone(
|
|
41
|
+
CSS_ADAPTER.get_or_init(|| Arc::new(SyntectAdapter::new(None))),
|
|
42
|
+
)))
|
|
39
43
|
} else {
|
|
40
44
|
let path = match rb_plugins
|
|
41
45
|
.get(ruby.to_symbol(super::SYNTAX_HIGHLIGHTER_PLUGIN))
|
|
@@ -80,7 +84,7 @@ pub fn construct_syntax_highlighter_from_plugin(
|
|
|
80
84
|
|
|
81
85
|
adapter = builder.theme_set(ts).theme(&theme).build();
|
|
82
86
|
|
|
83
|
-
Ok(Some(adapter))
|
|
87
|
+
Ok(Some(Arc::new(adapter)))
|
|
84
88
|
} else {
|
|
85
89
|
// no path? default theme lookup
|
|
86
90
|
ThemeSet::load_defaults()
|
|
@@ -93,7 +97,7 @@ pub fn construct_syntax_highlighter_from_plugin(
|
|
|
93
97
|
)
|
|
94
98
|
})?;
|
|
95
99
|
adapter = SyntectAdapter::new(Some(&theme));
|
|
96
|
-
Ok(Some(adapter))
|
|
100
|
+
Ok(Some(Arc::new(adapter)))
|
|
97
101
|
}
|
|
98
102
|
}
|
|
99
103
|
}
|