Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions ext/markly/markly.c
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,36 @@ static VALUE rb_node_set_fence_info(VALUE self, VALUE info) {
return Qnil;
}

/*
* Public: Gets fencing details for the current node.
*
* Returns a {Hash} with `:info`, `:length`, `:character`, and `:offset` keys
* for fenced code blocks, `nil` otherwise.
*/
static VALUE rb_node_get_fenced(VALUE self) {
const char *fence_info;
int fence_length = 0;
int fence_offset = 0;
char fence_character = '\0';
cmark_node *node;
VALUE result;
TypedData_Get_Struct(self, cmark_node, &rb_Markly_Node_Type, node);

if (!cmark_node_get_fenced(node, &fence_length, &fence_offset, &fence_character)) {
return Qnil;
}

fence_info = cmark_node_get_fence_info(node);

result = rb_hash_new();
rb_hash_aset(result, CSTR2SYM("info"), fence_info ? rb_str_new2(fence_info) : rb_str_new("", 0));
rb_hash_aset(result, CSTR2SYM("length"), INT2NUM(fence_length));
rb_hash_aset(result, CSTR2SYM("character"), rb_str_new(&fence_character, 1));
rb_hash_aset(result, CSTR2SYM("offset"), INT2NUM(fence_offset));

return result;
}

static VALUE rb_node_get_tasklist_item_checked(VALUE self) {
int tasklist_state;
cmark_node *node;
Expand Down Expand Up @@ -1242,6 +1272,7 @@ __attribute__((visibility("default"))) void Init_markly(void) {
rb_define_method(rb_Markly_Node, "list_tight=", rb_node_set_list_tight, 1);
rb_define_method(rb_Markly_Node, "fence_info", rb_node_get_fence_info, 0);
rb_define_method(rb_Markly_Node, "fence_info=", rb_node_set_fence_info, 1);
rb_define_method(rb_Markly_Node, "fenced", rb_node_get_fenced, 0);
rb_define_method(rb_Markly_Node, "table_alignments", rb_node_get_table_alignments, 0);
rb_define_method(rb_Markly_Node, "tasklist_item_checked?", rb_node_get_tasklist_item_checked, 0);
rb_define_method(rb_Markly_Node, "tasklist_item_checked=", rb_node_set_tasklist_item_checked, 1);
Expand Down
33 changes: 33 additions & 0 deletions test/markly/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,39 @@
end
end

with "#fenced" do
let(:fenced_backtick_node) {Markly.parse("``` ruby\nputs 'wow'\n```").first_child}
let(:fenced_tilde_node) {Markly.parse("~~~ ruby\nputs 'wow'\n~~~").first_child}
let(:indented_code_node) {Markly.parse(" puts 'wow'").first_child}
let(:paragraph_node) {Markly.parse("hello").first_child}

it "returns fenced metadata for backtick fences" do
expect(fenced_backtick_node.fenced).to be == {
info: "ruby",
length: 3,
character: "`",
offset: 0
}
end

it "returns fenced metadata for tilde fences" do
expect(fenced_tilde_node.fenced).to be == {
info: "ruby",
length: 3,
character: "~",
offset: 0
}
end

it "returns nil for non-fenced code blocks" do
expect(indented_code_node.fenced).to be_nil
end

it "returns nil for non-code nodes" do
expect(paragraph_node.fenced).to be_nil
end
end

with "#find_header" do
let(:document) {Markly.parse("# Heading\n\n## Subheading")}

Expand Down