sdoc 0.3.11 → 0.3.14
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +90 -1
- data/bin/sdoc +1 -1
- data/lib/rdoc/generator/template/rails/resources/css/reset.css +0 -5
- data/lib/rdoc/generator/template/rails/resources/js/searchdoc.js +1 -188
- data/lib/rdoc/generator/template/rails/resources/panel/index.html +2 -1
- data/lib/rdoc/generator/template/sdoc/resources/css/reset.css +0 -5
- data/lib/rdoc/generator/template/sdoc/resources/js/searchdoc.js +2 -188
- data/lib/rdoc/generator/template/sdoc/resources/panel/index.html +2 -1
- data/lib/sdoc/generator.rb +16 -86
- data/sdoc.gemspec +5 -10
- metadata +9 -22
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2011 Vladimir Kolesnikov
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -19,3 +19,92 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
|
+
|
23
|
+
|
24
|
+
Darkfish RDoc HTML Generator
|
25
|
+
|
26
|
+
Copyright (c) 2007, 2008, Michael Granger. All rights reserved.
|
27
|
+
|
28
|
+
Redistribution and use in source and binary forms, with or without
|
29
|
+
modification, are permitted provided that the following conditions are met:
|
30
|
+
|
31
|
+
* Redistributions of source code must retain the above copyright notice,
|
32
|
+
this list of conditions and the following disclaimer.
|
33
|
+
|
34
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
35
|
+
this list of conditions and the following disclaimer in the documentation
|
36
|
+
and/or other materials provided with the distribution.
|
37
|
+
|
38
|
+
* Neither the name of the author/s, nor the names of the project's
|
39
|
+
contributors may be used to endorse or promote products derived from this
|
40
|
+
software without specific prior written permission.
|
41
|
+
|
42
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
43
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
44
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
45
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
46
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
47
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
48
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
49
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
50
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
51
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
52
|
+
|
53
|
+
|
54
|
+
RDoc is copyrighted free software.
|
55
|
+
|
56
|
+
You can redistribute it and/or modify it under either the terms of the GPL
|
57
|
+
version 2 (see the file GPL), or the conditions below:
|
58
|
+
|
59
|
+
1. You may make and give away verbatim copies of the source form of the
|
60
|
+
software without restriction, provided that you duplicate all of the
|
61
|
+
original copyright notices and associated disclaimers.
|
62
|
+
|
63
|
+
2. You may modify your copy of the software in any way, provided that
|
64
|
+
you do at least ONE of the following:
|
65
|
+
|
66
|
+
a) place your modifications in the Public Domain or otherwise
|
67
|
+
make them Freely Available, such as by posting said
|
68
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
69
|
+
the author to include your modifications in the software.
|
70
|
+
|
71
|
+
b) use the modified software only within your corporation or
|
72
|
+
organization.
|
73
|
+
|
74
|
+
c) give non-standard binaries non-standard names, with
|
75
|
+
instructions on where to get the original software distribution.
|
76
|
+
|
77
|
+
d) make other distribution arrangements with the author.
|
78
|
+
|
79
|
+
3. You may distribute the software in object code or binary form,
|
80
|
+
provided that you do at least ONE of the following:
|
81
|
+
|
82
|
+
a) distribute the binaries and library files of the software,
|
83
|
+
together with instructions (in the manual page or equivalent)
|
84
|
+
on where to get the original distribution.
|
85
|
+
|
86
|
+
b) accompany the distribution with the machine-readable source of
|
87
|
+
the software.
|
88
|
+
|
89
|
+
c) give non-standard binaries non-standard names, with
|
90
|
+
instructions on where to get the original software distribution.
|
91
|
+
|
92
|
+
d) make other distribution arrangements with the author.
|
93
|
+
|
94
|
+
4. You may modify and include the part of the software into any other
|
95
|
+
software (possibly commercial). But some files in the distribution
|
96
|
+
are not written by the author, so that they are not under these terms.
|
97
|
+
|
98
|
+
For the list of those files and their copying conditions, see the
|
99
|
+
file LEGAL.
|
100
|
+
|
101
|
+
5. The scripts and library files supplied as input to or produced as
|
102
|
+
output from the software do not automatically fall under the
|
103
|
+
copyright of the software, but belong to whomever generated them,
|
104
|
+
and may be sold commercially, and may be aggregated with this
|
105
|
+
software.
|
106
|
+
|
107
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
108
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
109
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
110
|
+
PURPOSE.
|
data/bin/sdoc
CHANGED
@@ -131,193 +131,6 @@ function scrollIntoView(element, view) {
|
|
131
131
|
}
|
132
132
|
}
|
133
133
|
|
134
|
-
|
135
|
-
// searcher.js --------------------------------------------
|
136
|
-
|
137
|
-
Searchdoc.Searcher = function(data) {
|
138
|
-
this.data = data;
|
139
|
-
this.handlers = [];
|
140
|
-
}
|
141
|
-
|
142
|
-
Searchdoc.Searcher.prototype = new function() {
|
143
|
-
var CHUNK_SIZE = 1000, // search is performed in chunks of 1000 for non-bloking user input
|
144
|
-
MAX_RESULTS = 100, // do not try to find more than 100 results
|
145
|
-
huid = 1, suid = 1,
|
146
|
-
runs = 0;
|
147
|
-
|
148
|
-
|
149
|
-
this.find = function(query) {
|
150
|
-
var queries = splitQuery(query),
|
151
|
-
regexps = buildRegexps(queries),
|
152
|
-
highlighters = buildHilighters(queries),
|
153
|
-
state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++},
|
154
|
-
_this = this;
|
155
|
-
this.currentSuid = state.n;
|
156
|
-
|
157
|
-
if (!query) return;
|
158
|
-
|
159
|
-
var run = function() {
|
160
|
-
// stop current search thread if new search started
|
161
|
-
if (state.n != _this.currentSuid) return;
|
162
|
-
|
163
|
-
var results = performSearch(_this.data, regexps, queries, highlighters, state),
|
164
|
-
hasMore = (state.limit > 0 && state.pass < 3);
|
165
|
-
|
166
|
-
triggerResults.call(_this, results, !hasMore);
|
167
|
-
if (hasMore) {
|
168
|
-
setTimeout(run, 2);
|
169
|
-
}
|
170
|
-
runs++;
|
171
|
-
};
|
172
|
-
runs = 0;
|
173
|
-
|
174
|
-
// start search thread
|
175
|
-
run();
|
176
|
-
}
|
177
|
-
|
178
|
-
/* ----- Events ------ */
|
179
|
-
this.ready = function(fn) {
|
180
|
-
fn.huid = huid;
|
181
|
-
this.handlers.push(fn);
|
182
|
-
}
|
183
|
-
|
184
|
-
/* ----- Utilities ------ */
|
185
|
-
function splitQuery(query) {
|
186
|
-
return jQuery.grep(query.split(/(\s+|\(\)?)/), function(string) { return string.match(/\S/) });
|
187
|
-
}
|
188
|
-
|
189
|
-
function buildRegexps(queries) {
|
190
|
-
return jQuery.map(queries, function(query) { return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i') });
|
191
|
-
}
|
192
|
-
|
193
|
-
function buildHilighters(queries) {
|
194
|
-
return jQuery.map(queries, function(query) {
|
195
|
-
return jQuery.map( query.split(''), function(l, i){ return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2) } ).join('')
|
196
|
-
});
|
197
|
-
}
|
198
|
-
|
199
|
-
// function longMatchRegexp(index, longIndex, regexps) {
|
200
|
-
// for (var i = regexps.length - 1; i >= 0; i--){
|
201
|
-
// if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
|
202
|
-
// };
|
203
|
-
// return true;
|
204
|
-
// }
|
205
|
-
|
206
|
-
|
207
|
-
/* ----- Mathchers ------ */
|
208
|
-
function matchPass1(index, longIndex, queries, regexps) {
|
209
|
-
if (index.indexOf(queries[0]) != 0) return false;
|
210
|
-
for (var i=1, l = regexps.length; i < l; i++) {
|
211
|
-
if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
|
212
|
-
};
|
213
|
-
return true;
|
214
|
-
}
|
215
|
-
|
216
|
-
function matchPass2(index, longIndex, queries, regexps) {
|
217
|
-
if (index.indexOf(queries[0]) == -1) return false;
|
218
|
-
for (var i=1, l = regexps.length; i < l; i++) {
|
219
|
-
if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
|
220
|
-
};
|
221
|
-
return true;
|
222
|
-
}
|
223
|
-
|
224
|
-
function matchPassRegexp(index, longIndex, queries, regexps) {
|
225
|
-
if (!index.match(regexps[0])) return false;
|
226
|
-
for (var i=1, l = regexps.length; i < l; i++) {
|
227
|
-
if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
|
228
|
-
};
|
229
|
-
return true;
|
230
|
-
}
|
231
|
-
|
232
|
-
|
233
|
-
/* ----- Highlighters ------ */
|
234
|
-
function highlightRegexp(info, queries, regexps, highlighters) {
|
235
|
-
var result = createResult(info);
|
236
|
-
for (var i=0, l = regexps.length; i < l; i++) {
|
237
|
-
result.title = result.title.replace(regexps[i], highlighters[i]);
|
238
|
-
if (i > 0)
|
239
|
-
result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
|
240
|
-
};
|
241
|
-
return result;
|
242
|
-
}
|
243
|
-
|
244
|
-
function hltSubstring(string, pos, length) {
|
245
|
-
return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length);
|
246
|
-
}
|
247
|
-
|
248
|
-
function highlightQuery(info, queries, regexps, highlighters) {
|
249
|
-
var result = createResult(info), pos = 0, lcTitle = result.title.toLowerCase();
|
250
|
-
pos = lcTitle.indexOf(queries[0]);
|
251
|
-
if (pos != -1) {
|
252
|
-
result.title = hltSubstring(result.title, pos, queries[0].length);
|
253
|
-
}
|
254
|
-
for (var i=1, l = regexps.length; i < l; i++) {
|
255
|
-
result.title = result.title.replace(regexps[i], highlighters[i]);
|
256
|
-
result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
|
257
|
-
};
|
258
|
-
return result;
|
259
|
-
}
|
260
|
-
|
261
|
-
function createResult(info) {
|
262
|
-
var result = {};
|
263
|
-
result.title = info[0];
|
264
|
-
result.namespace = info[1];
|
265
|
-
result.path = info[2];
|
266
|
-
result.params = info[3];
|
267
|
-
result.snippet = info[4];
|
268
|
-
result.badge = info[6];
|
269
|
-
return result;
|
270
|
-
}
|
271
|
-
|
272
|
-
/* ----- Searching ------ */
|
273
|
-
function performSearch(data, regexps, queries, highlighters, state) {
|
274
|
-
var searchIndex = data.searchIndex, // search by title first and then by source
|
275
|
-
longSearchIndex = data.longSearchIndex,
|
276
|
-
info = data.info,
|
277
|
-
result = [],
|
278
|
-
i = state.from,
|
279
|
-
l = searchIndex.length,
|
280
|
-
togo = CHUNK_SIZE,
|
281
|
-
matchFunc, hltFunc;
|
282
|
-
|
283
|
-
while (state.pass < 3 && state.limit > 0 && togo > 0) {
|
284
|
-
if (state.pass == 0) {
|
285
|
-
matchFunc = matchPass1;
|
286
|
-
hltFunc = highlightQuery;
|
287
|
-
} else if (state.pass == 1) {
|
288
|
-
matchFunc = matchPass2;
|
289
|
-
hltFunc = highlightQuery;
|
290
|
-
} else if (state.pass == 2) {
|
291
|
-
matchFunc = matchPassRegexp;
|
292
|
-
hltFunc = highlightRegexp;
|
293
|
-
}
|
294
|
-
|
295
|
-
for (; togo > 0 && i < l && state.limit > 0; i++, togo--) {
|
296
|
-
if (info[i].n == state.n) continue;
|
297
|
-
if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) {
|
298
|
-
info[i].n = state.n;
|
299
|
-
result.push(hltFunc(info[i], queries, regexps, highlighters));
|
300
|
-
state.limit--;
|
301
|
-
}
|
302
|
-
};
|
303
|
-
if (searchIndex.length <= i) {
|
304
|
-
state.pass++;
|
305
|
-
i = state.from = 0;
|
306
|
-
} else {
|
307
|
-
state.from = i;
|
308
|
-
}
|
309
|
-
}
|
310
|
-
return result;
|
311
|
-
}
|
312
|
-
|
313
|
-
function triggerResults(results, isLast) {
|
314
|
-
jQuery.each(this.handlers, function(i, fn) { fn.call(this, results, isLast) })
|
315
|
-
}
|
316
|
-
}
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
134
|
// panel.js -----------------------------------------------
|
322
135
|
|
323
136
|
Searchdoc.Panel = function(element, data, tree, frame) {
|
@@ -328,7 +141,7 @@ Searchdoc.Panel = function(element, data, tree, frame) {
|
|
328
141
|
this.$current = null;
|
329
142
|
this.$view = this.$result.parent();
|
330
143
|
this.data = data;
|
331
|
-
this.searcher = new
|
144
|
+
this.searcher = new Searcher(data.index);
|
332
145
|
this.tree = new Searchdoc.Tree($('.tree', element), tree, this);
|
333
146
|
this.init();
|
334
147
|
}
|
@@ -7,7 +7,8 @@
|
|
7
7
|
<title>search index</title>
|
8
8
|
<link rel="stylesheet" href="../css/reset.css" type="text/css" media="screen" charset="utf-8" />
|
9
9
|
<link rel="stylesheet" href="../css/panel.css" type="text/css" media="screen" charset="utf-8" />
|
10
|
-
<script src="search_index.js" type="text/javascript" charset="utf-8"></script>
|
10
|
+
<script src="../js/search_index.js" type="text/javascript" charset="utf-8"></script>
|
11
|
+
<script src="../js/searcher.js" type="text/javascript" charset="utf-8"></script>
|
11
12
|
<script src="tree.js" type="text/javascript" charset="utf-8"></script>
|
12
13
|
<script src="../js/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
|
13
14
|
<script src="../js/searchdoc.js" type="text/javascript" charset="utf-8"></script>
|
@@ -131,193 +131,6 @@ function scrollIntoView(element, view) {
|
|
131
131
|
}
|
132
132
|
}
|
133
133
|
|
134
|
-
|
135
|
-
// searcher.js --------------------------------------------
|
136
|
-
|
137
|
-
Searchdoc.Searcher = function(data) {
|
138
|
-
this.data = data;
|
139
|
-
this.handlers = [];
|
140
|
-
}
|
141
|
-
|
142
|
-
Searchdoc.Searcher.prototype = new function() {
|
143
|
-
var CHUNK_SIZE = 1000, // search is performed in chunks of 1000 for non-bloking user input
|
144
|
-
MAX_RESULTS = 100, // do not try to find more than 100 results
|
145
|
-
huid = 1, suid = 1,
|
146
|
-
runs = 0;
|
147
|
-
|
148
|
-
|
149
|
-
this.find = function(query) {
|
150
|
-
var queries = splitQuery(query),
|
151
|
-
regexps = buildRegexps(queries),
|
152
|
-
highlighters = buildHilighters(queries),
|
153
|
-
state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++},
|
154
|
-
_this = this;
|
155
|
-
this.currentSuid = state.n;
|
156
|
-
|
157
|
-
if (!query) return;
|
158
|
-
|
159
|
-
var run = function() {
|
160
|
-
// stop current search thread if new search started
|
161
|
-
if (state.n != _this.currentSuid) return;
|
162
|
-
|
163
|
-
var results = performSearch(_this.data, regexps, queries, highlighters, state),
|
164
|
-
hasMore = (state.limit > 0 && state.pass < 3);
|
165
|
-
|
166
|
-
triggerResults.call(_this, results, !hasMore);
|
167
|
-
if (hasMore) {
|
168
|
-
setTimeout(run, 2);
|
169
|
-
}
|
170
|
-
runs++;
|
171
|
-
};
|
172
|
-
runs = 0;
|
173
|
-
|
174
|
-
// start search thread
|
175
|
-
run();
|
176
|
-
}
|
177
|
-
|
178
|
-
/* ----- Events ------ */
|
179
|
-
this.ready = function(fn) {
|
180
|
-
fn.huid = huid;
|
181
|
-
this.handlers.push(fn);
|
182
|
-
}
|
183
|
-
|
184
|
-
/* ----- Utilities ------ */
|
185
|
-
function splitQuery(query) {
|
186
|
-
return jQuery.grep(query.split(/(\s+|\(\)?)/), function(string) { return string.match(/\S/) });
|
187
|
-
}
|
188
|
-
|
189
|
-
function buildRegexps(queries) {
|
190
|
-
return jQuery.map(queries, function(query) { return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i') });
|
191
|
-
}
|
192
|
-
|
193
|
-
function buildHilighters(queries) {
|
194
|
-
return jQuery.map(queries, function(query) {
|
195
|
-
return jQuery.map( query.split(''), function(l, i){ return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2) } ).join('')
|
196
|
-
});
|
197
|
-
}
|
198
|
-
|
199
|
-
// function longMatchRegexp(index, longIndex, regexps) {
|
200
|
-
// for (var i = regexps.length - 1; i >= 0; i--){
|
201
|
-
// if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
|
202
|
-
// };
|
203
|
-
// return true;
|
204
|
-
// }
|
205
|
-
|
206
|
-
|
207
|
-
/* ----- Mathchers ------ */
|
208
|
-
function matchPass1(index, longIndex, queries, regexps) {
|
209
|
-
if (index.indexOf(queries[0]) != 0) return false;
|
210
|
-
for (var i=1, l = regexps.length; i < l; i++) {
|
211
|
-
if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
|
212
|
-
};
|
213
|
-
return true;
|
214
|
-
}
|
215
|
-
|
216
|
-
function matchPass2(index, longIndex, queries, regexps) {
|
217
|
-
if (index.indexOf(queries[0]) == -1) return false;
|
218
|
-
for (var i=1, l = regexps.length; i < l; i++) {
|
219
|
-
if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
|
220
|
-
};
|
221
|
-
return true;
|
222
|
-
}
|
223
|
-
|
224
|
-
function matchPassRegexp(index, longIndex, queries, regexps) {
|
225
|
-
if (!index.match(regexps[0])) return false;
|
226
|
-
for (var i=1, l = regexps.length; i < l; i++) {
|
227
|
-
if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
|
228
|
-
};
|
229
|
-
return true;
|
230
|
-
}
|
231
|
-
|
232
|
-
|
233
|
-
/* ----- Highlighters ------ */
|
234
|
-
function highlightRegexp(info, queries, regexps, highlighters) {
|
235
|
-
var result = createResult(info);
|
236
|
-
for (var i=0, l = regexps.length; i < l; i++) {
|
237
|
-
result.title = result.title.replace(regexps[i], highlighters[i]);
|
238
|
-
if (i > 0)
|
239
|
-
result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
|
240
|
-
};
|
241
|
-
return result;
|
242
|
-
}
|
243
|
-
|
244
|
-
function hltSubstring(string, pos, length) {
|
245
|
-
return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length);
|
246
|
-
}
|
247
|
-
|
248
|
-
function highlightQuery(info, queries, regexps, highlighters) {
|
249
|
-
var result = createResult(info), pos = 0, lcTitle = result.title.toLowerCase();
|
250
|
-
pos = lcTitle.indexOf(queries[0]);
|
251
|
-
if (pos != -1) {
|
252
|
-
result.title = hltSubstring(result.title, pos, queries[0].length);
|
253
|
-
}
|
254
|
-
for (var i=1, l = regexps.length; i < l; i++) {
|
255
|
-
result.title = result.title.replace(regexps[i], highlighters[i]);
|
256
|
-
result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
|
257
|
-
};
|
258
|
-
return result;
|
259
|
-
}
|
260
|
-
|
261
|
-
function createResult(info) {
|
262
|
-
var result = {};
|
263
|
-
result.title = info[0];
|
264
|
-
result.namespace = info[1];
|
265
|
-
result.path = info[2];
|
266
|
-
result.params = info[3];
|
267
|
-
result.snippet = info[4];
|
268
|
-
result.badge = info[6];
|
269
|
-
return result;
|
270
|
-
}
|
271
|
-
|
272
|
-
/* ----- Searching ------ */
|
273
|
-
function performSearch(data, regexps, queries, highlighters, state) {
|
274
|
-
var searchIndex = data.searchIndex, // search by title first and then by source
|
275
|
-
longSearchIndex = data.longSearchIndex,
|
276
|
-
info = data.info,
|
277
|
-
result = [],
|
278
|
-
i = state.from,
|
279
|
-
l = searchIndex.length,
|
280
|
-
togo = CHUNK_SIZE,
|
281
|
-
matchFunc, hltFunc;
|
282
|
-
|
283
|
-
while (state.pass < 3 && state.limit > 0 && togo > 0) {
|
284
|
-
if (state.pass == 0) {
|
285
|
-
matchFunc = matchPass1;
|
286
|
-
hltFunc = highlightQuery;
|
287
|
-
} else if (state.pass == 1) {
|
288
|
-
matchFunc = matchPass2;
|
289
|
-
hltFunc = highlightQuery;
|
290
|
-
} else if (state.pass == 2) {
|
291
|
-
matchFunc = matchPassRegexp;
|
292
|
-
hltFunc = highlightRegexp;
|
293
|
-
}
|
294
|
-
|
295
|
-
for (; togo > 0 && i < l && state.limit > 0; i++, togo--) {
|
296
|
-
if (info[i].n == state.n) continue;
|
297
|
-
if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) {
|
298
|
-
info[i].n = state.n;
|
299
|
-
result.push(hltFunc(info[i], queries, regexps, highlighters));
|
300
|
-
state.limit--;
|
301
|
-
}
|
302
|
-
};
|
303
|
-
if (searchIndex.length <= i) {
|
304
|
-
state.pass++;
|
305
|
-
i = state.from = 0;
|
306
|
-
} else {
|
307
|
-
state.from = i;
|
308
|
-
}
|
309
|
-
}
|
310
|
-
return result;
|
311
|
-
}
|
312
|
-
|
313
|
-
function triggerResults(results, isLast) {
|
314
|
-
jQuery.each(this.handlers, function(i, fn) { fn.call(this, results, isLast) })
|
315
|
-
}
|
316
|
-
}
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
134
|
// panel.js -----------------------------------------------
|
322
135
|
|
323
136
|
Searchdoc.Panel = function(element, data, tree, frame) {
|
@@ -328,7 +141,8 @@ Searchdoc.Panel = function(element, data, tree, frame) {
|
|
328
141
|
this.$current = null;
|
329
142
|
this.$view = this.$result.parent();
|
330
143
|
this.data = data;
|
331
|
-
this.searcher = new
|
144
|
+
this.searcher = new Searcher(data.index);
|
145
|
+
|
332
146
|
this.tree = new Searchdoc.Tree($('.tree', element), tree, this);
|
333
147
|
this.init();
|
334
148
|
}
|
@@ -7,7 +7,8 @@
|
|
7
7
|
<title>search index</title>
|
8
8
|
<link rel="stylesheet" href="../css/reset.css" type="text/css" media="screen" charset="utf-8" />
|
9
9
|
<link rel="stylesheet" href="../css/panel.css" type="text/css" media="screen" charset="utf-8" />
|
10
|
-
<script src="search_index.js" type="text/javascript" charset="utf-8"></script>
|
10
|
+
<script src="../js/search_index.js" type="text/javascript" charset="utf-8"></script>
|
11
|
+
<script src="../js/searcher.js" type="text/javascript" charset="utf-8"></script>
|
11
12
|
<script src="tree.js" type="text/javascript" charset="utf-8"></script>
|
12
13
|
<script src="../js/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
|
13
14
|
<script src="../js/searchdoc.js" type="text/javascript" charset="utf-8"></script>
|
data/lib/sdoc/generator.rb
CHANGED
@@ -2,27 +2,19 @@ require 'rubygems'
|
|
2
2
|
require 'erb'
|
3
3
|
require 'pathname'
|
4
4
|
require 'fileutils'
|
5
|
-
|
6
|
-
if Gem.available? "json"
|
5
|
+
if Gem::Specification.respond_to?(:find_by_name) ? Gem::Specification::find_by_name("json") : Gem.available?("json")
|
7
6
|
gem "json", ">= 1.1.3"
|
8
7
|
else
|
9
8
|
gem "json_pure", ">= 1.1.3"
|
10
9
|
end
|
11
10
|
require 'json'
|
12
|
-
require 'sanitize'
|
13
11
|
|
14
12
|
require 'sdoc/github'
|
15
13
|
require 'sdoc/templatable'
|
16
14
|
require 'sdoc/helpers'
|
17
15
|
require 'rdoc'
|
18
|
-
require 'rdoc/rdoc'
|
19
|
-
require 'rdoc/generator'
|
20
16
|
|
21
17
|
class RDoc::ClassModule
|
22
|
-
def document_self_or_methods
|
23
|
-
document_self || method_list.any?{ |m| m.document_self }
|
24
|
-
end
|
25
|
-
|
26
18
|
def with_documentation?
|
27
19
|
document_self_or_methods || classes_and_modules.any?{ |c| c.with_documentation? }
|
28
20
|
end
|
@@ -116,20 +108,14 @@ class RDoc::Generator::SDoc
|
|
116
108
|
|
117
109
|
GENERATOR_DIRS = [File.join('sdoc', 'generator')]
|
118
110
|
|
119
|
-
# Used in js to reduce index sizes
|
120
|
-
TYPE_CLASS = 1
|
121
|
-
TYPE_METHOD = 2
|
122
|
-
TYPE_FILE = 3
|
123
|
-
|
124
111
|
TREE_FILE = File.join 'panel', 'tree.js'
|
125
|
-
SEARCH_INDEX_FILE = File.join 'panel', 'search_index.js'
|
126
112
|
|
127
113
|
FILE_DIR = 'files'
|
128
114
|
CLASS_DIR = 'classes'
|
129
115
|
|
130
116
|
RESOURCES_DIR = File.join('resources', '.')
|
131
117
|
|
132
|
-
attr_reader :
|
118
|
+
attr_reader :base_dir
|
133
119
|
|
134
120
|
attr_reader :options
|
135
121
|
|
@@ -169,18 +155,20 @@ class RDoc::Generator::SDoc
|
|
169
155
|
@github_url_cache = {}
|
170
156
|
|
171
157
|
@template_dir = Pathname.new(options.template_dir)
|
172
|
-
@
|
158
|
+
@base_dir = Pathname.pwd.expand_path
|
159
|
+
|
160
|
+
@json_index = RDoc::Generator::JsonIndex.new self, options
|
173
161
|
end
|
174
162
|
|
175
163
|
def generate(top_levels)
|
176
|
-
@outputdir = Pathname.new(@options.op_dir).expand_path(@
|
164
|
+
@outputdir = Pathname.new(@options.op_dir).expand_path(@base_dir)
|
177
165
|
@files = top_levels.sort
|
178
166
|
@classes = RDoc::TopLevel.all_classes_and_modules.sort
|
179
167
|
|
180
168
|
# Now actually write the output
|
181
169
|
copy_resources
|
182
170
|
generate_class_tree
|
183
|
-
|
171
|
+
@json_index.generate top_levels
|
184
172
|
generate_file_files
|
185
173
|
generate_class_files
|
186
174
|
generate_index_file
|
@@ -216,8 +204,8 @@ class RDoc::Generator::SDoc
|
|
216
204
|
### Recursivly build class tree structure
|
217
205
|
def generate_class_tree_level(classes, visited = {})
|
218
206
|
tree = []
|
219
|
-
classes.select do |klass|
|
220
|
-
!visited[klass] && klass.with_documentation?
|
207
|
+
classes.select do |klass|
|
208
|
+
!visited[klass] && klass.with_documentation?
|
221
209
|
end.sort.each do |klass|
|
222
210
|
visited[klass] = true
|
223
211
|
item = [
|
@@ -231,30 +219,6 @@ class RDoc::Generator::SDoc
|
|
231
219
|
tree
|
232
220
|
end
|
233
221
|
|
234
|
-
### Create search index for all classes, methods and files
|
235
|
-
### Wite it as json
|
236
|
-
def generate_search_index
|
237
|
-
debug_msg "Generating search index"
|
238
|
-
|
239
|
-
index = {
|
240
|
-
:searchIndex => [],
|
241
|
-
:longSearchIndex => [],
|
242
|
-
:info => []
|
243
|
-
}
|
244
|
-
|
245
|
-
add_class_search_index(index)
|
246
|
-
add_method_search_index(index)
|
247
|
-
add_file_search_index(index)
|
248
|
-
|
249
|
-
debug_msg " writing search index to %s" % SEARCH_INDEX_FILE
|
250
|
-
data = {
|
251
|
-
:index => index
|
252
|
-
}
|
253
|
-
File.open(SEARCH_INDEX_FILE, "w", 0644) do |f|
|
254
|
-
f.write('var search_data = '); f.write(data.to_json(:max_nesting => 0))
|
255
|
-
end unless $dryrun
|
256
|
-
end
|
257
|
-
|
258
222
|
### Add files to search +index+ array
|
259
223
|
def add_file_search_index(index)
|
260
224
|
debug_msg " generating file search index"
|
@@ -366,16 +330,15 @@ class RDoc::Generator::SDoc
|
|
366
330
|
default = @files.first.path
|
367
331
|
return default unless @options.main_page
|
368
332
|
|
369
|
-
#
|
333
|
+
# Transform class name to file path
|
370
334
|
if @options.main_page.include?("::")
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
335
|
+
slashed = @options.main_page.sub(/^::/, "").gsub("::", "/")
|
336
|
+
"%s/%s.html" % [ class_dir, slashed ]
|
337
|
+
elsif file = @files.find { |f| f.full_name == @options.main_page }
|
338
|
+
file.path
|
339
|
+
else
|
340
|
+
default
|
375
341
|
end
|
376
|
-
|
377
|
-
# Nothing else worked, so stick with the default
|
378
|
-
return default
|
379
342
|
end
|
380
343
|
|
381
344
|
### Create index.html with frameset
|
@@ -396,39 +359,6 @@ class RDoc::Generator::SDoc
|
|
396
359
|
self.render_template( templatefile, binding(), outfile )
|
397
360
|
end
|
398
361
|
|
399
|
-
### Strip comments on a space after 100 chars
|
400
|
-
def snippet(str)
|
401
|
-
|
402
|
-
str ||= ''
|
403
|
-
if str =~ /^(?>\s*)[^\#]/
|
404
|
-
content = str
|
405
|
-
else
|
406
|
-
content = str.gsub(/^\s*(#+)\s*/, '')
|
407
|
-
end
|
408
|
-
|
409
|
-
# Get a plain string with no markup.
|
410
|
-
content = Sanitize.clean(RDoc::Markup::ToHtml.new.convert(content))
|
411
|
-
content = content.sub(/^(.{100,}?)\s.*/m, "\\1").gsub(/\r?\n/m, ' ')
|
412
|
-
|
413
|
-
begin
|
414
|
-
content.to_json(:max_nesting => 0)
|
415
|
-
rescue # might fail on non-unicode string
|
416
|
-
begin
|
417
|
-
content = Iconv.conv('latin1//ignore', "UTF8", content) # remove all non-unicode chars
|
418
|
-
content.to_json(:max_nesting => 0)
|
419
|
-
rescue
|
420
|
-
content = '' # something hugely wrong happend
|
421
|
-
end
|
422
|
-
end
|
423
|
-
content
|
424
|
-
end
|
425
|
-
|
426
|
-
### Build search index key
|
427
|
-
def search_string(string)
|
428
|
-
string ||= ''
|
429
|
-
string.downcase.gsub(/\s/,'')
|
430
|
-
end
|
431
|
-
|
432
362
|
### Copy all the resource files to output dir
|
433
363
|
def copy_resources
|
434
364
|
resoureces_path = @template_dir + RESOURCES_DIR
|
data/sdoc.gemspec
CHANGED
@@ -2,35 +2,30 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "sdoc"
|
5
|
-
s.version = "0.3.
|
5
|
+
s.version = "0.3.14"
|
6
6
|
|
7
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
7
|
s.authors = ["Vladimir Kolesnikov"]
|
9
|
-
s.date = %q{2011-09-27}
|
10
8
|
s.description = %q{rdoc generator html with javascript search index.}
|
11
9
|
s.summary = %q{rdoc html with javascript search index.}
|
12
10
|
s.homepage = %q{http://github.com/voloko/sdoc}
|
13
11
|
s.email = %q{voloko@gmail.com}
|
14
12
|
|
15
|
-
s.
|
16
|
-
|
17
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version=
|
13
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if
|
14
|
+
s.respond_to? :required_rubygems_version=
|
18
15
|
|
19
16
|
s.rdoc_options = ["--charset=UTF-8"]
|
20
17
|
s.extra_rdoc_files = ["README.rdoc"]
|
21
18
|
|
22
|
-
s.add_runtime_dependency('rdoc', "~> 3")
|
23
|
-
s.add_runtime_dependency('sanitize', '~> 2')
|
19
|
+
s.add_runtime_dependency('rdoc', "~> 3.10")
|
24
20
|
if defined?(JRUBY_VERSION)
|
25
21
|
s.platform = Gem::Platform.new(['universal', 'java', nil])
|
26
22
|
s.add_runtime_dependency("json_pure", ">= 1.1.3")
|
27
23
|
else
|
28
24
|
s.add_runtime_dependency("json", ">= 1.1.3")
|
29
|
-
end
|
25
|
+
end
|
30
26
|
|
31
27
|
s.files = `git ls-files`.split("\n")
|
32
28
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
33
29
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
34
|
-
s.require_paths = ["lib"]
|
35
30
|
end
|
36
31
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sdoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 14
|
10
|
+
version: 0.3.14
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Vladimir Kolesnikov
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-10-20 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -26,30 +26,17 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 19
|
30
30
|
segments:
|
31
31
|
- 3
|
32
|
-
|
32
|
+
- 10
|
33
|
+
version: "3.10"
|
33
34
|
type: :runtime
|
34
35
|
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: sanitize
|
37
|
-
prerelease: false
|
38
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
hash: 7
|
44
|
-
segments:
|
45
|
-
- 2
|
46
|
-
version: "2"
|
47
|
-
type: :runtime
|
48
|
-
version_requirements: *id002
|
49
36
|
- !ruby/object:Gem::Dependency
|
50
37
|
name: json
|
51
38
|
prerelease: false
|
52
|
-
requirement: &
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
53
40
|
none: false
|
54
41
|
requirements:
|
55
42
|
- - ">="
|
@@ -61,7 +48,7 @@ dependencies:
|
|
61
48
|
- 3
|
62
49
|
version: 1.1.3
|
63
50
|
type: :runtime
|
64
|
-
version_requirements: *
|
51
|
+
version_requirements: *id002
|
65
52
|
description: rdoc generator html with javascript search index.
|
66
53
|
email: voloko@gmail.com
|
67
54
|
executables:
|