markdown code
This commit is contained in:
1
lib/data/markdownrenderer/readme.md
Normal file
1
lib/data/markdownrenderer/readme.md
Normal file
@@ -0,0 +1 @@
|
||||
depends on https://github.com/vlang/markdown/tree/master
|
||||
194
lib/data/markdownrenderer/structure_renderer.v
Normal file
194
lib/data/markdownrenderer/structure_renderer.v
Normal file
@@ -0,0 +1,194 @@
|
||||
module markdownrenderer
|
||||
|
||||
import markdown
|
||||
|
||||
import strings
|
||||
|
||||
// Helper functions to extract information from C structs
|
||||
fn get_md_attribute_string(attr C.MD_ATTRIBUTE) ?string {
|
||||
unsafe {
|
||||
if attr.text == nil || attr.size == 0 {
|
||||
return none
|
||||
}
|
||||
return attr.text.vstring_with_len(int(attr.size))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_heading_level(detail voidptr) int {
|
||||
unsafe {
|
||||
h_detail := &C.MD_BLOCK_H_DETAIL(detail)
|
||||
return int(h_detail.level)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_code_language(detail voidptr) ?string {
|
||||
unsafe {
|
||||
code_detail := &C.MD_BLOCK_CODE_DETAIL(detail)
|
||||
return get_md_attribute_string(code_detail.lang)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_ul_details(detail voidptr) (bool, string) {
|
||||
unsafe {
|
||||
ul_detail := &C.MD_BLOCK_UL_DETAIL(detail)
|
||||
is_tight := ul_detail.is_tight != 0
|
||||
mark := ul_detail.mark.ascii_str()
|
||||
return is_tight, mark
|
||||
}
|
||||
}
|
||||
|
||||
fn get_ol_details(detail voidptr) (int, bool) {
|
||||
unsafe {
|
||||
ol_detail := &C.MD_BLOCK_OL_DETAIL(detail)
|
||||
start := int(ol_detail.start)
|
||||
is_tight := ol_detail.is_tight != 0
|
||||
return start, is_tight
|
||||
}
|
||||
}
|
||||
|
||||
fn get_link_details(detail voidptr) (?string, ?string) {
|
||||
unsafe {
|
||||
a_detail := &C.MD_SPAN_A_DETAIL(detail)
|
||||
href := get_md_attribute_string(a_detail.href)
|
||||
title := get_md_attribute_string(a_detail.title)
|
||||
return href, title
|
||||
}
|
||||
}
|
||||
|
||||
fn get_image_details(detail voidptr) (?string, ?string) {
|
||||
unsafe {
|
||||
img_detail := &C.MD_SPAN_IMG_DETAIL(detail)
|
||||
src := get_md_attribute_string(img_detail.src)
|
||||
title := get_md_attribute_string(img_detail.title)
|
||||
return src, title
|
||||
}
|
||||
}
|
||||
|
||||
fn get_wikilink_target(detail voidptr) ?string {
|
||||
unsafe {
|
||||
wl_detail := &C.MD_SPAN_WIKILINK_DETAIL(detail)
|
||||
return get_md_attribute_string(wl_detail.target)
|
||||
}
|
||||
}
|
||||
|
||||
// StructureRenderer is a custom renderer that outputs the structure of a markdown document
|
||||
pub struct StructureRenderer {
|
||||
mut:
|
||||
writer strings.Builder = strings.new_builder(200)
|
||||
indent int // Track indentation level for nested elements
|
||||
}
|
||||
|
||||
pub fn (mut sr StructureRenderer) str() string {
|
||||
return sr.writer.str()
|
||||
}
|
||||
|
||||
fn (mut sr StructureRenderer) enter_block(typ markdown.MD_BLOCKTYPE, detail voidptr) ? {
|
||||
// Add indentation based on current level
|
||||
sr.writer.write_string(strings.repeat(` `, sr.indent * 2))
|
||||
|
||||
// Output the block type
|
||||
sr.writer.write_string('BLOCK[${typ}]: ')
|
||||
|
||||
// Add specific details based on block type
|
||||
match typ {
|
||||
.md_block_h {
|
||||
level := get_heading_level(detail)
|
||||
sr.writer.write_string('Level ${level}')
|
||||
}
|
||||
.md_block_code {
|
||||
if lang := get_code_language(detail) {
|
||||
sr.writer.write_string('Language: ${lang}')
|
||||
} else {
|
||||
sr.writer.write_string('No language specified')
|
||||
}
|
||||
}
|
||||
.md_block_ul {
|
||||
is_tight, mark := get_ul_details(detail)
|
||||
sr.writer.write_string('Tight: ${is_tight}, Mark: ${mark}')
|
||||
}
|
||||
.md_block_ol {
|
||||
start, is_tight := get_ol_details(detail)
|
||||
sr.writer.write_string('Start: ${start}, Tight: ${is_tight}')
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
||||
sr.writer.write_u8(`\n`)
|
||||
sr.indent++
|
||||
}
|
||||
|
||||
fn (mut sr StructureRenderer) leave_block(typ markdown.MD_BLOCKTYPE, _ voidptr) ? {
|
||||
sr.indent--
|
||||
}
|
||||
|
||||
fn (mut sr StructureRenderer) enter_span(typ markdown.MD_SPANTYPE, detail voidptr) ? {
|
||||
// Add indentation based on current level
|
||||
sr.writer.write_string(strings.repeat(` `, sr.indent * 2))
|
||||
|
||||
// Output the span type
|
||||
sr.writer.write_string('SPAN[${typ}]: ')
|
||||
|
||||
// Add specific details based on span type
|
||||
match typ {
|
||||
.md_span_a {
|
||||
href, title := get_link_details(detail)
|
||||
if href != none {
|
||||
sr.writer.write_string('Link: ${href}')
|
||||
}
|
||||
if title != none {
|
||||
sr.writer.write_string(', Title: ${title}')
|
||||
}
|
||||
}
|
||||
.md_span_img {
|
||||
src, title := get_image_details(detail)
|
||||
if src != none {
|
||||
sr.writer.write_string('Source: ${src}')
|
||||
}
|
||||
if title != none {
|
||||
sr.writer.write_string(', Title: ${title}')
|
||||
}
|
||||
}
|
||||
.md_span_wikilink {
|
||||
if target := get_wikilink_target(detail) {
|
||||
sr.writer.write_string('Target: ${target}')
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
||||
sr.writer.write_u8(`\n`)
|
||||
sr.indent++
|
||||
}
|
||||
|
||||
fn (mut sr StructureRenderer) leave_span(typ markdown.MD_SPANTYPE, _ voidptr) ? {
|
||||
sr.indent--
|
||||
}
|
||||
|
||||
fn (mut sr StructureRenderer) text(typ markdown.MD_TEXTTYPE, text string) ? {
|
||||
if text.trim_space() == '' {
|
||||
return
|
||||
}
|
||||
|
||||
// Add indentation based on current level
|
||||
sr.writer.write_string(strings.repeat(` `, sr.indent * 2))
|
||||
|
||||
// Output the text type
|
||||
sr.writer.write_string('TEXT[${typ}]: ')
|
||||
|
||||
// Add the text content (truncate if too long)
|
||||
content := if text.len > 50 { text[..50] + '...' } else { text }
|
||||
sr.writer.write_string(content.replace('\n', '\\n'))
|
||||
|
||||
sr.writer.write_u8(`\n`)
|
||||
}
|
||||
|
||||
fn (mut sr StructureRenderer) debug_log(msg string) {
|
||||
println(msg)
|
||||
}
|
||||
|
||||
// to_structure renders a markdown string and returns its structure
|
||||
pub fn to_structure(input string) string {
|
||||
mut structure_renderer := StructureRenderer{}
|
||||
out := markdown.render(input, mut structure_renderer) or { '' }
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user