docdown 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +38 -0
- data/README.md +126 -0
- data/Rakefile +16 -0
- data/bin/docdown +47 -0
- data/docdown.gemspec +28 -0
- data/lib/docdown.rb +37 -0
- data/lib/docdown/code_command.rb +37 -0
- data/lib/docdown/code_commands/bash.rb +23 -0
- data/lib/docdown/code_commands/no_such_command.rb +6 -0
- data/lib/docdown/code_commands/repl.rb +38 -0
- data/lib/docdown/code_commands/write.rb +27 -0
- data/lib/docdown/parser.rb +138 -0
- data/lib/docdown/version.rb +3 -0
- data/test/docdown/parser_test.rb +104 -0
- data/test/docdown/regex_test.rb +200 -0
- data/test/docdown/test_parse_java.rb +8 -0
- data/test/fixtures/README.md +905 -0
- data/test/fixtures/docdown.rb +8 -0
- data/test/fixtures/java_websockets.md +225 -0
- data/test/test_helper.rb +15 -0
- data/tmp.file +0 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c2548137fcc0b4ebb025c13d5178d8d597ba644b
|
4
|
+
data.tar.gz: 1a5911b45cf51cab6d2c0b6f91fa51afe112a275
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6ef2f77c978d5d01d0d4757f79c078b3a67eb2c796188e36aa91e670f83ae610ac63d5068d83d59182f33af4e04b64bf5594a1848bb77e118fe0c61710d77082
|
7
|
+
data.tar.gz: 558c52df2dd318be7a675c6018a41a31fc986eaea8bda4a8111454431e44d56ed02802cc799e166e09437e5ab274249c0a3f272ac68a82671a6cb93788ce1216
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
test/fixtures/project/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
heroku_docdown (0.0.1)
|
5
|
+
repl_runner
|
6
|
+
thor
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activesupport (4.0.0)
|
12
|
+
i18n (~> 0.6, >= 0.6.4)
|
13
|
+
minitest (~> 4.2)
|
14
|
+
multi_json (~> 1.3)
|
15
|
+
thread_safe (~> 0.1)
|
16
|
+
tzinfo (~> 0.3.37)
|
17
|
+
atomic (1.1.14)
|
18
|
+
i18n (0.6.5)
|
19
|
+
metaclass (0.0.1)
|
20
|
+
minitest (4.7.5)
|
21
|
+
mocha (0.14.0)
|
22
|
+
metaclass (~> 0.0.1)
|
23
|
+
multi_json (1.8.0)
|
24
|
+
rake (10.1.0)
|
25
|
+
repl_runner (0.0.2)
|
26
|
+
activesupport
|
27
|
+
thor (0.18.1)
|
28
|
+
thread_safe (0.1.3)
|
29
|
+
atomic
|
30
|
+
tzinfo (0.3.37)
|
31
|
+
|
32
|
+
PLATFORMS
|
33
|
+
ruby
|
34
|
+
|
35
|
+
DEPENDENCIES
|
36
|
+
heroku_docdown!
|
37
|
+
mocha
|
38
|
+
rake
|
data/README.md
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
## Docdown
|
2
|
+
|
3
|
+
## What
|
4
|
+
|
5
|
+
Write your code/docs once, don't repeat yourself. Changes/updates to docs are guaranteed to match your project
|
6
|
+
|
7
|
+
## Why
|
8
|
+
|
9
|
+
I wrote a Rails course, that required I build an app and write
|
10
|
+
documentation for building said app. Wouldn't it be cool if instead
|
11
|
+
while I write the documentation I could automate the building of my
|
12
|
+
app?
|
13
|
+
|
14
|
+
Totally! That's this, this is that thing.
|
15
|
+
|
16
|
+
Write docs that build software.
|
17
|
+
|
18
|
+
Why docs to code and not code to docs? Code is hard, cold and machine runnable. Docs are soft, consumed by people, and need high flexability. It's easier to explicitly tell the machine what code you want generated, then to go the other way.
|
19
|
+
|
20
|
+
## Install
|
21
|
+
|
22
|
+
For now this software is distributed as a rubygem. Install it manually:
|
23
|
+
|
24
|
+
```
|
25
|
+
$ gem install docdown
|
26
|
+
```
|
27
|
+
|
28
|
+
or add it to your Gemfile:
|
29
|
+
|
30
|
+
```
|
31
|
+
gem 'docdown`
|
32
|
+
```
|
33
|
+
|
34
|
+
## Use It
|
35
|
+
|
36
|
+
Run the docdown command on any makdown file
|
37
|
+
|
38
|
+
```sh
|
39
|
+
$ docdown build my_file.md
|
40
|
+
```
|
41
|
+
|
42
|
+
This will generate a project folder with your project in it, and a markdown README.md with the parsed output of the markdown docs.
|
43
|
+
|
44
|
+
## Write it
|
45
|
+
|
46
|
+
Docdown uses github flavored markdown and the html-pipeline behind
|
47
|
+
the scenes. This means you write like normal but in your code sections
|
48
|
+
you can add special annotations that when run through docdown can
|
49
|
+
generate a project.
|
50
|
+
|
51
|
+
All docdown commands are prefixed with three colons `:::` and are inclosed in a code block a
|
52
|
+
command such as `$` which is an alias for `bash` commands like this:
|
53
|
+
|
54
|
+
```
|
55
|
+
::: $ git init .
|
56
|
+
```
|
57
|
+
|
58
|
+
Nothing before the three colons matters. The space between the colons
|
59
|
+
and the command is optional.
|
60
|
+
|
61
|
+
If you don't want the command to output to your markdown document you
|
62
|
+
can add a minus symbol `-` to the end to prevent it from being
|
63
|
+
rendered.
|
64
|
+
|
65
|
+
```
|
66
|
+
:::- $ git init .
|
67
|
+
```
|
68
|
+
|
69
|
+
If you want the output of the actual command to be rendered to
|
70
|
+
the screen you can use an equal sign so that
|
71
|
+
|
72
|
+
```
|
73
|
+
:::= $ ls
|
74
|
+
```
|
75
|
+
|
76
|
+
Might generate an output something like this to your markdown doc:
|
77
|
+
|
78
|
+
```
|
79
|
+
$ ls
|
80
|
+
Gemfile README.rdoc app config.ru doc log script tmp
|
81
|
+
Gemfile.lock Rakefile config db lib public test vendor
|
82
|
+
```
|
83
|
+
|
84
|
+
That's how you manipulate the shell with docdown, let's take a look at manipulating code.
|
85
|
+
|
86
|
+
|
87
|
+
## Files
|
88
|
+
|
89
|
+
Right now you can only write to files. Use the `write` keyword followed by a filename, on the next line(s) put the contents of the file
|
90
|
+
|
91
|
+
```
|
92
|
+
::: write config/routes.rb
|
93
|
+
|
94
|
+
Example::Application.routes.draw do
|
95
|
+
root :to => "pages#index"
|
96
|
+
|
97
|
+
namespace :users do
|
98
|
+
resources :after_signup
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
If you wanted to change `users` to `products` you would write to the same file again.
|
104
|
+
|
105
|
+
```
|
106
|
+
::: write config/routes.rb
|
107
|
+
Example::Application.routes.draw do
|
108
|
+
root :to => "pages#index"
|
109
|
+
|
110
|
+
namespace :products do
|
111
|
+
resources :after_signup
|
112
|
+
end
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
To delete files use bash `$` command.
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
## TODO
|
121
|
+
|
122
|
+
- Debug output
|
123
|
+
- Fail and exit on non zero exit code
|
124
|
+
- Breakpoints?
|
125
|
+
- Bash commands with side effects (cd; pwd; on different lines should actually change working directory)
|
126
|
+
- Better line matching for backtrace
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
require 'docdown'
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'rake/testtask'
|
8
|
+
|
9
|
+
task :default => [:test]
|
10
|
+
|
11
|
+
test_task = Rake::TestTask.new(:test) do |t|
|
12
|
+
t.libs << 'lib'
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = false
|
16
|
+
end
|
data/bin/docdown
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
unless File.respond_to? :realpath
|
4
|
+
class File #:nodoc:
|
5
|
+
def self.realpath path
|
6
|
+
return realpath(File.readlink(path)) if symlink?(path)
|
7
|
+
path
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
$: << File.expand_path(File.dirname(File.realpath(__FILE__)) + '/../lib')
|
12
|
+
|
13
|
+
require 'docdown'
|
14
|
+
require 'thor'
|
15
|
+
|
16
|
+
class DocdownCLI < Thor
|
17
|
+
|
18
|
+
def initialize(*args)
|
19
|
+
super
|
20
|
+
@config = options[:config]
|
21
|
+
@path = options[:path]
|
22
|
+
load("./#{@config}") if @config && File.exist?(@config)
|
23
|
+
end
|
24
|
+
|
25
|
+
default_task :help
|
26
|
+
|
27
|
+
desc "build", "turns docdown file into docs and a project"
|
28
|
+
class_option :path, banner: "path/to/file.md", optional: true, default: 'docdown.md'
|
29
|
+
class_option :config, banner: "path/to/docdown_config.rb", default: 'docdown.rb'
|
30
|
+
def build
|
31
|
+
|
32
|
+
raise "#{@path} does not exist" unless File.exist?(@path)
|
33
|
+
contents = File.read(@path)
|
34
|
+
dir = File.expand_path("../project", @path)
|
35
|
+
|
36
|
+
FileUtils.remove_entry_secure(dir) if Dir.exist?(dir)
|
37
|
+
FileUtils.mkdir_p(dir)
|
38
|
+
|
39
|
+
Dir.chdir(dir) do
|
40
|
+
@output = Docdown::Parser.new(contents).to_md
|
41
|
+
end
|
42
|
+
File.open("README.md", "w") {|f| f.write @output }
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
DocdownCLI.start(ARGV)
|
data/docdown.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'docdown/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "docdown"
|
8
|
+
gem.version = Docdown::VERSION
|
9
|
+
gem.authors = ["Richard Schneeman"]
|
10
|
+
gem.email = ["richard.schneeman+rubygems@gmail.com"]
|
11
|
+
gem.description = %q{docdown turns docs to runable code}
|
12
|
+
gem.summary = %q{docdown generates runable code from docs}
|
13
|
+
gem.homepage = "https://github.com/schneems/docdown"
|
14
|
+
gem.license = "MIT"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
|
22
|
+
gem.add_dependency "thor"
|
23
|
+
gem.add_dependency "repl_runner"
|
24
|
+
|
25
|
+
gem.add_development_dependency "rake"
|
26
|
+
gem.add_development_dependency "mocha"
|
27
|
+
end
|
28
|
+
|
data/lib/docdown.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require 'docdown/version'
|
4
|
+
|
5
|
+
module Docdown
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def code_command_from_keyword(keyword, *args)
|
9
|
+
klass = code_command(keyword.to_sym)
|
10
|
+
cc = klass.new(*args)
|
11
|
+
cc.keyword = keyword
|
12
|
+
cc
|
13
|
+
end
|
14
|
+
|
15
|
+
def code_lookup
|
16
|
+
@code_lookup ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def code_command(keyword)
|
20
|
+
code_lookup[:"#{keyword}"] || Docdown::CodeCommands::NoSuchCommand
|
21
|
+
end
|
22
|
+
|
23
|
+
def known_commands
|
24
|
+
code_lookup.keys
|
25
|
+
end
|
26
|
+
|
27
|
+
def register_code_command(keyword, klass)
|
28
|
+
code_lookup[keyword] = klass
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure(&block)
|
32
|
+
yield self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'docdown/parser'
|
37
|
+
require 'docdown/code_command'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Docdown
|
2
|
+
class CodeCommand
|
3
|
+
attr_accessor :hidden, :render_result, :command, :contents, :keyword
|
4
|
+
|
5
|
+
alias :hidden? :hidden
|
6
|
+
alias :render_result? :render_result
|
7
|
+
|
8
|
+
def initialize(arg)
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
# returns the markedup command
|
13
|
+
# do not over-write unless you call super
|
14
|
+
def render
|
15
|
+
result = self.call
|
16
|
+
return [to_md, result].join("\n") if render_result?
|
17
|
+
return "" if hidden?
|
18
|
+
to_md
|
19
|
+
end
|
20
|
+
|
21
|
+
def push(contents)
|
22
|
+
@contents ||= ""
|
23
|
+
@contents << contents
|
24
|
+
end
|
25
|
+
alias :<< :push
|
26
|
+
|
27
|
+
# executes command to build project
|
28
|
+
def call
|
29
|
+
raise "not implemented"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'docdown/code_commands/bash'
|
35
|
+
require 'docdown/code_commands/write'
|
36
|
+
require 'docdown/code_commands/repl'
|
37
|
+
require 'docdown/code_commands/no_such_command'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Docdown
|
2
|
+
module CodeCommands
|
3
|
+
class Bash < Docdown::CodeCommand
|
4
|
+
def initialize(command)
|
5
|
+
@command = command
|
6
|
+
@contents = ""
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
puts "Executing: #{to_md.inspect}"
|
11
|
+
`#{@command} #{contents} 2>&1`
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_md
|
15
|
+
"$ #{@command} #{contents}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
Docdown.register_code_command(:bash, Docdown::CodeCommands::Bash)
|
23
|
+
Docdown.register_code_command(:'$', Docdown::CodeCommands::Bash)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'repl_runner'
|
2
|
+
|
3
|
+
module Docdown
|
4
|
+
module CodeCommands
|
5
|
+
class Repl < Docdown::CodeCommand
|
6
|
+
def initialize(command)
|
7
|
+
@command = command
|
8
|
+
@contents = ""
|
9
|
+
end
|
10
|
+
|
11
|
+
def keyword=(keyword)
|
12
|
+
@keyword = keyword
|
13
|
+
puts keyword
|
14
|
+
if keyword.to_s == "repl"
|
15
|
+
command_array = @command.split(" ")
|
16
|
+
puts command_array.inspect
|
17
|
+
@keyword = command_array.first
|
18
|
+
else
|
19
|
+
@command = "#{keyword} #{@command}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def call
|
24
|
+
puts @contents.inspect
|
25
|
+
zip = ReplRunner.new(:"#{keyword}", @command).zip(contents.strip)
|
26
|
+
@result = zip.flatten.join("\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_md
|
30
|
+
"$ #{@command}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
Docdown.register_code_command(:repl, Docdown::CodeCommands::Repl)
|
38
|
+
Docdown.register_code_command(:irb, Docdown::CodeCommands::Repl)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Docdown
|
2
|
+
module CodeCommands
|
3
|
+
class Write < Docdown::CodeCommand
|
4
|
+
def initialize(filename)
|
5
|
+
@filename = filename
|
6
|
+
@dir = File.expand_path("../", @filename)
|
7
|
+
end
|
8
|
+
|
9
|
+
# todo diff file if it already exists
|
10
|
+
def to_md
|
11
|
+
"In file `#{@filename}` add:\n#{contents}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
puts "writing to : #{@filename}"
|
16
|
+
FileUtils.mkdir_p(@dir)
|
17
|
+
File.open(@filename, "w") do |f|
|
18
|
+
f.write(contents)
|
19
|
+
end
|
20
|
+
contents
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
Docdown.register_code_command(:write, Docdown::CodeCommands::Write)
|