aboutsummaryrefslogtreecommitdiffstats
path: root/lv2specgen
diff options
context:
space:
mode:
Diffstat (limited to 'lv2specgen')
-rw-r--r--lv2specgen/DTD/xhtml-datatypes-1.mod.1103
-rw-r--r--lv2specgen/DTD/xhtml-metaAttributes-1.mod154
-rw-r--r--lv2specgen/DTD/xhtml-rdfa-1.dtd472
-rw-r--r--lv2specgen/DTD/xhtml-rdfa-model-1.mod249
-rwxr-xr-xlv2specgen/lv2docgen.py17
-rwxr-xr-xlv2specgen/lv2specgen.py1666
-rw-r--r--lv2specgen/template.html136
7 files changed, 2120 insertions, 677 deletions
diff --git a/lv2specgen/DTD/xhtml-datatypes-1.mod.1 b/lv2specgen/DTD/xhtml-datatypes-1.mod.1
new file mode 100644
index 0000000..dde43e8
--- /dev/null
+++ b/lv2specgen/DTD/xhtml-datatypes-1.mod.1
@@ -0,0 +1,103 @@
+<!-- ...................................................................... -->
+<!-- XHTML Datatypes Module .............................................. -->
+<!-- file: xhtml-datatypes-1.mod
+
+ This is XHTML, a reformulation of HTML as a modular XML application.
+ Copyright 1998-2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+ Revision: $Id: xhtml-datatypes-1.mod,v 4.1 2001/04/06 19:23:32 altheim Exp $ SMI
+
+ This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+ PUBLIC "-//W3C//ENTITIES XHTML Datatypes 1.0//EN"
+ SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-datatypes-1.mod"
+
+ Revisions:
+ (none)
+ ....................................................................... -->
+
+<!-- Datatypes
+
+ defines containers for the following datatypes, many of
+ these imported from other specifications and standards.
+-->
+
+<!-- Length defined for cellpadding/cellspacing -->
+
+<!-- nn for pixels or nn% for percentage length -->
+<!ENTITY % Length.datatype "CDATA" >
+
+<!-- space-separated list of link types -->
+<!ENTITY % LinkTypes.datatype "NMTOKENS" >
+
+<!-- single or comma-separated list of media descriptors -->
+<!ENTITY % MediaDesc.datatype "CDATA" >
+
+<!-- pixel, percentage, or relative -->
+<!ENTITY % MultiLength.datatype "CDATA" >
+
+<!-- one or more digits (NUMBER) -->
+<!ENTITY % Number.datatype "CDATA" >
+
+<!-- integer representing length in pixels -->
+<!ENTITY % Pixels.datatype "CDATA" >
+
+<!-- script expression -->
+<!ENTITY % Script.datatype "CDATA" >
+
+<!-- textual content -->
+<!ENTITY % Text.datatype "CDATA" >
+
+<!-- Placeholder Compact URI-related types -->
+<!ENTITY % CURIE.datatype "CDATA" >
+<!ENTITY % CURIEs.datatype "CDATA" >
+<!ENTITY % SafeCURIE.datatype "CDATA" >
+<!ENTITY % SafeCURIEs.datatype "CDATA" >
+<!ENTITY % URIorSafeCURIE.datatype "CDATA" >
+<!ENTITY % URIorSafeCURIEs.datatype "CDATA" >
+
+<!-- Imported Datatypes ................................ -->
+
+<!-- a single character from [ISO10646] -->
+<!ENTITY % Character.datatype "CDATA" >
+
+<!-- a character encoding, as per [RFC2045] -->
+<!ENTITY % Charset.datatype "CDATA" >
+
+<!-- a space separated list of character encodings, as per [RFC2045] -->
+<!ENTITY % Charsets.datatype "CDATA" >
+
+<!-- Color specification using color name or sRGB (#RRGGBB) values -->
+<!ENTITY % Color.datatype "CDATA" >
+
+<!-- media type, as per [RFC2045] -->
+<!ENTITY % ContentType.datatype "CDATA" >
+
+<!-- comma-separated list of media types, as per [RFC2045] -->
+<!ENTITY % ContentTypes.datatype "CDATA" >
+
+<!-- date and time information. ISO date format -->
+<!ENTITY % Datetime.datatype "CDATA" >
+
+<!-- formal public identifier, as per [ISO8879] -->
+<!ENTITY % FPI.datatype "CDATA" >
+
+<!-- a language code, as per [RFC3066] or its successor -->
+<!ENTITY % LanguageCode.datatype "CDATA" >
+
+<!-- a comma separated list of language code ranges -->
+<!ENTITY % LanguageCodes.datatype "CDATA" >
+
+<!-- a qualified name , as per [XMLNS] or its successor -->
+<!ENTITY % QName.datatype "CDATA" >
+<!ENTITY % QNames.datatype "CDATA" >
+
+<!-- a Uniform Resource Identifier, see [URI] -->
+<!ENTITY % URI.datatype "CDATA" >
+
+<!-- a space-separated list of Uniform Resource Identifiers, see [URI] -->
+<!ENTITY % URIs.datatype "CDATA" >
+
+<!-- a relative URI reference consisting of an initial '#' and a fragment ID -->
+<!ENTITY % URIREF.datatype "CDATA" >
+
+<!-- end of xhtml-datatypes-1.mod -->
diff --git a/lv2specgen/DTD/xhtml-metaAttributes-1.mod b/lv2specgen/DTD/xhtml-metaAttributes-1.mod
new file mode 100644
index 0000000..b434e39
--- /dev/null
+++ b/lv2specgen/DTD/xhtml-metaAttributes-1.mod
@@ -0,0 +1,154 @@
+<!-- ...................................................................... -->
+<!-- XHTML MetaAttributes Module ......................................... -->
+<!-- file: xhtml-metaAttributes-1.mod
+
+ This is XHTML-RDFa, modules to annotate XHTML family documents.
+ Copyright 2007-2008 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+ Revision: $Id: xhtml-metaAttributes-1.mod,v 1.6 2008/08/01 20:01:00 smccarro Exp $
+
+ This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+ PUBLIC "-//W3C//ENTITIES XHTML MetaAttributes 1.0//EN"
+ SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-metaAttributes-1.mod"
+
+ Revisions:
+ (none)
+ ....................................................................... -->
+
+<!ENTITY % XHTML.global.attrs.prefixed "IGNORE" >
+
+<!-- Placeholder Compact URI-related types -->
+<!ENTITY % CURIE.datatype "CDATA" >
+<!ENTITY % CURIEs.datatype "CDATA" >
+<!ENTITY % SafeCURIE.datatype "CDATA" >
+<!ENTITY % SafeCURIEs.datatype "CDATA" >
+<!ENTITY % URIorSafeCURIE.datatype "CDATA" >
+<!ENTITY % URIorSafeCURIEs.datatype "CDATA" >
+
+<!-- Common Attributes
+
+ This module declares a collection of meta-information related
+ attributes.
+
+ %NS.decl.attrib; is declared in the XHTML Qname module.
+
+ This file also includes declarations of "global" versions of the
+ attributes. The global versions of the attributes are for use on
+ elements in other namespaces.
+-->
+
+<!ENTITY % about.attrib
+ "about %URIorSafeCURIE.datatype; #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.about.attrib
+ "%XHTML.prefix;:about %URIorSafeCURIE.datatype; #IMPLIED"
+>
+]]>
+
+<!ENTITY % typeof.attrib
+ "typeof %CURIEs.datatype; #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.typeof.attrib
+ "%XHTML.prefix;:typeof %CURIEs.datatype; #IMPLIED"
+>
+]]>
+
+<!ENTITY % property.attrib
+ "property %CURIEs.datatype; #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.property.attrib
+ "%XHTML.prefix;:property %CURIEs.datatype; #IMPLIED"
+>
+]]>
+
+<!ENTITY % resource.attrib
+ "resource %URIorSafeCURIE.datatype; #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.resource.attrib
+ "%XHTML.prefix;:resource %URIorSafeCURIE.datatype; #IMPLIED"
+>
+]]>
+
+<!ENTITY % content.attrib
+ "content CDATA #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.content.attrib
+ "%XHTML.prefix;:content CDATA #IMPLIED"
+>
+]]>
+
+<!ENTITY % datatype.attrib
+ "datatype %CURIE.datatype; #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.datatype.attrib
+ "%XHTML.prefix;:datatype %CURIE.datatype; #IMPLIED"
+>
+]]>
+
+<!ENTITY % rel.attrib
+ "rel %CURIEs.datatype; #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.rel.attrib
+ "%XHTML.prefix;:rel %CURIEs.datatype; #IMPLIED"
+>
+]]>
+
+<!ENTITY % rev.attrib
+ "rev %CURIEs.datatype; #IMPLIED"
+>
+
+<![%XHTML.global.attrs.prefixed;[
+<!ENTITY % XHTML.global.rev.attrib
+ "%XHTML.prefix;:rev %CURIEs.datatype; #IMPLIED"
+>
+]]>
+
+<!ENTITY % Metainformation.extra.attrib "" >
+
+<!ENTITY % Metainformation.attrib
+ "%about.attrib;
+ %content.attrib;
+ %datatype.attrib;
+ %typeof.attrib;
+ %property.attrib;
+ %rel.attrib;
+ %resource.attrib;
+ %rev.attrib;
+ %Metainformation.extra.attrib;"
+>
+
+<!ENTITY % XHTML.global.metainformation.extra.attrib "" >
+
+<![%XHTML.global.attrs.prefixed;[
+
+<!ENTITY % XHTML.global.metainformation.attrib
+ "%XHTML.global.about.attrib;
+ %XHTML.global.content.attrib;
+ %XHTML.global.datatype.attrib;
+ %XHTML.global.typeof.attrib;
+ %XHTML.global.property.attrib;
+ %XHTML.global.rel.attrib;
+ %XHTML.global.resource.attrib;
+ %XHTML.global.rev.attrib;
+ %XHTML.global.metainformation.extra.attrib;"
+>
+]]>
+
+<!ENTITY % XHTML.global.metainformation.attrib "" >
+
+
+<!-- end of xhtml-metaAttributes-1.mod -->
diff --git a/lv2specgen/DTD/xhtml-rdfa-1.dtd b/lv2specgen/DTD/xhtml-rdfa-1.dtd
new file mode 100644
index 0000000..26ed117
--- /dev/null
+++ b/lv2specgen/DTD/xhtml-rdfa-1.dtd
@@ -0,0 +1,472 @@
+<!-- ....................................................................... -->
+<!-- XHTML 1.1 + RDFa DTD ................................................. -->
+<!-- file: xhtml-rdfa-1.dtd
+-->
+
+<!-- XHTML 1.1 + RDFa DTD
+
+ This is an example markup language combining XHTML 1.1 and the RDFa
+ modules.
+
+ XHTML+RDFa
+ Copyright 1998-2008 World Wide Web Consortium
+ (Massachusetts Institute of Technology, European Research Consortium
+ for Informatics and Mathematics, Keio University).
+ All Rights Reserved.
+
+ Permission to use, copy, modify and distribute the XHTML DTD and its
+ accompanying documentation for any purpose and without fee is hereby
+ granted in perpetuity, provided that the above copyright notice and
+ this paragraph appear in all copies. The copyright holders make no
+ representation about the suitability of the DTD for any purpose.
+
+ It is provided "as is" without expressed or implied warranty.
+
+-->
+<!-- This is the driver file for version 1 of the XHTML + RDFa DTD.
+
+ Please use this public identifier to identify it:
+
+ "-//W3C//DTD XHTML+RDFa 1.0//EN"
+-->
+<!ENTITY % XHTML.version "XHTML+RDFa 1.0" >
+
+<!-- Use this URI to identify the default namespace:
+
+ "http://www.w3.org/1999/xhtml"
+
+ See the Qualified Names module for information
+ on the use of namespace prefixes in the DTD.
+
+ Note that XHTML namespace elements are not prefixed by default,
+ but the XHTML namespace prefix is defined as "xhtml" so that
+ other markup languages can extend this one and use the XHTML
+ prefixed global attributes if required.
+
+-->
+<!ENTITY % NS.prefixed "IGNORE" >
+<!ENTITY % XHTML.prefix "xhtml" >
+
+<!-- Be sure to include prefixed global attributes - we don't need
+ them, but languages that extend XHTML 1.1 might.
+-->
+<!ENTITY % XHTML.global.attrs.prefixed "INCLUDE" >
+
+<!-- Reserved for use with the XLink namespace:
+-->
+<!ENTITY % XLINK.xmlns "" >
+<!ENTITY % XLINK.xmlns.attrib "" >
+
+<!-- For example, if you are using XHTML 1.1 directly, use the public
+ identifier in the DOCTYPE declaration, with the namespace declaration
+ on the document element to identify the default namespace:
+
+ <?xml version="1.0"?>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
+ "xhtml-rdfa-1.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml"
+ xml:lang="en">
+ ...
+ </html>
+
+ Revisions:
+ (none)
+-->
+
+<!-- reserved for future use with document profiles -->
+<!ENTITY % XHTML.profile "" >
+
+<!-- ensure XHTML Notations are disabled -->
+<!ENTITY % xhtml-notations.module "IGNORE" >
+
+<!-- Bidirectional Text features
+ This feature-test entity is used to declare elements
+ and attributes used for bidirectional text support.
+-->
+<!ENTITY % XHTML.bidi "INCLUDE" >
+
+<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+
+<!-- Pre-Framework Redeclaration placeholder .................... -->
+<!-- this serves as a location to insert markup declarations
+ into the DTD prior to the framework declarations.
+-->
+<!ENTITY % xhtml-prefw-redecl.module "IGNORE" >
+<!ENTITY % xhtml-prefw-redecl.mod "" >
+<![%xhtml-prefw-redecl.module;[
+%xhtml-prefw-redecl.mod;
+<!-- end of xhtml-prefw-redecl.module -->]]>
+
+<!-- we need the datatypes now -->
+<!ENTITY % xhtml-datatypes.module "INCLUDE" >
+<![%xhtml-datatypes.module;[
+<!ENTITY % xhtml-datatypes.mod
+ PUBLIC "-//W3C//ENTITIES XHTML Datatypes 1.0//EN"
+ "xhtml-datatypes-1.mod" >
+%xhtml-datatypes.mod;]]>
+
+<!-- bring in the RDFa attributes cause we need them in Common -->
+<!ENTITY % xhtml-metaAttributes.module "INCLUDE" >
+<![%xhtml-metaAttributes.module;[
+<!ENTITY % xhtml-metaAttributes.mod
+ PUBLIC "-//W3C//ENTITIES XHTML MetaAttributes 1.0//EN"
+ "xhtml-metaAttributes-1.mod" >
+%xhtml-metaAttributes.mod;]]>
+
+<!ENTITY % xhtml-events.module "INCLUDE" >
+
+<!ENTITY % Common.extra.attrib
+ "href %URI.datatype; #IMPLIED
+ %Metainformation.attrib;"
+>
+<!-- adding the lang attribute into the I18N collection -->
+
+<!ENTITY % lang.attrib
+ "xml:lang %LanguageCode.datatype; #IMPLIED
+ lang %LanguageCode.datatype; #IMPLIED"
+>
+
+<!-- Inline Style Module ........................................ -->
+<!ENTITY % xhtml-inlstyle.module "INCLUDE" >
+<![%xhtml-inlstyle.module;[
+<!ENTITY % xhtml-inlstyle.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN"
+ "xhtml-inlstyle-1.mod" >
+%xhtml-inlstyle.mod;]]>
+
+<!-- declare Document Model module instantiated in framework
+-->
+<!ENTITY % xhtml-model.mod
+ PUBLIC "-//W3C//ENTITIES XHTML+RDFa Document Model 1.0//EN"
+ "xhtml-rdfa-model-1.mod" >
+
+<!-- Modular Framework Module (required) ......................... -->
+<!ENTITY % xhtml-framework.module "INCLUDE" >
+<![%xhtml-framework.module;[
+<!ENTITY % xhtml-framework.mod
+ PUBLIC "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN"
+ "xhtml-framework-1.mod" >
+%xhtml-framework.mod;]]>
+
+<!-- Post-Framework Redeclaration placeholder ................... -->
+<!-- this serves as a location to insert markup declarations
+ into the DTD following the framework declarations.
+-->
+<!ENTITY % xhtml-postfw-redecl.module "IGNORE" >
+<!ENTITY % xhtml-postfw-redecl.mod "">
+<![%xhtml-postfw-redecl.module;[
+%xhtml-postfw-redecl.mod;
+<!-- end of xhtml-postfw-redecl.module -->]]>
+
+
+
+<!-- Text Module (Required) ..................................... -->
+<!ENTITY % xhtml-text.module "INCLUDE" >
+<![%xhtml-text.module;[
+<!ENTITY % xhtml-text.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Text 1.0//EN"
+ "xhtml-text-1.mod" >
+%xhtml-text.mod;]]>
+
+<!-- Hypertext Module (required) ................................. -->
+<!ENTITY % a.attlist "IGNORE" >
+<!ENTITY % xhtml-hypertext.module "INCLUDE" >
+<![%xhtml-hypertext.module;[
+<!ENTITY % xhtml-hypertext.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN"
+ "xhtml-hypertext-1.mod" >
+%xhtml-hypertext.mod;]]>
+<!ATTLIST %a.qname;
+ %Common.attrib;
+ charset %Charset.datatype; #IMPLIED
+ type %ContentType.datatype; #IMPLIED
+ hreflang %LanguageCode.datatype; #IMPLIED
+ accesskey %Character.datatype; #IMPLIED
+ tabindex %Number.datatype; #IMPLIED
+>
+
+<!-- Lists Module (required) .................................... -->
+<!ENTITY % xhtml-list.module "INCLUDE" >
+<![%xhtml-list.module;[
+<!ENTITY % xhtml-list.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Lists 1.0//EN"
+ "xhtml-list-1.mod" >
+%xhtml-list.mod;]]>
+
+<!-- ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
+
+<!-- Edit Module ................................................ -->
+<!ENTITY % xhtml-edit.module "INCLUDE" >
+<![%xhtml-edit.module;[
+<!ENTITY % xhtml-edit.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Editing Elements 1.0//EN"
+ "xhtml-edit-1.mod" >
+%xhtml-edit.mod;]]>
+
+<!-- BIDI Override Module ....................................... -->
+<!ENTITY % xhtml-bdo.module "%XHTML.bidi;" >
+<![%xhtml-bdo.module;[
+<!ENTITY % xhtml-bdo.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML BIDI Override Element 1.0//EN"
+ "xhtml-bdo-1.mod" >
+%xhtml-bdo.mod;]]>
+
+<!-- Ruby Module ................................................ -->
+<!ENTITY % Ruby.common.attlists "INCLUDE" >
+<!ENTITY % Ruby.common.attrib "%Common.attrib;" >
+<!ENTITY % xhtml-ruby.module "INCLUDE" >
+<![%xhtml-ruby.module;[
+<!ENTITY % xhtml-ruby.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Ruby 1.0//EN"
+ "http://www.w3.org/TR/ruby/xhtml-ruby-1.mod" >
+%xhtml-ruby.mod;]]>
+
+<!-- Presentation Module ........................................ -->
+<!ENTITY % xhtml-pres.module "INCLUDE" >
+<![%xhtml-pres.module;[
+<!ENTITY % xhtml-pres.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Presentation 1.0//EN"
+ "xhtml-pres-1.mod" >
+%xhtml-pres.mod;]]>
+
+<!ENTITY % link.attlist "IGNORE" >
+<!-- Link Element Module ........................................ -->
+<!ENTITY % xhtml-link.module "INCLUDE" >
+<![%xhtml-link.module;[
+<!ENTITY % xhtml-link.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Link Element 1.0//EN"
+ "xhtml-link-1.mod" >
+%xhtml-link.mod;]]>
+
+<!ATTLIST %link.qname;
+ %Common.attrib;
+ charset %Charset.datatype; #IMPLIED
+ hreflang %LanguageCode.datatype; #IMPLIED
+ type %ContentType.datatype; #IMPLIED
+ media %MediaDesc.datatype; #IMPLIED
+>
+
+<!-- Document Metainformation Module ............................ -->
+<!ENTITY % meta.attlist "IGNORE" >
+<!ENTITY % xhtml-meta.module "INCLUDE" >
+<![%xhtml-meta.module;[
+<!ENTITY % xhtml-meta.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN"
+ "xhtml-meta-1.mod" >
+%xhtml-meta.mod;]]>
+<!ATTLIST %meta.qname;
+ %Common.attrib;
+ http-equiv NMTOKEN #IMPLIED
+ name NMTOKEN #IMPLIED
+ scheme CDATA #IMPLIED
+>
+
+<!-- Base Element Module ........................................ -->
+<!ENTITY % xhtml-base.module "INCLUDE" >
+<![%xhtml-base.module;[
+<!ENTITY % xhtml-base.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Base Element 1.0//EN"
+ "xhtml-base-1.mod" >
+%xhtml-base.mod;]]>
+
+<!-- Scripting Module ........................................... -->
+<!ENTITY % script.attlist "IGNORE" >
+<!ENTITY % xhtml-script.module "INCLUDE" >
+<![%xhtml-script.module;[
+<!ENTITY % xhtml-script.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Scripting 1.0//EN"
+ "xhtml-script-1.mod" >
+%xhtml-script.mod;]]>
+
+<!ATTLIST %script.qname;
+ %XHTML.xmlns.attrib;
+ %id.attrib;
+ %Metainformation.attrib;
+ href %URI.datatype; #IMPLIED
+ xml:space ( preserve ) #FIXED 'preserve'
+ charset %Charset.datatype; #IMPLIED
+ type %ContentType.datatype; #REQUIRED
+ src %URI.datatype; #IMPLIED
+ defer ( defer ) #IMPLIED
+>
+
+<!-- Style Sheets Module ......................................... -->
+<!ENTITY % style.attlist "IGNORE" >
+<!ENTITY % xhtml-style.module "INCLUDE" >
+<![%xhtml-style.module;[
+<!ENTITY % xhtml-style.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Style Sheets 1.0//EN"
+ "xhtml-style-1.mod" >
+%xhtml-style.mod;]]>
+<!ATTLIST %style.qname;
+ %XHTML.xmlns.attrib;
+ %id.attrib;
+ %title.attrib;
+ %I18n.attrib;
+ %Metainformation.attrib;
+ href %URI.datatype; #IMPLIED
+ xml:space ( preserve ) #FIXED 'preserve'
+ type %ContentType.datatype; #REQUIRED
+ media %MediaDesc.datatype; #IMPLIED
+>
+
+<!-- Image Module ............................................... -->
+<!ENTITY % xhtml-image.module "INCLUDE" >
+<![%xhtml-image.module;[
+<!ENTITY % xhtml-image.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Images 1.0//EN"
+ "xhtml-image-1.mod" >
+%xhtml-image.mod;]]>
+
+<!-- Client-side Image Map Module ............................... -->
+<!ENTITY % area.attlist "IGNORE" >
+
+<!ENTITY % xhtml-csismap.module "INCLUDE" >
+<![%xhtml-csismap.module;[
+<!ENTITY % xhtml-csismap.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Client-side Image Maps 1.0//EN"
+ "xhtml-csismap-1.mod" >
+%xhtml-csismap.mod;]]>
+
+<!ATTLIST %area.qname;
+ %Common.attrib;
+ shape %Shape.datatype; 'rect'
+ coords %Coords.datatype; #IMPLIED
+ nohref ( nohref ) #IMPLIED
+ alt %Text.datatype; #REQUIRED
+ tabindex %Number.datatype; #IMPLIED
+ accesskey %Character.datatype; #IMPLIED
+>
+
+<!-- Server-side Image Map Module ............................... -->
+<!ENTITY % xhtml-ssismap.module "INCLUDE" >
+<![%xhtml-ssismap.module;[
+<!ENTITY % xhtml-ssismap.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Server-side Image Maps 1.0//EN"
+ "xhtml-ssismap-1.mod" >
+%xhtml-ssismap.mod;]]>
+
+<!-- Param Element Module ....................................... -->
+<!ENTITY % param.attlist "IGNORE" >
+<!ENTITY % xhtml-param.module "INCLUDE" >
+<![%xhtml-param.module;[
+<!ENTITY % xhtml-param.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Param Element 1.0//EN"
+ "xhtml-param-1.mod" >
+%xhtml-param.mod;]]>
+
+<!ATTLIST %param.qname;
+ %XHTML.xmlns.attrib;
+ %id.attrib;
+ %Metainformation.attrib;
+ href %URI.datatype; #IMPLIED
+ name CDATA #REQUIRED
+ value CDATA #IMPLIED
+ valuetype ( data | ref | object ) 'data'
+ type %ContentType.datatype; #IMPLIED
+>
+<!-- Embedded Object Module ..................................... -->
+<!ENTITY % xhtml-object.module "INCLUDE" >
+<![%xhtml-object.module;[
+<!ENTITY % xhtml-object.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN"
+ "xhtml-object-1.mod" >
+%xhtml-object.mod;]]>
+
+<!-- Tables Module ............................................... -->
+<!ENTITY % xhtml-table.module "INCLUDE" >
+<![%xhtml-table.module;[
+<!ENTITY % xhtml-table.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Tables 1.0//EN"
+ "xhtml-table-1.mod" >
+%xhtml-table.mod;]]>
+
+<!-- Forms Module ............................................... -->
+<!ENTITY % xhtml-form.module "INCLUDE" >
+<![%xhtml-form.module;[
+<!ENTITY % xhtml-form.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Forms 1.0//EN"
+ "xhtml-form-1.mod" >
+%xhtml-form.mod;]]>
+
+<!-- Target Attribute Module .................................... -->
+<!ENTITY % xhtml-target.module "INCLUDE" >
+<![%xhtml-target.module;[
+<!ENTITY % xhtml-target.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Target 1.0//EN"
+ "xhtml-target-1.mod" >
+%xhtml-target.mod;]]>
+
+<!-- Legacy Markup ............................................... -->
+<!ENTITY % xhtml-legacy.module "IGNORE" >
+<![%xhtml-legacy.module;[
+<!ENTITY % xhtml-legacy.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Legacy Markup 1.0//EN"
+ "xhtml-legacy-1.mod" >
+%xhtml-legacy.mod;]]>
+
+<!-- Document Structure Module (required) ....................... -->
+<!ENTITY % html.attlist "IGNORE" >
+<!ENTITY % head.attlist "IGNORE" >
+<!ENTITY % title.attlist "IGNORE" >
+<!ENTITY % xhtml-struct.module "INCLUDE" >
+<![%xhtml-struct.module;[
+<!ENTITY % xhtml-struct.mod
+ PUBLIC "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN"
+ "xhtml-struct-1.mod" >
+%xhtml-struct.mod;]]>
+<!ENTITY % profile.attrib
+ "profile %URI.datatype; '%XHTML.profile;'"
+>
+<!ENTITY % XHTML.version.attrib
+ "version %FPI.datatype; #FIXED '%XHTML.version;'"
+>
+<!ATTLIST %html.qname;
+ %Common.attrib;
+ %XSI.schemaLocation.attrib;
+ %XHTML.version.attrib;
+>
+<!ATTLIST %head.qname;
+ %Common.attrib;
+ %profile.attrib;
+>
+<!ATTLIST %title.qname;
+ %Common.attrib;
+>
+
+<!-- end of XHTML-RDFa DTD ................................................ -->
+<!-- ....................................................................... -->
+
+<!-- Add xmlns attributes to validate lv2specgen output -->
+<!-- This is a pretty dirty hack, but avoids needing to write a bunch of code to
+ mangle DTDs to appease validation -->
+
+<!ATTLIST html xmlns:dc CDATA #IMPLIED>
+<!ATTLIST html xmlns:dct CDATA #IMPLIED>
+<!ATTLIST html xmlns:rdf CDATA #IMPLIED>
+<!ATTLIST html xmlns:rdfs CDATA #IMPLIED>
+
+<!ATTLIST html xmlns:atom CDATA #IMPLIED>
+<!ATTLIST html xmlns:bufsz CDATA #IMPLIED>
+<!ATTLIST html xmlns:da CDATA #IMPLIED>
+<!ATTLIST html xmlns:dman CDATA #IMPLIED>
+<!ATTLIST html xmlns:ev CDATA #IMPLIED>
+<!ATTLIST html xmlns:ia CDATA #IMPLIED>
+<!ATTLIST html xmlns:log CDATA #IMPLIED>
+<!ATTLIST html xmlns:lv2 CDATA #IMPLIED>
+<!ATTLIST html xmlns:midi CDATA #IMPLIED>
+<!ATTLIST html xmlns:morph CDATA #IMPLIED>
+<!ATTLIST html xmlns:opts CDATA #IMPLIED>
+<!ATTLIST html xmlns:param CDATA #IMPLIED>
+<!ATTLIST html xmlns:patch CDATA #IMPLIED>
+<!ATTLIST html xmlns:pg CDATA #IMPLIED>
+<!ATTLIST html xmlns:pprops CDATA #IMPLIED>
+<!ATTLIST html xmlns:pset CDATA #IMPLIED>
+<!ATTLIST html xmlns:rsz CDATA #IMPLIED>
+<!ATTLIST html xmlns:state CDATA #IMPLIED>
+<!ATTLIST html xmlns:time CDATA #IMPLIED>
+<!ATTLIST html xmlns:ui CDATA #IMPLIED>
+<!ATTLIST html xmlns:umap CDATA #IMPLIED>
+<!ATTLIST html xmlns:units CDATA #IMPLIED>
+<!ATTLIST html xmlns:urid CDATA #IMPLIED>
+<!ATTLIST html xmlns:work CDATA #IMPLIED>
diff --git a/lv2specgen/DTD/xhtml-rdfa-model-1.mod b/lv2specgen/DTD/xhtml-rdfa-model-1.mod
new file mode 100644
index 0000000..ad010ee
--- /dev/null
+++ b/lv2specgen/DTD/xhtml-rdfa-model-1.mod
@@ -0,0 +1,249 @@
+<!-- ....................................................................... -->
+<!-- XHTML+RDFa Document Model Module ..................................... -->
+<!-- file: xhtml-rdfa-model-1.mod
+
+ This is XHTML+RDFa.
+ Copyright 1998-2008 W3C (MIT, ERCIM, Keio), All Rights Reserved.
+ Revision: $Id: xhtml-rdfa-model-1.mod,v 1.4 2009/06/26 14:05:13 smccarro Exp $ SMI
+
+ This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+ PUBLIC "-//W3C//ENTITIES XHTML+RDFa Document Model 1.0//EN"
+ SYSTEM "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-model-1.mod"
+
+ Revisions:
+ (none)
+ ....................................................................... -->
+
+<!-- XHTML+RDFa Document Model
+
+ This module describes the groupings of elements that make up
+ common content models for XHTML elements.
+
+ XHTML has three basic content models:
+
+ %Inline.mix; character-level elements
+ %Block.mix; block-like elements, eg., paragraphs and lists
+ %Flow.mix; any block or inline elements
+
+ Any parameter entities declared in this module may be used
+ to create element content models, but the above three are
+ considered 'global' (insofar as that term applies here).
+
+ The reserved word '#PCDATA' (indicating a text string) is now
+ included explicitly with each element declaration that is
+ declared as mixed content, as XML requires that this token
+ occur first in a content model specification.
+-->
+<!-- Extending the Model
+
+ While in some cases this module may need to be rewritten to
+ accommodate changes to the document model, minor extensions
+ may be accomplished by redeclaring any of the three *.extra;
+ parameter entities to contain extension element types as follows:
+
+ %Misc.extra; whose parent may be any block or
+ inline element.
+
+ %Inline.extra; whose parent may be any inline element.
+
+ %Block.extra; whose parent may be any block element.
+
+ If used, these parameter entities must be an OR-separated
+ list beginning with an OR separator ("|"), eg., "| a | b | c"
+
+ All block and inline *.class parameter entities not part
+ of the *struct.class classes begin with "| " to allow for
+ exclusion from mixes.
+-->
+
+<!-- .............. Optional Elements in head .................. -->
+
+<!ENTITY % HeadOpts.mix
+ "( %script.qname; | %style.qname; | %meta.qname;
+ | %link.qname; | %object.qname; )*"
+>
+
+<!-- ................. Miscellaneous Elements .................. -->
+
+<!-- ins and del are used to denote editing changes
+-->
+<!ENTITY % Edit.class "| %ins.qname; | %del.qname;" >
+
+<!-- script and noscript are used to contain scripts
+ and alternative content
+-->
+<!ENTITY % Script.class "| %script.qname; | %noscript.qname;" >
+
+<!ENTITY % Misc.extra "" >
+
+<!-- These elements are neither block nor inline, and can
+ essentially be used anywhere in the document body.
+-->
+<!ENTITY % Misc.class
+ "%Edit.class;
+ %Script.class;
+ %Misc.extra;"
+>
+
+<!-- .................... Inline Elements ...................... -->
+
+<!ENTITY % InlStruct.class "%br.qname; | %span.qname;" >
+
+<!ENTITY % InlPhras.class
+ "| %em.qname; | %strong.qname; | %dfn.qname; | %code.qname;
+ | %samp.qname; | %kbd.qname; | %var.qname; | %cite.qname;
+ | %abbr.qname; | %acronym.qname; | %q.qname;" >
+
+<!ENTITY % InlPres.class
+ "| %tt.qname; | %i.qname; | %b.qname; | %big.qname;
+ | %small.qname; | %sub.qname; | %sup.qname;" >
+
+<!ENTITY % I18n.class "| %bdo.qname;" >
+
+<!ENTITY % Anchor.class "| %a.qname;" >
+
+<!ENTITY % InlSpecial.class
+ "| %img.qname; | %map.qname;
+ | %object.qname;" >
+
+<!ENTITY % InlForm.class
+ "| %input.qname; | %select.qname; | %textarea.qname;
+ | %label.qname; | %button.qname;" >
+
+<!ENTITY % Inline.extra "" >
+
+<!ENTITY % Ruby.class "| %ruby.qname;" >
+
+<!-- %Inline.class; includes all inline elements,
+ used as a component in mixes
+-->
+<!ENTITY % Inline.class
+ "%InlStruct.class;
+ %InlPhras.class;
+ %InlPres.class;
+ %I18n.class;
+ %Anchor.class;
+ %InlSpecial.class;
+ %InlForm.class;
+ %Ruby.class;
+ %Inline.extra;"
+>
+
+<!-- %InlNoRuby.class; includes all inline elements
+ except ruby, used as a component in mixes
+-->
+<!ENTITY % InlNoRuby.class
+ "%InlStruct.class;
+ %InlPhras.class;
+ %InlPres.class;
+ %I18n.class;
+ %Anchor.class;
+ %InlSpecial.class;
+ %InlForm.class;
+ %Inline.extra;"
+>
+
+<!-- %NoRuby.content; includes all inlines except ruby
+-->
+<!ENTITY % NoRuby.content
+ "( #PCDATA
+ | %InlNoRuby.class;
+ %Misc.class; )*"
+>
+
+<!-- %InlNoAnchor.class; includes all non-anchor inlines,
+ used as a component in mixes
+-->
+<!ENTITY % InlNoAnchor.class
+ "%InlStruct.class;
+ %InlPhras.class;
+ %InlPres.class;
+ %I18n.class;
+ %InlSpecial.class;
+ %InlForm.class;
+ %Ruby.class;
+ %Inline.extra;"
+>
+
+<!-- %InlNoAnchor.mix; includes all non-anchor inlines
+-->
+<!ENTITY % InlNoAnchor.mix
+ "%InlNoAnchor.class;
+ %Misc.class;"
+>
+
+<!-- %Inline.mix; includes all inline elements, including %Misc.class;
+-->
+<!ENTITY % Inline.mix
+ "%Inline.class;
+ %Misc.class;"
+>
+
+<!-- ..................... Block Elements ...................... -->
+
+<!-- In the HTML 4.0 DTD, heading and list elements were included
+ in the %block; parameter entity. The %Heading.class; and
+ %List.class; parameter entities must now be included explicitly
+ on element declarations where desired.
+-->
+
+<!ENTITY % Heading.class
+ "%h1.qname; | %h2.qname; | %h3.qname;
+ | %h4.qname; | %h5.qname; | %h6.qname;" >
+
+<!ENTITY % List.class "%ul.qname; | %ol.qname; | %dl.qname;" >
+
+<!ENTITY % Table.class "| %table.qname;" >
+
+<!ENTITY % Form.class "| %form.qname;" >
+
+<!ENTITY % Fieldset.class "| %fieldset.qname;" >
+
+<!ENTITY % BlkStruct.class "%p.qname; | %div.qname;" >
+
+<!ENTITY % BlkPhras.class
+ "| %pre.qname; | %blockquote.qname; | %address.qname;" >
+
+<!ENTITY % BlkPres.class "| %hr.qname; " >
+
+<!ENTITY % BlkSpecial.class
+ "%Table.class;
+ %Form.class;
+ %Fieldset.class;"
+>
+
+<!ENTITY % Block.extra "" >
+
+<!-- %Block.class; includes all block elements,
+ used as an component in mixes
+-->
+<!ENTITY % Block.class
+ "%BlkStruct.class;
+ %BlkPhras.class;
+ %BlkPres.class;
+ %BlkSpecial.class;
+ %Block.extra;"
+>
+
+<!-- %Block.mix; includes all block elements plus %Misc.class;
+-->
+<!ENTITY % Block.mix
+ "%Heading.class;
+ | %List.class;
+ | %Block.class;
+ %Misc.class;"
+>
+
+<!-- ................ All Content Elements .................. -->
+
+<!-- %Flow.mix; includes all text content, block and inline
+-->
+<!ENTITY % Flow.mix
+ "%Heading.class;
+ | %List.class;
+ | %Block.class;
+ | %Inline.class;
+ %Misc.class;"
+>
+<!-- end of xhtml-rdfa-model-1.mod -->
diff --git a/lv2specgen/lv2docgen.py b/lv2specgen/lv2docgen.py
index 423659e..23a239d 100755
--- a/lv2specgen/lv2docgen.py
+++ b/lv2specgen/lv2docgen.py
@@ -16,16 +16,16 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+import errno
+import os
+import sys
+
__date__ = '2012-03-27'
__version__ = '0.0.0'
__authors__ = 'David Robillard'
__license__ = 'ISC License <http://www.opensource.org/licenses/isc>'
__contact__ = 'devel@lists.lv2plug.in'
-import errno
-import os
-import sys
-
try:
import rdflib
except ImportError:
@@ -47,7 +47,7 @@ def get_doc(model, subject):
if comment:
return '<p class="content">%s</p>' % comment
return ''
-
+
def port_doc(model, port):
name = model.value(port, lv2.name, None)
comment = model.value(port, rdfs.comment, None)
@@ -131,11 +131,8 @@ if __name__ == '__main__':
pass
else:
raise
-
- print 'Writing <%s> documentation to %s' % (plugin, outpath)
+
+ print('Writing <%s> documentation to %s' % (plugin, outpath))
out = open(outpath, 'w')
out.write(html)
out.close()
-
-
-
diff --git a/lv2specgen/lv2specgen.py b/lv2specgen/lv2specgen.py
index efbf053..8cfa1c7 100755
--- a/lv2specgen/lv2specgen.py
+++ b/lv2specgen/lv2specgen.py
@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
#
# lv2specgen, a documentation generator for LV2 specifications.
-# Copyright (c) 2009-2012 David Robillard <d@drobilla.net>
+# Copyright (c) 2009-2014 David Robillard <d@drobilla.net>
#
# Based on SpecGen:
# <http://forge.morfeo-project.org/wiki_en/index.php/SpecGen>
@@ -30,36 +30,41 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-__date__ = "2011-10-26"
-__version__ = __date__.replace('-', '.')
-__authors__ = """
-Christopher Schmidt,
-Uldis Bojars,
-Sergio Fernández,
-David Robillard"""
-__license__ = "MIT License <http://www.opensource.org/licenses/mit>"
-__contact__ = "devel@lists.lv2plug.in"
-
import datetime
+import markdown
+import markdown.extensions
+import optparse
import os
import re
import sys
+import time
import xml.sax.saxutils
import xml.dom
import xml.dom.minidom
+__date__ = "2011-10-26"
+__version__ = __date__.replace("-", ".")
+__authors__ = """
+Christopher Schmidt,
+Uldis Bojars,
+Sergio Fernández,
+David Robillard"""
+__license__ = "MIT License <http://www.opensource.org/licenses/mit>"
+__contact__ = "devel@lists.lv2plug.in"
+
try:
from lxml import etree
+
have_lxml = True
-except:
+except Exception:
have_lxml = False
try:
import pygments
import pygments.lexers
+ import pygments.lexers.rdf
import pygments.formatters
- from pygments.lexer import RegexLexer, include, bygroups
- from pygments.token import Text, Comment, Operator, Keyword, Name, String, Literal, Punctuation
+
have_pygments = True
except ImportError:
print("Error importing pygments, syntax highlighting disabled")
@@ -78,31 +83,32 @@ spec_url = None
spec_ns_str = None
spec_ns = None
spec_pre = None
+spec_bundle = None
specgendir = None
ns_list = {
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#" : "rdf",
- "http://www.w3.org/2000/01/rdf-schema#" : "rdfs",
- "http://www.w3.org/2002/07/owl#" : "owl",
- "http://www.w3.org/2001/XMLSchema#" : "xsd",
- "http://rdfs.org/sioc/ns#" : "sioc",
- "http://xmlns.com/foaf/0.1/" : "foaf",
- "http://purl.org/dc/elements/1.1/" : "dc",
- "http://purl.org/dc/terms/" : "dct",
- "http://purl.org/rss/1.0/modules/content/" : "content",
- "http://www.w3.org/2003/01/geo/wgs84_pos#" : "geo",
- "http://www.w3.org/2004/02/skos/core#" : "skos",
- "http://lv2plug.in/ns/lv2core#" : "lv2",
- "http://usefulinc.com/ns/doap#" : "doap",
- "http://ontologi.es/doap-changeset#" : "dcs"
- }
-
-rdf = rdflib.Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#')
-rdfs = rdflib.Namespace('http://www.w3.org/2000/01/rdf-schema#')
-owl = rdflib.Namespace('http://www.w3.org/2002/07/owl#')
-lv2 = rdflib.Namespace('http://lv2plug.in/ns/lv2core#')
-doap = rdflib.Namespace('http://usefulinc.com/ns/doap#')
-dcs = rdflib.Namespace('http://ontologi.es/doap-changeset#')
-foaf = rdflib.Namespace('http://xmlns.com/foaf/0.1/')
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
+ "http://www.w3.org/2000/01/rdf-schema#": "rdfs",
+ "http://www.w3.org/2002/07/owl#": "owl",
+ "http://www.w3.org/2001/XMLSchema#": "xsd",
+ "http://rdfs.org/sioc/ns#": "sioc",
+ "http://xmlns.com/foaf/0.1/": "foaf",
+ "http://purl.org/dc/elements/1.1/": "dc",
+ "http://purl.org/dc/terms/": "dct",
+ "http://purl.org/rss/1.0/modules/content/": "content",
+ "http://www.w3.org/2003/01/geo/wgs84_pos#": "geo",
+ "http://www.w3.org/2004/02/skos/core#": "skos",
+ "http://lv2plug.in/ns/lv2core#": "lv2",
+ "http://usefulinc.com/ns/doap#": "doap",
+ "http://ontologi.es/doap-changeset#": "dcs",
+}
+
+rdf = rdflib.Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
+rdfs = rdflib.Namespace("http://www.w3.org/2000/01/rdf-schema#")
+owl = rdflib.Namespace("http://www.w3.org/2002/07/owl#")
+lv2 = rdflib.Namespace("http://lv2plug.in/ns/lv2core#")
+doap = rdflib.Namespace("http://usefulinc.com/ns/doap#")
+dcs = rdflib.Namespace("http://ontologi.es/doap-changeset#")
+foaf = rdflib.Namespace("http://xmlns.com/foaf/0.1/")
def findStatements(model, s, p, o):
@@ -110,10 +116,10 @@ def findStatements(model, s, p, o):
def findOne(m, s, p, o):
- l = findStatements(m, s, p, o)
+ triples = findStatements(m, s, p, o)
try:
- return l.next()
- except:
+ return sorted(triples)[0]
+ except Exception:
return None
@@ -146,6 +152,12 @@ def isLiteral(n):
def niceName(uri):
+ global spec_bundle
+ if uri.startswith(spec_ns_str):
+ return uri[len(spec_ns_str) :]
+ elif uri == str(rdfs.seeAlso):
+ return "See also"
+
regexp = re.compile("^(.*[/#])([^/#]+)$")
rez = regexp.search(uri)
if not rez:
@@ -165,148 +177,131 @@ def termName(m, urinode):
def getLabel(m, urinode):
- l = findOne(m, urinode, rdfs.label, None)
- if l:
- return getLiteralString(getObject(l))
+ statement = findOne(m, urinode, rdfs.label, None)
+ if statement:
+ return getLiteralString(getObject(statement))
else:
- return ''
-
-if have_pygments:
- # Based on sw.py by Philip Cooper
- class Notation3Lexer(RegexLexer):
- """
- Lexer for N3 / Turtle / NT
- """
- name = 'N3'
- aliases = ['n3', 'turtle']
- filenames = ['*.n3', '*.ttl', '*.nt']
- mimetypes = ['text/rdf+n3','application/x-turtle','application/n3']
-
- tokens = {
- 'comments': [
- (r'(\s*#.*)', Comment)
- ],
- 'root': [
- include('comments'),
- (r'(\s*@(?:prefix|base|keywords)\s*)(\w*:\s+)?(<[^> ]*>\s*\.\s*)',bygroups(Keyword,Name.Variable,Name.Namespace)),
- (r'\s*(<[^>]*\>)', Name.Class, ('triple','predObj')),
- (r'(\s*[a-zA-Z_:][a-zA-Z0-9\-_:]*\s)', Name.Class, ('triple','predObj')),
- (r'\s*\[\]\s*', Name.Class, ('triple','predObj')),
- ],
- 'triple' : [
- (r'\s*\.\s*', Text, '#pop')
- ],
- 'predObj': [
- include('comments'),
- (r'\s*a\s*', Name.Keyword, 'object'),
- (r'\s*[a-zA-Z_:][a-zA-Z0-9\-_:]*\b\s*', Name.Tag, 'object'),
- (r'\s*(<[^>]*\>)', Name.Tag, 'object'),
- (r'\s*\]\s*', Text, '#pop'),
- (r'(?=\s*\.\s*)', Keyword, '#pop'),
- ],
- 'objList': [
- include('comments'),
- (r'\s*\)', Text, '#pop'),
- include('object')
- ],
- 'object': [
- include('comments'),
- (r'\s*\[', Text, 'predObj'),
- (r'\s*<[^> ]*>', Name.Tag),
- (r'\s*("""(?:.|\n)*?""")(\@[a-z]{2-4}|\^\^<?[a-zA-Z0-9\-\:_#/\.]*>?)?\s*', bygroups(Literal.String,Text)),
- (r'\s*".*?[^\\]"(?:\@[a-z]{2-4}|\^\^<?[a-zA-Z0-9\-\:_#/\.]*>?)?\s*', Literal.String),
- (r'\s*[0-9]+\.[0-9]*\s*\n?', Literal.Number),
- (r'\s*[0-9]+\s*\n?', Literal.Number),
- (r'\s*[a-zA-Z0-9\-_\:]+\s*', Name.Tag),
- (r'\s*\(', Text, 'objList'),
- (r'\s*;\s*\n?', Punctuation, '#pop'),
- (r'\s*,\s*\n?', Punctuation), # Added by drobilla so "," is not an error
- (r'(?=\s*\])', Text, '#pop'),
- (r'(?=\s*\.)', Text, '#pop'),
- ],
- }
-
-def linkify(string):
+ return ""
+
+
+def linkifyCodeIdentifiers(string):
+ "Add links to code documentation for identifiers like LV2_Type"
+
if linkmap == {}:
return string
- "Add links to code documentation for identifiers"
if string in linkmap.keys():
# Exact match for complete string
return linkmap[string]
- rgx = re.compile('([^a-zA-Z0-9_:])(' + \
- '|'.join(map(re.escape, linkmap)) + \
- ')([^a-zA-Z0-9_:])')
+ rgx = re.compile(
+ "([^a-zA-Z0-9_:])("
+ + "|".join(map(re.escape, linkmap))
+ + ")([^a-zA-Z0-9_:])"
+ )
def translateCodeLink(match):
return match.group(1) + linkmap[match.group(2)] + match.group(3)
-
+
return rgx.sub(translateCodeLink, string)
-def getComment(m, urinode, classlist, proplist, instalist):
- c = findOne(m, urinode, lv2.documentation, None)
- if c:
- markup = getLiteralString(getObject(c))
-
- # Syntax highlight all C code
- if have_pygments:
- code_rgx = re.compile('<pre class="c-code">(.*?)</pre>', re.DOTALL)
- while True:
- code = code_rgx.search(markup)
- if not code:
- break
- match_str = xml.sax.saxutils.unescape(code.group(1))
- code_str = pygments.highlight(
- match_str,
- pygments.lexers.CLexer(),
- pygments.formatters.HtmlFormatter())
- markup = code_rgx.sub(code_str, markup, 1)
-
- # Syntax highlight all Turtle code
- if have_pygments:
- code_rgx = re.compile('<pre class="turtle-code">(.*?)</pre>', re.DOTALL)
- while True:
- code = code_rgx.search(markup)
- if not code:
- break
- match_str = xml.sax.saxutils.unescape(code.group(1))
- code_str = pygments.highlight(
- match_str,
- Notation3Lexer(),
- pygments.formatters.HtmlFormatter())
- markup = code_rgx.sub(code_str, markup, 1)
-
- # Add links to code documentation for identifiers
- markup = linkify(markup)
-
- # Transform prefixed names like eg:something into links if possible
- rgx = re.compile('([a-zA-Z0-9_-]+):([a-zA-Z0-9_-]+)')
- namespaces = getNamespaces(m)
- def translateLink(match):
- text = match.group(0)
- prefix = match.group(1)
- name = match.group(2)
- curie = match.group(0)
- uri = rdflib.URIRef(spec_ns + name)
- if prefix == spec_pre:
- if not ((classlist and uri in classlist) or
- (instalist and uri in instalist) or
- (proplist and uri in proplist)):
- print("warning: Link to undefined resource <%s>\n" % text)
- return '<a href="#%s">%s</a>' % (name, curie)
- elif prefix in namespaces:
- return '<a href="%s">%s</a>' % (
- namespaces[match.group(1)] + match.group(2),
- match.group(0))
- else:
- return text
- markup = rgx.sub(translateLink, markup)
-
- if have_lxml:
- try:
- # Parse and validate documentation as XHTML Basic 1.1
- doc = """<?xml version="1.0" encoding="UTF-8"?>
+
+def linkifyVocabIdentifiers(m, string, classlist, proplist, instalist):
+ "Add links to vocabulary documentation for prefixed names like eg:Thing"
+
+ rgx = re.compile("([a-zA-Z0-9_-]+):([a-zA-Z0-9_-]+)")
+ namespaces = getNamespaces(m)
+
+ def translateLink(match):
+ text = match.group(0)
+ prefix = match.group(1)
+ name = match.group(2)
+ uri = rdflib.URIRef(spec_ns + name)
+ if prefix == spec_pre:
+ if not (
+ (classlist and uri in classlist)
+ or (instalist and uri in instalist)
+ or (proplist and uri in proplist)
+ ):
+ print("warning: Link to undefined resource <%s>\n" % text)
+ return '<a href="#%s">%s</a>' % (name, name)
+ elif prefix in namespaces:
+ return '<a href="%s">%s</a>' % (
+ namespaces[match.group(1)] + match.group(2),
+ match.group(0),
+ )
+ else:
+ return text
+
+ return rgx.sub(translateLink, string)
+
+
+def prettifyHtml(m, markup, subject, classlist, proplist, instalist):
+ # Syntax highlight all C code
+ if have_pygments:
+ code_rgx = re.compile('<pre class="c-code">(.*?)</pre>', re.DOTALL)
+ while True:
+ code = code_rgx.search(markup)
+ if not code:
+ break
+ match_str = xml.sax.saxutils.unescape(code.group(1))
+ code_str = pygments.highlight(
+ match_str,
+ pygments.lexers.CLexer(),
+ pygments.formatters.HtmlFormatter(),
+ )
+ markup = code_rgx.sub(code_str, markup, 1)
+
+ # Syntax highlight all Turtle code
+ if have_pygments:
+ code_rgx = re.compile(
+ '<pre class="turtle-code">(.*?)</pre>', re.DOTALL
+ )
+ while True:
+ code = code_rgx.search(markup)
+ if not code:
+ break
+ match_str = xml.sax.saxutils.unescape(code.group(1))
+ code_str = pygments.highlight(
+ match_str,
+ pygments.lexers.rdf.TurtleLexer(),
+ pygments.formatters.HtmlFormatter(),
+ )
+ markup = code_rgx.sub(code_str, markup, 1)
+
+ # Add links to code documentation for identifiers
+ markup = linkifyCodeIdentifiers(markup)
+
+ # Add internal links for known prefixed names
+ markup = linkifyVocabIdentifiers(m, markup, classlist, proplist, instalist)
+
+ # Transform names like #foo into links into this spec if possible
+ rgx = re.compile("([ \t\n\r\f\v^]+)#([a-zA-Z0-9_-]+)")
+
+ def translateLocalLink(match):
+ text = match.group(0)
+ space = match.group(1)
+ name = match.group(2)
+ uri = rdflib.URIRef(spec_ns + name)
+ if (
+ (classlist and uri in classlist)
+ or (instalist and uri in instalist)
+ or (proplist and uri in proplist)
+ ):
+ return '%s<a href="#%s">%s</a>' % (space, name, name)
+ else:
+ print("warning: Link to undefined resource <%s>\n" % name)
+ return text
+
+ markup = rgx.sub(translateLocalLink, markup)
+
+ if not have_lxml:
+ print("warning: No Python lxml module found, output may be invalid")
+ else:
+ try:
+ # Parse and validate documentation as XHTML Basic 1.1
+ doc = (
+ """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
"DTD/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
@@ -314,43 +309,108 @@ def getComment(m, urinode, classlist, proplist, instalist):
<title>Validation Skeleton Document</title>
</head>
<body>
-%s
+"""
+ + markup
+ + """
</body>
-</html>
-""" % str(markup.decode())
-
- oldcwd = os.getcwd()
- os.chdir(specgendir)
- parser = etree.XMLParser(dtd_validation=True, no_network=True)
- root = etree.fromstring(doc, parser)
- os.chdir(oldcwd)
- except Exception as e:
- print("Invalid lv2:documentation for %s\n%s" % (urinode, e))
+</html>"""
+ )
+
+ oldcwd = os.getcwd()
+ os.chdir(specgendir)
+ parser = etree.XMLParser(dtd_validation=True, no_network=True)
+ etree.fromstring(doc.encode("utf-8"), parser)
+ except Exception as e:
+ print("Invalid documentation for %s\n%s" % (subject, e))
+ line_num = 1
+ for line in doc.split("\n"):
+ print("%3d: %s" % (line_num, line))
+ line_num += 1
+ finally:
+ os.chdir(oldcwd)
+
+ return markup
+
+
+def formatDoc(m, urinode, literal, classlist, proplist, instalist):
+ string = getLiteralString(literal)
+
+ if literal.datatype == lv2.Markdown:
+ ext = [
+ "markdown.extensions.codehilite",
+ "markdown.extensions.tables",
+ "markdown.extensions.def_list",
+ ]
+
+ doc = markdown.markdown(string, extensions=ext)
+
+ # Hack to make tables valid XHTML Basic 1.1
+ for tag in ["thead", "tbody"]:
+ doc = doc.replace("<%s>\n" % tag, "")
+ doc = doc.replace("</%s>\n" % tag, "")
+
+ return prettifyHtml(m, doc, urinode, classlist, proplist, instalist)
+ else:
+ doc = xml.sax.saxutils.escape(string)
+ doc = linkifyCodeIdentifiers(doc)
+ doc = linkifyVocabIdentifiers(m, doc, classlist, proplist, instalist)
+ return "<p>%s</p>" % doc
- return markup
- c = findOne(m, urinode, rdfs.comment, None)
+def getComment(m, subject, classlist, proplist, instalist):
+ c = findOne(m, subject, rdfs.comment, None)
if c:
- text = getLiteralString(getObject(c))
- return '<p>%s</p>' % xml.sax.saxutils.escape(text)
+ comment = getObject(c)
+ return formatDoc(m, subject, comment, classlist, proplist, instalist)
+
+ return ""
+
- return ''
+def getDetailedDocumentation(m, subject, classlist, proplist, instalist):
+ markup = ""
+
+ d = findOne(m, subject, lv2.documentation, None)
+ if d:
+ doc = getObject(d)
+ if doc.datatype == lv2.Markdown:
+ markup += formatDoc(
+ m, subject, doc, classlist, proplist, instalist
+ )
+ else:
+ html = getLiteralString(doc)
+ markup += prettifyHtml(
+ m, html, subject, classlist, proplist, instalist
+ )
+
+ return markup
+
+
+def getFullDocumentation(m, subject, classlist, proplist, instalist):
+ # Use rdfs:comment for first summary line
+ markup = getComment(m, subject, classlist, proplist, instalist)
+
+ # Use lv2:documentation for further details
+ markup += getDetailedDocumentation(
+ m, subject, classlist, proplist, instalist
+ )
+
+ return markup
def getProperty(val, first=True):
"Return a string representing a property value in a property table"
- doc = ''
+ doc = ""
if not first:
- doc += '<tr><td></td>' # Empty cell in header column
- doc += '<td>%s</td></tr>\n' % val
+ doc += "<tr><th></th>" # Empty cell in header column
+ doc += "<td>%s</td></tr>\n" % val
return doc
def endProperties(first):
if first:
- return '</tr>'
+ return "</tr>"
else:
- return ''
+ return ""
def rdfsPropertyInfo(term, m):
@@ -358,54 +418,64 @@ def rdfsPropertyInfo(term, m):
global classranges
global classdomains
doc = ""
- range = ""
- domain = ""
+
+ label = getLabel(m, term)
+ if label != "":
+ doc += "<tr><th>Label</th><td>%s</td></tr>" % label
# Find subPropertyOf information
- rlist = ''
+ rlist = ""
first = True
for st in findStatements(m, term, rdfs.subPropertyOf, None):
k = getTermLink(getObject(st), term, rdfs.subPropertyOf)
rlist += getProperty(k, first)
first = False
- if rlist != '':
- doc += '<tr><th>Sub-property of</th>' + rlist
+ if rlist != "":
+ doc += "<tr><th>Sub-property of</th>" + rlist
# Domain stuff
domains = findStatements(m, term, rdfs.domain, None)
domainsdoc = ""
first = True
- for d in domains:
+ for d in sorted(domains):
union = findOne(m, getObject(d), owl.unionOf, None)
if union:
uris = parseCollection(m, getObject(union))
for uri in uris:
- domainsdoc += getProperty(getTermLink(uri, term, rdfs.domain), first)
+ domainsdoc += getProperty(
+ getTermLink(uri, term, rdfs.domain), first
+ )
add(classdomains, uri, term)
else:
if not isBlank(getObject(d)):
- domainsdoc += getProperty(getTermLink(getObject(d), term, rdfs.domain), first)
+ domainsdoc += getProperty(
+ getTermLink(getObject(d), term, rdfs.domain), first
+ )
first = False
- if (len(domainsdoc) > 0):
+ if len(domainsdoc) > 0:
doc += "<tr><th>Domain</th>%s" % domainsdoc
# Range stuff
ranges = findStatements(m, term, rdfs.range, None)
rangesdoc = ""
first = True
- for r in ranges:
+ for r in sorted(ranges):
union = findOne(m, getObject(r), owl.unionOf, None)
if union:
uris = parseCollection(m, getObject(union))
for uri in uris:
- rangesdoc += getProperty(getTermLink(uri, term, rdfs.range), first)
+ rangesdoc += getProperty(
+ getTermLink(uri, term, rdfs.range), first
+ )
add(classranges, uri, term)
first = False
else:
if not isBlank(getObject(r)):
- rangesdoc += getProperty(getTermLink(getObject(r), term, rdfs.range), first)
+ rangesdoc += getProperty(
+ getTermLink(getObject(r), term, rdfs.range), first
+ )
first = False
- if (len(rangesdoc) > 0):
+ if len(rangesdoc) > 0:
doc += "<tr><th>Range</th>%s" % rangesdoc
return doc
@@ -416,10 +486,10 @@ def parseCollection(model, node):
while node:
first = findOne(model, node, rdf.first, None)
- rest = findOne(model, node, rdf.rest, None)
+ rest = findOne(model, node, rdf.rest, None)
if not first or not rest:
- break;
-
+ break
+
uris.append(getObject(first))
node = getObject(rest)
@@ -428,41 +498,36 @@ def parseCollection(model, node):
def getTermLink(uri, subject=None, predicate=None):
uri = str(uri)
- extra = ''
- if subject != None and predicate != None:
- extra = 'about="%s" rel="%s" resource="%s"' % (str(subject), niceName(str(predicate)), uri)
- if (uri.startswith(spec_ns_str)):
- return '<a href="#%s" %s>%s</a>' % (uri.replace(spec_ns_str, ""), extra, niceName(uri))
+ extra = ""
+ if subject is not None and predicate is not None:
+ extra = 'about="%s" rel="%s" resource="%s"' % (
+ str(subject),
+ niceName(str(predicate)),
+ uri,
+ )
+ if uri.startswith(spec_ns_str):
+ return '<a href="#%s" %s>%s</a>' % (
+ uri.replace(spec_ns_str, ""),
+ extra,
+ niceName(uri),
+ )
else:
return '<a href="%s" %s>%s</a>' % (uri, extra, niceName(uri))
-def rdfsClassInfo(term, m):
- """Generate rdfs-type information for Classes: ranges, and domains."""
- global classranges
- global classdomains
- doc = ""
-
- # Find subClassOf information
+def owlRestrictionInfo(term, m):
+ """Generate OWL restriction information for Classes"""
restrictions = []
- superclasses = []
- for st in findStatements(m, term, rdfs.subClassOf, None):
- if not isBlank(getObject(st)):
- uri = getObject(st)
- if not uri in superclasses:
- superclasses.append(uri)
- else:
- meta_type = findOne(m, getObject(st), rdf.type, None)
- restrictions.append(getSubject(meta_type))
-
- if len(superclasses) > 0:
- doc += "\n<tr><th>Sub-class of</th>"
- first = True
- for superclass in superclasses:
- doc += getProperty(getTermLink(superclass), first)
- first = False
+ for s in findStatements(m, term, rdfs.subClassOf, None):
+ if findOne(m, getObject(s), rdf.type, owl.Restriction):
+ restrictions.append(getObject(s))
+
+ if not restrictions:
+ return ""
+
+ doc = "<dl>"
- for r in restrictions:
+ for r in sorted(restrictions):
props = findStatements(m, r, None, None)
onProp = None
comment = None
@@ -471,46 +536,82 @@ def rdfsClassInfo(term, m):
onProp = getObject(p)
elif getPredicate(p) == rdfs.comment:
comment = getObject(p)
- if onProp != None:
- doc += '<tr><th>Restriction on %s</th><td>' % getTermLink(onProp)
+ if onProp is not None:
+ doc += "<dt>Restriction on %s</dt>\n" % getTermLink(onProp)
- prop_str = ''
- last_pred = None
- first = True
+ prop_str = ""
for p in findStatements(m, r, None, None):
- if (getPredicate(p) == owl.onProperty
+ if (
+ getPredicate(p) == owl.onProperty
or getPredicate(p) == rdfs.comment
- or (getPredicate(p) == rdf.type and getObject(p) == owl.Restriction)
- or getPredicate(p) == lv2.documentation):
- last_pred = None
+ or (
+ getPredicate(p) == rdf.type
+ and getObject(p) == owl.Restriction
+ )
+ or getPredicate(p) == lv2.documentation
+ ):
continue
- if getPredicate(p) != last_pred:
- prop_str += '<tr><th>%s</th>\n' % getTermLink(getPredicate(p))
- first = True
+ prop_str += getTermLink(getPredicate(p))
+
if isResource(getObject(p)):
- prop_str += getProperty(getTermLink(getObject(p)), first)
- first = False
+ prop_str += " " + getTermLink(getObject(p))
elif isLiteral(getObject(p)):
- prop_str += getProperty(getLiteralString(getObject(p)), first)
- first = False
+ prop_str += " " + getLiteralString(getObject(p))
+
+ if comment is not None:
+ prop_str += "\n<div>%s</div>\n" % getLiteralString(comment)
- last_pred = getPredicate(p)
+ doc += "<dd>%s</dd>" % prop_str if prop_str else ""
- prop_str += endProperties(first)
+ doc += "</dl>"
+ return doc
- if prop_str != '':
- doc += '<table class=\"restriction\">%s</table>\n' % prop_str
- if comment != None:
- doc += "<span>%s</span>\n" % getLiteralString(comment)
- doc += '</td></tr>'
+
+def rdfsClassInfo(term, m):
+ """Generate rdfs-type information for Classes: ranges, and domains."""
+ global classranges
+ global classdomains
+ doc = ""
+
+ label = getLabel(m, term)
+ if label != "":
+ doc += "<tr><th>Label</th><td>%s</td></tr>" % label
+
+ # Find superclasses
+ superclasses = set()
+ for st in findStatements(m, term, rdfs.subClassOf, None):
+ if not isBlank(getObject(st)):
+ uri = getObject(st)
+ superclasses |= set([uri])
+
+ if len(superclasses) > 0:
+ doc += "\n<tr><th>Subclass of</th>"
+ first = True
+ for superclass in sorted(superclasses):
+ doc += getProperty(getTermLink(superclass), first)
+ first = False
+
+ # Find subclasses
+ subclasses = set()
+ for st in findStatements(m, None, rdfs.subClassOf, term):
+ if not isBlank(getObject(st)):
+ uri = getSubject(st)
+ subclasses |= set([uri])
+
+ if len(subclasses) > 0:
+ doc += "\n<tr><th>Superclass of</th>"
+ first = True
+ for superclass in sorted(subclasses):
+ doc += getProperty(getTermLink(superclass), first)
+ first = False
# Find out about properties which have rdfs:domain of t
d = classdomains.get(str(term), "")
if d:
- dlist = ''
+ dlist = ""
first = True
- for k in d:
+ for k in sorted(d):
dlist += getProperty(getTermLink(k), first)
first = False
doc += "<tr><th>In domain of</th>%s" % dlist
@@ -518,9 +619,9 @@ def rdfsClassInfo(term, m):
# Find out about properties which have rdfs:range of t
r = classranges.get(str(term), "")
if r:
- rlist = ''
+ rlist = ""
first = True
- for k in r:
+ for k in sorted(r):
rlist += getProperty(getTermLink(k), first)
first = False
doc += "<tr><th>In range of</th>%s" % rlist
@@ -529,30 +630,45 @@ def rdfsClassInfo(term, m):
def isSpecial(pred):
- """Return True if the predicate is "special" and shouldn't be emitted generically"""
- return pred in [rdf.type, rdfs.range, rdfs.domain, rdfs.label, rdfs.comment, rdfs.subClassOf, rdfs.subPropertyOf, lv2.documentation]
+ """Return True if `pred` shouldn't be documented generically"""
+ return pred in [
+ rdf.type,
+ rdfs.range,
+ rdfs.domain,
+ rdfs.label,
+ rdfs.comment,
+ rdfs.subClassOf,
+ rdfs.subPropertyOf,
+ lv2.documentation,
+ owl.withRestrictions,
+ ]
def blankNodeDesc(node, m):
properties = findStatements(m, node, None, None)
- doc = ''
- last_pred = ''
- for p in properties:
+ doc = ""
+ for p in sorted(properties):
if isSpecial(getPredicate(p)):
continue
- doc += '<tr>'
+ doc += "<tr>"
doc += '<td class="blankterm">%s</td>\n' % getTermLink(getPredicate(p))
if isResource(getObject(p)):
doc += '<td class="blankdef">%s</td>\n' % getTermLink(getObject(p))
# getTermLink(str(getObject(p)), node, getPredicate(p))
elif isLiteral(getObject(p)):
- doc += '<td class="blankdef">%s</td>\n' % getLiteralString(getObject(p))
+ doc += '<td class="blankdef">%s</td>\n' % getLiteralString(
+ getObject(p)
+ )
elif isBlank(getObject(p)):
- doc += '<td class="blankdef">' + blankNodeDesc(getObject(p), m) + '</td>\n'
+ doc += (
+ '<td class="blankdef">'
+ + blankNodeDesc(getObject(p), m)
+ + "</td>\n"
+ )
else:
doc += '<td class="blankdef">?</td>\n'
- doc += '</tr>'
- if doc != '':
+ doc += "</tr>"
+ if doc != "":
doc = '<table class="blankdesc">\n%s\n</table>\n' % doc
return doc
@@ -561,27 +677,25 @@ def extraInfo(term, m):
"""Generate information about misc. properties of a term"""
doc = ""
properties = findStatements(m, term, None, None)
- last_pred = None
first = True
- for p in properties:
+ for p in sorted(properties):
if isSpecial(getPredicate(p)):
- last_pred = None
continue
- if getPredicate(p) != last_pred:
- doc += '<tr><th>%s</th>\n' % getTermLink(getPredicate(p))
- first = True
+ doc += "<tr><th>%s</th>\n" % getTermLink(getPredicate(p))
if isResource(getObject(p)):
- doc += getProperty(getTermLink(getObject(p), term, getPredicate(p)), first)
+ doc += getProperty(
+ getTermLink(getObject(p), term, getPredicate(p)), first
+ )
elif isLiteral(getObject(p)):
- doc += getProperty(linkify(str(getObject(p))), first)
+ doc += getProperty(
+ linkifyCodeIdentifiers(str(getObject(p))), first
+ )
elif isBlank(getObject(p)):
doc += getProperty(str(blankNodeDesc(getObject(p), m)), first)
else:
- doc += getProperty('?', first)
- first = False
- last_pred = getPredicate(p)
+ doc += getProperty("?", first)
- #doc += endProperties(first)
+ # doc += endProperties(first)
return doc
@@ -590,16 +704,20 @@ def rdfsInstanceInfo(term, m):
"""Generate rdfs-type information for instances"""
doc = ""
+ label = getLabel(m, term)
+ if label != "":
+ doc += "<tr><th>Label</th><td>%s</td></tr>" % label
+
first = True
- for match in findStatements(m, term, rdf.type, None):
- doc += getProperty(getTermLink(getObject(match),
- term,
- rdf.type),
- first)
+ types = ""
+ for match in sorted(findStatements(m, term, rdf.type, None)):
+ types += getProperty(
+ getTermLink(getObject(match), term, rdf.type), first
+ )
first = False
- if doc != "":
- doc = "<tr><th>Type</th>" + doc
+ if types != "":
+ doc += "<tr><th>Type</th>" + types
doc += endProperties(first)
@@ -608,7 +726,7 @@ def rdfsInstanceInfo(term, m):
def owlInfo(term, m):
"""Returns an extra information that is defined about a term using OWL."""
- res = ''
+ res = ""
# Inverse properties ( owl:inverseOf )
first = True
@@ -621,78 +739,81 @@ def owlInfo(term, m):
def owlTypeInfo(term, propertyType, name):
if findOne(m, term, rdf.type, propertyType):
- return "<tr><th>OWL Type</th><td>%s</td></tr>\n" % name
+ return "<tr><th>Type</th><td>%s</td></tr>\n" % name
else:
return ""
res += owlTypeInfo(term, owl.DatatypeProperty, "Datatype Property")
res += owlTypeInfo(term, owl.ObjectProperty, "Object Property")
res += owlTypeInfo(term, owl.AnnotationProperty, "Annotation Property")
- res += owlTypeInfo(term, owl.InverseFunctionalProperty, "Inverse Functional Property")
+ res += owlTypeInfo(
+ term, owl.InverseFunctionalProperty, "Inverse Functional Property"
+ )
res += owlTypeInfo(term, owl.SymmetricProperty, "Symmetric Property")
return res
+def isDeprecated(m, subject):
+ deprecated = findOne(m, subject, owl.deprecated, None)
+ return deprecated and (str(deprecated[2]).find("true") >= 0)
+
+
def docTerms(category, list, m, classlist, proplist, instalist):
"""
A wrapper class for listing all the terms in a specific class (either
Properties, or Classes. Category is 'Property' or 'Class', list is a
- list of term names (strings), return value is a chunk of HTML.
+ list of term URI strings, return value is a chunk of HTML.
"""
doc = ""
- nspre = spec_pre
- for item in list:
- t = termName(m, item)
- if (t.startswith(spec_ns_str)) and (
- len(t[len(spec_ns_str):].split("/")) < 2):
- term = t
- t = t.split(spec_ns_str[-1])[1]
- curie = "%s:%s" % (nspre, t)
- else:
- if t.startswith("http://"):
- term = t
- curie = getShortName(t)
- t = getAnchor(t)
- else:
- term = spec_ns[t]
- curie = "%s:%s" % (nspre, t)
-
- term_uri = term
+ for term in list:
+ if not term.startswith(spec_ns_str):
+ sys.stderr.write("warning: Skipping external term `%s'" % term)
+ continue
- doc += """<div class="specterm" id="%s" about="%s">\n<h3>%s <a href="#%s">%s</a></h3>\n""" % (t, term_uri, category, getAnchor(str(term_uri)), curie)
+ t = termName(m, term)
+ curie = term.split(spec_ns_str[-1])[1]
+ doc += '<div class="specterm" id="%s" about="%s">' % (t, term)
+ doc += '<h3><a href="#%s">%s</a></h3>' % (getAnchor(term), curie)
+ doc += '<span class="spectermtype">%s</span>' % category
- label = getLabel(m, term)
- comment = getComment(m, term, classlist, proplist, instalist)
+ comment = getFullDocumentation(m, term, classlist, proplist, instalist)
+ is_deprecated = isDeprecated(m, term)
doc += '<div class="spectermbody">'
- if label != '' or comment != '':
- doc += '<div class="description">'
-
- if label != '':
- doc += "<div property=\"rdfs:label\" class=\"label\">%s</div>" % label
-
- if comment != '':
- doc += "<div property=\"rdfs:comment\">%s</div>" % comment
-
- if label != '' or comment != '':
- doc += "</div>"
terminfo = ""
- if category == 'Property':
- terminfo += owlInfo(term, m)
+ extrainfo = ""
+ if category == "Property":
terminfo += rdfsPropertyInfo(term, m)
- if category == 'Class':
+ terminfo += owlInfo(term, m)
+ if category == "Class":
terminfo += rdfsClassInfo(term, m)
- if category == 'Instance':
+ extrainfo += owlRestrictionInfo(term, m)
+ if category == "Instance":
terminfo += rdfsInstanceInfo(term, m)
terminfo += extraInfo(term, m)
- if (len(terminfo) > 0): # to prevent empty list (bug #882)
+ if len(terminfo) > 0: # to prevent empty list (bug #882)
doc += '\n<table class="terminfo">%s</table>\n' % terminfo
- doc += '</div>'
+ doc += '<div class="description">'
+
+ if is_deprecated:
+ doc += '<div class="warning">Deprecated</div>'
+
+ if comment != "":
+ doc += (
+ '<div class="comment" property="rdfs:comment">%s</div>'
+ % comment
+ )
+
+ doc += extrainfo
+
+ doc += "</div>"
+
+ doc += "</div>"
doc += "\n</div>\n\n"
return doc
@@ -700,7 +821,7 @@ def docTerms(category, list, m, classlist, proplist, instalist):
def getShortName(uri):
uri = str(uri)
- if ("#" in uri):
+ if "#" in uri:
return uri.split("#")[-1]
else:
return uri.split("/")[-1]
@@ -708,29 +829,31 @@ def getShortName(uri):
def getAnchor(uri):
uri = str(uri)
- if (uri.startswith(spec_ns_str)):
- return uri[len(spec_ns_str):].replace("/", "_")
+ if uri.startswith(spec_ns_str):
+ return uri[len(spec_ns_str) :].replace("/", "_")
else:
return getShortName(uri)
def buildIndex(m, classlist, proplist, instalist=None):
- """
- Builds the A-Z list of terms. Args are a list of classes (strings) and
- a list of props (strings)
- """
+ if not (classlist or proplist or instalist):
+ return ""
- if len(classlist) == 0 and len(proplist) == 0 and (
- not instalist or len(instalist) == 0):
- return ''
+ head = ""
+ body = ""
- azlist = '<dl class="index">'
+ def termLink(m, t):
+ if str(t).startswith(spec_ns_str):
+ name = termName(m, t)
+ return '<a href="#%s">%s</a>' % (name, name)
+ else:
+ return '<a href="%s">%s</a>' % (str(t), str(t))
- if (len(classlist) > 0):
- azlist += "<dt>Classes</dt><dd><ul>"
- classlist.sort()
+ if len(classlist) > 0:
+ head += '<th><a href="#ref-classes" />Classes</th>'
+ body += "<td><ul>"
shown = {}
- for c in classlist:
+ for c in sorted(classlist):
if c in shown:
continue
@@ -738,65 +861,66 @@ def buildIndex(m, classlist, proplist, instalist=None):
local_subclass = False
for p in findStatements(m, c, rdfs.subClassOf, None):
parent = str(p[2])
- if parent[0:len(spec_ns_str)] == spec_ns_str:
+ if parent[0 : len(spec_ns_str)] == spec_ns_str:
local_subclass = True
if local_subclass:
continue
shown[c] = True
- name = termName(m, c)
- if name.startswith(spec_ns_str):
- name = name.split(spec_ns_str[-1])[1]
- azlist += '<li><a href="#%s">%s</a>' % (name, name)
+ body += "<li>" + termLink(m, c)
+
def class_tree(c):
- tree = ''
+ tree = ""
shown[c] = True
subclasses = []
for s in findStatements(m, None, rdfs.subClassOf, c):
subclasses += [getSubject(s)]
- subclasses.sort()
- for s in subclasses:
- s_name = termName(m, s)
- tree += '<li><a href="#%s">%s</a>\n' % (s_name, s_name)
+ for s in sorted(subclasses):
+ tree += "<li>" + termLink(m, s)
tree += class_tree(s)
- tree += '</li>'
- if tree != '':
- tree = '<ul>' + tree + '</ul>'
+ tree += "</li>"
+ if tree != "":
+ tree = "<ul>" + tree + "</ul>"
return tree
- azlist += class_tree(c)
- azlist += '</li>'
- azlist += '</ul></dd>\n'
-
- if (len(proplist) > 0):
- azlist += "<dt>Properties</dt><dd>"
- proplist.sort()
- props = []
- for p in proplist:
- name = termName(m, p)
- if name.startswith(spec_ns_str):
- name = name.split(spec_ns_str[-1])[1]
- props += ['<a href="#%s">%s</a>' % (name, name)]
- azlist += ', '.join(props) + '</dd>\n'
-
- if (instalist != None and len(instalist) > 0):
- azlist += "<dt>Instances</dt><dd>"
- instas = []
- for i in instalist:
+
+ body += class_tree(c)
+ body += "</li>"
+ body += "</ul></td>\n"
+
+ if len(proplist) > 0:
+ head += '<th><a href="#ref-properties" />Properties</th>'
+ body += "<td><ul>"
+ for p in sorted(proplist):
+ body += "<li>%s</li>" % termLink(m, p)
+ body += "</ul></td>\n"
+
+ if instalist is not None and len(instalist) > 0:
+ head += '<th><a href="#ref-instances" />Instances</th>'
+ body += "<td><ul>"
+ for i in sorted(instalist):
p = getShortName(i)
anchor = getAnchor(i)
- instas += ['<a href="#%s">%s</a>' % (anchor, p)]
- azlist += ', '.join(instas) + '</dd>\n'
+ body += '<li><a href="#%s">%s</a></li>' % (anchor, p)
+ body += "</ul></td>\n"
+
+ if head and body:
+ return """<table class="index">
+<thead><tr>%s</tr></thead>
+<tbody><tr>%s</tr></tbody></table>
+""" % (
+ head,
+ body,
+ )
- azlist += '\n</dl>'
- return azlist
+ return ""
def add(where, key, value):
- if not key in where:
+ if key not in where:
where[key] = []
- if not value in where[key]:
+ if value not in where[key]:
where[key].append(value)
@@ -814,23 +938,36 @@ def specInformation(m, ns):
classlist = []
for onetype in classtypes:
for classStatement in findStatements(m, None, rdf.type, onetype):
- for range in findStatements(m, None, rdfs.range, getSubject(classStatement)):
+ for range in findStatements(
+ m, None, rdfs.range, getSubject(classStatement)
+ ):
if not isBlank(getSubject(classStatement)):
- add(classranges,
+ add(
+ classranges,
str(getSubject(classStatement)),
- str(getSubject(range)))
- for domain in findStatements(m, None, rdfs.domain, getSubject(classStatement)):
+ str(getSubject(range)),
+ )
+ for domain in findStatements(
+ m, None, rdfs.domain, getSubject(classStatement)
+ ):
if not isBlank(getSubject(classStatement)):
- add(classdomains,
+ add(
+ classdomains,
str(getSubject(classStatement)),
- str(getSubject(domain)))
+ str(getSubject(domain)),
+ )
if not isBlank(getSubject(classStatement)):
klass = getSubject(classStatement)
if klass not in classlist and str(klass).startswith(ns):
classlist.append(klass)
# Create a list of properties in the schema.
- proptypes = [rdf.Property, owl.ObjectProperty, owl.DatatypeProperty, owl.AnnotationProperty]
+ proptypes = [
+ rdf.Property,
+ owl.ObjectProperty,
+ owl.DatatypeProperty,
+ owl.AnnotationProperty,
+ ]
proplist = []
for onetype in proptypes:
for propertyStatement in findStatements(m, None, rdf.type, onetype):
@@ -845,7 +982,7 @@ def specProperty(m, subject, predicate):
"Return a property of the spec."
for c in findStatements(m, subject, predicate, None):
return getLiteralString(getObject(c))
- return ''
+ return ""
def specProperties(m, subject, predicate):
@@ -858,94 +995,136 @@ def specProperties(m, subject, predicate):
def specAuthors(m, subject):
"Return an HTML description of the authors of the spec."
+
+ subjects = [subject]
+ p = findOne(m, subject, lv2.project, None)
+ if p:
+ subjects += [getObject(p)]
+
dev = set()
- for i in findStatements(m, subject, doap.developer, None):
- for j in findStatements(m, getObject(i), foaf.name, None):
- dev.add(getLiteralString(getObject(j)))
+ for s in subjects:
+ for i in findStatements(m, s, doap.developer, None):
+ for j in findStatements(m, getObject(i), foaf.name, None):
+ dev.add(getLiteralString(getObject(j)))
maint = set()
- for i in findStatements(m, subject, doap.maintainer, None):
- for j in findStatements(m, getObject(i), foaf.name, None):
- maint.add(getLiteralString(getObject(j)))
+ for s in subjects:
+ for i in findStatements(m, s, doap.maintainer, None):
+ for j in findStatements(m, getObject(i), foaf.name, None):
+ maint.add(getLiteralString(getObject(j)))
- doc = ''
+ doc = ""
- devdoc = ''
+ devdoc = ""
first = True
- for d in dev:
+ for d in sorted(dev):
if not first:
- devdoc += ', '
- devdoc += '<span class="author" property="doap:developer">%s</span>' % d
+ devdoc += ", "
+ devdoc += (
+ '<span class="author" property="doap:developer">%s</span>' % d
+ )
first = False
if len(dev) == 1:
- doc += '<tr><th class="metahead">Developer</th><td>%s</td></tr>' % devdoc
+ doc += (
+ '<tr><th class="metahead">Developer</th><td>%s</td></tr>' % devdoc
+ )
elif len(dev) > 0:
- doc += '<tr><th class="metahead">Developers</th><td>%s</td></tr>' % devdoc
+ doc += (
+ '<tr><th class="metahead">Developers</th><td>%s</td></tr>' % devdoc
+ )
- maintdoc = ''
+ maintdoc = ""
first = True
- for m in maint:
+ for m in sorted(maint):
if not first:
- maintdoc += ', '
- maintdoc += '<span class="author" property="doap:maintainer">%s</span>' % m
+ maintdoc += ", "
+ maintdoc += (
+ '<span class="author" property="doap:maintainer">%s</span>' % m
+ )
first = False
if len(maint) == 1:
- doc += '<tr><th class="metahead">Maintainer</th><td>%s</td></tr>' % maintdoc
+ doc += (
+ '<tr><th class="metahead">Maintainer</th><td>%s</td></tr>'
+ % maintdoc
+ )
elif len(maint) > 0:
- doc += '<tr><th class="metahead">Maintainers</th><td>%s</td></tr>' % maintdoc
+ doc += (
+ '<tr><th class="metahead">Maintainers</th><td>%s</td></tr>'
+ % maintdoc
+ )
return doc
-def specHistory(m, subject):
- entries = {}
+def releaseChangeset(m, release, prefix=""):
+ changeset = findOne(m, release, dcs.changeset, None)
+ if changeset is None:
+ return ""
+
+ entry = ""
+ # entry = '<dd><ul>\n'
+ for i in sorted(findStatements(m, getObject(changeset), dcs.item, None)):
+ item = getObject(i)
+ label = findOne(m, item, rdfs.label, None)
+ if not label:
+ print("error: dcs:item has no rdfs:label")
+ continue
+
+ text = getLiteralString(getObject(label))
+ if prefix:
+ text = prefix + ": " + text
+
+ entry += "<li>%s</li>\n" % text
+
+ # entry += '</ul></dd>\n'
+ return entry
+
+
+def specHistoryEntries(m, subject, entries):
for r in findStatements(m, subject, doap.release, None):
release = getObject(r)
revNode = findOne(m, release, doap.revision, None)
if not revNode:
- print "error: doap:release has no doap:revision"
+ print("error: doap:release has no doap:revision")
continue
rev = getLiteralString(getObject(revNode))
created = findOne(m, release, doap.created, None)
- dist = findOne(m, release, doap['file-release'], None)
+ dist = findOne(m, release, doap["file-release"], None)
if dist:
entry = '<dt><a href="%s">Version %s</a>' % (getObject(dist), rev)
else:
- entry = '<dt>Version %s' % rev
- #print "warning: doap:release has no doap:file-release"
+ entry = "<dt>Version %s" % rev
+ # print("warning: doap:release has no doap:file-release")
if created:
- entry += ' (%s)</dt>' % getLiteralString(getObject(created))
+ entry += " (%s)</dt>\n" % getLiteralString(getObject(created))
else:
entry += ' (<span class="warning">EXPERIMENTAL</span>)</dt>'
- changeset = findOne(m, release, dcs.changeset, None)
- if changeset:
- entry += '<dd><ul>'
- for i in findStatements(m, getObject(changeset), dcs.item, None):
- item = getObject(i)
- label = findOne(m, item, rdfs.label, None)
- if not label:
- print "error: dcs:item has no rdfs:label"
- continue
+ entry += "<dd><ul>\n%s" % releaseChangeset(m, release)
- entry += '<li>%s</li>' % getLiteralString(getObject(label))
+ if dist is not None:
+ entries[(getObject(created), getObject(dist))] = entry
- entry += '</ul></dd>\n'
+ return entries
- entries[rev] = entry
+def specHistoryMarkup(entries):
if len(entries) > 0:
- history = '<dl>'
+ history = "<dl>\n"
for e in sorted(entries.keys(), reverse=True):
- history += entries[e]
- history += '</dl>'
+ history += entries[e] + "</ul></dd>"
+ history += "</dl>\n"
return history
else:
- return ''
+ return ""
+
+
+def specHistory(m, subject):
+ return specHistoryMarkup(specHistoryEntries(m, subject, {}))
def specVersion(m, subject):
@@ -962,7 +1141,7 @@ def specVersion(m, subject):
latest_doap_revision = revision
latest_doap_release = getObject(i)
date = ""
- if latest_doap_release != None:
+ if latest_doap_release is not None:
for i in findStatements(m, latest_doap_release, doap.created, None):
date = getLiteralString(getObject(i))
@@ -990,16 +1169,19 @@ def getInstances(model, classes, properties):
if inst not in instances and str(inst) != spec_url:
instances.append(inst)
for i in findStatements(model, None, rdf.type, None):
- if ((not isResource(getSubject(i)))
+ if (
+ (not isResource(getSubject(i)))
or (getSubject(i) in classes)
or (getSubject(i) in instances)
- or (getSubject(i) in properties)):
+ or (getSubject(i) in properties)
+ ):
continue
full_uri = str(getSubject(i))
- if (full_uri.startswith(spec_ns_str)):
+ if full_uri.startswith(spec_ns_str):
instances.append(getSubject(i))
return instances
+
def load_tags(path, docdir):
"Build a (symbol => URI) map from a Doxygen tag file."
@@ -1009,45 +1191,175 @@ def load_tags(path, docdir):
def getChildText(elt, tagname):
"Return the content of the first child node with a certain tag name."
for e in elt.childNodes:
- if e.nodeType == xml.dom.Node.ELEMENT_NODE and e.tagName == tagname:
+ if (
+ e.nodeType == xml.dom.Node.ELEMENT_NODE
+ and e.tagName == tagname
+ ):
return e.firstChild.nodeValue
- return ''
-
- def linkTo(sym, url):
- return '<span><a href="%s/%s">%s</a></span>' % (docdir, url, sym)
-
- tagdoc = xml.dom.minidom.parse(path)
- root = tagdoc.documentElement
+ return ""
+
+ def linkTo(filename, anchor, sym):
+ if anchor:
+ return '<span><a href="%s/%s#%s">%s</a></span>' % (
+ docdir,
+ filename,
+ anchor,
+ sym,
+ )
+ else:
+ return '<span><a href="%s/%s">%s</a></span>' % (
+ docdir,
+ filename,
+ sym,
+ )
+
+ tagdoc = xml.dom.minidom.parse(path)
+ root = tagdoc.documentElement
linkmap = {}
for cn in root.childNodes:
- if (cn.nodeType == xml.dom.Node.ELEMENT_NODE
- and cn.tagName == 'compound'
- and cn.getAttribute('kind') != 'page'):
+ if (
+ cn.nodeType == xml.dom.Node.ELEMENT_NODE
+ and cn.tagName == "compound"
+ and cn.getAttribute("kind") != "page"
+ ):
+
+ name = getChildText(cn, "name")
+ filename = getChildText(cn, "filename")
+ anchor = getChildText(cn, "anchor")
+ if not filename.endswith(".html"):
+ filename += ".html"
+
+ if cn.getAttribute("kind") != "group":
+ linkmap[name] = linkTo(filename, anchor, name)
+
+ prefix = ""
+ if cn.getAttribute("kind") == "struct":
+ prefix = name + "::"
+
+ members = cn.getElementsByTagName("member")
+ for m in members:
+ mname = prefix + getChildText(m, "name")
+ mafile = getChildText(m, "anchorfile")
+ manchor = getChildText(m, "anchor")
+ linkmap[mname] = linkTo(mafile, manchor, mname)
- name = getChildText(cn, 'name')
- filename = getChildText(cn, 'filename')
- if not filename.endswith('.html'):
- filename += '.html'
+ return linkmap
- linkmap[name] = linkTo(name, filename)
- prefix = ''
- if cn.getAttribute('kind') != 'file':
- prefix = name + '::'
+def writeIndex(model, specloc, index_path, root_path, root_uri):
+ # Get extension URI
+ ext_node = model.value(None, rdf.type, lv2.Specification)
+ if not ext_node:
+ ext_node = model.value(None, rdf.type, owl.Ontology)
+ if not ext_node:
+ print("no extension found in %s" % bundle)
+ sys.exit(1)
- members = cn.getElementsByTagName('member')
- for m in members:
- mname = prefix + getChildText(m, 'name')
- mafile = getChildText(m, 'anchorfile')
- manchor = getChildText(m, 'anchor')
- linkmap[mname] = linkTo(
- mname, '%s#%s' % (mafile, manchor))
+ ext = str(ext_node)
- return linkmap
+ # Get version
+ minor = 0
+ micro = 0
+ try:
+ minor = int(model.value(ext_node, lv2.minorVersion, None))
+ micro = int(model.value(ext_node, lv2.microVersion, None))
+ except Exception:
+ print("warning: %s: failed to find version for %s" % (bundle, ext))
+
+ # Get date
+ date = None
+ for r in model.triples([ext_node, doap.release, None]):
+ revision = model.value(r[2], doap.revision, None)
+ if str(revision) == ("%d.%d" % (minor, micro)):
+ date = model.value(r[2], doap.created, None)
+ break
+
+ # Verify that this date is the latest
+ for r in model.triples([ext_node, doap.release, None]):
+ this_date = model.value(r[2], doap.created, None)
+ if this_date > date:
+ print(
+ "warning: %s revision %d.%d (%s) is not the latest release"
+ % (ext_node, minor, micro, date)
+ )
+ break
+
+ # Get name and short description
+ name = model.value(ext_node, doap.name, None)
+ shortdesc = model.value(ext_node, doap.shortdesc, None)
+
+ # Chop 'LV2' prefix from name for cleaner index
+ if name.startswith("LV2 "):
+ name = name[4:]
+
+ # Find relative link target
+ if root_uri and ext_node.startswith(root_uri):
+ target = ext_node[len(root_uri) :] + ".html"
+ else:
+ target = os.path.relpath(ext_node, root_path) + ".html"
+
+ stem = os.path.splitext(os.path.basename(target))[0]
+
+ # Specification (comment is to act as a sort key)
+ row = '<tr><!-- %s --><td><a rel="rdfs:seeAlso" href="%s">%s</a></td>' % (
+ b,
+ target,
+ name,
+ )
+
+ # API
+ row += "<td>"
+ row += '<a rel="rdfs:seeAlso" href="../doc/html/group__%s.html">%s</a>' % (
+ stem,
+ name,
+ )
+ row += "</td>"
+
+ # Description
+ if shortdesc:
+ row += "<td>" + str(shortdesc) + "</td>"
+ else:
+ row += "<td></td>"
-def specgen(specloc, indir, style_uri, docdir, tags, instances=False, offline=False):
+ # Version
+ version_str = "%s.%s" % (minor, micro)
+ if minor == 0 or (micro % 2 != 0):
+ row += '<td><span style="color: red">' + version_str + "</span></td>"
+ else:
+ row += "<td>" + version_str + "</td>"
+
+ # Status
+ deprecated = model.value(ext_node, owl.deprecated, None)
+ if minor == 0:
+ row += '<td><span class="error">Experimental</span></td>'
+ elif deprecated and str(deprecated[2]) != "false":
+ row += '<td><span class="warning">Deprecated</span></td>'
+ elif micro % 2 == 0:
+ row += '<td><span class="success">Stable</span></td>'
+
+ row += "</tr>"
+
+ index = open(index_path, "w")
+ index.write(row)
+ index.close()
+
+
+def specgen(
+ specloc,
+ indir,
+ style_uri,
+ docdir,
+ tags,
+ opts,
+ instances=False,
+ root_link=None,
+ index_path=None,
+ root_path=None,
+ root_uri=None,
+):
"""The meat and potatoes: Everything starts here."""
+ global spec_bundle
global spec_url
global spec_ns_str
global spec_ns
@@ -1056,6 +1368,7 @@ def specgen(specloc, indir, style_uri, docdir, tags, instances=False, offline=Fa
global specgendir
global linkmap
+ spec_bundle = "file://%s/" % os.path.abspath(os.path.dirname(specloc))
specgendir = os.path.abspath(indir)
# Template
@@ -1063,53 +1376,62 @@ def specgen(specloc, indir, style_uri, docdir, tags, instances=False, offline=Fa
template = None
f = open(temploc, "r")
template = f.read()
+ f.close()
# Load code documentation link map from tags file
linkmap = load_tags(tags, docdir)
m = rdflib.ConjunctiveGraph()
- manifest_path = os.path.join(os.path.dirname(specloc), 'manifest.ttl')
+ manifest_path = os.path.join(os.path.dirname(specloc), "manifest.ttl")
if os.path.exists(manifest_path):
- m.parse(manifest_path, format='n3')
- m.parse(specloc, format='n3')
+ m.parse(manifest_path, format="n3")
+ m.parse(specloc, format="n3")
- bundle_path = os.path.split(specloc[specloc.find(':') + 1:])[0]
- abs_bundle_path = os.path.abspath(bundle_path)
spec_url = getOntologyNS(m)
spec = rdflib.URIRef(spec_url)
- # Parse all seeAlso files in the bundle
- for uri in specProperties(m, spec, rdfs.seeAlso):
- if uri[:7] == 'file://':
- path = uri[7:]
- if (path != os.path.abspath(specloc)
- and path.endswith('.ttl')):
- m.parse(path, format='n3')
+ # Load all seeAlso files recursively
+ seeAlso = set()
+ done = False
+ while not done:
+ done = True
+ for uri in specProperties(m, spec, rdfs.seeAlso):
+ if uri[:7] == "file://":
+ path = uri[7:]
+ if (
+ path != os.path.abspath(specloc)
+ and path.endswith("ttl")
+ and path not in seeAlso
+ ):
+ seeAlso.add(path)
+ m.parse(path, format="n3")
+ done = False
spec_ns_str = spec_url
- if (spec_ns_str[-1] != "/" and spec_ns_str[-1] != "#"):
+ if spec_ns_str[-1] != "/" and spec_ns_str[-1] != "#":
spec_ns_str += "#"
spec_ns = rdflib.Namespace(spec_ns_str)
namespaces = getNamespaces(m)
- keys = namespaces.keys()
- keys.sort()
+ keys = sorted(namespaces.keys())
prefixes_html = "<span>"
for i in keys:
uri = namespaces[i]
- if uri.startswith('file:'):
- continue;
+ if uri.startswith("file:"):
+ continue
ns_list[str(uri)] = i
- if (str(uri) == spec_url + '#' or
- str(uri) == spec_url + '/' or
- str(uri) == spec_url):
+ if (
+ str(uri) == spec_url + "#"
+ or str(uri) == spec_url + "/"
+ or str(uri) == spec_url
+ ):
spec_pre = i
prefixes_html += '<a href="%s">%s</a> ' % (uri, i)
prefixes_html += "</span>"
if spec_pre is None:
- print('No namespace prefix for %s defined' % specloc)
+ print("No namespace prefix for %s defined" % specloc)
sys.exit(1)
ns_list[spec_ns_str] = spec_pre
@@ -1120,94 +1442,134 @@ def specgen(specloc, indir, style_uri, docdir, tags, instances=False, offline=Fa
instalist = None
if instances:
- instalist = getInstances(m, classlist, proplist)
- instalist.sort(lambda x, y: cmp(getShortName(x).lower(), getShortName(y).lower()))
+ instalist = sorted(
+ getInstances(m, classlist, proplist),
+ key=lambda x: getShortName(x).lower(),
+ )
azlist = buildIndex(m, classlist, proplist, instalist)
# Generate Term HTML
- termlist = docTerms('Property', proplist, m, classlist, proplist, instalist)
- termlist = docTerms('Class', classlist, m, classlist, proplist, instalist) + termlist
+ classlist = docTerms("Class", classlist, m, classlist, proplist, instalist)
+ proplist = docTerms(
+ "Property", proplist, m, classlist, proplist, instalist
+ )
if instances:
- termlist += docTerms('Instance', instalist, m, classlist, proplist, instalist)
-
- template = template.replace('@NAME@', specProperty(m, spec, doap.name))
- template = template.replace('@SUBTITLE@', specProperty(m, spec, doap.shortdesc))
- template = template.replace('@URI@', spec)
- template = template.replace('@PREFIX@', spec_pre)
- if spec_pre == 'lv2':
- template = template.replace('@XMLNS@', '')
+ instlist = docTerms(
+ "Instance", instalist, m, classlist, proplist, instalist
+ )
+
+ termlist = ""
+ if classlist:
+ termlist += '<div class="section">'
+ termlist += '<h2><a id="ref-classes" />Classes</h2>' + classlist
+ termlist += "</div>"
+
+ if proplist:
+ termlist += '<div class="section">'
+ termlist += '<h2><a id="ref-properties" />Properties</h2>' + proplist
+ termlist += "</div>"
+
+ if instlist:
+ termlist += '<div class="section">'
+ termlist += '<h2><a id="ref-instances" />Instances</h2>' + instlist
+ termlist += "</div>"
+
+ name = specProperty(m, spec, doap.name)
+ title = name
+ if root_link:
+ name = '<a href="%s">%s</a>' % (root_link, name)
+
+ template = template.replace("@TITLE@", title)
+ template = template.replace("@NAME@", name)
+ template = template.replace(
+ "@SHORT_DESC@", specProperty(m, spec, doap.shortdesc)
+ )
+ template = template.replace("@URI@", spec)
+ template = template.replace("@PREFIX@", spec_pre)
+ if spec_pre == "lv2":
+ template = template.replace("@XMLNS@", "")
else:
- template = template.replace('@XMLNS@', ' xmlns:%s="%s"' % (spec_pre, spec_ns_str))
+ template = template.replace(
+ "@XMLNS@", ' xmlns:%s="%s"' % (spec_pre, spec_ns_str)
+ )
filename = os.path.basename(specloc)
- basename = filename[0:filename.rfind('.')]
-
- template = template.replace('@STYLE_URI@', style_uri)
- template = template.replace('@PREFIXES@', str(prefixes_html))
- template = template.replace('@BASE@', spec_ns_str)
- template = template.replace('@AUTHORS@', specAuthors(m, spec))
- template = template.replace('@INDEX@', azlist)
- template = template.replace('@REFERENCE@', termlist)
- template = template.replace('@FILENAME@', filename)
- template = template.replace('@HEADER@', basename + '.h')
- template = template.replace('@MAIL@', 'devel@lists.lv2plug.in')
- template = template.replace('@HISTORY@', specHistory(m, spec))
+ basename = filename[0 : filename.rfind(".")]
+
+ template = template.replace("@STYLE_URI@", style_uri)
+ template = template.replace("@PREFIXES@", str(prefixes_html))
+ template = template.replace("@BASE@", spec_ns_str)
+ template = template.replace("@AUTHORS@", specAuthors(m, spec))
+ template = template.replace("@INDEX@", azlist)
+ template = template.replace("@REFERENCE@", termlist)
+ template = template.replace("@FILENAME@", filename)
+ template = template.replace("@HEADER@", basename + ".h")
+ template = template.replace("@HISTORY@", specHistory(m, spec))
+
+ mail_row = ""
+ if "list_email" in opts:
+ mail_row = '<tr><th>Discuss</th><td><a href="mailto:%s">%s</a>' % (
+ opts["list_email"],
+ opts["list_email"],
+ )
+ if "list_page" in opts:
+ mail_row += ' <a href="%s">(subscribe)</a>' % opts["list_page"]
+ mail_row += "</td></tr>"
+ template = template.replace("@MAIL@", mail_row)
version = specVersion(m, spec) # (minor, micro, date)
date_string = version[2]
if date_string == "":
date_string = "Undated"
- version_string = "%s.%s (%s)" % (version[0], version[1], date_string)
- experimental = (version[0] == 0 or version[1] % 2 == 1)
+ version_string = "%s.%s" % (version[0], version[1])
+ experimental = version[0] == 0 or version[1] % 2 == 1
if experimental:
version_string += ' <span class="warning">EXPERIMENTAL</span>'
- deprecated = findOne(m, rdflib.URIRef(spec_url), owl.deprecated, None)
- if deprecated and str(deprecated[2]).find("true") > 0:
+ if isDeprecated(m, rdflib.URIRef(spec_url)):
version_string += ' <span class="warning">DEPRECATED</span>'
- template = template.replace('@REVISION@', version_string)
+ template = template.replace("@VERSION@", version_string)
- file_list = ''
- see_also_files = specProperties(m, spec, rdfs.seeAlso)
- see_also_files.sort()
- for f in see_also_files:
- uri = str(f)
- if uri[:7] == 'file://':
- uri = uri[7:]
- if uri[:len(abs_bundle_path)] == abs_bundle_path:
- uri = uri[len(abs_bundle_path) + 1:]
- else:
- continue # Skip seeAlso file outside bundle
+ content_links = ""
+ if docdir is not None:
+ content_links = '<li><a href="%s">API</a></li>' % os.path.join(
+ docdir, "group__%s.html" % basename
+ )
+ template = template.replace("@CONTENT_LINKS@", content_links)
- if offline:
- entry = uri
- else:
- entry = '<a href="%s">%s</a>' % (uri, uri)
- if uri.endswith('.h') or uri.endswith('.hpp'):
- name = os.path.basename(uri)
- entry += ' - <a href="%s">Documentation</a> ' % (
- docdir + '/' + name.replace('.', '_8') + '.html')
- file_list += '<li>%s</li>' % entry
- else:
- file_list += '<li>%s</li>' % entry
+ docs = getDetailedDocumentation(
+ m, rdflib.URIRef(spec_url), classlist, proplist, instalist
+ )
+ template = template.replace("@DESCRIPTION@", docs)
- files = ''
- if file_list:
- files += '<li>Files<ul>%s</ul></li>' % file_list
+ now = int(os.environ.get("SOURCE_DATE_EPOCH", time.time()))
+ build_date = datetime.datetime.utcfromtimestamp(now)
+ template = template.replace("@DATE@", build_date.strftime("%F"))
+ template = template.replace("@TIME@", build_date.strftime("%F %H:%M UTC"))
- template = template.replace('@FILES@', files)
+ # Write index row
+ if index_path is not None:
+ writeIndex(m, specloc, index_path, root_path, root_uri)
- comment = getComment(m, rdflib.URIRef(spec_url), classlist, proplist, instalist)
- if comment != '':
- template = template.replace('@COMMENT@', comment)
- else:
- template = template.replace('@COMMENT@', '')
-
- template = template.replace('@TIME@', datetime.datetime.utcnow().strftime('%F %H:%M UTC'))
+ # Validate complete output page
+ try:
+ oldcwd = os.getcwd()
+ os.chdir(specgendir)
+ etree.fromstring(
+ template.replace(
+ '"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd"',
+ '"DTD/xhtml-rdfa-1.dtd"',
+ ).encode("utf-8"),
+ etree.XMLParser(dtd_validation=True, no_network=True),
+ )
+ except Exception as e:
+ sys.stderr.write("error: Validation failed for %s: %s" % (specloc, e))
+ finally:
+ os.chdir(oldcwd)
return template
@@ -1215,7 +1577,7 @@ def specgen(specloc, indir, style_uri, docdir, tags, instances=False, offline=Fa
def save(path, text):
try:
f = open(path, "w")
- f.write(text.encode("utf-8"))
+ f.write(text)
f.flush()
f.close()
except Exception:
@@ -1227,7 +1589,7 @@ def getNamespaces(m):
"""Return a prefix:URI dictionary of all namespaces seen during parsing"""
nspaces = {}
for prefix, uri in m.namespaces():
- if not re.match('default[0-9]*', prefix) and not prefix == 'xml':
+ if not re.match("default[0-9]*", prefix) and not prefix == "xml":
# Skip silly default namespaces added by rdflib
nspaces[prefix] = uri
return nspaces
@@ -1242,7 +1604,7 @@ def getOntologyNS(m):
if not isBlank(getSubject(s)):
ns = str(getSubject(s))
- if (ns == None):
+ if ns is None:
sys.exit("Impossible to get ontology's namespace")
else:
return ns
@@ -1250,53 +1612,157 @@ def getOntologyNS(m):
def usage():
script = os.path.basename(sys.argv[0])
- print("""Usage: %s ONTOLOGY INDIR STYLE OUTPUT [DOCDIR TAGS] [FLAGS]
-
- ONTOLOGY : Path to ontology file
- INDIR : Input directory containing template.html and style.css
- STYLE : Stylesheet URI
- OUTPUT : HTML output path
- DOCDIR : Doxygen HTML directory
- TAGS : Doxygen tags file
-
- Optional flags:
- -i : Document class/property instances (disabled by default)
- -p PREFIX : Set ontology namespace prefix from command line
-
-Example:
- %s lv2_foos.ttl template.html style.css lv2_foos.html ../doc -i -p foos
-""" % (script, script))
- sys.exit(-1)
+ return "Usage: %s ONTOLOGY_TTL OUTPUT_HTML [OPTION]..." % script
if __name__ == "__main__":
"""Ontology specification generator tool"""
- args = sys.argv[1:]
- if (len(args) < 3):
- usage()
- else:
- ontology = "file:" + str(args[0])
- indir = args[1]
- style = args[2]
- output = args[3]
- docdir = None
- tags = None
- if len(args) > 5:
- docdir = args[4]
- tags = args[5]
-
- # Flags
- instances = False
- if len(args) > 6:
- flags = args[6:]
- i = 0
- while i < len(flags):
- if flags[i] == '-i':
- instances = True
- elif flags[i] == '-p':
- spec_pre = flags[i + 1]
- i += 1
- i += 1
-
- save(output, specgen(ontology, indir, style, docdir, tags, instances=instances))
+ indir = os.path.abspath(os.path.dirname(sys.argv[0]))
+ if not os.path.exists(os.path.join(indir, "template.html")):
+ indir = os.path.join(os.path.dirname(indir), "share", "lv2specgen")
+
+ opt = optparse.OptionParser(
+ usage=usage(),
+ description="Write HTML documentation for an RDF ontology.",
+ )
+ opt.add_option(
+ "--list-email",
+ type="string",
+ dest="list_email",
+ help="Mailing list email address",
+ )
+ opt.add_option(
+ "--list-page",
+ type="string",
+ dest="list_page",
+ help="Mailing list info page address",
+ )
+ opt.add_option(
+ "--template-dir",
+ type="string",
+ dest="template_dir",
+ default=indir,
+ help="Template directory",
+ )
+ opt.add_option(
+ "--style-uri",
+ type="string",
+ dest="style_uri",
+ default="style.css",
+ help="Stylesheet URI",
+ )
+ opt.add_option(
+ "--docdir",
+ type="string",
+ dest="docdir",
+ default=None,
+ help="Doxygen output directory",
+ )
+ opt.add_option(
+ "--index",
+ type="string",
+ dest="index_path",
+ default=None,
+ help="Index row output file",
+ )
+ opt.add_option(
+ "--tags",
+ type="string",
+ dest="tags",
+ default=None,
+ help="Doxygen tags file",
+ )
+ opt.add_option(
+ "-r",
+ "--root-path",
+ type="string",
+ dest="root_path",
+ default="",
+ help="Root path",
+ )
+ opt.add_option(
+ "-R",
+ "--root-uri",
+ type="string",
+ dest="root_uri",
+ default="",
+ help="Root URI",
+ )
+ opt.add_option(
+ "-p",
+ "--prefix",
+ type="string",
+ dest="prefix",
+ help="Specification Turtle prefix",
+ )
+ opt.add_option(
+ "-i",
+ "--instances",
+ action="store_true",
+ dest="instances",
+ help="Document instances",
+ )
+ opt.add_option(
+ "--copy-style",
+ action="store_true",
+ dest="copy_style",
+ help="Copy style from template directory to output directory",
+ )
+
+ (options, args) = opt.parse_args()
+ opts = vars(options)
+
+ if len(args) < 2:
+ opt.print_help()
+ sys.exit(-1)
+
+ spec_pre = options.prefix
+ ontology = "file:" + str(args[0])
+ output = args[1]
+ index_path = options.index_path
+ docdir = options.docdir
+ tags = options.tags
+
+ out = "."
+ spec = args[0]
+ path = os.path.dirname(spec)
+ outdir = os.path.abspath(os.path.join(out, path))
+
+ bundle = str(outdir)
+ b = os.path.basename(outdir)
+
+ if not os.access(os.path.abspath(spec), os.R_OK):
+ print("warning: extension %s has no %s.ttl file" % (b, b))
+ sys.exit(1)
+
+ # Root link
+ root_path = opts["root_path"]
+ root_uri = opts["root_uri"]
+ root_link = os.path.join(root_path, "index.html")
+
+ # Generate spec documentation
+ specdoc = specgen(
+ spec,
+ indir,
+ opts["style_uri"],
+ docdir,
+ tags,
+ opts,
+ instances=True,
+ root_link=root_link,
+ index_path=index_path,
+ root_path=root_path,
+ root_uri=root_uri,
+ )
+
+ # Save to HTML output file
+ save(output, specdoc)
+
+ if opts["copy_style"]:
+ import shutil
+
+ shutil.copyfile(
+ os.path.join(indir, "style.css"),
+ os.path.join(os.path.dirname(output), "style.css"),
+ )
diff --git a/lv2specgen/template.html b/lv2specgen/template.html
index 691f6fd..ed9d6fb 100644
--- a/lv2specgen/template.html
+++ b/lv2specgen/template.html
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html about="@URI@"
xmlns="http://www.w3.org/1999/xhtml"
@@ -9,85 +10,86 @@
@XMLNS@
xml:lang="en">
<head>
- <title>@NAME@</title>
+ <title>@TITLE@</title>
<meta http-equiv="content-type" content="text/xhtml+xml; charset=utf-8" />
<meta name="generator" content="lv2specgen" />
<link href="@STYLE_URI@" rel="stylesheet" type="text/css" />
</head>
<body>
- <!-- HEADER -->
- <div id="header">
- <h1 id="title">@NAME@</h1>
- <span id="subtitle">@SUBTITLE@</span>
- <table id="meta">
- <tr><th>URI</th><td><a href="@URI@">@URI@</a></td></tr>
- <tr><th>Version</th><td>@REVISION@</td></tr>
- <tr><th>Prefixes</th><td>@PREFIXES@</td></tr>
- <tr><th>Discuss</th><td>
- <a href="mailto:@MAIL@">@MAIL@</a>
- (<a href="http://lists.lv2plug.in/listinfo.cgi/devel-lv2plug.in">subscribe</a>)
- </td></tr>
- @AUTHORS@
- </table>
- </div>
+ <!-- HEADER -->
+ <div id="topbar">
+ <div id="header">
+ <div id="titlebox">
+ <h1 id="title">@NAME@</h1>
+ <div id="shortdesc">@SHORT_DESC@</div>
+ </div>
+ <div id="metabox">
+ <table id="meta">
+ <tr><th>ID</th><td><a href="@URI@">@URI@</a></td></tr>
+ <tr><th>Version</th><td>@VERSION@</td></tr>
+ <tr><th>Date</th><td>@DATE@</td></tr>
+ @MAIL@
+ @AUTHORS@
+ </table>
+ </div>
+ </div>
+ </div>
- <h2 class="sec">Contents</h2>
- <div class="content">
- <ul>
- <li><a href="#sec-description">Description</a></li>
- <li><a href="#sec-index">Index</a></li>
- <li><a href="#sec-documentation">Documentation</a></li>
- <li><a href="#sec-releases">Releases</a></li>
- @FILES@
- </ul>
- </div>
+ <div id="content">
+ <div id="contentsbox">
+ <!-- Contents: -->
+ <ul id="contents">
+ <!-- <li><a href="#sec-description">Description</a></li> -->
+ <li><a href="#sec-index">Index</a></li>
+ <li><a href="#sec-history">History</a></li>
+ @CONTENT_LINKS@
+ </ul>
+ </div>
- <!-- DESCRIPTION -->
- <h2 class="sec" id="sec-description">Description</h2>
- <div class="content">@COMMENT@</div>
+ <!-- DESCRIPTION -->
+ <div class="section">@DESCRIPTION@</div>
- <!-- INDEX -->
- <h2 class="sec" id="sec-index">Index</h2>
- <div class="content">
- @INDEX@
- </div>
+ <!-- INDEX -->
+ <h2 id="sec-index">Index</h2>
+ <div class="section">
+ @INDEX@
+ </div>
- <!-- DOCUMENTATION -->
- <h2 class="sec" id="sec-documentation">Documentation</h2>
- <div class="content">
- @REFERENCE@
- </div>
+ <!-- REFERENCE -->
+ <div class="section">
+ @REFERENCE@
+ </div>
- <!-- RELEASES -->
- <h2 class="sec" id="sec-releases">Releases</h2>
- <div class="content">
- @HISTORY@
- </div>
+ <!-- HISTORY -->
+ <h2 id="sec-history">History</h2>
+ <div class="section">
+ @HISTORY@
+ </div>
- <!-- FOOTER -->
- <div id="footer">
- <div>
- This document is available under the
- <a about="" rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">
- Creative Commons Attribution-ShareAlike License
- </a>
- </div>
- <div>
- Valid
- <a about="" rel="dct:conformsTo" resource="http://www.w3.org/TR/rdfa-syntax"
- href="http://validator.w3.org/check?uri=referer">
- XHTML+RDFa
- </a>
- and
- <a about="" rel="dct:conformsTo" resource="http://www.w3.org/TR/CSS2"
- href="http://jigsaw.w3.org/css-validator/check/referer">
- CSS
- </a>
- generated from @FILENAME@ by <a href="http://drobilla.net/software/lv2specgen">lv2specgen</a>
- </div>
- </div>
+ <!-- FOOTER -->
+ <div id="footer">
+ <div>
+ This document is available under the
+ <a about="" rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">
+ Creative Commons Attribution-ShareAlike License
+ </a>
+ </div>
+ <div>
+ Valid
+ <a about="" rel="dct:conformsTo" resource="http://www.w3.org/TR/rdfa-syntax"
+ href="http://validator.w3.org/check?uri=referer">
+ XHTML+RDFa
+ </a>
+ and
+ <a about="" rel="dct:conformsTo" resource="http://www.w3.org/TR/CSS2"
+ href="http://jigsaw.w3.org/css-validator/check/referer">
+ CSS
+ </a>
+ generated from @FILENAME@ by lv2specgen
+ </div>
+ </div>
+ </div>
</body>
</html>
-