}
flatten [msubst $content]
} finally {
catch {
interp delete $interp
}
}
}
proc tclmark::msubst content {
variable interp
variable token
# Pass through already processed content marked with the
# token.
set tokenLen [string length $token]
if {[string range $content 0 $tokenLen-1] eq $token} {
return $content
}
set r [interp invokehidden \
$interp \
subst -nobackslashes -novariables $content \
]
if {$r eq $content} {
return [node text $content]
}
return [node tree $r]
}
proc tclmark::node {tag args} {
variable token
list $token $tag $args
}
proc tclmark::flatten node {
variable token
if {[llength $node] != 3} {
error [list not three elements: $node]
}
lassign $node nodeToken tag data
if {$nodeToken ne $token} {
error [list invalid token in $node]
}
switch -- $tag {
html {
lindex $data 0
}
text {
entities [lindex $data 0]
}
tree {
join [lmap el $data {
flatten $el
}] {}
}
default {
error [list unknown tag: $tag]
}
}
}
proc tclmark::entities text {
string map {
& &
< <
> >
\" "
' '
} $text
}
proc tclmark::cmd::b content {
node tree [node html <b>] [msubst $content] [node html </b>]
}
proc tclmark::cmd::i content {
node tree [node html <i>] [msubst $content] [node html </i>]
}
proc tclmark::generic-list {tag xs} {
if {$tag ni {nl ol}} {
error [list invalid tag: $tag
}
node tree \
[node html <$tag>] \
{*}[msubst-and-wrap li $xs] \
[node html </$tag>] \
}
proc tclmark::cmd::1 args { tailcall generic-list nl $args }
proc tclmark::cmd::* args { tailcall generic-list ol $args }
proc tclmark::msubst-and-wrap {tag items} {
lmap item $items {
node tree [node html <$tag>] [msubst $item] [node html </$tag>]
}
}
proc tclmark::run-tests {} {
set stats [dict create total 0 passed 0 failed 0]
proc test {name script arrow expected} {
upvar stats stats
dict incr stats total
catch $script result
set matched [switch -- $arrow {
-> { expr {$result eq $expected} }
->* { string match $expected $result }
->$ { regexp -- $expected $result }
default {
return -code error \
-errorcode {JIMLIB TEST BAD-ARROW} \
[list unknown arrow: $arrow]
}
}]
if {!$matched} {
set error {}
append error "\n>>>>> $name failed: [list $script]\n"
append error " got: [list $result]\n"
append error " expected: [list $expected]"
if {$arrow ne {->}} {
append error "\n match: $arrow"
}
dict incr stats failed
puts stderr $error
return