nandoc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/README +124 -0
  2. data/Rakefile +53 -0
  3. data/bin/nandoc +6 -0
  4. data/doc/CREDITS.md +6 -0
  5. data/doc/FAQ/why-not-wiki.md +20 -0
  6. data/doc/FAQ.md +68 -0
  7. data/doc/TODOs-and-BUGs.md +15 -0
  8. data/doc/bar/baz.md +4 -0
  9. data/doc/bar/bliff.md +8 -0
  10. data/doc/foo.md +5 -0
  11. data/doc/getting-started.rb +13 -0
  12. data/doc/svg/less-fonts.svg +21 -0
  13. data/lib/nandoc/commands/create-nandoc-site.rb +225 -0
  14. data/lib/nandoc/commands/diff.rb +279 -0
  15. data/lib/nandoc/config.rb +58 -0
  16. data/lib/nandoc/cri-hacks.rb +13 -0
  17. data/lib/nandoc/data-source.rb +239 -0
  18. data/lib/nandoc/filters.rb +661 -0
  19. data/lib/nandoc/helpers/menu-bouncy.rb +109 -0
  20. data/lib/nandoc/helpers/site-map.rb +157 -0
  21. data/lib/nandoc/helpers/top-nav.rb +47 -0
  22. data/lib/nandoc/helpers.rb +42 -0
  23. data/lib/nandoc/item-class-hacks.rb +57 -0
  24. data/lib/nandoc/nandoc.persistent.json +3 -0
  25. data/lib/nandoc/parse-readme.rb +95 -0
  26. data/lib/nandoc/spec-doc/mini-test/spec-instance-methods.rb +0 -0
  27. data/lib/nandoc/spec-doc/mini-test.rb +105 -0
  28. data/lib/nandoc/spec-doc/mock-prompt.rb +121 -0
  29. data/lib/nandoc/spec-doc/support-modules.rb +158 -0
  30. data/lib/nandoc/spec-doc/test-case-agent.rb +57 -0
  31. data/lib/nandoc/spec-doc/test-framework-dispatcher.rb +15 -0
  32. data/lib/nandoc/spec-doc/test-framework-proxy.rb +78 -0
  33. data/lib/nandoc/spec-doc.rb +46 -0
  34. data/lib/nandoc/support/diff-proxy.rb +113 -0
  35. data/lib/nandoc/support/orphanage.rb +77 -0
  36. data/lib/nandoc/support/path-tardo.rb +85 -0
  37. data/lib/nandoc/support/regexp-enhance.rb +76 -0
  38. data/lib/nandoc/support/site-diff.rb +46 -0
  39. data/lib/nandoc/support/site-merge.rb +62 -0
  40. data/lib/nandoc/support/site-methods.rb +69 -0
  41. data/lib/nandoc/support/stream-colorizer.rb +203 -0
  42. data/lib/nandoc/support-modules.rb +270 -0
  43. data/lib/nandoc/test/diff-to-string.rb +251 -0
  44. data/lib/nandoc/test/minitest-extlib.rb +53 -0
  45. data/lib/nandoc/treebis/NOGIT-DOCS/NEWS.md +5 -0
  46. data/lib/nandoc/treebis/NOGIT-README.md +65 -0
  47. data/lib/nandoc/treebis/nandoc.persistent.json +3 -0
  48. data/lib/nandoc.rb +48 -0
  49. data/proto/README.md +31 -0
  50. data/proto/default/Rakefile +1 -0
  51. data/proto/default/Rules +46 -0
  52. data/proto/default/config.yaml +57 -0
  53. data/proto/default/content/css/nanoc-dist-altered.css +213 -0
  54. data/proto/default/content/css/trollop-subset.css +116 -0
  55. data/proto/default/content/js/menu-bouncy.js +126 -0
  56. data/proto/default/content/stylesheet.css.diff +20 -0
  57. data/proto/default/content/vendor/jquery-1.3.js +4241 -0
  58. data/proto/default/content/vendor/jquery.easing.1.3.js +205 -0
  59. data/proto/default/layouts/default.html +70 -0
  60. data/proto/default/lib/default.orig.rb +2 -0
  61. data/proto/default/lib/default.rb +5 -0
  62. data/proto/default/treebis-task.rb +28 -0
  63. data/proto/misc/orphan-surrogate.md +6 -0
  64. data/test/test.rb +102 -0
  65. metadata +166 -0
data/README ADDED
@@ -0,0 +1,124 @@
1
+ <embed
2
+ style='position: absolute; right:0; top:0'
3
+ src="svg/less-fonts.svg" width="150px" height="150px"
4
+ type="image/svg+xml"
5
+ pluginspage="http://www.adobe.com/svg/viewer/install/" />
6
+
7
+ # NanDoc
8
+ this is a hack. this is nanDoc.
9
+
10
+ ## Summary
11
+
12
+ hack of [nanoc3](http://nanoc.stoneship.org) to generate a static site of your ruby project from your README etc.
13
+
14
+ ## Description
15
+
16
+ Generate a static site to document your ruby project from your README and other markdown-formatted documentation. Inject code examples from your unit tests into the generated docs. Extremely fragile hacks and some cool additions to nanoc3.
17
+
18
+ (This entire site is generated from a README and other docs with all
19
+ of the code examples coming from unit test "scrapes.")
20
+
21
+ ## Does this match you?
22
+
23
+ * Tired of all the other unit-test-driven static documentation-site-generators
24
+ that fall short of the usual promises?
25
+
26
+ * Agile development has your documentation content going rapidly stale?
27
+
28
+ * Sick of typing what you want to write by hand?
29
+
30
+ * Repeatedly hearing yourself repeat to yourself "Don't Repeat Yourself?"
31
+
32
+ * Don't underkill your documentation when it's so easy to &Uuml;berkill&trade; it! Don't be fooled by impostors!
33
+
34
+ <b>IF</b> you ansewered <b>YES</b> to zero or more of the above questions (of those that were
35
+ questions and not imperative statements), then <b>DON'T WAIT!</b> Press that
36
+ big giant silver spherical DWIM button floating in the sky!
37
+
38
+
39
+ ## High Concept
40
+ A semi-attractive RIA sopping with Web 1.0 gooey-goodness is just a view on your existing
41
+ vanilla documentation that you've surely been writing all along.
42
+
43
+ Nanoc3 makes making web sites fun and easy. Markdown makes documenting your projects fun and easy. Now, NanDoc puts the two together to make making web sites that present your markdown-documented projects tons of fun and super easy.
44
+
45
+ The crackiest part about it is when you start writing unit tests that provide example code for your docs. I really need to document this, both to document it and to showcase it. It's really important for humanity. It's tantamount to learning how to sing with your fingers. Or putting a webcam in your shower, depending on how good you are at writing tests, or how good your shower looks.
46
+
47
+ ## Installation
48
+
49
+ If we are lucky something like this will work:
50
+ from the command line:
51
+ ~~~
52
+ ~ > gem install -n ~/bin nandoc
53
+ ~~~
54
+
55
+ <em>(that <code>-n ~/bin</code> thing is just a matter of preference)</em>
56
+
57
+ <br />
58
+
59
+ To hack, try something like this:
60
+ from the command line:
61
+ ~~~
62
+ ~/tmp > git clone git@github.com:hipe/nandoc.git
63
+ ~/tmp > cd nandoc
64
+ ~/tmp/nandoc > rake gem
65
+ ~/tmp/nandoc > gem install -n ~/bin pkg/nandoc-0.0.0.gem
66
+ ~~~
67
+
68
+
69
+ ## Usage Summary
70
+
71
+ Start with a markdown-formatted README file:
72
+
73
+ (see: test.rb - "basic usage -- readme")
74
+
75
+ <br />
76
+
77
+ Then, next to this readme create a nanoc3 site/project with
78
+ nanDoc&reg;-powered&trade; nanoc&copy;:
79
+
80
+ (see: test.rb - 'basic usage -- create site')
81
+
82
+ <br />
83
+
84
+ Finally, compile your site with the nanoc3 `compile` command:
85
+
86
+ (see: test.rb - 'basic usage -- create site' - 'compile site')
87
+
88
+ <br />
89
+
90
+ From the command line start the nanoc3 (`adsf`) server:
91
+ from the command line:
92
+ ~~~
93
+ ~/tmp/my-site >nandoc view
94
+ ~/tmp/my-site >
95
+ ~~~
96
+
97
+ <br />
98
+
99
+ If all the bells are polished and whistles tuned, you will have a
100
+ site as handsome, usable as self-unawarely-understatedly brilliant as this
101
+ one, but stunningly and proudly your own:
102
+
103
+ (point and aim your browsing device to `http://localhost:3000/`)
104
+
105
+ <div style='border: 1px solid gray; width: 800px; padding: 0 0 1em 0;'>
106
+ (see: test.rb - 'basic usage -- create site' - 'index page body')
107
+ <div class='clear'>&nbsp;</div>
108
+ </div>
109
+
110
+ <br/>
111
+
112
+ This entire readme file/site showcases much of the currently exisiting site generation haxies available in the nanDoc hacks of nanoc3; and the example code and output you see above is generated from the unit tests in this project. [^treebis]
113
+
114
+ Even the above example page is generated by a README in a unit test and injected into this page (which itself is generated from the README of this project.)
115
+
116
+ Customizing your site is a matter of getting to know nanoc3 and discovering all the fantastic undocumented features hiding in nanDoc. (My next steps are to use this fun new tool to actually document how to use it to generate )
117
+
118
+ NanDoc. Genius never looked so stupid&reg;.
119
+
120
+ <br />
121
+ <hr />
122
+ <span style='font-size: 0.85em'>appologies to william morgan's [trollop](http://trollop.rubyforge.org/) site, product, and person for unwittingly encouraging me, and providing the CSS styles for the highlighted ruby code.</span>
123
+
124
+ [^treebis]:checkout the [treebis](http://treebis.hipeland.org) code to see some 'specdoc' features not used here.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require File.expand_path('../lib/nandoc/parse-readme.rb', __FILE__)
2
+
3
+ task :default => :test
4
+
5
+ me = "\e[35mnandoc\e[0m "
6
+
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |s|
9
+ s.authors = ['Chip Malice']
10
+ s.description = NanDoc::ParseReadme.description('README')
11
+ s.email = 'chip.malice@gmail.com'
12
+ s.executables = ['nandoc']
13
+ s.files = FileList['Rakefile', '[A-Z]*(?:\.md)?', '{bin,doc,lib,test,proto}/**/*']
14
+ s.homepage = 'http://nandoc.hipeland.org'
15
+ s.name = 'nandoc'
16
+ s.rubyforge_project = 'nandoc'
17
+ s.summary = NanDoc::ParseReadme.summary('README')
18
+
19
+ s.add_dependency 'nanoc3', '~> 3.1.2'
20
+ s.add_dependency 'treebis', '~> 0.0.1'
21
+ s.add_dependency 'syntax', '~> 1.0.0'
22
+ end
23
+
24
+
25
+ desc "#{me}hack turns the installed gem into a symlink to this directory"
26
+ task :hack do
27
+ kill_path = %x{gem which nandoc}
28
+ kill_path = File.dirname(File.dirname(kill_path))
29
+ new_name = File.dirname(kill_path)+'/ok-to-erase-'+File.basename(kill_path)
30
+ FileUtils.mv(kill_path, new_name, :verbose => 1)
31
+ this_path = File.dirname(__FILE__)
32
+ FileUtils.ln_s(this_path, kill_path, :verbose => 1)
33
+ end
34
+
35
+ desc "#{me}generate rcov coverage"
36
+ task :rcov do
37
+ sh %!rcov --exclude '.*gem.*' test/test.rb -- --seed 0!
38
+ end
39
+
40
+ desc "#{me}run the test file"
41
+ task :test do
42
+ sh %!ruby -w -e 'require "test/test.rb"'!
43
+ end
44
+
45
+ # desc "#{me}remove temporary, generated files like coverage"
46
+ # task :prune do
47
+ # require File.dirname(__FILE__)+'/lib/nandoc.rb'
48
+ # file_utils = NanDoc::Config.file_utils
49
+ # these = ['./lib/nandoc/treebis/coverage']
50
+ # these.each do |this|
51
+ # file_utils.remove_entry_secure(this, :verbose=>true)
52
+ # end
53
+ # end
data/bin/nandoc ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
3
+
4
+ require 'nandoc'
5
+
6
+ Nanoc3::CLI::Base.shared_base.run(ARGV)
data/doc/CREDITS.md ADDED
@@ -0,0 +1,6 @@
1
+ # NanDoc
2
+
3
+ ## Credits
4
+
5
+ * of course Denis Defreyne for [nanoc3](http://nanoc.stoneship.org/)
6
+ * William Morgan ([trollop](http://trollop.rubyforge.org/)), whose no-nonsense site inspired the design of the nanDoc default prototype site (in fact the whole project), and whose mostly unaltered stylesheet is used for the default ruby syntax colorization.
@@ -0,0 +1,20 @@
1
+ # Q: Why not a wiki or a CMS?
2
+ <p class='answer'>A: I don't have any experience running a wiki, and only a little experience hacking on them (a lot if you count radiant cms). With that stated:</p>
3
+
4
+ (I was going to make this a PRO's and CON's list but whether the below points are a pro or a con depends on your specific requirements[^assess].)
5
+
6
+ * wikis are more publicly editable. With the nanDoc, people would have to submit edits to docs patches and/or fork.
7
+
8
+ * some wikis require dedicated server software. NanDoc uses nanoc3 to generate a static site that you can serve with any http server that serves html documents.
9
+
10
+ * a given wiki supports a subset of the large variety of markup languages available [^markups]. Out of the box nandoc uses kramdown (markdown), but in theory can be configured to support any of the filters that nanoc3 can support. Out of the box nanDoc uses markdown because it seems to be a de-facto standard for this kind of thing (at least to the extend that github supports "Github Flavored Markdown"). Out of the box nanDoc uses kramdown to parse markdown because it is clean and hackable, and performance isn't important.
11
+
12
+ * github and the like usually give you a wiki for your project. I don't know to what extent you can get a handle on the content files for this wiki, and have them versioned, etc.
13
+
14
+ * I spent a good amount of time making that auto-generated site-map left nav thing, and the auto-generated top-nav bread-crumber thing (which are optional). In my experience with writing wiki pages this was always an annoyance, dealing with the information architecture of your site. (In most wikis it seems like a page doesn't really exist unless you link to it, and out of the box most wiki's don't seem to present to you a hierarchical tree of nodes, but rather a flat list of documents that can be linked to; or more accurately don't exist until they are linked to.)
15
+
16
+ * More generally the thing about nanDoc is that it can allow you to couple tightly your code and your docs, so for example if someone is watching your project on github they will get notified all the same when either your code or or you docs are updated.
17
+
18
+
19
+ [^assess]: coming soon!
20
+ [^markups]: @todo make a nice comparison matrix of these somewheres.
data/doc/FAQ.md ADDED
@@ -0,0 +1,68 @@
1
+ # Frequently Asked Questions
2
+ <span style='font-size: 0.9em'><em>I can't walk 2 blocks outside my home without some stranger coming up to me and asking me one or more of these questions.</em></span>
3
+
4
+ ## Q: Why not jekyll?
5
+ <p class='answer'>A: I started this knowing nothing about jekyll. nanoc3 found me and i was already acquainted with its author and i liked what i saw so i just ran with it without doing a broad survey of other solutions. At the time of this writing i still don't really know jekyll. @todo</p>
6
+
7
+ ## Q: What about a wiki or a CMS?
8
+ <p class='answer'>A: Yeah that's sorta what this feels like, isn't it. I don't know! What about it? Musings <a href='why-not-wiki/'>here</a>.</p>
9
+
10
+ ## Q: Why do you keep calling nanDoc a hack?
11
+ <p class='answer'>A: nanoc3 although awesome didn't meet the first requirement of nanDoc which was to use as source content a README (and other assets) that live at the root of your project (e.g. gem); as opposed to living in <code>my-site/content</code> folder the way nanoc3 wants it. Nanoc3 wants it this way for good reason, as it turns out, because it takes some work to deal with pulling content from arbitrary folders and files; and to bend Nanoc3 to do this has resulted in a fragile rube-goldberg machine.
12
+ </p>
13
+
14
+ (It bears mentioning that those parts of nanDoc not concerned with the above are not as fragile and quite awesome.)
15
+
16
+ ## Q: Why the hell do you want to do it this way? Why so many hoops?
17
+ <p class='answer'>A: Because I hate hate hate it when my documentation can't keep up with the way my code works, or worse lies about it; and I love love love the idea of generating as much as possible good documentation from good tests.</p>
18
+
19
+ I heard that with BSD/GNU/unix tools you couldn't release an alpha version of the thing without first finishing your manpage [citation needed]. In many responsible shops you can't commit your code unless it's covered by tests and doesn't break the other tests. With nanDoc you can't build your documentation unless your (relevant) tests pass, and it's not easy to build good documentation without them. I like it this way. If you don't, read these nikes!
20
+
21
+ ## Q: But what about rdoc/yard?
22
+ <span class='answer'>A:</span> Rdoc/yard are important tools that do what they do well. [^notyet] NanDoc is certainly not a replacement for them.
23
+
24
+ Rdoc/yard are good at generating API documentation and that's what they should be used for. NanDoc is for creating a narrative story, (indeed a grand metanarrative in the spirit of Lyotard,[^lyotard]) with a beginning middle and end (and hopefully some pretty pictures along the way); and grabbing pieces from your tests to use as examples (illustrations) in the story; or possibly creating taxonomies of such narratives.[^yard]
25
+
26
+ ## Q: What about (python's) doctest?
27
+ <p class='answer'>A: Python's doctest seems nifty and was one of the inspirations for this. However the overriding convention of the day seems to be to let your tests ("specs") live in their own files; and I like it this way so that when I'm looking at code I can read code and not let it get cluttered by natural language explaining (or possibly lying about) what the code <em>should</em> do.</p>
28
+
29
+ Whereas doctest is about writing comments that have embedded code that makes a test that tells a story, nanDoc is about taking your tests that tell a story and injecting parts of them into your (narrative) documentation.
30
+
31
+ Recent-esque trends in some parts (behavior-driven development, user-stories, cucumber et-al) have fed into the inpiration for this; but they don't run all the way to the finish line which is to give an accessible, natural language context to their stories beyond what code is capable of or should be used for.
32
+
33
+ ## Q: Could this idea behind nanDoc somehow be extended further with unit testing frameworks that bend themselves around telling a story?
34
+ <span class='answer'>A:</span> Yes. [^cucumber][^dtdsl]
35
+
36
+
37
+ ## Q: Will NanDoc be useful for generating docs for my Rails app or my Restful API, or my Ruby library?
38
+ <p class='answer'>A: No, as it is I don't really think so. For now it seems to be focused on writing narratives to explain command-line apps. I need to think about this! (hrm oops drats.)
39
+ </p>
40
+
41
+ Wait, come to think of it, yes maybe. If generating a static website from markdown-formatted files that live in arbitrary locations in your project is exactly what you have in mind, then nanDoc is your new best friend.
42
+
43
+
44
+ ## Q: But what about LaTeX?
45
+ <p class='answer'>A: If you know what LaTeX is you should put this book down right now and continue writing your own! (I'm lookin' at you, Ramaze!) (heh or not it has its disadvantages n'est-ce pas?) I like markdown-esque syntax because it's human readable as a plain-text document and it gets "this" job done. But of course it can't do everything. If you were to try and write a nanoc3 filter that reads TeX and outputs html/css/assets then you my friend are hereby being called a black pot by one crazy kettle.</p>
46
+
47
+ This is me trying not to think about generating a pdf from a nanDoc-generated site. (I guess the first question would be, "why?").
48
+
49
+ Also kramdown (that nanDoc uses) apperantly already supports LaTeX [math blocks](http://kramdown.rubyforge.org/syntax.html#math-blocks) which (like the safety cushion in an aiplane that can also be used as a flotation device) I don't ever plan on using but am glad exist.
50
+
51
+ <br />
52
+ <br />
53
+ <br />
54
+ <hr />
55
+ ## Die Fußnoten
56
+
57
+ [^notyet]: At least, I think rdoc and yard are important tools. I haven't really gotten to know them yet at the time of this writing. (I do know yard's author to be sharp, however.)
58
+
59
+ [^yard]: Up next and pretty soon here, i'm going to look into generating sister taxonomies from the api docs generated by yard and having them live next to the web content generated by markdown files. (Nokogiri's and the prettier but now hard to find site for Hpricot are good examples of this.) (Hpricot's now defunct site was a big inspiration for this. Just perfect.)
60
+
61
+
62
+ [^lyotard]: Ok actually he probably would [not](http://en.wikipedia.org/wiki/Metanarrative#Replacing_grand.2C_universal_narratives_with_small.2C_local_narratives) write one, would that poststructuralists wrote software, which is to say that they don['](http://rubyconf2007.confreaks.com/d1t1p1_what_makes_code_beautiful.html)t.
63
+
64
+
65
+ [^cucumber]: The first time I tried using cucumber it annoyed me the way rspec annoys people who are used to vanilla Test::Unit tests. But potential seems to be there (and has been surely been explored to a fuller extend elswhere [citation needed]) to do something like generating docs from these kind of tests.
66
+
67
+
68
+ [^dtdsl]: Or you might be like Dave Thomas (whoever he is) and [hate all DSL's](http://pragdave.blogs.pragprog.com/pragdave/2008/03/the-language-in.html)
@@ -0,0 +1,15 @@
1
+ # Todo's and Bugs
2
+ _(rougly in order of priority)_
3
+
4
+ ## Todo's
5
+ * document DocSpec and MockPrompt!!
6
+ * document the tags in the filter (satisfied partly by below & above)
7
+ * integrate yard api doc generation
8
+ * add explicit dependency on minitest (or not)
9
+ * document diffing commands
10
+
11
+ ## Bugs
12
+ * live [here](http://github.com/hipe/nandoc/issues)
13
+
14
+ ## Wishlist
15
+ * partial compile of only certain pages? ick.
data/doc/bar/baz.md ADDED
@@ -0,0 +1,4 @@
1
+ # what a crazy
2
+
3
+ ## way to
4
+ write your docs
data/doc/bar/bliff.md ADDED
@@ -0,0 +1,8 @@
1
+ # what if
2
+
3
+ ## you wrote
4
+
5
+ all your documenation
6
+ ~~~
7
+ like this
8
+ ~~~~
data/doc/foo.md ADDED
@@ -0,0 +1,5 @@
1
+ i am some secret content
2
+ ### in this
3
+ strange file
4
+
5
+ see bar somehow
@@ -0,0 +1,13 @@
1
+ ### requirements
2
+
3
+ boobric foobric blaz
4
+ ~~~
5
+ some code
6
+ ~~~
7
+
8
+
9
+ blaff bliff bloof
10
+
11
+ #### other stuff
12
+
13
+ that's how you just got started
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
3
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <!-- Generated by hipe version 0.0.0 (20100126.1600)
5
+ -->
6
+ <svg width="175" height="175"
7
+ viewBox="0.00 0.00 175.00 175.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
8
+ <g id="blah1" class="whatevs" transform="scale(1 1) rotate(0) translate(0 0)">
9
+ <title>this_some_awesome_thing</title>
10
+ <polygon fill="white" stroke="white" points="5,140 5,0 140,0 140,140 5,140"/>
11
+ <g id="node1" class="node"><title>song</title>
12
+ <polygon fill="#ff3300" points="19,0 175,0 175,132 169,122 162,132 157,122 148,130 145,119 136,127 133,116 124,124 121,113 112,120 109,109 99,116 98,104 87,109 87,98 76,104 76,92 65,97 65,86 54,91 55,80 43,84 45,73 33,75 38,64 26,64 32,54 21,53 28,44 17,42 25,34 14,32 23,25 12,21 22,16 12,12 21,7 13,3 15,0"/>
13
+
14
+ <g id="blah2" class="whatevs" transform="scale(1) rotate(20) translate(12, -30)">
15
+ <text text-anchor="middle" x="108" y="32" font-family="Super Sans; sans-serif" font-size="25" fill="#ffffff">now with</text>
16
+ <text text-anchor="middle" x="108" y="59" font-family="serif" font-size="25" fill="#ffffff">less fonts!</text>
17
+ </g>
18
+
19
+ </g>
20
+ </g>
21
+ </svg>
@@ -0,0 +1,225 @@
1
+ module NanDoc
2
+ class CreateNanDocSite < ::Nanoc3::CLI::Commands::CreateSite
3
+ #
4
+ # Most of this is fluff/filler/hacks. The key is that 1)
5
+ # in run() we set the datasource to be NanDoc::DataSource and 2)
6
+ # after the parent's site_populate() is run we apply our patch to it.
7
+ #
8
+
9
+
10
+ include OptsNormalizer, TaskCommon, CliCommandHelpers
11
+
12
+ def name; 'create_nandoc_site' end
13
+
14
+ def aliases; [ 'cnds', 'cns', 'cs' ] end # override create_site short!
15
+
16
+ def short_desc; 'create a nandoc site' end
17
+
18
+ def long_desc
19
+ <<-D.gsub(/\n +/,' ')
20
+ (nanDoc hack) Create a new site at the given path. This builds on the
21
+ create_site nanoc3 command. Please see that for more
22
+ information. Run this next to your README.md file.
23
+ D
24
+ end
25
+
26
+ def usage; "nandoc create_nandoc_site [-m] <path>" end
27
+
28
+ def option_definitions
29
+ [
30
+ { :long => 'patch-hack', :short => 'p', :argument => :none,
31
+ :desc => '(nanDoc hack) use files not patches when necessary' },
32
+
33
+ { :long => 'merge-hack', :short => 'm', :argument => :none,
34
+ :desc =>
35
+ '(nanDoc hack) when site already exists do something clever'
36
+ },
37
+ { :long => 'merge-hack-reverse', :short => 'M', :argument => :none,
38
+ :desc =>
39
+ '(nanDoc hack) show the reverse diff of above.'
40
+ }
41
+ ]
42
+ end
43
+
44
+ #
45
+ # On the _merge option: when we are doing a merge with a generated
46
+ # site and we want to generate a fresh site, we want to turn the below
47
+ # stderr hack off.
48
+ #
49
+ def run(opts, args, method_opts={:_merge=>true})
50
+ opts = normalize_opts opts
51
+ run_opts_process opts
52
+ #
53
+ # awful: see if nanoc triggers the error message about site
54
+ # already existing, then take action
55
+ #
56
+ if method_opts[:_merge]
57
+ StdErrListener.new do |listener|
58
+ listener.when(/A site at '.*' already exists/) do
59
+ throw :nandoc_hack, :site_already_exists
60
+ end
61
+ end
62
+ end
63
+ ret = nil
64
+ thing = catch(:nandoc_hack) do
65
+ ret = super(opts, args)
66
+ :normal
67
+ end
68
+ case thing
69
+ when :site_already_exists
70
+ site_already_exists opts, args
71
+ when :normal
72
+ ret
73
+ else
74
+ fail("hack fail: #{thing.inspect}")
75
+ end
76
+ end
77
+
78
+ def run_opts_process opts
79
+ task_abort("you can't have both -M and -m") if
80
+ opts[:merge_hack] && opts[:merge_hack_reverse]
81
+ if opts[:datasource]
82
+ task_abort <<-ABO.gsub(/\n */,"\n").strip
83
+ for now datasource is hardcoded to be nandoc.
84
+ usage: #{usage}
85
+ ABO
86
+ end
87
+ opts[:datasource] = 'nandoc'
88
+ @patch_hack = opts[:patch_hack]
89
+ nil
90
+ end
91
+ private :run_opts_process
92
+
93
+ protected
94
+
95
+ #
96
+ # see SupremeStderrHack
97
+ #
98
+ def initiate_the_supreme_hack_of_the_standard_error_stream
99
+ base = Nanoc3::CLI::Base
100
+ return if base.instance_methods.include?("print_error_orig")
101
+ base.send(:alias_method, :print_error_orig, :print_error)
102
+ base.send(:define_method, :print_error) do |error|
103
+ $stderr = SupremeStderrHack.new($stderr)
104
+ print_error_orig error
105
+ end
106
+ end
107
+
108
+
109
+ def site_already_exists opts, args
110
+ path = args.first
111
+ if ! (opts[:merge_hack] || opts[:merge_hack_reverse])
112
+ task_abort <<-FOO.gsub(/^ +/,'').chop
113
+ A site at '#{path}' already exists.
114
+ If you want to try and merge in changes from the site generator
115
+ (this might just generate a diff), try the --merge-hack (-m) option.
116
+ see `#{invocation_name} help #{name}` for more information
117
+ FOO
118
+ else
119
+ require File.expand_path('../../support/site-merge.rb', __FILE__)
120
+ SiteMerge.new(self).site_merge(opts, args)
121
+ end
122
+ end
123
+
124
+
125
+
126
+ #
127
+ # This is the crux of the whole thing: make the site as the parent
128
+ # does, then apply the patch.
129
+ #
130
+ def site_populate
131
+ initiate_the_supreme_hack_of_the_standard_error_stream
132
+ super
133
+ task = Treebis.dir_task(NanDoc::Root+'/proto/default')
134
+ task.file_utils = Config.file_utils
135
+ task.on(FileUtils.pwd).run(:patch_hack => @patch_hack)
136
+ end
137
+
138
+
139
+ #
140
+ # Somehow legitimize these awful hacks with an entire class
141
+ #
142
+ class StdErrListener
143
+ def initialize &block
144
+ @prev = $stderr
145
+ $stderr = self
146
+ @expired = false
147
+ @whens = []
148
+ block.call(self)
149
+ end
150
+ def when regex, &block
151
+ @whens.push(:regex=>regex, :block=>block)
152
+ end
153
+ def puts *args
154
+ if @expired
155
+ fail("hack failed when trying to write: #{str}")
156
+ elsif args.size != 1
157
+ expire!
158
+ $stderr.puts(*args)
159
+ else
160
+ found = @whens.detect{|x| x[:regex] =~ args.first}
161
+ if found
162
+ expire!
163
+ found[:block].call
164
+ else
165
+ expire!
166
+ $stderr.puts(*args)
167
+ end
168
+ end
169
+ end
170
+ alias_method :write, :puts # supreme & problematic
171
+ private
172
+ def expire!
173
+ $stderr = @prev
174
+ @expired = true
175
+ end
176
+ end
177
+
178
+
179
+ class SupremeStderrHack
180
+ #
181
+ # ridiculous: make a state machine that rewrites part of the error
182
+ # message coming from nanoc, then gets rid of itself when it's done.
183
+ # This is so fragile and stupid but I really needed to get the nanoc
184
+ # message ("please file bug reports") out of the error message so ppl
185
+ # don't misfile bug reports there that are actually NanDoc bugs.
186
+ #
187
+
188
+ def initialize real
189
+ @ui = real
190
+ @state = :looking_for_error_header
191
+ end
192
+ def puts *a
193
+ case @state
194
+ when :looking_for_error_header
195
+ if a.first && a.first.include?('/!\ ERROR /!\\')
196
+ @state = :waiting_for_end_of_error_box
197
+ @ui.puts <<-HERE.gsub(/^ +/,'')
198
+ +--- /!\ ERROR /!\ --------------------------------------------+
199
+ | An exception occured while running nandoc. If you think this |
200
+ | is a bug in nandoc (likely), please report it at |
201
+ | <http://github.com/hipe/nandoc/issues> -- thanks! |
202
+ | (it is very likely a treebis patch failure) |
203
+ +--------------------------------------------------------------+
204
+ HERE
205
+ else
206
+ @ui.puts(*a) # probably just whitespace?
207
+ end
208
+ when :waiting_for_end_of_error_box
209
+ if a.first && a.first =~ /\+-+\+/
210
+ $stderr = @ui
211
+ @state = :hack_failed
212
+ # nothing should be callig our puts() method any more
213
+ end
214
+ when :hack_failed
215
+ fail("hack failed")
216
+ else
217
+ fail("huh?")
218
+ end
219
+ end
220
+ def write *a
221
+ @ui.write(*a)
222
+ end
223
+ end
224
+ end
225
+ end