7 class DocBuilder : Object
11 public string VERSION = "1.0.0";
14 private Packer packer;
16 public DocBuilder (Packer p)
20 GLib.debug("Roo JsDoc Toolkit started at %s ", (new GLib.DateTime()).format("Y/m/d H:i:s"));
24 if (PackerRun.opt_tmp_dir != null && !FileUtils.test(PackerRun.opt_tmp_dir, GLib.FileTest.IS_DIR)) {
25 Posix.mkdir(PackerRun.opt_tmp_dir, 0700);
31 this.symbolSet = DocParser.symbols;
33 // this currently uses the concept of publish.js...
40 static bool done_init = false;
42 static GLib.Regex regex_dotdot;
50 DocBuilder.regex_dotdot = new Regex("\\\\.\\\\.?[/]");
57 * Parse the source files.
61 private void parseSrcFiles()
66 var useCache = PackerRun.opt_cache_dir == null ;
69 for (var i = 0, l = this.packer.files.size; i < l; i++) {
71 var srcFile = this.packer.files.get(i);
75 cacheFile = PackerRun.opt_cache_dir + srcFile.replace("/", '_') + ".cache";
78 // disabled at present!@!!
80 if (GLib.FileUtils.test(cacheFile, GLib.FileTest.EXISTS)) {
82 var cache_mt = File.new_for_path (cacheFile).queryInfo(FileAttribute.TIME_MODIFIED,
83 GLib.FileQueryInfoFlags.NONE, null).
84 get_modification_time();
85 var original_mt = File.new_for_path (sourceInfo).queryInfo(FileAttribute.TIME_MODIFIED,
86 GLib.FileQueryInfoFlags.NONE, null).
87 get_modification_time();
88 // this check does not appear to work according to the doc's - need to check it out.
90 if (cache_mt > original_mt) { // cached time > original time!
91 // use the cached mtimes..
92 GLib.debug("Read %s" , cacheFile);
93 var parser = new Json.Parser();
94 parser.load_from_file(cacheFile);
95 var ar = parser.get_root ().get_array();
97 for(var i = 0;i < ar.get_length();i++) {
98 var o = ar.get_object_element(i);
99 var sym = Json.gobject_from_data(typeof(Symbol), o) as Symbol;
100 DocParser.symbols.add(sym);
109 GLib.debug("reading : %s" , srcFile);
110 src = GLib.FileUtils.get_contents(srcFile);
112 catch(GLib.FileError e) {
113 GLib.debug("Can't read source file '%s': %s", srcFile, e.to_string());
119 var tr = new TokenReader(this.packer);
122 tr.keepComments = true;
123 tr.sepIdents = false;
124 tr.collapseWhite = false;
128 var toks = tr.tokenize( new TextStream(src) );
129 if (PackerRun.opt_dump_tokens) {
132 //GLib.Process.exit(0);
136 var ts = new TokenStream(toks);
141 DocParser.parse(ts, srcFile);
145 var ar = DocParser.symbolsToObject(srcFile);
147 var builder = new Json.Builder ();
148 builder.begin_array ();
149 for (var i=0;i<ar.size;i++) {
151 builder.add_object_value (ar.get(i));
153 builder.end_array ();
154 Json.Generator generator = new Json.Generator ();
155 Json.Node root = builder.get_root ();
156 generator.set_root (root);
157 generator.pretty= true;
159 generator.to_file(cacheFile);
175 GLib.debug("Publishing");
180 GLib.debug("Making directories");
181 if (!File.isDirectory(PackerRun.opt_doc_target)) {
182 Posix.mkdir(PackerRun.opt_doc_target,0755);
184 if (!File.isDirectory(PackerRun.opt_doc_target+"/symbols")) {
185 Posix.mkdir(PackerRun.opt_doc_target+"/symbols",0755);
187 if (!File.isDirectory(PackerRun.opt_doc_target+"/symbols/src")) {
188 Posix.mkdir(PackerRun.opt_doc_target+"/symbols/src",075);
190 if (!File.isDirectory(PackerRun.opt_doc_target +"/json")) {
191 File.mkdir(PackerRun.opt_doc_target +"/json",0755);
194 GLib.debug("Copying files from static: %s " , PackerRun.opt_doc_template_dir);
195 // copy everything in 'static' into
197 var iter = GLib.File.new_from_path(PackerRun.opt_doc_template_dir + "/static").enumerate_children (
199 FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
203 while ( (info = enumerator.next_file (null)) != null) {
204 if (info.get_file_type () == FileType.DIRECTORY) {
207 var src = File.new_from_path(info.get_name());
208 GLib.debug("Copy %s to %s/%s" , info.get_name() , f, PackerRun.opt_doc_target , src.get_basename());
211 GLib.File.new_from_path(PackerRun.opt_doc_target + '/' + src.get_basename()),
212 GLib.FileCopyFlags.OVERWRITE
217 GLib.debug("Setting up templates");
218 // used to check the details of things being linked to
219 Link.symbolSet = this.symbolSet;// need to work out where 'symbolset will be stored/set!
222 Link.srcFileFlatName = this.srcFileFlatName; // where set?
223 Link.srcFileRelName = this.srcFileRelName; // where set?
225 var classTemplate = new Template( PackerRun.opt_doc_template_dir + "/class." + PackerRun.opt_doc_ext );
226 var classesTemplate = new Template( PackerRun.opt_doc_template_dir+"/allclasses." + PackerRun.opt_doc_ext );
227 var classesindexTemplate = new Template( PackerRun.opt_doc_template_dir +"/index." + PackerRun.opt_doc_ext );
228 var fileindexTemplate = new Template( PackerRun.opt_doc_template_dir +"/allfiles."+ PackerRun.opt_doc_ext );
231 classTemplate.symbolSet = this.symbolSet; // where?
234 function hasNoParent($) {
235 return ($.memberOf == "")
237 function isaFile($) {
238 return ($.is("FILE"))
240 function isaClass($) {
241 return ($.is("CONSTRUCTOR") || $.isNamespace || $.isClass);
253 var symbols = this.symbolSet.toArray();
255 var files = this.packer.files;
257 for (var i = 0, l = files.size; i < l; i++) {
258 var file = files.get(i);
259 var targetDir = PackerRun.opt_doc_target + "/symbols/src/";
260 this.makeSrcFile(file, targetDir);
262 //print(JSON.stringify(symbols,null,4));
263 var classes = new Gee.ArrayList<Symbol>();
265 foreach(var symbol in symbols) {
266 if (symbol.isaClass()) {
270 classes.sort( (a,b) => {
271 return a.alias.collate(b.alias);
274 //GLib.debug("classTemplate Process : all classes");
276 // var classesIndex = classesTemplate.process(classes); // kept in memory
278 GLib.debug("iterate classes");
280 var jsonAll = new JSON.Object();
282 for (var i = 0, l = classes.size; i < l; i++) {
283 var symbol = classes.get(i);
286 GLib.debug("classTemplate Process : %s" , symbol.alias);
291 FileUtils.set_contents(
292 PackerRun.opt_doc_target+"/symbols/" +symbol.alias+'.' + PackerRun.opt_doc_ext ,
293 classTemplate.process(symbol)
296 jsonAll.set_object_member(symbol.alias, this.publishJSON(symbol));
299 Json.Generator generator = new Json.Generator ();
300 generator.set_root (jsonAll.get_node());
301 generator.pretty= true;
303 generator.to_file(PackerRun.opt_doc_target+"/json/roodata.json");
307 // regenrate the index with different relative links
309 //var classesIndex = classesTemplate.process(classes);
311 GLib.debug("build index");
313 FileUtils.set_contents(
314 PackerRun.opt_doc_target + "/index." _ PackerRun.opt_doc_ext
315 classesindexTemplate.process(classes)
318 // blank everything???? classesindexTemplate = classesIndex = classes = null;
322 var documentedFiles = symbols.filter(function ($) {
323 return ($.is("FILE"))
328 for (var i = 0; i < files.length; i++) {
329 allFiles.push(new Symbol(files[i], [], "FILE", new DocComment("/** *" + "/")));
332 for (var i = 0; i < documentedFiles.length; i++) {
333 var offset = files.indexOf(documentedFiles[i].alias);
334 allFiles[offset] = documentedFiles[i];
337 allFiles = allFiles.sort(makeSortby("name"));
338 GLib.debug("write files index");
340 FileUtils.set_contents(
341 PackerRun.opt_doc_target + "/files." + PackerRun.opt_doc_ext ,
342 fileindexTemplate.process(allFiles)
350 * JSON files are lookup files for the documentation
351 * - can be used by IDE's or AJAX based doc tools
355 JSON.Object publishJSON (Symbol data)
357 // what we need to output to be usefull...
359 var cfgProperties = new GLib.ArrayList<Symbol>();
360 if (!data.comment.getTag(DocTagTitle.SINGLETON).length) {
361 cfgProperties = data.configToArray();
362 cfgProperties = cfgProperties.sort((a,b) =>{
363 return a.alias.collate(b.alias);
368 var props = new JSON.Array();;
369 //println(cfgProperties.toSource());
371 for(var i =0; i < cfgProperties.size;i++) {
372 var p = cfgPropertiesget.get(i);
373 var add = new JSON.Object();
374 add.set_string_member("name",p.name);
375 add.set_string_member("type",p.type);
376 add.set_string_member("desc",p.desc);
377 add.set_string_member("memberOf", p.memberOf == data.alias ? '' : p.memberOf);
379 if (p.optvalues.size) {
380 add.set_array_member("desc",p.optvalues_as_json_array());
382 props.add_object(add );
386 var ownEvents = new Gee.ArrayList<Symbol>();
387 for(var i =0; i < data.methods.size;i++) {
388 var e = data.methods.get(i);
389 if (e.isEvent && e.comment.getTag(DocTagTitle.HIDE) == "") {
393 ownEvents.sort((a,b) => {
394 return a.name.collate(b.name);
397 var events = new JSON.Array();
399 for(var i =0; i < ownEvents.size;i++) {
400 var m = ownEvents.get(i);
401 var add = new JSON.Object();
402 add.set_string_member("name",m.name.substring(1,m.name.length-1);
403 add.set_string_member("type","function");
404 add.set_string_member("desc",m.desc);
405 add.set_string_member("sig", this.makeFuncSkel(m.params));
410 var ownMethods = new Gee.ArrayList<Symbol>();
411 for(var i =0; i < data.methods.size;i++) {
412 var e = data.methods.get(i);
413 if (!e.isEvent && e.comment.getTag(DocTagTitle.HIDE) == "") {
417 ownMethods.sort((a,b) => {
418 return a.name.collate(b.name);
421 var methods = new JSON.Array();
423 for(var i =0; i < ownMethods.size;i++) {
424 var m = ownMethods.get(i);
425 var add = new JSON.Object();
426 add.set_string_member("name",m.name.substring(1,m.name.length-1);
427 add.set_string_member("type","function");
428 add.set_string_member("desc",m.desc);
429 add.set_string_member("sig", this.makeMethodSkel(m.params));
433 //println(props.toSource());
434 // we need to output:
440 var ret = new JSON.Object();
441 ret.set_object_member("props", props);
442 ret.set_object_member("events", events);
443 ret.set_object_member("methods", methods);
455 string srcFileRelName(string sourceFile)
457 return sourceFile.substring(PackerRun.opt_real_basedir.length+1);
459 string srcFileFlatName(string sourceFile)
461 var name = this.srcFileRelName(sourceFile);
462 name = DocBuilder.regex_dotdot.replace(name, name.length, 0, "");
463 name = name.replace("/", "_").replace(":", "_") + .".html";
468 void makeSrcFile(string sourceFile)
470 // this stuff works...
473 var name = this.srcFileFlatName(sourceFile);
475 GLib.debug("Write Source file : %s/symbols/src/%s", opt_doc_target, name);
476 var pretty = PrettyPrint.toPretty(FileUtils.get_contenst(sourceFile));
477 File.write(PackerRun.opt_doc_target+"/symbols/src/" + name,
479 "<title>" + sourceFile + "</title>" +
480 "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../../css/highlight-js.css\"/>" +
481 "</head><body class=\"highlightpage\">" +
486 * used by JSON output to generate a function skeleton
489 string makeFuncSkel(Gee.ArrayList<Symbol> params) {
490 if (params.length < 0) {
491 return "function ()\n{\n\n}";
494 return "function (" +
497 return $.name.indexOf(".") == -1; // don't show config params in signature
499 ).map( function($) { return $.name == 'this' ? '_self' : $.name; } ).join(", ") +
502 makeMethodSkel :function(params) {
503 if (!params) return "()";
507 return $.name.indexOf(".") == -1; // don't show config params in signature
509 ).map( function($) { return $.type + " " +( $.name == 'this' ? '_self' : $.name ); } ).join(", ") +