00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "bookmark_tree.cpp"
00023
00024 #include <basis/function.h>
00025 #include <basis/guards.h>
00026 #include <basis/istring.h>
00027 #include <data_struct/stack.cpp>
00028 #include <opsystem/application_shell.h>
00029 #include <opsystem/byte_filer.h>
00030 #include <opsystem/command_line.h>
00031 #include <loggers/file_logger.h>
00032 #include <opsystem/filename.h>
00033 #include <data_struct/static_memory_gremlin.h>
00034 #include <textual/list_parsing.h>
00035
00036 using namespace nodes;
00037
00038
00039
00040
00041 #undef BASE_LOG
00042 #define BASE_LOG(s) program_wide_logger().log(s)
00043 #undef LOG
00044 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), \
00045 isprintf("line %d: ", _categories._line_number) + s)
00046
00047 const int MAX_FILE_SIZE = 4 * MEGABYTE;
00048
00049
00051
00052 class marks_maker_javascript : public application_shell
00053 {
00054 public:
00055 marks_maker_javascript()
00056 : application_shell(static_class_name()), _need_closure(false),
00057 _loader_count(0), _link_spool(0), _functions_pending(0) {}
00058 IMPLEMENT_CLASS_NAME("marks_maker_javascript");
00059 virtual int execute();
00060 int print_instructions(const filename &program_name);
00061
00062 int write_marks_page(const istring &output_filename,
00063 const istring &template_filename);
00064
00065
00066
00067 private:
00068 bookmark_tree _categories;
00069 bool _need_closure;
00070 int _loader_count;
00071 int _link_spool;
00072 stack<istring> _functions_pending;
00073
00074
00075
00076
00077
00078
00079
00080 void write_category(inner_mark_tree *node, istring &output);
00081 void write_link(inner_mark_tree *node, const link_record &linko,
00082 istring &output);
00083 };
00084
00086
00087 int marks_maker_javascript::print_instructions(const filename &program_name)
00088 {
00089 isprintf to_show("%s:\n\
00090 This program needs three filenames as command line parameters. The -i flag\n\
00091 is used to specify the input filename, the -t flag specifies a template web\n\
00092 page which is used as the wrapper around the links, and the -o flag specifies\n\
00093 the web page to be created. The input file is expected to be in the HOOPLE\n\
00094 link database format. The output file will be created from the template file\n\
00095 by finding the phrase $INSERT_LINKS_HERE in it and replacing that with html\n\
00096 formatted link and categories from the input file. Another tag of $TODAYS_DATE\n\
00097 will be replaced with the date when the output file is regenerated.\n\
00098 The HOOPLE link format is documented here:\n\
00099 http://hoople.org/guides/link_database/format_manifesto.txt\n\
00100 ", program_name.basename().raw().s(), program_name.basename().raw().s());
00101 program_wide_logger().log(to_show.s());
00102 return 12;
00103 }
00104
00105 void marks_maker_javascript::write_category(inner_mark_tree *node, istring &output)
00106 {
00107 FUNCDEF("write_category");
00108
00109
00110 int node_num = node->_uid;
00111 inner_mark_tree *parent = dynamic_cast<inner_mark_tree *>(node->parent());
00112 int parent_node = parent? parent->_uid : -1;
00113
00114 istring chewed_name = node->name();
00115 for (int i = chewed_name.end(); i >= 0; i--) {
00116
00117 if (chewed_name[i] == '\'') {
00118 chewed_name.zap(i, i);
00119 chewed_name.insert(i, "\\'");
00120 }
00121 }
00122 output += isprintf(" b.add(%d, %d, '%s');\n", node_num, parent_node,
00123 chewed_name.s());
00124 }
00125
00126 void marks_maker_javascript::write_link(inner_mark_tree *node, const link_record &linko,
00127 istring &output)
00128 {
00129 FUNCDEF("write_link");
00130
00131 int parent_node = node->_uid;
00132 istring chewed_name = linko._description;
00133 for (int i = chewed_name.end(); i >= 0; i--) {
00134
00135 if (chewed_name[i] == '\'') {
00136 chewed_name.zap(i, i);
00137 chewed_name.insert(i, "\\'");
00138 }
00139 }
00140
00141 if (!linko._url) {
00142
00143 if (!linko._description) return;
00144
00145
00146
00147
00148
00149
00150
00151
00152 return;
00153 }
00154
00155
00156 if (! (_link_spool % 100) ) {
00157 if (_link_spool) {
00158
00159 output += " setTimeout('run_tree_loaders()', 0);\n";
00160 output += "}\n";
00161 }
00162
00163 output += isprintf("function tree_loader_%d() {\n", _loader_count++);
00164 }
00165 _link_spool++;
00166
00167 output += isprintf(" b.add(%d, %d, '%s', '%s');\n",
00168 linko._uid, parent_node, chewed_name.s(), linko._url.s());
00169 }
00170
00171 int marks_maker_javascript::execute()
00172 {
00173 FUNCDEF("execute");
00174 SET_DEFAULT_COMBO_LOGGER;
00175
00176 command_line cmds(__argc, __argv);
00177 istring input_filename;
00178 istring output_filename;
00179 istring template_filename;
00180 if (!cmds.get_value('i', input_filename, false))
00181 return print_instructions(cmds.program_name());
00182 if (!cmds.get_value('o', output_filename, false))
00183 return print_instructions(cmds.program_name());
00184 if (!cmds.get_value('t', template_filename, false))
00185 return print_instructions(cmds.program_name());
00186
00187 BASE_LOG(istring("input file: ") + input_filename);
00188 BASE_LOG(istring("output file: ") + output_filename);
00189 BASE_LOG(istring("template file: ") + template_filename);
00190
00191 int ret = _categories.read_csv_file(input_filename);
00192 if (ret) return ret;
00193
00194 ret = write_marks_page(output_filename, template_filename);
00195 if (ret) return ret;
00196
00197 return 0;
00198 }
00199
00200 int marks_maker_javascript::write_marks_page(const istring &output_filename,
00201 const istring &template_filename)
00202 {
00203 FUNCDEF("write_marks_page");
00204 istring long_string;
00205
00206
00207
00208
00209 long_string += "<div class=\"marks_target\" id=\"martarg\">Marks Target</div>\n";
00210
00211
00212 long_string += "\n<div class=\"dtree\">\n";
00213 long_string += "<script type=\"text/javascript\">\n";
00214 long_string += "<!--\n";
00215
00216 long_string += "function open_mark(url) {\n";
00217 long_string += " window.open(url, '', '');\n";
00218 long_string += "}\n";
00219
00220
00221
00222 long_string += " b = new dTree('b');\n";
00224 long_string += " b.config.useCookies = false;\n";
00225 long_string += " b.config.folderLinks = false;\n";
00226
00227
00228 tree::iterator itty = _categories.access_root().start(tree::prefix);
00229 tree *curr = NIL;
00230 while ( (curr = itty.next()) ) {
00231 inner_mark_tree *nod = (inner_mark_tree *)curr;
00232
00233 write_category(nod, long_string);
00234
00235
00236 for (int i = 0; i < nod->_links.elements(); i++) {
00237 link_record *lin = nod->_links.borrow(i);
00238 write_link(nod, *lin, long_string);
00239 }
00240 }
00241
00242
00243 long_string += " setTimeout('run_tree_loaders()', 0);\n";
00244 long_string += "}\n\n";
00245
00246 long_string += isprintf("function tree_loader_%d()"
00247 "{ setTimeout('run_tree_loaders()', 0); }\n", _loader_count++);
00248
00249 long_string += "\nconst max_funcs = 1000;\n";
00250 long_string += "var loader_functions = new Array(max_funcs);\n";
00251 long_string += "var curr_func = 0;\n";
00252 long_string += "var done_rendering = false;\n\n";
00253
00254 long_string += isprintf("for (var i = 0; i < %d; i++) {\n", _loader_count);
00255 long_string += " loader_functions[curr_func++] "
00256 "= 'tree_loader_' + i + '()';\n";
00257 long_string += "}\n";
00258
00259 long_string += "var run_index = 0;\n";
00260 long_string += "function run_tree_loaders() {\n";
00261 long_string += " if (done_rendering) return;\n";
00262 long_string += " if (run_index >= curr_func) {\n";
00263
00264 long_string += " if (document.getElementById) {\n";
00265 long_string += " x = document.getElementById('martarg');\n";
00266 long_string += " x.innerHTML = '';\n";
00267 long_string += " x.innerHTML = b;\n";
00268 long_string += " } else { document.write(b); }\n";
00269
00270
00271 long_string += " done_rendering = true;\n";
00272 long_string += " return;\n";
00273 long_string += " }\n";
00274 long_string += " var next_func = loader_functions[run_index++];\n";
00275 long_string += " setTimeout(next_func, 0);\n";
00276 long_string += "}\n";
00277
00278 long_string += isprintf(" run_tree_loaders();\n", _loader_count);
00279
00280 long_string += "//-->\n";
00281 long_string += "</script>\n";
00282 long_string += "<p><a href=\"javascript: b.openAll();\">open all</a> | "
00283 "<a href=\"javascript: b.closeAll();\">close all</a></p>\n";
00284 long_string += "</div>\n";
00285
00286 byte_filer template_file(template_filename, "r");
00287 istring full_template;
00288 if (!template_file.good())
00289 non_continuable_error(class_name(), func, "the template file could not be opened");
00290 template_file.read(full_template, MAX_FILE_SIZE);
00291 template_file.close();
00292
00293
00294 int indy = full_template.ifind("</title>");
00295 if (negative(indy))
00296 non_continuable_error(class_name(), func, "the template file is missing "
00297 "a <head> declaration");
00298
00299 full_template.insert(indy + 8, "\n\n"
00300 "<link rel=\"StyleSheet\" href=\"/yeti/javascript/dtree/dtree.css\" "
00301 "type=\"text/css\" />\n"
00302 "<script type=\"text/javascript\" src=\"/yeti/javascript/"
00303 "dtree/dtree.js\"></script>\n");
00304
00305
00306 bool found_it = full_template.replace("$INSERT_LINKS_HERE", long_string);
00307 if (!found_it)
00308 non_continuable_error(class_name(), func, "the template file is missing "
00309 "the insertion point");
00310 full_template.replace("$TODAYS_DATE", timestamp(false, true));
00311
00312 filename outname(output_filename);
00313 if (outname.exists()) {
00314 non_continuable_error(class_name(), func, istring("the output file ")
00315 + output_filename + " already exists. It would be over-written if "
00316 "we continued.");
00317 }
00318
00319 byte_filer output_file(output_filename, "w");
00320 if (!output_file.good())
00321 non_continuable_error(class_name(), func, "the output file could not be opened");
00322
00323 output_file.write(full_template);
00324 output_file.close();
00325
00326
00327
00328
00329
00330 BASE_LOG(isprintf("wrote %d links in %d categories.",
00331 _categories.link_count(), _categories.category_count()));
00332 BASE_LOG("");
00333
00334 return 0;
00335 }
00336
00338
00339 HOOPLE_MAIN(marks_maker_javascript, )
00340
00341 #ifdef __BUILD_STATIC_APPLICATION__
00342
00343 #include <basis/array.cpp>
00344 #include <basis/byte_array.cpp>
00345 #include <basis/callstack_tracker.cpp>
00346 #include <basis/chaos.cpp>
00347 #include <basis/convert_utf.cpp>
00348 #include <basis/definitions.cpp>
00349 #include <basis/earth_time.cpp>
00350 #include <basis/guards.cpp>
00351 #include <basis/istring.cpp>
00352 #include <basis/log_base.cpp>
00353 #include <basis/memory_checker.cpp>
00354 #include <basis/mutex.cpp>
00355 #include <basis/object_base.cpp>
00356 #include <basis/outcome.cpp>
00357 #include <basis/packable.cpp>
00358 #include <basis/portable.cpp>
00359 #include <basis/sequence.cpp>
00360 #include <basis/set.cpp>
00361 #include <basis/utility.cpp>
00362 #include <basis/version_record.cpp>
00363 #include <data_struct/amorph.cpp>
00364 #include <data_struct/bit_vector.cpp>
00365 #include <data_struct/byte_hasher.cpp>
00366 #include <data_struct/configurator.cpp>
00367 #include <data_struct/hash_table.cpp>
00368 #include <data_struct/pointer_hash.cpp>
00369 #include <data_struct/stack.cpp>
00370 #include <data_struct/static_memory_gremlin.cpp>
00371 #include <data_struct/string_hash.cpp>
00372 #include <data_struct/string_hasher.cpp>
00373 #include <data_struct/string_table.cpp>
00374 #include <data_struct/symbol_table.cpp>
00375 #include <data_struct/table_configurator.cpp>
00376 #include <loggers/console_logger.cpp>
00377 #include <loggers/file_logger.cpp>
00378 #include <loggers/locked_logger.cpp>
00379 #include <loggers/null_logger.cpp>
00380 #include <loggers/program_wide_logger.cpp>
00381 #include <nodes/node.cpp>
00382 #include <nodes/path.cpp>
00383 #include <nodes/symbol_tree.cpp>
00384 #include <nodes/tree.cpp>
00385 #include <opsystem/application_base.cpp>
00386 #include <opsystem/application_shell.cpp>
00387 #include <opsystem/byte_filer.cpp>
00388 #include <opsystem/command_line.cpp>
00389 #include <opsystem/critical_events.cpp>
00390 #include <opsystem/directory.cpp>
00391 #include <opsystem/filename.cpp>
00392 #include <opsystem/ini_config.cpp>
00393 #include <opsystem/ini_parser.cpp>
00394 #include <opsystem/path_configuration.cpp>
00395 #include <opsystem/rendezvous.cpp>
00396 #include <textual/byte_format.cpp>
00397 #include <textual/list_parsing.cpp>
00398 #include <textual/parser_bits.cpp>
00399 #include <textual/string_manipulation.cpp>
00400 #include <textual/tokenizer.cpp>
00401 #endif // __BUILD_STATIC_APPLICATION__
00402