require 'jsduck/option_parser'
require 'jsduck/meta_tag_registry'
require 'jsduck/logger'
require 'jsduck/util/json'
require 'jsduck/util/os'
require 'jsduck/util/io'
require 'jsduck/util/parallel'
module JsDuck
# Keeps command line options
class Options
attr_accessor :input_files
attr_accessor :output_dir
attr_accessor :ignore_global
attr_accessor :external_classes
attr_accessor :ext4_events
# Customizing output
attr_accessor :title
attr_accessor :header
attr_accessor :footer
attr_accessor :head_html
attr_accessor :body_html
attr_accessor :message
attr_accessor :welcome
attr_accessor :guides
attr_accessor :videos
attr_accessor :examples
attr_accessor :categories_path
attr_accessor :source
attr_accessor :images
attr_accessor :link_tpl
attr_accessor :img_tpl
attr_accessor :export
attr_accessor :seo
attr_accessor :eg_iframe
attr_accessor :examples_base_url
attr_accessor :tests
attr_accessor :comments_url
attr_accessor :comments_domain
attr_accessor :search
attr_accessor :ignore_html
# Debugging
attr_accessor :warnings_exit_nonzero
attr_accessor :template_dir
attr_accessor :template_links
attr_accessor :extjs_path
attr_accessor :data_path
attr_accessor :local_storage_db
attr_accessor :touch_examples_ui
attr_accessor :ext_namespaces
attr_accessor :imports
attr_accessor :new_since
def initialize
@input_files = []
@output_dir = nil
@ignore_global = false
@external_classes = [
# JavaScript builtins
"Object",
"String",
"Number",
"Boolean",
"RegExp",
"Function",
"Array",
"Arguments",
"Date",
# JavaScript builtin error classes
# https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Error
"Error",
"EvalError",
"RangeError",
"ReferenceError",
"SyntaxError",
"TypeError",
"URIError",
# DOM
"HTMLElement",
"XMLElement",
"NodeList",
"TextNode",
"CSSStyleSheet",
"CSSStyleRule",
"Event",
# Special anything-goes type
"Mixed",
]
@ext4_events = nil
@meta_tag_paths = []
@version = "4.10.1"
# Customizing output
@title = "Documentation - JSDuck"
@header = "Documentation JSDuck"
@footer = format_footer("Generated on {DATE} by {JSDUCK} {VERSION}.")
@head_html = ""
@body_html = ""
@message = ""
@welcome = nil
@guides = nil
@videos = nil
@examples = nil
@categories_path = nil
@source = true
@images = []
@link_tpl = '%a'
# Note that we wrap image template inside
because {@img} often
# appears inline within text, but that just looks ugly in HTML
@img_tpl = '
![%a](%u)
'
@export = nil
@seo = false
@eg_iframe = nil
@examples_base_url = "extjs-build/examples/"
@tests = false
@comments_url = nil
@comments_domain = nil
@search = {}
@ignore_html = {}
# Debugging
@warnings_exit_nonzero = false
@root_dir = File.dirname(File.dirname(File.dirname(__FILE__)))
@template_dir = @root_dir + "/template-min"
@template_links = false
@extjs_path = "extjs/ext-all.js"
@data_path = nil # This gets assigned in JsDuck::WebWriter after writing the data file.
@local_storage_db = "docs"
@touch_examples_ui = false
@ext_namespaces = ["Ext"]
@imports = []
@new_since = nil
# Turn multiprocessing off by default in Windows
Util::Parallel.in_processes = Util::OS::windows? ? 0 : nil
# enable all warnings except :link_auto
Logger.set_warning(:all, true)
Logger.set_warning(:link_auto, false)
@optparser = create_option_parser
end
# Make options object behave like hash.
# This allows us to substitute it with hash in unit tests.
def [](key)
send(key)
end
def parse!(argv)
parse_options(argv)
auto_detect_config_file
validate
reg = MetaTagRegistry.new
reg.load([:builtins] + @meta_tag_paths)
reg[:new].create_tooltip!(@imports, @new_since)
MetaTagRegistry.instance = reg
end
private
def create_option_parser
return JsDuck::OptionParser.new do | opts |
opts.banner = "Usage: jsduck [options] files/dirs..."
opts.separator ""
opts.separator "For example:"
opts.separator ""
opts.separator " # Documentation for builtin JavaScript classes like Array and String"
opts.separator " jsduck --output output/dir --builtin-classes"
opts.separator ""
opts.separator " # Documentation for your own JavaScript"
opts.separator " jsduck --output output/dir input-file.js some/input/dir"
opts.separator ""
opts.separator "The main options:"
opts.separator ""
opts.on('-o', '--output=PATH',
"Directory to write all this documentation.",
"",
"This option is REQUIRED. When the directory exists,",
"it will be overwritten. Give dash '-' as argument",
"to write docs to STDOUT (works only with --export).") do |path|
@output_dir = path == "-" ? :stdout : canonical(path)
end
opts.on('--export=TYPE',
"Exports docs in JSON.",
"",
"TYPE is one of:",
"",
"- full - full class docs.",
"- examples - extracts inline examples from classes.") do |format|
export_type = format.to_sym
if [:full, :examples].include?(export_type)
@export = export_type
else
Logger.fatal("Unsupported export type: '#{export_type}'")
exit(1)
end
end
opts.on('--builtin-classes',
"Includes docs for JavaScript builtins.",
"",
"Docs for the following classes are included:",
"",
"- Array",
"- Boolean",
"- Date",
"- Function",
"- Number",
"- Object",
"- RegExp",
"- String") do
read_filenames(@root_dir + "/js-classes")
end
opts.on('--seo', "Enables SEO-friendly print version.",
"",
"Instead of index.html creates index.php that will serve",
"the regular docs, print-friendly docs, and search-engine-",
"friendly docs (the latter two are pretty much the same).") do
@seo = true
end
opts.on('--config=PATH',
"Loads config options from JSON file.",
"",
"An alternative to listing all options on command line.",
"",
"When the current directory contains jsduck.json file",
"then options are automatically read from there.",
"",
"See also: https://github.com/senchalabs/jsduck/wiki/Config-file") do |path|
path = canonical(path)
if File.exists?(path)
config = read_json_config(path)
else
Logger.fatal("The config file #{path} doesn't exist")
exit(1)
end
# treat paths inside JSON config relative to the location of
# config file. When done, switch back to current working dir.
@working_dir = File.dirname(path)
parse_options(config)
@working_dir = nil
end
opts.on('--encoding=NAME', "Input encoding (defaults to UTF-8).") do |encoding|
JsDuck::Util::IO.encoding = encoding
end
opts.separator ""
opts.separator "Customizing output:"
opts.separator ""
opts.on('--title=TEXT',
"Custom title text for the documentation.",
"",
"Defaults to 'Documentation - JSDuck'",
"",
"The title will be used both inside and in",
"the header of the page. Inside page header the left",
"part (from ' - ' separator) will be shown in bold.") do |text|
@title = text
@header = text.sub(/^(.*?) +- +/, "\\1 ")
end
opts.on('--footer=TEXT',
"Custom footer text for the documentation.",
"",
"The text can contain various placeholders:",
"",
" {DATE} - current date and time.",
" {JSDUCK} - link to JSDuck homepage.",
" {VERSION} - JSDuck version number.",
"",
"Defaults to: 'Generated on {DATE} by {JSDUCK} {VERSION}.'") do |text|
@footer = format_footer(text)
end
opts.on('--head-html=HTML',
"HTML for the section of index.html.",
"",
"Useful for adding extra