require 'jsduck/option_parser' require 'jsduck/logger' require 'jsduck/util/json' require 'jsduck/util/os' require 'jsduck/util/io' require 'jsduck/util/parallel' require 'jsduck/tag_registry' require 'jsduck/js/ext_patterns' 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 :css 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 :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 @version = "5.0.1" # Customizing output @title = "Documentation - JSDuck" @header = "Documentation JSDuck" @footer = format_footer("Generated on {DATE} by {JSDUCK} {VERSION}.") @head_html = "" @body_html = "" @css = "" @message = "" @welcome = nil @guides = nil @videos = nil @examples = nil @categories_path = nil @source = true @images = [] @custom_tag_paths = [] @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 = '
' @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" @local_storage_db = "docs" @touch_examples_ui = false @imports = [] @new_since = nil # Turn multiprocessing off by default in Windows Util::Parallel.in_processes = Util::OS::windows? ? 0 : nil # Enable all warnings except the following: Logger.set_warning(:all, true) Logger.set_warning(:link_auto, false) Logger.set_warning(:param_count, false) Logger.set_warning(:fires, false) Logger.set_warning(:no_doc_param, 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) instance_variable_get("@#{key}") end def []=(key, value) instance_variable_set("@#{key}", value) end def parse!(argv) parse_options(argv) auto_detect_config_file unless @config_option_specified validate if @custom_tag_paths.length > 0 TagRegistry.reconfigure(@custom_tag_paths) else # Ensure the TagRegistry get instantiated just once. # Otherwise the parallel processing causes multiple requests # to initialize the TagRegistry, resulting in loading the Tag # definitions multiple times. TagRegistry.instance end 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 @config_option_specified = true 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