Commit 20587065 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Merge branch 'master' into doc-tags

parents 3f916406 bcf309d7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ install:
  - gem install rdiscount
  - gem install json
  - gem install parallel
  - gem install execjs
  - gem install therubyracer -v 0.10.1
  - gem install rspec
  - gem install rake
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
  s.add_dependency 'rdiscount'
  s.add_dependency 'json'
  s.add_dependency 'parallel'
  s.add_dependency 'execjs'
  s.add_dependency 'therubyracer', '>= 0.10.0', '< 0.11.0'
  s.add_dependency 'dimensions'

+24 −9
Original line number Diff line number Diff line
require 'v8'
require 'execjs'
require 'jsduck/util/json'
require 'jsduck/util/singleton'

module JsDuck
  module Js

    # Runs Esprima.js through V8.
    # Runs Esprima.js through JavaScript runtime selected by ExecJS.
    # Normally this will be V8 engine within therubyracer gem, but when
    # JSDuck is installed through some other means than rubygems, then
    # one could use any of the runtimes supported by ExecJS.  (NodeJS
    # for example.)
    #
    # Initialized as singleton to avoid loading the esprima.js more
    # than once - otherwise performace will severely suffer.
@@ -13,23 +17,34 @@ module JsDuck
      include Util::Singleton

      def initialize
        @v8 = V8::Context.new
        esprima = File.dirname(File.expand_path(__FILE__))+"/esprima/esprima.js";
        esprima_path = File.dirname(File.expand_path(__FILE__)) + "/esprima/esprima.js"
        esprima = IO.read(esprima_path)

        # Esprima attempts to assign to window.esprima, but our v8
        # engine has no global window variable defined.  So define our
        # own and then grab esprima out from it again.
        @v8.eval("var window = {};")
        @v8.load(esprima)
        @v8.eval("var esprima = window.esprima;")
        source = <<-EOJS
          if (typeof window === "undefined") {
              var window = {};
          }

          #{esprima}

          var esprima = window.esprima;

          function runEsprima(js) {
            return JSON.stringify(esprima.parse(js, {comment: true, range: true, raw: true}));
          }
        EOJS

        @context = ExecJS.compile(source)
      end

      # Parses JavaScript source code using Esprima.js
      #
      # Returns the resulting AST
      def parse(input)
        @v8['js'] = input
        json = @v8.eval("JSON.stringify(esprima.parse(js, {comment: true, range: true, raw: true}))")
        json = @context.call("runEsprima", input)
        return Util::Json.parse(json, :max_nesting => false)
      end

+40 −12
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ module JsDuck
      # Customizing output
      @title = "Documentation - JSDuck"
      @header = "<strong>Documentation</strong> JSDuck"
      @footer = "Generated with <a href='https://github.com/senchalabs/jsduck'>JSDuck</a> #{@version}."
      @footer = format_footer("Generated on {DATE} by {JSDUCK} {VERSION}.")
      @head_html = ""
      @body_html = ""
      @css = ""
@@ -140,6 +140,8 @@ module JsDuck
      Logger.set_warning(:all, true)
      Logger.set_warning(:link_auto, false)
      Logger.set_warning(:param_count, false)

      @optparser = create_option_parser
    end

    # Make options object behave like hash.
@@ -152,9 +154,8 @@ module JsDuck
    end

    def parse!(argv)
      create_option_parser.parse!(argv).each do |fname|
        read_filenames(canonical(fname))
      end
      parse_options(argv)
      auto_detect_config_file
      validate

      if @custom_tag_paths.length > 0
@@ -162,8 +163,10 @@ module JsDuck
      end
    end

    private

    def create_option_parser
      optparser = JsDuck::OptionParser.new do | opts |
      return JsDuck::OptionParser.new do | opts |
        opts.banner = "Usage: jsduck [options] files/dirs..."
        opts.separator ""
        opts.separator "For example:"
@@ -231,6 +234,9 @@ module JsDuck
          "",
          "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)
@@ -242,7 +248,7 @@ module JsDuck
          # 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)
          optparser.parse!(config).each {|fname| read_filenames(canonical(fname)) }
          parse_options(config)
          @working_dir = nil
        end

@@ -269,11 +275,14 @@ module JsDuck
        opts.on('--footer=TEXT',
          "Custom footer text for the documentation.",
          "",
          "Defaults to: 'Generated with JSDuck {VERSION}.'",
          "The text can contain various placeholders:",
          "",
          "  {DATE} - current date and time.",
          "  {JSDUCK} - link to JSDuck homepage.",
          "  {VERSION} - JSDuck version number.",
          "",
          "'{VERSION}' is a placeholder that will get substituted",
          "with the current version of JSDuck.  See --version.") do |text|
          @footer = text.gsub(/\{VERSION\}/, @version)
          "Defaults to: 'Generated on {DATE} by {JSDUCK} {VERSION}.'") do |text|
          @footer = format_footer(text)
        end

        opts.on('--head-html=HTML',
@@ -600,7 +609,7 @@ module JsDuck
        opts.on('-v', '--verbose',
          "Turns on excessive logging.",
          "",
          "Log messages are writted to STDERR.") do
          "Log messages are written to STDERR.") do
          Logger.verbose = true
        end

@@ -725,8 +734,20 @@ module JsDuck
          exit
        end
      end
    end

      return optparser
    # Parses the given command line options
    # (could have also been read from config file)
    def parse_options(options)
      @optparser.parse!(options).each {|fname| read_filenames(canonical(fname)) }
    end

    # Reads jsduck.json file in current directory
    def auto_detect_config_file
      fname = Dir.pwd + "/jsduck.json"
      if File.exists?(fname)
        parse_options(read_json_config(fname))
      end
    end

    # Reads JSON configuration from file and returns an array of
@@ -800,6 +821,13 @@ module JsDuck
      File.expand_path(path, @working_dir)
    end

    # Replace special placeholders in footer text
    def format_footer(text)
      jsduck = "<a href='https://github.com/senchalabs/jsduck'>JSDuck</a>"
      date = Time.new.strftime('%a %d %b %Y %H:%M:%S')
      text.gsub(/\{VERSION\}/, @version).gsub(/\{JSDUCK\}/, jsduck).gsub(/\{DATE\}/, date)
    end

    # Runs checks on the options
    def validate
      if @input_files.length == 0 && !@welcome && !@guides && !@videos && !@examples
+32 −0
Original line number Diff line number Diff line
// Temporary fix for IE10 before we upgrade to ExtJS 4.2.
// Without this clicking on the icons of ThumbList will show blank
// page as the code won't be able to extract the value of ext:url
// attribute.
//
// Patch taken from forum:
// http://www.sencha.com/forum/showthread.php?250267-Ext.Element.getAttribute-not-working-in-IE10
Ext.override(Ext.dom.Element, {
    getAttribute: (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) ?
        function (name, ns) {
            var d = this.dom,
                    type;
            if (ns) {
                type = typeof d[ns + ":" + name];
                if (type != 'undefined' && type != 'unknown') {
                    return d[ns + ":" + name] || null;
                }
                return null;
            }
            if (name === "for") {
                name = "htmlFor";
            }
            return d[name] || null;
        } : function (name, ns) {
            var d = this.dom;
            if (ns) {
                return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name);
            }
            return d.getAttribute(name) || d[name] || null;
        }
});

/**
 * View showing a list of clickable items with thumbnails.
 */