1
2
3
4
5
6
7
8
9 """
10 Functions to produce colorized HTML code for various objects.
11 Currently, C{html_colorize} defines functions to colorize
12 Python source code.
13 """
14 __docformat__ = 'epytext en'
15
16 import re, codecs
17 from epydoc import log
18 from epydoc.util import py_src_filename
19 from epydoc.apidoc import *
20 import tokenize, token, cgi, keyword
21 try: from cStringIO import StringIO
22 except: from StringIO import StringIO
23
24
25
26
27 """
28 Goals:
29 - colorize tokens appropriately (using css)
30 - optionally add line numbers
31 -
32 """
33
34
35 PYSRC_JAVASCRIPTS = '''\
36 function expand(id) {
37 var elt = document.getElementById(id+"-expanded");
38 if (elt) elt.style.display = "block";
39 var elt = document.getElementById(id+"-expanded-linenums");
40 if (elt) elt.style.display = "block";
41 var elt = document.getElementById(id+"-collapsed");
42 if (elt) { elt.innerHTML = ""; elt.style.display = "none"; }
43 var elt = document.getElementById(id+"-collapsed-linenums");
44 if (elt) { elt.innerHTML = ""; elt.style.display = "none"; }
45 var elt = document.getElementById(id+"-toggle");
46 if (elt) { elt.innerHTML = "-"; }
47 }
48
49 function collapse(id) {
50 var elt = document.getElementById(id+"-expanded");
51 if (elt) elt.style.display = "none";
52 var elt = document.getElementById(id+"-expanded-linenums");
53 if (elt) elt.style.display = "none";
54 var elt = document.getElementById(id+"-collapsed-linenums");
55 if (elt) { elt.innerHTML = "<br />"; elt.style.display="block"; }
56 var elt = document.getElementById(id+"-toggle");
57 if (elt) { elt.innerHTML = "+"; }
58 var elt = document.getElementById(id+"-collapsed");
59 if (elt) {
60 elt.style.display = "block";
61
62 var indent = elt.getAttribute("indent");
63 var pad = elt.getAttribute("pad");
64 var s = "<tt class=\'py-lineno\'>";
65 for (var i=0; i<pad.length; i++) { s += " " }
66 s += "</tt>";
67 s += " <tt class=\'py-line\'>";
68 for (var i=0; i<indent.length; i++) { s += " " }
69 s += "<a href=\'#\' onclick=\'expand(\\"" + id;
70 s += "\\");return false\'>...</a></tt><br />";
71 elt.innerHTML = s;
72 }
73 }
74
75 function toggle(id) {
76 elt = document.getElementById(id+"-toggle");
77 if (elt.innerHTML == "-")
78 collapse(id);
79 else
80 expand(id);
81 return false;
82 }
83
84 function highlight(id) {
85 var elt = document.getElementById(id+"-def");
86 if (elt) elt.className = "py-highlight-hdr";
87 var elt = document.getElementById(id+"-expanded");
88 if (elt) elt.className = "py-highlight";
89 var elt = document.getElementById(id+"-collapsed");
90 if (elt) elt.className = "py-highlight";
91 }
92
93 function num_lines(s) {
94 var n = 1;
95 var pos = s.indexOf("\\n");
96 while ( pos > 0) {
97 n += 1;
98 pos = s.indexOf("\\n", pos+1);
99 }
100 return n;
101 }
102
103 // Collapse all blocks that mave more than `min_lines` lines.
104 function collapse_all(min_lines) {
105 var elts = document.getElementsByTagName("div");
106 for (var i=0; i<elts.length; i++) {
107 var elt = elts[i];
108 var split = elt.id.indexOf("-");
109 if (split > 0)
110 if (elt.id.substring(split, elt.id.length) == "-expanded")
111 if (num_lines(elt.innerHTML) > min_lines)
112 collapse(elt.id.substring(0, split));
113 }
114 }
115
116 function expandto(href) {
117 var start = href.indexOf("#")+1;
118 if (start != 0 && start != href.length) {
119 if (href.substring(start, href.length) != "-") {
120 collapse_all(4);
121 pos = href.indexOf(".", start);
122 while (pos != -1) {
123 var id = href.substring(start, pos);
124 expand(id);
125 pos = href.indexOf(".", pos+1);
126 }
127 var id = href.substring(start, href.length);
128 expand(id);
129 highlight(id);
130 }
131 }
132 }
133
134 function kill_doclink(id) {
135 var parent = document.getElementById(id);
136 parent.removeChild(parent.childNodes.item(0));
137 }
138 function auto_kill_doclink(ev) {
139 if (!ev) var ev = window.event;
140 if (!this.contains(ev.toElement)) {
141 var parent = document.getElementById(this.parentID);
142 parent.removeChild(parent.childNodes.item(0));
143 }
144 }
145
146 function doclink(id, name, targets_id) {
147 var elt = document.getElementById(id);
148
149 // If we already opened the box, then destroy it.
150 // (This case should never occur, but leave it in just in case.)
151 if (elt.childNodes.length > 1) {
152 elt.removeChild(elt.childNodes.item(0));
153 }
154 else {
155 // The outer box: relative + inline positioning.
156 var box1 = document.createElement("div");
157 box1.style.position = "relative";
158 box1.style.display = "inline";
159 box1.style.top = 0;
160 box1.style.left = 0;
161
162 // A shadow for fun
163 var shadow = document.createElement("div");
164 shadow.style.position = "absolute";
165 shadow.style.left = "-1.3em";
166 shadow.style.top = "-1.3em";
167 shadow.style.background = "#404040";
168
169 // The inner box: absolute positioning.
170 var box2 = document.createElement("div");
171 box2.style.position = "relative";
172