Changeset 2118

Show
Ignore:
Timestamp:
06/16/09 14:57:39 (9 months ago)
Author:
drobilla
Message:

Specgen improvements.

Location:
trunk
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/lv2/ext/port_groups/lv2_port_groups.ttl

    r2112 r2118  
    2222# OTHER DEALINGS IN THE SOFTWARE. 
    2323 
    24 @prefix pg:   <http://lv2plug.in/ns/dev/port-groups#> . 
     24@prefix pg:   <http://lv2plug.in/ns/ext/port-groups#> . 
    2525@prefix lv2:  <http://lv2plug.in/ns/lv2core#> . 
    2626@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . 
     
    3131@prefix foaf: <http://xmlns.com/foaf/0.1/> . 
    3232 
    33 <http://lv2plug.in/ns/dev/port-groups> a lv2:Specification ; 
     33<http://lv2plug.in/ns/ext/port-groups> a lv2:Specification ; 
    3434        doap:license <http://usefulinc.com/doap/licenses/mit> ; 
    3535        doap:name       "LV2 Port Groups" ; 
    36         rdfs:comment "Defines meaningful groupings of LV2 ports" ; 
     36        rdfs:comment "Defines semantic groupings of LV2 ports" ; 
    3737        doap:maintainer [ 
    3838                a foaf:Person ; 
  • trunk/lv2specgen/lv2specgen.py

    r2114 r2118  
    33# 
    44# lv2specgen, an LV2 extension specification page generator 
    5 # 
    65# Copyright (c) 2009 Dave Robillard <dave@drobilla.net> 
    76# 
     
    8079          } 
    8180 
    82 rdf = RDF.NS('http://www.w3.org/1999/02/22-rdf-syntax-ns#') 
     81rdf  = RDF.NS('http://www.w3.org/1999/02/22-rdf-syntax-ns#') 
    8382rdfs = RDF.NS('http://www.w3.org/2000/01/rdf-schema#') 
    84 owl = RDF.NS('http://www.w3.org/2002/07/owl#') 
    85 vs = RDF.NS('http://www.w3.org/2003/06/sw-vocab-status/ns#') 
    86 lv2 = RDF.NS('http://lv2plug.in/ns/lv2core#') 
     83owl  = RDF.NS('http://www.w3.org/2002/07/owl#') 
     84vs   = RDF.NS('http://www.w3.org/2003/06/sw-vocab-status/ns#') 
     85lv2  = RDF.NS('http://lv2plug.in/ns/lv2core#') 
    8786doap = RDF.NS('http://usefulinc.com/ns/doap#') 
    8887foaf = RDF.NS('http://xmlns.com/foaf/0.1/') 
     
    177176            k = getTermLink(str(st.object.uri), term, rdfs.subPropertyOf) 
    178177            rlist += "<dd>%s</dd>" % k 
    179         doc += "<dt>sub-property-of:</dt> %s" % rlist 
     178        doc += "<dt>Sub-property of</dt> %s" % rlist 
    180179 
    181180    #domain stuff 
     
    193192                domainsdoc += "<dd>%s</dd>" % getTermLink(str(d.object.uri), term, rdfs.domain) 
    194193    if (len(domainsdoc)>0): 
    195         doc += "<dt>Domain:</dt> %s" % domainsdoc 
     194        doc += "<dt>Domain</dt> %s" % domainsdoc 
    196195 
    197196    #range stuff 
     
    209208                rangesdoc += "<dd>%s</dd>" % getTermLink(str(r.object.uri), term, rdfs.range) 
    210209    if (len(rangesdoc)>0): 
    211         doc += "<dt>Range:</dt> %s" % rangesdoc 
     210        doc += "<dt>Range</dt> %s" % rangesdoc 
    212211 
    213212    return doc 
     
    259258    doc = "" 
    260259 
    261     #patch to control incoming strings (FIXME, why??? drop it!) 
    262     try: 
    263         term.uri 
    264     except: 
    265         term = RDF.Node(RDF.Uri(term)) 
    266  
    267260    # Find subClassOf information 
    268261    o = m.find_statements( RDF.Statement(term, rdfs.subClassOf, None) ) 
    269262    if o.current(): 
    270         doc += "<dt>sub-class-of:</dt>" 
    271263        superclasses = [] 
    272264        for st in o: 
     
    275267                if (not uri in superclasses): 
    276268                    superclasses.append(uri) 
    277         for superclass in superclasses: 
    278             doc += "<dd>%s</dd>" % getTermLink(superclass) 
     269        if len(superclasses) > 0: 
     270            doc += "<dt>Sub-class of</dt>" 
     271            for superclass in superclasses: 
     272                doc += "<dd>%s</dd>" % getTermLink(superclass) 
    279273 
    280274    # Find out about properties which have rdfs:domain of t 
     
    284278        for k in d: 
    285279            dlist += "<dd>%s</dd>" % getTermLink(k) 
    286         doc += "<dt>in-domain-of:</dt>" + dlist 
     280        doc += "<dt>In domain of</dt>" + dlist 
    287281 
    288282    # Find out about properties which have rdfs:range of t 
     
    292286        for k in r: 
    293287            rlist += "<dd>%s</dd>" % getTermLink(k) 
    294         doc += "<dt>in-range-of:</dt>" + rlist 
     288        doc += "<dt>In range of</dt>" + rlist 
    295289 
    296290    return doc 
     291 
     292 
     293def isSpecial(pred): 
     294    """Return True if the predicate is "special" and shouldn't be emitted generically""" 
     295    return pred == rdf.type or pred == rdfs.range or pred == rdfs.domain or pred == rdfs.label or pred == rdfs.comment 
     296 
     297 
     298def extraInfo(term,m): 
     299    """Generate information about misc. properties of a term""" 
     300    doc = "" 
     301    properties = m.find_statements(RDF.Statement(term, None, None)) 
     302    #if properties: 
     303    #    doc += '<dl>\n' 
     304    last_pred = '' 
     305    for p in properties: 
     306        if isSpecial(p.predicate) or p.object.is_blank(): 
     307            continue 
     308        if p.predicate != last_pred: 
     309            doc += '<dt>%s</dt>\n' % niceName(str(p.predicate.uri)) 
     310        if p.object.is_resource(): 
     311            doc += '<dd>%s</dd>\n' % getTermLink(str(p.object.uri), term, p.predicate) 
     312        elif p.object.is_literal(): 
     313            doc += '<dd>%s</dd>\n' % str(p.object) 
     314        last_pred = p.predicate 
     315    #if properties: 
     316    #    doc += '</dl>\n' 
     317    return doc 
     318 
    297319 
    298320def rdfsInstanceInfo(term,m): 
     
    302324    t = m.find_statements( RDF.Statement(RDF.Node(RDF.Uri(term)), rdf.type, None) ) 
    303325    if t.current(): 
    304         doc += "<dt>RDF Type:</dt>" 
     326        doc += "<dt>Type</dt>" 
    305327    while t.current(): 
    306328        doc += "<dd>%s</dd>" % getTermLink(str(t.current().object.uri), RDF.Node(RDF.Uri(term)), rdf.type) 
    307329        t.next() 
    308330 
     331    doc += extraInfo(RDF.Node(RDF.Uri(term)), m) 
     332 
    309333    return doc 
    310334 
     
    326350    o = m.find_statements( RDF.Statement(term, rdf.type, owl.DatatypeProperty) ) 
    327351    if o.current(): 
    328         res += "<dt>OWL Type:</dt><dd>DatatypeProperty</dd>\n" 
     352        res += "<dt>OWL Type</dt><dd>DatatypeProperty</dd>\n" 
    329353 
    330354    # Object Property ( owl.ObjectProperty ) 
    331355    o = m.find_statements( RDF.Statement(term, rdf.type, owl.ObjectProperty) ) 
    332356    if o.current(): 
    333         res += "<dt>OWL Type:</dt><dd>ObjectProperty</dd>\n" 
     357        res += "<dt>OWL Type</dt><dd>ObjectProperty</dd>\n" 
    334358 
    335359    # Annotation Property ( owl.AnnotationProperty ) 
    336360    o = m.find_statements( RDF.Statement(term, rdf.type, owl.AnnotationProperty) ) 
    337361    if o.current(): 
    338         res += "<dt>OWL Type:</dt><dd>AnnotationProperty</dd>\n" 
     362        res += "<dt>OWL Type</dt><dd>AnnotationProperty</dd>\n" 
    339363 
    340364    # IFPs ( owl.InverseFunctionalProperty ) 
    341365    o = m.find_statements( RDF.Statement(term, rdf.type, owl.InverseFunctionalProperty) ) 
    342366    if o.current(): 
    343         res += "<dt>OWL Type:</dt><dd>InverseFunctionalProperty (uniquely identifying property)</dd>\n" 
     367        res += "<dt>OWL Type</dt><dd>InverseFunctionalProperty (uniquely identifying property)</dd>\n" 
    344368 
    345369    # Symmertic Property ( owl.SymmetricProperty ) 
    346370    o = m.find_statements( RDF.Statement(term, rdf.type, owl.SymmetricProperty) ) 
    347371    if o.current(): 
    348         res += "<dt>OWL Type:</dt><dd>SymmetricProperty</dd>\n" 
     372        res += "<dt>OWL Type</dt><dd>SymmetricProperty</dd>\n" 
    349373 
    350374    return res 
     
    378402            term_uri = term 
    379403         
    380         doc += """<div class="specterm" id="term_%s" about="%s">\n<h3>%s: <a href="%s">%s</a></h3>\n""" % (t, term_uri, category, term_uri, curie) 
     404        doc += """<div class="specterm" id="term_%s" about="%s">\n<h3>%s <a href="%s">%s</a></h3>\n""" % (t, term_uri, category, term_uri, curie) 
    381405 
    382406        label, comment = get_rdfs(m, term)     
    383407        status = get_status(m, term) 
    384         doc += "<p><em>%s</em></p>" % label 
     408        if label!='': 
     409            doc += "<span property=\"rdfs:label\" class=\"subtitle\">%s</span>" % label 
    385410        if comment!='': 
    386411                        doc += "<p property=\"rdfs:comment\">%s</p>" % comment 
     
    393418        if category=='Instance': 
    394419            terminfo += rdfsInstanceInfo(term,m) 
     420         
     421        terminfo += extraInfo(term,m) 
     422         
    395423        if (len(terminfo)>0): #to prevent empty list (bug #882) 
    396424            doc += "\n<dl>%s</dl>\n" % terminfo 
     425         
    397426        doc += htmlDocInfo(t) 
    398         doc += "<p style=\"float: right; font-size: small;\">[<a href=\"#sec-glance\">back to top</a>]</p>\n\n" 
    399427        doc += "\n\n</div>\n\n" 
    400428     
     
    416444 
    417445 
    418 def buildazlist(classlist, proplist, instalist=None): 
     446def buildIndex(classlist, proplist, instalist=None): 
    419447    """ 
    420448    Builds the A-Z list of terms. Args are a list of classes (strings) and  
    421449    a list of props (strings) 
    422450    """ 
    423     azlist = '<div style="padding: 1em; border: dotted; background-color: #ddd;">' 
     451    azlist = '<dl class="index">' 
    424452 
    425453    if (len(classlist)>0): 
    426         azlist += "<p>Classes: " 
     454        azlist += "<dt>Classes</dt><dd>" 
    427455        classlist.sort() 
    428456        for c in classlist: 
     
    430458                c = c.split(spec_ns_str[-1])[1] 
    431459            azlist = """%s <a href="#term_%s">%s</a>, """ % (azlist, c, c) 
    432         azlist = """%s\n</p>""" % azlist 
     460        azlist = """%s</dd>\n""" % azlist 
    433461 
    434462    if (len(proplist)>0): 
    435         azlist += "<p>Properties: " 
     463        azlist += "<dt>Properties</dt><dd>" 
    436464        proplist.sort() 
    437465        for p in proplist: 
     
    439467                p = p.split(spec_ns_str[-1])[1] 
    440468            azlist = """%s <a href="#term_%s">%s</a>, """ % (azlist, p, p) 
    441         azlist = """%s\n</p>""" % azlist 
     469        azlist = """%s</dd>\n""" % azlist 
    442470 
    443471    if (instalist!=None and len(instalist)>0): 
    444         azlist += "<p>Instances: " 
     472        azlist += "<dt>Instances</dt><dd>" 
    445473        for i in instalist: 
    446474            p = getShortName(i) 
    447475            anchor = getAnchor(i) 
    448476            azlist = """%s <a href="#term_%s">%s</a>, """ % (azlist, anchor, p) 
    449         azlist = """%s\n</p>""" % azlist 
    450  
    451     azlist = """%s\n</div>""" % azlist 
    452     return azlist 
    453  
    454  
    455 def build_simple_list(classlist, proplist, instalist=None): 
    456     """ 
    457     Builds a simple <ul> A-Z list of terms. Args are a list of classes (strings) and  
    458     a list of props (strings) 
    459     """ 
    460  
    461     azlist = """<div style="padding: 5px; border: dotted; background-color: #ddd;">""" 
    462     azlist = """%s\n<p>Classes:""" % azlist 
    463     azlist += """\n<ul>""" 
    464  
    465     classlist.sort() 
    466     for c in classlist: 
    467         azlist += """\n  <li><a href="#term_%s">%s</a></li>""" % (c.replace(" ", ""), c) 
    468     azlist = """%s\n</ul></p>""" % azlist 
    469  
    470     azlist = """%s\n<p>Properties:""" % azlist 
    471     azlist += """\n<ul>""" 
    472     proplist.sort() 
    473     for p in proplist: 
    474         azlist += """\n  <li><a href="#term_%s">%s</a></li>""" % (p.replace(" ", ""), p) 
    475     azlist = """%s\n</ul></p>""" % azlist 
    476  
    477     #FIXME: instances 
    478  
    479     azlist = """%s\n</div>""" % azlist 
     477        azlist = """%s</dd>\n""" % azlist 
     478 
     479    azlist = """%s\n</dl>""" % azlist 
    480480    return azlist 
    481481 
     
    528528    return classlist, proplist 
    529529 
     530 
    530531def specProperty(m, subject, predicate): 
    531532    "Return the rdfs:comment of the spec." 
     
    534535            return str(c.object) 
    535536    return '' 
     537 
    536538 
    537539def specAuthors(m, subject): 
     
    542544            ret += '<div class="author" property="dc:creator">' + j.object.literal_value['string'] + '</div>\n' 
    543545    return ret 
     546 
    544547 
    545548def getInstances(model, classes, properties): 
     
    599602        instalist.sort(lambda x, y: cmp(getShortName(x).lower(), getShortName(y).lower())) 
    600603     
    601     if mode == "spec": 
    602         # Build HTML list of terms. 
    603         azlist = buildazlist(classlist, proplist, instalist) 
    604     elif mode == "list": 
    605         # Build simple <ul> list of terms. 
    606         azlist = build_simple_list(classlist, proplist, instalist) 
     604    azlist = buildIndex(classlist, proplist, instalist) 
    607605 
    608606    # Generate Term HTML 
     
    623621    template = re.sub(r"\$VersionInfo\$", owlVersionInfo(m).encode("utf-8"), template)  
    624622     
    625     # NOTE: This works with the assumtpion that all "%" in the template are escaped to "%%" and it 
    626     #       contains the same number of "%s" as the number of parameters in % ( ...parameters here... ) 
    627     template = template % (azlist, termlist.encode("utf-8"));     
    628     template += ("<!-- generated from %s by %s at %s -->" % 
    629         (os.path.basename(specloc), os.path.basename(sys.argv[0]), time.strftime('%X %x %Z'))) 
    630  
     623    template = template.replace('@INDEX@', azlist) 
     624    template = template.replace('@REFERENCE@', termlist.encode("utf-8")) 
    631625    template = template.replace('@NAME@', specProperty(m, spec_url, doap.name)) 
    632626    template = template.replace('@URI@', spec_url) 
     
    638632    template = template.replace('@AUTHORS@', specAuthors(m, spec_url)) 
    639633     
     634    template += ("<!-- generated from %s by %s at %s -->" % 
     635        (os.path.basename(specloc), os.path.basename(sys.argv[0]), time.strftime('%X %x %Z'))) 
     636     
    640637    return template 
    641638 
     
    648645        f.close() 
    649646    except Exception, e: 
    650         print "Error writting in file \"" + path + "\": " + str(e) 
     647        print "Error writing to file \"" + path + "\": " + str(e) 
    651648 
    652649 
     
    695692""" % (script, script) 
    696693    sys.exit(-1) 
     694 
    697695 
    698696if __name__ == "__main__": 
  • trunk/lv2specgen/template.html

    r2114 r2118  
    1313    <meta name="generator" content="lv2specgen" /> 
    1414    <!--<link rel="stylesheet" type="text/css" href="./style.css" />--> 
     15    <style type="text/css"> 
     16         
     17/* BEGIN STYLE */ 
     18 
     19body { 
     20    color: black; 
     21    background: white; 
     22} 
     23 
     24:link    { color: #00C; background: transparent } 
     25:visited { color: #609; background: transparent } 
     26a:active { color: #C00; background: transparent } 
     27 
     28h1, h2, h3, h4, h5, h6 { text-align: left; background-color: #eee; padding: 0.25ex } 
     29h2, h3, h4, h5, h6 { margin-top: 2.5ex; } 
     30h1, h2, h3 { color: #005A9C; } 
     31 
     32.subtitle { margin: 0; padding: 0; font-style: italic } 
     33.index { padding: 1ex; border: dotted gray 2px; background-color: #eee; } 
     34 
     35dl { padding: 0; margin: 0 } 
     36dt { padding-top: 1ex; font-weight: bold } 
     37 
     38hr { 
     39    color: silver; 
     40    background-color: silver; 
     41    height: 1px; 
     42    border: 0; 
     43    margin-top: 3ex; 
     44    margin-bottom: 3ex 
     45} 
     46 
     47div.head { margin-bottom: 1em } 
     48div.head h1 { margin-top: 2em; clear: both } 
     49div.head table { margin-left: 2em; margin-top: 2em } 
     50 
     51pre { margin-left: 2em } 
     52/* 
     53p { 
     54  margin-top: 0.6em; 
     55  margin-bottom: 0.6em; 
     56} 
     57*/ 
     58 
     59@media aural {   
     60    h1, h2, h3 { stress: 20; richness: 90 } 
     61    p.copyright { volume: x-soft; speech-rate: x-fast } 
     62    dt { pause-before: 20% } 
     63    pre { speak-punctuation: code }  
     64} 
     65 
     66/* END STYLE */ 
     67 
     68  </style> 
    1569  </head> 
    1670  <body> 
     
    3084  <hr /> 
    3185  <h2 id="abstract">Abstract</h2> 
    32   <p>This specification defines the "@NAME@" extension (with URI 
    33   <a href="@URI@">@URI@</a>) to the 
    34   <a href="http://lv2plug.in/ns/lv2core">LV2</a> specification.</p> 
     86  <p>@COMMENT@</p> 
     87 
    3588  <h2 id="status">About this Document</h2> 
    36   <p>This document is an <a href="http://validator.w3.org/check/referer?outline=1&amp;verbose=1" 
    37     title="Valid XHTML 1.0 Strict">XHTML+RDFa</a> 
     89  <p>This document describes &ldquo;@NAME@&rdquo; (<a href="@URI@">@URI@</a>), an extension to 
     90  <a href="http://lv2plug.in/ns/lv2core">LV2</a>.</p> 
     91  <p>This is an <a href="http://validator.w3.org/check/referer?outline=1&amp;verbose=1" 
     92    title="Valid XHTML+RDFa">XHTML+RDFa</a> 
    3893  page automatically generated from <a href="./@FILENAME@">@FILENAME@</a> by 
    3994  <a href="http://drobilla.net/software/lv2specgen">lv2specgen</a>. 
     
    45100 
    46101  <p>Comments are welcome, please direct discussion to <a href="mailto:@MAIL@">@MAIL@</a>.</p> 
    47   <h2 id="contents">Table of Contents</h2> 
     102  <h2 id="contents">Contents</h2> 
    48103  <ol id="toc"> 
    49     <li><a href="#desc">Description</a></li> 
    50104    <li><a href="#sec-glance">Index</a></li> 
    51     <li><a href="#reference">Reference</a></li> 
    52   </ol> 
    53   <h3>Appendices</h3> 
    54   <ol id="appendix"> 
     105    <li><a href="#reference">Documentation</a></li> 
    55106    <li><a href="#references">References</a></li> 
    56107  </ol> 
     
    58109   
    59110  <!-- ===================================================================== --> 
    60   <h2 id="desc">1 Description</h2> 
    61   <p>@COMMENT@</p> 
    62    
    63   <!-- ===================================================================== --> 
    64   <h2 id="sec-glance">2. Index</h2> 
    65   <p>An alphabetical index of @NAME@ terms, by class (concepts) and by property 
    66   (relationships, attributes), are given below. All the terms are hyperlinked 
    67   to their detailed description for quick reference.</p> 
     111  <h2 id="sec-glance">1. Index</h2> 
    68112  <!-- The following is the script-generated index --> 
    69   %s  
     113  @INDEX@  
    70114  <!-- End of the generated index --> 
    71115   
    72116  <!-- ===================================================================== --> 
    73   <h2 id="reference">3. Reference</h2> 
     117  <h2 id="reference">2. Reference</h2> 
    74118  <!-- The following is the script-generated class/property/instance reference --> 
    75   %s  
     119  @REFERENCE@ 
    76120  <!-- End of the generated reference --> 
    77121 
    78122  <!-- ===================================================================== --> 
    79   <h2 id="references">A References</h2> 
     123  <hr /> 
     124  <h2 id="references">3. References</h2> 
    80125  <dl> 
    81126    <dt class="label" id="ref-rfc2119">IETF RFC 2119</dt>