diff --git a/assets/javascripts/vendor/prism-invoke.js b/assets/javascripts/vendor/prism-invoke.js
new file mode 100644
index 00000000..9b48f616
--- /dev/null
+++ b/assets/javascripts/vendor/prism-invoke.js
@@ -0,0 +1,42 @@
+var HL = {
+ 'javascript': [
+ '._coffeescript pre:last-child',
+ '._angular .prettyprint',
+ '._d3 .highlight > pre',
+ '._underscore pre',
+ '._node pre > code',
+ '._jquery .syntaxhighlighter .javascript',
+ '._ember pre .javascript',
+ ['._knockout pre', 'data-bind="', false],
+ '._mdn pre[class*="js"]'
+ ],
+
+ 'c': [ '._ruby pre.c' ],
+ 'ruby': [ '._ruby pre.ruby' ],
+ 'coffeescript': [ '._coffeescript .code > pre:first-child' ],
+ 'python': [ '._sphinx pre.python' ],
+
+ 'markup': [
+ ['._knockout pre', 'data-bind="', true],
+ '._ember pre.html',
+ '._mdn pre[class*="html"]'
+ ]
+};
+
+function highlightAll(sels, language){
+ for(var i = 0; i < sels.length; ++i){
+ var sel = sels[i] instanceof Array ? sels[i] : [sels[i]];
+ var nodes = document.querySelectorAll(sel[0]);
+
+ for(var j = 0, c = nodes.length; j < c; ++j){
+ if(!sel[1] || nodes[j].innerHTML.indexOf(sel[i][1]) != -1 == sel[2]){
+ nodes[j].classList.add('language-' + language)
+ Prism.highlightElement(nodes[j]);
+ }
+ }
+ }
+}
+
+for(var lang in HL)
+ if(HL.hasOwnProperty(lang))
+ highlightAll(HL[lang], lang);
diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss
index de05a2e0..17b70f4f 100644
--- a/assets/stylesheets/application.css.scss
+++ b/assets/stylesheets/application.css.scss
@@ -14,7 +14,8 @@
@import 'global/variables',
'global/icons',
'global/classes',
- 'global/base';
+ 'global/base',
+ 'global/devhelp';
@import 'components/app',
'components/header',
diff --git a/assets/stylesheets/global/_devhelp.scss b/assets/stylesheets/global/_devhelp.scss
new file mode 100644
index 00000000..09f44ef5
--- /dev/null
+++ b/assets/stylesheets/global/_devhelp.scss
@@ -0,0 +1,22 @@
+._devhelp {
+ width: 90%;
+ height: auto !important;
+ margin: 0 auto !important;
+
+ border: none !important;
+ box-shadow: none !important;
+
+ font-family: Arial, sans-serif;
+
+ pre, code, samp, ._redis > .example {
+ font-family: "Lucida Console", "Sans Mono", "Courier New", monospace;
+ font-size: 1.05em;
+ }
+
+ ._content {
+ height: auto !important;
+ margin-left: 0px !important;
+ overflow-y: visible !important;
+ font-size: 1.1em;
+ }
+}
diff --git a/lib/devhelp.rb b/lib/devhelp.rb
new file mode 100644
index 00000000..5d43f92e
--- /dev/null
+++ b/lib/devhelp.rb
@@ -0,0 +1,218 @@
+require 'find'
+require 'fileutils'
+require 'nokogiri'
+require 'json'
+require 'downloader'
+
+class DevHelp
+ SKIP_ASSETS = %{.json .js .gz}
+ DEVHELP_NS = 'http://www.devhelp.net/book'
+
+ def initialize(options)
+ @options = options
+ end
+
+ def book_options(doc)
+ {
+ xmlns: DEVHELP_NS,
+ title: doc.name,
+ name: "#{doc.slug}-#{doc.version}",
+ version: 2,
+ author: '',
+ language: doc.language,
+ link: 'index.html'
+ }
+ end
+
+ def normalize_url(link)
+ link.gsub(/^([^.]+?)(?=$|#)/, '\1.html\2')
+ end
+
+ def build_devhelp(doc, structure)
+ builder do |xml|
+ xml.book book_options(doc) do
+ xml.doc.create_internal_subset('book', '-//W3C//DTD HTML 4.01 Transitional//EN', '')
+ xml.chapters do
+ structure[:terms].each do |term, link|
+ xml.sub name: term, link: normalize_url(link)
+ end
+ end
+ end
+ end.to_xml
+ end
+
+ def for_docs(*docs)
+ docs.flatten.each(&method(:for_doc))
+ end
+
+ def cp_r(src, dst)
+ t = File.dirname(dst)
+ FileUtils.mkdir_p(t) unless File.directory?(t)
+ FileUtils.cp_r(src, dst)
+ end
+
+ def prepare_assets(src, dst)
+ cp_r(src, dst)
+ Find.find(dst).select do |file|
+ ext = File.extname(file).downcase
+ File.unlink(file) if File.file?(file) && SKIP_ASSETS.include?(ext)
+ ext == '.css'
+ end
+ end
+
+ def prepare_js(js, dst)
+ js.map do |file|
+ npath = File.join(dst, File.basename(file))
+ FileUtils.cp(file, npath)
+ npath
+ end
+ end
+
+ def make_devhelp_file(doc, src, dst, unlink = false)
+ structure = parse_index(src)
+ File.write(dst, build_devhelp(doc, structure))
+ File.unlink(src)
+ structure
+ end
+
+ def downloader
+ @downloader ||= Downloader.new
+ end
+
+ def document_structure(doc, type)
+ doc.internal_subset.remove
+ doc.create_internal_subset('html', nil, nil)
+
+ unless doc.at_css('head')
+ title = Nokogiri::XML::Node.new 'head', doc
+ doc.root.children.first.add_previous_sibling title
+ end
+
+ body = doc.at_css('body')
+ content = body.children.remove
+
+ body.add_child <<-EOF
+
+ EOF
+ end
+
+ def set_title(doc, text = nil)
+ unless text
+ h1 = doc.at_css('h1, h2, h3, h4, h5')
+ return unless h1
+ text = h1.text.strip
+ end
+
+ title = doc.at_css('title')
+ unless title
+ title = Nokogiri::XML::Node.new 'title', doc
+ doc.at_css('head').add_child(title)
+ end
+
+ title.content = text
+ end
+
+ def inject_assets(doc, path, css, js, skip)
+ head = doc.at_css('head')
+ level = ['..'] * path[skip].count(File::SEPARATOR)
+
+ css.each do |asset|
+ link = Nokogiri::XML::Node.new 'link', doc
+ link['rel'] = 'stylesheet'
+ link['media'] = 'all'
+ link['charset'] = 'UTF-8'
+ link['href'] = File.join(level + [asset[skip]])
+ head.add_child(link)
+ end
+
+ body = doc.at_css('body')
+ js.each do |asset|
+ script = Nokogiri::XML::Node.new 'script', doc
+ script['type'] = 'text/javascript'
+ script['charset'] = 'UTF-8'
+ script['src'] = File.join(level + [asset[skip]])
+ body.add_child(script)
+ end
+ end
+
+ def src_for(doc)
+ src_path = File.join(@options[:base_path], doc.path)
+
+ unless File.exists?(src_path)
+ puts %(ERROR: can't find "#{doc.name}" documentation files. Please download/scrape it first.)
+ return nil
+ end
+
+ src_path
+ end
+
+ def dst_for(doc)
+ dst_path = File.join(@options[:devhelp_path], doc.path)
+
+ if File.exists?(dst_path)
+ unless @options[:force]
+ puts %(ERROR: #{doc.name} was already converted. Use --force to overwrite.)
+ return nil
+ end
+
+ FileUtils.rm_rf(dst_path)
+ end
+
+ dst_path
+ end
+
+ def for_doc(doc)
+ src_path = src_for(doc) || return
+ dst_path = dst_for(doc) || return
+
+ cp_r(src_path, dst_path)
+
+ css = prepare_assets(@options[:asset_path], File.join(dst_path, 'assets'))
+ js = prepare_js(@options[:js], File.join(dst_path, 'assets'))
+
+ titles = make_devhelp_file(doc,
+ File.join(dst_path, @options[:index]),
+ File.join(dst_path, "#{doc.slug}.devhelp2"),
+ true)
+
+ skip = (dst_path.length + 1) .. -1
+
+ downloader.processor do |file, parser|
+ document_structure(parser, doc.type)
+ set_title(parser, titles[:files][file[skip]])
+ inject_assets(parser, file, css, js, skip)
+ end
+
+ Find.find(dst_path).
+ select(&method(:is_document?)).
+ each {|d| downloader.process_page(nil, d)}
+
+ downloader.run
+ end
+
+ def is_document?(p)
+ !File.basename(p).starts_with?('.') && p.ends_with?('.html') && File.file?(p)
+ end
+
+ def builder(&block)
+ Nokogiri::XML::Builder.new(encoding: 'UTF-8', &block)
+ end
+
+ def parse_index(path)
+ structure = {terms: {}, files: {}}
+
+ JSON.load(open(path))['entries'].each do |e, o|
+ structure[:terms][e['name']] = e['path']
+
+ unless e['path'].include?('#')
+ structure[:files][e['path']] = e['name']
+ end
+ end
+
+ structure
+ end
+end
diff --git a/lib/docs.rb b/lib/docs.rb
index d6aaa20c..d27de263 100644
--- a/lib/docs.rb
+++ b/lib/docs.rb
@@ -24,6 +24,9 @@ module Docs
mattr_accessor :store_path
self.store_path = File.expand_path '../public/docs', @@root_path
+ mattr_accessor :devhelp_store_path
+ self.devhelp_store_path = File.expand_path '../public/devhelp', @@root_path
+
class DocNotFound < NameError; end
def self.all
diff --git a/lib/docs/core/doc.rb b/lib/docs/core/doc.rb
index e4177e4b..ed4775cb 100644
--- a/lib/docs/core/doc.rb
+++ b/lib/docs/core/doc.rb
@@ -3,7 +3,7 @@ module Docs
INDEX_FILENAME = 'index.json'
class << self
- attr_accessor :name, :slug, :type, :version, :abstract
+ attr_accessor :name, :slug, :type, :version, :abstract, :language
def inherited(subclass)
subclass.type = type
diff --git a/lib/docs/core/subscriber.rb b/lib/docs/core/subscriber.rb
index 5c21acb5..1f0e6d3c 100644
--- a/lib/docs/core/subscriber.rb
+++ b/lib/docs/core/subscriber.rb
@@ -44,7 +44,7 @@ module Docs
elsif ENV['COLUMNS']
ENV['COLUMNS'].to_i
else
- `stty size`.scan(/\d+/).last.to_i
+ `tput cols`.scan(/\d+/).last.to_i
end
rescue
@terminal_width = nil
diff --git a/lib/docs/scrapers/angular.rb b/lib/docs/scrapers/angular.rb
index f20a588a..6e15e49d 100644
--- a/lib/docs/scrapers/angular.rb
+++ b/lib/docs/scrapers/angular.rb
@@ -15,5 +15,6 @@ module Docs
self.type = 'angular'
self.version = '1.0.7'
self.base_url = ''
+ self.language = 'javascript'
end
end
diff --git a/lib/docs/scrapers/backbone.rb b/lib/docs/scrapers/backbone.rb
index b5fb3e53..04ff7e7f 100644
--- a/lib/docs/scrapers/backbone.rb
+++ b/lib/docs/scrapers/backbone.rb
@@ -5,6 +5,7 @@ module Docs
self.type = 'underscore'
self.version = '1.1.0'
self.base_url = 'http://backbonejs.org'
+ self.language = 'javascript'
html_filters.push 'backbone/clean_html', 'backbone/entries', 'title'
diff --git a/lib/docs/scrapers/coffeescript.rb b/lib/docs/scrapers/coffeescript.rb
index ecd45040..86538c94 100644
--- a/lib/docs/scrapers/coffeescript.rb
+++ b/lib/docs/scrapers/coffeescript.rb
@@ -4,6 +4,7 @@ module Docs
self.type = 'coffeescript'
self.version = '1.6.3'
self.base_url = 'http://coffeescript.org'
+ self.language = 'coffeescript'
html_filters.push 'coffeescript/clean_html', 'coffeescript/entries', 'title'
diff --git a/lib/docs/scrapers/d3.rb b/lib/docs/scrapers/d3.rb
index 81e6758e..f6e1b6da 100644
--- a/lib/docs/scrapers/d3.rb
+++ b/lib/docs/scrapers/d3.rb
@@ -6,6 +6,7 @@ module Docs
self.version = '3.4.1'
self.base_url = 'https://github.com/mbostock/d3/wiki/'
self.root_path = 'API-Reference'
+ self.language = 'javascript'
html_filters.push 'd3/clean_html', 'd3/entries'
diff --git a/lib/docs/scrapers/ember.rb b/lib/docs/scrapers/ember.rb
index becd2c29..75abbea3 100644
--- a/lib/docs/scrapers/ember.rb
+++ b/lib/docs/scrapers/ember.rb
@@ -5,6 +5,7 @@ module Docs
self.type = 'ember'
self.version = '1.3.0'
self.base_url = 'http://emberjs.com/api/'
+ self.language = 'javascript'
html_filters.push 'ember/clean_html', 'ember/entries', 'title'
diff --git a/lib/docs/scrapers/git.rb b/lib/docs/scrapers/git.rb
index eb0796c1..4392e601 100644
--- a/lib/docs/scrapers/git.rb
+++ b/lib/docs/scrapers/git.rb
@@ -4,6 +4,7 @@ module Docs
self.version = '1.8.5'
self.base_url = 'http://git-scm.com/docs'
self.initial_paths = %w(/git.html)
+ self.language = 'git'
html_filters.push 'git/clean_html', 'git/entries'
diff --git a/lib/docs/scrapers/http.rb b/lib/docs/scrapers/http.rb
index 2f517c75..91fec1e6 100644
--- a/lib/docs/scrapers/http.rb
+++ b/lib/docs/scrapers/http.rb
@@ -4,6 +4,7 @@ module Docs
self.type = 'rfc'
self.base_url = 'http://www.w3.org/Protocols/rfc2616/'
self.root_path = 'rfc2616.html'
+ self.language = 'http'
html_filters.push 'http/clean_html', 'http/entries'
diff --git a/lib/docs/scrapers/knockout.rb b/lib/docs/scrapers/knockout.rb
index 941927aa..d672fdac 100644
--- a/lib/docs/scrapers/knockout.rb
+++ b/lib/docs/scrapers/knockout.rb
@@ -6,6 +6,7 @@ module Docs
self.version = '3.0.0'
self.base_url = 'http://knockoutjs.com/documentation/'
self.root_path = 'introduction.html'
+ self.language = 'javascript'
html_filters.push 'knockout/clean_html', 'knockout/entries'
diff --git a/lib/docs/scrapers/less.rb b/lib/docs/scrapers/less.rb
index 310b8ea9..df614b63 100644
--- a/lib/docs/scrapers/less.rb
+++ b/lib/docs/scrapers/less.rb
@@ -3,6 +3,7 @@ module Docs
self.type = 'less'
self.version = '1.6.0'
self.base_url = 'http://lesscss.org'
+ self.language = 'less'
html_filters.push 'less/clean_html', 'less/entries', 'title'
diff --git a/lib/docs/scrapers/lodash.rb b/lib/docs/scrapers/lodash.rb
index 4cb9d52b..231611fb 100644
--- a/lib/docs/scrapers/lodash.rb
+++ b/lib/docs/scrapers/lodash.rb
@@ -5,6 +5,7 @@ module Docs
self.type = 'lodash'
self.version = '2.4.1'
self.base_url = 'http://lodash.com/docs'
+ self.language = 'javascript'
html_filters.push 'lodash/clean_html', 'lodash/entries', 'title'
diff --git a/lib/docs/scrapers/node.rb b/lib/docs/scrapers/node.rb
index afd780af..eb87ee39 100644
--- a/lib/docs/scrapers/node.rb
+++ b/lib/docs/scrapers/node.rb
@@ -5,6 +5,7 @@ module Docs
self.type = 'node'
self.version = '0.10.24'
self.base_url = 'http://nodejs.org/api/'
+ self.language = 'javascript'
html_filters.push 'node/clean_html', 'node/entries', 'title'
diff --git a/lib/docs/scrapers/php.rb b/lib/docs/scrapers/php.rb
index ae2f0bb4..a99c2739 100644
--- a/lib/docs/scrapers/php.rb
+++ b/lib/docs/scrapers/php.rb
@@ -16,6 +16,7 @@ module Docs
# Downloaded from php.net/download-docs.php
self.dir = '/Users/Thibaut/DevDocs/Docs/PHP'
+ self.language = 'php'
html_filters.push 'php/internal_urls', 'php/entries', 'php/clean_html', 'title'
text_filters.push 'php/fix_urls'
diff --git a/lib/docs/scrapers/postgresql.rb b/lib/docs/scrapers/postgresql.rb
index 909036fd..dda1aa61 100644
--- a/lib/docs/scrapers/postgresql.rb
+++ b/lib/docs/scrapers/postgresql.rb
@@ -7,6 +7,7 @@ module Docs
self.base_url = 'http://www.postgresql.org/docs/9.3/static/'
self.root_path = 'reference.html'
self.initial_paths = %w(sql.html runtime-config.html charset.html)
+ self.language = 'postgresql'
html_filters.insert_before 'normalize_urls', 'postgresql/clean_nav'
html_filters.push 'postgresql/clean_html', 'postgresql/entries', 'title'
diff --git a/lib/docs/scrapers/python.rb b/lib/docs/scrapers/python.rb
index c1cd7f97..05b50c5a 100644
--- a/lib/docs/scrapers/python.rb
+++ b/lib/docs/scrapers/python.rb
@@ -5,6 +5,7 @@ module Docs
self.dir = '/Users/Thibaut/DevDocs/Docs/Python' # downloaded from docs.python.org/3/download.html
self.base_url = 'http://docs.python.org/3/'
self.root_path = 'library/index.html'
+ self.language = 'python'
html_filters.push 'python/entries', 'python/clean_html'
diff --git a/lib/docs/scrapers/redis.rb b/lib/docs/scrapers/redis.rb
index 026a071a..0406149c 100644
--- a/lib/docs/scrapers/redis.rb
+++ b/lib/docs/scrapers/redis.rb
@@ -3,6 +3,7 @@ module Docs
self.type = 'redis'
self.version = 'up to 2.8.4'
self.base_url = 'http://redis.io/commands'
+ self.language = 'redis'
html_filters.push 'redis/entries', 'redis/clean_html', 'title'
diff --git a/lib/docs/scrapers/sass.rb b/lib/docs/scrapers/sass.rb
index d60f5b04..4f0178dd 100644
--- a/lib/docs/scrapers/sass.rb
+++ b/lib/docs/scrapers/sass.rb
@@ -4,6 +4,7 @@ module Docs
self.version = '3.2.12'
self.base_url = 'http://sass-lang.com/docs/yardoc/'
self.root_path = 'file.SASS_REFERENCE.html'
+ self.language = 'sass'
html_filters.push 'sass/clean_html', 'sass/entries', 'title'
diff --git a/lib/docs/scrapers/underscore.rb b/lib/docs/scrapers/underscore.rb
index 9728e117..20fcc8d8 100644
--- a/lib/docs/scrapers/underscore.rb
+++ b/lib/docs/scrapers/underscore.rb
@@ -5,6 +5,7 @@ module Docs
self.type = 'underscore'
self.version = '1.5.2'
self.base_url = 'http://underscorejs.org'
+ self.language = 'javascript'
html_filters.push 'underscore/clean_html', 'underscore/entries', 'title'
diff --git a/lib/downloader.rb b/lib/downloader.rb
new file mode 100644
index 00000000..ee11c294
--- /dev/null
+++ b/lib/downloader.rb
@@ -0,0 +1,161 @@
+require 'typhoeus'
+require 'nokogiri'
+require 'delegate'
+require 'fileutils'
+require 'cgi'
+
+class Downloader < SimpleDelegator
+ include Typhoeus
+
+ MAX_QUEUE_SIZE = 20
+
+ def initialize(*args)
+ super(Hydra.new(*args))
+ end
+
+ def processor(&block)
+ @processor = block
+ end
+
+ def queue_size
+ queued_requests.size
+ end
+
+ def file(src, dst, &block)
+ file = nil
+
+ request = Request.new(src)
+
+ request.on_headers do |response|
+ if response.response_code == 200
+ dname = File.dirname(dst)
+ FileUtils.mkdir_p(dname) unless File.directory?(dname)
+ file = open(dst, 'wb')
+ else
+ failed(src, dst, response)
+ end
+ end
+
+ request.on_body do |chunk|
+ file.write(chunk) if file
+ end
+
+ request.on_complete do |response|
+ if file
+ file.close
+ block.call(dst) if block
+ end
+ end
+
+ queue request
+ dst
+ end
+
+ def queue(*args, &block)
+ run while queue_size > MAX_QUEUE_SIZE
+ __getobj__(*args, &block)
+ end
+
+ def page(src, target)
+ file(src, target) { process_page(src, target) }
+ end
+
+ def process_page(src, path)
+ doc = Nokogiri::HTML.parse(File.read(path), 'UTF-8')
+ rdir = path.gsub(%r{\.[^./]*$}, '') + '_files'
+ skip = dirname_range(path)
+
+ doc.css('iframe[src], img[src], script[src], link[href][rel="stylesheet"], link[href][rel="shortcut icon"]').each do |elem|
+ uri = url_join(src, elem['src'] || elem['href'])
+
+ case elem.name
+ when 'iframe'
+ elem['src'] = page(uri, resource_path_for(rdir, uri, 'html'))[skip]
+ when 'link'
+ elem['href'] = file(uri, resource_path_for(rdir, uri, 'css')) do |f|
+ process_stylesheet_file(uri, f) if elem['rel'] == 'stylesheet'
+ end[skip]
+ when 'script'
+ elem['src'] = file(uri, resource_path_for(rdir, uri, 'js'))[skip]
+ when 'img'
+ elem['src'] = file(uri, resource_path_for(rdir, uri, 'png'))[skip]
+ end
+ end
+
+ doc.css('style').each do |style|
+ style.content = process_stylesheet(src, style.content, rdir)
+ end
+
+ @processor.call(path, doc) if @processor
+
+ File.write(path, doc.to_html)
+ end
+
+ protected
+
+ def dirname_range(path, dirname = false)
+ path = File.dirname(path) unless dirname
+ l = path.length
+ l += 1 if l > 0
+ l..-1
+ end
+
+ def process_stylesheet_file(src, fname)
+ File.write(fname, process_stylesheet(src, File.read(fname), File.dirname(fname)))
+ end
+
+ def process_stylesheet(src, style, dir)
+ skip = dirname_range(dir, true)
+
+ style = style.gsub(/@import\s*(?:url\s*)?(?:\()?(?:\s*)["']?([^'"\s\)]*)["']?\)?([\w\s\,^\]\(\)]*)\)?[;\n]?/) do
+ uri = url_join(src, $1)
+ fname = resource_path_for(dir, uri, 'css')
+ file(uri, fname) { process_stylesheet_file(uri, fname) }
+ %{@import url("#{fname[skip]}") #$2;\n}
+ end
+
+ style = style.gsub(/(?!@import )url\s*\(["']?(.+?)["']?\)/) do
+ uri = url_join(src, $1)
+ fname = resource_path_for(dir, uri, 'png')
+ file(uri, fname)
+ %{url("#{fname[skip]}")}
+ end
+
+ style
+ end
+
+ def url_join(base, new)
+ if base && new
+ URI.join(base, new).to_s
+ else
+ base || new
+ end
+ end
+
+ def resource_path_for(dir, resource, ext = nil)
+ rfile = CGI.unescape(resource.gsub(%r{.*/|[#?].*}, ''))
+
+ if rfile.empty?
+ rfile = "downloaded#{'%04d' % @counter}"
+ @counter += 1
+ end
+
+ rfile << ".#{ext}" if ext && File.extname(rfile).empty?
+
+ prefix = 1
+ tfile = rfile
+
+ puts rfile
+
+ loop do
+ path = File.join(dir, tfile)
+ break path unless File.exists?(path)
+ tfile = "#{prefix}_#{rfile}"
+ prefix += 1
+ end
+ end
+
+ def failed(src, dst, response)
+ puts "#{src} -> #{dst} failed: #{response.status_message}"
+ end
+end
diff --git a/lib/tasks/docs.thor b/lib/tasks/docs.thor
index da3eced3..8862151d 100644
--- a/lib/tasks/docs.thor
+++ b/lib/tasks/docs.thor
@@ -109,6 +109,9 @@ class DocsCLI < Thor
desc 'verify ( ... | --all)', 'Verify documentations'
option :all, type: :boolean
def verify(*names)
+ require 'find'
+ require 'cgi'
+
docs = options[:all] ? Docs.all : find_docs(names)
assert_docs(docs)
docs.each(&method(:verify_doc))
@@ -117,6 +120,36 @@ class DocsCLI < Thor
invalid_doc(error.name)
end
+ desc 'devhelp-book ( ... | --all)', 'Generate DevHelp book'
+ option :all, type: :boolean
+ option :force, type: :boolean
+ def devhelp_book(*names)
+ require 'app'
+ require 'devhelp'
+
+ unless File.exists?(App.assets_path)
+ AssetsCLI.new.invoke(:compile)
+ end
+
+ docs = options[:all] ? Docs.all : find_docs(names)
+ assert_docs(docs)
+
+ js = File.expand_path('../assets/javascripts/vendor', Docs.root_path)
+
+ DevHelp.new({
+ force: options[:force],
+ base_path: Docs.store_path,
+ devhelp_path: Docs.devhelp_store_path,
+ asset_path: App.assets_path,
+ index: Docs::Doc::INDEX_FILENAME,
+ js: [File.join(js, 'prism.js'), File.join(js, 'prism-invoke.js')]
+ }).for_docs(docs)
+
+ puts 'Done'
+ rescue Docs::DocNotFound => error
+ invalid_doc(error.name)
+ end
+
desc 'clean', 'Delete documentation packages'
def clean
File.delete(*Dir[File.join Docs.store_path, '*.tar.gz'])
@@ -215,9 +248,6 @@ class DocsCLI < Thor
skip_path = (doc_path.length + 1)..-1
- require 'find'
- require 'cgi'
-
Find.find(doc_path) do |path|
next unless is_document?(path)
diff --git a/public/docs/docs.json b/public/docs/docs.json
index 0637a088..e32ca251 100644
--- a/public/docs/docs.json
+++ b/public/docs/docs.json
@@ -1 +1 @@
-[]
\ No newline at end of file
+[{"name":"Angular.js","slug":"angular","type":"angular","version":"1.0.7","index_path":"angular/index.json","mtime":1376320383},{"name":"Backbone.js","slug":"backbone","type":"underscore","version":"1.1.0","index_path":"backbone/index.json","mtime":1381653808},{"name":"CoffeeScript","slug":"coffeescript","type":"coffeescript","version":"1.6.3","index_path":"coffeescript/index.json","mtime":1381655883},{"name":"CSS","slug":"css","type":"mdn","version":null,"index_path":"css/index.json","mtime":1386415462},{"name":"D3.js","slug":"d3","type":"d3","version":"3.4.1","index_path":"d3/index.json","mtime":1390150423},{"name":"DOM","slug":"dom","type":"mdn","version":null,"index_path":"dom/index.json","mtime":1386432655},{"name":"DOM Events","slug":"dom_events","type":"mdn","version":null,"index_path":"dom_events/index.json","mtime":1381908561},{"name":"Ember.js","slug":"ember","type":"ember","version":"1.3.0","index_path":"ember/index.json","mtime":1389536714},{"name":"Git","slug":"git","type":"git","version":"1.8.5","index_path":"git/index.json","mtime":1386958029},{"name":"HTML","slug":"html","type":"mdn","version":null,"index_path":"html/index.json","mtime":1386413422},{"name":"HTTP","slug":"http","type":"rfc","version":null,"index_path":"http/index.json","mtime":1381675313},{"name":"JavaScript","slug":"javascript","type":"mdn","version":null,"index_path":"javascript/index.json","mtime":1386425468},{"name":"jQuery","slug":"jquery","type":"jquery","version":"up to 2.0.3","index_path":"jquery/index.json","mtime":1388954827},{"name":"jQuery Mobile","slug":"jquerymobile","type":"jquery","version":"1.4.0","index_path":"jquerymobile/index.json","mtime":1388956495},{"name":"jQuery UI","slug":"jqueryui","type":"jquery","version":"1.10.3","index_path":"jqueryui/index.json","mtime":1388955780},{"name":"Knockout.js","slug":"knockout","type":"knockout","version":"3.0.0","index_path":"knockout/index.json","mtime":1390167124},{"name":"Less","slug":"less","type":"less","version":"1.6.0","index_path":"less/index.json","mtime":1388929594},{"name":"Lo-Dash","slug":"lodash","type":"lodash","version":"2.4.1","index_path":"lodash/index.json","mtime":1386144288},{"name":"Node.js","slug":"node","type":"node","version":"0.10.24","index_path":"node/index.json","mtime":1387611542},{"name":"PHP","slug":"php","type":"php","version":"up to 5.5.8","index_path":"php/index.json","mtime":1389535846},{"name":"PostgreSQL","slug":"postgresql","type":"postgres","version":"up to 9.3.2","index_path":"postgresql/index.json","mtime":1387061550},{"name":"Python","slug":"python","type":"sphinx","version":"3.3.3","index_path":"python/index.json","mtime":1385469242},{"name":"Ruby on Rails","slug":"rails","type":"rdoc","version":"4.0.2","index_path":"rails/index.json","mtime":1386228555},{"name":"Redis","slug":"redis","type":"redis","version":"up to 2.8.4","index_path":"redis/index.json","mtime":1389660376},{"name":"Ruby","slug":"ruby","type":"rdoc","version":"2.1.0","index_path":"ruby/index.json","mtime":1388961427},{"name":"Sass","slug":"sass","type":"yard","version":"3.2.12","index_path":"sass/index.json","mtime":1381679946},{"name":"Underscore.js","slug":"underscore","type":"underscore","version":"1.5.2","index_path":"underscore/index.json","mtime":1381654139}]
\ No newline at end of file