Hi all,

I've created a patch to our docs that hyperlinks all builtin template 
tags and filters in code samples that are marked as 'html+django'.  
This would be pretty hard to do at the render stage, so it is 
implemented using jQuery.

In order to only link genuine tags that have documentation, I had to 
create my own Sphinx builder which creates a 'templatebuiltins.js', 
but otherwise it is all javascript.

I have tested this with Python 2.5/Sphinx 0.5.1 and Python 2.4/Sphinx 
0.6.4.  I don't know which Sphinx versions we intend to support.  Do I 
need more extensive testing?  Also if anybody with more Sphinx 
experience than me spots other gotchas or problems with the patch, 
please let me know.

Assuming no problems, are other people happy with this going in before 
the release 1.2?  It is quite cool if I say so myself :-)

Luke

-- 
"Love is like an hourglass, with the heart filling up as the brain 
empties."

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

diff -r 4b727a43acaa docs/Makefile
--- a/docs/Makefile	Thu May 06 04:25:33 2010 +0000
+++ b/docs/Makefile	Fri May 07 01:39:12 2010 +0100
@@ -26,8 +26,8 @@
 	-rm -rf _build/*
 
 html:
-	mkdir -p _build/html _build/doctrees
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
+	mkdir -p _build/html/json _build/doctrees
+	$(SPHINXBUILD) -b djangohtml $(ALLSPHINXOPTS) _build/html
 	@echo
 	@echo "Build finished. The HTML pages are in _build/html."
 
diff -r 4b727a43acaa docs/_ext/djangodocs.py
--- a/docs/_ext/djangodocs.py	Thu May 06 04:25:33 2010 +0000
+++ b/docs/_ext/djangodocs.py	Fri May 07 01:39:12 2010 +0100
@@ -4,12 +4,25 @@
 
 import docutils.nodes
 import docutils.transforms
+try:
+    import json
+except ImportError:
+    try:
+        import simplejson as json
+    except ImportError:
+        json = None
+import os
 import sphinx
 import sphinx.addnodes
 try:
     from sphinx import builders
 except ImportError:
     import sphinx.builder as builders
+try:
+    import sphinx.builders.html as builders_html
+except ImportError:
+    builders_html = builders
+from sphinx.util.console import bold
 import sphinx.directives
 import sphinx.environment
 try:
@@ -56,7 +69,8 @@
     app.add_directive('versionadded', parse_version_directive, 1, (1, 1, 1))
     app.add_directive('versionchanged', parse_version_directive, 1, (1, 1, 1))
     app.add_transform(SuppressBlockquotes)
-    
+    app.add_builder(DjangoStandaloneHTMLBuilder)
+
     # Monkeypatch PickleHTMLBuilder so that it doesn't die in Sphinx 0.4.2
     if sphinx.__version__ == '0.4.2':
         monkeypatch_pickle_builder()
@@ -218,7 +232,6 @@
         import cPickle as pickle
     except ImportError:
         import pickle
-    from sphinx.util.console import bold
     
     def handle_finish(self):
         # dump the global context
@@ -248,3 +261,21 @@
 
     builders.PickleHTMLBuilder.handle_finish = handle_finish
 
+
+class DjangoStandaloneHTMLBuilder(builders_html.StandaloneHTMLBuilder):
+    """
+    Subclass to add some extra things we need.
+    """
+    name = 'djangohtml'
+    def finish(self):
+        super(DjangoStandaloneHTMLBuilder, self).finish()
+        if json is None:
+            self.warn(bold("cannot create templatebuiltins.js due to missing simplejson dependency"))
+            return
+        self.info(bold("writing templatebuiltins.js..."))
+        ttags = [n for (t,n) in self.env.reftargets.keys() if t == 'ttag']
+        tfilters = [n for (t,n) in self.env.reftargets.keys() if t == 'tfilter']
+        outfilename = os.path.join(self.outdir, "json", "templatebuiltins.js")
+        f = open(outfilename, 'wb')
+        f.write('var django_template_builtins = ')
+        json.dump({'ttags':ttags, 'tfilters':tfilters}, f)
diff -r 4b727a43acaa docs/_static/djangodocs.css
--- a/docs/_static/djangodocs.css	Thu May 06 04:25:33 2010 +0000
+++ b/docs/_static/djangodocs.css	Fri May 07 01:39:12 2010 +0100
@@ -98,7 +98,12 @@
 dt .literal, table .literal { background:none; }
 #bd a.reference { text-decoration: none; }
 #bd a.reference tt.literal { border-bottom: 1px #234f32 dotted; }
- 
+
+/* Restore colors of pygments hyperlinked code */
+#bd .highlight .k a:link, #bd .highlight .k a:visited { color: #000000; text-decoration: underline }
+#bd .highlight .nf a:link, #bd .highlight .nf a:visited { color: #990000; text-decoration: underline }
+
+
 /*** notes & admonitions ***/
 .note, .admonition { padding:.8em 1em .8em; margin: 1em 0; border:1px solid #94da3a; }
 .admonition-title { font-weight:bold; margin-top:0 !important; margin-bottom:0 !important;}
diff -r 4b727a43acaa docs/_templates/layout.html
--- a/docs/_templates/layout.html	Thu May 06 04:25:33 2010 +0000
+++ b/docs/_templates/layout.html	Fri May 07 01:39:12 2010 +0100
@@ -16,6 +16,43 @@
   {%- endif %}
 {%- endmacro %}
 
+{% block extrahead %}
+{{ super() }}
+<script type="text/javascript" src="{{ pathto('json/templatebuiltins.js', 1) }}"></script>
+<script type="text/javascript">
+(function($) {
+    if (!django_template_builtins) {
+       // templatebuiltins.js missing, do nothing.
+       return;
+    }
+    $(document).ready(function() {
+        // Hyperlink Django template tags and filters
+        var base = "{{ pathto('ref/templates/builtins') }}";
+        if (base == "#") {
+            // Special case for builtins.html itself
+            base = "";
+        }
+        // Tags are keywords, class '.k'
+        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
+             var tagname = $(elem).text();
+             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
+                 var fragment = tagname.replace(/_/, '-');
+                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
+             }
+        });
+        // Filters are functions, class '.nf'
+        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
+             var tagname = $(elem).text();
+             if ($.inArray(tagname, django_template_builtins.tfilters) != -1) {
+                 var fragment = tagname.replace(/_/, '-');
+                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
+             }
+        });
+    });
+})(jQuery);
+</script>
+{% endblock %}
+
 {% block document %}
   <div id="custom-doc" class="{% block bodyclass %}{{ 'yui-t6' if pagename != 'index' else '' }}{% endblock %}">
     <div id="hd">
@@ -84,4 +121,4 @@
 {% block relbar2 %}{% endblock %}
 {% block sidebar1 %}{% endblock %}
 {% block sidebar2 %}{% endblock %}
-{% block footer %}{% endblock %}
\ No newline at end of file
+{% block footer %}{% endblock %}

Reply via email to