sourceafFandocViewer::FandocResource.fan

using flux::Resource
using gfx::Image
using web::WebOutStream
using compilerDoc::Doc
using compilerDoc::DocPod
using compilerDoc::DocRenderer
using compilerDoc::DocTopIndex
using compilerDoc::UnknownDocErr

** A Flux wrapper around an Fandoc URI, as resolved by `FandocScheme`.
class FandocResource : Resource {
    private static const FandocEnv  docEnv  := FandocEnv()

    override Uri uri
    Doc doc
    
    new make(Uri uri, Obj? type) { 
        isTopIndex := (uri.host == null || uri.host.isEmpty) 
        this.doc = isTopIndex ? topIndex : loadFrom(uri)
        this.uri = uri
    }
    
    override Str name() {
        doc.isTopIndex ? "Fantom Viewer" : "${doc.space}::${doc.docName}" 
    }
    
    override Image icon() {
        Image(FandocResource#.pod.uri + `/res/icons/icoFantom.png`)
    }
    
    ** Renders the `compilerDoc::Doc` to a HTML Str.
    Str toHtml() {
        buff    := StrBuf()
        webOut  := WebOutStream(buff.out)
        render  := (DocRenderer) doc.renderer.make([docEnv, webOut, doc])
        render.writeDoc
        return buff.toStr
    }
    
    private Doc topIndex() {
        DocTopIndex() {
            it.spaces = Pod.list.map { 
                docEnv.space(it.name)
            }
        }
    }
    
    private Doc loadFrom(Uri uri) {
        podFile := Env.cur.findPodFile(uri.auth)
        // we get a nice 'Pod file not found err' is auth / pod doesn't exist
        docPod  := DocPod.load(podFile)
        doc     := docPod.doc(uri.name, false)
        
        if (doc == null) {
            docNames := [,]
            docPod.eachDoc { docNames.add(it.docName) }
            availableValues := availableValues("Pod Documents", docNames)
            throw UnknownDocErr("${docPod.name}::${uri.name} - $availableValues")
        }
        
        return doc
    }
    
    private Str availableValues(Str valueType, Obj[] values) {
        vals := values.map |Obj? value->Str?| { value?.toStr }.exclude |value| { value == null }.join(", \n    ")
        return " Available $valueType: \n    ${vals}"
    }
}