Permalink
Browse files

Created the ultimate TOC generator in javascript, build stylesheet fr…

…om sass, improve rakefile by using rules
  • Loading branch information...
manveru committed Apr 16, 2009
1 parent 5a37661 commit fbbdde3f7317ab92922fc9ef86e357f7acb21349
Showing with 429 additions and 78 deletions.
  1. +30 −15 Rakefile
  2. +138 −63 javascripts/toc.js
  3. +261 −0 stylesheets/xhtml11.sass
View
@@ -28,6 +28,7 @@ file JTR_XML => [JTR_TXT, *CHAPTER_FILES] do
end
namespace :build do
+ # the formats going over docbook format
formats.each do |format|
jtr_dir = "#{format}/"
jtr_base = "journey_to_ramaze.#{format}"
@@ -56,16 +57,24 @@ namespace :build do
file(jtr_dir){ mkdir(jtr_dir) }
end
+ # the asciidoc-xhtml
+
+ jtr_scripts = File.expand_path('javascripts')
+ jtr_styles = File.expand_path('stylesheets')
+ jtr_css = 'stylesheets/xhtml11.css'
jtr_dir = 'asciidoc-xhtml/'
jtr_base = 'journey_to_ramaze.html'
jtr_path = File.join(jtr_dir, jtr_base)
- CLOBBER.include(jtr_dir)
+
+ jtr_depends = [jtr_dir, JTR_TXT, jtr_css] + CHAPTER_FILES + XMP_FILES
+
+ CLOBBER.include(jtr_dir, File.join(jtr_styles, '**/*.css'))
file(jtr_dir){ mkdir(jtr_dir) }
- file jtr_path => [jtr_dir, JTR_TXT, *(CHAPTER_FILES + XMP_FILES)] do
- scripts_dir = File.expand_path('javascripts')
+ file jtr_path => jtr_depends do
sh('asciidoc',
- '--attribute', "scriptsdir=#{scripts_dir}",
+ '--attribute', "scriptsdir=#{jtr_scripts}",
+ '--attribute', "stylesdir=#{jtr_styles}",
'--attribute', 'toc',
'--backend', 'xhtml11',
'--doctype', 'book',
@@ -89,21 +98,20 @@ namespace :xmp do
'--interpreter', RUBY
]
- SOURCE_FILES.each do |source_file|
- xmp_file = source_file.sub(/\.rb$/, '.xmp')
+ rule('.xmp' => ['.rb']) do |t|
+ source_file = t.source
+ xmp_file = t.name
- file xmp_file => [source_file] do
- invocation = (xmp_invocation + [source_file]).join(' ')
+ invocation = (xmp_invocation + [source_file]).join(' ')
- puts "Converting #{source_file} to xmp => #{xmp_file}"
- puts invocation
- original_source = File.read(source_file).strip
- xmp_source = `#{invocation}`.strip
+ puts "Converting #{source_file} to xmp => #{xmp_file}"
+ puts invocation
+ original_source = File.read(source_file).strip
+ xmp_source = `#{invocation}`.strip
- fail("XMP failed for #{source_file}") if xmp_source == original_source
+ fail("XMP failed for #{source_file}") if xmp_source == original_source
- File.open(xmp_file, 'w+'){|xmp| xmp.write(xmp_source) }
- end
+ File.open(xmp_file, 'w+'){|xmp| xmp.write(xmp_source) }
end
CHAPTER_FILES.each do |chapter_file|
@@ -114,3 +122,10 @@ namespace :xmp do
end
end
end
+
+rule('.css' => ['.sass']) do |t|
+ sh('sass',
+ '--style', 'compressed', # nested, compact, compressed, expaned
+ t.source,
+ t.name)
+end
View
@@ -1,70 +1,145 @@
-/* Author: Mihai Bazon, September 2002
- * http://students.infoiasi.ro/~mishoo
- *
- * Table Of Content generator
- * Version: 0.4
- *
- * Feel free to use this script under the terms of the GNU General Public
- * License, as long as you do not remove or alter this notice.
- */
-
- /* modified by Troy D. Hanson, September 2006. License: GPL */
- /* modified by Stuart Rackham, October 2006. License: GPL */
- /* modified by Michael Fellinger, April 2009. License: GPL */
-
-function getText(el) {
- var text = "";
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
- text += i.data;
- else if (i.firstChild != null)
- text += getText(i);
- }
- return text;
-}
+TOCCreator = {
+ Header: function(level, text, visible, id){
+ var obj = {
+ level: level,
+ text: text,
+ id: id,
+ visible: visible,
+ childs: [],
+ mother: null,
-function TocEntry(el, text, toclevel) {
- this.element = el;
- this.text = text;
- this.toclevel = toclevel;
-}
+ add_child: function(child){
+ this.childs.push(child);
+ child.mother = this;
+ },
+
+ to_html: function(out){
+ var ol, li, a;
+
+ if(this.visible){
+ li = document.createElement('li');
+ a = document.createElement('a');
+ a.innerHTML = this.text;
+ a.href = '#' + this.id;
+ li.appendChild(a);
+ out.appendChild(li);
+
+ if(this.childs.length > 0){
+ ol = document.createElement('ol');
+ li.appendChild(ol);
+
+ this.each_child_to_html(ol);
+ }
+ } else {
+ ol = document.createElement('ol');
+ out.appendChild(ol);
+ this.each_child_to_html(ol);
+ }
+
+ return(out);
+ },
+
+ each_child_to_html: function(root){
+ for(child_i in this.childs){
+ this.childs[child_i].to_html(root);
+ }
+ }
+ };
+
+ return(obj);
+ },
+
+ elements_by_tag_names: function(list, given_doc){
+ var doc = (doc || document);
+ var tag_names = list.split(',');
+ var tags = [];
-function tocEntries(el, toclevels) {
- var result = new Array;
- var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
- // Function that scans the DOM tree for header elements (the DOM2
- // nodeIterator API would be a better technique but not supported by all
- // browsers).
- var iterate = function (el) {
- for (var i = el.firstChild; i != null; i = i.nextSibling) {
- if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
- var mo = re.exec(i.tagName)
- if (mo)
- result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
- iterate(i);
+ for(tag_names_i in tag_names){
+ var partials = doc.getElementsByTagName(tag_names[tag_names_i]);
+
+ for(i = 0; i < partials.length; i++){
+ tags.push(partials[i]);
}
}
- }
- iterate(el);
- return result;
-}
-// This function does the work. toclevels = 1..4.
-function generateToc(toclevels) {
- var toc = document.getElementById("toc");
- var entries = tocEntries(document.getElementsByTagName("body")[0], toclevels);
- for (var i = 0; i < entries.length; ++i) {
- var entry = entries[i];
- if (entry.element.id == "")
- entry.element.id = "toc" + i;
- var a = document.createElement("a");
- a.href = "#" + entry.element.id;
- a.appendChild(document.createTextNode(entry.text));
- var div = document.createElement("div");
- div.appendChild(a);
- div.className = "toclevel" + entry.toclevel;
- toc.appendChild(div);
+ var test_node = tags[0];
+
+ if(!test_node){
+ return([]);
+ } else if(test_node.sourceIndex){
+ tags.sort(function(a, b){ return(a.sourceIndex - b.sourceIndex); });
+ } else if(test_node.compareDocumentPosition){
+ tags.sort(function(a, b){ return(3 - (a.compareDocumentPosition(b) & 6)); });
+ }
+
+ return(tags);
+ },
+
+ collect_headers: function(given_levels, doc){
+ var levels = (given_levels || 'h1,h2,h3,h4,h5');
+ var headers = [];
+ var tags = this.elements_by_tag_names(levels, doc);
+
+ for(tag_i in tags){
+ var tag, level, text, id
+
+ tag = tags[tag_i];
+ level = tag.nodeName.match('H(\\d+)')[1];
+ text = tag.innerHTML;
+
+ if(tag.id){
+ id = tag.id;
+ } else {
+ id = 'toc_' + tag_i;
+ tag.id = id;
+ }
+
+ headers.push({toclevel: level, text: text, id: id});
+ }
+
+ return(headers);
+ },
+
+ generate_ast: function(doc){
+ var headers = this.collect_headers(doc);
+ var original_root = new this.Header(1, 'ROOT', false);
+ var root = original_root;
+ root.mother = root;
+
+ for(header_i in headers){
+ var element = headers[header_i];
+ var header = new this.Header(element.toclevel, element.text, true, element.id);
+ var temp = root;
+ var i;
+
+ if(header.level == root.level){
+ root.mother.add_child(header);
+ } else if(header.level > root.level){
+ for(i = (header.level - 1); i > root.level; i--){
+ var temp_child = new this.Header(i, 'TEMP', false);
+ temp.add_child(temp_child);
+ temp = temp_child;
+ }
+
+ temp.add_child(header);
+ } else if(header.level < root.level){
+ for(i = header.level; i <= root.level; i++){
+ var temp_mother = temp.mother;
+ temp = temp_mother;
+ }
+
+ temp.add_child(header);
+ }
+
+ root = header;
+ }
+
+ return(original_root);
}
- if (entries.length == 0)
- document.getElementById("header").removeChild(toc);
+};
+
+function generateToc(n){
+ var root = document.getElementById('toc');
+ var ast = TOCCreator.generate_ast();
+ ast.to_html(root);
}
Oops, something went wrong.

0 comments on commit fbbdde3

Please sign in to comment.