Index: library/lib/doc-tools.tcl
===================================================================
diff -u -rcabb7fe9c303839d53970b59262f9ae416aef2eb -r5f765b6d8713f416a443cc2367c3a47903cc2f83
--- library/lib/doc-tools.tcl (.../doc-tools.tcl) (revision cabb7fe9c303839d53970b59262f9ae416aef2eb)
+++ library/lib/doc-tools.tcl (.../doc-tools.tcl) (revision 5f765b6d8713f416a443cc2367c3a47903cc2f83)
@@ -383,7 +383,8 @@
set r [dict create]
# puts stderr SLOTS=$slots
foreach s $slots {
- if {![$s info is type ::nx::doc::PartAttribute] || ![$s eval {info exists :part_class}]} continue;
+ # [$s info is type ::nx::doc::PartAttribute]
+ if {![::nsf::objectproperty $s type ::nx::doc::PartAttribute] || ![$s eval {info exists :part_class}]} continue;
set accessor [$s name]
# puts stderr "PROCESSING ACCESSOR $accessor, [info exists :$accessor]"
if {[info exists :$accessor]} {
@@ -424,19 +425,22 @@
# performs substitution on it. The substitution is not essential,
# but looks for now convenient.
#
- :method text {-as_list:switch} {
+
+ :method as_list {} {
if {[info exists :@doc] && ${:@doc} ne ""} {
- set doc ${:@doc}
- set non_empty_elements [lsearch -all -not -exact $doc ""]
- set doc [lrange $doc [lindex $non_empty_elements 0] [lindex $non_empty_elements end]]
- if {$as_list} {
- return $doc
- } else {
- return [subst [join $doc " "]]
- }
+ set non_empty_elements [lsearch -all -not -exact ${:@doc} ""]
+ return [lrange ${:@doc} [lindex $non_empty_elements 0] [lindex $non_empty_elements end]]
}
}
+ :method as_text {} {
+ set doc [list]
+ foreach l [:as_list] {
+ lappend doc [string trimleft $l]
+ }
+ return [subst [join $doc " "]]
+ }
+
:method filename {} {
return [[:info class] tag]_[string trimleft [string map {:: __} ${:name}] "_"]
}
@@ -846,7 +850,40 @@
namespace eval ::nx::doc {
- Class create TemplateData {
+ Class create TemplateDataClass -superclass Class {
+ :method find_asset_path {{-subdir library/lib/doc-assets}} {
+ # This helper tries to identify the file system path of the
+ # asset ressources.
+ #
+ # @param -subdir Denotes the name of the sub-directory to look for
+ foreach dir $::auto_path {
+ set assets [file normalize [file join $dir $subdir]]
+ if {[file exists $assets]} {
+ return $assets
+ }
+ }
+ }
+
+ :method read_tmpl {path} {
+ if {[file pathtype $path] ne "absolute"} {
+ set assetdir [:find_asset_path]
+ set tmpl [file join $assetdir $path]
+ } else {
+ set tmpl [file normalize $path]
+ }
+ if {![file exists $tmpl] || ![file isfile $tmpl]} {
+ error "The template file '$path' was not found."
+ }
+ set fh [open $tmpl r]
+ set content [read $fh]
+ catch {close $fh}
+ return $content
+ }
+
+ }
+
+
+ TemplateDataClass create BaseTemplateData {
# This mixin class realises a rudimentary templating language to
# be used in nx::doc templates. It realises language expressions
# to verify the existence of variables and simple loop constructs
@@ -915,136 +952,157 @@
uplevel 1 [list subst [[::nsf::current class] read_tmpl $template]]
}
- #
- # TODO: This should turn into a hook, the output
- # specificities should move in a refinement of TemplateData, e.g.,
- # DefaultHtmlTemplateData or the like.
- #
- :method fit {str max {placeholder "..."}} {
- if {[llength [split $str ""]] < $max} {
- return $str;
- }
- set redux [llength [split $placeholder ""]]
- set margin [expr {($max-$redux)/2}]
- return "[string range $str 0 [expr {$margin-1}]]$placeholder[string range $str end-[expr {$margin+1}] end]"
+ :method code args {
+ error "Subclass responsibility: You must provide a method definition of '[current method]' in a proper subclass"
}
- :method list_structural_features {} {
- set entry {{"access": "$access", "host": "$host", "name": "$name", "url": "$url", "type": "$type"}}
- set entries [list]
- if {[:info is type ::nx::doc::@package]} {
- set features [list @object @command]
- foreach feature $features {
- set instances [sorted [$feature info instances] name]
- foreach inst $instances {
- set access ""
- set host [:name]
- set name [$inst name]
- set url "[$inst filename].html"
- set type [$feature tag]
- lappend entries [subst $entry]
- }
+ :method link args {
+ error "Subclass responsibility: You must provide a method definition of '[current method]' in a proper subclass"
+ }
+
+ set :markup_map(sub) {
+ "{{{" "\[:code \{"
+ "}}}" "\}\]"
+ "{{" "\[:link "
+ "}}" "\]"
+ }
+
+ set :markup_map(unescape) {
+ "\\{" "{"
+ "\\}" "}"
+ "\\#" "#"
+ }
+
+ :method map {line set} {
+ set line [string map [[::nsf::current class] eval [list set :markup_map($set)]] $line]
+ }
+
+ :method as_list {} {
+ set preprocessed [list]
+ set is_code_block 0
+ foreach line [next] {
+ if {[regsub -- {^\s*(\{\{\{)\s*$} $line "\[:code -inline false \{" line] || \
+ (${is_code_block} && [regsub -- {^\s*(\}\}\})\s*$} $line "\}\]" line])} {
+ set is_code_block [expr {!$is_code_block}]
+ append line \n
+ } elseif {${is_code_block}} {
+ # set line [:map $line unescape]
+ append line \n
+ } else {
+ # set line [:map $line sub]
+ # set line [:map $line unescape]
+ set line [string trimleft $line]
+ if {$line eq {}} {
+ set line "\n\n"
+ }
+ }
+ lappend preprocessed $line
}
- } elseif {[:info is type ::nx::doc::@object]} {
- # TODO: fix support for @object-method!
- set features [list @method @param]
- foreach feature $features {
- if {[info exists :$feature]} {
- set instances [sorted [:$feature] name]
+ return $preprocessed
+ }
+
+ :method as_text {} {
+ set preprocessed [join [:as_list] " "]
+ set preprocessed [:map $preprocessed sub]
+ set preprocessed [:map $preprocessed unescape]
+ return [subst $preprocessed]
+ }
+
+ }
+
+ #
+ # A default TemplateData implementation, targeting the derived YUI
+ # Doc templates.
+ #
+
+ TemplateDataClass create NxDocTemplateData -superclass BaseTemplateData {
+ :method fit {str max {placeholder "..."}} {
+ if {[llength [split $str ""]] < $max} {
+ return $str;
+ }
+ set redux [llength [split $placeholder ""]]
+ set margin [expr {($max-$redux)/2}]
+ return "[string range $str 0 [expr {$margin-1}]]$placeholder[string range $str end-[expr {$margin+1}] end]"
+ }
+
+ :method list_structural_features {} {
+ set entry {{"access": "$access", "host": "$host", "name": "$name", "url": "$url", "type": "$type"}}
+ set entries [list]
+ if {[:info is type ::nx::doc::@package]} {
+ set features [list @object @command]
+ foreach feature $features {
+ set instances [sorted [$feature info instances] name]
foreach inst $instances {
- set access [expr {[info exists :@modifier]?[:@modifier]:""}]
+ set access ""
set host [:name]
set name [$inst name]
- set url "[:filename].html#[$feature tag]_[$inst name]"
+ set url "[$inst filename].html"
set type [$feature tag]
lappend entries [subst $entry]
}
}
- }
- } elseif {[:info is type ::nx::doc::@command]} {
- set features @subcommand
- foreach feature $features {
- if {[info exists :$feature]} {
- set instances [sorted [set :$feature] name]
- foreach inst $instances {
- set access ""
- set host ${:name}
- set name [$inst name]
- set url "[:filename].html#[$feature tag]_[$inst name]"
- set type [$feature tag]
- lappend entries [subst $entry]
+ } elseif {[:info is type ::nx::doc::@object]} {
+ # TODO: fix support for @object-method!
+ set features [list @method @param]
+ foreach feature $features {
+ if {[info exists :$feature]} {
+ set instances [sorted [:$feature] name]
+ foreach inst $instances {
+ set access [expr {[info exists :@modifier]?[:@modifier]:""}]
+ set host [:name]
+ set name [$inst name]
+ set url "[:filename].html#[$feature tag]_[$inst name]"
+ set type [$feature tag]
+ lappend entries [subst $entry]
+ }
}
}
+ } elseif {[:info is type ::nx::doc::@command]} {
+ set features @subcommand
+ foreach feature $features {
+ if {[info exists :$feature]} {
+ set instances [sorted [set :$feature] name]
+ foreach inst $instances {
+ set access ""
+ set host ${:name}
+ set name [$inst name]
+ set url "[:filename].html#[$feature tag]_[$inst name]"
+ set type [$feature tag]
+ lappend entries [subst $entry]
+ }
+ }
+ }
}
+ return "\[[join $entries ,\n]\]"
}
- return "\[[join $entries ,\n]\]"
- }
-
- :method code {{-inline true} script} {
- return [expr {$inline?"$script
":"
$script"}] - } - - :method link {entity_type args} { - set id [$entity_type id {*}$args] - if {![::nsf::is $id object]} return; - set pof "" - if {[$id info is type ::nx::doc::Part]} { - set pof "[[$id partof] name]#" - set filename [[$id partof] filename] - } else { - set filename [$id filename] + + # + # TODO: This should turn into a hook, the output + # specificities should move in a refinement of TemplateData, e.g., + # DefaultHtmlTemplateData or the like. + # + + :method code {{-inline true} script} { + return [expr {$inline?"
$script
":"$script"}] } - return "$pof[$id name]" - } - - :method text {} { - # Provide \n replacements for empty lines according to the - # rendering frontend (e.g., in HTML ->