Merge branch 'hardening_types'
authorJean Privat <jean@pryen.org>
Fri, 28 Feb 2014 21:15:36 +0000 (16:15 -0500)
committerJean Privat <jean@pryen.org>
Fri, 28 Feb 2014 21:15:36 +0000 (16:15 -0500)
133 files changed:
.mailmap
LICENSE-MIT [deleted file]
NOTICE
VERSION
examples/opengles2_hello_triangle.nit [new file with mode: 0644]
lib/a_star.nit
lib/console.nit [new file with mode: 0644]
lib/counter.nit
lib/cpp.nit [new file with mode: 0644]
lib/egl.nit [new file with mode: 0644]
lib/glesv2.nit [new file with mode: 0644]
lib/mnit/input_events.nit
lib/mnit_linux/sdl.nit
lib/poset.nit
lib/standard/file.nit
lib/standard/math.nit
lib/standard/string.nit
lib/x11.nit [new file with mode: 0644]
share/nitdoc/ZeroClipboard.swf [deleted file]
share/nitdoc/css/Nitdoc.GitHub.css [moved from share/nitdoc/styles/Nitdoc.GitHub.css with 81% similarity]
share/nitdoc/css/Nitdoc.ModalBox.css [new file with mode: 0644]
share/nitdoc/css/Nitdoc.QuickSearch.css [moved from share/nitdoc/styles/Nitdoc.QuickSearch.css with 89% similarity]
share/nitdoc/css/Nitdoc.UI.css [moved from share/nitdoc/styles/Nitdoc.UI.css with 71% similarity]
share/nitdoc/css/main.css [moved from share/nitdoc/styles/main.css with 92% similarity]
share/nitdoc/js/lib/github-api.js [new file with mode: 0644]
share/nitdoc/js/lib/highlight.js [new file with mode: 0644]
share/nitdoc/js/lib/jquery-ui.js [new file with mode: 0644]
share/nitdoc/js/lib/jquery.js [moved from share/nitdoc/scripts/jquery-1.7.1.min.js with 100% similarity]
share/nitdoc/js/lib/marked.js [new file with mode: 0644]
share/nitdoc/js/lib/nit.js [new file with mode: 0644]
share/nitdoc/js/lib/require.js [new file with mode: 0644]
share/nitdoc/js/lib/utils.js [new file with mode: 0644]
share/nitdoc/js/nitdoc.js [new file with mode: 0644]
share/nitdoc/js/plugins/filtering.js [new file with mode: 0644]
share/nitdoc/js/plugins/folding.js [new file with mode: 0644]
share/nitdoc/js/plugins/github.js [new file with mode: 0644]
share/nitdoc/js/plugins/github/commentbox.js [new file with mode: 0644]
share/nitdoc/js/plugins/github/loginbox.js [new file with mode: 0644]
share/nitdoc/js/plugins/modalbox.js [new file with mode: 0644]
share/nitdoc/js/plugins/quicksearch.js [new file with mode: 0644]
share/nitdoc/scripts/Markdown.Converter.js [deleted file]
share/nitdoc/scripts/Nitdoc.GitHub.js [deleted file]
share/nitdoc/scripts/Nitdoc.QuickSearch.js [deleted file]
share/nitdoc/scripts/Nitdoc.UI.js [deleted file]
share/nitdoc/scripts/ZeroClipboard.min.js [deleted file]
share/nitdoc/scripts/base64.js [deleted file]
src/abstract_compiler.nit
src/auto_super_init.nit
src/common_ffi/c_compiler_options.nit
src/common_ffi/common_ffi.nit
src/common_ffi/cpp.nit [new file with mode: 0644]
src/debugger.nit
src/global_compiler.nit
src/metrics/inheritance_metrics.nit
src/metrics/mclasses_metrics.nit [new file with mode: 0644]
src/metrics/metrics.nit
src/metrics/metrics_base.nit
src/metrics/mmodules_metrics.nit [new file with mode: 0644]
src/metrics/nullables_metrics.nit
src/metrics/rta_metrics.nit
src/modelize_property.nit
src/naive_interpreter.nit
src/nitdoc.nit
src/separate_compiler.nit
src/typing.nit
tests/base_for_nullable.nit [new file with mode: 0644]
tests/base_init_super_call.nit [new file with mode: 0644]
tests/base_init_super_call2.nit [new file with mode: 0644]
tests/base_virtual_type_redef.nit [new file with mode: 0644]
tests/error_needed_method.nit
tests/nitg-s.skip
tests/nitmetrics.args
tests/sav/base_attr_gen.res
tests/sav/base_for_nullable.res [new file with mode: 0644]
tests/sav/base_for_nullable_alt1.res [new file with mode: 0644]
tests/sav/base_for_nullable_alt2.res [new file with mode: 0644]
tests/sav/base_init_super_call.res [new file with mode: 0644]
tests/sav/base_init_super_call2.res [new file with mode: 0644]
tests/sav/base_init_super_call2_alt1.res [new file with mode: 0644]
tests/sav/base_init_super_call2_alt2.res [new file with mode: 0644]
tests/sav/base_init_super_call2_alt3.res [new file with mode: 0644]
tests/sav/base_init_super_call2_alt4.res [new file with mode: 0644]
tests/sav/base_init_super_call2_alt5.res [new file with mode: 0644]
tests/sav/base_init_super_call2_alt6.res [new file with mode: 0644]
tests/sav/base_init_super_call_alt1.res [new file with mode: 0644]
tests/sav/base_init_super_call_alt2.res [new file with mode: 0644]
tests/sav/base_init_super_call_alt3.res [new file with mode: 0644]
tests/sav/base_init_super_call_alt4.res [new file with mode: 0644]
tests/sav/base_init_super_call_alt5.res [new file with mode: 0644]
tests/sav/base_init_super_call_alt6.res [new file with mode: 0644]
tests/sav/base_iterator3.res
tests/sav/base_primitive_null_alt1.res
tests/sav/base_primitive_null_alt2.res
tests/sav/base_primitive_null_alt3.res
tests/sav/base_virtual_type_redef.res [new file with mode: 0644]
tests/sav/egl.res [new file with mode: 0644]
tests/sav/error_expr_not_ok_alt4.res
tests/sav/error_expr_not_ok_alt5.res
tests/sav/error_expr_not_ok_alt6.res
tests/sav/error_for_coll.res
tests/sav/error_needed_method_alt2.res
tests/sav/error_needed_types_alt8.res
tests/sav/glesv2.res [new file with mode: 0644]
tests/sav/nitc/base_for_nullable.res [new file with mode: 0644]
tests/sav/nitc/base_for_nullable_alt1.res [new file with mode: 0644]
tests/sav/nitc/base_for_nullable_alt2.res [new file with mode: 0644]
tests/sav/nitdoc.res
tests/sav/nitdoc_args1.res
tests/sav/nitg-s/fixme/base_attr_gen_alt1.res
tests/sav/nitmetrics.res
tests/sav/nitmetrics_args1.res
tests/sav/opengles2_hello_triangle.res [new file with mode: 0644]
tests/sav/rterror_attr_def_alt6.res
tests/sav/rterror_attr_def_alt8.res
tests/sav/rterror_null_receiver_alt1.res
tests/sav/rterror_null_receiver_alt2.res
tests/sav/rterror_null_receiver_alt3.res
tests/sav/rterror_null_receiver_alt4.res
tests/sav/rterror_null_receiver_alt5.res
tests/sav/rterror_null_receiver_alt6.res
tests/sav/test_ffi_cpp_callbacks.res [new file with mode: 0644]
tests/sav/test_ffi_cpp_header.res [new file with mode: 0644]
tests/sav/test_ffi_cpp_simple_fun.res [new file with mode: 0644]
tests/sav/test_ffi_cpp_strings.res [new file with mode: 0644]
tests/sav/test_ffi_cpp_types.res [new file with mode: 0644]
tests/sav/test_file_copy.res [new file with mode: 0644]
tests/sav/x11.res [new file with mode: 0644]
tests/test_ffi_cpp_callbacks.nit [new file with mode: 0644]
tests/test_ffi_cpp_header.nit [new file with mode: 0644]
tests/test_ffi_cpp_simple_fun.nit [new file with mode: 0644]
tests/test_ffi_cpp_strings.nit [new file with mode: 0644]
tests/test_ffi_cpp_types.nit [new file with mode: 0644]
tests/test_file_copy.nit [new file with mode: 0644]

index 7f1f623..a3e389c 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -1,12 +1,25 @@
 <jean@pryen.org> <privat@ciara.pryen.org>
+<jean@pryen.org> <jean@x400.pryen.org>
 
 Alexandre Terrasa <alexandre@moz-code.org> <alexadre@moz-code.org>
 <alexandre@moz-code.org> <alexandre@moz-concept.com>
 Alexandre Terrasa <alexandre@moz-code.org> <alexandre.terrasa@gmail.com>
+<alexandre@moz-code.org> <Morriar@users.noreply.github.com>
 
-Lucas Bajolet <lucas.bajolet@hotmail.com>
-Lucas Bajolet <lucas.bajolet@hotmail.com> <r4pass@hotmail.com>
-Lucas Bajolet <lucas.bajolet@hotmail.com> <r4pass@r4pass-ubu-laptophp.(none)>
-<lucas.bajolet@hotmail.com> <r4pass@localhost.localdomain> 
+Lucas Bajolet <r4pass@hotmail.com> <lucas.bajolet@hotmail.com>
+Lucas Bajolet <r4pass@hotmail.com>
+Lucas Bajolet <r4pass@hotmail.com> <r4pass@r4pass-ubu-laptophp.(none)>
+<r4pass@hotmail.com> <r4pass@localhost.localdomain>
 
 Nathan Heu <heu.nathan@courrier.uqam.ca>
+
+Geoffrey Hecht <geoffrey.hecht@gmail.com>
+
+Johan Kayser <johan.kayser@viacesi.fr>
+
+Romain Chanoir <romain.chanoir@viacesi.fr> 
+<romain.chanoir@viacesi.fr> <chanoir.romain@courrier.uqam.ca>
+
+Clement de Figueiredo <clement.defigueiredo@gmail.com>
+
+Christophe Gigax <christophe.gigax@viacesi.fr>
diff --git a/LICENSE-MIT b/LICENSE-MIT
deleted file mode 100644 (file)
index 0ca65b9..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-The MIT License (MIT)
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
diff --git a/NOTICE b/NOTICE
index 72c94fe..e85c0fc 100644 (file)
--- a/NOTICE
+++ b/NOTICE
@@ -36,8 +36,3 @@ Copyright: 2009-2012 Alexis Laferrière <alexis.laf@xymus.net>
            2006 Gabriel Bauman <gbauman@gmail.com>
 License: GPL 2.0 (see LICENSE-GPL-2)
 Comment: GPL because the original work is GPL
-
-Files: share/nitdoc/ZeroClipboard.swf
-       share/nitdoc/scripts/ZeroClipboard.min.js
-Copyright: 2013 Jon Rohan, James M. Greene
-Licence: MIT (see LICENSE-MIT)
diff --git a/VERSION b/VERSION
index 9bee95a..2fc7b36 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-v0.6.1-git
+v0.6.4
diff --git a/examples/opengles2_hello_triangle.nit b/examples/opengles2_hello_triangle.nit
new file mode 100644 (file)
index 0000000..a16090c
--- /dev/null
@@ -0,0 +1,184 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Basic example of OpenGL ES 2.0 usage from the book OpenGL ES 2.0 Programming Guide.
+#
+# Code reference:
+# https://code.google.com/p/opengles-book-samples/source/browse/trunk/LinuxX11/Chapter_2/Hello_Triangle/Hello_Triangle.c 
+module opengles2_hello_triangle
+
+import glesv2
+import egl
+import mnit_linux # for sdl
+import x11
+
+if "NIT_TESTING".environ == "true" then exit(0)
+
+var window_width = 800
+var window_height = 600
+
+#
+## SDL
+#
+var sdl_display = new SDLDisplay(window_width, window_height)
+var sdl_wm_info = new SDLSystemWindowManagerInfo
+var x11_window_handle = sdl_wm_info.x11_window_handle
+
+#
+## X11
+#
+var x_display = x_open_default_display
+assert x_display != 0 else print "x11 fail"
+
+#
+## EGL
+#
+var egl_display = new EGLDisplay(x_display)
+assert egl_display.is_valid else print "EGL display is not valid"
+egl_display.initialize
+
+print "EGL version: {egl_display.version}"
+print "EGL vendor: {egl_display.vendor}"
+print "EGL extensions: {egl_display.extensions.join(", ")}"
+print "EGL client APIs: {egl_display.client_apis.join(", ")}"
+
+assert egl_display.is_valid else print egl_display.error
+
+var config_chooser = new EGLConfigChooser
+#config_chooser.surface_type_egl
+config_chooser.blue_size = 8
+config_chooser.green_size = 8
+config_chooser.red_size = 8
+#config_chooser.alpha_size = 8
+#config_chooser.depth_size = 8
+#config_chooser.stencil_size = 8
+#config_chooser.sample_buffers = 1
+config_chooser.close
+
+var configs = config_chooser.choose(egl_display)
+assert configs != null else print "choosing config failed: {egl_display.error}"
+assert not configs.is_empty else print "no EGL config"
+
+var config = configs.first
+
+var format = config.attribs(egl_display).native_visual_id
+
+# TODO android part
+# Opengles1Display_midway_init(recv, format);
+
+var surface = egl_display.create_window_surface(config, x11_window_handle, [0])
+assert surface.is_ok else print egl_display.error
+
+var context = egl_display.create_context(config)
+assert context.is_ok else print egl_display.error
+
+var make_current_res = egl_display.make_current(surface, surface, context)
+assert make_current_res
+
+var width = surface.attribs(egl_display).width
+var height = surface.attribs(egl_display).height
+print "Width: {width}"
+print "Height: {height}"
+
+assert egl_bind_opengl_es_api else print "eglBingAPI failed: {egl_display.error}"
+
+#
+## GLESv2
+#
+
+print "Can compile shaders? {gl_shader_compiler}"
+assert_no_gl_error
+
+assert gl_shader_compiler else print "Cannot compile shaders"
+
+# gl program
+print gl_error.to_s
+var program = new GLProgram
+if not program.is_ok then
+       print "Program is not ok: {gl_error.to_s}\nLog:"
+       print program.info_log
+       abort
+end
+assert_no_gl_error
+
+# vertex shader
+var vertex_shader = new GLVertexShader
+assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl_error}"
+vertex_shader.source = """
+attribute vec4 vPosition;   
+void main()                 
+{                           
+  gl_Position = vPosition;  
+}                           """
+vertex_shader.compile
+assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {vertex_shader.info_log} {program.info_log}"
+assert_no_gl_error
+
+# fragment shader
+var fragment_shader = new GLFragmentShader
+assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl_error}"
+fragment_shader.source = """
+precision mediump float;
+void main()
+{
+       gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+"""
+fragment_shader.compile
+assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}"
+assert_no_gl_error
+
+program.attach_shader vertex_shader
+program.attach_shader fragment_shader
+program.bind_attrib_location(0, "vPosition")
+program.link
+assert program.is_linked else print "Linking failed: {program.info_log}"
+assert_no_gl_error
+
+# draw!
+var vertices = [0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0]
+var vertex_array = new VertexArray(0, 3, vertices)
+vertex_array.attrib_pointer
+gl_clear_color(0.5, 0.0, 0.5, 1.0)
+for i in [0..10000[ do
+       printn "."
+       assert_no_gl_error
+       gl_viewport(0, 0, width, height)
+       gl_clear_color_buffer
+       program.use
+       vertex_array.enable
+       vertex_array.draw_arrays_triangles
+       egl_display.swap_buffers(surface)
+end
+
+# delete
+program.delete
+vertex_shader.delete
+fragment_shader.delete
+
+#
+## EGL
+#
+# close
+egl_display.make_current(new EGLSurface.none, new EGLSurface.none, new EGLContext.none)
+egl_display.destroy_context(context)
+egl_display.destroy_surface(surface)
+
+#
+## SDL
+#
+# close
+sdl_display.destroy
index 5613cec..3d8112d 100644 (file)
 # Services related to pathfinding of graphs using A*
 # A single graph may have different properties according to the `PathContext` used
 #
+#
 # Usage:
 #
-#    # Weighted graph (letters are nodes, digits are weights):
-#    #
-#    #     a -2- b
-#    #    /     /
-#    #   3     1
-#    #  /     /
-#    # c -3- d -8- e
-#    #
-#    var graph = new Graph[Node,WeigthedLink[Node]]
+# ~~~
+# # Weighted graph (letters are nodes, digits are weights):
+# #
+# #     a -2- b
+# #    /     /
+# #   3     1
+# #  /     /
+# # c -3- d -8- e
+# #
+# var graph = new Graph[Node,WeigthedLink[Node]]
 #
-#    var na = new Node(graph)
-#    var nb = new Node(graph)
-#    var nc = new Node(graph)
-#    var nd = new Node(graph)
-#    var ne = new Node(graph)
+# var na = new Node(graph)
+# var nb = new Node(graph)
+# var nc = new Node(graph)
+# var nd = new Node(graph)
+# var ne = new Node(graph)
 #
-#    var lab = new WeightedLink(graph, na, nb, 2)
-#    var lac = new WeightedLink(graph, na, nc, 3)
-#    var lbd = new WeightedLink(graph, nb, nd, 1)
-#    var lcd = new WeightedLink(graph, nc, nd, 3)
-#    var lde = new WeightedLink(graph, nd, ne, 8)
+# var lab = new WeightedLink(graph, na, nb, 2)
+# var lac = new WeightedLink(graph, na, nc, 3)
+# var lbd = new WeightedLink(graph, nb, nd, 1)
+# var lcd = new WeightedLink(graph, nc, nd, 3)
+# var lde = new WeightedLink(graph, nd, ne, 8)
 #
-#    var context = new WeightedPathContext(graph)
+# var context = new WeightedPathContext(graph)
 #
-#    var path = na.path_to(ne, 100, context)
-#    assert path != null else print "No possible path"
+# var path = na.path_to(ne, 100, context)
+# assert path != null else print "No possible path"
 #
-#    assert path.step == nb
-#    assert path.step == nd
-#    assert path.step == ne
-#    assert path.at_end_of_path
+# assert path.step == nb
+# assert path.step == nd
+# assert path.step == ne
+# assert path.at_end_of_path
+# ~~~
 module a_star
 
 redef class Object
diff --git a/lib/console.nit b/lib/console.nit
new file mode 100644 (file)
index 0000000..e6a129f
--- /dev/null
@@ -0,0 +1,36 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Simple numerical statistical analysis and presentation
+module console
+
+# Redef String class to add a function to color the string
+redef class String
+       private fun add_escape_char(escapechar: String): String do
+               return "{escapechar}{self}{esc}[0m"
+       end
+
+       private fun esc: Char do return 27.ascii
+       fun gray: String do return add_escape_char("{esc}[30m")
+       fun red: String do return add_escape_char("{esc}[31m")
+       fun green: String do return add_escape_char("{esc}[32m")
+       fun yellow: String do return add_escape_char("{esc}[33m")
+       fun blue: String do return add_escape_char("{esc}[34m")
+       fun purple: String do return add_escape_char("{esc}[35m")
+       fun cyan: String do return add_escape_char("{esc}[36m")
+       fun light_gray: String do return add_escape_char("{esc}[37m")
+       fun bold: String do return add_escape_char("{esc}[1m")
+       fun underline: String do return add_escape_char("{esc}[4m")
+end
+
index 0aaa711..4c7b6d6 100644 (file)
@@ -27,6 +27,8 @@ class Counter[E: Object]
 
        private var map = new HashMap[E, Int]
 
+       redef fun iterator do return map.iterator
+
        # The number of counted occurrences of `e`
        redef fun [](e: E): Int
        do
@@ -46,6 +48,12 @@ class Counter[E: Object]
 
        redef fun values do return map.values
 
+       redef fun length do return map.length
+
+       redef fun is_empty do return map.is_empty
+
+       redef fun clear do map.clear
+
        # Count one more occurrence of `e`
        fun inc(e: E)
        do
@@ -118,6 +126,42 @@ class Counter[E: Object]
                        print "  {element_to_s(t)}: {self[t]} ({div(self[t]*100,self.total)}%)"
                end
        end
+
+       # Return the element with the highest value
+       fun max: nullable E do
+               var max: nullable Int = null
+               var elem: nullable E = null
+               for e, v in map do
+                       if max == null or v > max then
+                               max = v
+                               elem = e
+                       end
+               end
+               return elem
+       end
+
+       # Return the couple with the lowest value
+       fun min: nullable E do
+               var min: nullable Int = null
+               var elem: nullable E = null
+               for e, v in map do
+                       if min == null or v < min then
+                               min = v
+                               elem = e
+                       end
+               end
+               return elem
+       end
+
+       # Values average
+       fun avg: Float do
+               if values.is_empty then return 0.0
+               var sum = 0
+               for value in map.values do
+                       sum += value
+               end
+               return sum.to_f / values.length.to_f
+       end
 end
 
 private class CounterSorter[E: Object]
diff --git a/lib/cpp.nit b/lib/cpp.nit
new file mode 100644 (file)
index 0000000..b994a83
--- /dev/null
@@ -0,0 +1,32 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Offers features to interface with C++ code and libraries
+module cpp
+
+# A pointer to a C++ std::string instance
+extern class CppString in "C++" `{ std::string* `}
+end
+
+redef class String
+       fun to_cpp_string: CppString do return to_cstring.to_cpp_string
+end
+
+redef class NativeString
+       fun to_cpp_string: CppString in "C++" `{
+               return new std::string(recv);
+       `}
+end
diff --git a/lib/egl.nit b/lib/egl.nit
new file mode 100644 (file)
index 0000000..38cd1f2
--- /dev/null
@@ -0,0 +1,369 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# EGL is an interface between the rendering APIs OpenGL, OpenGL ES, etc.
+# and the native windowing system.
+#
+# Most services of this module are a direct wrapper of the underlying
+# C library. If a method or class is not documented in Nit, refer to
+# the official documentation by the Khronos Group at:
+# http://www.khronos.org/registry/egl/sdk/docs/man/xhtml/
+module egl is pkgconfig("egl")
+
+in "C Header" `{
+       #include <EGL/egl.h>
+`}
+
+extern class EGLNativeDisplayType `{ EGLNativeDisplayType `}
+       new from_x11(handle: Pointer) `{ return (EGLNativeDisplayType)handle; `}
+end
+
+extern class EGLDisplay `{ EGLDisplay `}
+       new current `{ return eglGetCurrentDisplay(); `}
+       new(handle: Pointer) `{ return eglGetDisplay(handle); `}
+
+       fun is_valid: Bool `{ return recv != EGL_NO_DISPLAY; `}
+
+       fun initialize: Bool `{
+               EGLBoolean r = eglInitialize(recv, NULL, NULL);
+               if (r == EGL_FALSE) {
+                       fprintf(stderr, "Unable to eglInitialize");
+                       return 0;
+               }
+               return 1;
+       `}
+
+       fun major_version: Int `{
+               EGLint val;
+               eglInitialize(recv, &val, NULL);
+               return val;
+       `}
+       fun minor_version: Int `{
+               EGLint val;
+               eglInitialize(recv, NULL, &val);
+               return val;
+       `}
+
+       # TODO if useful
+       # Returns all configs supported by the hardware
+       #fun get_configs: nullable Array[EGLConfig] import Array[EGLConfig].with_native `{
+
+       # Returns some configs compatible with the specified `attributes`
+       fun choose_configs(attribs: Array[Int]): nullable Array[EGLConfig] import Array[Int].length, Array[Int].[], Array[EGLConfig], Array[EGLConfig].add, Array[EGLConfig] as nullable, report_egl_error `{
+               EGLConfig *configs;
+               int n_configs;
+               int n_attribs = Array_of_Int_length(attribs);
+               int i;
+               int *c_attribs = malloc(sizeof(int)*n_attribs);
+               for (i = 0; i < n_attribs; i ++) {
+                       c_attribs[i] = Array_of_Int__index(attribs, i);
+               }
+
+               // get number of configs
+               EGLBoolean r = eglChooseConfig(recv, c_attribs, NULL, 0, &n_configs);
+
+               if (r == EGL_FALSE) {
+                       EGLDisplay_report_egl_error(recv, "failed to get number of available configs.");
+                       return null_Array_of_EGLConfig();
+               } else if (n_configs == 0) {
+                       EGLDisplay_report_egl_error(recv, "no config available.");
+                       return null_Array_of_EGLConfig();
+               }
+
+               configs = (EGLConfig*)malloc(sizeof(EGLConfig)*n_configs);
+               r = eglChooseConfig(recv, c_attribs, configs, n_configs, &n_configs);
+
+               if (r == EGL_FALSE) {
+                       EGLDisplay_report_egl_error(recv, "failed to load config.");
+                       return null_Array_of_EGLConfig();
+               } else {
+                       Array_of_EGLConfig array = new_Array_of_EGLConfig();
+                       for (i=0; i < n_configs; i++)
+                               Array_of_EGLConfig_add(array, configs[i]);
+
+                       return Array_of_EGLConfig_as_nullable(array);
+               }
+       `}
+
+       # Can be used directly, but it is preferable to use a `EGLConfigAttribs`
+       fun config_attrib(config: EGLConfig, attribute: Int): Int `{
+               EGLint val;
+               EGLBoolean r = eglGetConfigAttrib(recv, config, attribute, &val);
+               if (r == EGL_FALSE)
+                       return -1;
+               else
+                       return val;
+       `}
+
+       fun terminate: Bool `{
+               return eglTerminate(recv) == EGL_TRUE;
+       `}
+
+       fun create_window_surface(config: EGLConfig, native_window: Pointer, attribs: Array[Int]): EGLSurface `{
+               EGLSurface surface = eglCreateWindowSurface(recv, config, (EGLNativeWindowType)native_window, NULL);
+               return surface;
+       `}
+
+       # TODO add share_context
+       fun create_context(config: EGLConfig): EGLContext `{
+               EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE}; // TODO move out!
+               EGLContext context = eglCreateContext(recv, config, EGL_NO_CONTEXT, context_attribs);
+               return context;
+       `}
+
+       fun make_current(draw, read: EGLSurface, context: EGLContext): Bool `{
+               if (eglMakeCurrent(recv, draw, read, context) == EGL_FALSE) {
+                       fprintf(stderr, "Unable to eglMakeCurrent");
+                       return 0;
+               }
+               return 1;
+       `}
+
+       # Can be used directly, but it is preferable to use a `EGLSurfaceAttribs`
+       fun query_surface(surface: EGLSurface, attribute: Int): Int `{
+               int val;
+               EGLBoolean r = eglQuerySurface(recv, surface, attribute, &val);
+               if (r == EGL_FALSE)
+                       return -1;
+               else
+                       return val;
+       `}
+
+       fun destroy_context(context: EGLContext): Bool `{
+               return eglDestroyContext(recv, context);
+       `}
+
+       fun destroy_surface(surface: EGLSurface): Bool `{
+               return eglDestroySurface(recv, surface);
+       `}
+
+       fun error: EGLError `{ return eglGetError(); `}
+
+       # Utility method for easier debugging
+       fun assert_no_egl_error
+       do
+               var error = self.error
+               if not error.is_success then
+                       print "EGL error: {error}"
+                       abort
+               end
+       end
+
+       private fun query_string(name: Int): String import NativeString.to_s `{
+               return (void*)(long)NativeString_to_s(eglQueryString(recv, name));
+       `}
+
+       fun vendor: String do return query_string("3053".to_hex)
+
+       fun version: String do return query_string("3054".to_hex)
+
+       fun extensions: Array[String] do return query_string("3055".to_hex).split_with(" ")
+
+       fun client_apis: Array[String] do return query_string("308D".to_hex).split_with(" ")
+
+       fun swap_buffers(surface: EGLSurface) `{ eglSwapBuffers(recv, surface); `}
+end
+
+extern class EGLConfig `{ EGLConfig `}
+       fun attribs(display: EGLDisplay): EGLConfigAttribs do
+               return new EGLConfigAttribs(display, self)
+       end
+end
+
+extern class EGLSurface `{ EGLSurface `}
+       new current_draw `{ return eglGetCurrentSurface(EGL_DRAW); `}
+       new current_read `{ return eglGetCurrentSurface(EGL_READ); `}
+       new none `{ return EGL_NO_SURFACE; `}
+
+       fun is_ok: Bool `{ return recv != EGL_NO_SURFACE; `}
+
+       fun attribs(display: EGLDisplay): EGLSurfaceAttribs do
+               return new EGLSurfaceAttribs(display, self)
+       end
+end
+
+extern class EGLContext `{ EGLContext `}
+       new current `{ return eglGetCurrentContext(); `}
+       new none `{ return EGL_NO_CONTEXT; `}
+
+       fun is_ok: Bool `{ return recv != EGL_NO_CONTEXT; `}
+end
+
+# Attributes of a config for a given EGL display
+class EGLConfigAttribs
+       var display: EGLDisplay
+       var config: EGLConfig
+
+       fun alpha_size: Int do return display.config_attrib(config, "3021".to_hex)
+       fun native_visual_id: Int do return display.config_attrib(config, "302E".to_hex)
+       fun native_visual_type: Int do return display.config_attrib(config, "302F".to_hex)
+end
+
+# Attributes of a surface for a given EGL display
+class EGLSurfaceAttribs
+       var display: EGLDisplay
+       var surface: EGLSurface
+
+       fun height: Int do return display.query_surface(surface, "3056".to_hex)
+       fun width: Int do return display.query_surface(surface, "3057".to_hex)
+       fun largest_pbuffer: Int do return display.query_surface(surface, "3058".to_hex)
+       fun texture_format: Int do return display.query_surface(surface, "3080".to_hex)
+       fun texture_target: Int do return display.query_surface(surface, "3081".to_hex)
+       fun mipmap_texture: Int do return display.query_surface(surface, "3082".to_hex)
+       fun mipmap_level: Int do return display.query_surface(surface, "3083".to_hex)
+       fun render_buffer: Int do return display.query_surface(surface, "3086".to_hex)
+       fun vg_colorspace: Int do return display.query_surface(surface, "3087".to_hex)
+       fun vg_alpha_format: Int do return display.query_surface(surface, "3088".to_hex)
+       fun horizontal_resolution: Int do return display.query_surface(surface, "3090".to_hex)
+       fun vertical_resolution: Int do return display.query_surface(surface, "3091".to_hex)
+       fun pixel_aspect_ratio: Int do return display.query_surface(surface, "3092".to_hex)
+       fun swap_behavior: Int do return display.query_surface(surface, "3093".to_hex)
+       fun multisample_resolve: Int do return display.query_surface(surface, "3099".to_hex)
+end
+
+extern class EGLError `{ EGLint `}
+       fun is_success: Bool `{ return recv == EGL_SUCCESS; `}
+
+       fun is_not_initialized: Bool `{ return recv == EGL_NOT_INITIALIZED; `}
+       fun is_bad_access: Bool `{ return recv == EGL_BAD_ACCESS; `}
+       fun is_bad_alloc: Bool `{ return recv == EGL_BAD_ALLOC; `}
+       fun is_bad_attribute: Bool `{ return recv == EGL_BAD_ATTRIBUTE; `}
+       fun is_bad_config: Bool `{ return recv == EGL_BAD_CONFIG; `}
+       fun is_bad_context: Bool `{ return recv == EGL_BAD_CONTEXT; `}
+       fun is_bad_current_surface: Bool `{ return recv == EGL_BAD_CURRENT_SURFACE; `}
+       fun is_bad_display: Bool `{ return recv == EGL_BAD_DISPLAY; `}
+       fun is_bad_match: Bool `{ return recv == EGL_BAD_MATCH; `}
+       fun is_bad_native_pixmap: Bool `{ return recv == EGL_BAD_NATIVE_PIXMAP; `}
+       fun is_bad_native_window: Bool `{ return recv == EGL_BAD_NATIVE_WINDOW; `}
+       fun is_bad_parameter: Bool `{ return recv == EGL_BAD_PARAMETER; `}
+       fun is_bad_surface: Bool `{ return recv == EGL_BAD_SURFACE; `}
+       fun is_context_lost: Bool `{ return recv == EGL_CONTEXT_LOST; `}
+
+       redef fun to_s
+       do
+               if is_not_initialized then return "Not initialized"
+               if is_bad_access then return "Bad access"
+               if is_bad_alloc then return "Bad allocation"
+               if is_bad_attribute then return "Bad attribute"
+               if is_bad_config then return "Bad configuration"
+               if is_bad_context then return "Bad context"
+               if is_bad_current_surface then return "Bad current surface"
+               if is_bad_display then return "Bad display"
+               if is_bad_match then return "Bad match"
+               if is_bad_native_pixmap then return "Bad native pixmap"
+               if is_bad_native_window then return "Bad native window"
+               if is_bad_parameter then return "Bad parameter"
+               if is_bad_surface then return "Bad surface"
+               if is_context_lost then return "Context lost"
+               return "Unknown error" # this is not good
+       end
+end
+
+extern class EGLContextAttribute `{ EGLint `}
+       new buffer_size `{ return EGL_BUFFER_SIZE; `}
+       new alpha_size `{ return EGL_ALPHA_SIZE; `}
+       new blue_size `{ return EGL_BLUE_SIZE; `}
+       new green_size `{ return EGL_GREEN_SIZE; `}
+       new red_size `{ return EGL_RED_SIZE; `}
+       new depth_size `{ return EGL_DEPTH_SIZE; `}
+       new stencil_size `{ return EGL_STENCIL_SIZE; `}
+       new config_caveat `{ return EGL_CONFIG_CAVEAT; `}
+       new config_id `{ return EGL_CONFIG_ID; `}
+       new level `{ return EGL_LEVEL; `}
+       new max_pbuffer_height `{ return EGL_MAX_PBUFFER_HEIGHT; `}
+       new max_pbuffer_pixels `{ return EGL_MAX_PBUFFER_PIXELS; `}
+       new max_pbuffer_width `{ return EGL_MAX_PBUFFER_WIDTH; `}
+       new native_renderable `{ return EGL_NATIVE_RENDERABLE; `}
+       new native_visual_id `{ return EGL_NATIVE_VISUAL_ID; `}
+       new native_visual_type `{ return EGL_NATIVE_VISUAL_TYPE; `}
+       new samples `{ return EGL_SAMPLES; `}
+       new sample_buffers `{ return EGL_SAMPLE_BUFFERS; `}
+       new surface_type `{ return EGL_SURFACE_TYPE; `}
+       new transparent_type `{ return EGL_TRANSPARENT_TYPE; `}
+       new transparent_blue_value `{ return EGL_TRANSPARENT_BLUE_VALUE; `}
+       new transparent_green_value `{ return EGL_TRANSPARENT_GREEN_VALUE; `}
+       new transparent_red_value `{ return EGL_TRANSPARENT_RED_VALUE; `}
+       new bind_to_texture_rgb `{ return EGL_BIND_TO_TEXTURE_RGB; `}
+       new bind_to_texture_rgba `{ return EGL_BIND_TO_TEXTURE_RGBA; `}
+       new min_swap_interval `{ return EGL_MIN_SWAP_INTERVAL; `}
+       new max_swap_interval `{ return EGL_MAX_SWAP_INTERVAL; `}
+       new limunance_size `{ return EGL_LUMINANCE_SIZE; `}
+       new alpha_mask_size `{ return EGL_ALPHA_MASK_SIZE; `}
+       new color_buffer_type `{ return EGL_COLOR_BUFFER_TYPE; `}
+       new renderable_type `{ return EGL_RENDERABLE_TYPE; `}
+       new match_native_pixmap `{ return EGL_MATCH_NATIVE_PIXMAP; `}
+       new conformant `{ return EGL_CONFORMANT; `}
+
+       # Attrib list terminator
+       new none `{ return EGL_NONE; `}
+end
+
+# Utility class to choose an EGLConfig
+class EGLConfigChooser
+       var array = new Array[Int]
+       var closed = false
+       protected var inserted_attribs = new Array[Int]
+
+       protected fun insert_attrib_key(key: Int)
+       do
+               assert not inserted_attribs.has(key) else
+                       print "Duplicate attrib passed to EGLConfigChooser"
+               end
+               array.add key
+       end
+
+       protected fun insert_attrib_with_val(key, val: Int)
+       do
+               insert_attrib_key key
+               array.add val
+       end
+
+       fun close do
+               insert_attrib_key "3038".to_hex
+               closed = true
+       end
+
+       fun surface_type=(flag: Int) do insert_attrib_with_val("3033".to_hex, flag)
+       fun surface_type_egl do surface_type = 4
+
+       fun blue_size=(size: Int) do insert_attrib_with_val("3022".to_hex, size)
+       fun green_size=(size: Int) do insert_attrib_with_val("3023".to_hex, size)
+       fun red_size=(size: Int) do insert_attrib_with_val("3024".to_hex, size)
+
+       fun alpha_size=(size: Int) do insert_attrib_with_val("3021".to_hex, size)
+       fun depth_size=(size: Int) do insert_attrib_with_val("3025".to_hex, size)
+       fun stencil_size=(size: Int) do insert_attrib_with_val("3026".to_hex, size)
+       fun sample_buffers=(size: Int) do insert_attrib_with_val("3031".to_hex, size)
+
+       fun choose(display: EGLDisplay): nullable Array[EGLConfig]
+       do
+               assert closed else print "EGLConfigChooser not closed."
+               return display.choose_configs(array)
+       end
+end
+
+redef class Object
+       private fun report_egl_error(cmsg: NativeString)
+       do
+               var msg = cmsg.to_s
+               print "libEGL error: {msg}"
+       end
+end
+
+protected fun egl_bind_opengl_api: Bool `{ return eglBindAPI(EGL_OPENGL_API); `}
+protected fun egl_bind_opengl_es_api: Bool `{ return eglBindAPI(EGL_OPENGL_ES_API); `}
+protected fun egl_bind_openvg_api: Bool `{ return eglBindAPI(EGL_OPENVG_API); `}
diff --git a/lib/glesv2.nit b/lib/glesv2.nit
new file mode 100644 (file)
index 0000000..fd33d63
--- /dev/null
@@ -0,0 +1,232 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# OpenGL graphics rendering library for embedded systems, version 2.0.
+#
+# Most services of this module are a direct wrapper of the underlying
+# C library. If a method or class is not documented in Nit, refer to
+# the official documentation by the Khronos Group at:
+# http://www.khronos.org/opengles/sdk/docs/man/
+module glesv2 is pkgconfig("glesv2")
+
+in "C Header" `{
+       #include <GLES2/gl2.h>
+`}
+
+# Opengl ES program to which we attach shaders
+extern class GLProgram `{GLuint`}
+       new `{ return glCreateProgram(); `}
+
+       fun is_ok: Bool `{ return glIsProgram(recv); `}
+
+       fun attach_shader(shader: GLShader) `{ glAttachShader(recv, shader); `}
+
+       fun bind_attrib_location(index: Int, name: String) import String.to_cstring `{
+               GLchar *c_name = String_to_cstring(name);
+               glBindAttribLocation(recv, index, c_name);
+       `}
+
+       fun attrib_location(name: String): Int import String.to_cstring `{
+               GLchar *c_name = String_to_cstring(name);
+               return glGetAttribLocation(recv, c_name);
+       `}
+
+       fun query(pname: Int): Int `{
+               int val;
+               glGetProgramiv(recv, pname, &val);
+               return val;
+       `}
+
+       fun link `{ glLinkProgram(recv); `}
+       fun is_linked: Bool do return query("8B82".to_hex) != 0
+
+       fun use `{ glUseProgram(recv); `}
+
+       fun delete `{ glDeleteProgram(recv); `}
+       fun is_deleted: Bool do return query("8B80".to_hex) != 0
+
+       fun validate `{ glValidateProgram(recv); `}
+       fun is_validated: Bool do return query("8B83".to_hex) != 0
+
+       fun info_log: String import NativeString.to_s `{
+               int size;
+               glGetProgramiv(recv, GL_INFO_LOG_LENGTH, &size);
+               GLchar *msg = malloc(size);
+               glGetProgramInfoLog(recv, size, NULL, msg);
+               return NativeString_to_s(msg);
+       `}
+end
+
+# Abstract OpenGL ES shader object, implemented by `GLFragmentShader` and `GLVertexShader`
+extern class GLShader `{GLuint`}
+       fun source=(code: String) import String.to_cstring, String.length `{
+               GLchar *c_code = String_to_cstring(code);
+               glShaderSource(recv, 1, (const GLchar * const*)&c_code, NULL);
+       `}
+       fun source: nullable String import NativeString.to_s `{
+               int size;
+               glGetShaderiv(recv, GL_SHADER_SOURCE_LENGTH, &size);
+               if (size == 0) return NULL;
+               GLchar *code = malloc(size);
+               glGetShaderSource(recv, size, NULL, code);
+               return NativeString_to_s(code);
+       `}
+
+       protected fun query(pname: Int): Int `{
+               int val;
+               glGetShaderiv(recv, pname, &val);
+               return val;
+       `}
+
+       fun compile `{ glCompileShader(recv); `}
+       fun is_compiled: Bool do return query("8B81".to_hex) != 0
+
+       fun delete `{ glDeleteShader(recv); `}
+       fun is_deleted: Bool do return query("8B80".to_hex) != 0
+
+       fun is_ok: Bool `{ return glIsShader(recv); `}
+
+       fun info_log: String import NativeString.to_s `{
+               int size;
+               glGetShaderiv(recv, GL_INFO_LOG_LENGTH, &size);
+               GLchar *msg = malloc(size);
+               glGetShaderInfoLog(recv, size, NULL, msg);
+               return NativeString_to_s(msg);
+       `}
+
+end
+
+extern class GLFragmentShader 
+       super GLShader
+
+       new `{ return glCreateShader(GL_FRAGMENT_SHADER); `}
+end
+
+extern class GLVertexShader
+       super GLShader
+       
+       new `{ return glCreateShader(GL_VERTEX_SHADER); `}
+end
+
+# An array of `Float` associated to a program variable
+class VertexArray
+       var index: Int
+       var count: Int
+       protected var glfloat_array: GLfloatArray
+
+       init(index, count: Int, array: Array[Float])
+       do
+               self.index = index
+               self.count = count
+               self.glfloat_array = new GLfloatArray(array)
+       end
+
+       fun attrib_pointer do attrib_pointer_intern(index, count, glfloat_array)
+       private fun attrib_pointer_intern(index, count: Int, array: GLfloatArray) `{
+               glVertexAttribPointer(index, count, GL_FLOAT, GL_FALSE, 0, array);
+       `}
+
+       fun enable do enable_intern(index)
+       private fun enable_intern(index: Int) `{ glEnableVertexAttribArray(index); `}
+
+       fun draw_arrays_triangles do draw_arrays_triangles_intern(index, count)
+       private fun draw_arrays_triangles_intern(index, count: Int) `{
+               glDrawArrays(GL_TRIANGLES, index, count);
+       `}
+end
+
+# Low level array of `Float`
+extern class GLfloatArray `{GLfloat *`}
+       new (array: Array[Float]) import Array[Float].length, Array[Float].[] `{
+               int i;
+               int len = Array_of_Float_length(array);
+               GLfloat *vertex_array = malloc(sizeof(GLfloat)*len);
+               for (i = 0; i < len; i ++) vertex_array[i] = Array_of_Float__index(array, i);
+               return vertex_array;
+       `}
+end
+
+extern class GLError `{ GLenum `}
+       fun is_ok: Bool do return is_no_error
+       fun is_no_error: Bool `{ return recv == GL_NO_ERROR; `}
+       fun is_invalid_enum: Bool `{ return recv == GL_INVALID_ENUM; `}
+       fun is_invalid_value: Bool `{ return recv == GL_INVALID_VALUE; `}
+       fun is_invalid_operation: Bool `{ return recv == GL_INVALID_OPERATION; `}
+       fun is_invalid_framebuffer_operation: Bool `{ return recv == GL_INVALID_FRAMEBUFFER_OPERATION; `}
+       fun is_out_of_memory: Bool `{ return recv == GL_OUT_OF_MEMORY; `}
+
+       redef fun to_s
+       do
+               if is_no_error then return "No error"
+               if is_invalid_enum then return "Invalid enum"
+               if is_invalid_value then return "Invalid value"
+               if is_invalid_operation then return "Invalid operation"
+               if is_invalid_framebuffer_operation then return "invalid framebuffer operation"
+               if is_out_of_memory then return "Out of memory"
+               return "Truely unknown error"
+       end
+end
+
+protected fun gl_clear_color(r, g, b, a: Float) `{ glClearColor(r, g, b, a); `}
+protected fun gl_viewport(x, y, width, height: Int) `{ glViewport(x, y, width, height); `} 
+protected fun gl_vertex_attrib_pointer_int(index, length: Int, normalize: Bool, stride: Int, vertex: Array[Int]) import Array[Int].length, Array[Int].intern_items `{
+       int* c_vertex = Array_of_Int_intern_items(vertex);
+       glVertexAttribPointer(index, length, GL_INT, normalize, stride, c_vertex);
+`}
+protected fun gl_vertex_attrib_pointer_float(index, length: Int, normalize: Bool, stride: Int, vertex: Array[Float]) import Array[Float].length, Array[Float].intern_items `{
+       int* c_vertex = Array_of_Float_intern_items(vertex);
+       glVertexAttribPointer(index, length, GL_FLOAT, normalize, stride, c_vertex);
+`}
+
+# Direct call to `glClear`, call with a combinaison of `gl_clear_color_buffer`,
+# `gl_stencil_buffer_bit` and `gl_color_buffer_bit`.
+private fun gl_clear(flag: Int) `{ glClear(flag); `}
+
+protected fun gl_depth_buffer_bit: Int do return once "0100".to_hex
+protected fun gl_stencil_buffer_bit: Int do return once "0400".to_hex
+protected fun gl_color_buffer_bit: Int do return once "4000".to_hex
+
+protected fun gl_clear_color_buffer do gl_clear(gl_color_buffer_bit)
+protected fun gl_clear_depth_buffer do gl_clear(gl_depth_buffer_bit)
+protected fun gl_clear_stencil_buffer do gl_clear(gl_stencil_buffer_bit)
+
+protected fun gl_error: GLError `{ return glGetError(); `}
+protected fun assert_no_gl_error
+do
+       var error = gl_error
+       if not error.is_ok then
+               print "GL error: {error}"
+               abort
+       end
+end
+
+private fun gl_get_bool(key: Int): Bool `{
+       GLboolean val;
+       glGetBooleanv(GL_SHADER_COMPILER, &val);
+       return val == GL_TRUE;
+`}
+private fun gl_get_float(key: Int): Float `{
+       GLfloat val;
+       glGetFloatv(key, &val);
+       return val;
+`}
+private fun gl_get_int(key: Int): Int `{
+       GLint val;
+       glGetIntegerv(key, &val);
+       return val;
+`}
+
+fun gl_shader_compiler: Bool do return gl_get_bool("8DFA".to_hex)
index 93e8a95..51c3412 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Defines abstract classes for user inputs
+# Defines abstract classes for user and general inputs to the application.
+# Implemented independantly for each platforms and technologies.
 module input_events
 
-# General type of inputs
+# Input to the App, propagated through `App::input`.
 interface InputEvent
 end
 
index 094905b..7fb8382 100644 (file)
@@ -38,7 +38,7 @@ extern SDLDisplay in "C" `{SDL_Surface *`}
 
        redef type I: SDLImage
 
-        # Initialize a surface with width and height
+       # Initialize a surface with width and height
        new ( w, h: Int) is extern `{
                SDL_Init(SDL_INIT_VIDEO);
 
@@ -53,7 +53,7 @@ extern SDLDisplay in "C" `{SDL_Surface *`}
                return SDL_SetVideoMode( w, h, 24, SDL_HWSURFACE );
        `}
 
-        # Destroy the surface
+       # Destroy the surface
        fun destroy is extern `{
        if ( SDL_WasInit( SDL_INIT_VIDEO ) )
                SDL_Quit();
@@ -155,7 +155,7 @@ extern SDLDisplay in "C" `{SDL_Surface *`}
        # Set the position of the cursor to x,y
        fun warp_mouse( x,y: Int ) `{ SDL_WarpMouse( x, y ); `}
 
-        # Show or hide the cursor
+       # Show or hide the cursor
        fun show_cursor( show: Bool ) `{ SDL_ShowCursor( show ); `}
 end
 
@@ -199,7 +199,7 @@ extern SDLImage in "C" `{SDL_Surface*`} # TODO remove
                return NULL;
        `}
 
-        # Copy of an existing SDLImage
+       # Copy of an existing SDLImage
        new copy_of( image: SDLImage ) is extern `{
                SDL_Surface *new_image = SDL_CreateRGBSurface( image->flags, image->w, image->h, 24,
                                                          0, 0, 0, 0 );
@@ -217,7 +217,7 @@ extern SDLImage in "C" `{SDL_Surface*`} # TODO remove
        # Save the image into the specified file
        fun save_to_file( path: String ) is extern import String::to_cstring `{ `}
 
-        # Destroy the image and free the memory
+       # Destroy the image and free the memory
        redef fun destroy is extern `{ SDL_FreeSurface( recv ); `}
 
        redef fun width: Int is extern `{ return recv->w; `}
@@ -228,7 +228,7 @@ end
 
 # A simple rectangle
 extern SDLRectangle in "C" `{SDL_Rect*`}
-        # Constructor with x,y positions width and height of the rectangle
+       # Constructor with x,y positions width and height of the rectangle
        new ( x: Int, y: Int, w: Int, h: Int ) is extern `{
                SDL_Rect *rect = malloc( sizeof( SDL_Rect ) );
                rect->x = (Sint16)x;
@@ -346,10 +346,10 @@ class SDLKeyEvent
                end
        end
 
-        # Return true if the key is down, false otherwise
+       # Return true if the key is down, false otherwise
        redef fun is_down do return down
 
-        # Return true if the key is the up arrow
+       # Return true if the key is the up arrow
        redef fun is_arrow_up do return key_name == "up"
        # Return true if the key is the left arrow
        redef fun is_arrow_left do return key_name == "left"
@@ -430,7 +430,7 @@ extern SDLFont in "C" `{TTF_Font *`}
                return TTF_FontLineSkip( recv );
        `}
 
-        # Return true is the font used fixed width for each char
+       # Return true is the font used fixed width for each char
        fun is_fixed_width: Bool is extern `{
                return TTF_FontFaceIsFixedWidth( recv );
        `}
@@ -468,3 +468,26 @@ extern SDLFont in "C" `{TTF_Font *`}
                        return w;
        `}
 end
+
+# Information on the SDL window
+# Used in other modules to get window handle
+extern class SDLSystemWindowManagerInfo `{SDL_SysWMinfo *`}
+
+       new `{
+               SDL_SysWMinfo *val = malloc(sizeof(SDL_SysWMinfo));
+
+               SDL_VERSION(&val->version);
+
+               if(SDL_GetWMInfo(val) <= 0) {
+                       printf("Unable to get window handle");
+                       return 0;
+               }
+
+               return val;
+       `}
+
+       # Returns the handle of this window on a X11 window system
+       fun x11_window_handle: Pointer `{
+               return (void*)recv->info.x11.window;
+       `}
+end
index aea40bb..fc6090f 100644 (file)
@@ -230,4 +230,20 @@ class POSetElement[E: Object]
        do
                return t != self.element and self.tos.has(t)
        end
+
+       # The length of the shortest path to the root of the poset hierarchy
+       fun depth: Int do
+               if direct_greaters.is_empty then
+                       return 0
+               end
+               var min = -1
+               for p in direct_greaters do
+                       var d = poset[p].depth + 1
+                       if min == -1 or d < min then
+                               min = d
+                       end
+               end
+               return min
+
+       end
 end
index cbb8ac6..64094f7 100644 (file)
@@ -215,6 +215,21 @@ redef class String
        # Remove a file, return true if success
        fun file_delete: Bool do return to_cstring.file_delete
 
+       # Copy content of file at `self` to `dest`
+       fun file_copy_to(dest: String)
+       do
+               var input = new IFStream.open(self)
+               var output = new OFStream.open(dest)
+
+               while not input.eof do
+                       var buffer = input.read(1024)
+                       output.write buffer
+               end
+
+               input.close
+               output.close
+       end
+
        # remove the trailing extension "ext"
        fun strip_extension(ext: String): String
        do
index 5d73c8e..340222a 100644 (file)
@@ -21,6 +21,7 @@ in "C header" `{
 `}
 
 redef class Int
+       # Returns a random `Int` in `[0 .. self[`.
        fun rand: Int is extern "kernel_Int_Int_rand_0"
        fun bin_and(i: Int): Int is extern "kernel_Int_Int_binand_0"
        fun bin_or(i: Int): Int is extern "kernel_Int_Int_binor_0"
@@ -44,6 +45,7 @@ redef class Float
        fun log: Float is extern "kernel_Float_Float_log_0"
        fun exp: Float is extern "kernel_Float_Float_exp_0"
        
+       # Returns a random `Float` in `[0.0 .. self[`.
        fun rand: Float is extern "kernel_Float_Float_rand_0"
        fun hypot_with( b : Float ) : Float is extern "hypotf"
 end
index b9ee718..00bb14f 100644 (file)
@@ -883,11 +883,6 @@ private class FlatBufferCharView
 
        redef type SELFTYPE: Buffer
 
-       init(tgt: Buffer)
-       do
-               self.target = tgt
-       end
-
        redef fun [](index) do return target._items[index]
 
        redef fun []=(index, item)
diff --git a/lib/x11.nit b/lib/x11.nit
new file mode 100644 (file)
index 0000000..b4f51d5
--- /dev/null
@@ -0,0 +1,34 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Serices from the X11 library
+module x11 is pkgconfig("x11")
+
+# Open the current display from the environment variables
+#
+# See <http://www.x.org/releases/X11R7.7/doc/man/man3/XOpenDisplay.3.xhtml>
+fun x_open_default_display: Pointer `{
+       return (void*)(long)XOpenDisplay(NULL);
+`}
+
+# Open a specific display
+#
+# `name` is in the format: "hostname:number.screen_number"
+# 
+# See <http://www.x.org/releases/X11R7.7/doc/man/man3/XOpenDisplay.3.xhtml>
+fun x_open_display(name: String): Pointer import String.to_cstring `{
+       return (void*)XOpenDisplay(String_to_cstring(name));
+`}
diff --git a/share/nitdoc/ZeroClipboard.swf b/share/nitdoc/ZeroClipboard.swf
deleted file mode 100644 (file)
index 8b707aa..0000000
Binary files a/share/nitdoc/ZeroClipboard.swf and /dev/null differ
similarity index 81%
rename from share/nitdoc/styles/Nitdoc.GitHub.css
rename to share/nitdoc/css/Nitdoc.GitHub.css
index c4cd574..bba519c 100644 (file)
@@ -21,9 +21,9 @@
  */\r
 \r
 #nitdoc-github-li {\r
-       float: right;\r
+       float: left;\r
        padding: 0;\r
-       margin: -2px 15px 5px 5px;\r
+       margin: -2px 5px 5px 15px;\r
 }\r
 \r
 #nitdoc-github-li.current {\r
@@ -40,7 +40,7 @@
        position: absolute;\r
        width : 220px;\r
        margin-top: 2px;\r
-       margin-left: -208px;\r
+       margin-left: -10px;\r
        display: block;\r
        padding: 10px;\r
        text-align: left;\r
@@ -68,8 +68,7 @@
        border-style: solid;\r
        border-width: 7px;\r
        top: -7px;\r
-       left: 50%;\r
-       margin-left: 90px;\r
+       margin-left: 2px;\r
        border-bottom-color: #999;\r
        border-bottom-color: rgba(0, 0, 0, 0.25);\r
        border-top-width: 0;\r
        margin-bottom: 20px;\r
 }\r
 \r
+\r
 #nitdoc-github-loginbox a.nitdoc-github-loginbox-githublink {\r
        display: block;\r
        margin: 10px;\r
  * Nitdoc Github buttons\r
  */\r
 \r
-button.nitdoc-github-button {\r
+.nitdoc-github-button {\r
        display: inline-block;\r
        cursor: pointer;\r
        background-color: #92C929;\r
@@ -177,77 +177,43 @@ button.nitdoc-github-button img {
        width: 16px;\r
 }\r
 \r
-/*\r
- * Modal Box\r
- */\r
-\r
-.nitdoc-github-fade {\r
-       background: #000;\r
-       position: fixed; left: 0; top: 0;\r
-       width: 100%; height: 100%;\r
-       opacity: .80;\r
-       filter: alpha(opacity=80);\r
-       z-index: 9999;\r
-}\r
+/* Comment editing */\r
 \r
-.nitdoc-github-modal {\r
+.nitdoc-github-commentbox {\r
+       margin: 1em 5px;\r
+       border: 1px solid #eee;\r
+       padding: 1em;\r
        background: #fff;\r
-       padding: 20px;\r
-       border: 1px solid #ddd;\r
-       float: left;\r
-       position: fixed;\r
-       z-index: 99999;\r
-       /* fix Box Shadow CSS3 */\r
-       -webkit-box-shadow: 0px 0px 20px #000;\r
-       -moz-box-shadow: 0px 0px 20px #000;\r
-       box-shadow: 0px 0px 20px #000;\r
-       /* round corners CSS3 */\r
-       -webkit-border-radius: 2px;\r
-       -moz-border-radius: 2px;\r
-       border-radius: 2px;\r
-       text-align: left;\r
+       -moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\r
+       -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\r
+       box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);\r
 }\r
 \r
-.nitdoc-github-buttons, .nitdoc-github-modal h3 {\r
-       text-align: center;\r
+.nitdoc-github-commentbox h3 {\r
+       margin: 0;\r
 }\r
 \r
-.nitdoc-github-modal.nitdoc-github-error h3 {\r
-       color: red;\r
-}\r
-\r
-.nitdoc-github-modal textarea {\r
-       min-width: 300px;\r
-       width: 100%;\r
+.nitdoc-github-commentbox-buttons {\r
+       text-align: right;\r
 }\r
 \r
-.nitdoc-github-modal button {\r
-       line-height: 20px;\r
+.nitdoc-github-commentbox dl {\r
        margin-bottom: 0;\r
-       padding: 4px 12px;\r
-       margin-top: 20px;\r
 }\r
 \r
-.nitdoc-github-close {\r
-       float: right;\r
-       margin: -22px -17px 0 0;\r
-       cursor: pointer;\r
-       font-size: 1.3em;\r
-       font-weight: bold;\r
-       text-transform: lowercase;\r
+.nitdoc-github-commentbox dt {\r
+       margin-bottom: 0.5em;\r
 }\r
 \r
-/* Comment editing */\r
-\r
-.nitdoc-github-commentbox {\r
-       text-align: right;\r
+.nitdoc-github-commentbox dd {\r
+       margin: 0 0 1em 0;\r
 }\r
 \r
 .nitdoc-github-commentbox textarea {\r
+       display: block;\r
        font-family: monospace;\r
        font-size: 1em;\r
        width: 100%;\r
-       margin-top: 1em;\r
        padding: 4px;\r
        padding-left: 11px;\r
        overflow-y: hidden;\r
@@ -287,3 +253,54 @@ a.nitdoc-github-update {
        color: orange;\r
        cursor: pointer;\r
 }\r
+\r
+.nitdoc-dialog h4 {\r
+       font-weight: bold;\r
+}\r
+\r
+/* hljs */\r
+\r
+.hljs.nitcode {\r
+       padding-left: 10px;\r
+}\r
+\r
+.hljs-comment, .hljs-comment-block {\r
+       color: #777;\r
+}\r
+\r
+.hljs-keyword {\r
+       color: #000;\r
+       font-weight: bold;\r
+}\r
+\r
+.hljs-title {\r
+       font-weight: bold;\r
+}\r
+\r
+.hljs-module {\r
+       color: #3762E4;\r
+}\r
+\r
+.hljs-class .hljs-title {\r
+       color: #3762E4;\r
+}\r
+\r
+.hljs-type {\r
+       color: #3762E4;\r
+}\r
+\r
+.hljs-string {\r
+       color: #8F1546;\r
+}\r
+\r
+.hljs-subst {\r
+       color: #9E6BEB;\r
+}\r
+\r
+.hljs-fun .hljs-title {\r
+       color: #3762E4;\r
+}\r
+\r
+.hljs-char, .hljs-number {\r
+       color: #009999;\r
+}\r
diff --git a/share/nitdoc/css/Nitdoc.ModalBox.css b/share/nitdoc/css/Nitdoc.ModalBox.css
new file mode 100644 (file)
index 0000000..bf9f9aa
--- /dev/null
@@ -0,0 +1,110 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+   Documentation generator for the nit language.\r
+   Generate API documentation in HTML format from nit source code.\r
+*/\r
+\r
+/* \r
+ * Nitdoc ModalBox style\r
+ */\r
+\r
+.nitdoc-dialog-fade {\r
+       background: #000;\r
+       position: fixed; left: 0; top: 0;\r
+       width: 100%; height: 100%;\r
+       opacity: .80;\r
+       filter: alpha(opacity=80);\r
+       z-index: 9999;\r
+}\r
+\r
+.nitdoc-dialog {\r
+       background: #fff;\r
+       border: 1px solid #ddd;\r
+       float: left;\r
+       position: fixed;\r
+       z-index: 99999;\r
+       -webkit-box-shadow: 0px 0px 20px #000;\r
+       -moz-box-shadow: 0px 0px 20px #000;\r
+       box-shadow: 0px 0px 20px #000;\r
+       -webkit-border-radius: 2px;\r
+       -moz-border-radius: 2px;\r
+       border-radius: 2px;\r
+       text-align: left;\r
+       min-width: 300px;\r
+}\r
+\r
+.nitdoc-dialog-header {\r
+       padding: 10px 10px 10px 20px;\r
+       background: #f1f1f1;\r
+       border-bottom: 1px solid #ddd;\r
+}\r
+\r
+.nitdoc-dialog-error .nitdoc-dialog-header {\r
+       background: #C92020;\r
+}\r
+.nitdoc-dialog-error .nitdoc-dialog-header h3 {\r
+       color: white;\r
+}\r
+\r
+.nitdoc-dialog h3 {\r
+       display: inline;\r
+       margin: 0;\r
+}\r
+\r
+.nitdoc-dialog-content {\r
+       max-height: 450px;\r
+       overflow-y: scroll;\r
+       padding: 10px;\r
+}\r
+\r
+.nitdoc-dialog-buttons {\r
+       text-align: right;\r
+       padding: 5px;\r
+       border-top: 1px solid #ddd;\r
+}\r
+\r
+.nitdoc-dialog textarea {\r
+       min-width: 300px;\r
+       width: 100%;\r
+}\r
+\r
+.nitdoc-dialog button {\r
+       cursor: pointer;\r
+       border-radius: 2px;\r
+       -moz-border-radius: 2px;\r
+       -webkit-border-radius: 2px;\r
+       font-size: 14px;\r
+       padding: 5px 7px 5px 7px;\r
+       text-align: center;\r
+       background: #eee;\r
+       color: #333;\r
+       border: 1px solid #ddd;\r
+       font-weight: bold;\r
+}\r
+\r
+.nitdoc-dialog button:hover {\r
+       background: #0D8921;\r
+       color: #fff;\r
+       border: 1px solid #1d7900;\r
+}\r
+\r
+.nitdoc-dialog-close {\r
+       float: right;\r
+       padding: 5px;\r
+       margin: 0px;\r
+       line-height: 10px;\r
+       text-transform: lowercase;\r
+}\r
+\r
similarity index 89%
rename from share/nitdoc/styles/Nitdoc.QuickSearch.css
rename to share/nitdoc/css/Nitdoc.QuickSearch.css
index b0a434c..42b3925 100644 (file)
@@ -55,7 +55,6 @@
        overflow: hidden;\r
        line-height: 22px;\r
        padding: 2px;\r
-       width: 25%;\r
 }\r
 \r
 #nitdoc-qs-table td.nitdoc-qs-sub {\r
@@ -65,8 +64,7 @@
 \r
 #nitdoc-qs-table td.nitdoc-qs-info {\r
        color: #0D8921;\r
-       font-size: small;\r
-       width: 75%;\r
+       font-size: smaller;\r
        text-align: right;\r
 }\r
 \r
@@ -76,8 +74,7 @@
        line-height: 15px;\r
 }\r
 \r
-#nitdoc-qs-table tr.nitdoc-qs-overflow-up td,\r
-#nitdoc-qs-table tr.nitdoc-qs-overflow-down td {\r
+#nitdoc-qs-table tr.nitdoc-qs-overflow td {\r
        text-align: center;\r
        font-size:      x-small;\r
        line-height: 10px;\r
similarity index 71%
rename from share/nitdoc/styles/Nitdoc.UI.css
rename to share/nitdoc/css/Nitdoc.UI.css
index 35c5343..17b248d 100644 (file)
@@ -31,33 +31,6 @@ a.nitdoc-ui-fold {
        font-size: 120%;\r
 }\r
 \r
-/* Copy signature to clipboard */\r
-\r
-button.nitdoc-ui-copy.zeroclipboard-is-active {\r
-       border-color: #0D8921;\r
-}\r
-\r
-button.nitdoc-ui-copy {\r
-       visibility: hidden;\r
-       vertical-align: middle;\r
-       margin: -2px 0px 0px 10px;\r
-       width: 22px;\r
-       height: 19px;\r
-       padding: 1px;\r
-       cursor: pointer;\r
-       background: #eee;\r
-       border: 1px solid #ccc;\r
-       box-shadow: none;\r
-}\r
-\r
-button.nitdoc-ui-copy img {\r
-       width: 16px;\r
-}\r
-\r
-article:hover > .signature button.nitdoc-ui-copy, button.nitdoc-ui-copy.zeroclipboard-is-hover {\r
-       visibility: visible;\r
-}\r
-\r
 /* Search page field */\r
 \r
 .nitdoc-ui-searchpage-field {\r
similarity index 92%
rename from share/nitdoc/styles/main.css
rename to share/nitdoc/css/main.css
index d617b92..1d9ddcf 100644 (file)
@@ -76,7 +76,7 @@ body {
 \r
 header {\r
        position: fixed;\r
-       z-index: 600;\r
+       z-index: 50;\r
        left: 0;\r
        right: 0;\r
 }\r
@@ -88,7 +88,7 @@ header {
 \r
 .sidebar {\r
        position: fixed;\r
-       z-index: 500;\r
+       z-index: 10;\r
        top: 50px;\r
        bottom: 1em;\r
        width: 250px;\r
@@ -101,7 +101,7 @@ header {
 \r
 .content {\r
        position: fixed;\r
-       z-index: 500;\r
+       z-index: 10;\r
        top: 50px;\r
        bottom: 1em;\r
        left: 0;\r
@@ -123,7 +123,7 @@ header {
 \r
 footer {\r
        position: fixed;\r
-       z-index: 500;\r
+       z-index: 50;\r
        bottom: 0;\r
        width: 100%;\r
 }\r
@@ -422,22 +422,31 @@ nav.main input[type=text] {
 \r
 /* New comments style */\r
 \r
-.content .nitdoc {\r
+.nitdoc {\r
   background: #F7F7F7;\r
   padding: 5px;\r
   color: black;\r
   overflow: auto;\r
 }\r
 \r
-.content .nitdoc pre {\r
+.nitdoc pre {\r
   background: #EEE;\r
 }\r
 \r
-.content .nitdoc code {\r
+.nitdoc code {\r
   background: #DDD;\r
   padding: 0 1px;\r
 }\r
 \r
+.nitdoc pre code {\r
+       background: none;\r
+}\r
+\r
+.nitdoc .synopsys, .nitdoc p:first-child {\r
+       font-weight: bold;\r
+       color: #6c6c6c;\r
+}\r
+\r
 .rawcode {\r
 }\r
 \r
diff --git a/share/nitdoc/js/lib/github-api.js b/share/nitdoc/js/lib/github-api.js
new file mode 100644 (file)
index 0000000..f03188a
--- /dev/null
@@ -0,0 +1,295 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+   Documentation generator for the nit language.\r
+   Generate API documentation in HTML format from nit source code.\r
+*/\r
+\r
+/* \r
+ * GitHub API wrapper for github plugin\r
+ */\r
+define([\r
+       "jquery",\r
+       "utils"\r
+], function($, Utils) {\r
+       return {\r
+\r
+               // try to login the user to github API\r
+               login: function(user) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "GET",\r
+                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo,\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function() {\r
+                                       res = true;\r
+                               }\r
+                       });\r
+                       user.infos = this.getUserInfos(user);\r
+                       user.signedOff = this.getSignedOff(user)\r
+                       return res;\r
+               },\r
+\r
+               // request for user github account infos\r
+               getUserInfos: function(user) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "GET",\r
+                                       url: "https://api.github.com/users/" + user.login,\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               // build signedoff user default signature\r
+               getSignedOff: function(user) {\r
+                       return user.infos.name + " <" + user.infos.email + ">";\r
+               },\r
+\r
+               // get the branches list from a repo\r
+               getBranches: function(user) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "GET",\r
+                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/branches",\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               /* GitHub commits */\r
+\r
+               // get the latest commit on `branchName`\r
+               getCommit: function(user, sha) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "GET",\r
+                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/commits/" + sha,\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               // get the base tree for a commit sha\r
+               getTree: function(user, sha) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "GET",\r
+                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/trees/" + sha + "?recursive=1",\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               // create a new blob\r
+               createBlob: function(user, content) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "POST",\r
+                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/blobs",\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               data: JSON.stringify({\r
+                                       content: content.base64Encode(),\r
+                                       encoding: "base64"\r
+                               }),\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               // create a new tree from a base tree\r
+               createTree: function(user, baseTree, path, blob) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "POST",\r
+                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/trees",\r
+                               data: JSON.stringify({\r
+                                       base_tree: baseTree.sha,\r
+                                       tree: [{\r
+                                               path: path,\r
+                                               mode: "100644", // file (blob)\r
+                                               type: "blob",\r
+                                               sha: blob.sha\r
+                                       }]\r
+                               }),\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               // create a new commit\r
+               createCommit: function(user, message, parentCommit, tree) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "POST",\r
+                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/commits",\r
+                               data: JSON.stringify({\r
+                                       message: message,\r
+                                       parents: parentCommit,\r
+                                       tree: tree.sha,\r
+                               }),\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               // create a pull request\r
+               createPullRequest: function(user, title, body, origin, head) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                       xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "POST",\r
+                               url: "https://api.github.com/repos/" + origin.user + "/" + origin.repo + "/pulls",\r
+                               data: JSON.stringify({\r
+                                       title: title,\r
+                                       body: body,\r
+                                       base: origin.branch,\r
+                                       head: user.login + ":" + head\r
+                               }),\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               // update a pull request\r
+               updatePullRequest: function(user, title, body, state, request) {\r
+                       var res = false;\r
+                               $.ajax({\r
+                               beforeSend: function (xhr) {\r
+                                               xhr.setRequestHeader ("Authorization", user.auth);\r
+                               },\r
+                               type: "PATCH",\r
+                               url: request.url,\r
+                               data: JSON.stringify({\r
+                                       title: title,\r
+                                       body: body,\r
+                                       state: state\r
+                               }),\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               },\r
+\r
+               /* Files */\r
+\r
+               getFile: function(user, path, branch) {\r
+                       var res = false;\r
+                       $.ajax({\r
+                               type: "GET",\r
+                               url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/contents/" + path,\r
+                               data: {\r
+                                       ref: branch\r
+                               },\r
+                               async: false,\r
+                               dataType: 'json',\r
+                               success: function(response) {\r
+                                       res = response;\r
+                               },\r
+                               error: function(response) {\r
+                                       res = response;\r
+                               }\r
+                       });\r
+                       return res;\r
+               }\r
+       }\r
+});\r
diff --git a/share/nitdoc/js/lib/highlight.js b/share/nitdoc/js/lib/highlight.js
new file mode 100644 (file)
index 0000000..54f02a6
--- /dev/null
@@ -0,0 +1,719 @@
+/*     Copyright (c) 2006, Ivan Sagalaev
+       All rights reserved.
+       Redistribution and use in source and binary forms, with or without
+       modification, are permitted provided that the following conditions are met:
+
+               * Redistributions of source code must retain the above copyright
+                 notice, this list of conditions and the following disclaimer.
+               * Redistributions in binary form must reproduce the above copyright
+                 notice, this list of conditions and the following disclaimer in the
+                 documentation and/or other materials provided with the distribution.
+               * Neither the name of highlight.js nor the names of its contributors
+                 may be used to endorse or promote products derived from this software
+                 without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+       EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+       WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+       DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+       DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+       (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+       ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+define([], function () {
+       var hljs = new function() {
+
+         /* Utility functions */
+
+         function escape(value) {
+               return value.replace(/&/gm, '&amp;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;');
+         }
+
+         function tag(node) {
+               return node.nodeName.toLowerCase();
+         }
+
+         function testRe(re, lexeme) {
+               var match = re && re.exec(lexeme);
+               return match && match.index == 0;
+         }
+
+         function blockLanguage(block) {
+               var classes = (block.className + ' ' + (block.parentNode ? block.parentNode.className : '')).split(/\s+/);
+               classes = classes.map(function(c) {return c.replace(/^lang(uage)?-/, '');});
+               return classes.filter(function(c) {return getLanguage(c) || c == 'no-highlight';})[0];
+         }
+
+         function inherit(parent, obj) {
+               var result = {};
+               for (var key in parent)
+                 result[key] = parent[key];
+               if (obj)
+                 for (var key in obj)
+                   result[key] = obj[key];
+               return result;
+         };
+
+         /* Stream merging */
+
+         function nodeStream(node) {
+               var result = [];
+               (function _nodeStream(node, offset) {
+                 for (var child = node.firstChild; child; child = child.nextSibling) {
+                   if (child.nodeType == 3)
+                     offset += child.nodeValue.length;
+                   else if (tag(child) == 'br')
+                     offset += 1;
+                   else if (child.nodeType == 1) {
+                     result.push({
+                       event: 'start',
+                       offset: offset,
+                       node: child
+                     });
+                     offset = _nodeStream(child, offset);
+                     result.push({
+                       event: 'stop',
+                       offset: offset,
+                       node: child
+                     });
+                   }
+                 }
+                 return offset;
+               })(node, 0);
+               return result;
+         }
+
+         function mergeStreams(original, highlighted, value) {
+               var processed = 0;
+               var result = '';
+               var nodeStack = [];
+
+               function selectStream() {
+                 if (!original.length || !highlighted.length) {
+                   return original.length ? original : highlighted;
+                 }
+                 if (original[0].offset != highlighted[0].offset) {
+                   return (original[0].offset < highlighted[0].offset) ? original : highlighted;
+                 }
+
+                 /*
+                 To avoid starting the stream just before it should stop the order is
+                 ensured that original always starts first and closes last:
+
+                 if (event1 == 'start' && event2 == 'start')
+                   return original;
+                 if (event1 == 'start' && event2 == 'stop')
+                   return highlighted;
+                 if (event1 == 'stop' && event2 == 'start')
+                   return original;
+                 if (event1 == 'stop' && event2 == 'stop')
+                   return highlighted;
+
+                 ... which is collapsed to:
+                 */
+                 return highlighted[0].event == 'start' ? original : highlighted;
+               }
+
+               function open(node) {
+                 function attr_str(a) {return ' ' + a.nodeName + '="' + escape(a.value) + '"';}
+                 result += '<' + tag(node) + Array.prototype.map.call(node.attributes, attr_str).join('') + '>';
+               }
+
+               function close(node) {
+                 result += '</' + tag(node) + '>';
+               }
+
+               function render(event) {
+                 (event.event == 'start' ? open : close)(event.node);
+               }
+
+               while (original.length || highlighted.length) {
+                 var stream = selectStream();
+                 result += escape(value.substr(processed, stream[0].offset - processed));
+                 processed = stream[0].offset;
+                 if (stream == original) {
+                   /*
+                   On any opening or closing tag of the original markup we first close
+                   the entire highlighted node stack, then render the original tag along
+                   with all the following original tags at the same offset and then
+                   reopen all the tags on the highlighted stack.
+                   */
+                   nodeStack.reverse().forEach(close);
+                   do {
+                     render(stream.splice(0, 1)[0]);
+                     stream = selectStream();
+                   } while (stream == original && stream.length && stream[0].offset == processed);
+                   nodeStack.reverse().forEach(open);
+                 } else {
+                   if (stream[0].event == 'start') {
+                     nodeStack.push(stream[0].node);
+                   } else {
+                     nodeStack.pop();
+                   }
+                   render(stream.splice(0, 1)[0]);
+                 }
+               }
+               return result + escape(value.substr(processed));
+         }
+
+         /* Initialization */
+
+         function compileLanguage(language) {
+
+               function reStr(re) {
+                   return (re && re.source) || re;
+               }
+
+               function langRe(value, global) {
+                 return RegExp(
+                   reStr(value),
+                   'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : '')
+                 );
+               }
+
+               function compileMode(mode, parent) {
+                 if (mode.compiled)
+                   return;
+                 mode.compiled = true;
+
+                 mode.keywords = mode.keywords || mode.beginKeywords;
+                 if (mode.keywords) {
+                   var compiled_keywords = {};
+
+                   function flatten(className, str) {
+                     if (language.case_insensitive) {
+                       str = str.toLowerCase();
+                     }
+                     str.split(' ').forEach(function(kw) {
+                       var pair = kw.split('|');
+                       compiled_keywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1];
+                     });
+                   }
+
+                   if (typeof mode.keywords == 'string') { // string
+                     flatten('keyword', mode.keywords);
+                   } else {
+                     Object.keys(mode.keywords).forEach(function (className) {
+                       flatten(className, mode.keywords[className]);
+                     });
+                   }
+                   mode.keywords = compiled_keywords;
+                 }
+                 mode.lexemesRe = langRe(mode.lexemes || /\b[A-Za-z0-9_]+\b/, true);
+
+                 if (parent) {
+                   if (mode.beginKeywords) {
+                     mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')\\b';
+                   }
+                   if (!mode.begin)
+                     mode.begin = /\B|\b/;
+                   mode.beginRe = langRe(mode.begin);
+                   if (!mode.end && !mode.endsWithParent)
+                     mode.end = /\B|\b/;
+                   if (mode.end)
+                     mode.endRe = langRe(mode.end);
+                   mode.terminator_end = reStr(mode.end) || '';
+                   if (mode.endsWithParent && parent.terminator_end)
+                     mode.terminator_end += (mode.end ? '|' : '') + parent.terminator_end;
+                 }
+                 if (mode.illegal)
+                   mode.illegalRe = langRe(mode.illegal);
+                 if (mode.relevance === undefined)
+                   mode.relevance = 1;
+                 if (!mode.contains) {
+                   mode.contains = [];
+                 }
+                 var expanded_contains = [];
+                 mode.contains.forEach(function(c) {
+                   if (c.variants) {
+                     c.variants.forEach(function(v) {expanded_contains.push(inherit(c, v));});
+                   } else {
+                     expanded_contains.push(c == 'self' ? mode : c);
+                   }
+                 });
+                 mode.contains = expanded_contains;
+                 mode.contains.forEach(function(c) {compileMode(c, mode);});
+
+                 if (mode.starts) {
+                   compileMode(mode.starts, parent);
+                 }
+
+                 var terminators =
+                   mode.contains.map(function(c) {
+                     return c.beginKeywords ? '\\.?(' + c.begin + ')\\.?' : c.begin;
+                   })
+                   .concat([mode.terminator_end, mode.illegal])
+                   .map(reStr)
+                   .filter(Boolean);
+                 mode.terminators = terminators.length ? langRe(terminators.join('|'), true) : {exec: function(s) {return null;}};
+
+                 mode.continuation = {};
+               }
+
+               compileMode(language);
+         }
+
+         /*
+         Core highlighting function. Accepts a language name, or an alias, and a
+         string with the code to highlight. Returns an object with the following
+         properties:
+
+         - relevance (int)
+         - value (an HTML string with highlighting markup)
+
+         */
+         function highlight(name, value, ignore_illegals, continuation) {
+
+               function subMode(lexeme, mode) {
+                 for (var i = 0; i < mode.contains.length; i++) {
+                   if (testRe(mode.contains[i].beginRe, lexeme)) {
+                     return mode.contains[i];
+                   }
+                 }
+               }
+
+               function endOfMode(mode, lexeme) {
+                 if (testRe(mode.endRe, lexeme)) {
+                   return mode;
+                 }
+                 if (mode.endsWithParent) {
+                   return endOfMode(mode.parent, lexeme);
+                 }
+               }
+
+               function isIllegal(lexeme, mode) {
+                 return !ignore_illegals && testRe(mode.illegalRe, lexeme);
+               }
+
+               function keywordMatch(mode, match) {
+                 var match_str = language.case_insensitive ? match[0].toLowerCase() : match[0];
+                 return mode.keywords.hasOwnProperty(match_str) && mode.keywords[match_str];
+               }
+
+               function buildSpan(classname, insideSpan, leaveOpen, noPrefix) {
+                 var classPrefix = noPrefix ? '' : options.classPrefix,
+                     openSpan    = '<span class="' + classPrefix,
+                     closeSpan   = leaveOpen ? '' : '</span>';
+
+                 openSpan += classname + '">';
+
+                 return openSpan + insideSpan + closeSpan;
+               }
+
+               function processKeywords() {
+                 if (!top.keywords)
+                   return escape(mode_buffer);
+                 var result = '';
+                 var last_index = 0;
+                 top.lexemesRe.lastIndex = 0;
+                 var match = top.lexemesRe.exec(mode_buffer);
+                 while (match) {
+                   result += escape(mode_buffer.substr(last_index, match.index - last_index));
+                   var keyword_match = keywordMatch(top, match);
+                   if (keyword_match) {
+                     relevance += keyword_match[1];
+                     result += buildSpan(keyword_match[0], escape(match[0]));
+                   } else {
+                     result += escape(match[0]);
+                   }
+                   last_index = top.lexemesRe.lastIndex;
+                   match = top.lexemesRe.exec(mode_buffer);
+                 }
+                 return result + escape(mode_buffer.substr(last_index));
+               }
+
+               function processSubLanguage() {
+                 if (top.subLanguage && !languages[top.subLanguage]) {
+                   return escape(mode_buffer);
+                 }
+                 var result = top.subLanguage ? highlight(top.subLanguage, mode_buffer, true, top.continuation.top) : highlightAuto(mode_buffer);
+                 // Counting embedded language score towards the host language may be disabled
+                 // with zeroing the containing mode relevance. Usecase in point is Markdown that
+                 // allows XML everywhere and makes every XML snippet to have a much larger Markdown
+                 // score.
+                 if (top.relevance > 0) {
+                   relevance += result.relevance;
+                 }
+                 if (top.subLanguageMode == 'continuous') {
+                   top.continuation.top = result.top;
+                 }
+                 return buildSpan(result.language, result.value, false, true);
+               }
+
+               function processBuffer() {
+                 return top.subLanguage !== undefined ? processSubLanguage() : processKeywords();
+               }
+
+               function startNewMode(mode, lexeme) {
+                 var markup = mode.className? buildSpan(mode.className, '', true): '';
+                 if (mode.returnBegin) {
+                   result += markup;
+                   mode_buffer = '';
+                 } else if (mode.excludeBegin) {
+                   result += escape(lexeme) + markup;
+                   mode_buffer = '';
+                 } else {
+                   result += markup;
+                   mode_buffer = lexeme;
+                 }
+                 top = Object.create(mode, {parent: {value: top}});
+               }
+
+               function processLexeme(buffer, lexeme) {
+
+                 mode_buffer += buffer;
+                 if (lexeme === undefined) {
+                   result += processBuffer();
+                   return 0;
+                 }
+
+                 var new_mode = subMode(lexeme, top);
+                 if (new_mode) {
+                   result += processBuffer();
+                   startNewMode(new_mode, lexeme);
+                   return new_mode.returnBegin ? 0 : lexeme.length;
+                 }
+
+                 var end_mode = endOfMode(top, lexeme);
+                 if (end_mode) {
+                   var origin = top;
+                   if (!(origin.returnEnd || origin.excludeEnd)) {
+                     mode_buffer += lexeme;
+                   }
+                   result += processBuffer();
+                   do {
+                     if (top.className) {
+                       result += '</span>';
+                     }
+                     relevance += top.relevance;
+                     top = top.parent;
+                   } while (top != end_mode.parent);
+                   if (origin.excludeEnd) {
+                     result += escape(lexeme);
+                   }
+                   mode_buffer = '';
+                   if (end_mode.starts) {
+                     startNewMode(end_mode.starts, '');
+                   }
+                   return origin.returnEnd ? 0 : lexeme.length;
+                 }
+
+                 if (isIllegal(lexeme, top))
+                   throw new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.className || '<unnamed>') + '"');
+
+                 /*
+                 Parser should not reach this point as all types of lexemes should be caught
+                 earlier, but if it does due to some bug make sure it advances at least one
+                 character forward to prevent infinite looping.
+                 */
+                 mode_buffer += lexeme;
+                 return lexeme.length || 1;
+               }
+
+               var language = getLanguage(name);
+               if (!language) {
+                 throw new Error('Unknown language: "' + name + '"');
+               }
+
+               compileLanguage(language);
+               var top = continuation || language;
+               var result = '';
+               for(var current = top; current != language; current = current.parent) {
+                 if (current.className) {
+                   result += buildSpan(current.className, result, true);
+                 }
+               }
+               var mode_buffer = '';
+               var relevance = 0;
+               try {
+                 var match, count, index = 0;
+                 while (true) {
+                   top.terminators.lastIndex = index;
+                   match = top.terminators.exec(value);
+                   if (!match)
+                     break;
+                   count = processLexeme(value.substr(index, match.index - index), match[0]);
+                   index = match.index + count;
+                 }
+                 processLexeme(value.substr(index));
+                 for(var current = top; current.parent; current = current.parent) { // close dangling modes
+                   if (current.className) {
+                     result += '</span>';
+                   }
+                 };
+                 return {
+                   relevance: relevance,
+                   value: result,
+                   language: name,
+                   top: top
+                 };
+               } catch (e) {
+                 if (e.message.indexOf('Illegal') != -1) {
+                   return {
+                     relevance: 0,
+                     value: escape(value)
+                   };
+                 } else {
+                   throw e;
+                 }
+               }
+         }
+
+         /*
+         Highlighting with language detection. Accepts a string with the code to
+         highlight. Returns an object with the following properties:
+
+         - language (detected language)
+         - relevance (int)
+         - value (an HTML string with highlighting markup)
+         - second_best (object with the same structure for second-best heuristically
+               detected language, may be absent)
+
+         */
+         function highlightAuto(text, languageSubset) {
+               languageSubset = languageSubset || options.languages || Object.keys(languages);
+               var result = {
+                 relevance: 0,
+                 value: escape(text)
+               };
+               var second_best = result;
+               languageSubset.forEach(function(name) {
+                 if (!getLanguage(name)) {
+                   return;
+                 }
+                 var current = highlight(name, text, false);
+                 current.language = name;
+                 if (current.relevance > second_best.relevance) {
+                   second_best = current;
+                 }
+                 if (current.relevance > result.relevance) {
+                   second_best = result;
+                   result = current;
+                 }
+               });
+               if (second_best.language) {
+                 result.second_best = second_best;
+               }
+               return result;
+         }
+
+         /*
+         Post-processing of the highlighted markup:
+
+         - replace TABs with something more useful
+         - replace real line-breaks with '<br>' for non-pre containers
+
+         */
+         function fixMarkup(value) {
+               if (options.tabReplace) {
+                 value = value.replace(/^((<[^>]+>|\t)+)/gm, function(match, p1, offset, s) {
+                   return p1.replace(/\t/g, options.tabReplace);
+                 });
+               }
+               if (options.useBR) {
+                 value = value.replace(/\n/g, '<br>');
+               }
+               return value;
+         }
+
+         /*
+         Applies highlighting to a DOM node containing code. Accepts a DOM node and
+         two optional parameters for fixMarkup.
+         */
+         function highlightBlock(block) {
+               var text = options.useBR ? block.innerHTML
+                 .replace(/\n/g,'').replace(/<br>|<br [^>]*>/g, '\n').replace(/<[^>]*>/g,'')
+                 : block.textContent;
+               var language = blockLanguage(block);
+               if (language == 'no-highlight')
+                   return;
+               var result = language ? highlight(language, text, true) : highlightAuto(text);
+               var original = nodeStream(block);
+               if (original.length) {
+                 var pre = document.createElementNS('http://www.w3.org/1999/xhtml', 'pre');
+                 pre.innerHTML = result.value;
+                 result.value = mergeStreams(original, nodeStream(pre), text);
+               }
+               result.value = fixMarkup(result.value);
+
+               block.innerHTML = result.value;
+               block.className += ' hljs ' + (!language && result.language || '');
+               block.result = {
+                 language: result.language,
+                 re: result.relevance
+               };
+               if (result.second_best) {
+                 block.second_best = {
+                   language: result.second_best.language,
+                   re: result.second_best.relevance
+                 };
+               }
+         }
+
+         var options = {
+               classPrefix: 'hljs-',
+               tabReplace: null,
+               useBR: false,
+               languages: undefined
+         };
+
+         /*
+         Updates highlight.js global options with values passed in the form of an object
+         */
+         function configure(user_options) {
+               options = inherit(options, user_options);
+         }
+
+         /*
+         Applies highlighting to all <pre><code>..</code></pre> blocks on a page.
+         */
+         function initHighlighting() {
+               if (initHighlighting.called)
+                 return;
+               initHighlighting.called = true;
+
+               var blocks = document.querySelectorAll('pre code');
+               Array.prototype.forEach.call(blocks, highlightBlock);
+         }
+
+         /*
+         Attaches highlighting to the page load event.
+         */
+         function initHighlightingOnLoad() {
+               addEventListener('DOMContentLoaded', initHighlighting, false);
+               addEventListener('load', initHighlighting, false);
+         }
+
+         var languages = {};
+         var aliases = {};
+
+         function registerLanguage(name, language) {
+               var lang = languages[name] = language(this);
+               if (lang.aliases) {
+                 lang.aliases.forEach(function(alias) {aliases[alias] = name;});
+               }
+         }
+
+         function listLanguages() {
+               return Object.keys(languages);
+         }
+
+         function getLanguage(name) {
+               return languages[name] || languages[aliases[name]];
+         }
+
+         /* Interface definition */
+
+         this.highlight = highlight;
+         this.highlightAuto = highlightAuto;
+         this.fixMarkup = fixMarkup;
+         this.highlightBlock = highlightBlock;
+         this.configure = configure;
+         this.initHighlighting = initHighlighting;
+         this.initHighlightingOnLoad = initHighlightingOnLoad;
+         this.registerLanguage = registerLanguage;
+         this.listLanguages = listLanguages;
+         this.getLanguage = getLanguage;
+         this.inherit = inherit;
+
+         // Common regexps
+         this.IDENT_RE = '[a-zA-Z][a-zA-Z0-9_]*';
+         this.UNDERSCORE_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*';
+         this.NUMBER_RE = '\\b\\d+(\\.\\d+)?';
+         this.C_NUMBER_RE = '(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float
+         this.BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b...
+         this.RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
+
+         // Common modes
+         this.BACKSLASH_ESCAPE = {
+               begin: '\\\\[\\s\\S]', relevance: 0
+         };
+         this.APOS_STRING_MODE = {
+               className: 'string',
+               begin: '\'', end: '\'',
+               illegal: '\\n',
+               contains: [this.BACKSLASH_ESCAPE]
+         };
+         this.QUOTE_STRING_MODE = {
+               className: 'string',
+               begin: '"', end: '"',
+               illegal: '\\n',
+               contains: [this.BACKSLASH_ESCAPE]
+         };
+         this.PHRASAL_WORDS_MODE = {
+               begin: /\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/
+         };
+         this.C_LINE_COMMENT_MODE = {
+               className: 'comment',
+               begin: '//', end: '$',
+               contains: [this.PHRASAL_WORDS_MODE]
+         };
+         this.C_BLOCK_COMMENT_MODE = {
+               className: 'comment',
+               begin: '/\\*', end: '\\*/',
+               contains: [this.PHRASAL_WORDS_MODE]
+         };
+         this.HASH_COMMENT_MODE = {
+               className: 'comment',
+               begin: '#', end: '$',
+               contains: [this.PHRASAL_WORDS_MODE]
+         };
+         this.NUMBER_MODE = {
+               className: 'number',
+               begin: this.NUMBER_RE,
+               relevance: 0
+         };
+         this.C_NUMBER_MODE = {
+               className: 'number',
+               begin: this.C_NUMBER_RE,
+               relevance: 0
+         };
+         this.BINARY_NUMBER_MODE = {
+               className: 'number',
+               begin: this.BINARY_NUMBER_RE,
+               relevance: 0
+         };
+         this.CSS_NUMBER_MODE = {
+               className: 'number',
+               begin: this.NUMBER_RE + '(' +
+                 '%|em|ex|ch|rem'  +
+                 '|vw|vh|vmin|vmax' +
+                 '|cm|mm|in|pt|pc|px' +
+                 '|deg|grad|rad|turn' +
+                 '|s|ms' +
+                 '|Hz|kHz' +
+                 '|dpi|dpcm|dppx' +
+                 ')?',
+               relevance: 0
+         };
+         this.REGEXP_MODE = {
+               className: 'regexp',
+               begin: /\//, end: /\/[gim]*/,
+               illegal: /\n/,
+               contains: [
+                 this.BACKSLASH_ESCAPE,
+                 {
+                   begin: /\[/, end: /\]/,
+                   relevance: 0,
+                   contains: [this.BACKSLASH_ESCAPE]
+                 }
+               ]
+         };
+         this.TITLE_MODE = {
+               className: 'title',
+               begin: this.IDENT_RE,
+               relevance: 0
+         };
+         this.UNDERSCORE_TITLE_MODE = {
+               className: 'title',
+               begin: this.UNDERSCORE_IDENT_RE,
+               relevance: 0
+         };
+       };
+       return hljs;
+});
+
diff --git a/share/nitdoc/js/lib/jquery-ui.js b/share/nitdoc/js/lib/jquery-ui.js
new file mode 100644 (file)
index 0000000..ce3dc7d
--- /dev/null
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.10.4 - 2014-02-09
+* http://jqueryui.com
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
+
+(function(e,t){function i(t,i){var s,a,o,r=t.nodeName.toLowerCase();return"area"===r?(s=t.parentNode,a=s.name,t.href&&a&&"map"===s.nodeName.toLowerCase()?(o=e("img[usemap=#"+a+"]")[0],!!o&&n(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||i:i)&&n(t)}function n(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var s=0,a=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,n){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),n&&n.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var n,s,a=e(this[0]);a.length&&a[0]!==document;){if(n=a.css("position"),("absolute"===n||"relative"===n||"fixed"===n)&&(s=parseInt(a.css("zIndex"),10),!isNaN(s)&&0!==s))return s;a=a.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++s)})},removeUniqueId:function(){return this.each(function(){a.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,n){return!!e.data(t,n[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),s=isNaN(n);return(s||n>=0)&&i(t,!s)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,n){function s(t,i,n,s){return e.each(a,function(){i-=parseFloat(e.css(t,"padding"+this))||0,n&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var a="Width"===n?["Left","Right"]:["Top","Bottom"],o=n.toLowerCase(),r={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+n]=function(i){return i===t?r["inner"+n].call(this):this.each(function(){e(this).css(o,s(this,i)+"px")})},e.fn["outer"+n]=function(t,i){return"number"!=typeof t?r["outer"+n].call(this,t):this.each(function(){e(this).css(o,s(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,n){var s,a=e.ui[t].prototype;for(s in n)a.plugins[s]=a.plugins[s]||[],a.plugins[s].push([i,n[s]])},call:function(e,t,i){var n,s=e.plugins[t];if(s&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(n=0;s.length>n;n++)e.options[s[n][0]]&&s[n][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var n=i&&"left"===i?"scrollLeft":"scrollTop",s=!1;return t[n]>0?!0:(t[n]=1,s=t[n]>0,t[n]=0,s)}})})(jQuery);(function(t,e){var i=0,s=Array.prototype.slice,n=t.cleanData;t.cleanData=function(e){for(var i,s=0;null!=(i=e[s]);s++)try{t(i).triggerHandler("remove")}catch(o){}n(e)},t.widget=function(i,s,n){var o,a,r,h,l={},c=i.split(".")[0];i=i.split(".")[1],o=c+"-"+i,n||(n=s,s=t.Widget),t.expr[":"][o.toLowerCase()]=function(e){return!!t.data(e,o)},t[c]=t[c]||{},a=t[c][i],r=t[c][i]=function(t,i){return this._createWidget?(arguments.length&&this._createWidget(t,i),e):new r(t,i)},t.extend(r,a,{version:n.version,_proto:t.extend({},n),_childConstructors:[]}),h=new s,h.options=t.widget.extend({},h.options),t.each(n,function(i,n){return t.isFunction(n)?(l[i]=function(){var t=function(){return s.prototype[i].apply(this,arguments)},e=function(t){return s.prototype[i].apply(this,t)};return function(){var i,s=this._super,o=this._superApply;return this._super=t,this._superApply=e,i=n.apply(this,arguments),this._super=s,this._superApply=o,i}}(),e):(l[i]=n,e)}),r.prototype=t.widget.extend(h,{widgetEventPrefix:a?h.widgetEventPrefix||i:i},l,{constructor:r,namespace:c,widgetName:i,widgetFullName:o}),a?(t.each(a._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,r,i._proto)}),delete a._childConstructors):s._childConstructors.push(r),t.widget.bridge(i,r)},t.widget.extend=function(i){for(var n,o,a=s.call(arguments,1),r=0,h=a.length;h>r;r++)for(n in a[r])o=a[r][n],a[r].hasOwnProperty(n)&&o!==e&&(i[n]=t.isPlainObject(o)?t.isPlainObject(i[n])?t.widget.extend({},i[n],o):t.widget.extend({},o):o);return i},t.widget.bridge=function(i,n){var o=n.prototype.widgetFullName||i;t.fn[i]=function(a){var r="string"==typeof a,h=s.call(arguments,1),l=this;return a=!r&&h.length?t.widget.extend.apply(null,[a].concat(h)):a,r?this.each(function(){var s,n=t.data(this,o);return n?t.isFunction(n[a])&&"_"!==a.charAt(0)?(s=n[a].apply(n,h),s!==n&&s!==e?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):e):t.error("no such method '"+a+"' for "+i+" widget instance"):t.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var e=t.data(this,o);e?e.option(a||{})._init():t.data(this,o,new n(a,this))}),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this.bindings=t(),this.hoverable=t(),this.focusable=t(),s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(i,s){var n,o,a,r=i;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof i)if(r={},n=i.split("."),i=n.shift(),n.length){for(o=r[i]=t.widget.extend({},this.options[i]),a=0;n.length-1>a;a++)o[n[a]]=o[n[a]]||{},o=o[n[a]];if(i=n.pop(),1===arguments.length)return o[i]===e?null:o[i];o[i]=s}else{if(1===arguments.length)return this.options[i]===e?null:this.options[i];r[i]=s}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!e).attr("aria-disabled",e),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var o,a=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=o=t(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,o=this.widget()),t.each(n,function(n,r){function h(){return i||a.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?a[r]:r).apply(a,arguments):e}"string"!=typeof r&&(h.guid=r.guid=r.guid||h.guid||t.guid++);var l=n.match(/^(\w+)\s*(.*)$/),c=l[1]+a.eventNamespace,u=l[2];u?o.delegate(u,c,h):s.bind(c,h)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(e).undelegate(e)},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}})})(jQuery);(function(t){var e=!1;t(document).mouseup(function(){e=!1}),t.widget("ui.mouse",{version:"1.10.4",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.bind("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).bind("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!e){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?t(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===t.data(i.target,this.widgetName+".preventClickEvent")&&t.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return s._mouseMove(t)},this._mouseUpDelegate=function(t){return s._mouseUp(t)},t(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),e=!0,!0)):!0}},_mouseMove:function(e){return t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button?this._mouseUp(e):this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){return t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),!1},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,l=Math.round,h=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType;return{element:i,isWindow:s,isDocument:n,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)return f.apply(this,arguments);e=t.extend({},e);var a,p,g,m,v,_,b=t(e.of),y=t.position.getWithinInfo(e.within),k=t.position.getScrollInfo(y),w=(e.collision||"flip").split(" "),D={};return _=n(b),b[0].preventDefault&&(e.at="left top"),p=_.width,g=_.height,m=_.offset,v=t.extend({},m),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=h.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=h.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),D[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===w.length&&(w[1]=w[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=g:"center"===e.at[1]&&(v.top+=g/2),a=i(D.at,p,g),v.left+=a[0],v.top+=a[1],this.each(function(){var n,h,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),_=s(this,"marginTop"),x=u+f+s(this,"marginRight")+k.width,C=d+_+s(this,"marginBottom")+k.height,M=t.extend({},v),T=i(D.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?M.left-=u:"center"===e.my[0]&&(M.left-=u/2),"bottom"===e.my[1]?M.top-=d:"center"===e.my[1]&&(M.top-=d/2),M.left+=T[0],M.top+=T[1],t.support.offsetFractions||(M.left=l(M.left),M.top=l(M.top)),n={marginLeft:f,marginTop:_},t.each(["left","top"],function(i,s){t.ui.position[w[i]]&&t.ui.position[w[i]][s](M,{targetWidth:p,targetHeight:g,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:x,collisionHeight:C,offset:[a[0]+T[0],a[1]+T[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(h=function(t){var i=m.left-M.left,s=i+p-u,n=m.top-M.top,a=n+g-d,l={target:{element:b,left:m.left,top:m.top,width:p,height:g},element:{element:c,left:M.left,top:M.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(l.horizontal="center"),d>g&&g>r(n+a)&&(l.vertical="middle"),l.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.call(this,t,l)}),c.offset(t.extend(M,{using:h}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-o-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-o-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-o-a,t.top+p+f+g>c&&(0>s||r(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,t.top+p+f+g>u&&(i>0||u>r(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(t){t.widget("ui.draggable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(t(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){t("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(t(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_mouseDrag:function(e,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||t.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1):!1},_mouseUp:function(e){return t("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.element.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,t(document).width()-this.helperProportions.width-this.margins.left,(t(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(e){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=e.pageX,h=e.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0]&&(l=i[0]+this.offset.click.left),e.pageY-this.offset.click.top<i[1]&&(h=i[1]+this.offset.click.top),e.pageX-this.offset.click.left>i[2]&&(l=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,l=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s]),"drag"===e&&(this.positionAbs=this._convertPositionTo("absolute")),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i){var s=t(this).data("ui-draggable"),n=s.options,a=t.extend({},i,{item:s.element});s.sortables=[],t(n.connectToSortable).each(function(){var i=t.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",e,a))})},stop:function(e,i){var s=t(this).data("ui-draggable"),n=t.extend({},i,{item:s.element});t.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(e),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",e,n))})},drag:function(e,i){var s=t(this).data("ui-draggable"),n=this;t.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,t.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&t.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=t(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},e.target=this.instance.currentItem[0],this.instance._mouseCapture(e,!0),this.instance._mouseStart(e,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",e),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(e)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",e,this.instance._uiHash(this.instance)),this.instance._mouseStop(e,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",e),s.dropped=!1)})}}),t.ui.plugin.add("draggable","cursor",{start:function(){var e=t("body"),i=t(this).data("ui-draggable").options;e.css("cursor")&&(i._cursor=e.css("cursor")),e.css("cursor",i.cursor)},stop:function(){var e=t(this).data("ui-draggable").options;e._cursor&&t("body").css("cursor",e._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._opacity&&t(i.helper).css("opacity",s._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(){var e=t(this).data("ui-draggable");e.scrollParent[0]!==document&&"HTML"!==e.scrollParent[0].tagName&&(e.overflowOffset=e.scrollParent.offset())},drag:function(e){var i=t(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-e.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:e.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-e.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:e.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(e.pageY-t(document).scrollTop()<s.scrollSensitivity?n=t(document).scrollTop(t(document).scrollTop()-s.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<s.scrollSensitivity&&(n=t(document).scrollTop(t(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(e.pageX-t(document).scrollLeft()<s.scrollSensitivity?n=t(document).scrollLeft(t(document).scrollLeft()-s.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<s.scrollSensitivity&&(n=t(document).scrollLeft(t(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&t.ui.ddmanager&&!s.dropBehaviour&&t.ui.ddmanager.prepareOffsets(i,e)}}),t.ui.plugin.add("draggable","snap",{start:function(){var e=t(this).data("ui-draggable"),i=e.options;e.snapElements=[],t(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=t(this),s=i.offset();this!==e.element[0]&&e.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(e,i){var s,n,a,o,r,l,h,c,u,d,p=t(this).data("ui-draggable"),g=p.options,f=g.snapTolerance,m=i.offset.left,_=m+p.helperProportions.width,v=i.offset.top,b=v+p.helperProportions.height;for(u=p.snapElements.length-1;u>=0;u--)r=p.snapElements[u].left,l=r+p.snapElements[u].width,h=p.snapElements[u].top,c=h+p.snapElements[u].height,r-f>_||m>l+f||h-f>b||v>c+f||!t.contains(p.snapElements[u].item.ownerDocument,p.snapElements[u].item)?(p.snapElements[u].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=!1):("inner"!==g.snapMode&&(s=f>=Math.abs(h-b),n=f>=Math.abs(c-v),a=f>=Math.abs(r-_),o=f>=Math.abs(l-m),s&&(i.position.top=p._convertPositionTo("relative",{top:h-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l}).left-p.margins.left)),d=s||n||a||o,"outer"!==g.snapMode&&(s=f>=Math.abs(h-v),n=f>=Math.abs(c-b),a=f>=Math.abs(r-m),o=f>=Math.abs(l-_),s&&(i.position.top=p._convertPositionTo("relative",{top:h,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[u].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=s||n||a||o||d)}}),t.ui.plugin.add("draggable","stack",{start:function(){var e,i=this.data("ui-draggable").options,s=t.makeArray(t(i.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});s.length&&(e=parseInt(t(s[0]).css("zIndex"),10)||0,t(s).each(function(i){t(this).css("zIndex",e+i)}),this.css("zIndex",e+s.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._zIndex&&t(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}t.widget("ui.droppable",{version:"1.10.4",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var e,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=t.isFunction(s)?s:function(t){return t.is(s)},this.proportions=function(){return arguments.length?(e=arguments[0],undefined):e?e:e={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},t.ui.ddmanager.droppables[i.scope]=t.ui.ddmanager.droppables[i.scope]||[],t.ui.ddmanager.droppables[i.scope].push(this),i.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){for(var e=0,i=t.ui.ddmanager.droppables[this.options.scope];i.length>e;e++)i[e]===this&&i.splice(e,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(e,i){"accept"===e&&(this.accept=t.isFunction(i)?i:function(t){return t.is(i)}),t.Widget.prototype._setOption.apply(this,arguments)},_activate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",e,this.ui(i))},_deactivate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",e,this.ui(i))},_over:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",e,this.ui(i)))},_out:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",e,this.ui(i)))},_drop:function(e,i){var s=i||t.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var e=t.data(this,"ui-droppable");return e.options.greedy&&!e.options.disabled&&e.options.scope===s.options.scope&&e.accept.call(e.element[0],s.currentItem||s.element)&&t.ui.intersect(s,t.extend(e,{offset:e.element.offset()}),e.options.tolerance)?(n=!0,!1):undefined}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",e,this.ui(s)),this.element):!1):!1},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}}}),t.ui.intersect=function(t,i,s){if(!i.offset)return!1;var n,a,o=(t.positionAbs||t.position.absolute).left,r=(t.positionAbs||t.position.absolute).top,l=o+t.helperProportions.width,h=r+t.helperProportions.height,c=i.offset.left,u=i.offset.top,d=c+i.proportions().width,p=u+i.proportions().height;switch(s){case"fit":return o>=c&&d>=l&&r>=u&&p>=h;case"intersect":return o+t.helperProportions.width/2>c&&d>l-t.helperProportions.width/2&&r+t.helperProportions.height/2>u&&p>h-t.helperProportions.height/2;case"pointer":return n=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,a=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,e(a,u,i.proportions().height)&&e(n,c,i.proportions().width);case"touch":return(r>=u&&p>=r||h>=u&&p>=h||u>r&&h>p)&&(o>=c&&d>=o||l>=c&&d>=l||c>o&&l>d);default:return!1}},t.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,i){var s,n,a=t.ui.ddmanager.droppables[e.options.scope]||[],o=i?i.type:null,r=(e.currentItem||e.element).find(":data(ui-droppable)").addBack();t:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||e&&!a[s].accept.call(a[s].element[0],e.currentItem||e.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue t}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(e,i){var s=!1;return t.each((t.ui.ddmanager.droppables[e.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&t.ui.intersect(e,this,this.options.tolerance)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(e,i){e.element.parentsUntil("body").bind("scroll.droppable",function(){e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)})},drag:function(e,i){e.options.refreshPositions&&t.ui.ddmanager.prepareOffsets(e,i),t.each(t.ui.ddmanager.droppables[e.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=t.ui.intersect(e,this,this.options.tolerance),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return t.data(this,"ui-droppable").options.scope===n}),a.length&&(s=t.data(a[0],"ui-droppable"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(e,i){e.element.parentsUntil("body").unbind("scroll.droppable"),e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)}}})(jQuery);(function(t){function e(t){return parseInt(t,10)||0}function i(t){return!isNaN(parseInt(t,10))}t.widget("ui.resizable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var e,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),e=this.handles.split(","),this.handles={},i=0;e.length>i;i++)s=t.trim(e[i]),a="ui-resizable-"+s,n=t("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(e){var i,s,n,a;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=t(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=t(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,a),this._proportionallyResize()),t(this.handles[i]).length},this._renderAxis(this.element),this._handles=t(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),t(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(t(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(t(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=e(this.helper.css("left")),n=e(this.helper.css("top")),o.containment&&(s+=t(o.containment).scrollLeft()||0,n+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(e){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,c=this.size.height,u=e.pageX-a.left||0,d=e.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[e,u,d]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==c&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(n)||this._trigger("resize",e,this.ui()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&t.ui.hasScroll(i[0],"left")?0:c.sizeDiff.height,a=s?0:c.sizeDiff.width,o={width:c.helper.width()-a,height:c.helper.height()-n},r=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null,h=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(o,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(t){var e,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),i(t.left)&&(this.position.left=t.left),i(t.top)&&(this.position.top=t.top),i(t.height)&&(this.size.height=t.height),i(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,s=this.size,n=this.axis;return i(t.height)?t.width=t.height*this.aspectRatio:i(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===n&&(t.left=e.left+(s.width-t.width),t.top=null),"nw"===n&&(t.top=e.top+(s.height-t.height),t.left=e.left+(s.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,s=this.axis,n=i(t.width)&&e.maxWidth&&e.maxWidth<t.width,a=i(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=i(t.width)&&e.minWidth&&e.minWidth>t.width,r=i(t.height)&&e.minHeight&&e.minHeight>t.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,c=/sw|nw|w/.test(s),u=/nw|ne|n/.test(s);return o&&(t.width=e.minWidth),r&&(t.height=e.minHeight),n&&(t.width=e.maxWidth),a&&(t.height=e.maxHeight),o&&c&&(t.left=h-e.minWidth),n&&c&&(t.left=h-e.maxWidth),r&&u&&(t.top=l-e.minHeight),a&&u&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var t,e,i,s,n,a=this.helper||this.element;for(t=0;this._proportionallyResizeElements.length>t;t++){if(n=this._proportionallyResizeElements[t],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],e=0;i.length>e;e++)this.borderDif[e]=(parseInt(i[e],10)||0)+(parseInt(s[e],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&t.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,c=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=t(this).data("ui-resizable"),c=l.options,u=l.element,d=c.containment,p=d instanceof t?d.get(0):/parent/.test(d)?u.parent().get(0):d;p&&(l.containerElement=t(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(i=t(p),s=[],t(["Top","Right","Left","Bottom"]).each(function(t,n){s[t]=e(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=t.ui.hasScroll(p,"left")?p.scrollWidth:o,h=t.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(e){var i,s,n,a,o=t(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,c=o._aspectRatio||e.shiftKey,u={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-u.left),c&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),c&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-u.left:o.offset.left-u.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-u.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=Math.abs(o.parentData.left)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,c&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,c&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.containerOffset,n=e.containerPosition,a=e.containerElement,o=t(e.helper),r=o.offset(),h=o.outerWidth()-e.sizeDiff.width,l=o.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=function(e){t(e).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseInt(e.width(),10),height:parseInt(e.height(),10),left:parseInt(e.css("left"),10),top:parseInt(e.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):t.each(i.alsoResize,function(t){s(t)})},resize:function(e,i){var s=t(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(e,s){t(e).each(function(){var e=t(this),n=t(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(n[e]||0)+(r[e]||0);i&&i>=0&&(a[e]=i||null)}),e.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):t.each(n.alsoResize,function(t,e){h(t,e)})},stop:function(){t(this).removeData("resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).data("ui-resizable");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).data("ui-resizable");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size,n=e.originalSize,a=e.originalPosition,o=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,c=Math.round((s.width-n.width)/h)*h,u=Math.round((s.height-n.height)/l)*l,d=n.width+c,p=n.height+u,f=i.maxWidth&&d>i.maxWidth,g=i.maxHeight&&p>i.maxHeight,m=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=h),v&&(p+=l),f&&(d-=h),g&&(p-=l),/^(se|s|e)$/.test(o)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.top=a.top-u):/^(sw)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.left=a.left-c):(p-l>0?(e.size.height=p,e.position.top=a.top-u):(e.size.height=l,e.position.top=a.top+n.height-l),d-h>0?(e.size.width=d,e.position.left=a.left-c):(e.size.width=h,e.position.left=a.left+n.width-h))}})})(jQuery);(function(t){t.widget("ui.selectable",t.ui.mouse,{version:"1.10.4",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var e,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){e=t(i.options.filter,i.element[0]),e.addClass("ui-selectee"),e.each(function(){var e=t(this),i=e.offset();t.data(this,"selectable-item",{element:this,$element:e,left:i.left,top:i.top,right:i.left+e.outerWidth(),bottom:i.top+e.outerHeight(),startselected:!1,selected:e.hasClass("ui-selected"),selecting:e.hasClass("ui-selecting"),unselecting:e.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=e.addClass("ui-selectee"),this._mouseInit(),this.helper=t("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(e){var i=this,s=this.options;this.opos=[e.pageX,e.pageY],this.options.disabled||(this.selectees=t(s.filter,this.element[0]),this._trigger("start",e),t(s.appendTo).append(this.helper),this.helper.css({left:e.pageX,top:e.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=t.data(this,"selectable-item");s.startselected=!0,e.metaKey||e.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",e,{unselecting:s.element}))}),t(e.target).parents().addBack().each(function(){var s,n=t.data(this,"selectable-item");return n?(s=!e.metaKey&&!e.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",e,{selecting:n.element}):i._trigger("unselecting",e,{unselecting:n.element}),!1):undefined}))},_mouseDrag:function(e){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=e.pageX,l=e.pageY;return a>r&&(i=r,r=a,a=i),o>l&&(i=l,l=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:l-o}),this.selectees.each(function(){var i=t.data(this,"selectable-item"),h=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?h=!(i.left>r||a>i.right||i.top>l||o>i.bottom):"fit"===n.tolerance&&(h=i.left>a&&r>i.right&&i.top>o&&l>i.bottom),h?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",e,{selecting:i.element}))):(i.selecting&&((e.metaKey||e.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",e,{unselecting:i.element}))),i.selected&&(e.metaKey||e.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",e,{unselecting:i.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,t(".ui-unselecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",e,{unselected:s.element})}),t(".ui-selecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",e,{selected:s.element})}),this._trigger("stop",e),this.helper.remove(),!1}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}function i(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))}t.widget("ui.sortable",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var t=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===t.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_setOption:function(e,i){"disabled"===e?(this.options[e]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):t.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):undefined}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("<style>*{ cursor: "+a.cursor+" !important; }</style>").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<a.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+a.scrollSpeed:e.pageY-this.overflowOffset.top<a.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-a.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<a.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+a.scrollSpeed:e.pageX-this.overflowOffset.left<a.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-a.scrollSpeed)):(e.pageY-t(document).scrollTop()<a.scrollSensitivity?r=t(document).scrollTop(t(document).scrollTop()-a.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<a.scrollSensitivity&&(r=t(document).scrollTop(t(document).scrollTop()+a.scrollSpeed)),e.pageX-t(document).scrollLeft()<a.scrollSensitivity?r=t(document).scrollLeft(t(document).scrollLeft()-a.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<a.scrollSensitivity&&(r=t(document).scrollLeft(t(document).scrollLeft()+a.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var i="x"===this.options.axis||e(this.positionAbs.top+this.offset.click.top,t.top,t.height),s="y"===this.options.axis||e(this.positionAbs.left+this.offset.click.left,t.left,t.width),n=i&&s,o=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return n?this.floating?a&&"right"===a||"down"===o?2:1:o&&("down"===o?2:1):!1},_intersectsWithSides:function(t){var i=e(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),s=e(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),n=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return this.floating&&o?"right"===o&&s||"left"===o&&!s:n&&("down"===n&&i||"up"===n&&!i)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],h=[],l=this._connectWith();if(l&&e)for(s=l.length-1;s>=0;s--)for(o=t(l[s]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&h.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(h.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",a),c.push({item:h,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]).addClass(i||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?e.currentItem.children().each(function(){t("<td>&#160;</td>",e.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_contactContainers:function(s){var n,o,a,r,h,l,c,u,d,p,f=null,g=null;for(n=this.containers.length-1;n>=0;n--)if(!t.contains(this.currentItem[0],this.containers[n].element[0]))if(this._intersectsWith(this.containers[n].containerCache)){if(f&&t.contains(this.containers[n].element[0],f.element[0]))continue;f=this.containers[n],g=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",s,this._uiHash(this)),this.containers[n].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[g].containerCache.over||(this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1);else{for(a=1e4,r=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",c=this.positionAbs[h]+this.offset.click[h],o=this.items.length-1;o>=0;o--)t.contains(this.containers[g].element[0],this.items[o].item[0])&&this.items[o].item[0]!==this.currentItem[0]&&(!p||e(this.positionAbs.top+this.offset.click.top,this.items[o].top,this.items[o].height))&&(u=this.items[o].item.offset()[h],d=!1,Math.abs(u-c)>Math.abs(u+this.items[o][l]-c)&&(d=!0,u+=this.items[o][l]),a>Math.abs(u-c)&&(a=Math.abs(u-c),r=this.items[o],this.direction=d?"up":"down"));if(!r&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[g])return;r?this._rearrange(s,r,null,!0):this._rearrange(s,null,this.containers[g].element,!0),this._trigger("change",s,this._uiHash()),this.containers[g]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[g],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,t("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(t("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(o=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(a=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!e){for(this._trigger("beforeStop",t,this._uiHash()),s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}if(e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})})(jQuery);(function(e){var t=0,i={},a={};i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="hide",a.height=a.paddingTop=a.paddingBottom=a.borderTopWidth=a.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.10.4",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e(),content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),undefined):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t),undefined)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,a=this.headers.length,s=this.headers.index(t.target),n=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:n=this.headers[(s+1)%a];break;case i.LEFT:case i.UP:n=this.headers[(s-1+a)%a];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:n=this.headers[0];break;case i.END:n=this.headers[a-1]}n&&(e(t.target).attr("tabIndex",-1),e(n).attr("tabIndex",0),n.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var i,a=this.options,s=a.heightStyle,n=this.element.parent(),r=this.accordionId="ui-accordion-"+(this.element.attr("id")||++t);this.active=this._findActive(a.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(t){var i=e(this),a=i.attr("id"),s=i.next(),n=s.attr("id");a||(a=r+"-header-"+t,i.attr("id",a)),n||(n=r+"-panel-"+t,s.attr("id",n)),i.attr("aria-controls",n),s.attr("aria-labelledby",a)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(a.event),"fill"===s?(i=n.height(),this.element.siblings(":visible").each(function(){var t=e(this),a=t.css("position");"absolute"!==a&&"fixed"!==a&&(i-=t.outerHeight(!0))}),this.headers.each(function(){i-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,i-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===s&&(i=0,this.headers.next().each(function(){i=Math.max(i,e(this).css("height","").height())}).height(i))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,a=this.active,s=e(t.currentTarget),n=s[0]===a[0],r=n&&i.collapsible,o=r?e():s.next(),h=a.next(),d={oldHeader:a,oldPanel:h,newHeader:r?e():s,newPanel:o};t.preventDefault(),n&&!i.collapsible||this._trigger("beforeActivate",t,d)===!1||(i.active=r?!1:this.headers.index(s),this.active=n?e():s,this._toggle(d),a.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&a.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),n||(s.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),s.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var i=t.newPanel,a=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=a,this.options.animate?this._animate(i,a,t):(a.hide(),i.show(),this._toggleComplete(t)),a.attr({"aria-hidden":"true"}),a.prev().attr("aria-selected","false"),i.length&&a.length?a.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true",tabIndex:0,"aria-expanded":"true"})},_animate:function(e,t,s){var n,r,o,h=this,d=0,c=e.length&&(!t.length||e.index()<t.index()),l=this.options.animate||{},u=c&&l.down||l,v=function(){h._toggleComplete(s)};return"number"==typeof u&&(o=u),"string"==typeof u&&(r=u),r=r||u.easing||l.easing,o=o||u.duration||l.duration,t.length?e.length?(n=e.show().outerHeight(),t.animate(i,{duration:o,easing:r,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(a,{duration:o,easing:r,complete:v,step:function(e,i){i.now=Math.round(e),"height"!==i.prop?d+=i.now:"content"!==h.options.heightStyle&&(i.now=Math.round(n-t.outerHeight()-d),d=0)}}),undefined):t.animate(i,o,r,v):e.animate(a,o,r,v)},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}})})(jQuery);(function(e){e.widget("ui.autocomplete",{version:"1.10.4",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,undefined;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:case a.NUMPAD_ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),undefined;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),undefined):(this._searchTimeout(e),undefined)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,undefined):(clearTimeout(this.searching),this.close(e),this._change(e),undefined)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),undefined;var s=i.item.data("ui-autocomplete-item");!1!==this._trigger("focus",t,{item:s})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value):this.liveRegion.text(s.value)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertBefore(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length<this.options.minLength?this.close(t):this._trigger("search",t)!==!1?this._search(e):undefined},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var t=++this.requestIndex;return e.proxy(function(e){t===this.requestIndex&&this.__response(e),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},this)},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return"string"==typeof t?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var i=this.menu.element.empty();this._renderMenu(i,t),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,i){var s=this;e.each(i,function(e,i){s._renderItemData(t,i)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,i){return e("<li>").append(e("<a>").text(i.label)).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this._value(this.term),this.menu.blur(),undefined):(this.menu[e](t),undefined):(this.search(null,t),undefined)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments),this.options.disabled||this.cancelSearch||(t=e&&e.length?this.options.messages.results(e.length):this.options.messages.noResults,this.liveRegion.text(t))}})})(jQuery);(function(e){var t,i="ui-button ui-widget ui-state-default ui-corner-all",n="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",s=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},a=function(t){var i=t.name,n=t.form,s=e([]);return i&&(i=i.replace(/'/g,"\\'"),s=n?e(n).find("[name='"+i+"']"):e("[name='"+i+"']",t.ownerDocument).filter(function(){return!this.form})),s};e.widget("ui.button",{version:"1.10.4",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,s),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var n=this,o=this.options,r="checkbox"===this.type||"radio"===this.type,h=r?"":"ui-state-active";null===o.label&&(o.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(i).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){o.disabled||this===t&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){o.disabled||e(this).removeClass(h)}).bind("click"+this.eventNamespace,function(e){o.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this._on({focus:function(){this.buttonElement.addClass("ui-state-focus")},blur:function(){this.buttonElement.removeClass("ui-state-focus")}}),r&&this.element.bind("change"+this.eventNamespace,function(){n.refresh()}),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return o.disabled?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(o.disabled)return!1;e(this).addClass("ui-state-active"),n.buttonElement.attr("aria-pressed","true");var t=n.element[0];a(t).not(t).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return o.disabled?!1:(e(this).addClass("ui-state-active"),t=this,n.document.one("mouseup",function(){t=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return o.disabled?!1:(e(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(t){return o.disabled?!1:((t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",o.disabled),this._resetButton()},_determineButtonType:function(){var e,t,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(i+" ui-state-active "+n).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){return this._super(e,t),"disabled"===e?(this.element.prop("disabled",!!t),t&&this.buttonElement.removeClass("ui-state-focus"),undefined):(this._resetButton(),undefined)},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),"radio"===this.type?a(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var t=this.buttonElement.removeClass(n),i=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),s=this.options.icons,a=s.primary&&s.secondary,o=[];s.primary||s.secondary?(this.options.text&&o.push("ui-button-text-icon"+(a?"s":s.primary?"-primary":"-secondary")),s.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+s.primary+"'></span>"),s.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+s.secondary+"'></span>"),this.options.text||(o.push(a?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(i)))):o.push("ui-button-text-only"),t.addClass(o.join(" "))}}),e.widget("ui.buttonset",{version:"1.10.4",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){"disabled"===e&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(e,t){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.dpDiv=a(e("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function a(t){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(i,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",function(){e.datepicker._isDisabledDatepicker(n.inline?t.parent()[0]:n.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))})}function s(t,i){e.extend(t,i);for(var a in i)null==i[a]&&(t[a]=i[a]);return t}e.extend(e.ui,{datepicker:{version:"1.10.4"}});var n,r="datepicker";e.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return s(this._defaults,e||{}),this},_attachDatepicker:function(t,i){var a,s,n;a=t.nodeName.toLowerCase(),s="div"===a||"span"===a,t.id||(this.uuid+=1,t.id="dp"+this.uuid),n=this._newInst(e(t),s),n.settings=e.extend({},i||{}),"input"===a?this._connectDatepicker(t,n):s&&this._inlineDatepicker(t,n)},_newInst:function(t,i){var s=t[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:s,input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?a(e("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(t,i){var a=e(t);i.append=e([]),i.trigger=e([]),a.hasClass(this.markerClassName)||(this._attachments(a,i),a.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),e.data(t,r,i),i.settings.disabled&&this._disableDatepicker(t))},_attachments:function(t,i){var a,s,n,r=this._get(i,"appendText"),o=this._get(i,"isRTL");i.append&&i.append.remove(),r&&(i.append=e("<span class='"+this._appendClass+"'>"+r+"</span>"),t[o?"before":"after"](i.append)),t.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),a=this._get(i,"showOn"),("focus"===a||"both"===a)&&t.focus(this._showDatepicker),("button"===a||"both"===a)&&(s=this._get(i,"buttonText"),n=this._get(i,"buttonImage"),i.trigger=e(this._get(i,"buttonImageOnly")?e("<img/>").addClass(this._triggerClass).attr({src:n,alt:s,title:s}):e("<button type='button'></button>").addClass(this._triggerClass).html(n?e("<img/>").attr({src:n,alt:s,title:s}):s)),t[o?"before":"after"](i.trigger),i.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,i,a,s,n=new Date(2009,11,20),r=this._get(e,"dateFormat");r.match(/[DM]/)&&(t=function(e){for(i=0,a=0,s=0;e.length>s;s++)e[s].length>i&&(i=e[s].length,a=s);return a},n.setMonth(t(this._get(e,r.match(/MM/)?"monthNames":"monthNamesShort"))),n.setDate(t(this._get(e,r.match(/DD/)?"dayNames":"dayNamesShort"))+20-n.getDay())),e.input.attr("size",this._formatDate(e,n).length)}},_inlineDatepicker:function(t,i){var a=e(t);a.hasClass(this.markerClassName)||(a.addClass(this.markerClassName).append(i.dpDiv),e.data(t,r,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(t),i.dpDiv.css("display","block"))},_dialogDatepicker:function(t,i,a,n,o){var u,c,h,l,d,p=this._dialogInst;return p||(this.uuid+=1,u="dp"+this.uuid,this._dialogInput=e("<input type='text' id='"+u+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},e.data(this._dialogInput[0],r,p)),s(p.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(c=document.documentElement.clientWidth,h=document.documentElement.clientHeight,l=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[c/2-100+l,h/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=a,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],r,p),this},_destroyDatepicker:function(t){var i,a=e(t),s=e.data(t,r);a.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),e.removeData(t,r),"input"===i?(s.append.remove(),s.trigger.remove(),a.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&a.removeClass(this.markerClassName).empty())},_enableDatepicker:function(t){var i,a,s=e(t),n=e.data(t,r);s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!1,n.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(a=s.children("."+this._inlineClass),a.children().removeClass("ui-state-disabled"),a.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var i,a,s=e(t),n=e.data(t,r);s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!0,n.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(a=s.children("."+this._inlineClass),a.children().addClass("ui-state-disabled"),a.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,r)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,a,n){var r,o,u,c,h=this._getInst(i);return 2===arguments.length&&"string"==typeof a?"defaults"===a?e.extend({},e.datepicker._defaults):h?"all"===a?e.extend({},h.settings):this._get(h,a):null:(r=a||{},"string"==typeof a&&(r={},r[a]=n),h&&(this._curInst===h&&this._hideDatepicker(),o=this._getDateDatepicker(i,!0),u=this._getMinMaxDate(h,"min"),c=this._getMinMaxDate(h,"max"),s(h.settings,r),null!==u&&r.dateFormat!==t&&r.minDate===t&&(h.settings.minDate=this._formatDate(h,u)),null!==c&&r.dateFormat!==t&&r.maxDate===t&&(h.settings.maxDate=this._formatDate(h,c)),"disabled"in r&&(r.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(e(i),h),this._autoSize(h),this._setDate(h,o),this._updateAlternate(h),this._updateDatepicker(h)),t)},_changeDatepicker:function(e,t,i){this._optionDatepicker(e,t,i)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var i=this._getInst(e);i&&(this._setDate(i,t),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(e,t){var i=this._getInst(e);return i&&!i.inline&&this._setDateFromField(i,t),i?this._getDate(i):null},_doKeyDown:function(t){var i,a,s,n=e.datepicker._getInst(t.target),r=!0,o=n.dpDiv.is(".ui-datepicker-rtl");if(n._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),r=!1;break;case 13:return s=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",n.dpDiv),s[0]&&e.datepicker._selectDay(t.target,n.selectedMonth,n.selectedYear,s[0]),i=e.datepicker._get(n,"onSelect"),i?(a=e.datepicker._formatDate(n),i.apply(n.input?n.input[0]:null,[a,n])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(n,"stepBigMonths"):-e.datepicker._get(n,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(n,"stepBigMonths"):+e.datepicker._get(n,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),r=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),r=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,o?1:-1,"D"),r=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(n,"stepBigMonths"):-e.datepicker._get(n,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),r=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,o?-1:1,"D"),r=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(n,"stepBigMonths"):+e.datepicker._get(n,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),r=t.ctrlKey||t.metaKey;break;default:r=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):r=!1;r&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(i){var a,s,n=e.datepicker._getInst(i.target);return e.datepicker._get(n,"constrainInput")?(a=e.datepicker._possibleChars(e.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">s||!a||a.indexOf(s)>-1):t},_doKeyUp:function(t){var i,a=e.datepicker._getInst(t.target);if(a.input.val()!==a.lastVal)try{i=e.datepicker.parseDate(e.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,e.datepicker._getFormatConfig(a)),i&&(e.datepicker._setDateFromField(a),e.datepicker._updateAlternate(a),e.datepicker._updateDatepicker(a))}catch(s){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,a,n,r,o,u,c;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),a=e.datepicker._get(i,"beforeShow"),n=a?a.apply(t,[t,i]):{},n!==!1&&(s(i.settings,n),i.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(i),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),r=!1,e(t).parents().each(function(){return r|="fixed"===e(this).css("position"),!r}),o={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(i),o=e.datepicker._checkOffset(i,o,r),i.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":r?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),i.inline||(u=e.datepicker._get(i,"showAnim"),c=e.datepicker._get(i,"duration"),i.dpDiv.zIndex(e(t).zIndex()+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[u]?i.dpDiv.show(u,e.datepicker._get(i,"showOptions"),c):i.dpDiv[u||"show"](u?c:null),e.datepicker._shouldFocusInput(i)&&i.input.focus(),e.datepicker._curInst=i))}},_updateDatepicker:function(t){this.maxRows=4,n=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t),t.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,a=this._getNumberOfMonths(t),s=a[1],r=17;t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),s>1&&t.dpDiv.addClass("ui-datepicker-multi-"+s).css("width",r*s+"em"),t.dpDiv[(1!==a[0]||1!==a[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(i=t.yearshtml,setTimeout(function(){i===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),i=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&!e.input.is(":focus")},_checkOffset:function(t,i,a){var s=t.dpDiv.outerWidth(),n=t.dpDiv.outerHeight(),r=t.input?t.input.outerWidth():0,o=t.input?t.input.outerHeight():0,u=document.documentElement.clientWidth+(a?0:e(document).scrollLeft()),c=document.documentElement.clientHeight+(a?0:e(document).scrollTop());return i.left-=this._get(t,"isRTL")?s-r:0,i.left-=a&&i.left===t.input.offset().left?e(document).scrollLeft():0,i.top-=a&&i.top===t.input.offset().top+o?e(document).scrollTop():0,i.left-=Math.min(i.left,i.left+s>u&&u>s?Math.abs(i.left+s-u):0),i.top-=Math.min(i.top,i.top+n>c&&c>n?Math.abs(n+o):0),i},_findPos:function(t){for(var i,a=this._getInst(t),s=this._get(a,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[s?"previousSibling":"nextSibling"];return i=e(t).offset(),[i.left,i.top]},_hideDatepicker:function(t){var i,a,s,n,o=this._curInst;!o||t&&o!==e.data(t,r)||this._datepickerShowing&&(i=this._get(o,"showAnim"),a=this._get(o,"duration"),s=function(){e.datepicker._tidyDialog(o)},e.effects&&(e.effects.effect[i]||e.effects[i])?o.dpDiv.hide(i,e.datepicker._get(o,"showOptions"),a,s):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?a:null,s),i||s(),this._datepickerShowing=!1,n=this._get(o,"onClose"),n&&n.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(e.datepicker._curInst){var i=e(t.target),a=e.datepicker._getInst(i[0]);(i[0].id!==e.datepicker._mainDivId&&0===i.parents("#"+e.datepicker._mainDivId).length&&!i.hasClass(e.datepicker.markerClassName)&&!i.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||i.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==a)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,i,a){var s=e(t),n=this._getInst(s[0]);this._isDisabledDatepicker(s[0])||(this._adjustInstDate(n,i+("M"===a?this._get(n,"showCurrentAtPos"):0),a),this._updateDatepicker(n))},_gotoToday:function(t){var i,a=e(t),s=this._getInst(a[0]);this._get(s,"gotoCurrent")&&s.currentDay?(s.selectedDay=s.currentDay,s.drawMonth=s.selectedMonth=s.currentMonth,s.drawYear=s.selectedYear=s.currentYear):(i=new Date,s.selectedDay=i.getDate(),s.drawMonth=s.selectedMonth=i.getMonth(),s.drawYear=s.selectedYear=i.getFullYear()),this._notifyChange(s),this._adjustDate(a)},_selectMonthYear:function(t,i,a){var s=e(t),n=this._getInst(s[0]);n["selected"+("M"===a?"Month":"Year")]=n["draw"+("M"===a?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(n),this._adjustDate(s)},_selectDay:function(t,i,a,s){var n,r=e(t);e(s).hasClass(this._unselectableClass)||this._isDisabledDatepicker(r[0])||(n=this._getInst(r[0]),n.selectedDay=n.currentDay=e("a",s).html(),n.selectedMonth=n.currentMonth=i,n.selectedYear=n.currentYear=a,this._selectDate(t,this._formatDate(n,n.currentDay,n.currentMonth,n.currentYear)))},_clearDate:function(t){var i=e(t);this._selectDate(i,"")},_selectDate:function(t,i){var a,s=e(t),n=this._getInst(s[0]);i=null!=i?i:this._formatDate(n),n.input&&n.input.val(i),this._updateAlternate(n),a=this._get(n,"onSelect"),a?a.apply(n.input?n.input[0]:null,[i,n]):n.input&&n.input.trigger("change"),n.inline?this._updateDatepicker(n):(this._hideDatepicker(),this._lastInput=n.input[0],"object"!=typeof n.input[0]&&n.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var i,a,s,n=this._get(t,"altField");n&&(i=this._get(t,"altFormat")||this._get(t,"dateFormat"),a=this._getDate(t),s=this.formatDate(i,a,this._getFormatConfig(t)),e(n).each(function(){e(this).val(s)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,""]},iso8601Week:function(e){var t,i=new Date(e.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),t=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((t-i)/864e5)/7)+1},parseDate:function(i,a,s){if(null==i||null==a)throw"Invalid arguments";if(a="object"==typeof a?""+a:a+"",""===a)return null;var n,r,o,u,c=0,h=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,l="string"!=typeof h?h:(new Date).getFullYear()%100+parseInt(h,10),d=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,p=(s?s.dayNames:null)||this._defaults.dayNames,g=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,m=(s?s.monthNames:null)||this._defaults.monthNames,f=-1,_=-1,v=-1,k=-1,y=!1,b=function(e){var t=i.length>n+1&&i.charAt(n+1)===e;return t&&n++,t},D=function(e){var t=b(e),i="@"===e?14:"!"===e?20:"y"===e&&t?4:"o"===e?3:2,s=RegExp("^\\d{1,"+i+"}"),n=a.substring(c).match(s);if(!n)throw"Missing number at position "+c;return c+=n[0].length,parseInt(n[0],10)},w=function(i,s,n){var r=-1,o=e.map(b(i)?n:s,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(o,function(e,i){var s=i[1];return a.substr(c,s.length).toLowerCase()===s.toLowerCase()?(r=i[0],c+=s.length,!1):t}),-1!==r)return r+1;throw"Unknown name at position "+c},M=function(){if(a.charAt(c)!==i.charAt(n))throw"Unexpected literal at position "+c;c++};for(n=0;i.length>n;n++)if(y)"'"!==i.charAt(n)||b("'")?M():y=!1;else switch(i.charAt(n)){case"d":v=D("d");break;case"D":w("D",d,p);break;case"o":k=D("o");break;case"m":_=D("m");break;case"M":_=w("M",g,m);break;case"y":f=D("y");break;case"@":u=new Date(D("@")),f=u.getFullYear(),_=u.getMonth()+1,v=u.getDate();break;case"!":u=new Date((D("!")-this._ticksTo1970)/1e4),f=u.getFullYear(),_=u.getMonth()+1,v=u.getDate();break;case"'":b("'")?M():y=!0;break;default:M()}if(a.length>c&&(o=a.substr(c),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===f?f=(new Date).getFullYear():100>f&&(f+=(new Date).getFullYear()-(new Date).getFullYear()%100+(l>=f?0:-100)),k>-1)for(_=1,v=k;;){if(r=this._getDaysInMonth(f,_-1),r>=v)break;_++,v-=r}if(u=this._daylightSavingAdjust(new Date(f,_-1,v)),u.getFullYear()!==f||u.getMonth()+1!==_||u.getDate()!==v)throw"Invalid date";return u},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,i){if(!t)return"";var a,s=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,n=(i?i.dayNames:null)||this._defaults.dayNames,r=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,o=(i?i.monthNames:null)||this._defaults.monthNames,u=function(t){var i=e.length>a+1&&e.charAt(a+1)===t;return i&&a++,i},c=function(e,t,i){var a=""+t;if(u(e))for(;i>a.length;)a="0"+a;return a},h=function(e,t,i,a){return u(e)?a[t]:i[t]},l="",d=!1;if(t)for(a=0;e.length>a;a++)if(d)"'"!==e.charAt(a)||u("'")?l+=e.charAt(a):d=!1;else switch(e.charAt(a)){case"d":l+=c("d",t.getDate(),2);break;case"D":l+=h("D",t.getDay(),s,n);break;case"o":l+=c("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":l+=c("m",t.getMonth()+1,2);break;case"M":l+=h("M",t.getMonth(),r,o);break;case"y":l+=u("y")?t.getFullYear():(10>t.getYear()%100?"0":"")+t.getYear()%100;break;case"@":l+=t.getTime();break;case"!":l+=1e4*t.getTime()+this._ticksTo1970;break;case"'":u("'")?l+="'":d=!0;break;default:l+=e.charAt(a)}return l},_possibleChars:function(e){var t,i="",a=!1,s=function(i){var a=e.length>t+1&&e.charAt(t+1)===i;return a&&t++,a};for(t=0;e.length>t;t++)if(a)"'"!==e.charAt(t)||s("'")?i+=e.charAt(t):a=!1;else switch(e.charAt(t)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":s("'")?i+="'":a=!0;break;default:i+=e.charAt(t)}return i},_get:function(e,i){return e.settings[i]!==t?e.settings[i]:this._defaults[i]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var i=this._get(e,"dateFormat"),a=e.lastVal=e.input?e.input.val():null,s=this._getDefaultDate(e),n=s,r=this._getFormatConfig(e);try{n=this.parseDate(i,a,r)||s}catch(o){a=t?"":a}e.selectedDay=n.getDate(),e.drawMonth=e.selectedMonth=n.getMonth(),e.drawYear=e.selectedYear=n.getFullYear(),e.currentDay=a?n.getDate():0,e.currentMonth=a?n.getMonth():0,e.currentYear=a?n.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,i,a){var s=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},n=function(i){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),i,e.datepicker._getFormatConfig(t))}catch(a){}for(var s=(i.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,n=s.getFullYear(),r=s.getMonth(),o=s.getDate(),u=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,c=u.exec(i);c;){switch(c[2]||"d"){case"d":case"D":o+=parseInt(c[1],10);break;case"w":case"W":o+=7*parseInt(c[1],10);break;case"m":case"M":r+=parseInt(c[1],10),o=Math.min(o,e.datepicker._getDaysInMonth(n,r));break;case"y":case"Y":n+=parseInt(c[1],10),o=Math.min(o,e.datepicker._getDaysInMonth(n,r))}c=u.exec(i)}return new Date(n,r,o)},r=null==i||""===i?a:"string"==typeof i?n(i):"number"==typeof i?isNaN(i)?a:s(i):new Date(i.getTime());return r=r&&"Invalid Date"==""+r?a:r,r&&(r.setHours(0),r.setMinutes(0),r.setSeconds(0),r.setMilliseconds(0)),this._daylightSavingAdjust(r)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,i){var a=!t,s=e.selectedMonth,n=e.selectedYear,r=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=r.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=r.getMonth(),e.drawYear=e.selectedYear=e.currentYear=r.getFullYear(),s===e.selectedMonth&&n===e.selectedYear||i||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(a?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&""===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var i=this._get(t,"stepMonths"),a="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){e.datepicker._adjustDate(a,-i,"M")},next:function(){e.datepicker._adjustDate(a,+i,"M")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(a)},selectDay:function(){return e.datepicker._selectDay(a,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(a,this,"M"),!1},selectYear:function(){return e.datepicker._selectMonthYear(a,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,i,a,s,n,r,o,u,c,h,l,d,p,g,m,f,_,v,k,y,b,D,w,M,C,x,I,N,T,A,E,S,Y,F,P,O,j,K,R,H=new Date,W=this._daylightSavingAdjust(new Date(H.getFullYear(),H.getMonth(),H.getDate())),L=this._get(e,"isRTL"),U=this._get(e,"showButtonPanel"),B=this._get(e,"hideIfNoPrevNext"),z=this._get(e,"navigationAsDateFormat"),q=this._getNumberOfMonths(e),G=this._get(e,"showCurrentAtPos"),J=this._get(e,"stepMonths"),Q=1!==q[0]||1!==q[1],V=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),$=this._getMinMaxDate(e,"min"),X=this._getMinMaxDate(e,"max"),Z=e.drawMonth-G,et=e.drawYear;if(0>Z&&(Z+=12,et--),X)for(t=this._daylightSavingAdjust(new Date(X.getFullYear(),X.getMonth()-q[0]*q[1]+1,X.getDate())),t=$&&$>t?$:t;this._daylightSavingAdjust(new Date(et,Z,1))>t;)Z--,0>Z&&(Z=11,et--);for(e.drawMonth=Z,e.drawYear=et,i=this._get(e,"prevText"),i=z?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z-J,1)),this._getFormatConfig(e)):i,a=this._canAdjustMonth(e,-1,et,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"e":"w")+"'>"+i+"</span></a>":B?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"e":"w")+"'>"+i+"</span></a>",s=this._get(e,"nextText"),s=z?this.formatDate(s,this._daylightSavingAdjust(new Date(et,Z+J,1)),this._getFormatConfig(e)):s,n=this._canAdjustMonth(e,1,et,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+s+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"w":"e")+"'>"+s+"</span></a>":B?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+s+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"w":"e")+"'>"+s+"</span></a>",r=this._get(e,"currentText"),o=this._get(e,"gotoCurrent")&&e.currentDay?V:W,r=z?this.formatDate(r,o,this._getFormatConfig(e)):r,u=e.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(e,"closeText")+"</button>",c=U?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(L?u:"")+(this._isInRange(e,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+r+"</button>":"")+(L?"":u)+"</div>":"",h=parseInt(this._get(e,"firstDay"),10),h=isNaN(h)?0:h,l=this._get(e,"showWeek"),d=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),g=this._get(e,"monthNames"),m=this._get(e,"monthNamesShort"),f=this._get(e,"beforeShowDay"),_=this._get(e,"showOtherMonths"),v=this._get(e,"selectOtherMonths"),k=this._getDefaultDate(e),y="",D=0;q[0]>D;D++){for(w="",this.maxRows=4,M=0;q[1]>M;M++){if(C=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),x=" ui-corner-all",I="",Q){if(I+="<div class='ui-datepicker-group",q[1]>1)switch(M){case 0:I+=" ui-datepicker-group-first",x=" ui-corner-"+(L?"right":"left");break;case q[1]-1:I+=" ui-datepicker-group-last",x=" ui-corner-"+(L?"left":"right");break;default:I+=" ui-datepicker-group-middle",x=""}I+="'>"}for(I+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+x+"'>"+(/all|left/.test(x)&&0===D?L?n:a:"")+(/all|right/.test(x)&&0===D?L?a:n:"")+this._generateMonthYearHeader(e,Z,et,$,X,D>0||M>0,g,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",N=l?"<th class='ui-datepicker-week-col'>"+this._get(e,"weekHeader")+"</th>":"",b=0;7>b;b++)T=(b+h)%7,N+="<th"+((b+h+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[T]+"'>"+p[T]+"</span></th>";for(I+=N+"</tr></thead><tbody>",A=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,A)),E=(this._getFirstDayOfMonth(et,Z)-h+7)%7,S=Math.ceil((E+A)/7),Y=Q?this.maxRows>S?this.maxRows:S:S,this.maxRows=Y,F=this._daylightSavingAdjust(new Date(et,Z,1-E)),P=0;Y>P;P++){for(I+="<tr>",O=l?"<td class='ui-datepicker-week-col'>"+this._get(e,"calculateWeek")(F)+"</td>":"",b=0;7>b;b++)j=f?f.apply(e.input?e.input[0]:null,[F]):[!0,""],K=F.getMonth()!==Z,R=K&&!v||!j[0]||$&&$>F||X&&F>X,O+="<td class='"+((b+h+6)%7>=5?" ui-datepicker-week-end":"")+(K?" ui-datepicker-other-month":"")+(F.getTime()===C.getTime()&&Z===e.selectedMonth&&e._keyEvent||k.getTime()===F.getTime()&&k.getTime()===C.getTime()?" "+this._dayOverClass:"")+(R?" "+this._unselectableClass+" ui-state-disabled":"")+(K&&!_?"":" "+j[1]+(F.getTime()===V.getTime()?" "+this._currentClass:"")+(F.getTime()===W.getTime()?" ui-datepicker-today":""))+"'"+(K&&!_||!j[2]?"":" title='"+j[2].replace(/'/g,"&#39;")+"'")+(R?"":" data-handler='selectDay' data-event='click' data-month='"+F.getMonth()+"' data-year='"+F.getFullYear()+"'")+">"+(K&&!_?"&#xa0;":R?"<span class='ui-state-default'>"+F.getDate()+"</span>":"<a class='ui-state-default"+(F.getTime()===W.getTime()?" ui-state-highlight":"")+(F.getTime()===V.getTime()?" ui-state-active":"")+(K?" ui-priority-secondary":"")+"' href='#'>"+F.getDate()+"</a>")+"</td>",F.setDate(F.getDate()+1),F=this._daylightSavingAdjust(F);I+=O+"</tr>"}Z++,Z>11&&(Z=0,et++),I+="</tbody></table>"+(Q?"</div>"+(q[0]>0&&M===q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),w+=I}y+=w}return y+=c,e._keyEvent=!1,y},_generateMonthYearHeader:function(e,t,i,a,s,n,r,o){var u,c,h,l,d,p,g,m,f=this._get(e,"changeMonth"),_=this._get(e,"changeYear"),v=this._get(e,"showMonthAfterYear"),k="<div class='ui-datepicker-title'>",y="";if(n||!f)y+="<span class='ui-datepicker-month'>"+r[t]+"</span>";else{for(u=a&&a.getFullYear()===i,c=s&&s.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",h=0;12>h;h++)(!u||h>=a.getMonth())&&(!c||s.getMonth()>=h)&&(y+="<option value='"+h+"'"+(h===t?" selected='selected'":"")+">"+o[h]+"</option>");y+="</select>"}if(v||(k+=y+(!n&&f&&_?"":"&#xa0;")),!e.yearshtml)if(e.yearshtml="",n||!_)k+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(l=this._get(e,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?i+parseInt(e.substring(1),10):e.match(/[+\-].*/)?d+parseInt(e,10):parseInt(e,10);
+return isNaN(t)?d:t},g=p(l[0]),m=Math.max(g,p(l[1]||"")),g=a?Math.max(g,a.getFullYear()):g,m=s?Math.min(m,s.getFullYear()):m,e.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=g;g++)e.yearshtml+="<option value='"+g+"'"+(g===i?" selected='selected'":"")+">"+g+"</option>";e.yearshtml+="</select>",k+=e.yearshtml,e.yearshtml=null}return k+=this._get(e,"yearSuffix"),v&&(k+=(!n&&f&&_?"":"&#xa0;")+y),k+="</div>"},_adjustInstDate:function(e,t,i){var a=e.drawYear+("Y"===i?t:0),s=e.drawMonth+("M"===i?t:0),n=Math.min(e.selectedDay,this._getDaysInMonth(a,s))+("D"===i?t:0),r=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(a,s,n)));e.selectedDay=r.getDate(),e.drawMonth=e.selectedMonth=r.getMonth(),e.drawYear=e.selectedYear=r.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var i=this._getMinMaxDate(e,"min"),a=this._getMinMaxDate(e,"max"),s=i&&i>t?i:t;return a&&s>a?a:s},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,i,a){var s=this._getNumberOfMonths(e),n=this._daylightSavingAdjust(new Date(i,a+(0>t?t:s[0]*s[1]),1));return 0>t&&n.setDate(this._getDaysInMonth(n.getFullYear(),n.getMonth())),this._isInRange(e,n)},_isInRange:function(e,t){var i,a,s=this._getMinMaxDate(e,"min"),n=this._getMinMaxDate(e,"max"),r=null,o=null,u=this._get(e,"yearRange");return u&&(i=u.split(":"),a=(new Date).getFullYear(),r=parseInt(i[0],10),o=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(r+=a),i[1].match(/[+\-].*/)&&(o+=a)),(!s||t.getTime()>=s.getTime())&&(!n||t.getTime()<=n.getTime())&&(!r||t.getFullYear()>=r)&&(!o||o>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t="string"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,i,a){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var s=t?"object"==typeof t?t:this._daylightSavingAdjust(new Date(a,i,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),s,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e("#"+e.datepicker._mainDivId).length&&e("body").append(e.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof t||"isDisabled"!==t&&"getDate"!==t&&"widget"!==t?"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof t?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(i)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i))},e.datepicker=new i,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.10.4"})(jQuery);(function(e){var t={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.10.4",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i,a=this;if(this._isOpen&&this._trigger("beforeClose",t)!==!1){if(this._isOpen=!1,this._destroyOverlay(),!this.opener.filter(":focusable").focus().length)try{i=this.document[0].activeElement,i&&"body"!==i.nodeName.toLowerCase()&&e(i).blur()}catch(s){}this._hide(this.uiDialog,this.options.hide,function(){a._trigger("close",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,t){var i=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return i&&!t&&this._trigger("focus",e),i},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),undefined):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._trigger("open"),undefined)},_focusTabbable:function(){var e=this.element.find("[autofocus]");e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),undefined;if(t.keyCode===e.ui.keyCode.TAB){var i=this.uiDialog.find(":tabbable"),a=i.filter(":first"),s=i.filter(":last");t.target!==s[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==a[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(s.focus(1),t.preventDefault()):(a.focus(1),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button type='button'></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html("&#160;"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),undefined):(e.each(i,function(i,a){var s,n;a=e.isFunction(a)?{click:a,text:i}:a,a=e.extend({type:"button"},a),s=a.click,a.click=function(){s.apply(t.element[0],arguments)},n={icons:a.icons,text:a.showText},delete a.icons,delete a.showText,e("<button></button>",a).button(n).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),undefined)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,a=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(a,s){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",a,t(s))},drag:function(e,a){i._trigger("drag",e,t(a))},stop:function(s,n){a.position=[n.position.left-i.document.scrollLeft(),n.position.top-i.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",s,t(n))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,a=this.options,s=a.resizable,n=this.uiDialog.css("position"),r="string"==typeof s?s:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:a.maxWidth,maxHeight:a.maxHeight,minWidth:a.minWidth,minHeight:this._minHeight(),handles:r,start:function(a,s){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",a,t(s))},resize:function(e,a){i._trigger("resize",e,t(a))},stop:function(s,n){a.height=e(this).height(),a.width=e(this).width(),e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",s,t(n))}}).css("position",n)},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(a){var s=this,n=!1,r={};e.each(a,function(e,a){s._setOption(e,a),e in t&&(n=!0),e in i&&(r[e]=a)}),n&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",r)},_setOption:function(e,t){var i,a,s=this.uiDialog;"dialogClass"===e&&s.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=s.is(":data(ui-draggable)"),i&&!t&&s.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(a=s.is(":data(ui-resizable)"),a&&!t&&s.resizable("destroy"),a&&"string"==typeof t&&s.resizable("option","handles",t),a||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,a=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),a.minWidth>a.width&&(a.width=a.minWidth),e=this.uiDialog.css({height:"auto",width:a.width}).outerHeight(),t=Math.max(0,a.minHeight-e),i="number"==typeof a.maxHeight?Math.max(0,a.maxHeight-e):"none","auto"===a.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,a.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=this,i=this.widgetFullName;e.ui.dialog.overlayInstances||this._delay(function(){e.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(a){t._allowInteraction(a)||(a.preventDefault(),e(".ui-dialog:visible:last .ui-dialog-content").data(i)._focusTabbable())})}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),e.ui.dialog.overlayInstances++}},_destroyOverlay:function(){this.options.modal&&this.overlay&&(e.ui.dialog.overlayInstances--,e.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),e.ui.dialog.overlayInstances=0,e.uiBackCompat!==!1&&e.widget("ui.dialog",e.ui.dialog,{_position:function(){var t,i=this.options.position,a=[],s=[0,0];i?(("string"==typeof i||"object"==typeof i&&"0"in i)&&(a=i.split?i.split(" "):[i[0],i[1]],1===a.length&&(a[1]=a[0]),e.each(["left","top"],function(e,t){+a[e]===a[e]&&(s[e]=a[e],a[e]=t)}),i={my:a[0]+(0>s[0]?s[0]:"+"+s[0])+" "+a[1]+(0>s[1]?s[1]:"+"+s[1]),at:a.join(" ")}),i=e.extend({},e.ui.dialog.prototype.options.position,i)):i=e.ui.dialog.prototype.options.position,t=this.uiDialog.is(":visible"),t||this.uiDialog.show(),this.uiDialog.position(i),t||this.uiDialog.hide()}})})(jQuery);(function(t){t.widget("ui.menu",{version:"1.10.4",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,t.proxy(function(t){this.options.disabled&&t.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(t){t.preventDefault()},"click .ui-state-disabled > a":function(t){t.preventDefault()},"click .ui-menu-item:has(a)":function(e){var i=t(e.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&t(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){var i=t(e.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(e,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.children(".ui-menu-item").eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){t.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){t(e.target).closest(".ui-menu").length||this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var e=t(this);e.data("ui-menu-submenu-carat")&&e.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(e){function i(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var s,n,a,o,r,l=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:l=!1,n=this.previousFilter||"",a=String.fromCharCode(e.keyCode),o=!1,clearTimeout(this.filterTimer),a===n?o=!0:a=n+a,r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())}),s=o&&-1!==s.index(this.active.next())?this.active.nextAll(".ui-menu-item"):s,s.length||(a=String.fromCharCode(e.keyCode),r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())})),s.length?(this.focus(e,s),s.length>1?(this.previousFilter=a,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}l&&e.preventDefault()},_activate:function(t){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i=this.options.icons.submenu,s=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),s.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),s=e.prev("a"),n=t("<span>").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);s.attr("aria-haspopup","true").prepend(n),e.attr("aria-labelledby",s.attr("id"))}),e=s.add(this.element),e.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),e.children(":not(.ui-menu-item)").each(function(){var e=t(this);/[^\-\u2014\u2013\s]/.test(e.text())||e.addClass("ui-widget-content ui-menu-divider")}),e.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){"icons"===t&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(e.submenu),this._super(t,e)},focus:function(t,e){var i,s;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=e.height(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",t,{item:this.active}))},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.children(".ui-menu-item")[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())),undefined):(this.next(e),undefined)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item").first())),undefined):(this.next(e),undefined)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)}})})(jQuery);(function(t,e){t.widget("ui.progressbar",{version:"1.10.4",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=t("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(t){return t===e?this.options.value:(this.options.value=this._constrainedValue(t),this._refreshValue(),e)},_constrainedValue:function(t){return t===e&&(t=this.options.value),this.indeterminate=t===!1,"number"!=typeof t&&(t=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var e=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=t("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":e}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),e===this.options.max&&this._trigger("complete")}})})(jQuery);(function(t){var e=5;t.widget("ui.slider",t.ui.mouse,{version:"1.10.4",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),a="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)o.push(a);this.handles=n.add(t(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e)})},_createRange:function(){var e=this.options,i="";e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=t("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===e.range||"max"===e.range?" ui-slider-range-"+e.range:""))):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){var t=this.handles.add(this.range).filter("a");this._off(t),this._on(t,this._handleEvents),this._hoverable(t),this._focusable(t)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,a,o,r,l,h,u=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-u.values(e));(n>i||n===i&&(e===u._lastChangedValue||u.values(e)===c.min))&&(n=i,a=t(this),o=e)}),r=this._start(e,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass("ui-state-active").focus(),l=a.offset(),h=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=h?{left:0,top:0}:{left:e.pageX-l.left-a.width()/2,top:e.pageY-l.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,a;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(t,e){var i={handle:this.handles[e],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("start",t,i)},_slide:function(t,e,i){var s,n,a;this.options.values&&this.options.values.length?(s=this.values(e?0:1),2===this.options.values.length&&this.options.range===!0&&(0===e&&i>s||1===e&&s>i)&&(i=s),i!==this.values(e)&&(n=this.values(),n[e]=i,a=this._trigger("slide",t,{handle:this.handles[e],value:i,values:n}),s=this.values(e?0:1),a!==!1&&this.values(e,i))):i!==this.value()&&(a=this._trigger("slide",t,{handle:this.handles[e],value:i}),a!==!1&&this.value(i))},_stop:function(t,e){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("stop",t,i)},_change:function(t,e){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._lastChangedValue=e,this._trigger("change",t,i)}},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),undefined):this._value()},values:function(e,i){var s,n,a;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),undefined;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(e):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),t.Widget.prototype._setOption.apply(this,arguments),e){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e:-e),parseFloat(s.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var e,i,s,n,a,o=this.options.range,r=this.options,l=this,h=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((l.values(s)-l._valueMin())/(l._valueMax()-l._valueMin())),u["horizontal"===l.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[h?"animate":"css"](u,r.animate),l.options.range===!0&&("horizontal"===l.orientation?(0===s&&l.range.stop(1,1)[h?"animate":"css"]({left:i+"%"},r.animate),1===s&&l.range[h?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&l.range.stop(1,1)[h?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&l.range[h?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[h?"animate":"css"](u,r.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({width:i+"%"},r.animate),"max"===o&&"horizontal"===this.orientation&&this.range[h?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({height:i+"%"},r.animate),"max"===o&&"vertical"===this.orientation&&this.range[h?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(i){var s,n,a,o,r=t(i.target).data("ui-slider-handle-index");switch(i.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(i.preventDefault(),!this._keySliding&&(this._keySliding=!0,t(i.target).addClass("ui-state-active"),s=this._start(i,r),s===!1))return}switch(o=this.options.step,n=a=this.options.values&&this.options.values.length?this.values(r):this.value(),i.keyCode){case t.ui.keyCode.HOME:a=this._valueMin();break;case t.ui.keyCode.END:a=this._valueMax();break;case t.ui.keyCode.PAGE_UP:a=this._trimAlignValue(n+(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.PAGE_DOWN:a=this._trimAlignValue(n-(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(n===this._valueMax())return;a=this._trimAlignValue(n+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(n===this._valueMin())return;a=this._trimAlignValue(n-o)}this._slide(i,r,a)},click:function(t){t.preventDefault()},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),t(e.target).removeClass("ui-state-active"))}}})})(jQuery);(function(t){function e(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.widget("ui.spinner",{version:"1.10.4",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e={},i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);void 0!==n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var t=this.element[0]===this.document[0].activeElement;t||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var t=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=t.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*t.height())&&t.height()>0&&t.height(t.height()),this.options.disabled&&this.disable()},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){if("culture"===t||"numberFormat"===t){var i=this._parse(this.element.val());return this.options[t]=e,this.element.val(this._format(i)),void 0}("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(e.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(e.down)),this._super(t,e),"disabled"===t&&(e?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:e(function(t){this._super(t),this._value(this.element.val())}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:e(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:e(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:e(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:e(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(e(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}})})(jQuery);(function(t,e){function i(){return++n}function s(t){return t=t.cloneNode(!1),t.hash.length>1&&decodeURIComponent(t.href.replace(a,""))===decodeURIComponent(location.href.replace(a,""))}var n=0,a=/#.*$/;t.widget("ui.tabs",{version:"1.10.4",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.each(function(s,a){return t(a).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),a=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:a=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;default:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,a),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDisabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var a,o,r,h=t(n).uniqueId().attr("id"),l=t(n).closest("li"),c=l.attr("aria-controls");s(n)?(a=n.hash,o=e.element.find(e._sanitizeSelector(a))):(r=e._tabId(l),a="#"+r,o=e.element.find(a),o.length||(o=e._createPanel(r),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),c&&l.data("ui-tabs-aria-controls",c),l.attr({"aria-controls":a.substring(1),"aria-labelledby":h}),o.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?t():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):t(),c={oldTab:s,oldPanel:l,newTab:r?t():a,newPanel:h};e.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",e,c)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?t():a,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),e),this._toggle(e,c))},_toggle:function(e,i){function s(){a.running=!1,a._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.options.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,a=this.tabs.eq(e),o=a.find(".ui-tabs-anchor"),r=this._getPanelForTab(a),h={tab:a,panel:r};s(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(a.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),a.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href"),beforeSend:function(e,a){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:a},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})})(jQuery);(function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.4",options:{content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,o=e?e.type:null;return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=o),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function o(t){l.of=t,a.is(":hidden")||a.position(l)}var a,r,h,l=t.extend({},this.options.position);if(n){if(a=this._find(s),a.length)return a.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),a=this._tooltip(s),e(s,a.attr("id")),a.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._on(this.document,{mousemove:o}),o(i)):a.position(t.extend({of:s},this.options.position)),a.hide(),this._show(a,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){a.is(":visible")&&(o(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:a}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(a)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),o=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),o.stop(!0),this._hide(o,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:o}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("<div>").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("<div>").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})})(jQuery);(function(t,e){var i="ui-effects-";t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=h(),n=s._rgba=[];return i=i.toLowerCase(),f(l,function(t,a){var o,r=a.re.exec(i),l=r&&a.parse(r),h=a.space||"rgba";return l?(o=s[h](l),s[c[h].cache]=o[c[h].cache],n=s._rgba=o._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,a.transparent),s):a[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,l=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],h=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=h.support={},p=t("<p>")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),h.fn=t.extend(h.prototype,{parse:function(n,o,r,l){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(o),o=e);var u=this,d=t.type(n),p=this._rgba=[];return o!==e&&(n=[n,o,r,l],d="array"),"string"===d?this.parse(s(n)||a._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof h?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var a=s.cache;f(s.props,function(t,e){if(!u[a]&&s.to){if("alpha"===t||null==n[t])return;u[a]=s.to(u._rgba)}u[a][e.idx]=i(n[t],e,!0)}),u[a]&&0>t.inArray(null,u[a].slice(0,3))&&(u[a][3]=1,s.from&&(u._rgba=s.from(u[a])))}),this):e},is:function(t){var i=h(t),s=!0,n=this;return f(c,function(t,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=h(t),n=s._space(),a=c[n],o=0===this.alpha()?h("transparent"):this,r=o[a.cache]||a.to(o._rgba),l=r.slice();return s=s[a.cache],f(a.props,function(t,n){var a=n.idx,o=r[a],h=s[a],c=u[n.type]||{};null!==h&&(null===o?l[a]=h:(c.mod&&(h-o>c.mod/2?o+=c.mod:o-h>c.mod/2&&(o-=c.mod)),l[a]=i((h-o)*e+o,n)))}),this[n](l)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=h(e)._rgba;return h(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),h.fn.parse.prototype=h.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,a=t[2]/255,o=t[3],r=Math.max(s,n,a),l=Math.min(s,n,a),h=r-l,c=r+l,u=.5*c;return e=l===r?0:s===r?60*(n-a)/h+360:n===r?60*(a-s)/h+120:60*(s-n)/h+240,i=0===h?0:.5>=u?h/c:h/(2-c),[Math.round(e)%360,i,u,null==o?1:o]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],a=t[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,e+1/3)),Math.round(255*n(r,o,e)),Math.round(255*n(r,o,e-1/3)),a]},f(c,function(s,n){var a=n.props,o=n.cache,l=n.to,c=n.from;h.fn[s]=function(s){if(l&&!this[o]&&(this[o]=l(this._rgba)),s===e)return this[o].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[o].slice();return f(a,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=h(c(d)),n[o]=d,n):h(d)},f(a,function(e,i){h.fn[e]||(h.fn[e]=function(n){var a,o=t.type(n),l="alpha"===e?this._hsla?"hsla":"rgba":s,h=this[l](),c=h[i.idx];return"undefined"===o?c:("function"===o&&(n=n.call(this,c),o=t.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=c+parseFloat(a[2])*("+"===a[1]?1:-1))),h[i.idx]=n,this[l](h)))})})}),h.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var a,o,r="";if("transparent"!==n&&("string"!==t.type(n)||(a=s(n)))){if(n=h(a||n),!d.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&o&&o.style;)try{r=t.css(o,"backgroundColor"),o=o.parentNode}catch(l){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(l){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=h(e.elem,i),e.end=h(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},h.hook(o),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},a=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function s(e,i){var s,n,o={};for(s in i)n=i[s],e[s]!==n&&(a[s]||(t.fx.step[s]||!isNaN(parseFloat(n)))&&(o[s]=n));return o}var n=["add","remove","toggle"],a={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(jQuery.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(e,a,o,r){var l=t.speed(a,o,r);return this.queue(function(){var a,o=t(this),r=o.attr("class")||"",h=l.children?o.find("*").addBack():o;h=h.map(function(){var e=t(this);return{el:e,start:i(this)}}),a=function(){t.each(n,function(t,i){e[i]&&o[i+"Class"](e[i])})},a(),h=h.map(function(){return this.end=i(this.el[0]),this.diff=s(this.start,this.end),this}),o.attr("class",r),h=h.map(function(){var e=this,i=t.Deferred(),s=t.extend({},l,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,h.get()).done(function(){a(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),l.complete.call(o[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,a){return s?t.effects.animateClass.call(this,{add:i},s,n,a):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,a){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,a):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(i){return function(s,n,a,o,r){return"boolean"==typeof n||n===e?a?t.effects.animateClass.call(this,n?{add:s}:{remove:s},a,o,r):i.apply(this,arguments):t.effects.animateClass.call(this,{toggle:s},n,a,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,a){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,a)}})}(),function(){function s(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function n(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}t.extend(t.effects,{version:"1.10.4",save:function(t,e){for(var s=0;e.length>s;s++)null!==e[s]&&t.data(i+e[s],t[0].style[e[s]])},restore:function(t,s){var n,a;for(a=0;s.length>a;a++)null!==s[a]&&(n=t.data(i+s[a]),n===e&&(n=""),t.css(s[a],n))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return e.wrap(s),(e[0]===a||t.contains(e[0],a))&&t(a).focus(),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).focus()),e},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var a=e.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),t.fn.extend({effect:function(){function e(e){function s(){t.isFunction(a)&&a.call(n[0]),t.isFunction(e)&&e()}var n=t(this),a=i.complete,r=i.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),s()):o.call(n[0],i,s)}var i=s.apply(this,arguments),n=i.mode,a=i.queue,o=t.effects.effect[i.effect];return t.fx.off||!o?n?this[n](i.duration,i.complete):this.each(function(){i.complete&&i.complete.call(this)}):a===!1?this.each(e):this.queue(a||"fx",e)},show:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="show",this.effect.call(this,i)}}(t.fn.show),hide:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="hide",this.effect.call(this,i)}}(t.fn.hide),toggle:function(t){return function(e){if(n(e)||"boolean"==typeof e)return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="toggle",this.effect.call(this,i)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s}})}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}()})(jQuery);(function(t){var e=/up|down|vertical/,i=/up|left|vertical|horizontal/;t.effects.effect.blind=function(s,n){var a,o,r,l=t(this),h=["position","top","bottom","left","right","height","width"],c=t.effects.setMode(l,s.mode||"hide"),u=s.direction||"up",d=e.test(u),p=d?"height":"width",f=d?"top":"left",g=i.test(u),m={},v="show"===c;l.parent().is(".ui-effects-wrapper")?t.effects.save(l.parent(),h):t.effects.save(l,h),l.show(),a=t.effects.createWrapper(l).css({overflow:"hidden"}),o=a[p](),r=parseFloat(a.css(f))||0,m[p]=v?o:0,g||(l.css(d?"bottom":"right",0).css(d?"top":"left","auto").css({position:"absolute"}),m[f]=v?r:o+r),v&&(a.css(p,0),g||a.css(f,r+o)),a.animate(m,{duration:s.duration,easing:s.easing,queue:!1,complete:function(){"hide"===c&&l.hide(),t.effects.restore(l,h),t.effects.removeWrapper(l),n()}})}})(jQuery);(function(t){t.effects.effect.bounce=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],l=t.effects.setMode(o,e.mode||"effect"),h="hide"===l,c="show"===l,u=e.direction||"up",d=e.distance,p=e.times||5,f=2*p+(c||h?1:0),g=e.duration/f,m=e.easing,v="up"===u||"down"===u?"top":"left",_="up"===u||"left"===u,b=o.queue(),y=b.length;for((c||h)&&r.push("opacity"),t.effects.save(o,r),o.show(),t.effects.createWrapper(o),d||(d=o["top"===v?"outerHeight":"outerWidth"]()/3),c&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,_?2*-d:2*d).animate(a,g,m)),h&&(d/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(_?"-=":"+=")+d,o.animate(n,g,m).animate(a,g,m),d=h?2*d:d/2;h&&(n={opacity:0},n[v]=(_?"-=":"+=")+d,o.animate(n,g,m)),o.queue(function(){h&&o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}),y>1&&b.splice.apply(b,[1,0].concat(b.splice(y,f+1))),o.dequeue()}})(jQuery);(function(t){t.effects.effect.clip=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],l=t.effects.setMode(o,e.mode||"hide"),h="show"===l,c=e.direction||"vertical",u="vertical"===c,d=u?"height":"width",p=u?"top":"left",f={};t.effects.save(o,r),o.show(),s=t.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[d](),h&&(n.css(d,0),n.css(p,a/2)),f[d]=h?a:0,f[p]=h?0:a/2,n.animate(f,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){h||o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.drop=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","opacity","height","width"],o=t.effects.setMode(n,e.mode||"hide"),r="show"===o,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l?"pos":"neg",u={opacity:r?1:0};t.effects.save(n,a),n.show(),t.effects.createWrapper(n),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(h,"pos"===c?-s:s),u[h]=(r?"pos"===c?"+=":"-=":"pos"===c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.explode=function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),g||p.hide(),i()}var a,o,r,l,h,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=t.effects.setMode(p,e.mode||"hide"),g="show"===f,m=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/d),_=Math.ceil(p.outerHeight()/u),b=[];for(a=0;u>a;a++)for(l=m.top+a*_,c=a-(u-1)/2,o=0;d>o;o++)r=m.left+o*v,h=o-(d-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*_}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:_,left:r+(g?h*v:0),top:l+(g?c*_:0),opacity:g?0:1}).animate({left:r+(g?0:h*v),top:l+(g?0:c*_),opacity:g?1:0},e.duration||500,e.easing,s)}})(jQuery);(function(t){t.effects.effect.fade=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}})(jQuery);(function(t){t.effects.effect.fold=function(e,i){var s,n,a=t(this),o=["position","top","bottom","left","right","height","width"],r=t.effects.setMode(a,e.mode||"hide"),l="show"===r,h="hide"===r,c=e.size||15,u=/([0-9]+)%/.exec(c),d=!!e.horizFirst,p=l!==d,f=p?["width","height"]:["height","width"],g=e.duration/2,m={},v={};t.effects.save(a,o),a.show(),s=t.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],u&&(c=parseInt(u[1],10)/100*n[h?0:1]),l&&s.css(d?{height:0,width:c}:{height:c,width:0}),m[f[0]]=l?n[0]:c,v[f[1]]=l?n[1]:0,s.animate(m,g,e.easing).animate(v,g,e.easing,function(){h&&a.hide(),t.effects.restore(a,o),t.effects.removeWrapper(a),i()})}})(jQuery);(function(t){t.effects.effect.highlight=function(e,i){var s=t(this),n=["backgroundImage","backgroundColor","opacity"],a=t.effects.setMode(s,e.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),t.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(o,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===a&&s.hide(),t.effects.restore(s,n),i()}})}})(jQuery);(function(t){t.effects.effect.pulsate=function(e,i){var s,n=t(this),a=t.effects.setMode(n,e.mode||"show"),o="show"===a,r="hide"===a,l=o||"hide"===a,h=2*(e.times||5)+(l?1:0),c=e.duration/h,u=0,d=n.queue(),p=d.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),u=1),s=1;h>s;s++)n.animate({opacity:u},c,e.easing),u=1-u;n.animate({opacity:u},c,e.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&d.splice.apply(d,[1,0].concat(d.splice(p,h+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.puff=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"hide"),a="hide"===n,o=parseInt(e.percent,10)||150,r=o/100,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};t.extend(e,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?l:{height:l.height*r,width:l.width*r,outerHeight:l.outerHeight*r,outerWidth:l.outerWidth*r}}),s.effect(e)},t.effects.effect.scale=function(e,i){var s=t(this),n=t.extend(!0,{},e),a=t.effects.setMode(s,e.mode||"effect"),o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"hide"===a?0:100),r=e.direction||"both",l=e.origin,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},c={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=l||["middle","center"],n.restore=!0),n.from=e.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:h),n.to={height:h.height*c.y,width:h.width*c.x,outerHeight:h.outerHeight*c.y,outerWidth:h.outerWidth*c.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},t.effects.effect.size=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],l=["position","top","bottom","left","right","overflow","opacity"],h=["width","height","overflow"],c=["fontSize"],u=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],d=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=t.effects.setMode(o,e.mode||"effect"),f=e.restore||"effect"!==p,g=e.scale||"both",m=e.origin||["middle","center"],v=o.css("position"),_=f?r:l,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===e.mode&&"show"===p?(o.from=e.to||b,o.to=e.from||s):(o.from=e.from||("show"===p?b:s),o.to=e.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===g||"both"===g)&&(a.from.y!==a.to.y&&(_=_.concat(u),o.from=t.effects.setTransition(o,u,a.from.y,o.from),o.to=t.effects.setTransition(o,u,a.to.y,o.to)),a.from.x!==a.to.x&&(_=_.concat(d),o.from=t.effects.setTransition(o,d,a.from.x,o.from),o.to=t.effects.setTransition(o,d,a.to.x,o.to))),("content"===g||"both"===g)&&a.from.y!==a.to.y&&(_=_.concat(c).concat(h),o.from=t.effects.setTransition(o,c,a.from.y,o.from),o.to=t.effects.setTransition(o,c,a.to.y,o.to)),t.effects.save(o,_),o.show(),t.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(n=t.effects.getBaseline(m,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===g||"both"===g)&&(u=u.concat(["marginTop","marginBottom"]).concat(c),d=d.concat(["marginLeft","marginRight"]),h=r.concat(u).concat(d),o.find("*[width]").each(function(){var i=t(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};f&&t.effects.save(i,h),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=t.effects.setTransition(i,u,a.from.y,i.from),i.to=t.effects.setTransition(i,u,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=t.effects.setTransition(i,d,a.from.x,i.from),i.to=t.effects.setTransition(i,d,a.to.x,i.to)),i.css(i.from),i.animate(i.to,e.duration,e.easing,function(){f&&t.effects.restore(i,h)})})),o.animate(o.to,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),t.effects.restore(o,_),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):t.each(["top","left"],function(t,e){o.css(e,function(e,i){var s=parseInt(i,10),n=t?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.shake=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","height","width"],o=t.effects.setMode(n,e.mode||"effect"),r=e.direction||"left",l=e.distance||20,h=e.times||3,c=2*h+1,u=Math.round(e.duration/c),d="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},g={},m={},v=n.queue(),_=v.length;for(t.effects.save(n,a),n.show(),t.effects.createWrapper(n),f[d]=(p?"-=":"+=")+l,g[d]=(p?"+=":"-=")+2*l,m[d]=(p?"-=":"+=")+2*l,n.animate(f,u,e.easing),s=1;h>s;s++)n.animate(g,u,e.easing).animate(m,u,e.easing);n.animate(g,u,e.easing).animate(f,u/2,e.easing).queue(function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}),_>1&&v.splice.apply(v,[1,0].concat(v.splice(_,c+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.slide=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","width","height"],o=t.effects.setMode(n,e.mode||"show"),r="show"===o,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l,u={};t.effects.save(n,a),n.show(),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0),t.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(h,c?isNaN(s)?"-"+s:-s:s),u[h]=(r?c?"+=":"-=":c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.transfer=function(e,i){var s=t(this),n=t(e.to),a="fixed"===n.css("position"),o=t("body"),r=a?o.scrollTop():0,l=a?o.scrollLeft():0,h=n.offset(),c={top:h.top-r,left:h.left-l,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(e.className).css({top:u.top-r,left:u.left-l,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),i()})}})(jQuery);
\ No newline at end of file
diff --git a/share/nitdoc/js/lib/marked.js b/share/nitdoc/js/lib/marked.js
new file mode 100644 (file)
index 0000000..2656832
--- /dev/null
@@ -0,0 +1,1252 @@
+/**
+ * marked - a markdown parser
+ * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
+ * https://github.com/chjj/marked
+ */
+
+;(function() {
+
+/**
+ * Block-Level Grammar
+ */
+
+var block = {
+  newline: /^\n+/,
+  code: /^( {4}[^\n]+\n*)+/,
+  fences: noop,
+  hr: /^( *[-*_]){3,} *(?:\n+|$)/,
+  heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
+  nptable: noop,
+  lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
+  blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
+  list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
+  html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
+  def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
+  table: noop,
+  paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
+  text: /^[^\n]+/
+};
+
+block.bullet = /(?:[*+-]|\d+\.)/;
+block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
+block.item = replace(block.item, 'gm')
+  (/bull/g, block.bullet)
+  ();
+
+block.list = replace(block.list)
+  (/bull/g, block.bullet)
+  ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
+  ();
+
+block._tag = '(?!(?:'
+  + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
+  + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
+  + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
+
+block.html = replace(block.html)
+  ('comment', /<!--[\s\S]*?-->/)
+  ('closed', /<(tag)[\s\S]+?<\/\1>/)
+  ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
+  (/tag/g, block._tag)
+  ();
+
+block.paragraph = replace(block.paragraph)
+  ('hr', block.hr)
+  ('heading', block.heading)
+  ('lheading', block.lheading)
+  ('blockquote', block.blockquote)
+  ('tag', '<' + block._tag)
+  ('def', block.def)
+  ();
+
+/**
+ * Normal Block Grammar
+ */
+
+block.normal = merge({}, block);
+
+/**
+ * GFM Block Grammar
+ */
+
+block.gfm = merge({}, block.normal, {
+  fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
+  paragraph: /^/
+});
+
+block.gfm.paragraph = replace(block.paragraph)
+  ('(?!', '(?!'
+    + block.gfm.fences.source.replace('\\1', '\\2') + '|'
+    + block.list.source.replace('\\1', '\\3') + '|')
+  ();
+
+/**
+ * GFM + Tables Block Grammar
+ */
+
+block.tables = merge({}, block.gfm, {
+  nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
+  table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
+});
+
+/**
+ * Block Lexer
+ */
+
+function Lexer(options) {
+  this.tokens = [];
+  this.tokens.links = {};
+  this.options = options || marked.defaults;
+  this.rules = block.normal;
+
+  if (this.options.gfm) {
+    if (this.options.tables) {
+      this.rules = block.tables;
+    } else {
+      this.rules = block.gfm;
+    }
+  }
+}
+
+/**
+ * Expose Block Rules
+ */
+
+Lexer.rules = block;
+
+/**
+ * Static Lex Method
+ */
+
+Lexer.lex = function(src, options) {
+  var lexer = new Lexer(options);
+  return lexer.lex(src);
+};
+
+/**
+ * Preprocessing
+ */
+
+Lexer.prototype.lex = function(src) {
+  src = src
+    .replace(/\r\n|\r/g, '\n')
+    .replace(/\t/g, '    ')
+    .replace(/\u00a0/g, ' ')
+    .replace(/\u2424/g, '\n');
+
+  return this.token(src, true);
+};
+
+/**
+ * Lexing
+ */
+
+Lexer.prototype.token = function(src, top) {
+  var src = src.replace(/^ +$/gm, '')
+    , next
+    , loose
+    , cap
+    , bull
+    , b
+    , item
+    , space
+    , i
+    , l;
+
+  while (src) {
+    // newline
+    if (cap = this.rules.newline.exec(src)) {
+      src = src.substring(cap[0].length);
+      if (cap[0].length > 1) {
+        this.tokens.push({
+          type: 'space'
+        });
+      }
+    }
+
+    // code
+    if (cap = this.rules.code.exec(src)) {
+      src = src.substring(cap[0].length);
+      cap = cap[0].replace(/^ {4}/gm, '');
+      this.tokens.push({
+        type: 'code',
+        text: !this.options.pedantic
+          ? cap.replace(/\n+$/, '')
+          : cap
+      });
+      continue;
+    }
+
+    // fences (gfm)
+    if (cap = this.rules.fences.exec(src)) {
+      src = src.substring(cap[0].length);
+      this.tokens.push({
+        type: 'code',
+        lang: cap[2],
+        text: cap[3]
+      });
+      continue;
+    }
+
+    // heading
+    if (cap = this.rules.heading.exec(src)) {
+      src = src.substring(cap[0].length);
+      this.tokens.push({
+        type: 'heading',
+        depth: cap[1].length,
+        text: cap[2]
+      });
+      continue;
+    }
+
+    // table no leading pipe (gfm)
+    if (top && (cap = this.rules.nptable.exec(src))) {
+      src = src.substring(cap[0].length);
+
+      item = {
+        type: 'table',
+        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
+        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
+        cells: cap[3].replace(/\n$/, '').split('\n')
+      };
+
+      for (i = 0; i < item.align.length; i++) {
+        if (/^ *-+: *$/.test(item.align[i])) {
+          item.align[i] = 'right';
+        } else if (/^ *:-+: *$/.test(item.align[i])) {
+          item.align[i] = 'center';
+        } else if (/^ *:-+ *$/.test(item.align[i])) {
+          item.align[i] = 'left';
+        } else {
+          item.align[i] = null;
+        }
+      }
+
+      for (i = 0; i < item.cells.length; i++) {
+        item.cells[i] = item.cells[i].split(/ *\| */);
+      }
+
+      this.tokens.push(item);
+
+      continue;
+    }
+
+    // lheading
+    if (cap = this.rules.lheading.exec(src)) {
+      src = src.substring(cap[0].length);
+      this.tokens.push({
+        type: 'heading',
+        depth: cap[2] === '=' ? 1 : 2,
+        text: cap[1]
+      });
+      continue;
+    }
+
+    // hr
+    if (cap = this.rules.hr.exec(src)) {
+      src = src.substring(cap[0].length);
+      this.tokens.push({
+        type: 'hr'
+      });
+      continue;
+    }
+
+    // blockquote
+    if (cap = this.rules.blockquote.exec(src)) {
+      src = src.substring(cap[0].length);
+
+      this.tokens.push({
+        type: 'blockquote_start'
+      });
+
+      cap = cap[0].replace(/^ *> ?/gm, '');
+
+      // Pass `top` to keep the current
+      // "toplevel" state. This is exactly
+      // how markdown.pl works.
+      this.token(cap, top);
+
+      this.tokens.push({
+        type: 'blockquote_end'
+      });
+
+      continue;
+    }
+
+    // list
+    if (cap = this.rules.list.exec(src)) {
+      src = src.substring(cap[0].length);
+      bull = cap[2];
+
+      this.tokens.push({
+        type: 'list_start',
+        ordered: bull.length > 1
+      });
+
+      // Get each top-level item.
+      cap = cap[0].match(this.rules.item);
+
+      next = false;
+      l = cap.length;
+      i = 0;
+
+      for (; i < l; i++) {
+        item = cap[i];
+
+        // Remove the list item's bullet
+        // so it is seen as the next token.
+        space = item.length;
+        item = item.replace(/^ *([*+-]|\d+\.) +/, '');
+
+        // Outdent whatever the
+        // list item contains. Hacky.
+        if (~item.indexOf('\n ')) {
+          space -= item.length;
+          item = !this.options.pedantic
+            ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
+            : item.replace(/^ {1,4}/gm, '');
+        }
+
+        // Determine whether the next list item belongs here.
+        // Backpedal if it does not belong in this list.
+        if (this.options.smartLists && i !== l - 1) {
+          b = block.bullet.exec(cap[i + 1])[0];
+          if (bull !== b && !(bull.length > 1 && b.length > 1)) {
+            src = cap.slice(i + 1).join('\n') + src;
+            i = l - 1;
+          }
+        }
+
+        // Determine whether item is loose or not.
+        // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
+        // for discount behavior.
+        loose = next || /\n\n(?!\s*$)/.test(item);
+        if (i !== l - 1) {
+          next = item.charAt(item.length - 1) === '\n';
+          if (!loose) loose = next;
+        }
+
+        this.tokens.push({
+          type: loose
+            ? 'loose_item_start'
+            : 'list_item_start'
+        });
+
+        // Recurse.
+        this.token(item, false);
+
+        this.tokens.push({
+          type: 'list_item_end'
+        });
+      }
+
+      this.tokens.push({
+        type: 'list_end'
+      });
+
+      continue;
+    }
+
+    // html
+    if (cap = this.rules.html.exec(src)) {
+      src = src.substring(cap[0].length);
+      this.tokens.push({
+        type: this.options.sanitize
+          ? 'paragraph'
+          : 'html',
+        pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
+        text: cap[0]
+      });
+      continue;
+    }
+
+    // def
+    if (top && (cap = this.rules.def.exec(src))) {
+      src = src.substring(cap[0].length);
+      this.tokens.links[cap[1].toLowerCase()] = {
+        href: cap[2],
+        title: cap[3]
+      };
+      continue;
+    }
+
+    // table (gfm)
+    if (top && (cap = this.rules.table.exec(src))) {
+      src = src.substring(cap[0].length);
+
+      item = {
+        type: 'table',
+        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
+        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
+        cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
+      };
+
+      for (i = 0; i < item.align.length; i++) {
+        if (/^ *-+: *$/.test(item.align[i])) {
+          item.align[i] = 'right';
+        } else if (/^ *:-+: *$/.test(item.align[i])) {
+          item.align[i] = 'center';
+        } else if (/^ *:-+ *$/.test(item.align[i])) {
+          item.align[i] = 'left';
+        } else {
+          item.align[i] = null;
+        }
+      }
+
+      for (i = 0; i < item.cells.length; i++) {
+        item.cells[i] = item.cells[i]
+          .replace(/^ *\| *| *\| *$/g, '')
+          .split(/ *\| */);
+      }
+
+      this.tokens.push(item);
+
+      continue;
+    }
+
+    // top-level paragraph
+    if (top && (cap = this.rules.paragraph.exec(src))) {
+      src = src.substring(cap[0].length);
+      this.tokens.push({
+        type: 'paragraph',
+        text: cap[1].charAt(cap[1].length - 1) === '\n'
+          ? cap[1].slice(0, -1)
+          : cap[1]
+      });
+      continue;
+    }
+
+    // text
+    if (cap = this.rules.text.exec(src)) {
+      // Top-level should never reach here.
+      src = src.substring(cap[0].length);
+      this.tokens.push({
+        type: 'text',
+        text: cap[0]
+      });
+      continue;
+    }
+
+    if (src) {
+      throw new
+        Error('Infinite loop on byte: ' + src.charCodeAt(0));
+    }
+  }
+
+  return this.tokens;
+};
+
+/**
+ * Inline-Level Grammar
+ */
+
+var inline = {
+  escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
+  autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
+  url: noop,
+  tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
+  link: /^!?\[(inside)\]\(href\)/,
+  reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
+  nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
+  strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
+  em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
+  code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
+  br: /^ {2,}\n(?!\s*$)/,
+  del: noop,
+  text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
+};
+
+inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
+inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
+
+inline.link = replace(inline.link)
+  ('inside', inline._inside)
+  ('href', inline._href)
+  ();
+
+inline.reflink = replace(inline.reflink)
+  ('inside', inline._inside)
+  ();
+
+/**
+ * Normal Inline Grammar
+ */
+
+inline.normal = merge({}, inline);
+
+/**
+ * Pedantic Inline Grammar
+ */
+
+inline.pedantic = merge({}, inline.normal, {
+  strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
+  em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
+});
+
+/**
+ * GFM Inline Grammar
+ */
+
+inline.gfm = merge({}, inline.normal, {
+  escape: replace(inline.escape)('])', '~|])')(),
+  url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
+  del: /^~~(?=\S)([\s\S]*?\S)~~/,
+  text: replace(inline.text)
+    (']|', '~]|')
+    ('|', '|https?://|')
+    ()
+});
+
+/**
+ * GFM + Line Breaks Inline Grammar
+ */
+
+inline.breaks = merge({}, inline.gfm, {
+  br: replace(inline.br)('{2,}', '*')(),
+  text: replace(inline.gfm.text)('{2,}', '*')()
+});
+
+/**
+ * Inline Lexer & Compiler
+ */
+
+function InlineLexer(links, options) {
+  this.options = options || marked.defaults;
+  this.links = links;
+  this.rules = inline.normal;
+  this.renderer = this.options.renderer || new Renderer;
+  this.renderer.options = this.options;
+
+  if (!this.links) {
+    throw new
+      Error('Tokens array requires a `links` property.');
+  }
+
+  if (this.options.gfm) {
+    if (this.options.breaks) {
+      this.rules = inline.breaks;
+    } else {
+      this.rules = inline.gfm;
+    }
+  } else if (this.options.pedantic) {
+    this.rules = inline.pedantic;
+  }
+}
+
+/**
+ * Expose Inline Rules
+ */
+
+InlineLexer.rules = inline;
+
+/**
+ * Static Lexing/Compiling Method
+ */
+
+InlineLexer.output = function(src, links, options) {
+  var inline = new InlineLexer(links, options);
+  return inline.output(src);
+};
+
+/**
+ * Lexing/Compiling
+ */
+
+InlineLexer.prototype.output = function(src) {
+  var out = ''
+    , link
+    , text
+    , href
+    , cap;
+
+  while (src) {
+    // escape
+    if (cap = this.rules.escape.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += cap[1];
+      continue;
+    }
+
+    // autolink
+    if (cap = this.rules.autolink.exec(src)) {
+      src = src.substring(cap[0].length);
+      if (cap[2] === '@') {
+        text = cap[1].charAt(6) === ':'
+          ? this.mangle(cap[1].substring(7))
+          : this.mangle(cap[1]);
+        href = this.mangle('mailto:') + text;
+      } else {
+        text = escape(cap[1]);
+        href = text;
+      }
+      out += this.renderer.link(href, null, text);
+      continue;
+    }
+
+    // url (gfm)
+    if (cap = this.rules.url.exec(src)) {
+      src = src.substring(cap[0].length);
+      text = escape(cap[1]);
+      href = text;
+      out += this.renderer.link(href, null, text);
+      continue;
+    }
+
+    // tag
+    if (cap = this.rules.tag.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += this.options.sanitize
+        ? escape(cap[0])
+        : cap[0];
+      continue;
+    }
+
+    // link
+    if (cap = this.rules.link.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += this.outputLink(cap, {
+        href: cap[2],
+        title: cap[3]
+      });
+      continue;
+    }
+
+    // reflink, nolink
+    if ((cap = this.rules.reflink.exec(src))
+        || (cap = this.rules.nolink.exec(src))) {
+      src = src.substring(cap[0].length);
+      link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
+      link = this.links[link.toLowerCase()];
+      if (!link || !link.href) {
+        out += cap[0].charAt(0);
+        src = cap[0].substring(1) + src;
+        continue;
+      }
+      out += this.outputLink(cap, link);
+      continue;
+    }
+
+    // strong
+    if (cap = this.rules.strong.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += this.renderer.strong(this.output(cap[2] || cap[1]));
+      continue;
+    }
+
+    // em
+    if (cap = this.rules.em.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += this.renderer.em(this.output(cap[2] || cap[1]));
+      continue;
+    }
+
+    // code
+    if (cap = this.rules.code.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += this.renderer.codespan(escape(cap[2], true));
+      continue;
+    }
+
+    // br
+    if (cap = this.rules.br.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += this.renderer.br();
+      continue;
+    }
+
+    // del (gfm)
+    if (cap = this.rules.del.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += this.renderer.del(this.output(cap[1]));
+      continue;
+    }
+
+    // text
+    if (cap = this.rules.text.exec(src)) {
+      src = src.substring(cap[0].length);
+      out += escape(this.smartypants(cap[0]));
+      continue;
+    }
+
+    if (src) {
+      throw new
+        Error('Infinite loop on byte: ' + src.charCodeAt(0));
+    }
+  }
+
+  return out;
+};
+
+/**
+ * Compile Link
+ */
+
+InlineLexer.prototype.outputLink = function(cap, link) {
+  var href = escape(link.href)
+    , title = link.title ? escape(link.title) : null;
+
+  return cap[0].charAt(0) !== '!'
+    ? this.renderer.link(href, title, this.output(cap[1]))
+    : this.renderer.image(href, title, escape(cap[1]));
+};
+
+/**
+ * Smartypants Transformations
+ */
+
+InlineLexer.prototype.smartypants = function(text) {
+  if (!this.options.smartypants) return text;
+  return text
+    // em-dashes
+    .replace(/--/g, '\u2014')
+    // opening singles
+    .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
+    // closing singles & apostrophes
+    .replace(/'/g, '\u2019')
+    // opening doubles
+    .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
+    // closing doubles
+    .replace(/"/g, '\u201d')
+    // ellipses
+    .replace(/\.{3}/g, '\u2026');
+};
+
+/**
+ * Mangle Links
+ */
+
+InlineLexer.prototype.mangle = function(text) {
+  var out = ''
+    , l = text.length
+    , i = 0
+    , ch;
+
+  for (; i < l; i++) {
+    ch = text.charCodeAt(i);
+    if (Math.random() > 0.5) {
+      ch = 'x' + ch.toString(16);
+    }
+    out += '&#' + ch + ';';
+  }
+
+  return out;
+};
+
+/**
+ * Renderer
+ */
+
+function Renderer(options) {
+  this.options = options || {};
+}
+
+Renderer.prototype.code = function(code, lang, escaped) {
+  if (this.options.highlight) {
+    var out = this.options.highlight(code, lang);
+    if (out != null && out !== code) {
+      escaped = true;
+      code = out;
+    }
+  }
+
+  if (!lang) {
+    return '<pre><code>'
+      + (escaped ? code : escape(code, true))
+      + '\n</code></pre>';
+  }
+
+  return '<pre><code class="'
+    + this.options.langPrefix
+    + escape(lang, true)
+    + '">'
+    + (escaped ? code : escape(code, true))
+    + '\n</code></pre>\n';
+};
+
+Renderer.prototype.blockquote = function(quote) {
+  return '<blockquote>\n' + quote + '</blockquote>\n';
+};
+
+Renderer.prototype.html = function(html) {
+  return html;
+};
+
+Renderer.prototype.heading = function(text, level, raw) {
+  return '<h'
+    + level
+    + ' id="'
+    + this.options.headerPrefix
+    + raw.toLowerCase().replace(/[^\w]+/g, '-')
+    + '">'
+    + text
+    + '</h'
+    + level
+    + '>\n';
+};
+
+Renderer.prototype.hr = function() {
+  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
+};
+
+Renderer.prototype.list = function(body, ordered) {
+  var type = ordered ? 'ol' : 'ul';
+  return '<' + type + '>\n' + body + '</' + type + '>\n';
+};
+
+Renderer.prototype.listitem = function(text) {
+  return '<li>' + text + '</li>\n';
+};
+
+Renderer.prototype.paragraph = function(text) {
+  return '<p>' + text + '</p>\n';
+};
+
+Renderer.prototype.table = function(header, body) {
+  return '<table>\n'
+    + '<thead>\n'
+    + header
+    + '</thead>\n'
+    + '<tbody>\n'
+    + body
+    + '</tbody>\n'
+    + '</table>\n';
+};
+
+Renderer.prototype.tablerow = function(content) {
+  return '<tr>\n' + content + '</tr>\n';
+};
+
+Renderer.prototype.tablecell = function(content, flags) {
+  var type = flags.header ? 'th' : 'td';
+  var tag = flags.align
+    ? '<' + type + ' style="text-align:' + flags.align + '">'
+    : '<' + type + '>';
+  return tag + content + '</' + type + '>\n';
+};
+
+// span level renderer
+Renderer.prototype.strong = function(text) {
+  return '<strong>' + text + '</strong>';
+};
+
+Renderer.prototype.em = function(text) {
+  return '<em>' + text + '</em>';
+};
+
+Renderer.prototype.codespan = function(text) {
+  return '<code>' + text + '</code>';
+};
+
+Renderer.prototype.br = function() {
+  return this.options.xhtml ? '<br/>' : '<br>';
+};
+
+Renderer.prototype.del = function(text) {
+  return '<del>' + text + '</del>';
+};
+
+Renderer.prototype.link = function(href, title, text) {
+  if (this.options.sanitize) {
+    try {
+      var prot = decodeURIComponent(unescape(href))
+        .replace(/[^\w:]/g, '')
+        .toLowerCase();
+    } catch (e) {
+      return '';
+    }
+    if (prot.indexOf('javascript:') === 0) {
+      return '';
+    }
+  }
+  var out = '<a href="' + href + '"';
+  if (title) {
+    out += ' title="' + title + '"';
+  }
+  out += '>' + text + '</a>';
+  return out;
+};
+
+Renderer.prototype.image = function(href, title, text) {
+  var out = '<img src="' + href + '" alt="' + text + '"';
+  if (title) {
+    out += ' title="' + title + '"';
+  }
+  out += this.options.xhtml ? '/>' : '>';
+  return out;
+};
+
+/**
+ * Parsing & Compiling
+ */
+
+function Parser(options) {
+  this.tokens = [];
+  this.token = null;
+  this.options = options || marked.defaults;
+  this.options.renderer = this.options.renderer || new Renderer;
+  this.renderer = this.options.renderer;
+  this.renderer.options = this.options;
+}
+
+/**
+ * Static Parse Method
+ */
+
+Parser.parse = function(src, options, renderer) {
+  var parser = new Parser(options, renderer);
+  return parser.parse(src);
+};
+
+/**
+ * Parse Loop
+ */
+
+Parser.prototype.parse = function(src) {
+  this.inline = new InlineLexer(src.links, this.options, this.renderer);
+  this.tokens = src.reverse();
+
+  var out = '';
+  while (this.next()) {
+    out += this.tok();
+  }
+
+  return out;
+};
+
+/**
+ * Next Token
+ */
+
+Parser.prototype.next = function() {
+  return this.token = this.tokens.pop();
+};
+
+/**
+ * Preview Next Token
+ */
+
+Parser.prototype.peek = function() {
+  return this.tokens[this.tokens.length - 1] || 0;
+};
+
+/**
+ * Parse Text Tokens
+ */
+
+Parser.prototype.parseText = function() {
+  var body = this.token.text;
+
+  while (this.peek().type === 'text') {
+    body += '\n' + this.next().text;
+  }
+
+  return this.inline.output(body);
+};
+
+/**
+ * Parse Current Token
+ */
+
+Parser.prototype.tok = function() {
+  switch (this.token.type) {
+    case 'space': {
+      return '';
+    }
+    case 'hr': {
+      return this.renderer.hr();
+    }
+    case 'heading': {
+      return this.renderer.heading(
+        this.inline.output(this.token.text),
+        this.token.depth,
+        this.token.text);
+    }
+    case 'code': {
+      return this.renderer.code(this.token.text,
+        this.token.lang,
+        this.token.escaped);
+    }
+    case 'table': {
+      var header = ''
+        , body = ''
+        , i
+        , row
+        , cell
+        , flags
+        , j;
+
+      // header
+      cell = '';
+      for (i = 0; i < this.token.header.length; i++) {
+        flags = { header: true, align: this.token.align[i] };
+        cell += this.renderer.tablecell(
+          this.inline.output(this.token.header[i]),
+          { header: true, align: this.token.align[i] }
+        );
+      }
+      header += this.renderer.tablerow(cell);
+
+      for (i = 0; i < this.token.cells.length; i++) {
+        row = this.token.cells[i];
+
+        cell = '';
+        for (j = 0; j < row.length; j++) {
+          cell += this.renderer.tablecell(
+            this.inline.output(row[j]),
+            { header: false, align: this.token.align[j] }
+          );
+        }
+
+        body += this.renderer.tablerow(cell);
+      }
+      return this.renderer.table(header, body);
+    }
+    case 'blockquote_start': {
+      var body = '';
+
+      while (this.next().type !== 'blockquote_end') {
+        body += this.tok();
+      }
+
+      return this.renderer.blockquote(body);
+    }
+    case 'list_start': {
+      var body = ''
+        , ordered = this.token.ordered;
+
+      while (this.next().type !== 'list_end') {
+        body += this.tok();
+      }
+
+      return this.renderer.list(body, ordered);
+    }
+    case 'list_item_start': {
+      var body = '';
+
+      while (this.next().type !== 'list_item_end') {
+        body += this.token.type === 'text'
+          ? this.parseText()
+          : this.tok();
+      }
+
+      return this.renderer.listitem(body);
+    }
+    case 'loose_item_start': {
+      var body = '';
+
+      while (this.next().type !== 'list_item_end') {
+        body += this.tok();
+      }
+
+      return this.renderer.listitem(body);
+    }
+    case 'html': {
+      var html = !this.token.pre && !this.options.pedantic
+        ? this.inline.output(this.token.text)
+        : this.token.text;
+      return this.renderer.html(html);
+    }
+    case 'paragraph': {
+      return this.renderer.paragraph(this.inline.output(this.token.text));
+    }
+    case 'text': {
+      return this.renderer.paragraph(this.parseText());
+    }
+  }
+};
+
+/**
+ * Helpers
+ */
+
+function escape(html, encode) {
+  return html
+    .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;')
+    .replace(/"/g, '&quot;')
+    .replace(/'/g, '&#39;');
+}
+
+function unescape(html) {
+  return html.replace(/&([#\w]+);/g, function(_, n) {
+    n = n.toLowerCase();
+    if (n === 'colon') return ':';
+    if (n.charAt(0) === '#') {
+      return n.charAt(1) === 'x'
+        ? String.fromCharCode(parseInt(n.substring(2), 16))
+        : String.fromCharCode(+n.substring(1));
+    }
+    return '';
+  });
+}
+
+function replace(regex, opt) {
+  regex = regex.source;
+  opt = opt || '';
+  return function self(name, val) {
+    if (!name) return new RegExp(regex, opt);
+    val = val.source || val;
+    val = val.replace(/(^|[^\[])\^/g, '$1');
+    regex = regex.replace(name, val);
+    return self;
+  };
+}
+
+function noop() {}
+noop.exec = noop;
+
+function merge(obj) {
+  var i = 1
+    , target
+    , key;
+
+  for (; i < arguments.length; i++) {
+    target = arguments[i];
+    for (key in target) {
+      if (Object.prototype.hasOwnProperty.call(target, key)) {
+        obj[key] = target[key];
+      }
+    }
+  }
+
+  return obj;
+}
+
+
+/**
+ * Marked
+ */
+
+function marked(src, opt, callback) {
+  if (callback || typeof opt === 'function') {
+    if (!callback) {
+      callback = opt;
+      opt = null;
+    }
+
+    opt = merge({}, marked.defaults, opt || {});
+
+    var highlight = opt.highlight
+      , tokens
+      , pending
+      , i = 0;
+
+    try {
+      tokens = Lexer.lex(src, opt)
+    } catch (e) {
+      return callback(e);
+    }
+
+    pending = tokens.length;
+
+    var done = function() {
+      var out, err;
+
+      try {
+        out = Parser.parse(tokens, opt);
+      } catch (e) {
+        err = e;
+      }
+
+      opt.highlight = highlight;
+
+      return err
+        ? callback(err)
+        : callback(null, out);
+    };
+
+    if (!highlight || highlight.length < 3) {
+      return done();
+    }
+
+    delete opt.highlight;
+
+    if (!pending) return done();
+
+    for (; i < tokens.length; i++) {
+      (function(token) {
+        if (token.type !== 'code') {
+          return --pending || done();
+        }
+        return highlight(token.text, token.lang, function(err, code) {
+          if (code == null || code === token.text) {
+            return --pending || done();
+          }
+          token.text = code;
+          token.escaped = true;
+          --pending || done();
+        });
+      })(tokens[i]);
+    }
+
+    return;
+  }
+  try {
+    if (opt) opt = merge({}, marked.defaults, opt);
+    return Parser.parse(Lexer.lex(src, opt), opt);
+  } catch (e) {
+    e.message += '\nPlease report this to https://github.com/chjj/marked.';
+    if ((opt || marked.defaults).silent) {
+      return '<p>An error occured:</p><pre>'
+        + escape(e.message + '', true)
+        + '</pre>';
+    }
+    throw e;
+  }
+}
+
+/**
+ * Options
+ */
+
+marked.options =
+marked.setOptions = function(opt) {
+  merge(marked.defaults, opt);
+  return marked;
+};
+
+marked.defaults = {
+  gfm: true,
+  tables: true,
+  breaks: false,
+  pedantic: false,
+  sanitize: false,
+  smartLists: false,
+  silent: false,
+  highlight: null,
+  langPrefix: 'lang-',
+  smartypants: false,
+  headerPrefix: '',
+  renderer: new Renderer,
+  xhtml: false
+};
+
+/**
+ * Expose
+ */
+
+marked.Parser = Parser;
+marked.parser = Parser.parse;
+
+marked.Renderer = Renderer;
+
+marked.Lexer = Lexer;
+marked.lexer = Lexer.lex;
+
+marked.InlineLexer = InlineLexer;
+marked.inlineLexer = InlineLexer.output;
+
+marked.parse = marked;
+
+if (typeof exports === 'object') {
+  module.exports = marked;
+} else if (typeof define === 'function' && define.amd) {
+  define(function() { return marked; });
+} else {
+  this.marked = marked;
+}
+
+}).call(function() {
+  return this || (typeof window !== 'undefined' ? window : global);
+}());
diff --git a/share/nitdoc/js/lib/nit.js b/share/nitdoc/js/lib/nit.js
new file mode 100644 (file)
index 0000000..eac858c
--- /dev/null
@@ -0,0 +1,146 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+   Documentation generator for the nit language.
+   Generate API documentation in HTML format from nit source code.
+*/
+
+define(['highlight'], function(hljs) {
+       hljs.registerLanguage('nit', function(hljs) {
+var METHOD_RE = '[a-z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?';
+       var KEYWORDS = {
+               keyword: 'abort abstract and as assert break class continue do else end enum extern for fun ' +
+               'if import in init interface intern intrude is isa isset label loop module new nullable not ' +
+               'once or protected private redef return self super then type universal var ' +
+               'when while writable',
+               literal: "true false null"
+       };
+       var COMMENT = {
+               className: 'comment',
+               begin: '#', end: '$',
+       };
+       var SUBST = {
+               className: 'subst',
+               begin: '{', end: '}',
+               keywords: KEYWORDS
+       };
+       var STRING = {
+               className: 'string',
+               contains: [hljs.BACKSLASH_ESCAPE, SUBST],
+               variants: [
+                       {begin: /"/, end: /"/},
+               ]
+       };
+       var CHAR = {
+               className: 'char',
+               contains: [hljs.BACKSLASH_ESCAPE, SUBST],
+               begin: /'/, end: /'/,
+       };
+       var TYPE = {
+               className: 'type',
+               begin: '[A-Z]\\w*'
+       }
+       var PARAMS = {
+               className: 'params',
+               begin: '\\(', end: '\\)',
+               keywords: KEYWORDS,
+               contains: [TYPE]
+       };
+       var RET_TYPE = {
+               className: 'rettype',
+               begin: ':', end: '$|do|is|=',
+               keywords: 'nullable',
+               returnEnd: true,
+               contains: [TYPE]
+       }
+       var DO_BLOCK = {
+               className: 'block',
+               begin: 'do', end: '$|end',
+               keywords: KEYWORDS
+       }
+       var IS_BLOCK = {
+               className: 'modifiers',
+               begin: 'is', end: '$',
+               keywords: KEYWORDS
+       }
+       var CONTAINS = [
+               STRING,
+               CHAR,
+               COMMENT,
+               TYPE,
+               {
+                       className: 'module',
+                       beginKeywords: 'module', end: '$',
+                       contains: [
+                               hljs.inherit(hljs.TITLE_MODE, {begin: '[a-z_]\\w*'}),
+                               COMMENT
+                       ]
+               },
+               {
+                       className: 'import',
+                       begin: '(intrude )?import', end: '$',
+                       keywords: 'intrude import',
+                       contains: [
+                               {
+                                       className: 'module',
+                                       begin: '[a-z_]\\w*'
+                               },
+                               COMMENT
+                       ]
+               },
+               {
+                       className: 'class',
+                       begin: '(redef |private |protected )?(abstract )?(class|interface)', end: '$',
+                       keywords: 'redef private protected abstract class interface',
+                       contains: [
+                               hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Z]\\w*'}),
+                               {
+                                       className: 'super',
+                                       begin: '\\bsuper', end: '$',
+                                       keywords: 'super',
+                                       contains: [TYPE]
+                               },
+                               COMMENT
+                       ]
+               },
+               {
+                       className: 'fun',
+                       begin: '(redef |private |protected )?(fun|init|type)\\b', end: '$',
+                       keywords: KEYWORDS,
+                       contains: [
+                               PARAMS,
+                               RET_TYPE,
+                               DO_BLOCK,
+                               IS_BLOCK,
+                               {
+                                       className: 'title',
+                                       begin: '\\b[a-zA-Z_][a-zA-Z_]*\\b'
+                               },
+                               COMMENT
+                       ]
+               },
+               {
+                       className: 'number',
+                       begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
+                       relevance: 0
+               }
+       ];
+       SUBST.contains = CONTAINS;
+
+       return {
+               keywords: KEYWORDS,
+               contains: CONTAINS
+       };
+       });
+});
diff --git a/share/nitdoc/js/lib/require.js b/share/nitdoc/js/lib/require.js
new file mode 100644 (file)
index 0000000..84d1d67
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ RequireJS 2.1.10 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
+ Available via the MIT or new BSD license.
+ see: http://github.com/jrburke/requirejs for details
+*/
+var requirejs,require,define;
+(function(ca){function G(b){return"[object Function]"===N.call(b)}function H(b){return"[object Array]"===N.call(b)}function v(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function U(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function s(b,c){return ga.call(b,c)}function j(b,c){return s(b,c)&&b[c]}function B(b,c){for(var d in b)if(s(b,d)&&c(b[d],d))break}function V(b,c,d,g){c&&B(c,function(c,h){if(d||!s(b,h))g&&"object"===typeof c&&c&&!H(c)&&!G(c)&&!(c instanceof
+RegExp)?(b[h]||(b[h]={}),V(b[h],c,d,g)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function da(b){throw b;}function ea(b){if(!b)return b;var c=ca;v(b.split("."),function(b){c=c[b]});return c}function C(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=g;d&&(c.originalError=d);return c}function ha(b){function c(a,e,b){var f,n,c,d,g,h,i,I=e&&e.split("/");n=I;var m=l.map,k=m&&m["*"];if(a&&"."===a.charAt(0))if(e){n=
+I.slice(0,I.length-1);a=a.split("/");e=a.length-1;l.nodeIdCompat&&R.test(a[e])&&(a[e]=a[e].replace(R,""));n=a=n.concat(a);d=n.length;for(e=0;e<d;e++)if(c=n[e],"."===c)n.splice(e,1),e-=1;else if(".."===c)if(1===e&&(".."===n[2]||".."===n[0]))break;else 0<e&&(n.splice(e-1,2),e-=2);a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if(b&&m&&(I||k)){n=a.split("/");e=n.length;a:for(;0<e;e-=1){d=n.slice(0,e).join("/");if(I)for(c=I.length;0<c;c-=1)if(b=j(m,I.slice(0,c).join("/")))if(b=j(b,d)){f=b;
+g=e;break a}!h&&(k&&j(k,d))&&(h=j(k,d),i=e)}!f&&h&&(f=h,g=i);f&&(n.splice(0,g,f),a=n.join("/"))}return(f=j(l.pkgs,a))?f:a}function d(a){z&&v(document.getElementsByTagName("script"),function(e){if(e.getAttribute("data-requiremodule")===a&&e.getAttribute("data-requirecontext")===i.contextName)return e.parentNode.removeChild(e),!0})}function g(a){var e=j(l.paths,a);if(e&&H(e)&&1<e.length)return e.shift(),i.require.undef(a),i.require([a]),!0}function u(a){var e,b=a?a.indexOf("!"):-1;-1<b&&(e=a.substring(0,
+b),a=a.substring(b+1,a.length));return[e,a]}function m(a,e,b,f){var n,d,g=null,h=e?e.name:null,l=a,m=!0,k="";a||(m=!1,a="_@r"+(N+=1));a=u(a);g=a[0];a=a[1];g&&(g=c(g,h,f),d=j(p,g));a&&(g?k=d&&d.normalize?d.normalize(a,function(a){return c(a,h,f)}):c(a,h,f):(k=c(a,h,f),a=u(k),g=a[0],k=a[1],b=!0,n=i.nameToUrl(k)));b=g&&!d&&!b?"_unnormalized"+(Q+=1):"";return{prefix:g,name:k,parentMap:e,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(g?g+"!"+k:k)+b}}function q(a){var e=a.id,b=j(k,e);b||(b=k[e]=new i.Module(a));
+return b}function r(a,e,b){var f=a.id,n=j(k,f);if(s(p,f)&&(!n||n.defineEmitComplete))"defined"===e&&b(p[f]);else if(n=q(a),n.error&&"error"===e)b(n.error);else n.on(e,b)}function w(a,e){var b=a.requireModules,f=!1;if(e)e(a);else if(v(b,function(e){if(e=j(k,e))e.error=a,e.events.error&&(f=!0,e.emit("error",a))}),!f)h.onError(a)}function x(){S.length&&(ia.apply(A,[A.length,0].concat(S)),S=[])}function y(a){delete k[a];delete W[a]}function F(a,e,b){var f=a.map.id;a.error?a.emit("error",a.error):(e[f]=
+!0,v(a.depMaps,function(f,c){var d=f.id,g=j(k,d);g&&(!a.depMatched[c]&&!b[d])&&(j(e,d)?(a.defineDep(c,p[d]),a.check()):F(g,e,b))}),b[f]=!0)}function D(){var a,e,b=(a=1E3*l.waitSeconds)&&i.startTime+a<(new Date).getTime(),f=[],c=[],h=!1,k=!0;if(!X){X=!0;B(W,function(a){var i=a.map,m=i.id;if(a.enabled&&(i.isDefine||c.push(a),!a.error))if(!a.inited&&b)g(m)?h=e=!0:(f.push(m),d(m));else if(!a.inited&&(a.fetched&&i.isDefine)&&(h=!0,!i.prefix))return k=!1});if(b&&f.length)return a=C("timeout","Load timeout for modules: "+
+f,null,f),a.contextName=i.contextName,w(a);k&&v(c,function(a){F(a,{},{})});if((!b||e)&&h)if((z||fa)&&!Y)Y=setTimeout(function(){Y=0;D()},50);X=!1}}function E(a){s(p,a[0])||q(m(a[0],null,!0)).init(a[1],a[2])}function L(a){var a=a.currentTarget||a.srcElement,e=i.onScriptLoad;a.detachEvent&&!Z?a.detachEvent("onreadystatechange",e):a.removeEventListener("load",e,!1);e=i.onScriptError;(!a.detachEvent||Z)&&a.removeEventListener("error",e,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function M(){var a;
+for(x();A.length;){a=A.shift();if(null===a[0])return w(C("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));E(a)}}var X,$,i,K,Y,l={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},k={},W={},aa={},A=[],p={},T={},ba={},N=1,Q=1;K={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?a.module:
+a.module={id:a.map.id,uri:a.map.url,config:function(){return j(l.config,a.map.id)||{}},exports:K.exports(a)}}};$=function(a){this.events=j(aa,a.id)||{};this.map=a;this.shim=j(l.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};$.prototype={init:function(a,e,b,f){f=f||{};if(!this.inited){this.factory=e;if(b)this.on("error",b);else this.events.error&&(b=t(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=b;this.inited=
+!0;this.ignore=f.ignore;f.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,e){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=e)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=
+this.map.url;T[a]||(T[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,e,b=this.map.id;e=this.depExports;var f=this.exports,c=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&&
+(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=
+this.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,"defined",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||""),f=m(a.prefix+"!"+J,this.map.parentMap),r(f,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f);
+if(this.events.error)g.on("error",t(this,function(a){this.emit("error",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C("fromtexteval",
+"fromText eval for "+b+" failed: "+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if("string"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(K,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,"defined",t(this,function(a){this.defineDep(b,
+a);this.check()}));this.errback&&r(a,"error",t(this,this.errback))}c=a.id;f=k[c];!s(K,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m,
+nextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b,
+a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+"/"+(a.main||"main").replace(ja,"").replace(R,"")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild=
+!0);if("string"===typeof f){if(G(c))return w(C("requireargs","Invalid require call"),d);if(a&&s(K,f))return K[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C("notloaded",'Module name "'+j+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[j]}M();i.nextTick(function(){M();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf("."),g=b.split("/")[0];if(-1!==
+d&&(!("."===g||".."===g)||1<d))e=b.substring(d,b.length),b=b.substring(0,d);return i.nameToUrl(c(b,a&&a.id,!0),e,!0)},defined:function(b){return s(p,m(b,a,!1,!0).id)},specified:function(b){b=m(b,a,!1,!0).id;return s(p,b)||s(k,b)}});a||(g.undef=function(b){x();var c=m(b,a,!0),e=j(k,b);d(b);delete p[b];delete T[c.url];delete aa[b];U(A,function(a,c){a[0]===b&&A.splice(c,1)});e&&(e.events.defined&&(aa[b]=e.events),y(b))});return g},enable:function(a){j(k,a.id)&&q(a).enable()},completeLoad:function(a){var b,
+c,f=j(l.shim,a)||{},d=f.exports;for(x();A.length;){c=A.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);E(c)}c=j(k,a);if(!b&&!s(p,a)&&c&&!c.inited){if(l.enforceDefine&&(!d||!ea(d)))return g(a)?void 0:w(C("nodefine","No define call for "+a,null,[a]));E([a,f.deps||[],f.exportsFn])}D()},nameToUrl:function(a,b,c){var f,d,g;(f=j(l.pkgs,a))&&(a=f);if(f=j(ba,a))return i.nameToUrl(f,b,c);if(h.jsExtRegExp.test(a))f=a+(b||"");else{f=l.paths;a=a.split("/");for(d=a.length;0<d;d-=1)if(g=a.slice(0,
+d).join("/"),g=j(f,g)){H(g)&&(g=g[0]);a.splice(0,d,g);break}f=a.join("/");f+=b||(/^data\:|\?/.test(f)||c?"":".js");f=("/"===f.charAt(0)||f.match(/^[\w\+\.\-]+:/)?"":l.baseUrl)+f}return l.urlArgs?f+((-1===f.indexOf("?")?"?":"&")+l.urlArgs):f},load:function(a,b){h.load(i,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ka.test((a.currentTarget||a.srcElement).readyState))P=null,a=L(a),i.completeLoad(a.id)},onScriptError:function(a){var b=L(a);if(!g(b.id))return w(C("scripterror",
+"Script error for: "+b.id,a,[b.id]))}};i.require=i.makeRequire();return i}var h,x,y,D,L,E,P,M,q,Q,la=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ma=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,R=/\.js$/,ja=/^\.\//;x=Object.prototype;var N=x.toString,ga=x.hasOwnProperty,ia=Array.prototype.splice,z=!!("undefined"!==typeof window&&"undefined"!==typeof navigator&&window.document),fa=!z&&"undefined"!==typeof importScripts,ka=z&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,
+Z="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),F={},r={},S=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(G(requirejs))return;r=requirejs;requirejs=void 0}"undefined"!==typeof require&&!G(require)&&(r=require,require=void 0);h=requirejs=function(b,c,d,g){var u,m="_";!H(b)&&"string"!==typeof b&&(u=b,H(c)?(b=c,c=d,d=g):b=[]);u&&u.context&&(m=u.context);(g=j(F,m))||(g=F[m]=h.s.newContext(m));u&&g.configure(u);return g.require(b,c,d)};h.config=function(b){return h(b)};
+h.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=h);h.version="2.1.10";h.jsExtRegExp=/^\/|:|\?|\.js$/;h.isBrowser=z;x=h.s={contexts:F,newContext:ha};h({});v(["toUrl","undef","defined","specified"],function(b){h[b]=function(){var c=F._;return c.require[b].apply(c,arguments)}});if(z&&(y=x.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))y=x.head=D.parentNode;h.onError=da;h.createNode=function(b){var c=
+b.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");c.type=b.scriptType||"text/javascript";c.charset="utf-8";c.async=!0;return c};h.load=function(b,c,d){var g=b&&b.config||{};if(z)return g=h.createNode(g,c,d),g.setAttribute("data-requirecontext",b.contextName),g.setAttribute("data-requiremodule",c),g.attachEvent&&!(g.attachEvent.toString&&0>g.attachEvent.toString().indexOf("[native code"))&&!Z?(O=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)):
+(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1)),g.src=d,M=g,D?y.insertBefore(g,D):y.appendChild(g),M=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(L=b.getAttribute("data-main"))return q=L,r.baseUrl||(E=q.split("/"),q=E.pop(),Q=E.length?E.join("/")+"/":"./",r.baseUrl=
+Q),q=q.replace(R,""),h.jsExtRegExp.test(q)&&(q=L),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(g=M))P&&"interactive"===P.readyState||U(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),g=P;g&&(b||
+(b=g.getAttribute("data-requiremodule")),h=F[g.getAttribute("data-requirecontext")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this);
diff --git a/share/nitdoc/js/lib/utils.js b/share/nitdoc/js/lib/utils.js
new file mode 100644 (file)
index 0000000..43d437d
--- /dev/null
@@ -0,0 +1,209 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+   Documentation generator for the nit language.\r
+   Generate API documentation in HTML format from nit source code.\r
+*/\r
+\r
+/*\r
+ * Utils module\r
+ */\r
+define([\r
+       "jquery",\r
+], function($) {\r
+\r
+       String.prototype.startsWith = function(prefix, caseSensitive) {\r
+               if(caseSensitive) {\r
+                       return this.toUpperCase().indexOf(prefix.toUpperCase()) === 0;\r
+               }\r
+               return this.indexOf(prefix) === 0;\r
+       }\r
+\r
+       // Compare two strings using Sorensen-Dice Coefficient\r
+       // see: http://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient\r
+       String.prototype.dice = function(other) {\r
+               var length1 = this.length - 1;\r
+               var length2 = other.length - 1;\r
+               if(length1 < 1 || length2 < 1) return 0;\r
+\r
+               var bigrams2 = [];\r
+               for(var i = 0; i < length2; i++) {\r
+                       bigrams2.push(other.substr(i, 2));\r
+               }\r
+\r
+               var intersection = 0;\r
+               for(var i = 0; i < length1; i++) {\r
+                       var bigram1 = this.substr(i, 2);\r
+                       for(var j = 0; j < length2; j++) {\r
+                               if(bigram1 == bigrams2[j]) {\r
+                                       intersection++;\r
+                                       bigrams2[j] = null;\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+               return (2.0 * intersection) / (length1 + length2);\r
+       }\r
+\r
+       /* base64 */\r
+\r
+       String.prototype._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";\r
+\r
+       // public method for encoding\r
+       String.prototype.base64Encode = function () {\r
+               var output = "";\r
+               var chr1, chr2, chr3, enc1, enc2, enc3, enc4;\r
+               var i = 0;\r
+\r
+               input = this._utf8_encode();\r
+\r
+               while (i < input.length) {\r
+\r
+                       chr1 = input.charCodeAt(i++);\r
+                       chr2 = input.charCodeAt(i++);\r
+                       chr3 = input.charCodeAt(i++);\r
+\r
+                       enc1 = chr1 >> 2;\r
+                       enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\r
+                       enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\r
+                       enc4 = chr3 & 63;\r
+\r
+                       if (isNaN(chr2)) {\r
+                               enc3 = enc4 = 64;\r
+                       } else if (isNaN(chr3)) {\r
+                               enc4 = 64;\r
+                       }\r
+\r
+                       output = output +\r
+                       this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +\r
+                       this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);\r
+\r
+               }\r
+               return output;\r
+       };\r
+\r
+       // public method for decoding\r
+       String.prototype.base64Decode = function () {\r
+               var output = "";\r
+               var chr1, chr2, chr3;\r
+               var enc1, enc2, enc3, enc4;\r
+               var i = 0;\r
+\r
+               input = this.replace(/[^A-Za-z0-9\+\/\=]/g, "");\r
+\r
+               while (i < input.length) {\r
+\r
+                       enc1 = this._keyStr.indexOf(input.charAt(i++));\r
+                       enc2 = this._keyStr.indexOf(input.charAt(i++));\r
+                       enc3 = this._keyStr.indexOf(input.charAt(i++));\r
+                       enc4 = this._keyStr.indexOf(input.charAt(i++));\r
+\r
+                       chr1 = (enc1 << 2) | (enc2 >> 4);\r
+                       chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\r
+                       chr3 = ((enc3 & 3) << 6) | enc4;\r
+\r
+                       output = output + String.fromCharCode(chr1);\r
+\r
+                       if (enc3 != 64) {\r
+                               output = output + String.fromCharCode(chr2);\r
+                       }\r
+                       if (enc4 != 64) {\r
+                               output = output + String.fromCharCode(chr3);\r
+                       }\r
+\r
+               }\r
+               return output._utf8_decode();;\r
+       };\r
+\r
+       // private method for UTF-8 encoding\r
+       String.prototype._utf8_encode = function () {\r
+               string = this.replace(/\r\n/g,"\n");\r
+               var utftext = "";\r
+\r
+               for (var n = 0; n < string.length; n++) {\r
+\r
+                       var c = string.charCodeAt(n);\r
+\r
+                       if (c < 128) {\r
+                               utftext += String.fromCharCode(c);\r
+                       }\r
+                       else if((c > 127) && (c < 2048)) {\r
+                               utftext += String.fromCharCode((c >> 6) | 192);\r
+                               utftext += String.fromCharCode((c & 63) | 128);\r
+                       }\r
+                       else {\r
+                               utftext += String.fromCharCode((c >> 12) | 224);\r
+                               utftext += String.fromCharCode(((c >> 6) & 63) | 128);\r
+                               utftext += String.fromCharCode((c & 63) | 128);\r
+                       }\r
+\r
+               }\r
+               return utftext;\r
+       };\r
+\r
+       // private method for UTF-8 decoding\r
+       String.prototype._utf8_decode = function () {\r
+               var string = "";\r
+               var i = 0;\r
+               var c = c1 = c2 = 0;\r
+\r
+               while ( i < this.length ) {\r
+\r
+                       c = this.charCodeAt(i);\r
+\r
+                       if (c < 128) {\r
+                               string += String.fromCharCode(c);\r
+                               i++;\r
+                       }\r
+                       else if((c > 191) && (c < 224)) {\r
+                               c2 = this.charCodeAt(i+1);\r
+                               string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));\r
+                               i += 2;\r
+                       }\r
+                       else {\r
+                               c2 = this.charCodeAt(i+1);\r
+                               c3 = this.charCodeAt(i+2);\r
+                               string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));\r
+                               i += 3;\r
+                       }\r
+\r
+               }\r
+               return string;\r
+       };\r
+\r
+       // JQuery Case Insensitive :icontains selector\r
+       $.expr[':'].icontains = function(obj, index, meta, stack){\r
+               return (obj.textContent.replace(/\[[0-9]+\]/g, "") || obj.innerText.replace(/\[[0-9]+\]/g, "") || jQuery(obj).text().replace(/\[[0-9]+\]/g, "") || '').toLowerCase().indexOf(meta[3].toLowerCase()) >= 0;\r
+       };\r
+\r
+       return {\r
+               // Extract anchor part (after #) from URL string\r
+               extractAnchor: function(url) {\r
+                       var index = url.indexOf("#");\r
+                       if (index >= 0) {\r
+                               return url.substring(index + 1);\r
+                       }\r
+                       return null;\r
+               },\r
+\r
+               delayEvent: function(handler, event) {\r
+                       if(this.delayEvent.timeout) {\r
+                               clearTimeout(this.delayEvent.timeout);\r
+                       }\r
+                       this.delayEvent.timeout = setTimeout(function() {\r
+                           handler.call(event);\r
+                       }, 50);\r
+               }\r
+       };\r
+});\r
diff --git a/share/nitdoc/js/nitdoc.js b/share/nitdoc/js/nitdoc.js
new file mode 100644 (file)
index 0000000..73d33a4
--- /dev/null
@@ -0,0 +1,27 @@
+// require.js configuration
+var baseUrl = document.body.getAttribute("data-bootstrap-share") + '/js/lib';
+var href = document.location.href
+var searchList = href.substring(0, href.lastIndexOf('/')) + '/quicksearch-list';
+require.config({
+       baseUrl: baseUrl,
+       paths: {
+               plugins: '../plugins',
+               quicksearchList: searchList,
+               jQueryUI: "jquery-ui",
+    },
+       shim: {
+               "jQueryUI": {
+                   export: "$",
+                   deps: ['jquery']
+               }
+       }
+});
+
+// nitdoc main module
+define([
+       "plugins/folding",
+       "plugins/filtering",
+       "plugins/quicksearch",
+       "plugins/github",
+], function() {});
+
diff --git a/share/nitdoc/js/plugins/filtering.js b/share/nitdoc/js/plugins/filtering.js
new file mode 100644 (file)
index 0000000..1bb6e20
--- /dev/null
@@ -0,0 +1,167 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+   Documentation generator for the nit language.\r
+   Generate API documentation in HTML format from nit source code.\r
+*/\r
+\r
+/*\r
+ * Nitdoc Filtering\r
+ *\r
+ * Allow user to filter sidebar entries and search page\r
+ */\r
+define([\r
+       "jquery",\r
+       'jQueryUI',\r
+       "utils"\r
+], function($, UI, Utils) {\r
+\r
+       var Filtering = {\r
+\r
+               // Allow user to filter sidebar box entries by name\r
+               enableSidebarTextFilters: function(filterSelector) {\r
+                       var div = $(document.createElement("div"))\r
+                       .addClass("nitdoc-ui-filter")\r
+                       .append(\r
+                               $(document.createElement("input"))\r
+                               .addClass("nitdoc-ui-filter-field")\r
+                               .addClass("nitdoc-ui-filter-field-notused")\r
+                               .attr("type", "text")\r
+                               .attr("value",  "filter...")\r
+                               .keyup(function() {\r
+                                       var box = $(this).parents("nav.filterable");\r
+                                       var value = $(this).val();\r
+                                       box.find("ul li:not(:icontains('" + value + "'))").hide();\r
+                                       box.find("ul li:icontains('" + value + "')").show();\r
+                               })\r
+                               .focusout(function() {\r
+                                       if($(this).val() == "") {\r
+                                               $(this).addClass("nitdoc-ui-filter-field-notused");\r
+                                               $(this).val("filter...");\r
+                                       }\r
+                               })\r
+                               .focusin(function() {\r
+                                       if($(this).val() == "filter...") {\r
+                                               $(this).removeClass("nitdoc-ui-filter-field-notused");\r
+                                               $(this).val("");\r
+                                       }\r
+                               })\r
+                       );\r
+                       $(filterSelector).after(div);\r
+                       this.preloadSidebarTextFilters();\r
+               },\r
+\r
+               // Prealod filters using search query\r
+               preloadSidebarTextFilters: function() {\r
+                       var anchor = Utils.extractAnchor(document.location.hash);\r
+                       if(!anchor || anchor.indexOf("q=") == -1) return;\r
+\r
+                       var query = anchor.substring(2);\r
+                       if(!query) return;\r
+\r
+                       $(".nitdoc-ui-filter input:text")\r
+                       .val(query)\r
+                       .removeClass("nitdoc-ui-notused")\r
+                       .trigger("keyup");\r
+               },\r
+\r
+               // Allow user to filter side bar box entries by Introduced/Refined/inHerited type\r
+               enableSidebarTypeFilters: function(filterSelector) {\r
+                       var box = $(filterSelector);\r
+                       var types = {};\r
+\r
+                       box.find("li").each(function() {\r
+                               var span = $(this).find("span:first");\r
+                               if(!types[span.html()]) types[span.html()] = {\r
+                                       title: span.attr("title"),\r
+                                       class: $(this).attr("class")\r
+                               }\r
+                       });\r
+\r
+                       for(var type in types) {\r
+                               var a = $(document.createElement("a"))\r
+                               .addClass("nitdoc-ui-filter-link")\r
+                               .html(type)\r
+                               .attr("title", "Hide " + types[type].title)\r
+                               .attr("data-filter-class", types[type].class)\r
+                               .toggle(\r
+                                       function() {\r
+                                               var hclass = $(this).attr("data-filter-class");\r
+                                               $(this).parents(filterSelector).find("li." + hclass).hide();\r
+                                               $(this).addClass("nitdoc-ui-filter-hidden")\r
+                                       },\r
+                                       function() {\r
+                                               var hclass = $(this).attr("data-filter-class");\r
+                                               $(this).parents(filterSelector).find("li." + hclass).show();\r
+                                               $(this).removeClass("nitdoc-ui-filter-hidden")\r
+                                       }\r
+                               )\r
+                               $(filterSelector).find(".nitdoc-ui-filter").append(a);\r
+                       }\r
+               },\r
+\r
+               // Allow user to filter sidebar box entries by name\r
+               enableSearchPageField: function(filterSelector) {\r
+                       var div = $(document.createElement("div"))\r
+                       .addClass("nitdoc-ui-searchpage-filter")\r
+                       .append(\r
+                               $(document.createElement("input"))\r
+                               .addClass("nitdoc-ui-searchpage-field")\r
+                               .addClass("nitdoc-ui-filter-field-notused")\r
+                               .attr("type", "text")\r
+                               .attr("value",  "filter...")\r
+                               .keyup(function() {\r
+                                       var box = $(this).parents(".content.fullpage").find("article.filterable");\r
+                                       var value = $(this).val();\r
+                                       box.find("ul li:not(:icontains('" + value + "'))").hide();\r
+                                       box.find("ul li:icontains('" + value + "')").show();\r
+                               })\r
+                               .focusout(function() {\r
+                                       if($(this).val() == "") {\r
+                                               $(this).addClass("nitdoc-ui-filter-field-notused");\r
+                                               $(this).val("filter...");\r
+                                       }\r
+                               })\r
+                               .focusin(function() {\r
+                                       if($(this).val() == "filter...") {\r
+                                               $(this).removeClass("nitdoc-ui-filter-field-notused");\r
+                                               $(this).val("");\r
+                                       }\r
+                               })\r
+                       );\r
+                       $(filterSelector).after(div);\r
+                       this.preloadSearchPageField();\r
+               },\r
+\r
+               // Prealod filter using search query\r
+               preloadSearchPageField: function() {\r
+                       var anchor = Utils.extractAnchor(document.location.hash);\r
+                       if(!anchor || anchor.indexOf("q=") == -1) return;\r
+\r
+                       var query = anchor.substring(2);\r
+                       if(!query) return;\r
+\r
+                       $(".nitdoc-ui-searchpage-field")\r
+                       .val(query)\r
+                       .removeClass("nitdoc-ui-notused")\r
+                       .trigger("keyup");\r
+               }\r
+       };\r
+\r
+       Filtering.enableSidebarTextFilters("nav.filterable h3");\r
+       Filtering.enableSidebarTypeFilters("nav.filterable");\r
+       Filtering.enableSearchPageField(".content.fullpage h1:contains('Search')");\r
+\r
+       return Filtering;\r
+});\r
diff --git a/share/nitdoc/js/plugins/folding.js b/share/nitdoc/js/plugins/folding.js
new file mode 100644 (file)
index 0000000..9d58e3b
--- /dev/null
@@ -0,0 +1,66 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+   Documentation generator for the nit language.\r
+   Generate API documentation in HTML format from nit source code.\r
+*/\r
+\r
+/*\r
+ * Nitdoc Folding\r
+ *\r
+ * Allow user to fold sidebar blocks\r
+ */\r
+define([\r
+       'jquery',\r
+       'jQueryUI'\r
+], function($) {\r
+       $.widget("nitdoc.folding", {\r
+\r
+               options: {\r
+                       foldText: "-",\r
+                       unfoldText: "+",\r
+                       linkHolder: "h3",\r
+                       linkClass: "nitdoc-ui-fold",\r
+                       linkCSS: {\r
+                               "cursor": "pointer"\r
+                       }\r
+               },\r
+\r
+               _create: function() {\r
+                       this._foldLink = $("<a/>")\r
+                               .addClass(this.options.linkClass)\r
+                               .text(this.options.foldText);\r
+\r
+                       this.element.find(this.options.linkHolder)\r
+                       .prepend(this._foldLink)\r
+                       .css(this.options.linkCSS)\r
+                       .toggle(\r
+                               $.proxy(this._fold, this),\r
+                               $.proxy(this._unfold, this)\r
+                       );\r
+               },\r
+\r
+               _fold: function(event) {\r
+                       this._foldLink.text(this.options.unfoldText);\r
+                       this.element.find(this.options.linkHolder).nextAll().toggle();\r
+               },\r
+\r
+               _unfold: function() {\r
+                       this._foldLink.text(this.options.foldText);\r
+                       this.element.find(this.options.linkHolder).nextAll().toggle();\r
+               }\r
+       });\r
+\r
+       $(".sidebar nav").folding();\r
+});\r
diff --git a/share/nitdoc/js/plugins/github.js b/share/nitdoc/js/plugins/github.js
new file mode 100644 (file)
index 0000000..84ad4f2
--- /dev/null
@@ -0,0 +1,583 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+   Documentation generator for the nit language.\r
+   Generate API documentation in HTML format from nit source code.\r
+*/\r
+\r
+/*\r
+ * Nitdoc.Github comment edition module\r
+ *\r
+ * Allows user to modify source code comments directly from the Nitdoc\r
+ */\r
+define([\r
+       "jquery",\r
+       "github-api",\r
+       "highlight",\r
+       "marked",\r
+       "nit",\r
+       "plugins/modalbox",\r
+       "plugins/github/loginbox",\r
+       "plugins/github/commentbox",\r
+       "utils"\r
+], function($, GithubAPI, hljs, marked) {\r
+       var GithubUser = function(login, password, repo, branch) {\r
+               this.login = login;\r
+               this.password = password;\r
+               this.repo = repo;\r
+               this.auth = "Basic " +  (login + ':' + password).base64Encode();\r
+               this.branch = branch;\r
+       }\r
+\r
+       var GithubUI = {\r
+               init: function(upstream, basesha1) {\r
+                       console.info("Github plugin: init GitHub module (upstream: "+ upstream +", base: " + basesha1 + ")");\r
+                       this.origin = this._parseUpstream(upstream);\r
+                       this._initMarked();\r
+                       // Add github menu\r
+                       $("nav.main ul").append(\r
+                               $("<li/>")\r
+                               .attr("id", "nitdoc-github-li")\r
+                               .loginbox()\r
+                               .loginbox("displayLogin")\r
+                               .bind("loginbox_logoff", function() {\r
+                                       GithubUI.disactivate();\r
+                               })\r
+                               .bind("loginbox_login", function(event, infos) {\r
+                                       GithubUI._tryLoginFromCredentials(infos);\r
+                               })\r
+                       );\r
+                       // check local session\r
+                       this._tryLoginFromLocalSession();\r
+               },\r
+\r
+               activate: function(user, origin) {\r
+                       this.openedComments = 0;\r
+                       this._saveSession(user);\r
+                       $("#nitdoc-github-li").loginbox("displayLogout", origin, user);\r
+                       this._attachCommentBoxes();\r
+                       this._reloadComments();\r
+\r
+                       // Prevent page unload if there is comments in editing mode\r
+                       $(window).on('beforeunload', function() {\r
+                               if(GithubUI.openedComments > 0){\r
+                                       return "There is uncommited modified comments. Are you sure you want to leave this page?";\r
+                               }\r
+                       });\r
+               },\r
+\r
+               disactivate: function() {\r
+                       if(this.openedComments > 0){\r
+                               if(!confirm('There is uncommited modified comments. Are you sure you want to leave this page?')) {\r
+                                       return false;\r
+                               }\r
+                       }\r
+\r
+                       localStorage.clear();\r
+                       $("#nitdoc-github-li").loginbox("toggle");\r
+                       $("#nitdoc-github-li").loginbox("displayLogin");\r
+                       $(window).unbind('beforeunload');\r
+                       //window.location.reload();\r
+               },\r
+\r
+               /* login */\r
+\r
+               _checkLoginInfos: function(infos) {\r
+                       if(!infos.login || !infos.password || !infos.repo || !infos.branch) {\r
+                               $("<p/>")\r
+                               .text("Please enter your GitHub username, password, repository and branch.")\r
+                               .modalbox({\r
+                                       title: "Sign in error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return false;\r
+                       } else {\r
+                               return true;\r
+                       }\r
+               },\r
+\r
+               _tryLoginFromCredentials: function(infos) {\r
+                       if(this._checkLoginInfos(infos)) {\r
+                               var isok = this._tryLogin(infos.login, infos.password, infos.repo, infos.branch);\r
+                               if(isok === true) {\r
+                                       this.activate(this.user, this.origin);\r
+                               } else {\r
+                                       if(isok == "error:login") {\r
+                                               $("<p/>")\r
+                                               .text("The username, password, repo or branch you entered is incorrect.")\r
+                                               .modalbox({\r
+                                                       title: "Github sign in error",\r
+                                                       isError: true\r
+                                               })\r
+                                               .modalbox("open");\r
+                                       } else if(isok == "error:sha") {\r
+                                               $("<p/>")\r
+                                               .text("The provided Github repository must contain the base commit '" + UI.origin.sha + "'.")\r
+                                               .modalbox({\r
+                                                       title: "Github base commit error",\r
+                                                       isError: true\r
+                                               })\r
+                                               .modalbox("open");\r
+                                       } else if(isok == "error:profile") {\r
+                                               $("<p/>")\r
+                                               .text("Please set your public name and email in your " +\r
+                                                       "<a href='https://github.com/settings/profile'>GitHub profile</a>." +\r
+                                                       "<br/><br/>Your public profile informations are used to sign-off your commits.")\r
+                                               .modalbox({\r
+                                                       title: "Github profile error",\r
+                                                       isError: true\r
+                                               })\r
+                                               .modalbox("open");\r
+                                       }\r
+                               }\r
+                       }\r
+               },\r
+\r
+               _tryLoginFromLocalSession: function() {\r
+                       if(localStorage.user) {\r
+                               var session = JSON.parse(localStorage.user);\r
+                               var isok = this._tryLogin(\r
+                                       session.login,\r
+                                       session.password.base64Decode(),\r
+                                       session.repo,\r
+                                       session.branch\r
+                               );\r
+                               if(isok === true) {\r
+                                       this.activate(this.user, this.origin);\r
+                               } else {\r
+                                       console.debug("Github plugin: Session found but authentification failed");\r
+                                       localStorage.clear();\r
+                               }\r
+                       } else {\r
+                               console.debug("Github plugin: No session found");\r
+                       }\r
+               },\r
+\r
+               _tryLogin: function(login, password, repo, branch) {\r
+                       var tmpUser = new GithubUser(login, password, repo, branch);\r
+                       if(!GithubAPI.login(tmpUser)) {\r
+                               return "error:login";\r
+                       }\r
+                       if(!tmpUser.infos.name || !tmpUser.infos.email) {\r
+                               return "error:profile";\r
+                       }\r
+                       var commit = GithubAPI.getCommit(tmpUser, this.origin.sha);\r
+                       if(!commit || !commit.sha) {\r
+                               return "error:sha";\r
+                       }\r
+                       this.user = tmpUser;\r
+                       return true;\r
+               },\r
+\r
+               _saveSession: function(user) {\r
+                       localStorage.user = JSON.stringify({\r
+                               login: user.login,\r
+                               password: user.password.base64Encode(),\r
+                               repo: user.repo,\r
+                               branch: user.branch,\r
+                       });\r
+                       // check local storage synchro with branch\r
+                       if(localStorage.base != this.origin.sha) {\r
+                               console.log("Base changed: cleaned cache");\r
+                               localStorage.requests = "[]";\r
+                               localStorage.base = this.origin.sha;\r
+                       }\r
+               },\r
+\r
+               /* html decoration */\r
+\r
+               // Attach edit button on each comment\r
+               _attachCommentBoxes: function() {\r
+                       $("textarea.baseComment").each(function() {\r
+                               $(this).commentbox();\r
+\r
+                               var isNew = false;\r
+                               if(!$(this).val()) {\r
+                                       isNew = true;\r
+                                       $(this).nextAll(".info:first").find(".noComment").hide()\r
+                                       $(this).nextAll(".info:first").before(\r
+                                               $("<div/>")\r
+                                               .hide()\r
+                                               .addClass("comment")\r
+                                               .append(\r
+                                                       $("<div/>").addClass("nitdoc")\r
+                                               )\r
+                                       )\r
+                               }\r
+\r
+                               $(this).nextAll(".info:first").prepend(\r
+                                       $("<a/>")\r
+                                       .addClass("nitdoc-github-editComment")\r
+                                       .css("cursor", "pointer")\r
+                                       .text((isNew ? "add" : "edit") + " comment")\r
+                                       .click($.proxy(GithubUI._openCommentBox, GithubUI, null, $(this)))\r
+                                       .after(" for ")\r
+                               )\r
+\r
+                               $(this).bind("commentbox_commit", function(event, data) {\r
+                                       GithubUI._saveChanges(data);\r
+                                       $(this).commentbox("close");\r
+                                       GithubUI._reloadComments();\r
+                               })\r
+                               .bind("commentbox_preview", function(event, data) {\r
+                                       $("<div/>")\r
+                                       .append($("<h4/>").text("Comment:"))\r
+                                       .append(\r
+                                               $("<div/>")\r
+                                               .addClass("description")\r
+                                               .append(\r
+                                                       $("<div/>")\r
+                                                       .addClass("comment")\r
+                                                       .append(\r
+                                                               $("<div/>")\r
+                                                               .addClass("nitdoc")\r
+                                                               .html(marked(data.value))\r
+                                                       )\r
+                                               )\r
+                                       )\r
+                                       .append($("<h4/>").text("Message:"))\r
+                                       .append(\r
+                                               $("<div/>")\r
+                                               .addClass("description")\r
+                                               .append(\r
+                                                       $("<div/>")\r
+                                                       .addClass("comment")\r
+                                                       .append(\r
+                                                               $("<div/>").html(marked(data.message))\r
+                                                       )\r
+                                               )\r
+                                       )\r
+                                       .modalbox({\r
+                                               title: "Preview comment",\r
+                                               css: {"min-width": "500px"}\r
+                                       })\r
+                                       .modalbox("open");\r
+                               })\r
+                               .bind("commentbox_open", function(event, data) {\r
+                                       GithubUI.openedComments++;\r
+                                       $(this).nextAll(".comment").hide();\r
+                               })\r
+                               .bind("commentbox_close", function(event, data) {\r
+                                       GithubUI.openedComments--;\r
+                                       $(this).nextAll(".comment").show();\r
+                               });\r
+                       });\r
+               },\r
+\r
+               // reload comments from saved pull request\r
+               _reloadComments: function() {\r
+                       if(!localStorage.requests){ return; }\r
+                       $("p.pullRequest").remove();\r
+                       var requests = JSON.parse(localStorage.requests);\r
+                       // Look for modified comments in page\r
+                       for(i in requests) {\r
+                               if(!requests[i]) { continue; }\r
+                               var request = requests[i];\r
+                               $("textarea[data-comment-location=\"" + request.location + "\"]").each(function () {\r
+                                       if(request.isClosed) {\r
+                                               var oldComment = request.oldComment.base64Decode();\r
+                                               var htmlComment = marked(oldComment);\r
+                                               $(this).val(oldComment);\r
+                                               if(!$(this).val()) {\r
+                                                       $(this).nextAll("div.comment:first").hide();\r
+                                               } else {\r
+                                                       $(this).nextAll("div.comment:first").show();\r
+                                               }\r
+                                               $(this).nextAll("div.comment").find("div.nitdoc").empty().html(htmlComment);\r
+                                               $(this).nextAll("p.info").find("a.nitdoc-github-editComment").show();\r
+                                       } else {\r
+                                               var newComment = request.comment.base64Decode();\r
+                                               var htmlComment = marked(newComment);\r
+                                               $(this).val(newComment);\r
+                                               if(!$(this).val()) {\r
+                                                       $(this).nextAll("div.comment:first").hide();\r
+                                               } else {\r
+                                                       $(this).nextAll("div.comment:first").show();\r
+                                               }\r
+                                               $(this).nextAll("div.comment").find("div.nitdoc").empty().html(htmlComment);\r
+                                               GithubUI._addPullRequestLink($(this), request);\r
+                                               $(this).nextAll("p.info").find("a.nitdoc-github-editComment").hide();\r
+                                       }\r
+                               });\r
+                       }\r
+               },\r
+\r
+               _addPullRequestLink: function(baseArea, request) {\r
+                       baseArea.nextAll("p.info").before(\r
+                               $("<p/>")\r
+                               .addClass("pullRequest inheritance")\r
+                               .text("comment modified in ")\r
+                               .append(\r
+                                       $("<a/>")\r
+                                       .attr({\r
+                                               href: request.request.html_url,\r
+                                               title: "Review on GitHub"\r
+                                       })\r
+                                       .text("pull request #" + request.request.number)\r
+                               )\r
+                               .append(" ")\r
+                               .append(\r
+                                       $("<a/>")\r
+                                       .data("pullrequest-number", request.request.number)\r
+                                       .addClass("nitdoc-github-update")\r
+                                       .text("update")\r
+                                       .click($.proxy(GithubUI._doUpdateRequest, GithubUI, null, baseArea, request))\r
+                               )\r
+                               .append(" ")\r
+                               .append(\r
+                                       $("<a/>")\r
+                                       .data("pullrequest-number", request.request.number)\r
+                                       .addClass("nitdoc-github-cancel")\r
+                                       .text("cancel")\r
+                                       .click($.proxy(GithubUI._doCancelRequest, GithubUI, null, baseArea, request))\r
+                               )\r
+                       );\r
+               },\r
+\r
+               /* github calls */\r
+\r
+               _saveChanges: function(edit) {\r
+                       // if pull request update close existing pull request for the comment\r
+                       if(edit.requestID) {\r
+                               this._closePullRequest(edit.requestID);\r
+                       }\r
+                       edit.oldContent = this._getFileContent(edit.location.path);\r
+                       edit.newContent = this._mergeComment(edit.oldContent, edit.newComment, edit.location);\r
+                       edit.request = this._pushChanges(edit)\r
+                       if(!edit.request) {\r
+                               $("<p/>")\r
+                               .text("Unable to commit changes.<br/>" + response)\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return;\r
+                       }\r
+                       this._saveRequest(edit);\r
+               },\r
+\r
+               // save pull request in local storage\r
+               _saveRequest: function(edit) {\r
+                       var requests = {};\r
+                       if(localStorage.requests) {requests = JSON.parse(localStorage.requests)}\r
+                       requests[edit.request.number] = {\r
+                               request: edit.request,\r
+                               location: edit.location.origin,\r
+                               comment: edit.newComment.base64Encode(),\r
+                               oldComment: edit.oldComment.base64Encode()\r
+                       };\r
+                       localStorage.requests = JSON.stringify(requests);\r
+               },\r
+\r
+               /*\r
+                  Creating a new pull request with the new comment take 5 steps:\r
+                       1. get the base tree from latest commit\r
+\r
+                       2. create a new blob with updated file content\r
+                       3. post a new tree from base tree and blob\r
+                       4. post the new commit with new tree\r
+                       5. create the pull request\r
+               */\r
+               _pushChanges: function(edit) {\r
+                       var baseTree = GithubAPI.getTree(this.user, this.origin.sha);\r
+                       if(!baseTree.sha) {\r
+                               $("<p/>")\r
+                               .text("Unable to locate base tree.<br/>" + baseTree.status + ": " + baseTree.statusText)\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return false;\r
+                       }\r
+                       console.log("Base tree: " + baseTree.url);\r
+                       var newBlob = GithubAPI.createBlob(this.user, edit.newContent);\r
+                       if(!newBlob.sha) {\r
+                               $("<p/>")\r
+                               .text("Unable to create new blob.<br/>" + newBlob.status + ": " + newBlob.statusText)\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return false;\r
+                       }\r
+                       console.log("New blob: " + newBlob.url);\r
+                       var newTree = GithubAPI.createTree(this.user, baseTree, edit.location.path, newBlob);\r
+                       if(!newTree.sha) {\r
+                               $("<p/>")\r
+                               .text("Unable to create new tree.<br/>" + newTree.status + ": " + newTree.statusText)\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return false;\r
+                       }\r
+                       console.log("New tree: " + newTree.url);\r
+                       var newCommit = GithubAPI.createCommit(this.user, edit.message, baseTree.sha, newTree);\r
+                       if(!newCommit.sha) {\r
+                               $("<p/>")\r
+                               .text("Unable to create new commit.<br/>" + newCommit.status + ": " + newCommit.statusText)\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return false;\r
+                       }\r
+                       console.log("New commit: " + newCommit.url);\r
+                       var pullRequest = GithubAPI.createPullRequest(this.user, edit.title, "Pull request from Nitdoc", this.origin, newCommit.sha);\r
+                       if(!pullRequest.number) {\r
+                               $("<p/>")\r
+                               .text("Unable to create pull request.<br/>" + pullRequest.status + ": " + pullRequest.statusText)\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return false;\r
+                       }\r
+                       console.log("New pull request: " + pullRequest.url);\r
+                       return pullRequest;\r
+               },\r
+\r
+               // close previously opened pull request\r
+               _closePullRequest: function(number) {\r
+                       var requests = JSON.parse(localStorage.requests);\r
+                       if(!requests[number]) {\r
+                               $("<p/>")\r
+                               .text("Unable to close pull request.<br/>" + "Pull request " + number + "not found")\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return false;\r
+                       }\r
+                       // close pull request\r
+                       var res = GithubAPI.updatePullRequest(this.user, "Closed from Nitdoc", "", "closed", requests[number].request);\r
+                       if(!res.id) {\r
+                               $("<p/>")\r
+                               .text("Unable to close pull request.<br/>" + res.status + ": " + res.statusText)\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return false;\r
+                       }\r
+                       // update in localstorage\r
+                       requests[number].isClosed = true;\r
+                       localStorage.requests = JSON.stringify(requests);\r
+               },\r
+\r
+               /* internals */\r
+\r
+               _initMarked: function() {\r
+                       var renderer = new marked.Renderer();\r
+                       renderer.code = function(code) {\r
+                               return '<pre class="nitcode hljs">' + hljs.highlight('nit', code).value + '</pre>';\r
+                       }\r
+                       renderer.codespan = function(code) {\r
+                               return '<code class="nitcode hljs">' + hljs.highlight('nit', code).value + '</code>';\r
+                       }\r
+                       marked.setOptions({\r
+                               renderer: renderer,\r
+                               gfm: true,\r
+                               tables: true,\r
+                               breaks: true,\r
+                               pedantic: false,\r
+                               sanitize: true,\r
+                               smartLists: true,\r
+                               smartypants: false\r
+                       });\r
+               },\r
+\r
+               _parseUpstream: function(upstream) {\r
+                       var parts = upstream.split(":");\r
+                       return {\r
+                               user: parts[0],\r
+                               repo: parts[1],\r
+                               branch: parts[2],\r
+                               sha: basesha1\r
+                       };\r
+               },\r
+\r
+               _getFileContent: function(githubUrl) {\r
+                       var origFile = GithubAPI.getFile(this.user, githubUrl);\r
+                       if(!origFile.content) {\r
+                               $("<p/>")\r
+                               .text("Unable to locate source file.<br/>" + origFile.status + ": " + origFile.statusText)\r
+                               .modalbox({\r
+                                       title: "Github commit error",\r
+                                       isError: true\r
+                               })\r
+                               .modalbox("open");\r
+                               return;\r
+                       }\r
+                       var base64Content = origFile.content.substring(0, origFile.content.length - 1)\r
+                       return base64Content.base64Decode();\r
+               },\r
+\r
+               _mergeComment: function(fileContent, comment, location) {\r
+                       // replace comment in file content\r
+                       var res = new String();\r
+                       var lines = fileContent.split("\n");\r
+                       // copy lines fron 0 to lstart\r
+                       for(var i = 0; i < location.lstart - 1; i++) {\r
+                               res += lines[i] + "\n";\r
+                       }\r
+                       // set comment\r
+                       if(comment && comment != "") {\r
+                               var commentLines = comment.split("\n");\r
+                               for(var i = 0; i < commentLines.length; i++) {\r
+                                       var line = commentLines[i];\r
+                                       var tab = location.tabpos > 1 ? "\t" : "";\r
+                                       res += tab + (line.length > 0 ? "# " : "#") + line + "\n";\r
+                               }\r
+                       }\r
+                       // copy lines fron lend to end\r
+                       for(var i = location.lend - 1; i < lines.length; i++) {\r
+                               res += lines[i];\r
+                               if(i < lines.length - 1) { res += "\n"; }\r
+                       }\r
+                       return res;\r
+               },\r
+\r
+               /* events */\r
+\r
+               _openCommentBox: function(event, baseArea) {\r
+                       baseArea.commentbox("open", this.user);\r
+               },\r
+\r
+               _doCancelRequest: function(event, baseArea, request) {\r
+                       this._closePullRequest(request.request.number);\r
+                       this._reloadComments();\r
+               },\r
+\r
+               _doUpdateRequest: function(event, baseArea, request) {\r
+                       baseArea.commentbox("open", this.user, request.request.number);\r
+               },\r
+       }\r
+\r
+       // Get github plugin data\r
+       var upstream = $("body").attr("data-github-upstream");\r
+       var basesha1 = $("body").attr("data-github-base-sha1");\r
+       if(upstream && basesha1) {\r
+               GithubUI.init(upstream, basesha1);\r
+       }\r
+});\r
diff --git a/share/nitdoc/js/plugins/github/commentbox.js b/share/nitdoc/js/plugins/github/commentbox.js
new file mode 100644 (file)
index 0000000..2bb6a18
--- /dev/null
@@ -0,0 +1,231 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+*/\r
+\r
+/*\r
+ * CommentBox allows user to edit comments then preview, commit or cancel the changes\r
+ */\r
+define([\r
+       "jquery",\r
+       "jQueryUI"\r
+], function($) {\r
+       var Location = function(location) {\r
+               var parts = location.split(":");\r
+               this.origin = location;\r
+               this.path = parts[0];\r
+               this.lstart = parseInt(parts[1].split("--")[0].split(",")[0]);\r
+               this.tabpos = parseInt(parts[1].split("--")[0].split(",")[1]);\r
+               this.lend = parseInt(parts[1].split("--")[1].split(",")[0]);\r
+               this.toString = function() {\r
+                       return this.path + ":" + this.lstart + "," + this.tabpos + "--" + this.lend + ",0";\r
+               }\r
+       }\r
+\r
+       $.widget("nitdoc.commentbox", {\r
+\r
+               options: {\r
+                       previewTxt: "preview",\r
+                       commitTxt: "Commit",\r
+                       cancelTxt: "Cancel",\r
+                       commentboxTitle: "Edit comment",\r
+                       messageTxt: "Commit message"\r
+               },\r
+\r
+               _create: function() {\r
+                       this._id = $(".nitdoc-github-commentbox").length\r
+                       this._oldComment = this.element.val();\r
+                       this._namespace = this.element.data("comment-namespace");\r
+                       this._location = new Location(this.element.data("comment-location"));\r
+                       this.commentBox = $("<div/>")\r
+                       .hide()\r
+                       .addClass("nitdoc-github-commentbox")\r
+                       .append(\r
+                               $("<h3/>")\r
+                               .text(this.options.commentboxTitle)\r
+                       )\r
+                       .append(\r
+                               $("<dl/>")\r
+                               .addClass("nitdoc-github-commentbox-fields")\r
+                               .append(\r
+                                       $("<dd/>")\r
+                                       .append(\r
+                                               $("<textarea/>")\r
+                                               .attr("id", "nitdoc-github-commentbox-comment" + this._id)\r
+                                               .addClass("nitdoc-github-commentarea")\r
+                                               .keyup($.proxy(this._doKeyUp, this))\r
+                                               .keydown($.proxy(this._doKeyDown, this))\r
+                                       )\r
+                               )\r
+                               .append(\r
+                                       $("<dt/>")\r
+                                       .append(\r
+                                               $("<label/>")\r
+                                               .attr("for", "nitdoc-github-commentbox-message" + this._id)\r
+                                               .text(this.options.messageTxt + ":")\r
+                                       )\r
+                               )\r
+                               .append(\r
+                                       $("<dd/>")\r
+                                       .append(\r
+                                               $("<textarea/>")\r
+                                               .attr("id", "nitdoc-github-commentbox-message" + this._id)\r
+                                               .keyup($.proxy(this._doKeyUp, this))\r
+                                               .keydown($.proxy(this._doKeyDown, this))\r
+                                       )\r
+                               )\r
+                               .append(\r
+                                       $("<dt/>")\r
+                                       .append(\r
+                                               $("<input/>")\r
+                                               .attr({\r
+                                                       id: "nitdoc-github-commentbox-signedoff" + this._id,\r
+                                                       type: "checkbox"\r
+                                               })\r
+                                               .change($.proxy(this._doSignedChange, this))\r
+                                       )\r
+                                       .append(\r
+                                               $("<label/>")\r
+                                               .attr({\r
+                                                       "id": "nitdoc-github-commentbox-signedoff-label" + this._id,\r
+                                                       "for": "nitdoc-github-commentbox-signedoff" + this._id\r
+                                               })\r
+                                       )\r
+                               )\r
+                       )\r
+                       this._buildButtonBar();\r
+                       this.element.after(this.commentBox);\r
+               },\r
+\r
+               _buildButtonBar: function() {\r
+                       this.commentBox.append(\r
+                               $("<div/>")\r
+                               .addClass("nitdoc-github-commentbox-buttons")\r
+                               .append(\r
+                                       $("<a/>")\r
+                                       .addClass("nitdoc-github-preview")\r
+                                       .html(this.options.previewTxt)\r
+                                       .click($.proxy(this._doPreviewClick, this))\r
+                               )\r
+                               .append(\r
+                                       $("<button/>")\r
+                                       .addClass("nitdoc-github-button")\r
+                                       .addClass("nitdoc-github-commit")\r
+                                       .attr("disabled", "disabled")\r
+                                       .html(this.options.commitTxt)\r
+                                       .click($.proxy(this._doCommitClick, this))\r
+                               )\r
+                               .append(\r
+                                       $("<button/>")\r
+                                       .addClass("nitdoc-github-button")\r
+                                       .addClass("nitdoc-github-cancel")\r
+                                       .html(this.options.cancelTxt)\r
+                                       .click($.proxy(this._doCancelClick, this))\r
+                               )\r
+                       );\r
+               },\r
+\r
+               /* public actions */\r
+\r
+               open: function(user, requestID) {\r
+                       this._requestID = requestID;\r
+                       var value = this.element.val();\r
+                       var isNew = !value;\r
+                       var message = "doc: " + (isNew ? "added" : "modified") + " comment for " + this._namespace;\r
+                       this._setMessage(message);\r
+                       this._setSignedOff("Signed-off-by: " + user.signedOff);\r
+                       this._setComment(value);\r
+                       this.commentBox.show();\r
+                       this.commentBox.find("textarea").width(this.commentBox.innerWidth() - 45)\r
+                       $("#nitdoc-github-commentbox-comment" + this._id).focus();\r
+                       $("#nitdoc-github-commentbox-comment" + this._id).trigger("keyup");\r
+                       $("#nitdoc-github-commentbox-message" + this._id).trigger("keyup");\r
+                       this._trigger("_open", null, {commentBox: this});\r
+               },\r
+\r
+               close: function() {\r
+                       this.commentBox.hide();\r
+                       this._trigger("_close", null, {commentBox: this});\r
+               },\r
+\r
+               /* internals */\r
+\r
+               _setComment: function(value) {\r
+                       $("#nitdoc-github-commentbox-comment" + this._id).val(value);\r
+               },\r
+\r
+               _getComment: function() {\r
+                       return $("#nitdoc-github-commentbox-comment" + this._id).val();\r
+               },\r
+\r
+               _getMessage: function() {\r
+                       return $("#nitdoc-github-commentbox-message" + this._id).val();\r
+               },\r
+\r
+               _setMessage: function(message) {\r
+                       $("#nitdoc-github-commentbox-message" + this._id).val(message);\r
+               },\r
+\r
+               _getSignedOff: function() {\r
+                       return $("#nitdoc-github-commentbox-signedoff" + this._id).val();\r
+               },\r
+\r
+               _setSignedOff: function(signedoff) {\r
+                       $("#nitdoc-github-commentbox-signedoff" + this._id).val(signedoff);\r
+                       $("#nitdoc-github-commentbox-signedoff-label" + this._id).text(signedoff);\r
+               },\r
+\r
+               /* events */\r
+\r
+               _doKeyUp: function(event) {\r
+                       $(event.target).height($(event.target).val().split(/\r|\n/).length * 16);\r
+               },\r
+\r
+               _doKeyDown: function(event) {\r
+                       if(event.keyCode == 13){\r
+                               $(event.target).css("height", ($(event.target).outerHeight() + 6) + "px");\r
+                       }\r
+               },\r
+\r
+               _doSignedChange: function(event) {\r
+                       if ($(event.currentTarget).is(':checked')) {\r
+                               this.commentBox.find("button.nitdoc-github-commit").removeAttr("disabled");\r
+                       } else {\r
+                               this.commentBox.find("button.nitdoc-github-commit").attr("disabled", "disabled");\r
+                       }\r
+               },\r
+\r
+               _doPreviewClick: function(event) {\r
+                       this._trigger("_preview", event, {\r
+                               value: this._getComment(),\r
+                               message: this._getMessage() + "\n\n" + this._getSignedOff()\r
+                       });\r
+               },\r
+\r
+               _doCommitClick: function() {\r
+                       this._trigger("_commit", event, {\r
+                               requestID: this._requestID,\r
+                               location: this._location,\r
+                               namespace: this._namespace,\r
+                               oldComment: this._oldComment,\r
+                               newComment: this._getComment(),\r
+                               title: this._getMessage(),\r
+                               message: this._getMessage() + "\n\n" + this._getSignedOff()\r
+                       });\r
+               },\r
+\r
+               _doCancelClick: function() {\r
+                       this.close();\r
+               }\r
+       });\r
+});\r
diff --git a/share/nitdoc/js/plugins/github/loginbox.js b/share/nitdoc/js/plugins/github/loginbox.js
new file mode 100644 (file)
index 0000000..119b5e8
--- /dev/null
@@ -0,0 +1,234 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+*/\r
+\r
+/*\r
+ * LoginBox allows user to login and logoff from GitHub API\r
+ */\r
+define([\r
+       "jquery",\r
+       "jQueryUI"\r
+], function($) {\r
+       $.widget("nitdoc.loginbox", {\r
+               options: {\r
+                       icon: "resources/icons/github-icon.png",\r
+                       iconActive: "resources/icons/github-icon-green.png",\r
+                       iconAlt: "GitHub",\r
+                       signedinTxt: "Signed in Github",\r
+                       signedoutTxt: "Sign in Github",\r
+                       welcomeTxt: "Hello",\r
+                       upstreamTxt: "Upstream branch",\r
+                       baseTxt: "Base",\r
+                       signoffTxt: "Sign Off",\r
+                       usernameTxt: "Username",\r
+                       passwordTxt: "Password",\r
+                       repoTxt: "Repository",\r
+                       branchTxt: "Branch",\r
+                       signinTxt: "Sign In"\r
+               },\r
+\r
+               _create: function() {\r
+                       this.element.append(\r
+                               $("<a/>")\r
+                               .append(\r
+                                       $("<img/>")\r
+                                       .attr({\r
+                                               src: this.options.icon,\r
+                                               alt: this.options.iconAlt\r
+                                       })\r
+                                       .addClass("nitdoc-github-li-img")\r
+                               )\r
+                               .click($.proxy(this.toggle, this))\r
+                       );\r
+\r
+                       this.content = $("<div/>");\r
+                       this.loginBox = $("<div/>")\r
+                       .attr("id", "nitdoc-github-loginbox")\r
+                       .css("display", "none")\r
+                       .append(\r
+                               $(document.createElement("div"))\r
+                               .addClass("nitdoc-github-loginbox-arrow")\r
+                               .append("&nbsp;")\r
+                       )\r
+                       .append(this.content);\r
+                       this.element.append(this.loginBox);\r
+               },\r
+\r
+               /* public actions */\r
+\r
+               displayLogout: function(origin, user) {\r
+                       this.content.empty();\r
+                       this.content.append(\r
+                               $("<h3/>").text(this.options.signedinTxt)\r
+                       )\r
+                       this.content.append(\r
+                               $("<div/>")\r
+                               .append(\r
+                                       $("<h4/>")\r
+                                       .append(this.options.welcomeTxt + " ")\r
+                                       .append(\r
+                                               $("<a/>")\r
+                                               .attr("href", "https://github.com/" + user.login)\r
+                                               .append(user.login)\r
+                                       ).append(",")\r
+                               )\r
+                               .append(\r
+                                       $("<label/>")\r
+                                       .text("Upstream Branch")\r
+                               )\r
+                               .append(\r
+                                       $("<a/>")\r
+                                       .text(origin.user + ":" + origin.repo + ":" + origin.branch)\r
+                                       .addClass("nitdoc-github-loginbox-githublink")\r
+                                       .attr({\r
+                                               title: "Open branch in GitHub",\r
+                                               href: "https://github.com/" + origin.user + "/" + origin.repo + "/tree/" + origin.branch\r
+                                       })\r
+                               )\r
+                               .append(\r
+                                       $("<label/>")\r
+                                       .attr("for", "github-base")\r
+                                       .append("Your branch")\r
+                               )\r
+                               .append(\r
+                                       $("<a/>")\r
+                                       .text(user.login + ":" + user.repo + ":" + user.branch)\r
+                                       .addClass("nitdoc-github-loginbox-githublink")\r
+                                       .attr({\r
+                                               title: "Open branch in GitHub",\r
+                                               href: "https://github.com/" + user.login + "/" + user.repo + "/tree/" + user.branch\r
+                                       })\r
+                               )\r
+                               .append(\r
+                                       $("<button/>")\r
+                                       .addClass("nitdoc-github-button")\r
+                                       .addClass("nitdoc-github-cancel")\r
+                                       .append(\r
+                                               $("<img/>")\r
+                                               .attr("src", this.options.icon)\r
+                                       ).text(this.options.signoffTxt)\r
+                                       .click($.proxy(this._doClickLogoff, this))\r
+                               )\r
+                       );\r
+                       $(".nitdoc-github-li-img").attr("src", this.options.iconActive);\r
+               },\r
+\r
+               displayLogin: function() {\r
+                       this.content.empty();\r
+                       this.content.append(\r
+                               $("<h3/>").text(this.options.signedoutTxt)\r
+                       )\r
+                       this.content.append(\r
+                               $("<form/>")\r
+                               .keyup($.proxy(this._doFormChange, this))\r
+                               .append(\r
+                                       $("<label/>")\r
+                                       .attr("for", "nitdoc-github-login-field")\r
+                                       .append(this.options.usernameTxt)\r
+                               )\r
+                               .append(\r
+                                       $("<input/>")\r
+                                       .attr({\r
+                                               id: "nitdoc-github-login-field",\r
+                                               type: "text"\r
+                                       })\r
+                               )\r
+                               .append(\r
+                                       $("<label/>")\r
+                                       .attr("for", "nitdoc-github-password-field")\r
+                                       .append(this.options.passwordTxt)\r
+                               )\r
+                               .append(\r
+                                       $("<input/>")\r
+                                       .attr({\r
+                                               id: "nitdoc-github-password-field",\r
+                                               type: "password"\r
+                                       })\r
+                               )\r
+                               .append(\r
+                                       $("<label/>")\r
+                                       .attr("for", "nitdoc-github-repo-field")\r
+                                       .append(this.options.repoTxt)\r
+                               )\r
+                               .append(\r
+                                       $("<input/>")\r
+                                       .attr({\r
+                                               id: "nitdoc-github-repo-field",\r
+                                               type: "text"\r
+                                       })\r
+                               )\r
+                               .append(\r
+                                       $("<label/>")\r
+                                       .attr("for", "nitdoc-github-branch-field")\r
+                                       .append(this.options.branchTxt)\r
+                               )\r
+                               .append(\r
+                                       $("<input/>")\r
+                                       .attr({\r
+                                               id: "nitdoc-github-branch-field",\r
+                                               type: "text"\r
+                                       })\r
+                               )\r
+                               .append(\r
+                                       $("<button/>")\r
+                                       .addClass("nitdoc-github-button")\r
+                                       .attr("disabled", "disabled")\r
+                                       .append(\r
+                                               $("<img/>")\r
+                                               .attr("src", this.options.icon)\r
+                                       ).text(this.options.signinTxt)\r
+                                       .click($.proxy(this._doClickLogin, this))\r
+                               )\r
+                       );\r
+                       $(".nitdoc-github-li-img").attr("src", this.options.icon);\r
+               },\r
+\r
+               toggle: function() {\r
+                       if(this.loginBox.is(':hidden')) {\r
+                               this.loginBox.show();\r
+                               if ($('#nitdoc-github-login-field').is(':visible')) { $('#nitdoc-github-login-field').focus(); }\r
+                       } else {\r
+                               this.loginBox.hide();\r
+                       }\r
+               },\r
+\r
+               /* events */\r
+\r
+               _doClickLogoff: function(event) {\r
+                       this._trigger("_logoff", event);\r
+               },\r
+\r
+               _doClickLogin: function(event) {\r
+                       this._trigger("_login", event, {\r
+                               login: $('#nitdoc-github-login-field').val(),\r
+                               password: $('#nitdoc-github-password-field').val(),\r
+                               repo: $('#nitdoc-github-repo-field').val(),\r
+                               branch: $('#nitdoc-github-branch-field').val()\r
+                       });\r
+                       return false;\r
+               },\r
+\r
+               _doFormChange: function(event) {\r
+                       login = $('#nitdoc-github-login-field').val();\r
+                       password = $('#nitdoc-github-password-field').val();\r
+                       repo = $('#nitdoc-github-repo-field').val();\r
+                       branch = $('#nitdoc-github-branch-field').val();\r
+                       if(login && password && repo && branch) {\r
+                               this.loginBox.find("form .nitdoc-github-button").removeAttr("disabled");\r
+                       } else {\r
+                               this.loginBox.find("form .nitdoc-github-button").attr("disabled", "disabled");\r
+                       }\r
+               }\r
+       });\r
+});\r
diff --git a/share/nitdoc/js/plugins/modalbox.js b/share/nitdoc/js/plugins/modalbox.js
new file mode 100644 (file)
index 0000000..71bbbad
--- /dev/null
@@ -0,0 +1,104 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+   http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+   Documentation generator for the nit language.\r
+   Generate API documentation in HTML format from nit source code.\r
+*/\r
+\r
+define([\r
+       "jquery",\r
+       "jQueryUI"\r
+], function($) {\r
+       $.widget("nitdoc.modalbox", {\r
+               options: {\r
+                       id: "nitdoc-dialog",\r
+                       classes: "nitdoc-dialog",\r
+                       css: {},\r
+                       title: "Title",\r
+                       isError: false,\r
+               },\r
+\r
+               _create: function() {\r
+                       this._addFade();\r
+                       this._makeDialog();\r
+               },\r
+\r
+               open: function() {\r
+                       this._dialog\r
+                       .show()\r
+                       .css({\r
+                               top: "50%",\r
+                               marginTop: -(this._dialog.outerHeight() / 2) + "px",\r
+                               left: "50%",\r
+                               marginLeft: -(this._dialog.outerWidth() / 2) + "px"\r
+                       })\r
+                       .find(".nitdoc-dialog-buttons button:first").focus();\r
+\r
+                       this._fade.show();\r
+               },\r
+\r
+               close: function() {\r
+                       this._fade.hide();\r
+                       this._dialog.hide();\r
+               },\r
+\r
+               _addFade: function() {\r
+                       this._fade = $("<div/>")\r
+                       .hide()\r
+                       .attr("id", "nitdoc-dialog-fade-" + this.options.id)\r
+                       .addClass("nitdoc-dialog-fade");\r
+                       $("body").append(this._fade);\r
+               },\r
+\r
+               _makeDialog: function() {\r
+                       this._dialog = $("<div/>")\r
+                       .hide()\r
+                       .attr("id", this.options.id)\r
+                       .addClass(this.options.classes)\r
+                       .css(this.options.css)\r
+                       .append(\r
+                               $("<div/>")\r
+                               .addClass("nitdoc-dialog-header")\r
+                               .append(\r
+                                       $("<h3/>")\r
+                                       .text(this.options.title)\r
+                               )\r
+                               .append(\r
+                                       $("<button/>")\r
+                                       .addClass("nitdoc-dialog-close")\r
+                                       .append("x")\r
+                                       .click($.proxy(this.close, this))\r
+                               )\r
+                       )\r
+                       .append(\r
+                               $("<div/>")\r
+                               .addClass("nitdoc-dialog-content")\r
+                               .html(this.element)\r
+                       )\r
+                       .append(\r
+                               $("<div/>")\r
+                               .addClass("nitdoc-dialog-buttons")\r
+                               .append(\r
+                                       $("<button/>")\r
+                                       .append("Ok")\r
+                                       .click($.proxy(this.close, this))\r
+                               )\r
+                       );\r
+                       if(this.options.isError) {\r
+                               this._dialog.addClass("nitdoc-dialog-error");\r
+                       }\r
+                       $("body").append(this._dialog);\r
+               }\r
+       });\r
+});\r
diff --git a/share/nitdoc/js/plugins/quicksearch.js b/share/nitdoc/js/plugins/quicksearch.js
new file mode 100644 (file)
index 0000000..c4cd682
--- /dev/null
@@ -0,0 +1,396 @@
+/* This file is part of NIT ( http://www.nitlanguage.org ).
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+   Documentation generator for the nit language.
+   Generate API documentation in HTML format from nit source code.
+*/
+
+/*
+ * Nitdoc QuickSearch widget
+ */
+define([
+       "jquery",
+       "jQueryUI",
+       "utils",
+       "quicksearchList",
+], function($, ui, utils) {
+       $.widget("nitdoc.quicksearch", {
+
+               options: {
+                       list: {}, // List of raw results generated by nitdoc tool
+                       fieldNotUsedClass: "nitdoc-qs-field-notused",
+                       fieldAttrs: {
+                               autocomplete: "off",
+                               value: "quick search..."
+                       },
+                       tableID: "nitdoc-qs-table",
+                       tableCSS: {
+                               "position": "absolute"
+                       },
+                       rowClass: "nitdoc-qs-row",
+                       rowCatClass: "nitdoc-qs-cat",
+                       rowSubClass: "nitdoc-qs-sub",
+                       rowActiveClass: "nitdoc-qs-active",
+                       rowOverflowClass: "nitdoc-qs-overflow",
+                       rowOverflowActive: "nitdoc-qs-overflow-active",
+                       rowNoResultClass: "nitdoc-qs-noresult",
+                       overflowUpHtml: "&#x25B2;",
+                       overflowDownHtml: "&#x25BC;",
+                       noresultText: "Sorry, there is no match, best results are:",
+                       infoClass: "nitdoc-qs-info",
+                       gotoPage: "search.html",
+                       maxSize: 10
+               },
+
+               _create: function() {
+                       this.element
+                               .attr(this.options.fieldAttrs)
+                               .addClass(this.options.fieldNotUsedClass)
+                               .keydown($.proxy(this._doKeyDown, this))
+                               .keyup($.proxy(this._doKeyUp, this))
+                               .focusout($.proxy(this._doFocusOut, this))
+                               .focusin($.proxy(this._doFocusIn, this));
+
+                       this._table = $("<table/>")
+                               .attr("id", this.options.tableID)
+                               .css(this.options.tableCSS)
+                               .css("min-width", this.element.outerWidth());
+                       $("body").append(this._table);
+
+                       $(document).click($.proxy(this.closeTable, this));
+               },
+
+               /* events */
+
+               _doKeyDown: function(event) {
+                       switch(event.keyCode) {
+                               case 38: // Up
+                                       this._selectPrev();
+                                       return false;
+                               case 40: // Down
+                                       this._selectNext();
+                                       return false;
+                               default:
+                                       return true;
+                        }
+               },
+
+               _doKeyUp: function(event) {
+                       switch(event.keyCode) {
+                               case 38: // Up
+                               case 40: // Down
+                                       break;
+                               case 13: // Enter
+                                       this._loadResult();
+                                       break;
+                               case 27: // Escape
+                                       this.element.blur();
+                                       this.closeTable();
+                                       break;
+                               default: // Other keys
+                                       utils.delayEvent($.proxy(this.search, this));
+                                       break;
+                       }
+               },
+
+               _doFocusOut: function() {
+                       if(this.element.val() == "") {
+                               this.element.addClass(this.options.fieldNotUsedClass);
+                               this.element.val(this.options.fieldAttrs.value);
+                       }
+               },
+
+               _doFocusIn: function() {
+                       if(this.element.val() == this.options.fieldAttrs.value) {
+                               this.element.removeClass(this.options.fieldNotUsedClass);
+                               this.element.val("");
+                       }
+               },
+
+               /* Result lookup */
+
+               _getResults: function(query) {
+                       var results = {};
+                       results.matches = [];
+                       for(var entry in this.options.list) {
+                               if(!entry.startsWith(query, true)) {
+                                       continue;
+                               }
+                               var cat = {
+                                       name: entry,
+                                       entries: this.options.list[entry]
+                               };
+                               results.matches[results.matches.length] = cat;
+
+                               if(entry == query) {
+                                       cat.rank = 3;
+                               } else if(entry.toUpperCase() == query.toUpperCase()) {
+                                       cat.rank = 2;
+                               } else {
+                                       cat.rank = 1 + query.dice(entry);
+                               }
+                       }
+                       results.matches.sort(this._rankSorter);
+                       results.partials = new Array();
+                       if(results.matches.length == 0) {
+                               for(var entry in this.options.list) {
+                                       var cat = {
+                                               name: entry,
+                                               entries: this.options.list[entry]
+                                       }
+                                       cat.rank = query.dice(entry);
+                                       if(cat.rank > 0) {
+                                               results.partials[results.partials.length] = cat;
+                                       }
+                               }
+                               results.partials.sort(this._rankSorter);
+                       }
+                       return results;
+               },
+
+               _rankSorter: function(a, b){
+                       if(a.rank < b.rank) {
+                               return 1;
+                       } else if(a.rank > b.rank) {
+                               return -1;
+                       }
+                       return 0;
+               },
+
+               /* Results table */
+
+               search: function() {
+                       var query = this.element.val();
+                       if(query) {
+                               var results = this._getResults(query);
+                               this.openTable(query, results);
+                       }
+               },
+
+               openTable: function(query, results) {
+                       this._table.empty();
+                       this._rows = [];
+                       this._index = -1;
+
+                       var resultSet = results.matches;
+                       if(resultSet.length == 0) {
+                               resultSet = results.partials
+                       }
+
+                       for(var i in resultSet) {
+                               var cat = resultSet[i];
+                               var result = cat.entries[0];
+                               this.addRow(cat.name, result.txt, result.url, this.options.rowCatClass)
+                               for(var j = 1; j < cat.entries.length; j++) {
+                                       var result = cat.entries[j];
+                                       this.addRow(cat.name, result.txt, result.url, this.options.rowSubClass)
+                               }
+                       }
+
+                       if(this._rows.length >= this.options.maxSize) {
+                               this.addOverflowUp();
+                               this.addOverflowDown();
+                       }
+                       if(results.matches.length == 0) {
+                               this.addNoResultRow();
+                       }
+
+                       if(resultSet.length > 0) {
+                               this._setIndex(0);
+                       }
+                       this._table.show();
+                       this._autosizeTable();
+               },
+
+               closeTable: function(target) {
+                       if(target != this.element && target != this._table) {
+                               this._table.hide();
+                       }
+               },
+
+               addRow: function(name, txt, url, cls) {
+                       var row = $("<tr/>")
+                               .addClass(this.options.rowClass)
+                               .data("searchDetails", {name: name, url: url})
+                               .data("index", this._rows.length)
+                               .append(
+                                       $("<td/>")
+                                               .html(name)
+                                               .addClass(cls)
+                               )
+                               .append(
+                                       $("<td/>")
+                                               .html(txt + "&nbsp;&raquo;")
+                                               .addClass(this.options.infoClass)
+                               )
+                               .mouseover($.proxy(this._mouseOverRow, this))
+                               .click($.proxy(this._clickRow, this))
+                       this._rows.push(row);
+                       if(this._rows.length >= this.options.maxSize) {
+                               row.hide();
+                       }
+                       this._table.append(row);
+               },
+
+               addOverflowUp: function() {
+                       this._table.prepend(
+                               $("<tr/>")
+                                       .addClass(this.options.rowOverflowClass)
+                                       .append(
+                                               $("<td/>")
+                                                       .attr("colspan", 2)
+                                                       .html(this.options.overflowUpHtml)
+                                       )
+                                       .click($.proxy(this._clickPrev, this))
+                       );
+               },
+
+               addOverflowDown: function() {
+                       this._table.append(
+                               $("<tr/>")
+                                       .addClass(this.options.rowOverflowClass)
+                                       .addClass(this.options.rowOverflowActive)
+                                       .append(
+                                               $("<td/>")
+                                                       .attr("colspan", 2)
+                                                       .html(this.options.overflowDownHtml)
+                                       )
+                                       .click($.proxy(this._clickNext, this))
+                       );
+               },
+
+               addNoResultRow: function() {
+                       this._table.prepend(
+                               $("<tr/>")
+                               .addClass(this.options.rowNoResultClass)
+                               .append(
+                                       $("<td/>")
+                                       .attr("colspan", "2")
+                                       .text(this.options.noresultText)
+                               )
+                       );
+               },
+
+               _autosizeTable: function() {
+                       this._table.position({
+                               my: "right top",
+                               at: "right bottom",
+                               of: this.element
+                       });
+               },
+
+               _hasIndex: function(index) {
+                       return index >= 0 && index < this._rows.length;
+               },
+
+               _hasPrev: function(index) {
+                       return index - 1 >= 0;
+               },
+
+               _hasNext: function(index) {
+                       return index + 1 < this._rows.length;
+               },
+
+               _setIndex: function(index) {
+                       if(this._hasIndex(this._index)) {
+                               this._rows[this._index].removeClass(this.options.rowActiveClass);
+                       }
+                       this._index = index;
+                       if(this._hasIndex(this._index)) {
+                               this._rows[this._index].addClass(this.options.rowActiveClass);
+                       }
+               },
+
+               _selectPrev: function() {
+                       if(this._hasPrev(this._index)) {
+                               this._setIndex(this._index - 1);
+                               if(!this._rows[this._index].is(":visible")) {
+                                       this._table.find("tr." + this.options.rowClass + ":visible").last().hide();
+                                       this._table.find("tr." + this.options.rowOverflowClass).addClass(this.options.rowOverflowActive);
+                                       this._rows[this._index].show();
+                                       if(!this._hasPrev(this._index)) {
+                                               this._table.find("tr." + this.options.rowOverflowClass).removeClass(this.options.rowOverflowActive);
+                                       }
+                                       this._autosizeTable();
+                               }
+                       }
+               },
+
+               _selectNext: function() {
+                       if(this._hasNext(this._index)) {
+                               this._setIndex(this._index + 1);
+                               if(!this._rows[this._index].is(":visible")) {
+                                       this._table.find("tr." + this.options.rowClass + ":visible").first().hide();
+                                       this._table.find("tr." + this.options.rowOverflowClass).addClass(this.options.rowOverflowActive);
+                                       this._rows[this._index].show();
+                                       if(!this._hasNext(this._index)) {
+                                               this._table.find("tr." + this.options.rowOverflowClass).removeClass(this.options.rowOverflowActive);
+                                       }
+                                       this._autosizeTable();
+                               }
+                       }
+               },
+
+               // Load selected search result page
+               _loadResult: function() {
+                       if(this._index > -1) {
+                               window.location = this._rows[this._index].data("searchDetails").url;
+                               return;
+                       }
+                       if(this.element.val().length == 0) { return; }
+
+                       window.location = this.options.gotoPage + "#q=" + this.element.val();
+                       if(window.location.href.indexOf(this.options.gotoPage) > -1) {
+                               location.reload();
+                       }
+               },
+
+               /* table events */
+
+               _clickNext: function(event) {
+                       event.stopPropagation();
+                       this._selectNext();
+               },
+
+               _clickPrev: function(event) {
+                       event.stopPropagation();
+                       this._selectPrev();
+               },
+
+               _clickRow: function(event) {
+                       window.location = $(event.currentTarget).data("searchDetails")["url"];
+               },
+
+               _mouseOverRow: function(event) {
+                       this._setIndex($(event.currentTarget).data("index"));
+               }
+       });
+
+       var searchField = $("<input/>")
+       .addClass("nitdoc-qs-field-notused")
+       .attr({
+               id: "nitdoc-qs-field",
+               type: "text",
+       })
+
+       $("nav.main ul").append(
+               $("<li/>")
+                       .attr("id", "nitdoc-qs-li")
+                       .append(searchField)
+       );
+
+       searchField.quicksearch({
+               list: this.nitdocQuickSearchRawList
+       });
+});
diff --git a/share/nitdoc/scripts/Markdown.Converter.js b/share/nitdoc/scripts/Markdown.Converter.js
deleted file mode 100644 (file)
index 1a60277..0000000
+++ /dev/null
@@ -1,1412 +0,0 @@
-var Markdown;\r
-\r
-if (typeof exports === "object" && typeof require === "function") // we're in a CommonJS (e.g. Node.js) module\r
-    Markdown = exports;\r
-else\r
-    Markdown = {};\r
-\r
-// The following text is included for historical reasons, but should\r
-// be taken with a pinch of salt; it's not all true anymore.\r
-\r
-//\r
-// Wherever possible, Showdown is a straight, line-by-line port\r
-// of the Perl version of Markdown.\r
-//\r
-// This is not a normal parser design; it's basically just a\r
-// series of string substitutions.  It's hard to read and\r
-// maintain this way,  but keeping Showdown close to the original\r
-// design makes it easier to port new features.\r
-//\r
-// More importantly, Showdown behaves like markdown.pl in most\r
-// edge cases.  So web applications can do client-side preview\r
-// in Javascript, and then build identical HTML on the server.\r
-//\r
-// This port needs the new RegExp functionality of ECMA 262,\r
-// 3rd Edition (i.e. Javascript 1.5).  Most modern web browsers\r
-// should do fine.  Even with the new regular expression features,\r
-// We do a lot of work to emulate Perl's regex functionality.\r
-// The tricky changes in this file mostly have the "attacklab:"\r
-// label.  Major or self-explanatory changes don't.\r
-//\r
-// Smart diff tools like Araxis Merge will be able to match up\r
-// this file with markdown.pl in a useful way.  A little tweaking\r
-// helps: in a copy of markdown.pl, replace "#" with "//" and\r
-// replace "$text" with "text".  Be sure to ignore whitespace\r
-// and line endings.\r
-//\r
-\r
-\r
-//\r
-// Usage:\r
-//\r
-//   var text = "Markdown *rocks*.";\r
-//\r
-//   var converter = new Markdown.Converter();\r
-//   var html = converter.makeHtml(text);\r
-//\r
-//   alert(html);\r
-//\r
-// Note: move the sample code to the bottom of this\r
-// file before uncommenting it.\r
-//\r
-\r
-(function () {\r
-\r
-    function identity(x) { return x; }\r
-    function returnFalse(x) { return false; }\r
-\r
-    function HookCollection() { }\r
-\r
-    HookCollection.prototype = {\r
-\r
-        chain: function (hookname, func) {\r
-            var original = this[hookname];\r
-            if (!original)\r
-                throw new Error("unknown hook " + hookname);\r
-\r
-            if (original === identity)\r
-                this[hookname] = func;\r
-            else\r
-                this[hookname] = function (text) {\r
-                    var args = Array.prototype.slice.call(arguments, 0);\r
-                    args[0] = original.apply(null, args);\r
-                    return func.apply(null, args);\r
-                };\r
-        },\r
-        set: function (hookname, func) {\r
-            if (!this[hookname])\r
-                throw new Error("unknown hook " + hookname);\r
-            this[hookname] = func;\r
-        },\r
-        addNoop: function (hookname) {\r
-            this[hookname] = identity;\r
-        },\r
-        addFalse: function (hookname) {\r
-            this[hookname] = returnFalse;\r
-        }\r
-    };\r
-\r
-    Markdown.HookCollection = HookCollection;\r
-\r
-    // g_urls and g_titles allow arbitrary user-entered strings as keys. This\r
-    // caused an exception (and hence stopped the rendering) when the user entered\r
-    // e.g. [push] or [__proto__]. Adding a prefix to the actual key prevents this\r
-    // (since no builtin property starts with "s_"). See\r
-    // http://meta.stackoverflow.com/questions/64655/strange-wmd-bug\r
-    // (granted, switching from Array() to Object() alone would have left only __proto__\r
-    // to be a problem)\r
-    function SaveHash() { }\r
-    SaveHash.prototype = {\r
-        set: function (key, value) {\r
-            this["s_" + key] = value;\r
-        },\r
-        get: function (key) {\r
-            return this["s_" + key];\r
-        }\r
-    };\r
-\r
-    Markdown.Converter = function () {\r
-        var pluginHooks = this.hooks = new HookCollection();\r
-        \r
-        // given a URL that was encountered by itself (without markup), should return the link text that's to be given to this link\r
-        pluginHooks.addNoop("plainLinkText");\r
-        \r
-        // called with the orignal text as given to makeHtml. The result of this plugin hook is the actual markdown source that will be cooked\r
-        pluginHooks.addNoop("preConversion");\r
-        \r
-        // called with the text once all normalizations have been completed (tabs to spaces, line endings, etc.), but before any conversions have\r
-        pluginHooks.addNoop("postNormalization");\r
-        \r
-        // Called with the text before / after creating block elements like code blocks and lists. Note that this is called recursively\r
-        // with inner content, e.g. it's called with the full text, and then only with the content of a blockquote. The inner\r
-        // call will receive outdented text.\r
-        pluginHooks.addNoop("preBlockGamut");\r
-        pluginHooks.addNoop("postBlockGamut");\r
-        \r
-        // called with the text of a single block element before / after the span-level conversions (bold, code spans, etc.) have been made\r
-        pluginHooks.addNoop("preSpanGamut");\r
-        pluginHooks.addNoop("postSpanGamut");\r
-        \r
-        // called with the final cooked HTML code. The result of this plugin hook is the actual output of makeHtml\r
-        pluginHooks.addNoop("postConversion");\r
-\r
-        //\r
-        // Private state of the converter instance:\r
-        //\r
-\r
-        // Global hashes, used by various utility routines\r
-        var g_urls;\r
-        var g_titles;\r
-        var g_html_blocks;\r
-\r
-        // Used to track when we're inside an ordered or unordered list\r
-        // (see _ProcessListItems() for details):\r
-        var g_list_level;\r
-\r
-        this.makeHtml = function (text) {\r
-\r
-            //\r
-            // Main function. The order in which other subs are called here is\r
-            // essential. Link and image substitutions need to happen before\r
-            // _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>\r
-            // and <img> tags get encoded.\r
-            //\r
-\r
-            // This will only happen if makeHtml on the same converter instance is called from a plugin hook.\r
-            // Don't do that.\r
-            if (g_urls)\r
-                throw new Error("Recursive call to converter.makeHtml");\r
-        \r
-            // Create the private state objects.\r
-            g_urls = new SaveHash();\r
-            g_titles = new SaveHash();\r
-            g_html_blocks = [];\r
-            g_list_level = 0;\r
-\r
-            text = pluginHooks.preConversion(text);\r
-\r
-            // attacklab: Replace ~ with ~T\r
-            // This lets us use tilde as an escape char to avoid md5 hashes\r
-            // The choice of character is arbitray; anything that isn't\r
-            // magic in Markdown will work.\r
-            text = text.replace(/~/g, "~T");\r
-\r
-            // attacklab: Replace $ with ~D\r
-            // RegExp interprets $ as a special character\r
-            // when it's in a replacement string\r
-            text = text.replace(/\$/g, "~D");\r
-\r
-            // Standardize line endings\r
-            text = text.replace(/\r\n/g, "\n"); // DOS to Unix\r
-            text = text.replace(/\r/g, "\n"); // Mac to Unix\r
-\r
-            // Make sure text begins and ends with a couple of newlines:\r
-            text = "\n\n" + text + "\n\n";\r
-\r
-            // Convert all tabs to spaces.\r
-            text = _Detab(text);\r
-\r
-            // Strip any lines consisting only of spaces and tabs.\r
-            // This makes subsequent regexen easier to write, because we can\r
-            // match consecutive blank lines with /\n+/ instead of something\r
-            // contorted like /[ \t]*\n+/ .\r
-            text = text.replace(/^[ \t]+$/mg, "");\r
-            \r
-            text = pluginHooks.postNormalization(text);\r
-\r
-            // Turn block-level HTML blocks into hash entries\r
-            text = _HashHTMLBlocks(text);\r
-\r
-            // Strip link definitions, store in hashes.\r
-            text = _StripLinkDefinitions(text);\r
-\r
-            text = _RunBlockGamut(text);\r
-\r
-            text = _UnescapeSpecialChars(text);\r
-\r
-            // attacklab: Restore dollar signs\r
-            text = text.replace(/~D/g, "$$");\r
-\r
-            // attacklab: Restore tildes\r
-            text = text.replace(/~T/g, "~");\r
-\r
-            text = pluginHooks.postConversion(text);\r
-\r
-            g_html_blocks = g_titles = g_urls = null;\r
-\r
-            return text;\r
-        };\r
-\r
-        function _StripLinkDefinitions(text) {\r
-            //\r
-            // Strips link definitions from text, stores the URLs and titles in\r
-            // hash references.\r
-            //\r
-\r
-            // Link defs are in the form: ^[id]: url "optional title"\r
-\r
-            /*\r
-            text = text.replace(/\r
-                ^[ ]{0,3}\[(.+)\]:  // id = $1  attacklab: g_tab_width - 1\r
-                [ \t]*\r
-                \n?                 // maybe *one* newline\r
-                [ \t]*\r
-                <?(\S+?)>?          // url = $2\r
-                (?=\s|$)            // lookahead for whitespace instead of the lookbehind removed below\r
-                [ \t]*\r
-                \n?                 // maybe one newline\r
-                [ \t]*\r
-                (                   // (potential) title = $3\r
-                    (\n*)           // any lines skipped = $4 attacklab: lookbehind removed\r
-                    [ \t]+\r
-                    ["(]\r
-                    (.+?)           // title = $5\r
-                    [")]\r
-                    [ \t]*\r
-                )?                  // title is optional\r
-                (?:\n+|$)\r
-            /gm, function(){...});\r
-            */\r
-\r
-            text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm,\r
-                function (wholeMatch, m1, m2, m3, m4, m5) {\r
-                    m1 = m1.toLowerCase();\r
-                    g_urls.set(m1, _EncodeAmpsAndAngles(m2));  // Link IDs are case-insensitive\r
-                    if (m4) {\r
-                        // Oops, found blank lines, so it's not a title.\r
-                        // Put back the parenthetical statement we stole.\r
-                        return m3;\r
-                    } else if (m5) {\r
-                        g_titles.set(m1, m5.replace(/"/g, "&quot;"));\r
-                    }\r
-\r
-                    // Completely remove the definition from the text\r
-                    return "";\r
-                }\r
-            );\r
-\r
-            return text;\r
-        }\r
-\r
-        function _HashHTMLBlocks(text) {\r
-\r
-            // Hashify HTML blocks:\r
-            // We only want to do this for block-level HTML tags, such as headers,\r
-            // lists, and tables. That's because we still want to wrap <p>s around\r
-            // "paragraphs" that are wrapped in non-block-level tags, such as anchors,\r
-            // phrase emphasis, and spans. The list of tags we're looking for is\r
-            // hard-coded:\r
-            var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"\r
-            var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"\r
-\r
-            // First, look for nested blocks, e.g.:\r
-            //   <div>\r
-            //     <div>\r
-            //     tags for inner block must be indented.\r
-            //     </div>\r
-            //   </div>\r
-            //\r
-            // The outermost tags must start at the left margin for this to match, and\r
-            // the inner nested divs must be indented.\r
-            // We need to do this before the next, more liberal match, because the next\r
-            // match will start at the first `<div>` and stop at the first `</div>`.\r
-\r
-            // attacklab: This regex can be expensive when it fails.\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (                       // save in $1\r
-                    ^                   // start of line  (with /m)\r
-                    <($block_tags_a)    // start tag = $2\r
-                    \b                  // word break\r
-                                        // attacklab: hack around khtml/pcre bug...\r
-                    [^\r]*?\n           // any number of lines, minimally matching\r
-                    </\2>               // the matching end tag\r
-                    [ \t]*              // trailing spaces/tabs\r
-                    (?=\n+)             // followed by a newline\r
-                )                       // attacklab: there are sentinel newlines at end of document\r
-            /gm,function(){...}};\r
-            */\r
-            text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm, hashElement);\r
-\r
-            //\r
-            // Now match more liberally, simply from `\n<tag>` to `</tag>\n`\r
-            //\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (                       // save in $1\r
-                    ^                   // start of line  (with /m)\r
-                    <($block_tags_b)    // start tag = $2\r
-                    \b                  // word break\r
-                                        // attacklab: hack around khtml/pcre bug...\r
-                    [^\r]*?             // any number of lines, minimally matching\r
-                    .*</\2>             // the matching end tag\r
-                    [ \t]*              // trailing spaces/tabs\r
-                    (?=\n+)             // followed by a newline\r
-                )                       // attacklab: there are sentinel newlines at end of document\r
-            /gm,function(){...}};\r
-            */\r
-            text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm, hashElement);\r
-\r
-            // Special case just for <hr />. It was easier to make a special case than\r
-            // to make the other regex more complicated.  \r
-\r
-            /*\r
-            text = text.replace(/\r
-                \n                  // Starting after a blank line\r
-                [ ]{0,3}\r
-                (                   // save in $1\r
-                    (<(hr)          // start tag = $2\r
-                        \b          // word break\r
-                        ([^<>])*?\r
-                    \/?>)           // the matching end tag\r
-                    [ \t]*\r
-                    (?=\n{2,})      // followed by a blank line\r
-                )\r
-            /g,hashElement);\r
-            */\r
-            text = text.replace(/\n[ ]{0,3}((<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashElement);\r
-\r
-            // Special case for standalone HTML comments:\r
-\r
-            /*\r
-            text = text.replace(/\r
-                \n\n                                            // Starting after a blank line\r
-                [ ]{0,3}                                        // attacklab: g_tab_width - 1\r
-                (                                               // save in $1\r
-                    <!\r
-                    (--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)   // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackoverflow.com/q/95256\r
-                    >\r
-                    [ \t]*\r
-                    (?=\n{2,})                                  // followed by a blank line\r
-                )\r
-            /g,hashElement);\r
-            */\r
-            text = text.replace(/\n\n[ ]{0,3}(<!(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>[ \t]*(?=\n{2,}))/g, hashElement);\r
-\r
-            // PHP and ASP-style processor instructions (<?...?> and <%...%>)\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (?:\r
-                    \n\n            // Starting after a blank line\r
-                )\r
-                (                   // save in $1\r
-                    [ ]{0,3}        // attacklab: g_tab_width - 1\r
-                    (?:\r
-                        <([?%])     // $2\r
-                        [^\r]*?\r
-                        \2>\r
-                    )\r
-                    [ \t]*\r
-                    (?=\n{2,})      // followed by a blank line\r
-                )\r
-            /g,hashElement);\r
-            */\r
-            text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashElement);\r
-\r
-            return text;\r
-        }\r
-\r
-        function hashElement(wholeMatch, m1) {\r
-            var blockText = m1;\r
-\r
-            // Undo double lines\r
-            blockText = blockText.replace(/^\n+/, "");\r
-\r
-            // strip trailing blank lines\r
-            blockText = blockText.replace(/\n+$/g, "");\r
-\r
-            // Replace the element text with a marker ("~KxK" where x is its key)\r
-            blockText = "\n\n~K" + (g_html_blocks.push(blockText) - 1) + "K\n\n";\r
-\r
-            return blockText;\r
-        }\r
-        \r
-        var blockGamutHookCallback = function (t) { return _RunBlockGamut(t); }\r
-\r
-        function _RunBlockGamut(text, doNotUnhash) {\r
-            //\r
-            // These are all the transformations that form block-level\r
-            // tags like paragraphs, headers, and list items.\r
-            //\r
-            \r
-            text = pluginHooks.preBlockGamut(text, blockGamutHookCallback);\r
-            \r
-            text = _DoHeaders(text);\r
-\r
-            // Do Horizontal Rules:\r
-            var replacement = "<hr />\n";\r
-            text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, replacement);\r
-            text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm, replacement);\r
-            text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, replacement);\r
-\r
-            text = _DoLists(text);\r
-            text = _DoCodeBlocks(text);\r
-            text = _DoBlockQuotes(text);\r
-            \r
-            text = pluginHooks.postBlockGamut(text, blockGamutHookCallback);\r
-\r
-            // We already ran _HashHTMLBlocks() before, in Markdown(), but that\r
-            // was to escape raw HTML in the original Markdown source. This time,\r
-            // we're escaping the markup we've just created, so that we don't wrap\r
-            // <p> tags around block-level tags.\r
-            text = _HashHTMLBlocks(text);\r
-            text = _FormParagraphs(text, doNotUnhash);\r
-\r
-            return text;\r
-        }\r
-\r
-        function _RunSpanGamut(text) {\r
-            //\r
-            // These are all the transformations that occur *within* block-level\r
-            // tags like paragraphs, headers, and list items.\r
-            //\r
-\r
-            text = pluginHooks.preSpanGamut(text);\r
-            \r
-            text = _DoCodeSpans(text);\r
-            text = _EscapeSpecialCharsWithinTagAttributes(text);\r
-            text = _EncodeBackslashEscapes(text);\r
-\r
-            // Process anchor and image tags. Images must come first,\r
-            // because ![foo][f] looks like an anchor.\r
-            text = _DoImages(text);\r
-            text = _DoAnchors(text);\r
-\r
-            // Make links out of things like `<http://example.com/>`\r
-            // Must come after _DoAnchors(), because you can use < and >\r
-            // delimiters in inline links like [this](<url>).\r
-            text = _DoAutoLinks(text);\r
-            \r
-            text = text.replace(/~P/g, "://"); // put in place to prevent autolinking; reset now\r
-            \r
-            text = _EncodeAmpsAndAngles(text);\r
-            text = _DoItalicsAndBold(text);\r
-\r
-            // Do hard breaks:\r
-            text = text.replace(/  +\n/g, " <br>\n");\r
-            \r
-            text = pluginHooks.postSpanGamut(text);\r
-\r
-            return text;\r
-        }\r
-\r
-        function _EscapeSpecialCharsWithinTagAttributes(text) {\r
-            //\r
-            // Within tags -- meaning between < and > -- encode [\ ` * _] so they\r
-            // don't conflict with their use in Markdown for code, italics and strong.\r
-            //\r
-\r
-            // Build a regex to find HTML tags and comments.  See Friedl's \r
-            // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.\r
-\r
-            // SE: changed the comment part of the regex\r
-\r
-            var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--(?:|(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>)/gi;\r
-\r
-            text = text.replace(regex, function (wholeMatch) {\r
-                var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`");\r
-                tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackoverflow.com/questions/95987\r
-                return tag;\r
-            });\r
-\r
-            return text;\r
-        }\r
-\r
-        function _DoAnchors(text) {\r
-            //\r
-            // Turn Markdown link shortcuts into XHTML <a> tags.\r
-            //\r
-            //\r
-            // First, handle reference-style links: [link text] [id]\r
-            //\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (                           // wrap whole match in $1\r
-                    \[\r
-                    (\r
-                        (?:\r
-                            \[[^\]]*\]      // allow brackets nested one level\r
-                            |\r
-                            [^\[]           // or anything else\r
-                        )*\r
-                    )\r
-                    \]\r
-\r
-                    [ ]?                    // one optional space\r
-                    (?:\n[ ]*)?             // one optional newline followed by spaces\r
-\r
-                    \[\r
-                    (.*?)                   // id = $3\r
-                    \]\r
-                )\r
-                ()()()()                    // pad remaining backreferences\r
-            /g, writeAnchorTag);\r
-            */\r
-            text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);\r
-\r
-            //\r
-            // Next, inline-style links: [link text](url "optional title")\r
-            //\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (                           // wrap whole match in $1\r
-                    \[\r
-                    (\r
-                        (?:\r
-                            \[[^\]]*\]      // allow brackets nested one level\r
-                            |\r
-                            [^\[\]]         // or anything else\r
-                        )*\r
-                    )\r
-                    \]\r
-                    \(                      // literal paren\r
-                    [ \t]*\r
-                    ()                      // no id, so leave $3 empty\r
-                    <?(                     // href = $4\r
-                        (?:\r
-                            \([^)]*\)       // allow one level of (correctly nested) parens (think MSDN)\r
-                            |\r
-                            [^()\s]\r
-                        )*?\r
-                    )>?                \r
-                    [ \t]*\r
-                    (                       // $5\r
-                        (['"])              // quote char = $6\r
-                        (.*?)               // Title = $7\r
-                        \6                  // matching quote\r
-                        [ \t]*              // ignore any spaces/tabs between closing quote and )\r
-                    )?                      // title is optional\r
-                    \)\r
-                )\r
-            /g, writeAnchorTag);\r
-            */\r
-\r
-            text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?((?:\([^)]*\)|[^()\s])*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);\r
-\r
-            //\r
-            // Last, handle reference-style shortcuts: [link text]\r
-            // These must come last in case you've also got [link test][1]\r
-            // or [link test](/foo)\r
-            //\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (                   // wrap whole match in $1\r
-                    \[\r
-                    ([^\[\]]+)      // link text = $2; can't contain '[' or ']'\r
-                    \]\r
-                )\r
-                ()()()()()          // pad rest of backreferences\r
-            /g, writeAnchorTag);\r
-            */\r
-            text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);\r
-\r
-            return text;\r
-        }\r
-\r
-        function writeAnchorTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {\r
-            if (m7 == undefined) m7 = "";\r
-            var whole_match = m1;\r
-            var link_text = m2.replace(/:\/\//g, "~P"); // to prevent auto-linking withing the link. will be converted back after the auto-linker runs\r
-            var link_id = m3.toLowerCase();\r
-            var url = m4;\r
-            var title = m7;\r
-\r
-            if (url == "") {\r
-                if (link_id == "") {\r
-                    // lower-case and turn embedded newlines into spaces\r
-                    link_id = link_text.toLowerCase().replace(/ ?\n/g, " ");\r
-                }\r
-                url = "#" + link_id;\r
-\r
-                if (g_urls.get(link_id) != undefined) {\r
-                    url = g_urls.get(link_id);\r
-                    if (g_titles.get(link_id) != undefined) {\r
-                        title = g_titles.get(link_id);\r
-                    }\r
-                }\r
-                else {\r
-                    if (whole_match.search(/\(\s*\)$/m) > -1) {\r
-                        // Special case for explicit empty url\r
-                        url = "";\r
-                    } else {\r
-                        return whole_match;\r
-                    }\r
-                }\r
-            }\r
-            url = encodeProblemUrlChars(url);\r
-            url = escapeCharacters(url, "*_");\r
-            var result = "<a href=\"" + url + "\"";\r
-\r
-            if (title != "") {\r
-                title = attributeEncode(title);\r
-                title = escapeCharacters(title, "*_");\r
-                result += " title=\"" + title + "\"";\r
-            }\r
-\r
-            result += ">" + link_text + "</a>";\r
-\r
-            return result;\r
-        }\r
-\r
-        function _DoImages(text) {\r
-            //\r
-            // Turn Markdown image shortcuts into <img> tags.\r
-            //\r
-\r
-            //\r
-            // First, handle reference-style labeled images: ![alt text][id]\r
-            //\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (                   // wrap whole match in $1\r
-                    !\[\r
-                    (.*?)           // alt text = $2\r
-                    \]\r
-\r
-                    [ ]?            // one optional space\r
-                    (?:\n[ ]*)?     // one optional newline followed by spaces\r
-\r
-                    \[\r
-                    (.*?)           // id = $3\r
-                    \]\r
-                )\r
-                ()()()()            // pad rest of backreferences\r
-            /g, writeImageTag);\r
-            */\r
-            text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);\r
-\r
-            //\r
-            // Next, handle inline images:  ![alt text](url "optional title")\r
-            // Don't forget: encode * and _\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (                   // wrap whole match in $1\r
-                    !\[\r
-                    (.*?)           // alt text = $2\r
-                    \]\r
-                    \s?             // One optional whitespace character\r
-                    \(              // literal paren\r
-                    [ \t]*\r
-                    ()              // no id, so leave $3 empty\r
-                    <?(\S+?)>?      // src url = $4\r
-                    [ \t]*\r
-                    (               // $5\r
-                        (['"])      // quote char = $6\r
-                        (.*?)       // title = $7\r
-                        \6          // matching quote\r
-                        [ \t]*\r
-                    )?              // title is optional\r
-                    \)\r
-                )\r
-            /g, writeImageTag);\r
-            */\r
-            text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);\r
-\r
-            return text;\r
-        }\r
-        \r
-        function attributeEncode(text) {\r
-            // unconditionally replace angle brackets here -- what ends up in an attribute (e.g. alt or title)\r
-            // never makes sense to have verbatim HTML in it (and the sanitizer would totally break it)\r
-            return text.replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");\r
-        }\r
-\r
-        function writeImageTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {\r
-            var whole_match = m1;\r
-            var alt_text = m2;\r
-            var link_id = m3.toLowerCase();\r
-            var url = m4;\r
-            var title = m7;\r
-\r
-            if (!title) title = "";\r
-\r
-            if (url == "") {\r
-                if (link_id == "") {\r
-                    // lower-case and turn embedded newlines into spaces\r
-                    link_id = alt_text.toLowerCase().replace(/ ?\n/g, " ");\r
-                }\r
-                url = "#" + link_id;\r
-\r
-                if (g_urls.get(link_id) != undefined) {\r
-                    url = g_urls.get(link_id);\r
-                    if (g_titles.get(link_id) != undefined) {\r
-                        title = g_titles.get(link_id);\r
-                    }\r
-                }\r
-                else {\r
-                    return whole_match;\r
-                }\r
-            }\r
-            \r
-            alt_text = escapeCharacters(attributeEncode(alt_text), "*_[]()");\r
-            url = escapeCharacters(url, "*_");\r
-            var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";\r
-\r
-            // attacklab: Markdown.pl adds empty title attributes to images.\r
-            // Replicate this bug.\r
-\r
-            //if (title != "") {\r
-            title = attributeEncode(title);\r
-            title = escapeCharacters(title, "*_");\r
-            result += " title=\"" + title + "\"";\r
-            //}\r
-\r
-            result += " />";\r
-\r
-            return result;\r
-        }\r
-\r
-        function _DoHeaders(text) {\r
-\r
-            // Setext-style headers:\r
-            //  Header 1\r
-            //  ========\r
-            //  \r
-            //  Header 2\r
-            //  --------\r
-            //\r
-            text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,\r
-                function (wholeMatch, m1) { return "<h1>" + _RunSpanGamut(m1) + "</h1>\n\n"; }\r
-            );\r
-\r
-            text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,\r
-                function (matchFound, m1) { return "<h2>" + _RunSpanGamut(m1) + "</h2>\n\n"; }\r
-            );\r
-\r
-            // atx-style headers:\r
-            //  # Header 1\r
-            //  ## Header 2\r
-            //  ## Header 2 with closing hashes ##\r
-            //  ...\r
-            //  ###### Header 6\r
-            //\r
-\r
-            /*\r
-            text = text.replace(/\r
-                ^(\#{1,6})      // $1 = string of #'s\r
-                [ \t]*\r
-                (.+?)           // $2 = Header text\r
-                [ \t]*\r
-                \#*             // optional closing #'s (not counted)\r
-                \n+\r
-            /gm, function() {...});\r
-            */\r
-\r
-            text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,\r
-                function (wholeMatch, m1, m2) {\r
-                    var h_level = m1.length;\r
-                    return "<h" + h_level + ">" + _RunSpanGamut(m2) + "</h" + h_level + ">\n\n";\r
-                }\r
-            );\r
-\r
-            return text;\r
-        }\r
-\r
-        function _DoLists(text, isInsideParagraphlessListItem) {\r
-            //\r
-            // Form HTML ordered (numbered) and unordered (bulleted) lists.\r
-            //\r
-\r
-            // attacklab: add sentinel to hack around khtml/safari bug:\r
-            // http://bugs.webkit.org/show_bug.cgi?id=11231\r
-            text += "~0";\r
-\r
-            // Re-usable pattern to match any entirel ul or ol list:\r
-\r
-            /*\r
-            var whole_list = /\r
-                (                                   // $1 = whole list\r
-                    (                               // $2\r
-                        [ ]{0,3}                    // attacklab: g_tab_width - 1\r
-                        ([*+-]|\d+[.])              // $3 = first list item marker\r
-                        [ \t]+\r
-                    )\r
-                    [^\r]+?\r
-                    (                               // $4\r
-                        ~0                          // sentinel for workaround; should be $\r
-                        |\r
-                        \n{2,}\r
-                        (?=\S)\r
-                        (?!                         // Negative lookahead for another list item marker\r
-                            [ \t]*\r
-                            (?:[*+-]|\d+[.])[ \t]+\r
-                        )\r
-                    )\r
-                )\r
-            /g\r
-            */\r
-            var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;\r
-\r
-            if (g_list_level) {\r
-                text = text.replace(whole_list, function (wholeMatch, m1, m2) {\r
-                    var list = m1;\r
-                    var list_type = (m2.search(/[*+-]/g) > -1) ? "ul" : "ol";\r
-\r
-                    var result = _ProcessListItems(list, list_type, isInsideParagraphlessListItem);\r
-\r
-                    // Trim any trailing whitespace, to put the closing `</$list_type>`\r
-                    // up on the preceding line, to get it past the current stupid\r
-                    // HTML block parser. This is a hack to work around the terrible\r
-                    // hack that is the HTML block parser.\r
-                    result = result.replace(/\s+$/, "");\r
-                    result = "<" + list_type + ">" + result + "</" + list_type + ">\n";\r
-                    return result;\r
-                });\r
-            } else {\r
-                whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;\r
-                text = text.replace(whole_list, function (wholeMatch, m1, m2, m3) {\r
-                    var runup = m1;\r
-                    var list = m2;\r
-\r
-                    var list_type = (m3.search(/[*+-]/g) > -1) ? "ul" : "ol";\r
-                    var result = _ProcessListItems(list, list_type);\r
-                    result = runup + "<" + list_type + ">\n" + result + "</" + list_type + ">\n";\r
-                    return result;\r
-                });\r
-            }\r
-\r
-            // attacklab: strip sentinel\r
-            text = text.replace(/~0/, "");\r
-\r
-            return text;\r
-        }\r
-\r
-        var _listItemMarkers = { ol: "\\d+[.]", ul: "[*+-]" };\r
-\r
-        function _ProcessListItems(list_str, list_type, isInsideParagraphlessListItem) {\r
-            //\r
-            //  Process the contents of a single ordered or unordered list, splitting it\r
-            //  into individual list items.\r
-            //\r
-            //  list_type is either "ul" or "ol".\r
-\r
-            // The $g_list_level global keeps track of when we're inside a list.\r
-            // Each time we enter a list, we increment it; when we leave a list,\r
-            // we decrement. If it's zero, we're not in a list anymore.\r
-            //\r
-            // We do this because when we're not inside a list, we want to treat\r
-            // something like this:\r
-            //\r
-            //    I recommend upgrading to version\r
-            //    8. Oops, now this line is treated\r
-            //    as a sub-list.\r
-            //\r
-            // As a single paragraph, despite the fact that the second line starts\r
-            // with a digit-period-space sequence.\r
-            //\r
-            // Whereas when we're inside a list (or sub-list), that line will be\r
-            // treated as the start of a sub-list. What a kludge, huh? This is\r
-            // an aspect of Markdown's syntax that's hard to parse perfectly\r
-            // without resorting to mind-reading. Perhaps the solution is to\r
-            // change the syntax rules such that sub-lists must start with a\r
-            // starting cardinal number; e.g. "1." or "a.".\r
-\r
-            g_list_level++;\r
-\r
-            // trim trailing blank lines:\r
-            list_str = list_str.replace(/\n{2,}$/, "\n");\r
-\r
-            // attacklab: add sentinel to emulate \z\r
-            list_str += "~0";\r
-\r
-            // In the original attacklab showdown, list_type was not given to this function, and anything\r
-            // that matched /[*+-]|\d+[.]/ would just create the next <li>, causing this mismatch:\r
-            //\r
-            //  Markdown          rendered by WMD        rendered by MarkdownSharp\r
-            //  ------------------------------------------------------------------\r
-            //  1. first          1. first               1. first\r
-            //  2. second         2. second              2. second\r
-            //  - third           3. third                   * third\r
-            //\r
-            // We changed this to behave identical to MarkdownSharp. This is the constructed RegEx,\r
-            // with {MARKER} being one of \d+[.] or [*+-], depending on list_type:\r
-        \r
-            /*\r
-            list_str = list_str.replace(/\r
-                (^[ \t]*)                       // leading whitespace = $1\r
-                ({MARKER}) [ \t]+               // list marker = $2\r
-                ([^\r]+?                        // list item text   = $3\r
-                    (\n+)\r
-                )\r
-                (?=\r
-                    (~0 | \2 ({MARKER}) [ \t]+)\r
-                )\r
-            /gm, function(){...});\r
-            */\r
-\r
-            var marker = _listItemMarkers[list_type];\r
-            var re = new RegExp("(^[ \\t]*)(" + marker + ")[ \\t]+([^\\r]+?(\\n+))(?=(~0|\\1(" + marker + ")[ \\t]+))", "gm");\r
-            var last_item_had_a_double_newline = false;\r
-            list_str = list_str.replace(re,\r
-                function (wholeMatch, m1, m2, m3) {\r
-                    var item = m3;\r
-                    var leading_space = m1;\r
-                    var ends_with_double_newline = /\n\n$/.test(item);\r
-                    var contains_double_newline = ends_with_double_newline || item.search(/\n{2,}/) > -1;\r
-\r
-                    if (contains_double_newline || last_item_had_a_double_newline) {\r
-                        item = _RunBlockGamut(_Outdent(item), /* doNotUnhash = */true);\r
-                    }\r
-                    else {\r
-                        // Recursion for sub-lists:\r
-                        item = _DoLists(_Outdent(item), /* isInsideParagraphlessListItem= */ true);\r
-                        item = item.replace(/\n$/, ""); // chomp(item)\r
-                        if (!isInsideParagraphlessListItem) // only the outer-most item should run this, otherwise it's run multiple times for the inner ones\r
-                            item = _RunSpanGamut(item);\r
-                    }\r
-                    last_item_had_a_double_newline = ends_with_double_newline;\r
-                    return "<li>" + item + "</li>\n";\r
-                }\r
-            );\r
-\r
-            // attacklab: strip sentinel\r
-            list_str = list_str.replace(/~0/g, "");\r
-\r
-            g_list_level--;\r
-            return list_str;\r
-        }\r
-\r
-        function _DoCodeBlocks(text) {\r
-            //\r
-            //  Process Markdown `<pre><code>` blocks.\r
-            //  \r
-\r
-            /*\r
-            text = text.replace(/\r
-                (?:\n\n|^)\r
-                (                               // $1 = the code block -- one or more lines, starting with a space/tab\r
-                    (?:\r
-                        (?:[ ]{4}|\t)           // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width\r
-                        .*\n+\r
-                    )+\r
-                )\r
-                (\n*[ ]{0,3}[^ \t\n]|(?=~0))    // attacklab: g_tab_width\r
-            /g ,function(){...});\r
-            */\r
-\r
-            // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug\r
-            text += "~0";\r
-\r
-            text = text.replace(/(?:\n\n|^\n?)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,\r
-                function (wholeMatch, m1, m2) {\r
-                    var codeblock = m1;\r
-                    var nextChar = m2;\r
-\r
-                    codeblock = _EncodeCode(_Outdent(codeblock));\r
-                    codeblock = _Detab(codeblock);\r
-                    codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines\r
-                    codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace\r
-\r
-                    codeblock = "<pre><code>" + codeblock + "\n</code></pre>";\r
-\r
-                    return "\n\n" + codeblock + "\n\n" + nextChar;\r
-                }\r
-            );\r
-\r
-            // attacklab: strip sentinel\r
-            text = text.replace(/~0/, "");\r
-\r
-            return text;\r
-        }\r
-\r
-        function hashBlock(text) {\r
-            text = text.replace(/(^\n+|\n+$)/g, "");\r
-            return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n";\r
-        }\r
-\r
-        function _DoCodeSpans(text) {\r
-            //\r
-            // * Backtick quotes are used for <code></code> spans.\r
-            // \r
-            // * You can use multiple backticks as the delimiters if you want to\r
-            //   include literal backticks in the code span. So, this input:\r
-            //     \r
-            //      Just type ``foo `bar` baz`` at the prompt.\r
-            //     \r
-            //   Will translate to:\r
-            //     \r
-            //      <p>Just type <code>foo `bar` baz</code> at the prompt.</p>\r
-            //     \r
-            //   There's no arbitrary limit to the number of backticks you\r
-            //   can use as delimters. If you need three consecutive backticks\r
-            //   in your code, use four for delimiters, etc.\r
-            //\r
-            // * You can use spaces to get literal backticks at the edges:\r
-            //     \r
-            //      ... type `` `bar` `` ...\r
-            //     \r
-            //   Turns to:\r
-            //     \r
-            //      ... type <code>`bar`</code> ...\r
-            //\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (^|[^\\])       // Character before opening ` can't be a backslash\r
-                (`+)            // $2 = Opening run of `\r
-                (               // $3 = The code block\r
-                    [^\r]*?\r
-                    [^`]        // attacklab: work around lack of lookbehind\r
-                )\r
-                \2              // Matching closer\r
-                (?!`)\r
-            /gm, function(){...});\r
-            */\r
-\r
-            text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,\r
-                function (wholeMatch, m1, m2, m3, m4) {\r
-                    var c = m3;\r
-                    c = c.replace(/^([ \t]*)/g, ""); // leading whitespace\r
-                    c = c.replace(/[ \t]*$/g, ""); // trailing whitespace\r
-                    c = _EncodeCode(c);\r
-                    c = c.replace(/:\/\//g, "~P"); // to prevent auto-linking. Not necessary in code *blocks*, but in code spans. Will be converted back after the auto-linker runs.\r
-                    return m1 + "<code>" + c + "</code>";\r
-                }\r
-            );\r
-\r
-            return text;\r
-        }\r
-\r
-        function _EncodeCode(text) {\r
-            //\r
-            // Encode/escape certain characters inside Markdown code runs.\r
-            // The point is that in code, these characters are literals,\r
-            // and lose their special Markdown meanings.\r
-            //\r
-            // Encode all ampersands; HTML entities are not\r
-            // entities within a Markdown code span.\r
-            text = text.replace(/&/g, "&amp;");\r
-\r
-            // Do the angle bracket song and dance:\r
-            text = text.replace(/</g, "&lt;");\r
-            text = text.replace(/>/g, "&gt;");\r
-\r
-            // Now, escape characters that are magic in Markdown:\r
-            text = escapeCharacters(text, "\*_{}[]\\", false);\r
-\r
-            // jj the line above breaks this:\r
-            //---\r
-\r
-            //* Item\r
-\r
-            //   1. Subitem\r
-\r
-            //            special char: *\r
-            //---\r
-\r
-            return text;\r
-        }\r
-\r
-        function _DoItalicsAndBold(text) {\r
-\r
-            // <strong> must go first:\r
-            text = text.replace(/([\W_]|^)(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\2([\W_]|$)/g,\r
-            "$1<strong>$3</strong>$4");\r
-\r
-            text = text.replace(/([\W_]|^)(\*|_)(?=\S)([^\r\*_]*?\S)\2([\W_]|$)/g,\r
-            "$1<em>$3</em>$4");\r
-\r
-            return text;\r
-        }\r
-\r
-        function _DoBlockQuotes(text) {\r
-\r
-            /*\r
-            text = text.replace(/\r
-                (                           // Wrap whole match in $1\r
-                    (\r
-                        ^[ \t]*>[ \t]?      // '>' at the start of a line\r
-                        .+\n                // rest of the first line\r
-                        (.+\n)*             // subsequent consecutive lines\r
-                        \n*                 // blanks\r
-                    )+\r
-                )\r
-            /gm, function(){...});\r
-            */\r
-\r
-            text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,\r
-                function (wholeMatch, m1) {\r
-                    var bq = m1;\r
-\r
-                    // attacklab: hack around Konqueror 3.5.4 bug:\r
-                    // "----------bug".replace(/^-/g,"") == "bug"\r
-\r
-                    bq = bq.replace(/^[ \t]*>[ \t]?/gm, "~0"); // trim one level of quoting\r
-\r
-                    // attacklab: clean up hack\r
-                    bq = bq.replace(/~0/g, "");\r
-\r
-                    bq = bq.replace(/^[ \t]+$/gm, "");     // trim whitespace-only lines\r
-                    bq = _RunBlockGamut(bq);             // recurse\r
-\r
-                    bq = bq.replace(/(^|\n)/g, "$1  ");\r
-                    // These leading spaces screw with <pre> content, so we need to fix that:\r
-                    bq = bq.replace(\r
-                            /(\s*<pre>[^\r]+?<\/pre>)/gm,\r
-                        function (wholeMatch, m1) {\r
-                            var pre = m1;\r
-                            // attacklab: hack around Konqueror 3.5.4 bug:\r
-                            pre = pre.replace(/^  /mg, "~0");\r
-                            pre = pre.replace(/~0/g, "");\r
-                            return pre;\r
-                        });\r
-\r
-                    return hashBlock("<blockquote>\n" + bq + "\n</blockquote>");\r
-                }\r
-            );\r
-            return text;\r
-        }\r
-\r
-        function _FormParagraphs(text, doNotUnhash) {\r
-            //\r
-            //  Params:\r
-            //    $text - string to process with html <p> tags\r
-            //\r
-\r
-            // Strip leading and trailing lines:\r
-            text = text.replace(/^\n+/g, "");\r
-            text = text.replace(/\n+$/g, "");\r
-\r
-            var grafs = text.split(/\n{2,}/g);\r
-            var grafsOut = [];\r
-            \r
-            var markerRe = /~K(\d+)K/;\r
-\r
-            //\r
-            // Wrap <p> tags.\r
-            //\r
-            var end = grafs.length;\r
-            for (var i = 0; i < end; i++) {\r
-                var str = grafs[i];\r
-\r
-                // if this is an HTML marker, copy it\r
-                if (markerRe.test(str)) {\r
-                    grafsOut.push(str);\r
-                }\r
-                else if (/\S/.test(str)) {\r
-                    str = _RunSpanGamut(str);\r
-                    str = str.replace(/^([ \t]*)/g, "<p>");\r
-                    str += "</p>"\r
-                    grafsOut.push(str);\r
-                }\r
-\r
-            }\r
-            //\r
-            // Unhashify HTML blocks\r
-            //\r
-            if (!doNotUnhash) {\r
-                end = grafsOut.length;\r
-                for (var i = 0; i < end; i++) {\r
-                    var foundAny = true;\r
-                    while (foundAny) { // we may need several runs, since the data may be nested\r
-                        foundAny = false;\r
-                        grafsOut[i] = grafsOut[i].replace(/~K(\d+)K/g, function (wholeMatch, id) {\r
-                            foundAny = true;\r
-                            return g_html_blocks[id];\r
-                        });\r
-                    }\r
-                }\r
-            }\r
-            return grafsOut.join("\n\n");\r
-        }\r
-\r
-        function _EncodeAmpsAndAngles(text) {\r
-            // Smart processing for ampersands and angle brackets that need to be encoded.\r
-\r
-            // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:\r
-            //   http://bumppo.net/projects/amputator/\r
-            text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, "&amp;");\r
-\r
-            // Encode naked <'s\r
-            text = text.replace(/<(?![a-z\/?!]|~D)/gi, "&lt;");\r
-\r
-            return text;\r
-        }\r
-\r
-        function _EncodeBackslashEscapes(text) {\r
-            //\r
-            //   Parameter:  String.\r
-            //   Returns:    The string, with after processing the following backslash\r
-            //               escape sequences.\r
-            //\r
-\r
-            // attacklab: The polite way to do this is with the new\r
-            // escapeCharacters() function:\r
-            //\r
-            //     text = escapeCharacters(text,"\\",true);\r
-            //     text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);\r
-            //\r
-            // ...but we're sidestepping its use of the (slow) RegExp constructor\r
-            // as an optimization for Firefox.  This function gets called a LOT.\r
-\r
-            text = text.replace(/\\(\\)/g, escapeCharacters_callback);\r
-            text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, escapeCharacters_callback);\r
-            return text;\r
-        }\r
-\r
-        var charInsideUrl = "[-A-Z0-9+&@#/%?=~_|[\\]()!:,.;]",\r
-            charEndingUrl = "[-A-Z0-9+&@#/%=~_|[\\])]",\r
-            autoLinkRegex = new RegExp("(=\"|<)?\\b(https?|ftp)(://" + charInsideUrl + "*" + charEndingUrl + ")(?=$|\\W)", "gi"),\r
-            endCharRegex = new RegExp(charEndingUrl, "i");\r
-\r
-        function handleTrailingParens(wholeMatch, lookbehind, protocol, link) {\r
-            if (lookbehind)\r
-                return wholeMatch;\r
-            if (link.charAt(link.length - 1) !== ")")\r
-                return "<" + protocol + link + ">";\r
-            var parens = link.match(/[()]/g);\r
-            var level = 0;\r
-            for (var i = 0; i < parens.length; i++) {\r
-                if (parens[i] === "(") {\r
-                    if (level <= 0)\r
-                        level = 1;\r
-                    else\r
-                        level++;\r
-                }\r
-                else {\r
-                    level--;\r
-                }\r
-            }\r
-            var tail = "";\r
-            if (level < 0) {\r
-                var re = new RegExp("\\){1," + (-level) + "}$");\r
-                link = link.replace(re, function (trailingParens) {\r
-                    tail = trailingParens;\r
-                    return "";\r
-                });\r
-            }\r
-            if (tail) {\r
-                var lastChar = link.charAt(link.length - 1);\r
-                if (!endCharRegex.test(lastChar)) {\r
-                    tail = lastChar + tail;\r
-                    link = link.substr(0, link.length - 1);\r
-                }\r
-            }\r
-            return "<" + protocol + link + ">" + tail;\r
-        }\r
-        \r
-        function _DoAutoLinks(text) {\r
-\r
-            // note that at this point, all other URL in the text are already hyperlinked as <a href=""></a>\r
-            // *except* for the <http://www.foo.com> case\r
-\r
-            // automatically add < and > around unadorned raw hyperlinks\r
-            // must be preceded by a non-word character (and not by =" or <) and followed by non-word/EOF character\r
-            // simulating the lookbehind in a consuming way is okay here, since a URL can neither and with a " nor\r
-            // with a <, so there is no risk of overlapping matches.\r
-            text = text.replace(autoLinkRegex, handleTrailingParens);\r
-\r
-            //  autolink anything like <http://example.com>\r
-            \r
-            var replacer = function (wholematch, m1) { return "<a href=\"" + m1 + "\">" + pluginHooks.plainLinkText(m1) + "</a>"; }\r
-            text = text.replace(/<((https?|ftp):[^'">\s]+)>/gi, replacer);\r
-\r
-            // Email addresses: <address@domain.foo>\r
-            /*\r
-            text = text.replace(/\r
-                <\r
-                (?:mailto:)?\r
-                (\r
-                    [-.\w]+\r
-                    \@\r
-                    [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+\r
-                )\r
-                >\r
-            /gi, _DoAutoLinks_callback());\r
-            */\r
-\r
-            /* disabling email autolinking, since we don't do that on the server, either\r
-            text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,\r
-                function(wholeMatch,m1) {\r
-                    return _EncodeEmailAddress( _UnescapeSpecialChars(m1) );\r
-                }\r
-            );\r
-            */\r
-            return text;\r
-        }\r
-\r
-        function _UnescapeSpecialChars(text) {\r
-            //\r
-            // Swap back in all the special characters we've hidden.\r
-            //\r
-            text = text.replace(/~E(\d+)E/g,\r
-                function (wholeMatch, m1) {\r
-                    var charCodeToReplace = parseInt(m1);\r
-                    return String.fromCharCode(charCodeToReplace);\r
-                }\r
-            );\r
-            return text;\r
-        }\r
-\r
-        function _Outdent(text) {\r
-            //\r
-            // Remove one level of line-leading tabs or spaces\r
-            //\r
-\r
-            // attacklab: hack around Konqueror 3.5.4 bug:\r
-            // "----------bug".replace(/^-/g,"") == "bug"\r
-\r
-            text = text.replace(/^(\t|[ ]{1,4})/gm, "~0"); // attacklab: g_tab_width\r
-\r
-            // attacklab: clean up hack\r
-            text = text.replace(/~0/g, "")\r
-\r
-            return text;\r
-        }\r
-\r
-        function _Detab(text) {\r
-            if (!/\t/.test(text))\r
-                return text;\r
-\r
-            var spaces = ["    ", "   ", "  ", " "],\r
-            skew = 0,\r
-            v;\r
-\r
-            return text.replace(/[\n\t]/g, function (match, offset) {\r
-                if (match === "\n") {\r
-                    skew = offset + 1;\r
-                    return match;\r
-                }\r
-                v = (offset - skew) % 4;\r
-                skew = offset + 1;\r
-                return spaces[v];\r
-            });\r
-        }\r
-\r
-        //\r
-        //  attacklab: Utility functions\r
-        //\r
-\r
-        var _problemUrlChars = /(?:["'*()[\]:]|~D)/g;\r
-\r
-        // hex-encodes some unusual "problem" chars in URLs to avoid URL detection problems \r
-        function encodeProblemUrlChars(url) {\r
-            if (!url)\r
-                return "";\r
-\r
-            var len = url.length;\r
-\r
-            return url.replace(_problemUrlChars, function (match, offset) {\r
-                if (match == "~D") // escape for dollar\r
-                    return "%24";\r
-                if (match == ":") {\r
-                    if (offset == len - 1 || /[0-9\/]/.test(url.charAt(offset + 1)))\r
-                        return ":"\r
-                }\r
-                return "%" + match.charCodeAt(0).toString(16);\r
-            });\r
-        }\r
-\r
-\r
-        function escapeCharacters(text, charsToEscape, afterBackslash) {\r
-            // First we have to escape the escape characters so that\r
-            // we can build a character class out of them\r
-            var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g, "\\$1") + "])";\r
-\r
-            if (afterBackslash) {\r
-                regexString = "\\\\" + regexString;\r
-            }\r
-\r
-            var regex = new RegExp(regexString, "g");\r
-            text = text.replace(regex, escapeCharacters_callback);\r
-\r
-            return text;\r
-        }\r
-\r
-\r
-        function escapeCharacters_callback(wholeMatch, m1) {\r
-            var charCodeToEscape = m1.charCodeAt(0);\r
-            return "~E" + charCodeToEscape + "E";\r
-        }\r
-\r
-    }; // end of the Markdown.Converter constructor\r
-\r
-})();\r
diff --git a/share/nitdoc/scripts/Nitdoc.GitHub.js b/share/nitdoc/scripts/Nitdoc.GitHub.js
deleted file mode 100644 (file)
index 5b5782c..0000000
+++ /dev/null
@@ -1,1248 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-/*\r
- * Nitdoc.Github comment edition module\r
- *\r
- * Allows user to modify source code comments directly from the Nitdoc\r
- */\r
-\r
-var Nitdoc = Nitdoc || {};\r
-\r
-Nitdoc.GitHub = {}; // Declare Nitdoc.GitHub submodule\r
-\r
-// Load GitHub UI\r
-$(document).ready(function() {\r
-       //FIXME base should be choosen by user\r
-       var upstream = $("body").attr("data-github-upstream");\r
-       var basesha1 = $("body").attr("data-github-base-sha1");\r
-       if(upstream && basesha1) {\r
-               Nitdoc.GitHub.UI.init(upstream, basesha1);\r
-       }\r
-});\r
-\r
-/*\r
- * Nitdoc.Github.UI for comment edition module\r
- */\r
-Nitdoc.GitHub.UI = function() {\r
-       var openedComments = 0; // currently edited comments count\r
-       var user = false; // logged user\r
-       var origin;\r
-\r
-       var init = function(upstream, basesha1) {\r
-               console.log("init GitHub module (upstream: "+ upstream +", base: " + basesha1 + ")");\r
-\r
-               // parse origin\r
-               var parts = upstream.split(":");\r
-               if(parts.length < 3) {\r
-                       console.error("Incorrect upstream name `" + upstream + "`, should be of the form user:repo:branch");\r
-               }\r
-               origin = {\r
-                       user: parts[0],\r
-                       repo: parts[1],\r
-                       branch: parts[2],\r
-                       sha: basesha1\r
-               };\r
-\r
-               // check local session\r
-               if(localStorage.user) {\r
-                       var session = JSON.parse(localStorage.user);\r
-                       var user = tryLogin(session.login, Base64.decode(session.password), session.repo, session.branch);\r
-                       if(!user.login) {\r
-                               console.log("Session found but authentification failed");\r
-                               localStorage.clear();\r
-                       }\r
-               } else {\r
-                       console.log("No session found");\r
-               }\r
-\r
-               // activate ui\r
-               Nitdoc.GitHub.LoginBox.init("nav.main ul");\r
-               if(user && user.login) {\r
-                       Nitdoc.GitHub.LoginBox.displayLogout(origin, user);\r
-                       activate(user);\r
-               } else {\r
-                       Nitdoc.GitHub.LoginBox.displayLogin();\r
-               }\r
-\r
-               // Prevent page unload if there is comments in editing mode\r
-               $(window).on('beforeunload', function() {\r
-                       if(Nitdoc.GitHub.UI.getOpenedComments() > 0){\r
-                               return "There is uncommited modified comments. Are you sure you want to leave this page?";\r
-                       }\r
-               });\r
-       }\r
-\r
-       // Activate comment UI for a logged user\r
-       var activate = function(loggedUser) {\r
-               // Save session\r
-               user = loggedUser;\r
-               saveSession(user);\r
-               \r
-               // check local storage synchro with branch\r
-               if(localStorage.base != origin.sha) {\r
-                       console.log("Base changed: cleaned cache");\r
-                       localStorage.requests = "[]";\r
-                       localStorage.base = origin.sha;\r
-               }\r
-\r
-               attachCommentEvents();\r
-               reloadComments();\r
-       }\r
-\r
-       // clear storage\r
-       var disactivate = function() {\r
-               if(Nitdoc.GitHub.UI.getOpenedComments() > 0){\r
-                       if(!confirm('There is uncommited modified comments. Are you sure you want to leave this page?')) {\r
-                               return false;\r
-                       }\r
-               }\r
-               // close session and purge cookie\r
-               localStorage.clear();\r
-               $(window).unbind('beforeunload');\r
-               window.location.reload();\r
-       }\r
-\r
-       // Attempt login through GitHub API\r
-       var tryLogin = function(login, password, repo, branch) {\r
-               var user = new Nitdoc.GitHub.User(login, password, repo, branch);\r
-               if(!Nitdoc.GitHub.API.login(user)) {\r
-                       return "error:login";\r
-               }\r
-               // check github profile fields\r
-               if(!user.infos.name || !user.infos.email) {\r
-                       return "error:profile";\r
-               }\r
-               // check correct base commit\r
-               var commit = Nitdoc.GitHub.API.getCommit(user, origin.sha);\r
-               if(!commit || !commit.sha) {\r
-                       return "error:sha";\r
-               }\r
-               return user;\r
-       }\r
-\r
-       // Attach edit button on each comment\r
-       var attachCommentEvents = function() {\r
-               // Blocks without comment\r
-               $("span.noComment").each(function() {\r
-                       //FIXME this should be done by nitdoc\r
-                       var baseComment = $(this).parent().prev();\r
-                       var location = Nitdoc.GitHub.Utils.parseLocation(baseComment.attr("data-comment-location"));\r
-                       var locString = location.path + ":" + location.lstart + "," + location.tabpos + "--" + location.lstart + ",0";\r
-                       baseComment.attr("data-comment-location", locString);\r
-                       $(this).html("<a class='nitdoc-github-editComment noComment'>add comment</a> for ");\r
-                       $(this).addClass("nitdoc-github-editComment");\r
-               });\r
-               // Blocks with comment\r
-               $('.description div.comment').each(function() {\r
-                       var p = $(this).next();\r
-                       p.prepend("<span class='nitdoc-github-editComment'><a class='nitdoc-github-editComment'>edit comment</a> for </span>")\r
-               });\r
-\r
-               // Attach links events\r
-               $('a.nitdoc-github-editComment').each(function() {\r
-                       $(this).css("cursor", "pointer")\r
-                       $(this).click(function() {\r
-                               // hide link\r
-                               $(this).parent().hide();\r
-                               // add infos\r
-                               var infos = {};\r
-                               var baseTextarea;\r
-                               if(!$(this).hasClass("noComment")) {\r
-                                       $(this).parent().parent().prev().hide();\r
-                                       baseTextarea = $(this).parent().parent().prev().prev();\r
-                               } else {\r
-                                       baseTextarea = $(this).parent().parent().prev();\r
-                                       infos.isNew = true;\r
-                               }\r
-                               infos.user = Nitdoc.GitHub.UI.getUser();\r
-                               infos.location = Nitdoc.GitHub.Utils.parseLocation(baseTextarea.attr("data-comment-location"));\r
-                               infos.namespace = baseTextarea.attr("data-comment-namespace");\r
-                               infos.oldComment = baseTextarea.val();\r
-                               var box = new Nitdoc.GitHub.CommentBox(infos);\r
-                               box.open(baseTextarea);\r
-                       });\r
-               });\r
-       }\r
-\r
-       // reload comments from saved pull request\r
-       var reloadComments = function() {\r
-               if(!localStorage.requests){ return; }\r
-               var requests = JSON.parse(localStorage.requests);\r
-               var converter = new Markdown.Converter();\r
-               // Look for modified comments in page\r
-               for(i in requests) {\r
-                       if(!requests[i]) { continue; }\r
-                       var request = requests[i];\r
-                       $("textarea[data-comment-location=\"" + request.location + "\"]").each(function () {\r
-                               var div = $(this).next();\r
-                               if(request.isClosed) {\r
-                                       if(div.is("div.comment.newComment")) {\r
-                                               // hide empty comment\r
-                                               div.next().remove();\r
-                                               div.next().find("span.noComment").show();\r
-                                               div.remove();\r
-                                       } else if(div.is("div.comment.locked")) {\r
-                                               // unlock comment\r
-                                               div.empty();\r
-                                               div.append(converter.makeHtml($(this).text()));\r
-                                               div.removeClass("locked");\r
-                                               div.css("cursor", "pointer")\r
-                                               div.next().remove();\r
-                                               div.next().find("span.nitdoc-github-editComment").show();\r
-                                       }\r
-                               } else {\r
-                                       // create div for the new coment\r
-                                       if(!div.is("div.comment")) {\r
-                                               $(this).after("<div class='comment newComment'></div>");\r
-                                               div = $(this).next();\r
-                                       }\r
-                                       // lock modified comment\r
-                                       if(!div.hasClass("locked")) {\r
-                                               // convert modified comment to markdown\r
-                                               div.empty()\r
-                                               div.append(converter.makeHtml(Base64.decode(request.comment)));\r
-                                               // lock click\r
-                                               div.css("cursor", "auto");\r
-                                               div.addClass("locked");\r
-                                               div.next().find("span.nitdoc-github-editComment").hide();\r
-                                               div.after(\r
-                                                       $("<p class='locked inheritance'>")\r
-                                                       .text("comment modified in ")\r
-                                                       .append("<a href='"+ request.request.html_url +"' target='_blank' title='Review on GitHub'>pull request #"+ request.request.number +"</a>")\r
-                                                       .append(" ")\r
-                                                       .append(\r
-                                                               $("<a data-pullrequest-number='"+ request.request.number +"' class='nitdoc-github-update'>update</a>")\r
-                                                               .click(function (){\r
-                                                                       $(this).parent().hide();\r
-                                                                       div.hide();\r
-                                                                       var baseTextarea = div.prev();\r
-                                                                       // add infos\r
-                                                                       var infos = {};\r
-                                                                       infos.user = Nitdoc.GitHub.UI.getUser();\r
-                                                                       infos.location = Nitdoc.GitHub.Utils.parseLocation(baseTextarea.attr("data-comment-location"));\r
-                                                                       infos.namespace = baseTextarea.attr("data-comment-namespace");\r
-                                                                       infos.oldComment = baseTextarea.val();\r
-                                                                       infos.requestID = $(this).attr("data-pullrequest-number");\r
-                                                                       var box = new Nitdoc.GitHub.CommentBox(infos);\r
-                                                                       box.open(baseTextarea);                                                         \r
-                                                               })\r
-                                                       )\r
-                                                       .append(" ")\r
-                                                       .append(\r
-                                                               $("<a data-pullrequest-number='"+ request.request.number +"' class='nitdoc-github-cancel'>cancel</a>")\r
-                                                               .click(function (){\r
-                                                                       ui.closePullRequest($(this).attr("data-pullrequest-number"));\r
-                                                                       ui.reloadComments();\r
-                                                               })\r
-                                                       )\r
-                                               );\r
-                                       }\r
-                                       // hide "add comment" link\r
-                                       if(div.hasClass("newComment")) {\r
-                                               div.next().next().find("span.noComment").hide();\r
-                                       }\r
-                               }\r
-\r
-                       });\r
-               }\r
-       }\r
-\r
-       // Commit changes and send pull request\r
-       var saveChanges = function(infos) {\r
-               // if pull request update close existing pull request for the comment\r
-               if(infos.requestID) {\r
-                       closePullRequest(infos.requestID);\r
-               }\r
-\r
-               // forge commit\r
-               var fileContent = getFileContent(infos.location.path);\r
-               infos.newContent = Nitdoc.GitHub.Utils.mergeComment(fileContent, infos.newComment, infos.location);\r
-\r
-               // commit\r
-               infos.request = pushChanges(infos)\r
-               if(!infos.request) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to commit changes!", response, true);\r
-                       return;\r
-               }\r
-               saveRequest(infos);\r
-\r
-               // close boxes and reload comments              \r
-               Nitdoc.GitHub.CommitBox.close();\r
-               infos.commentBox.close();\r
-               reloadComments();\r
-       }\r
-\r
-       /*\r
-          Creating a new pull request with the new comment take 5 steps:\r
-               1. get the base tree from latest commit\r
-\r
-               2. create a new blob with updated file content\r
-               3. post a new tree from base tree and blob\r
-               4. post the new commit with new tree\r
-               5. create the pull request\r
-       */\r
-       var pushChanges = function(infos) {\r
-               var baseTree = Nitdoc.GitHub.API.getTree(user, origin.sha);\r
-               if(!baseTree.sha) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to locate base tree!", baseTree.status + ": " + baseTree.statusText, true);\r
-                       return false;\r
-               }\r
-               console.log("Base tree: " + baseTree.url);\r
-               var newBlob = Nitdoc.GitHub.API.createBlob(user, infos.newContent);\r
-               if(!newBlob.sha) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to create new blob!", newBlob.status + ": " + newBlob.statusText, true);\r
-                       return false;\r
-               }\r
-               console.log("New blob: " + newBlob.url);\r
-               var newTree = Nitdoc.GitHub.API.createTree(user, baseTree, infos.location.path, newBlob);\r
-               if(!newTree.sha) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to create new tree!", newTree.status + ": " + newTree.statusText, true);\r
-                       return false;\r
-               }\r
-               console.log("New tree: " + newTree.url);\r
-               var newCommit = Nitdoc.GitHub.API.createCommit(user, infos.message, baseTree.sha, newTree);\r
-               if(!newCommit.sha) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to create new commit!", newCommit.status + ": " + newCommit.statusText, true);\r
-                       return false;\r
-               }\r
-               console.log("New commit: " + newCommit.url);\r
-               var pullRequest = Nitdoc.GitHub.API.createPullRequest(user, infos.message.split("\n\n")[0], "Pull request from Nitdoc", origin, newCommit.sha);\r
-               if(!pullRequest.number) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to create pull request!", pullRequest.status + ": " + pullRequest.statusText, true);\r
-                       return false;\r
-               }\r
-               console.log("New pull request: " + pullRequest.url);\r
-               return pullRequest;\r
-       }\r
-\r
-       // close previously opened pull request\r
-       var closePullRequest = function(number) {\r
-               var requests = JSON.parse(localStorage.requests);\r
-               if(!requests[number]) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to close pull request!", "Pull request " + number + "not found", true);\r
-                       return false;\r
-               }\r
-               // close pull request\r
-               var res = Nitdoc.GitHub.API.updatePullRequest(user, "Canceled from Nitdoc", "", "closed", requests[number].request);\r
-               if(!res.id) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to close pull request!", res.status + ": " + res.statusText, true);\r
-                       return false;\r
-               }\r
-               // update in localstorage\r
-               requests[number].isClosed = true;\r
-               localStorage.requests = JSON.stringify(requests);\r
-       }\r
-\r
-       // Get file content from github\r
-       var getFileContent = function(githubUrl) {\r
-               var origFile = Nitdoc.GitHub.API.getFile(user, githubUrl);\r
-               if(!origFile.content) {\r
-                       Nitdoc.GitHub.ModalBox.open("Unable to locate source file!", origFile.status + ": " + origFile.statusText, true);\r
-                       return;\r
-               }\r
-               var base64Content = origFile.content.substring(0, origFile.content.length - 1)\r
-               return Base64.decode(base64Content);\r
-       }\r
-\r
-       // save pull request in local storage\r
-       var saveRequest = function(infos) {\r
-               var requests = [];\r
-               if(localStorage.requests) {requests = JSON.parse(localStorage.requests)}\r
-               requests[infos.request.number] = {\r
-                       request: infos.request,\r
-                       location: infos.location.origin,\r
-                       comment: Base64.encode(infos.newComment)\r
-               };\r
-               localStorage.requests = JSON.stringify(requests);\r
-       }\r
-\r
-       // save user in local storage\r
-       var saveSession = function(user) {\r
-               var session = {\r
-                       login: user.login,\r
-                       password: Base64.encode(user.password),\r
-                       repo: user.repo,\r
-                       branch: user.branch,\r
-               };\r
-               localStorage.user = JSON.stringify(session);\r
-       }\r
-\r
-       // accessors\r
-\r
-       var getUser = function() { return user; }\r
-       var getOrigin = function() { return origin; }\r
-       var getOpenedComments = function() { return openedComments; }\r
-       var addOpenedComments = function() { openedComments += 1; }\r
-       var remOpenedComments = function() { openedComments -= 1; }\r
-\r
-       // public interface\r
-       var ui = {\r
-               init: init,\r
-               tryLogin: tryLogin,\r
-               activate: activate,\r
-               disactivate: disactivate,\r
-               getUser: getUser,\r
-               getOrigin: getOrigin,\r
-               getOpenedComments: getOpenedComments,\r
-               addOpenedComments: addOpenedComments,\r
-               remOpenedComments: remOpenedComments,\r
-               saveChanges: saveChanges,\r
-               closePullRequest: closePullRequest,\r
-               reloadComments: reloadComments\r
-       }\r
-\r
-       return ui;\r
-}();\r
-\r
-/*\r
- * GitHub API user object\r
- */\r
-Nitdoc.GitHub.User = function(login, password, repo, branch) {\r
-       this.login = login;\r
-       this.password = password;\r
-       this.repo = repo;\r
-       this.auth = "Basic " +  Base64.encode(login + ':' + password);\r
-       this.branch = branch;\r
-};\r
-\r
-/* \r
- * GitHub API module\r
- */\r
-Nitdoc.GitHub.API = function() {\r
-\r
-       // try to login the user to github API\r
-       var login = function(user) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "GET",\r
-                       url: "https://api.github.com/repos/" + user.login + "/" + user.repo,\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function() {\r
-                               res = true;\r
-                       }\r
-               });\r
-               user.infos = getUserInfos(user);\r
-               user.signedOff = getSignedOff(user)\r
-               return res;\r
-       }\r
-\r
-       // request for user github account infos\r
-       var getUserInfos = function(user) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "GET",\r
-                           url: "https://api.github.com/users/" + user.login,\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-       }\r
-\r
-       // build signedoff user default signature\r
-       var getSignedOff = function(user) {\r
-               return user.infos.name + " <" + user.infos.email + ">";\r
-       }\r
-\r
-       // get the branches list from a repo\r
-       var getBranches = function(user) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "GET",\r
-                       url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/branches",\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-    }\r
-\r
-       /* GitHub commits */\r
-\r
-       // get the latest commit on `branchName`\r
-       var getCommit = function(user, sha) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "GET",\r
-                       url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/commits/" + sha,\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-    }\r
-\r
-       // get the base tree for a commit sha\r
-       var getTree = function(user, sha) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "GET",\r
-                       url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/trees/" + sha + "?recursive=1",\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-       }\r
-\r
-       // create a new blob\r
-       var createBlob = function(user, content) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "POST",\r
-                       url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/blobs",\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       data: JSON.stringify({\r
-                               content: Base64.encode(content),\r
-                               encoding: "base64"\r
-                       }),\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-    }\r
-\r
-       // create a new tree from a base tree\r
-       var createTree = function(user, baseTree, path, blob) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "POST",\r
-                       url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/trees",\r
-                       data: JSON.stringify({\r
-                               base_tree: baseTree.sha,\r
-                               tree: [{\r
-                                       path: path,\r
-                                       mode: "100644", // file (blob)\r
-                                       type: "blob",\r
-                                       sha: blob.sha\r
-                               }]\r
-                       }),\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-       }\r
-\r
-       // create a new commit\r
-       var createCommit = function(user, message, parentCommit, tree) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "POST",\r
-                       url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/git/commits",\r
-                       data: JSON.stringify({\r
-                               message: message,\r
-                               parents: parentCommit,\r
-                               tree: tree.sha,\r
-                       }),\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-       }\r
-\r
-       // create a pull request\r
-       var createPullRequest = function(user, title, body, origin, head) {\r
-               var res = false;\r
-               $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                               xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "POST",\r
-                       url: "https://api.github.com/repos/" + origin.user + "/" + origin.repo + "/pulls",\r
-                       data: JSON.stringify({\r
-                               title: title,\r
-                               body: body,\r
-                               base: origin.branch,\r
-                               head: user.login + ":" + head\r
-                       }),\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-       }\r
-\r
-       // update a pull request\r
-       var updatePullRequest = function(user, title, body, state, request) {\r
-               var res = false;\r
-                       $.ajax({\r
-                       beforeSend: function (xhr) {\r
-                                       xhr.setRequestHeader ("Authorization", user.auth);\r
-                       },\r
-                       type: "PATCH",\r
-                       url: request.url,\r
-                       data: JSON.stringify({\r
-                               title: title,\r
-                               body: body,\r
-                               state: state\r
-                       }),\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-       }\r
-\r
-       /* Files */\r
-\r
-       var getFile = function(user, path, branch) {\r
-               var res = false;\r
-               $.ajax({\r
-                       type: "GET",\r
-                       url: "https://api.github.com/repos/" + user.login + "/" + user.repo + "/contents/" + path,\r
-                       data: {\r
-                               ref: branch\r
-                       },\r
-                       async: false,\r
-                       dataType: 'json',\r
-                       success: function(response) {\r
-                               res = response;\r
-                       },\r
-                       error: function(response) {\r
-                               res = response;\r
-                       }\r
-               });\r
-               return res;\r
-       }\r
-\r
-       var api = {\r
-               login: login,\r
-               getCommit: getCommit,\r
-               getBranches: getBranches,\r
-               getTree: getTree,\r
-               createBlob: createBlob,\r
-               createTree: createTree,\r
-               createCommit: createCommit,\r
-               createPullRequest: createPullRequest,\r
-               updatePullRequest: updatePullRequest,\r
-               getFile: getFile\r
-       }\r
-\r
-       return api;\r
-}();\r
-\r
-/*\r
- * Nitdoc GitHub loginbox module\r
- */\r
-\r
-Nitdoc.GitHub.LoginBox = function() {\r
-       var loginBox;\r
-       var loginBoxLi;\r
-       var loginBoxContent;\r
-\r
-       var init = function(containerSelector) {\r
-               loginBoxLi = $(document.createElement("li"))\r
-               .attr("id", "nitdoc-github-li")\r
-               .append(\r
-                       $(document.createElement("a"))\r
-                       .append(\r
-                               $(document.createElement("img"))\r
-                               .attr({\r
-                                       src: "resources/icons/github-icon.png",\r
-                                       alt: "GitHub"\r
-                               })\r
-                               .addClass("nitdoc-github-li-img")\r
-                       )\r
-                       .click(function() { Nitdoc.GitHub.LoginBox.toggle() })\r
-               )\r
-\r
-               loginBoxContent = $(document.createElement("div"));\r
-               loginBox = $(document.createElement("div"))\r
-               .attr("id", "nitdoc-github-loginbox")\r
-               .css("display", "none")\r
-               .append(\r
-                       $(document.createElement("div"))\r
-                       .addClass("nitdoc-github-loginbox-arrow")\r
-                       .append("&nbsp;")\r
-               )\r
-               .append(loginBoxContent);\r
-\r
-               loginBoxLi.append(loginBox);\r
-               $(containerSelector).append(loginBoxLi);\r
-       }\r
-\r
-       // Panel of login box to display when the user is logged in\r
-       var displayLogout = function(origin, user) {\r
-               var panel = $(document.createElement("div"))\r
-               .append(\r
-                       $(document.createElement("h3"))\r
-                       .append("Signed in Github")\r
-               )\r
-               .append(\r
-                       $(document.createElement("h4"))\r
-                       .append("Hello ")\r
-                       .append(\r
-                               $(document.createElement("a"))\r
-                               .attr("href", "https://github.com/" + user.login)\r
-                               .append(user.login)\r
-                       ).append("!")\r
-               )\r
-               .append(\r
-                       $(document.createElement("label"))\r
-                       .attr("for", "github-origin")\r
-                       .append("Upstram branch")\r
-               )\r
-               .append(\r
-                       $(document.createElement("a"))\r
-                       .addClass("nitdoc-github-loginbox-githublink")\r
-                       .attr({\r
-                               title: "Open branch in GitHub",\r
-                               href: "https://github.com/" + origin.user + "/" + origin.repo + "/tree/" + origin.branch,\r
-                               target: "_blank"\r
-                       })\r
-                       .append(origin.user + ":" + origin.repo + ":" + origin.branch)\r
-               )\r
-               .append(\r
-                       $(document.createElement("label"))\r
-                       .attr("for", "github-base")\r
-                       .append("Your branch")\r
-               )\r
-               .append(\r
-                       $(document.createElement("a"))\r
-                       .addClass("nitdoc-github-loginbox-githublink")\r
-                       .attr({\r
-                               title: "Open branch in GitHub",\r
-                               href: "https://github.com/" + user.login + "/" + user.repo + "/tree/" + user.branch,\r
-                               target: "_blank"\r
-                       })\r
-                       .append(origin.user + ":" + origin.repo + ":" + origin.branch)\r
-               )\r
-               .append(\r
-                       $(document.createElement("button"))\r
-                       .addClass("nitdoc-github-button")\r
-                       .addClass("nitdoc-github-cancel")\r
-                       .append(\r
-                               $(document.createElement("img"))\r
-                               .attr("src", "resources/icons/github-icon.png")\r
-                       ).append("Sign Off")\r
-                       .click(function() { // log out user\r
-                               Nitdoc.GitHub.UI.disactivate();\r
-                               Nitdoc.GitHub.LoginBox.toggle();\r
-                       })\r
-               );\r
-               $(".nitdoc-github-li-img").attr("src", "resources/icons/github-icon-green.png");\r
-               loginBoxContent.empty()\r
-               loginBoxContent.append(panel);\r
-       }\r
-\r
-       // Panel of login box to display when the user is logged out\r
-       var displayLogin = function() {\r
-               var panel = $(document.createElement("form"))\r
-               .append(\r
-                       $(document.createElement("h3"))\r
-                       .append("Sign in Github")\r
-               )\r
-               .append(\r
-                       $(document.createElement("label"))\r
-                       .attr("for", "nitdoc-github-login-field")\r
-                       .append("Username")\r
-               )\r
-               .append(\r
-                       $(document.createElement("input"))\r
-                       .attr({\r
-                               id: "nitdoc-github-login-field",\r
-                               type: "text"\r
-                       })\r
-               )\r
-               .append(\r
-                       $(document.createElement("label"))\r
-                       .attr("for", "nitdoc-github-password-field")\r
-                       .append("Password")\r
-               )\r
-               .append(\r
-                       $(document.createElement("input"))\r
-                       .attr({\r
-                               id: "nitdoc-github-password-field",\r
-                               type: "password"\r
-                       })\r
-               )\r
-               .append(\r
-                       $(document.createElement("label"))\r
-                       .attr("for", "nitdoc-github-repo-field")\r
-                       .append("Repository")\r
-               )\r
-               .append(\r
-                       $(document.createElement("input"))\r
-                       .attr({\r
-                               id: "nitdoc-github-repo-field",\r
-                               type: "text"\r
-                       })\r
-               )\r
-               .append(\r
-                       $(document.createElement("label"))\r
-                       .attr("for", "nitdoc-github-branch-field")\r
-                       .append("Branch")\r
-               )\r
-               .append(\r
-                       $(document.createElement("input"))\r
-                       .attr({\r
-                               id: "nitdoc-github-branch-field",\r
-                               type: "text"\r
-                       })\r
-               )\r
-               .append(\r
-                       $(document.createElement("button"))\r
-                       .addClass("nitdoc-github-button")\r
-                       .append(\r
-                               $(document.createElement("img"))\r
-                               .attr("src", "resources/icons/github-icon.png")\r
-                       ).append("Sign In")\r
-                       .click(function() {\r
-                               var login = $('#nitdoc-github-login-field').val();\r
-                               var password = $('#nitdoc-github-password-field').val();\r
-                               var repo = $('#nitdoc-github-repo-field').val();\r
-                               var branch = $('#nitdoc-github-branch-field').val();\r
-                               if(!login || !password || !repo || !branch) {\r
-                                       Nitdoc.GitHub.ModalBox.open("Sign in error", "Please enter your GitHub username, password, repository and branch.", true);\r
-                               } else {\r
-                                       var user = Nitdoc.GitHub.UI.tryLogin(login, password, repo, branch);\r
-                                       if(user == "error:login") {\r
-                                               Nitdoc.GitHub.ModalBox.open("Sign in error", "The username, password, repo or branch you entered is incorrect.", true);\r
-                                       } else if(user == "error:sha") {\r
-                                               Nitdoc.GitHub.ModalBox.open("Base commit not found", "The provided GitHub repository must contains the base commit '" + Nitdoc.GitHub.UI.getOrigin().sha + "'", true);\r
-                                       } else if(user == "error:profile") {\r
-                                               Nitdoc.GitHub.ModalBox.open("Incomplete GitHub profile", "Please set your public name and email in your <a href='https://github.com/settings/profile'>GitHub profile</a>.<br/><br/>Your public profile informations are used to sign-off your commits.", true);\r
-                                       } else {\r
-                                               Nitdoc.GitHub.UI.activate(user);\r
-                                               var origin = Nitdoc.GitHub.UI.getOrigin();\r
-                                               Nitdoc.GitHub.LoginBox.displayLogout(origin, user);\r
-                                       }\r
-                               }\r
-                               return false;\r
-                       })\r
-               )\r
-               $(".nitdoc-github-li-img").attr("src", "resources/icons/github-icon.png");\r
-               loginBoxContent.empty()\r
-               loginBoxContent.append(panel);\r
-       }\r
-\r
-       var toggle = function() {\r
-               if(loginBox.is(':hidden')) {\r
-                       loginBox.show();\r
-                       if (!$('#loginGit').is(':hidden')) { $('#loginGit').focus(); }\r
-               } else {\r
-                       loginBox.hide();\r
-               }\r
-       }\r
-\r
-       // Public interface\r
-       var loginbox = {\r
-               init: init,\r
-               displayLogin: displayLogin,\r
-               displayLogout: displayLogout,\r
-               toggle: toggle,\r
-               \r
-       };\r
-\r
-       return loginbox;\r
-}();\r
-\r
-/*\r
- * Nitdoc.GitHub.CommentBox class\r
- */\r
-\r
-// Init new modal box instance\r
-Nitdoc.GitHub.CommentBox = function(infos) {\r
-       this.infos = infos;\r
-       this.commentBoxDiv;\r
-}\r
-\r
-Nitdoc.GitHub.CommentBox.prototype.open = function(baseArea) {\r
-       Nitdoc.GitHub.UI.addOpenedComments();\r
-       var instance = this;\r
-\r
-       if(this.infos.requestID) {\r
-               // get comment from last pull request\r
-               var requests = JSON.parse(localStorage.requests);\r
-               this.infos.newComment = Base64.decode(requests[this.infos.requestID].comment);\r
-       } else {\r
-               this.infos.newComment = false;\r
-       }\r
-\r
-       // create comment box\r
-       var tarea = $(document.createElement("textarea"))\r
-       .append(this.infos.newComment === false? this.infos.oldComment: this.infos.newComment)\r
-       .keyup(function(event) {\r
-               $(event.target).css("height", (event.target.value.split(/\r|\n/).length * 16) + "px");\r
-               if ( (!instance.infos.requestID && $(event.target).val() != instance.infos.oldComment) || (instance.infos.requestID && $(event.target).val() != instance.infos.oldComment && $(event.target).val() != instance.infos.newComment) ) {\r
-                       $(event.target).parent().find("button.nitdoc-github-commit").removeAttr("disabled");\r
-               } else {\r
-                       $(event.target).parent().find("button.nitdoc-github-commit").attr("disabled", "disabled");\r
-               }\r
-       })\r
-       .keydown(function(event) {\r
-               if(event.keyCode == 13){\r
-                       $(event.target).css("height", ($(event.target).outerHeight() + 6) + "px");\r
-               }\r
-       });\r
-\r
-       this.commentBoxDiv = $(document.createElement("div"))\r
-       .addClass("nitdoc-github-commentbox")\r
-       .append(tarea)\r
-       .append(\r
-               $(document.createElement("a"))\r
-               .addClass("nitdoc-github-preview")\r
-               .click(function() {\r
-                       var converter = new Markdown.Converter()\r
-                       var html = converter.makeHtml(tarea.val());\r
-                       Nitdoc.GitHub.ModalBox.open("Preview", html, false);\r
-               })\r
-       )\r
-       .append(\r
-               $(document.createElement("button"))\r
-               .addClass("nitdoc-github-button")\r
-               .addClass("nitdoc-github-commit")\r
-               .append("Commit...")\r
-               .click(function() {\r
-                       instance.infos.newComment = tarea.val();\r
-                       instance.infos.commentBox = instance;\r
-                       Nitdoc.GitHub.CommitBox.open(instance.infos);\r
-               })\r
-       )\r
-       .append(\r
-               $(document.createElement("button"))\r
-               .addClass("nitdoc-github-button")\r
-               .addClass("nitdoc-github-cancel")\r
-               .append("Cancel")\r
-               .click(function() {instance.close()})\r
-       );\r
-\r
-       baseArea.after(this.commentBoxDiv);\r
-       var cbWidth = this.commentBoxDiv.innerWidth();\r
-       var taWidth = tarea.outerWidth();\r
-       tarea.width(cbWidth - (taWidth - cbWidth));\r
-       tarea.trigger("keyup");\r
-       tarea.focus();\r
-}\r
-\r
-Nitdoc.GitHub.CommentBox.prototype.close = function() {\r
-       Nitdoc.GitHub.UI.remOpenedComments();\r
-       if(this.infos.isNew) {\r
-               this.commentBoxDiv.next().find("span.nitdoc-github-editComment").show();\r
-       } else if(this.infos.requestID) {\r
-               this.commentBoxDiv.next().show();\r
-               this.commentBoxDiv.next().next().show();\r
-       } else {\r
-               this.commentBoxDiv.next().show();\r
-               this.commentBoxDiv.next().next().find("span.nitdoc-github-editComment").show();\r
-       }\r
-       this.commentBoxDiv.remove();\r
-}\r
-\r
-/*\r
- * Nitdoc.GitHub.ModalBox class\r
- */\r
-\r
-// Init new modal box instance\r
-Nitdoc.GitHub.ModalBox = function() {\r
-\r
-       // Open modal box instance\r
-       var open = function(title, content, isError) {\r
-               $("body").append(\r
-                       $(document.createElement("div"))\r
-                       .attr("id", "nitdoc-github-modal-fade")\r
-                       .addClass("nitdoc-github-fade")\r
-               )\r
-               .append(\r
-                       $(document.createElement("div"))\r
-                       .attr("id", "nitdoc-github-modal")\r
-                       .addClass("nitdoc-github-modal")\r
-                       .append(\r
-                               $(document.createElement("a"))\r
-                               .addClass("nitdoc-github-close")\r
-                               .attr("title", "Close")\r
-                               .append("x")\r
-                               .click(function() { Nitdoc.GitHub.ModalBox.close() })\r
-                       )\r
-                       .append("<h3>" + title + "</h3>")\r
-                       .append("<div>" + content + "</div>")\r
-                       .append(\r
-                               $(document.createElement("div"))\r
-                               .addClass("nitdoc-github-buttons")\r
-                               .append(\r
-                                       $(document.createElement("button"))\r
-                                       .addClass("nitdoc-github-button")\r
-                                       .append("Ok")\r
-                                       .click(function() { Nitdoc.GitHub.ModalBox.close() })\r
-                               )\r
-                       )\r
-               );\r
-\r
-               if(isError) {\r
-                       $("#nitdoc-github-modal").addClass("nitdoc-github-error");\r
-               }\r
-\r
-               $("#nitdoc-github-modal")\r
-               .css({\r
-                       top: "50%",\r
-                       marginTop: -($("#nitdoc-github-modal").outerHeight() / 2) + "px",\r
-                       left: "50%",\r
-                       marginLeft: -($("#nitdoc-github-modal").outerWidth() / 2) + "px"\r
-               })\r
-               .find("button.nitdoc-github-button").focus();\r
-       }\r
-\r
-       // Close modal box instance\r
-       var close = function() {\r
-               $("#nitdoc-github-modal").remove();\r
-               $("#nitdoc-github-modal-fade").remove();\r
-       }\r
-\r
-       // Public interface\r
-       var modalBox = {\r
-               open: open,\r
-               close: close\r
-       };\r
-\r
-       return modalBox;\r
-}();\r
-\r
-/*\r
- * Nitdoc.GitHub.CommitBox instance\r
- */\r
-\r
-// Init new commit box instance\r
-Nitdoc.GitHub.CommitBox = function() {\r
-\r
-       // Open commit box instance\r
-       var open = function(infos) {\r
-               $("body").append(\r
-                       $(document.createElement("div"))\r
-                       .attr("id", "nitdoc-github-commitBox-fade")\r
-                       .addClass("nitdoc-github-fade")\r
-               );\r
-               $("body").append(\r
-                       $(document.createElement("div"))\r
-                       .attr("id", "nitdoc-github-commitBox")\r
-                       .addClass("nitdoc-github-modal")\r
-                       .append(\r
-                               $(document.createElement("a"))\r
-                               .addClass("nitdoc-github-close")\r
-                               .attr("title", "Close")\r
-                               .append("x")\r
-                               .click(function() { Nitdoc.GitHub.CommitBox.close() })\r
-                       )\r
-                       .append("<h3>Commit changes</h3>")\r
-                       .append(\r
-                               $(document.createElement("div"))\r
-                               .append(\r
-                                       $(document.createElement("label"))\r
-                                       .attr("for", "nitdoc-github-commit-message")\r
-                               )\r
-                               .append("<br/>")\r
-                               .append(\r
-                                       $(document.createElement("textarea"))\r
-                                       .attr("id", "nitdoc-github-commit-message")\r
-                                       .append("doc: " + (infos.isNew ? "added" : "modified") + " comment for " + infos.namespace)\r
-                               )\r
-                               .append("<br/>")\r
-                               .append(\r
-                                       $(document.createElement("input"))\r
-                                       .attr({\r
-                                               id: "nitdoc-github-commit-signedoff",\r
-                                               type: "checkbox",\r
-                                               value: "Signed-off-by: " + infos.user.signedOff\r
-                                       })\r
-                                       .change(function(e) {\r
-                                               if ($(this).is(':checked')) {\r
-                                                       $("#nitdoc-github-commit-button").removeAttr("disabled");\r
-                                               } else {\r
-                                                       $("#nitdoc-github-commit-button").attr("disabled", "disabled");\r
-                                               }\r
-                                       })\r
-                               )\r
-                               .append(\r
-                                       $(document.createElement("label"))\r
-                                       .attr("for", "nitdoc-github-commit-signedoff")\r
-                                       .text("Signed-off-by: " + infos.user.signedOff)\r
-                               )\r
-                       ).append(\r
-                               $(document.createElement("div"))\r
-                               .addClass("nitdoc-github-buttons")\r
-                               .append(\r
-                                       $(document.createElement("button"))\r
-                                       .attr({\r
-                                               id: "nitdoc-github-commit-button",\r
-                                               disabled: "disabled"\r
-                                       })\r
-                                       .addClass("nitdoc-github-button")\r
-                                       .append(\r
-                                               $(document.createElement("img"))\r
-                                               .attr("src", "resources/icons/github-icon.png")\r
-                                       )\r
-                                       .append("Commit")\r
-                                       .mousedown(function() {\r
-                                               $(this).text("Commiting...");\r
-                                       })\r
-                                       .mouseup(function() {\r
-                                               infos.message = $("#nitdoc-github-commit-message").val() + "\n\n" + infos.user.signedOff;\r
-                                               Nitdoc.GitHub.UI.saveChanges(infos);\r
-                                       })\r
-                               )\r
-                       )\r
-               );\r
-\r
-               $("#nitdoc-github-commitBox")\r
-               .css({\r
-                       top: "50%",\r
-                       marginTop: -($("#nitdoc-github-commitBox").outerHeight() / 2) + "px",\r
-                       left: "50%",\r
-                       marginLeft: -($("#nitdoc-github-commitBox").outerWidth() / 2) + "px"\r
-               })\r
-               .find("#nitdoc-github-commit-message").focus();\r
-       }\r
-\r
-       // Close commit box instance\r
-       var close = function() {\r
-               $("#nitdoc-github-commitBox").remove();\r
-               $("#nitdoc-github-commitBox-fade").remove();\r
-       }\r
-\r
-       // Public interface\r
-       var commitBox = {\r
-               open: open,\r
-               close: close\r
-       }\r
-       return commitBox;\r
-}();\r
-\r
-/*\r
- * Nitdoc.GitHub.Utils module\r
- */\r
-\r
-Nitdoc.GitHub.Utils = function() {\r
-       // Extract infos from string location "lib/standard/collection/array.nit:457,1--458,0"\r
-       var parseLocation = function(location) {\r
-               var parts = location.split(":");\r
-               var loc = new Object();\r
-               loc.origin = location;\r
-               loc.path = parts[0];\r
-               loc.lstart = parseInt(parts[1].split("--")[0].split(",")[0]);\r
-               loc.tabpos = parseInt(parts[1].split("--")[0].split(",")[1]);\r
-               loc.lend = parseInt(parts[1].split("--")[1].split(",")[0]);\r
-               return loc;\r
-       }\r
-\r
-       // Meld modified comment into file conten\r
-       var mergeComment = function(fileContent, comment, location) {\r
-               // replace comment in file content\r
-               var res = new String();\r
-               var lines = fileContent.split("\n");\r
-               // copy lines fron 0 to lstart\r
-               for(var i = 0; i < location.lstart - 1; i++) {\r
-                       res += lines[i] + "\n";\r
-               }\r
-               // set comment\r
-               if(comment && comment != "") {\r
-                       var commentLines = comment.split("\n");\r
-                       for(var i = 0; i < commentLines.length; i++) {\r
-                               var line = commentLines[i];\r
-                               var tab = location.tabpos > 1 ? "\t" : "";\r
-                               res += tab + (line.length > 0 ? "# " : "#") + line + "\n";\r
-                       }\r
-               }\r
-               // copy lines fron lend to end\r
-               for(var i = location.lend - 1; i < lines.length; i++) {\r
-                       res += lines[i];\r
-                       if(i < lines.length - 1) { res += "\n"; }\r
-               }\r
-               return res;\r
-       }\r
-\r
-       // Public interface\r
-       var utils = {\r
-               parseLocation: parseLocation,\r
-               mergeComment: mergeComment\r
-       };\r
-\r
-       return utils;\r
-}();\r
-\r
diff --git a/share/nitdoc/scripts/Nitdoc.QuickSearch.js b/share/nitdoc/scripts/Nitdoc.QuickSearch.js
deleted file mode 100644 (file)
index 20dcf60..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-   Documentation generator for the nit language.
-   Generate API documentation in HTML format from nit source code.
-*/
-
-var Nitdoc = Nitdoc || {};
-
-/*
- * Nitdoc QuickSearch module
- *
- */
-
-Nitdoc.QuickSearch = function() {
-       var rawList = nitdocQuickSearchRawList; // List of raw resulsts generated by nitdoc tool
-       var searchField = null; // <input:text> search field
-       var currentTable = null; // current search results <table>
-       var currentIndex = -1; // current cursor position into search results table
-
-       // Enable QuickSearch plugin
-       var enableQuickSearch = function(containerSelector) {
-               searchField = $(document.createElement("input"))
-               .attr({
-                       id: "nitdoc-qs-field",
-                       type: "text",
-                       autocomplete: "off",
-                       value: "quick search..."
-               })
-               .addClass("nitdoc-qs-field-notused")
-               .keydown(function(event) {
-                       return Nitdoc.QuickSearch.doKeyDownAction(event.keyCode);
-               })
-               .keyup(function(event) {
-                       Nitdoc.QuickSearch.doKeyUpAction(event.keyCode);
-               })
-               .focusout(function() {
-                       if($(this).val() == "") {
-                               $(this).addClass("nitdoc-qs-field-notused");
-                               $(this).val("quick search...");
-                       }
-               })
-               .focusin(function() {
-                       if($(this).val() == "quick search...") {
-                               $(this).removeClass("nitdoc-qs-field-notused");
-                               $(this).val("");
-                       }
-               });
-
-               $(containerSelector).append(
-                       $(document.createElement("li"))
-                       .attr("id", "nitdoc-qs-li")
-                       .append(searchField)
-               );
-
-               // Close quicksearch list on click
-               $(document).click(function(e) {
-                       Nitdoc.QuickSearch.closeResultsTable();
-               });
-       }
-
-       var doKeyDownAction = function(key) {
-               switch(key) {
-                       case 38: // Up
-                               selectPrevResult();
-                               return false;
-                       case 40: // Down
-                               selectNextResult();
-                               return false;
-                       default:
-                               return true;
-                }
-       }
-
-       var doKeyUpAction = function(key) {
-               switch(key) {
-                       case 38: // Up
-                       case 40: // Down
-                       break;
-
-                       case 13: // Enter
-                               goToResult();
-                               return false;
-                       break;
-
-                       case 27: // Escape
-                               $(this).blur();
-                               closeResultsTable();
-                       break;
-
-                       default: // Other keys
-                               var query = searchField.val();
-                               if(!query) {
-                                       return false;
-                               }
-                               var results = getResults(query);
-                               displayResultsTable(query, results);
-                       break;
-               }
-       }
-
-       // Get results corresponding to search query
-       var getResults = function(query) {
-               var results = {};
-               results.matches = new Array();
-               for(var entry in rawList) {
-                       if(!entry.startsWith(query, true)) {
-                               continue;
-                       }
-                       var cat = new Object();
-                       cat.name = entry;
-                       cat.entries = rawList[entry];
-                       results.matches[results.matches.length] = cat;
-
-                       if(entry == query) {
-                               cat.rank = 3;
-                       } else if(entry.toUpperCase() == query.toUpperCase()) {
-                               cat.rank = 2;
-                       } else {
-                               cat.rank = 1 + query.dice(entry);
-                       }
-               }
-               results.matches.sort(rankSorter);
-               results.partials = new Array();
-               if(results.matches.length == 0) {
-                       for(var entry in rawList) {
-                               var cat = new Object();
-                               cat.name = entry;
-                               cat.entries = rawList[entry];
-                               cat.rank = query.dice(entry);
-                               if(cat.rank > 0) {
-                                       results.partials[results.partials.length] = cat;
-                               }
-                       }
-                       results.partials.sort(rankSorter);
-               }
-               return results;
-       }
-
-       // Sort an array of results by rank
-       var rankSorter = function(a, b){
-               if(a.rank < b.rank) {
-                       return 1;
-               } else if(a.rank > b.rank) {
-                       return -1;
-               }
-               return 0;
-       }
-
-       // Display results in a popup table
-       var displayResultsTable = function(query, results) {
-               // Clear results table
-               if(currentTable) currentTable.remove();
-
-               // Build results table
-               currentIndex = -1;
-               currentTable = $(document.createElement("table"));
-               currentTable.attr("id", "nitdoc-qs-table");
-               currentTable.css("position", "absolute");
-               currentTable.width(searchField.outerWidth());
-
-               var maxSize = 10;
-               var count = 0;
-               var resultSet;
-               if(results.matches.length == 0) {
-                       resultSet = results.partials
-               } else {
-                       resultSet = results.matches
-               }
-               for(var i in resultSet) {
-                       var cat = resultSet[i];
-                       var result = cat.entries[0];
-
-                       addResultRow(count, cat.name, result.txt, result.url, "nitdoc-qs-cat")
-                       if(count >= maxSize) {
-                               currentTable.find("tbody").children().last().hide();
-                       }
-                       count++;
-
-                       for(var j = 1; j < cat.entries.length; j++) {
-                               var result = cat.entries[j];
-                               addResultRow(count, cat.name, result.txt, result.url, "nitdoc-qs-sub")
-                               if(count >= maxSize) {
-                                       currentTable.find("tr.nitdoc-qs-row").last().hide();
-                               }
-                               count++;
-                       }
-               }
-               if(count >= maxSize) {
-                       currentTable.prepend(
-                               $(document.createElement("tr"))
-                               .addClass("nitdoc-qs-overflow-up")
-                               .addClass("nitdoc-qs-overflow-inactive")
-                               .append(
-                                       $(document.createElement("td"))
-                                       .attr("colspan", 2)
-                                       .html("&#x25B2;")
-                               )
-                               .click( function(e) {
-                                       e.stopPropagation();
-                                       selectPrevResult();
-                               })
-                       );
-                       currentTable.append(
-                               $(document.createElement("tr"))
-                               .addClass("nitdoc-qs-overflow-down")
-                               .addClass(count >= maxSize ? "nitdoc-qs-overflow-active" : "nitdoc-qs-overflow-inactive")
-                               .append(
-                                       $(document.createElement("td"))
-                                       .attr("colspan", 2)
-                                       .html("&#x25BC;")
-                               )
-                               .click( function(e) {
-                                       e.stopPropagation();
-                                       console.log("nest");
-                                       selectNextResult();
-                               })
-                       );
-               }
-               if(results.matches.length == 0) {
-                       currentTable.prepend(
-                               $("<tr class='nitdoc-qs-noresult'>")
-                               .append(
-                                       $("<td colspan='2'>")
-                                       .html("Sorry, there is no match, best results are:")
-                               )
-                       );
-               }
-
-               // Initialize table
-               $("body").append(currentTable);
-               resizeResultsTable();
-               if(currentTable.find("tr").length > 0) {
-                       setIndex(0);
-               }
-       }
-
-       // adds a result row to the current result table
-       var addResultRow = function(index, name, txt, url, cls) {
-               currentTable.append(
-                       $(document.createElement("tr"))
-                       .addClass("nitdoc-qs-row")
-                       .data("searchDetails", {name: name, url: url})
-                       .data("index", index)
-                       .append(
-                               $(document.createElement("td")).html(name)
-                               .addClass(cls)
-                       )
-                       .append(
-                               $(document.createElement("td"))
-                                       .addClass("nitdoc-qs-info")
-                                       .html(txt + "&nbsp;&raquo;")
-                       )
-                       .mouseover( function() {
-                               setIndex($(this).data("index"));
-                       })
-                       .mouseout( function() {
-                               $(this).removeClass("nitdoc-qs-active");
-                        })
-                       .click( function() {
-                               window.location = $(this).data("searchDetails")["url"];
-                       })
-               );
-       }
-
-       // adapts result table to content
-       var resizeResultsTable = function() {
-               currentTable.offset({
-                       left: searchField.offset().left + (searchField.outerWidth() - currentTable.outerWidth()),
-                       top: searchField.offset().top + searchField.outerHeight()
-               });
-       }
-
-       // select row at index
-       var setIndex = function(index) {
-               $(currentTable.find("tr.nitdoc-qs-row")[currentIndex]).removeClass("nitdoc-qs-active");
-               currentIndex = index;
-               var currentRow = $(currentTable.find("tr.nitdoc-qs-row")[currentIndex]);
-               currentRow.addClass("nitdoc-qs-active");
-               //searchField.val(currentRow.data("searchDetails").name);
-       }
-
-       var hasPrev = function(index) {
-               return index - 1 >= 0;
-       }
-
-       var hasNext = function(index) {
-               return index + 1 < currentTable.find("tr.nitdoc-qs-row").length;
-       }
-
-       var selectPrevResult = function() {
-               if(hasPrev(currentIndex)) {
-                       setIndex(currentIndex - 1);
-                       if(!$(currentTable.find("tr.nitdoc-qs-row")[currentIndex]).is(":visible")) {
-                               currentTable.find("tr.nitdoc-qs-row:visible").last().hide();
-                               currentTable.find("tr.nitdoc-qs-overflow-down").addClass("nitdoc-qs-overflow-active");
-                               $(currentTable.find("tr.nitdoc-qs-row")[currentIndex]).show();
-                               if(!hasPrev(currentIndex)) {
-                                       currentTable.find("tr.nitdoc-qs-overflow-up").removeClass("nitdoc-qs-overflow-active");
-                               }
-                               resizeResultsTable();
-                       }
-               }
-       }
-
-       var selectNextResult = function() {
-               if(hasNext(currentIndex)) {
-                       setIndex(currentIndex + 1);
-                       if(!$(currentTable.find("tr.nitdoc-qs-row")[currentIndex]).is(":visible")) {
-                               currentTable.find("tr.nitdoc-qs-row:visible").first().hide();
-                               currentTable.find("tr.nitdoc-qs-overflow-up").addClass("nitdoc-qs-overflow-active");
-                               $(currentTable.find("tr.nitdoc-qs-row")[currentIndex]).show();
-                               if(!hasNext(currentIndex)) {
-                                       currentTable.find("tr.nitdoc-qs-overflow-down").removeClass("nitdoc-qs-overflow-active");
-                               }
-                               resizeResultsTable();
-                       }
-               }
-       }
-
-       // Load selected search result page
-       var goToResult = function() {
-               if(currentIndex > -1) {
-                       window.location = $(currentTable.find("tr.nitdoc-qs-row")[currentIndex]).data("searchDetails").url;
-                       return;
-               }
-
-               if(searchField.val().length == 0) { return; }
-
-               window.location = "search.html#q=" + searchField.val();
-               if(window.location.href.indexOf("search.html") > -1) {
-                       location.reload();
-               }
-       }
-
-       // Close the results table
-       closeResultsTable = function(target) {
-               if(target != searchField && target != currentTable) {
-                       if(currentTable != null) {
-                               currentTable.remove();
-                               currentTable = null;
-                       }
-               }
-       }
-
-       // Public interface
-       var quicksearch = {
-               enableQuickSearch: enableQuickSearch,
-               doKeyUpAction: doKeyUpAction,
-               doKeyDownAction: doKeyDownAction,
-               closeResultsTable: closeResultsTable
-       };
-
-       return quicksearch;
-}();
-
-$(document).ready(function() {
-       Nitdoc.QuickSearch.enableQuickSearch("nav.main ul");
-});
-
-/*
- * Utils
- */
-
-String.prototype.startsWith = function(prefix, caseSensitive) {
-       if(caseSensitive) {
-               return this.toUpperCase().indexOf(prefix.toUpperCase()) === 0;
-       }
-    return this.indexOf(prefix) === 0;
-}
-
-// Compare two strings using Sorensen-Dice Coefficient
-// see: http://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient
-String.prototype.dice = function(other) {
-       var length1 = this.length - 1;
-       var length2 = other.length - 1;
-       if(length1 < 1 || length2 < 1) return 0;
-
-       var bigrams2 = [];
-       for(var i = 0; i < length2; i++) {
-               bigrams2.push(other.substr(i, 2));
-       }
-
-       var intersection = 0;
-       for(var i = 0; i < length1; i++) {
-               var bigram1 = this.substr(i, 2);
-               for(var j = 0; j < length2; j++) {
-                       if(bigram1 == bigrams2[j]) {
-                               intersection++;
-                               bigrams2[j] = null;
-                               break;
-                       }
-               }
-       }
-       return (2.0 * intersection) / (length1 + length2);
-}
-
diff --git a/share/nitdoc/scripts/Nitdoc.UI.js b/share/nitdoc/scripts/Nitdoc.UI.js
deleted file mode 100644 (file)
index 5b8d004..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
-   Licensed under the Apache License, Version 2.0 (the "License");\r
-   you may not use this file except in compliance with the License.\r
-   You may obtain a copy of the License at\r
-\r
-   http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-\r
-   Documentation generator for the nit language.\r
-   Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-var Nitdoc = Nitdoc || {};\r
-\r
-/*\r
- * Nitdoc UI module\r
- *\r
- * Enhance nitdoc usability with JS features\r
- */\r
-\r
-Nitdoc.UI = function() {\r
-\r
-       // Allow user to fold sidebar nav elements on click\r
-       var enableFolding = function(containerSelector) {\r
-               var container = $(containerSelector);\r
-               var foldLink = $(document.createElement("a"))\r
-               .addClass("nitdoc-ui-fold")\r
-               .html("-");\r
-\r
-               container.find("nav h3")\r
-               .prepend(foldLink)\r
-               .css("cursor", "pointer")\r
-               .toggle(\r
-                       function() {\r
-                               $(this).find("a.nitdoc-ui-fold").html("+");\r
-                               $(this).nextAll().toggle();\r
-                       },\r
-                       function() {\r
-                               $(this).find("a.nitdoc-ui-fold").html("-");\r
-                               $(this).nextAll().toggle();\r
-                       }\r
-               );\r
-       }\r
-\r
-       // Allow user to copy signatures to clipboard with ZeroClipboard flahs plugin\r
-       // See: https://github.com/zeroclipboard/ZeroClipboard\r
-       var enableCopyToClipboard = function(copySelector) {\r
-               $(copySelector).each(function() {\r
-                       var btn = $(document.createElement("button"))\r
-                       .addClass("nitdoc-ui-copy")\r
-                       .attr("data-clipboard-text", $(this).attr("data-untyped-signature"))\r
-                       .append(\r
-                               $(document.createElement("img"))\r
-                               .attr("src", './resources/icons/copy.png')\r
-                       );\r
-                       $(this).append(btn);\r
-               });\r
-\r
-               var clip = new ZeroClipboard($("button.nitdoc-ui-copy"), {\r
-                       moviePath: "./ZeroClipboard.swf"\r
-               });\r
-       }\r
-\r
-       // Allow user to filter sidebar box entries by name\r
-       var enableSidebarTextFilters = function(filterSelector) {\r
-               var div = $(document.createElement("div"))\r
-               .addClass("nitdoc-ui-filter")\r
-               .append(\r
-                       $(document.createElement("input"))\r
-                       .addClass("nitdoc-ui-filter-field")\r
-                       .addClass("nitdoc-ui-filter-field-notused")\r
-                       .attr("type", "text")\r
-                       .attr("value",  "filter...")\r
-                       .keyup(function() {\r
-                               var box = $(this).parents("nav.filterable");\r
-                               var value = $(this).val();\r
-                               box.find("ul li:not(:icontains('" + value + "'))").hide();\r
-                               box.find("ul li:icontains('" + value + "')").show();\r
-                       })\r
-                       .focusout(function() {\r
-                               if($(this).val() == "") {\r
-                                       $(this).addClass("nitdoc-ui-filter-field-notused");\r
-                                       $(this).val("filter...");\r
-                               }\r
-                       })\r
-                       .focusin(function() {\r
-                               if($(this).val() == "filter...") {\r
-                                       $(this).removeClass("nitdoc-ui-filter-field-notused");\r
-                                       $(this).val("");\r
-                               }\r
-                       })\r
-               );\r
-               $(filterSelector).after(div);\r
-               preloadSidebarTextFilters();\r
-       }\r
-\r
-       // Prealod filters using search query\r
-       var preloadSidebarTextFilters = function() {\r
-               var anchor = Nitdoc.Utils.extractAnchor(document.location.hash);\r
-               if(!anchor || anchor.indexOf("q=") == -1) return;\r
-\r
-               var query = anchor.substring(2);\r
-               if(!query) return;\r
-\r
-               $(".nitdoc-ui-filter input:text")\r
-               .val(query)\r
-               .removeClass("nitdoc-ui-notused")\r
-               .trigger("keyup");\r
-       }\r
-\r
-       // Allow user to filter side bar box entries by Introduced/Refined/inHerited type\r
-       var enableSidebarTypeFilters = function(filterSelector) {\r
-               var box = $(filterSelector);\r
-               var types = {};\r
-\r
-               box.find("li").each(function() {\r
-                       var span = $(this).find("span:first");\r
-                       if(!types[span.html()]) types[span.html()] = {\r
-                               title: span.attr("title"),\r
-                               class: $(this).attr("class")\r
-                       }\r
-               });\r
-\r
-               for(var type in types) {\r
-                       var a = $(document.createElement("a"))\r
-                       .addClass("nitdoc-ui-filter-link")\r
-                       .html(type)\r
-                       .attr("title", "Hide " + types[type].title)\r
-                       .attr("data-filter-class", types[type].class)\r
-                       .toggle(\r
-                               function() {\r
-                                       var hclass = $(this).attr("data-filter-class");\r
-                                       $(this).parents(filterSelector).find("li." + hclass).hide();\r
-                                       $(this).addClass("nitdoc-ui-filter-hidden")\r
-                               },\r
-                               function() {\r
-                                       var hclass = $(this).attr("data-filter-class");\r
-                                       $(this).parents(filterSelector).find("li." + hclass).show();\r
-                                       $(this).removeClass("nitdoc-ui-filter-hidden")\r
-                               }\r
-                       )\r
-                       $(filterSelector).find(".nitdoc-ui-filter").append(a);\r
-               }\r
-       }\r
-\r
-       // Allow user to filter sidebar box entries by name\r
-       var enableSearchPageField = function(filterSelector) {\r
-               var div = $(document.createElement("div"))\r
-               .addClass("nitdoc-ui-searchpage-filter")\r
-               .append(\r
-                       $(document.createElement("input"))\r
-                       .addClass("nitdoc-ui-searchpage-field")\r
-                       .addClass("nitdoc-ui-filter-field-notused")\r
-                       .attr("type", "text")\r
-                       .attr("value",  "filter...")\r
-                       .keyup(function() {\r
-                               var box = $(this).parents(".content.fullpage").find("article.filterable");\r
-                               var value = $(this).val();\r
-                               box.find("ul li:not(:icontains('" + value + "'))").hide();\r
-                               box.find("ul li:icontains('" + value + "')").show();\r
-                       })\r
-                       .focusout(function() {\r
-                               if($(this).val() == "") {\r
-                                       $(this).addClass("nitdoc-ui-filter-field-notused");\r
-                                       $(this).val("filter...");\r
-                               }\r
-                       })\r
-                       .focusin(function() {\r
-                               if($(this).val() == "filter...") {\r
-                                       $(this).removeClass("nitdoc-ui-filter-field-notused");\r
-                                       $(this).val("");\r
-                               }\r
-                       })\r
-               );\r
-               $(filterSelector).after(div);\r
-               preloadSearchPageField();\r
-       }\r
-\r
-       // Prealod filter using search query\r
-       var preloadSearchPageField = function() {\r
-               var anchor = Nitdoc.Utils.extractAnchor(document.location.hash);\r
-               if(!anchor || anchor.indexOf("q=") == -1) return;\r
-\r
-               var query = anchor.substring(2);\r
-               if(!query) return;\r
-\r
-               $(".nitdoc-ui-searchpage-field")\r
-               .val(query)\r
-               .removeClass("nitdoc-ui-notused")\r
-               .trigger("keyup");\r
-       }\r
-\r
-       // Public interface\r
-       var ui = {\r
-               enableFolding: enableFolding,\r
-               enableCopyToClipboard: enableCopyToClipboard,\r
-               enableSidebarTextFilters: enableSidebarTextFilters,\r
-               enableSidebarTypeFilters: enableSidebarTypeFilters,\r
-               enableSearchPageField: enableSearchPageField\r
-       };\r
-\r
-       return ui;\r
-}();\r
-\r
-// Init UI on page load\r
-$(document).ready(function() {\r
-       Nitdoc.UI.enableFolding(".sidebar");\r
-       Nitdoc.UI.enableCopyToClipboard(".signature");\r
-       Nitdoc.UI.enableSidebarTextFilters("nav.filterable h3");\r
-       Nitdoc.UI.enableSidebarTypeFilters("nav.filterable");\r
-       Nitdoc.UI.enableSearchPageField(".content.fullpage h1:contains('Search')");\r
-});\r
-\r
-/*\r
- * Utils module\r
- *\r
- * Utility functions\r
- */\r
-\r
-Nitdoc.Utils = function() {\r
-\r
-       // Extract anchor part (after #) from URL string\r
-       var extractAnchor = function(url) {\r
-           var index = url.indexOf("#");\r
-           if (index >= 0) {\r
-                       return url.substring(index + 1);\r
-               }\r
-               return null;\r
-       }\r
-\r
-       // Public interface\r
-       var utils = {\r
-               extractAnchor: extractAnchor\r
-       };\r
-\r
-       return utils;\r
-}();\r
-\r
-// JQuery Case Insensitive :icontains selector\r
-$.expr[':'].icontains = function(obj, index, meta, stack){\r
-       return (obj.textContent.replace(/\[[0-9]+\]/g, "") || obj.innerText.replace(/\[[0-9]+\]/g, "") || jQuery(obj).text().replace(/\[[0-9]+\]/g, "") || '').toLowerCase().indexOf(meta[3].toLowerCase()) >= 0;\r
-};\r
-\r
diff --git a/share/nitdoc/scripts/ZeroClipboard.min.js b/share/nitdoc/scripts/ZeroClipboard.min.js
deleted file mode 100644 (file)
index 9038520..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/*!
- * zeroclipboard
- * The ZeroClipboard library provides an easy way to copy text to the clipboard using an invisible Adobe Flash movie, and a JavaScript interface.
- * Copyright 2013 Jon Rohan, James M. Greene, .
- * Released under the MIT license
- * http://zeroclipboard.github.io/ZeroClipboard/
- * v1.2.0-beta.4
- */(function(){"use strict";var a=function(){var a=/\-([a-z])/g,b=function(a,b){return b.toUpperCase()};return function(c){return c.replace(a,b)}}(),b=function(b,c){var d,e,f,g,h,i;window.getComputedStyle?d=window.getComputedStyle(b,null).getPropertyValue(c):(e=a(c),b.currentStyle?d=b.currentStyle[e]:d=b.style[e]);if(c==="cursor")if(!d||d==="auto"){f=b.tagName.toLowerCase(),g=["a"];for(h=0,i=g.length;h<i;h++)if(f===g[h])return"pointer"}return d},c=function(a){if(!o.prototype._singleton)return;a||(a=window.event);var b;this!==window?b=this:a.target?b=a.target:a.srcElement&&(b=a.srcElement),o.prototype._singleton.setCurrent(b)},d=function(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent("on"+b,c)},e=function(a,b,c){a.removeEventListener?a.removeEventListener(b,c,!1):a.detachEvent&&a.detachEvent("on"+b,c)},f=function(a,b){if(a.addClass)return a.addClass(b),a;if(b&&typeof b=="string"){var c=(b||"").split(/\s+/);if(a.nodeType===1)if(!a.className)a.className=b;else{var d=" "+a.className+" ",e=a.className;for(var f=0,g=c.length;f<g;f++)d.indexOf(" "+c[f]+" ")<0&&(e+=" "+c[f]);a.className=e.replace(/^\s+|\s+$/g,"")}}return a},g=function(a,b){if(a.removeClass)return a.removeClass(b),a;if(b&&typeof b=="string"||b===undefined){var c=(b||"").split(/\s+/);if(a.nodeType===1&&a.className)if(b){var d=(" "+a.className+" ").replace(/[\n\t]/g," ");for(var e=0,f=c.length;e<f;e++)d=d.replace(" "+c[e]+" "," ");a.className=d.replace(/^\s+|\s+$/g,"")}else a.className=""}return a},h=function(){var a,b,c,d=1;return typeof document.body.getBoundingClientRect=="function"&&(a=document.body.getBoundingClientRect(),b=a.right-a.left,c=document.body.offsetWidth,d=Math.round(b/c*100)/100),d},i=function(a){var c={left:0,top:0,width:0,height:0,zIndex:999999999},d=b(a,"z-index");d&&d!=="auto"&&(c.zIndex=parseInt(d,10));if(a.getBoundingClientRect){var e=a.getBoundingClientRect(),f,g,i;"pageXOffset"in window&&"pageYOffset"in window?(f=window.pageXOffset,g=window.pageYOffset):(i=h(),f=Math.round(document.documentElement.scrollLeft/i),g=Math.round(document.documentElement.scrollTop/i));var j=document.documentElement.clientLeft||0,k=document.documentElement.clientTop||0;c.left=e.left+f-j,c.top=e.top+g-k,c.width="width"in e?e.width:e.right-e.left,c.height="height"in e?e.height:e.bottom-e.top}return c},j=function(a){var b=o.prototype._singleton;return b.options.useNoCache?(a.indexOf("?")>=0?"&nocache=":"?nocache=")+(new Date).getTime():""},k=function(a){var b=[];if(a.trustedDomains){var c;typeof a.trustedDomains=="string"&&a.trustedDomains?c=[a.trustedDomains]:"length"in a.trustedDomains&&(c=a.trustedDomains),b.push("trustedDomain="+encodeURIComponent(c.join(",")))}return typeof a.amdModuleId=="string"&&a.amdModuleId&&b.push("amdModuleId="+encodeURIComponent(a.amdModuleId)),typeof a.cjsModuleId=="string"&&a.cjsModuleId&&b.push("cjsModuleId="+encodeURIComponent(a.cjsModuleId)),b.join("&")},l=function(a,b){if(b.indexOf)return b.indexOf(a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},m=function(a){if(typeof a=="string")throw new TypeError("ZeroClipboard doesn't accept query strings.");return a.length?a:[a]},n=function(a,b,c,d,e){e?window.setTimeout(function(){a.call(b,c,d)},0):a.call(b,c,d)},o=function(a,b){a&&(o.prototype._singleton||this).glue(a);if(o.prototype._singleton)return o.prototype._singleton;o.prototype._singleton=this,this.options={};for(var c in s)this.options[c]=s[c];for(var d in b)this.options[d]=b[d];this.handlers={},o.detectFlashSupport()&&v()},p,q=[];o.prototype.setCurrent=function(a){p=a,this.reposition();var c=a.getAttribute("title");c&&this.setTitle(c);var d=this.options.forceHandCursor===!0||b(a,"cursor")==="pointer";r.call(this,d)},o.prototype.setText=function(a){a&&a!==""&&(this.options.text=a,this.ready()&&this.flashBridge.setText(a))},o.prototype.setTitle=function(a){a&&a!==""&&this.htmlBridge.setAttribute("title",a)},o.prototype.setSize=function(a,b){this.ready()&&this.flashBridge.setSize(a,b)},o.prototype.setHandCursor=function(a){a=typeof a=="boolean"?a:!!a,r.call(this,a),this.options.forceHandCursor=a};var r=function(a){this.ready()&&this.flashBridge.setHandCursor(a)};o.version="1.2.0-beta.4";var s={moviePath:"ZeroClipboard.swf",trustedDomains:null,text:null,hoverClass:"zeroclipboard-is-hover",activeClass:"zeroclipboard-is-active",allowScriptAccess:"sameDomain",useNoCache:!0,forceHandCursor:!1};o.setDefaults=function(a){for(var b in a)s[b]=a[b]},o.destroy=function(){o.prototype._singleton.unglue(q);var a=o.prototype._singleton.htmlBridge;a.parentNode.removeChild(a),delete o.prototype._singleton},o.detectFlashSupport=function(){var a=!1;if(typeof ActiveXObject=="function")try{new ActiveXObject("ShockwaveFlash.ShockwaveFlash")&&(a=!0)}catch(b){}return!a&&navigator.mimeTypes["application/x-shockwave-flash"]&&(a=!0),a};var t=null,u=null,v=function(){var a=o.prototype._singleton,b=document.getElementById("global-zeroclipboard-html-bridge");if(!b){var c={};for(var d in a.options)c[d]=a.options[d];c.amdModuleId=t,c.cjsModuleId=u;var e=k(c),f='      <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="global-zeroclipboard-flash-bridge" width="100%" height="100%">         <param name="movie" value="'+a.options.moviePath+j(a.options.moviePath)+'"/>         <param name="allowScriptAccess" value="'+a.options.allowScriptAccess+'"/>         <param name="scale" value="exactfit"/>         <param name="loop" value="false"/>         <param name="menu" value="false"/>         <param name="quality" value="best" />         <param name="bgcolor" value="#ffffff"/>         <param name="wmode" value="transparent"/>         <param name="flashvars" value="'+e+'"/>         <embed src="'+a.options.moviePath+j(a.options.moviePath)+'"           loop="false" menu="false"           quality="best" bgcolor="#ffffff"           width="100%" height="100%"           name="global-zeroclipboard-flash-bridge"           allowScriptAccess="always"           allowFullScreen="false"           type="application/x-shockwave-flash"           wmode="transparent"           pluginspage="http://www.macromedia.com/go/getflashplayer"           flashvars="'+e+'"           scale="exactfit">         </embed>       </object>';b=document.createElement("div"),b.id="global-zeroclipboard-html-bridge",b.setAttribute("class","global-zeroclipboard-container"),b.setAttribute("data-clipboard-ready",!1),b.style.position="absolute",b.style.left="-9999px",b.style.top="-9999px",b.style.width="15px",b.style.height="15px",b.style.zIndex="9999",b.innerHTML=f,document.body.appendChild(b)}a.htmlBridge=b,a.flashBridge=document["global-zeroclipboard-flash-bridge"]||b.children[0].lastElementChild};o.prototype.resetBridge=function(){this.htmlBridge.style.left="-9999px",this.htmlBridge.style.top="-9999px",this.htmlBridge.removeAttribute("title"),this.htmlBridge.removeAttribute("data-clipboard-text"),g(p,this.options.activeClass),p=null,this.options.text=null},o.prototype.ready=function(){var a=this.htmlBridge.getAttribute("data-clipboard-ready");return a==="true"||a===!0},o.prototype.reposition=function(){if(!p)return!1;var a=i(p);this.htmlBridge.style.top=a.top+"px",this.htmlBridge.style.left=a.left+"px",this.htmlBridge.style.width=a.width+"px",this.htmlBridge.style.height=a.height+"px",this.htmlBridge.style.zIndex=a.zIndex+1,this.setSize(a.width,a.height)},o.dispatch=function(a,b){o.prototype._singleton.receiveEvent(a,b)},o.prototype.on=function(a,b){var c=a.toString().split(/\s/g);for(var d=0;d<c.length;d++)a=c[d].toLowerCase().replace(/^on/,""),this.handlers[a]||(this.handlers[a]=b);this.handlers.noflash&&!o.detectFlashSupport()&&this.receiveEvent("onNoFlash",null)},o.prototype.addEventListener=o.prototype.on,o.prototype.off=function(a,b){var c=a.toString().split(/\s/g);for(var d=0;d<c.length;d++){a=c[d].toLowerCase().replace(/^on/,"");for(var e in this.handlers)e===a&&this.handlers[e]===b&&delete this.handlers[e]}},o.prototype.removeEventListener=o.prototype.off,o.prototype.receiveEvent=function(a,b){a=a.toString().toLowerCase().replace(/^on/,"");var c=p,d=!0;switch(a){case"load":if(b&&parseFloat(b.flashVersion.replace(",",".").replace(/[^0-9\.]/gi,""))<10){this.receiveEvent("onWrongFlash",{flashVersion:b.flashVersion});return}this.htmlBridge.setAttribute("data-clipboard-ready",!0);break;case"mouseover":f(c,this.options.hoverClass);break;case"mouseout":g(c,this.options.hoverClass),this.resetBridge();break;case"mousedown":f(c,this.options.activeClass);break;case"mouseup":g(c,this.options.activeClass);break;case"datarequested":var e=c.getAttribute("data-clipboard-target"),h=e?document.getElementById(e):null;if(h){var i=h.value||h.textContent||h.innerText;i&&this.setText(i)}else{var j=c.getAttribute("data-clipboard-text");j&&this.setText(j)}d=!1;break;case"complete":this.options.text=null}if(this.handlers[a]){var k=this.handlers[a];typeof k=="string"&&typeof window[k]=="function"&&(k=window[k]),typeof k=="function"&&n(k,c,this,b,d)}},o.prototype.glue=function(a){a=m(a);for(var b=0;b<a.length;b++)l(a[b],q)==-1&&(q.push(a[b]),d(a[b],"mouseover",c))},o.prototype.unglue=function(a){a=m(a);for(var b=0;b<a.length;b++){e(a[b],"mouseover",c);var d=l(a[b],q);d!=-1&&q.splice(d,1)}},typeof define=="function"&&define.amd?define(["require","exports","module"],function(a,b,c){return t=c&&c.id||null,o}):typeof module!="undefined"&&module?(u=module.id||null,module.exports=o):window.ZeroClipboard=o})();
\ No newline at end of file
diff --git a/share/nitdoc/scripts/base64.js b/share/nitdoc/scripts/base64.js
deleted file mode 100644 (file)
index 1c23d21..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-var Base64 = {
-
-       // private property
-       _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
-
-       // public method for encoding
-       encode : function (input) {
-               var output = "";
-               var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
-               var i = 0;
-
-               input = Base64._utf8_encode(input);
-
-               while (i < input.length) {
-
-                       chr1 = input.charCodeAt(i++);
-                       chr2 = input.charCodeAt(i++);
-                       chr3 = input.charCodeAt(i++);
-
-                       enc1 = chr1 >> 2;
-                       enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
-                       enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
-                       enc4 = chr3 & 63;
-
-                       if (isNaN(chr2)) {
-                               enc3 = enc4 = 64;
-                       } else if (isNaN(chr3)) {
-                               enc4 = 64;
-                       }
-
-                       output = output +
-                       this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
-                       this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
-
-               }
-
-               return output;
-       },
-
-       // public method for decoding
-       decode : function (input) {
-               var output = "";
-               var chr1, chr2, chr3;
-               var enc1, enc2, enc3, enc4;
-               var i = 0;
-
-               input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
-
-               while (i < input.length) {
-
-                       enc1 = this._keyStr.indexOf(input.charAt(i++));
-                       enc2 = this._keyStr.indexOf(input.charAt(i++));
-                       enc3 = this._keyStr.indexOf(input.charAt(i++));
-                       enc4 = this._keyStr.indexOf(input.charAt(i++));
-
-                       chr1 = (enc1 << 2) | (enc2 >> 4);
-                       chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
-                       chr3 = ((enc3 & 3) << 6) | enc4;
-
-                       output = output + String.fromCharCode(chr1);
-
-                       if (enc3 != 64) {
-                               output = output + String.fromCharCode(chr2);
-                       }
-                       if (enc4 != 64) {
-                               output = output + String.fromCharCode(chr3);
-                       }
-
-               }
-
-               output = Base64._utf8_decode(output);
-
-               return output;
-
-       },
-
-       // private method for UTF-8 encoding
-       _utf8_encode : function (string) {
-               string = string.replace(/\r\n/g,"\n");
-               var utftext = "";
-
-               for (var n = 0; n < string.length; n++) {
-
-                       var c = string.charCodeAt(n);
-
-                       if (c < 128) {
-                               utftext += String.fromCharCode(c);
-                       }
-                       else if((c > 127) && (c < 2048)) {
-                               utftext += String.fromCharCode((c >> 6) | 192);
-                               utftext += String.fromCharCode((c & 63) | 128);
-                       }
-                       else {
-                               utftext += String.fromCharCode((c >> 12) | 224);
-                               utftext += String.fromCharCode(((c >> 6) & 63) | 128);
-                               utftext += String.fromCharCode((c & 63) | 128);
-                       }
-
-               }
-
-               return utftext;
-       },
-
-       // private method for UTF-8 decoding
-       _utf8_decode : function (utftext) {
-               var string = "";
-               var i = 0;
-               var c = c1 = c2 = 0;
-
-               while ( i < utftext.length ) {
-
-                       c = utftext.charCodeAt(i);
-
-                       if (c < 128) {
-                               string += String.fromCharCode(c);
-                               i++;
-                       }
-                       else if((c > 191) && (c < 224)) {
-                               c2 = utftext.charCodeAt(i+1);
-                               string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
-                               i += 2;
-                       }
-                       else {
-                               c2 = utftext.charCodeAt(i+1);
-                               c3 = utftext.charCodeAt(i+2);
-                               string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
-                               i += 3;
-                       }
-
-               }
-
-               return string;
-       }
-}
-
index 76aaa19..c8454e5 100644 (file)
@@ -127,15 +127,53 @@ redef class ModelBuilder
 
                compile_dir.mkdir
 
+               var cfiles = new Array[String]
+               write_files(compiler, compile_dir, cfiles)
+
+               # Generate the Makefile
+
+               write_makefile(compiler, compile_dir, cfiles)
+
+               var time1 = get_time
+               self.toolcontext.info("*** END WRITING C: {time1-time0} ***", 2)
+
+               # Execute the Makefile
+
+               if self.toolcontext.opt_no_cc.value then return
+
+               time0 = time1
+               self.toolcontext.info("*** COMPILING C ***", 1)
+
+               compile_c_code(compiler, compile_dir)
+
+               time1 = get_time
+               self.toolcontext.info("*** END COMPILING C: {time1-time0} ***", 2)
+       end
+
+       fun write_files(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
+       do
                if self.toolcontext.opt_stacktrace.value then compiler.build_c_to_nit_bindings
 
-               var orig_dir=".." # FIXME only works if `compile_dir` is a subdirectory of cwd
+               # Add gc_choser.h to aditionnal bodies
+               var gc_chooser = new ExternCFile("gc_chooser.c", "-DWITH_LIBGC")
+               compiler.extern_bodies.add(gc_chooser)
+               compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.c"
+               compiler.files_to_copy.add "{cc_paths.first}/gc_chooser.h"
 
-               var outname = self.toolcontext.opt_output.value
-               if outname == null then
-                       outname = "{mainmodule.name}"
+               # FFI
+               for m in compiler.mainmodule.in_importation.greaters do if mmodule2nmodule.keys.has(m) then
+                       var amodule = mmodule2nmodule[m]
+                       if m.uses_ffi or amodule.uses_legacy_ni then
+                               compiler.finalize_ffi_for_module(amodule)
+                       end
+               end
+
+               # Copy original .[ch] files to compile_dir
+               for src in compiler.files_to_copy do
+                       var basename = src.basename("")
+                       var dst = "{compile_dir}/{basename}"
+                       src.file_copy_to dst
                end
-               var outpath = orig_dir.join_path(outname).simplify_path
 
                var hfilename = compiler.header.file.name + ".h"
                var hfilepath = "{compile_dir}/{hfilename}"
@@ -150,8 +188,6 @@ redef class ModelBuilder
                end
                h.close
 
-               var cfiles = new Array[String]
-
                for f in compiler.files do
                        var i = 0
                        var hfile: nullable OFStream = null
@@ -199,24 +235,25 @@ redef class ModelBuilder
                end
 
                self.toolcontext.info("Total C source files to compile: {cfiles.length}", 2)
+       end
 
-               # FFI
-               for m in mainmodule.in_importation.greaters do if mmodule2nmodule.keys.has(m) then
-                       var amodule = mmodule2nmodule[m]
-                       if m.uses_ffi or amodule.uses_legacy_ni then
-                               compiler.finalize_ffi_for_module(amodule)
-                       end
-               end
+       fun write_makefile(compiler: AbstractCompiler, compile_dir: String, cfiles: Array[String])
+       do
+               var mainmodule = compiler.mainmodule
 
-               # Generate the Makefile
+               var outname = self.toolcontext.opt_output.value
+               if outname == null then
+                       outname = "{mainmodule.name}"
+               end
 
+               var orig_dir=".." # FIXME only works if `compile_dir` is a subdirectory of cwd
+               var outpath = orig_dir.join_path(outname).simplify_path
                var makename = "{mainmodule.name}.mk"
                var makepath = "{compile_dir}/{makename}"
                var makefile = new OFStream.open(makepath)
 
                var cc_includes = ""
                for p in cc_paths do
-                       p = orig_dir.join_path(p).simplify_path
                        cc_includes += " -I \"" + p + "\""
                end
 
@@ -226,33 +263,38 @@ redef class ModelBuilder
                        linker_options.add(amod.c_linker_options)
                end
 
-               if not toolcontext.opt_no_stacktrace.value then
-                       linker_options.add("-lunwind")
-    end
+               if not toolcontext.opt_no_stacktrace.value then linker_options.add("-lunwind")
 
                makefile.write("CC = ccache cc\nCFLAGS = -g -O2\nCINCL = {cc_includes}\nLDFLAGS ?= \nLDLIBS  ?= -lm -lgc {linker_options.join(" ")}\n\n")
                makefile.write("all: {outpath}\n\n")
 
                var ofiles = new Array[String]
+               var dep_rules = new Array[String]
                # Compile each generated file
                for f in cfiles do
                        var o = f.strip_extension(".c") + ".o"
                        makefile.write("{o}: {f}\n\t$(CC) $(CFLAGS) $(CINCL) -D NONITCNI -c -o {o} {f}\n\n")
                        ofiles.add(o)
+                       dep_rules.add(o)
                end
 
-               # Add gc_choser.h to aditionnal bodies
-               var gc_chooser = new ExternCFile("{cc_paths.first}/gc_chooser.c", "-DWITH_LIBGC")
-               compiler.extern_bodies.add(gc_chooser)
-
                # Compile each required extern body into a specific .o
                for f in compiler.extern_bodies do
                        if f isa ExternCFile then
                                var basename = f.filename.basename(".c")
                                var o = "{basename}.extern.o"
-                               var ff = orig_dir.join_path(f.filename).simplify_path
+                               var ff = f.filename.basename("")
                                makefile.write("{o}: {ff}\n\t$(CC) $(CFLAGS) -D NONITCNI {f.cflags} -c -o {o} {ff}\n\n")
                                ofiles.add(o)
+                               dep_rules.add(o)
+                       else
+                               var o = f.makefile_rule_name
+                               var ff = f.filename.basename("")
+                               makefile.write("{o}: {ff}\n")
+                               makefile.write("\t{f.makefile_rule_content}\n")
+                               dep_rules.add(f.makefile_rule_name)
+
+                               if f isa ExternCppFile then ofiles.add(o)
                        end
                end
 
@@ -262,16 +304,12 @@ redef class ModelBuilder
                makefile.write("clean:\n\trm {ofiles.join(" ")} 2>/dev/null\n\n")
                makefile.close
                self.toolcontext.info("Generated makefile: {makepath}", 2)
+       end
 
-               var time1 = get_time
-               self.toolcontext.info("*** END WRITING C: {time1-time0} ***", 2)
-
-               # Execute the Makefile
-
-               if self.toolcontext.opt_no_cc.value then return
+       fun compile_c_code(compiler: AbstractCompiler, compile_dir: String)
+       do
+               var makename = "{compiler.mainmodule.name}.mk" # FIXME duplicated from write_makefile
 
-               time0 = time1
-               self.toolcontext.info("*** COMPILING C ***", 1)
                var makeflags = self.toolcontext.opt_make_flags.value
                if makeflags == null then makeflags = ""
                self.toolcontext.info("make -B -C {compile_dir} -f {makename} -j 4 {makeflags}", 2)
@@ -285,9 +323,6 @@ redef class ModelBuilder
                if res != 0 then
                        toolcontext.error(null, "make failed! Error code: {res}.")
                end
-
-               time1 = get_time
-               self.toolcontext.info("*** END COMPILING C: {time1-time0} ***", 2)
        end
 end
 
@@ -389,7 +424,7 @@ abstract class AbstractCompiler
                self.header.add_decl("#include <stdlib.h>")
                self.header.add_decl("#include <stdio.h>")
                self.header.add_decl("#include <string.h>")
-               self.header.add_decl("#include <gc_chooser.h>")
+               self.header.add_decl("#include \"gc_chooser.h\"")
 
                compile_header_structs
                compile_nitni_structs
@@ -440,6 +475,11 @@ abstract class AbstractCompiler
                        end
                end
 
+               v.add_decl("void sig_handler(int signo)\{")
+               v.add_decl("printf(\"Caught signal : %s\\n\", strsignal(signo));")
+               v.add_decl("show_backtrace(signo);")
+               v.add_decl("\}")
+
                v.add_decl("void show_backtrace (int signo) \{")
                if not modelbuilder.toolcontext.opt_no_stacktrace.value then
                        v.add_decl("char* opt = getenv(\"NIT_NO_STACK\");")
@@ -475,12 +515,12 @@ abstract class AbstractCompiler
 
                v.add_decl("int main(int argc, char** argv) \{")
 
-               v.add("signal(SIGABRT, show_backtrace);")
-               v.add("signal(SIGFPE, show_backtrace);")
-               v.add("signal(SIGILL, show_backtrace);")
-               v.add("signal(SIGINT, show_backtrace);")
-               v.add("signal(SIGTERM, show_backtrace);")
-               v.add("signal(SIGSEGV, show_backtrace);")
+               v.add("signal(SIGABRT, sig_handler);")
+               v.add("signal(SIGFPE, sig_handler);")
+               v.add("signal(SIGILL, sig_handler);")
+               v.add("signal(SIGINT, sig_handler);")
+               v.add("signal(SIGTERM, sig_handler);")
+               v.add("signal(SIGSEGV, sig_handler);")
 
                v.add("glob_argc = argc; glob_argv = argv;")
                v.add("initialize_gc_option();")
@@ -532,6 +572,9 @@ abstract class AbstractCompiler
        # List of additional files required to compile (FFI)
        var extern_bodies = new Array[ExternFile]
 
+       # List of source files to copy over to the compile dir
+       var files_to_copy = new Array[String]
+
        # This is used to avoid adding an extern file more than once
        private var seen_extern = new ArraySet[String]
 
@@ -847,7 +890,7 @@ abstract class AbstractCompilerVisitor
                var maybenull = recv.mcasttype isa MNullableType or recv.mcasttype isa MNullType
                if maybenull then
                        self.add("if ({recv} == NULL) \{")
-                       self.add_abort("Reciever is null")
+                       self.add_abort("Receiver is null")
                        self.add("\}")
                end
        end
@@ -1010,11 +1053,13 @@ abstract class AbstractCompilerVisitor
                file = file.strip_extension(".nit")
                var tryfile = file + ".nit.h"
                if tryfile.file_exists then
-                       self.declare_once("#include \"{"..".join_path(tryfile)}\"")
+                       self.declare_once("#include \"{tryfile.basename("")}\"")
+                       self.compiler.files_to_copy.add(tryfile)
                end
                tryfile = file + "_nit.h"
                if tryfile.file_exists then
-                       self.declare_once("#include \"{"..".join_path(tryfile)}\"")
+                       self.declare_once("#include \"{tryfile.basename("")}\"")
+                       self.compiler.files_to_copy.add(tryfile)
                end
 
                if self.compiler.seen_extern.has(file) then return
@@ -1024,8 +1069,9 @@ abstract class AbstractCompilerVisitor
                        tryfile = file + "_nit.c"
                        if not tryfile.file_exists then return
                end
-               var f = new ExternCFile(tryfile, "")
+               var f = new ExternCFile(tryfile.basename(""), "")
                self.compiler.extern_bodies.add(f)
+               self.compiler.files_to_copy.add(tryfile)
        end
 
        # Return a new local runtime_variable initialized with the C expression `cexpr`.
@@ -1463,13 +1509,13 @@ redef class AConcreteMethPropdef
                # Call the implicit super-init
                var auto_super_inits = self.auto_super_inits
                if auto_super_inits != null then
-                       var selfarg = [arguments.first]
+                       var args = [arguments.first]
                        for auto_super_init in auto_super_inits do
-                               if auto_super_init.intro.msignature.arity == 0 then
-                                       v.send(auto_super_init, selfarg)
-                               else
-                                       v.send(auto_super_init, arguments)
+                               args.clear
+                               for i in [0..auto_super_init.intro.msignature.arity+1[ do
+                                       args.add(arguments[i])
                                end
+                               v.send(auto_super_init, args)
                        end
                end
                v.stmt(self.n_block)
@@ -2398,20 +2444,24 @@ redef class ASuperExpr
                for a in self.n_args.n_exprs do
                        args.add(v.expr(a, null))
                end
-               if args.length == 1 then
-                       args = v.frame.arguments
-               end
 
                var callsite = self.callsite
                if callsite != null then
-                       if callsite.mproperty.intro.msignature.arity == 0 then
-                               args = [recv]
+                       # Add additionnals arguments for the super init call
+                       if args.length == 1 then
+                               for i in [0..callsite.mproperty.intro.msignature.arity[ do
+                                       args.add(v.frame.arguments[i+1])
+                               end
                        end
                        # Super init call
                        var res = v.compile_callsite(callsite, args)
                        return res
                end
 
+               if args.length == 1 then
+                       args = v.frame.arguments
+               end
+
                # stantard call-next-method
                return v.supercall(v.frame.mpropdef.as(MMethodDef), recv.mtype.as(MClassType), args)
        end
index 89362a2..62bb58b 100644 (file)
@@ -56,6 +56,7 @@ redef class AConcreteMethPropdef
                var mclassdef = self.parent.as(AClassdef).mclassdef.as(not null)
                var mpropdef = self.mpropdef.as(not null)
                var mmodule = mpropdef.mclassdef.mmodule
+               var anchor = mclassdef.bound_mtype
 
                # Collect only for constructors
                if not mpropdef.mproperty.is_init then return
@@ -92,23 +93,34 @@ redef class AConcreteMethPropdef
                                candidate = modelbuilder.try_get_mproperty_by_name2(self, mmodule, msupertype, "init")
                        end
                        if candidate == null then
-                               modelbuilder.error(self, "Cannot do an implicit constructor call for {mpropdef}: there is no costructor named {mpropdef.mproperty.name} in {msupertype}.")
+                               modelbuilder.error(self, "Error: Cannot do an implicit constructor call in {mpropdef}; there is no constructor named {mpropdef.mproperty.name} in {msupertype}.")
                                return
                        end
                        assert candidate isa MMethod
                        auto_super_inits.add(candidate)
                end
                if auto_super_inits.is_empty then
-                       modelbuilder.error(self, "No constructors to call implicitely. Call one explicitely.")
+                       modelbuilder.error(self, "Error: No constructors to call implicitely in {mpropdef}. Call one explicitely.")
                        return
                end
                for auto_super_init in auto_super_inits do
                        var auto_super_init_def = auto_super_init.intro
                        var msig = mpropdef.msignature.as(not null)
                        var supermsig = auto_super_init_def.msignature.as(not null)
-                       if auto_super_init_def.msignature.arity != 0 and auto_super_init_def.msignature.arity != mpropdef.msignature.arity then
-                               # TODO: Better check of the signature
-                               modelbuilder.error(self, "Problem with signature of constructor {auto_super_init_def}{supermsig}. Expected {msig}")
+                       if auto_super_init_def.msignature.arity > mpropdef.msignature.arity then
+                               modelbuilder.error(self, "Error: Cannot do an implicit constructor call to {auto_super_init_def}{supermsig}. Expected at least {auto_super_init_def.msignature.arity} arguments, got {mpropdef.msignature.arity}.")
+                               continue
+                       end
+                       var i = 0
+                       for sp in auto_super_init_def.msignature.mparameters do
+                               var p = mpropdef.msignature.mparameters[i]
+                               var sub = p.mtype
+                               var sup = sp.mtype
+                               if not sub.is_subtype(mmodule, anchor, sup) then
+                                       modelbuilder.error(self, "Error: Cannot do an implicit constructor call to {auto_super_init_def}{supermsig}. Expected argument #{i} of type {sp.mtype}, got implicit argument {p.name} of type {p.mtype}.")
+                                       break
+                               end
+                               i += 1
                        end
                end
                self.auto_super_inits = auto_super_inits
index 7733990..b596a8a 100644 (file)
@@ -20,6 +20,7 @@
 module c_compiler_options
 
 import c
+import cpp
 
 redef class ToolContext
        var c_compiler_options_phase: Phase = new CCompilerOptionsPhase(self, null)
@@ -30,13 +31,15 @@ private class CCompilerOptionsPhase
 
        fun compiler_annotation_name: String do return "c_compiler_option"
        fun linker_annotation_name: String do return "c_linker_option"
+       fun cpp_compiler_annotation_name: String do return "cpp_compiler_option"
 
        redef fun process_annotated_node(nmoduledecl, nat)
        do
                # Skip if we are not interested
                var annotation_name = nat.n_atid.n_id.text
                if annotation_name != compiler_annotation_name and
-                  annotation_name != linker_annotation_name then return
+                  annotation_name != linker_annotation_name and
+                  annotation_name != cpp_compiler_annotation_name then return
 
                # Do some validity checks and print errors if the annotation is used incorrectly
                var modelbuilder = toolcontext.modelbuilder
@@ -139,6 +142,8 @@ private class CCompilerOptionsPhase
                                process_c_compiler_annotation(nmodule, cmd)
                        else if annotation_name == linker_annotation_name then
                                process_c_linker_annotation(nmodule, cmd)
+                       else if annotation_name == cpp_compiler_annotation_name then
+                               process_cpp_compiler_annotation(nmodule, cmd)
                        else abort
                end
        end
@@ -152,6 +157,11 @@ private class CCompilerOptionsPhase
        do
                nmodule.c_linker_options = "{nmodule.c_linker_options} {opt}"
        end
+
+       fun process_cpp_compiler_annotation(nmodule: AModule, opt: String)
+       do
+               nmodule.cpp_compiler_options = "{nmodule.cpp_compiler_options} {opt}"
+       end
 end
 
 abstract class CCompilerOption
index 89788cd..01d3b17 100644 (file)
@@ -30,6 +30,7 @@ import header_dependency
 import pkgconfig
 import c_compiler_options
 import c
+import cpp
 
 redef class MModule
        # Does this module uses the FFI?
diff --git a/src/common_ffi/cpp.nit b/src/common_ffi/cpp.nit
new file mode 100644 (file)
index 0000000..3af6d1a
--- /dev/null
@@ -0,0 +1,262 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Supports the use of the C++ language through the FFI
+module cpp
+
+import extern_classes
+import c
+
+redef class FFILanguageAssignationPhase
+       var cpp_language: FFILanguage = new CPPLanguage(self)
+end
+
+redef class AModule
+       private var cpp_file: nullable CPPCompilationUnit = null
+       var cpp_compiler_options writable = ""
+end
+
+class CPPLanguage
+       super FFILanguage
+
+       redef fun identify_language(n) do return n.is_cpp
+
+       redef fun compile_module_block(block, ecc, nmodule)
+       do
+               if nmodule.cpp_file == null then nmodule.cpp_file = new CPPCompilationUnit
+
+               if block.is_cpp_header then
+                       nmodule.cpp_file.header_custom.add(block.location.as_line_pragma)
+                       nmodule.cpp_file.header_custom.add(block.code)
+               else if block.is_cpp_body then
+                       nmodule.cpp_file.body_custom.add( block.location.as_line_pragma )
+                       nmodule.cpp_file.body_custom.add( block.code )
+               end
+       end
+
+       # We call C++ from C using 2 more files (_ffi.c and _ffi.cpp) and multiple generated functions:
+       # 1. The standard C implementation function (___impl) expected by the common FFI
+       # 2. The indirection function (___cpp_impl_mid) is a C function, called from C but implemented as `extern "C"` in C++
+       # 3. The actual C++ implementation function (___cpp_impl)
+       redef fun compile_extern_method(block, m, ecc, nmodule)
+       do
+               if nmodule.cpp_file == null then nmodule.cpp_file = new CPPCompilationUnit
+
+               var mmodule = nmodule.mmodule.as(not null)
+               var mclass_type = m.parent.as(AClassdef).mclass.mclass_type
+               var mproperty = m.mpropdef.mproperty
+
+               # Signature of the indirection function implemented as `extern "C"` in C++
+               var indirection_sig = mproperty.build_csignature(mclass_type, mmodule, "___cpp_impl_mid", long_signature, internal_call_context)
+
+               ## In C file (__ffi.c)
+               
+               # Declare the indirection function in C
+               ecc.body_decl.add("{indirection_sig};\n")
+
+               # Call the indirection function from C (___impl)
+               var fc: CFunction = new ExternCFunction(m, mmodule)
+               fc.exprs.add(mproperty.build_ccall(mclass_type, mmodule, "___cpp_impl_mid", long_signature, cpp_call_context, null))
+               fc.exprs.add("\n")
+               ecc.add_exported_function( fc )
+
+               ## In C++ file (__ffi.cpp)
+
+               # Declare the indirection function in C++
+               nmodule.cpp_file.header_decl.add("extern \"C\" \{\n")
+               nmodule.cpp_file.header_decl.add("{indirection_sig};\n")
+               nmodule.cpp_file.header_decl.add("\}\n")
+
+               # Implement the indirection function as extern in C++
+               # Will convert C arguments to C++ and call the C++ implementation function.
+               fc = new CFunction(indirection_sig)
+               if not mproperty.is_init then
+                       var param_name = "recv"
+                       var type_name = to_cpp_call_context.name_mtype(mclass_type)
+                       if mclass_type.mclass.ftype isa ForeignCppType then
+                               fc.exprs.add("{type_name} {param_name}_for_cpp = static_cast<{type_name}>({param_name});\n")
+                       else
+                               fc.exprs.add("{type_name} {param_name}_for_cpp = {param_name};\n")
+                       end
+               end
+               for param in m.mpropdef.msignature.mparameters do
+                       var param_name = param.name
+                       var type_name = to_cpp_call_context.name_mtype(param.mtype)
+                       if mclass_type.mclass.ftype isa ForeignCppType then
+                               fc.exprs.add("{type_name} {param_name}_for_cpp = static_cast<{type_name}>({param_name});\n")
+                       else
+                               fc.exprs.add("{type_name} {param_name}_for_cpp = {param_name};\n")
+                       end
+               end
+               fc.exprs.add(mproperty.build_ccall(mclass_type, mmodule, "___cpp_impl", long_signature, cpp_call_context, "_for_cpp"))
+               fc.exprs.add("\n")
+               nmodule.cpp_file.add_local_function(fc)
+
+               # Custom C++, the body of the Nit C++ method is copied to its own C++ function
+               var cpp_signature = mproperty.build_csignature(mclass_type, mmodule, "___cpp_impl", long_signature, cpp_call_context)
+               fc = new CFunction(cpp_signature)
+               fc.decls.add( block.location.as_line_pragma )
+               fc.exprs.add( block.code )
+               nmodule.cpp_file.add_local_function( fc )
+       end
+
+       redef fun compile_extern_class(block, m, ecc, nmodule) do end
+
+       redef fun get_ftype(block, m) do return new ForeignCppType(block.code)
+
+       redef fun compile_to_files(nmodule, compdir)
+       do
+               var cpp_file = nmodule.cpp_file
+               assert cpp_file != null
+
+               # write .cpp and .hpp file
+               cpp_file.header_custom.add("extern \"C\" \{\n")
+               cpp_file.header_custom.add("#include \"{nmodule.mmodule.name}._ffi.h\"\n")
+               cpp_file.header_custom.add("\}\n")
+
+               var file = cpp_file.write_to_files(nmodule, compdir)
+
+               # add complation to makefile
+               nmodule.ffi_files.add(file)
+
+               # add linked option to support C++
+               nmodule.c_linker_options = "{nmodule.c_linker_options} -lstdc++"
+       end
+
+       redef fun compile_callback(callback, nmodule, mmodule, ecc)
+       do
+               callback.compile_callback_to_cpp(nmodule, mmodule)
+       end
+end
+
+redef class AExternCodeBlock
+       fun is_cpp : Bool do return language_name != null and
+               (language_name_lowered == "c++" or language_name_lowered.has_prefix("c++ "))
+
+       fun is_cpp_body : Bool do return language_name != null and
+               (language_name_lowered == "c++" or language_name_lowered == "c++ body")
+
+       fun is_cpp_header : Bool do return language_name != null and
+               (language_name_lowered == "c++ header")
+end
+
+class CPPCompilationUnit
+       super CCompilationUnit
+
+       fun write_to_files(amodule: AModule, compdir: String): ExternCppFile
+       do
+               var base_name = "{amodule.mmodule.name}._ffi"
+
+               var h_file = "{base_name}.hpp"
+               var guard = "{amodule.cname.to_s.to_upper}_NIT_HPP"
+
+               write_header_to_file(amodule, "{compdir}/{h_file}", new Array[String], guard)
+
+               var c_file = "{base_name}.cpp"
+               write_body_to_file(amodule, "{compdir}/{c_file}", ["<string>", "<iostream>", "\"{h_file}\""])
+
+               files.add("{compdir}/{c_file}")
+
+               return new ExternCppFile("{compdir}/{c_file}", amodule)
+       end
+end
+
+class ExternCppFile
+       super ExternFile
+
+       var amodule: AModule
+       init(path: String, amodule: AModule)
+       do
+               super
+               self.amodule = amodule
+       end
+
+       redef fun makefile_rule_name do return "{filename.basename("")}.o"
+       redef fun makefile_rule_content do return "g++ {amodule.cpp_compiler_options} -c {filename.basename("")} -o {filename.basename("")}.o"
+end
+
+class ForeignCppType
+       super ForeignType
+
+       var cpp_type: String
+
+       init (cpp_type: String)
+       do
+               self.cpp_type = cpp_type
+       end
+end
+
+redef class NitniCallback
+       fun compile_callback_to_cpp(nmodule: AModule, mmodule: MModule) do end
+end
+
+redef class Object
+       private fun cpp_call_context: CppCallContext do return once new CppCallContext
+       private fun to_cpp_call_context: ToCppCallContext do return once new ToCppCallContext
+       private fun from_cpp_call_context: FromCppCallContext do return once new FromCppCallContext
+end
+
+redef class MExplicitCall
+       redef fun compile_callback_to_cpp(nmodule, mmodule)
+       do
+               var mproperty = mproperty
+               assert mproperty isa MMethod
+
+               var cpp_signature = mproperty.build_csignature(recv_mtype, mmodule, null, short_signature, from_cpp_call_context)
+               var ccall = mproperty.build_ccall(recv_mtype, mmodule, null, long_signature, from_cpp_call_context, null)
+               var fc = new CFunction(cpp_signature)
+               fc.exprs.add(ccall)
+               nmodule.cpp_file.add_local_function( fc )
+       end
+end
+
+private class CppCallContext
+       super CallContext
+
+       redef fun name_mtype(mtype)
+       do
+               if mtype isa MClassType then
+                       var ftype = mtype.mclass.ftype
+                       if ftype isa ForeignCppType then
+                               return ftype.cpp_type
+                       end
+               end
+
+               return mtype.cname
+       end
+end
+
+class ToCppCallContext
+       super CppCallContext
+
+       redef fun cast_to(mtype, name)
+       do
+               if mtype isa MClassType and mtype.mclass.ftype isa ForeignCppType then
+                       return "(void*)({name})"
+               else return name
+       end
+end
+
+private class FromCppCallContext
+       super CppCallContext
+
+       redef fun cast_from(mtype, name)
+       do
+               if mtype isa MClassType and mtype.mclass.ftype isa ForeignCppType then
+                       return "static_cast<{name_mtype(mtype)}>({name})"
+               else return name
+       end
+end
index 12d8b37..02276be 100644 (file)
@@ -271,12 +271,7 @@ class Debugger
                        self.discover_call_trace.add mpropdef
                        self.debug("Discovered {mpropdef}")
                end
-               if args.length < mpropdef.msignature.arity + 1 or args.length > mpropdef.msignature.arity + 1 then
-                       fatal("NOT YET IMPLEMENTED: Invalid arity for {mpropdef}. {args.length} arguments given.")
-               end
-               if args.length < mpropdef.msignature.arity + 1 then
-                       fatal("NOT YET IMPLEMENTED: default closures")
-               end
+               assert args.length == mpropdef.msignature.arity + 1 else debug("Invalid arity for {mpropdef}. {args.length} arguments given.")
 
                # Look for the AST node that implements the property
                var mproperty = mpropdef.mproperty
index ecd7265..89f8a1f 100644 (file)
@@ -384,7 +384,7 @@ class GlobalCompilerVisitor
                                        self.add("{res} = 1; /* {args[1].inspect} cannot be null */")
                                end
                        else
-                               self.add_abort("Reciever is null")
+                               self.add_abort("Receiver is null")
                        end
                        self.add "\} else"
                end
@@ -456,11 +456,7 @@ class GlobalCompilerVisitor
        # Finalizes a call to a method ´m´ on type ´recvtype´ with arguments ´args´
        private fun finalize_call(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
        do
-               if args.length != m.msignature.arity + 1 then # because of self
-                       add("printf(\"NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.\\n\"); show_backtrace(1);")
-                       debug("NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.")
-                       return null
-               end
+               assert args.length == m.msignature.arity + 1 else debug("Invalid arity for {m}. {args.length} arguments given.")
 
                var rm = new CustomizedRuntimeFunction(m, recvtype)
                return rm.call(self, args)
index 015dbe1..5e7f21f 100644 (file)
@@ -1,6 +1,6 @@
 # This file is part of NIT ( http://www.nitlanguage.org ).
 #
-# Copyright 2012 Jean Privat <jean@pryen.org>
+# Copyright 2014 Alexandre Terrasa <alexandre@moz-code.org>
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -18,7 +18,8 @@
 module inheritance_metrics
 
 import model
-private import metrics_base
+import mmodules_metrics
+import mclasses_metrics
 import phase
 import frontend
 
@@ -26,1049 +27,476 @@ redef class ToolContext
        var inheritance_metrics_phase = new InheritanceMetricsPhase(self, null)
 end
 
-# Extract metrics about module and class hierarchies.
+# Extract metrics about inheritance from model.
 private class InheritanceMetricsPhase
        super Phase
        redef fun process_mainmodule(mainmodule)
        do
                if not toolcontext.opt_inheritance.value and not toolcontext.opt_all.value then return
-               compute_inheritance_metrics(toolcontext, toolcontext.modelbuilder.model)
-       end
-end
-
-redef class Model
-       # Extract the subset of classes from a set of mclass
-       private fun extract_classes(mclasses: Collection[MClass]): Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclass in mclasses do if mclass.is_class then lst.add(mclass)
-               return lst
-       end
-
-       # Extract the subset of interfaces from a set of mclass
-       private fun extract_interfaces(mclasses: Collection[MClass]): Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclass in mclasses do if mclass.is_interface then lst.add(mclass)
-               return lst
-       end
-
-       # Extract the subset of generic classes/interfaces from a set of mclass
-       private fun extract_generics(mclasses: Collection[MClass]): Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclass in mclasses do if mclass.arity > 0 then lst.add(mclass)
-               return lst
-       end
-
-       # Extract the subset of abstract classes from a set of mclass
-       private fun extract_abstracts(mclasses: Collection[MClass]): Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclass in mclasses do if mclass.is_abstract then lst.add(mclass)
-               return lst
-       end
-
-       # Extract the subset of user defined classes/interfaces from a set of mclass
-       private fun extract_user_defined(mclasses: Collection[MClass]): Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclass in mclasses do if mclass.is_user_defined then lst.add(mclass)
-               return lst
-       end
 
-       # Extract the subset of user defined modules from a set of mmodules
-       private fun extract_user_defined_modules(mmodules: Collection[MModule]): Set[MModule] do
-               var lst = new HashSet[MModule]
-               for mmodule in mmodules do if mmodule.is_user_defined then lst.add(mmodule)
-               return lst
-       end
-
-       # Extract the subset of classes/interfaces from sl lib
-       private fun extract_stdlib(mclasses: Collection[MClass]): Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclass in mclasses do if not mclass.is_user_defined then lst.add(mclass)
-               return lst
+               print toolcontext.format_h1("\n# Inheritance metrics")
+
+               var hmetrics = new InheritanceMetricSet
+               hmetrics.register(new MDUI, new MDUIC, new MDUII, new MIF, new MIFC, new MIFI)
+               
+               var cmetrics = new MClassMetricSet
+               cmetrics.register(new CNOA, new CNOP, new CNOC, new CNODC)
+               cmetrics.register(new CNOA, new CNOP, new CNOC, new CNODI)
+               cmetrics.register(new CDIT, new CDITI)
+
+               var model = toolcontext.modelbuilder.model
+               var mmodules = new HashSet[MModule]
+               var mclasses = new HashSet[MClass]
+               for mproject in model.mprojects do
+
+                       print toolcontext.format_h2("\n ## project {mproject}")
+
+                       for mgroup in mproject.mgroups do
+                               if mgroup.mmodules.is_empty then continue
+
+                               # Scalar metrics
+                               print toolcontext.format_h3("  `- group {mgroup.full_name}")
+
+                               var mod_mclasses = new HashSet[MClass]
+                               for mmodule in mgroup.mmodules do mod_mclasses.add_all(mmodule.intro_mclasses)
+                               if mod_mclasses.is_empty then continue
+                               mmodules.add_all(mgroup.mmodules)
+                               mclasses.add_all(mod_mclasses)
+                               cmetrics.collect(new HashSet[MClass].from(mod_mclasses), mainmodule)
+                               for name, metric in cmetrics.metrics do
+                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                       print toolcontext.format_p("\t    avg: {metric.avg}")
+                                       var max = metric.max
+                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                       var min = metric.min
+                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               end
+                               hmetrics.collect(new HashSet[MModule].from(mgroup.mmodules), mainmodule)
+                               for name, metric in hmetrics.metrics do
+                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                       print toolcontext.format_p("\t    avg: {metric.avg}")
+                                       var max = metric.max
+                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                       var min = metric.min
+                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               end
+                       end
+               end
+               if not mclasses.is_empty then
+                       # Global metrics
+                       print toolcontext.format_h2("\n ## global metrics")
+                       cmetrics.collect(mclasses, mainmodule)
+                       for name, metric in cmetrics.metrics do
+                               print toolcontext.format_h4("\t{name}: {metric.desc}")
+                               print toolcontext.format_p("\t    avg: {metric.avg}")
+                               var max = metric.max
+                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                               var min = metric.min
+                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                       end
+                       hmetrics.collect(mmodules, mainmodule)
+                       for name, metric in hmetrics.metrics do
+                               print toolcontext.format_h4("\t{name}: {metric.desc}")
+                               print toolcontext.format_p("\t    avg: {metric.avg}")
+                               var max = metric.max
+                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                               var min = metric.min
+                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                       end
+               end
        end
+end
 
-       # Extract the subset of user defined modules from std lib
-       private fun extract_stdlib_modules(mmodules: Collection[MModule]): Set[MModule] do
-               var lst = new HashSet[MModule]
-               for mmodule in mmodules do if not mmodule.is_user_defined then lst.add(mmodule)
-               return lst
+# Metric Set used to collect data about inheritance in each module
+class InheritanceMetricSet
+       super MetricSet
+       redef type METRIC: InheritanceMetric
+       fun collect(mmodules: Set[MModule], mainmodule: MModule) do
+               clear
+               for metric in metrics.values do
+                       for mmodule in mmodules do
+                               metric.collect(mmodule, mainmodule)
+                       end
+               end
        end
 end
 
-redef class MClass
-       # Inheritance
-       private var nop: Int = 0                # (NOP) Number of parents (direct superclasses)
-       private var nopc: Int = 0               # (NOPC) Number of class parents
-       private var nopi: Int = 0               # (NOPI) Number of interface parents
-       private var noa: Int = 0                # (NOA) Number of ancestors (direct and indirect)
-       private var noac: Int = 0               # (NOAC) Number of class ancestors
-       private var noai: Int = 0               # (NOAI) Number of interface ancestors
-       private var noc: Int = 0        # (NOC) Number of children (direct subclasses)
-       private var nocc: Int = 0               # (NOCC) Number of class children
-       private var noci: Int = 0               # (NOCI) Number of interface children
-       private var nod: Int = 0        # (NOD) Number of descendants (direct and indirect)
-       private var nodc: Int = 0               # (NODC) Number of class descendants
-       private var nodi: Int = 0               # (NODI) Number of interface descendants
-       private var dit: Int = 0                # (DIT) Depth in Inheritance Tree (maximum distance to root of the hierarchy)
-       private var ditc: Int = 0               # (DITC) Length of longest path to the root hierarchy and consisting only of extends edges
-       private var diti: Int = 0               # (DITI) Length of longest path to the root hierarchy and consisting only of extends implements
-
-       # User Defined inheritance
-       private var nopud: Int = 0              # (NOPUD) Number of parents (direct superclasses)
-       private var nopcud: Int = 0     # (NOPCUD) Number of class parents
-       private var nopiud: Int = 0             # (NOPIUD) Number of interface parents
-       private var noaud: Int = 0              # (NOAUD) Number of ancestors (direct and indirect)
-       private var noacud: Int = 0             # (NOACUD) Number of class ancestors
-       private var noaiud: Int = 0             # (NOAIUD) Number of interface ancestors
-       private var nocud: Int = 0      # (NOCUD) Number of children (direct subclasses)
-       private var noccud: Int = 0     # (NOCCUD) Number of class children
-       private var nociud: Int = 0             # (NOCIUD) Number of interface children
-       private var nodud: Int = 0      # (NODUD) Number of descendants (direct and indirect)
-       private var nodcud: Int = 0     # (NODCUD) Number of class descendants
-       private var nodiud: Int = 0             # (NODIUD) Number of interface descendants
-       private var ditud: Int = 0              # (DITUD) Depth in Inheritance Tree (maximum distance to root of the hierarchy)
-       private var ditcud: Int = 0             # (DITCUD) Length of longest path to the root hierarchy and consisting only of extends edges
-       private var ditiud: Int = 0             # (DITIUD) Length of longest path to the root hierarchy and consisting only of extends implements
-
-       private fun compute_class_inheritance_metrics(model: Model) do
-               # inheritance metrics
-               self.nop = parents.length
-               self.nopc = model.extract_classes(parents).length
-               self.nopi = model.extract_interfaces(parents).length
-               self.noa = ancestors.length
-               self.noac = model.extract_classes(ancestors).length
-               self.noai = model.extract_interfaces(ancestors).length
-               self.noc = children.length
-               self.nocc = model.extract_classes(children).length
-               self.noci = model.extract_interfaces(children).length
-               self.nod = descendants.length
-               self.nodc = model.extract_classes(descendants).length
-               self.nodi = model.extract_interfaces(descendants).length
-               self.dit = path_to_object.length
-               self.ditc = class_path_to_object.length
-               self.diti = interface_path_to_object.length
-
-               # used defined metrics
-               self.nopud = model.extract_user_defined(parents).length
-               self.nopcud = model.extract_user_defined(model.extract_classes(parents)).length
-               self.nopiud = model.extract_user_defined(model.extract_interfaces(parents)).length
-               self.noaud = model.extract_user_defined(ancestors).length
-               self.noacud = model.extract_user_defined(model.extract_classes(ancestors)).length
-               self.noaiud = model.extract_user_defined(model.extract_interfaces(ancestors)).length
-               self.nocud = model.extract_user_defined(children).length
-               self.noccud = model.extract_user_defined(model.extract_classes(children)).length
-               self.nociud = model.extract_user_defined(model.extract_interfaces(children)).length
-               self.nodud = model.extract_user_defined(descendants).length
-               self.nodcud = model.extract_user_defined(model.extract_classes(descendants)).length
-               self.nodiud = model.extract_user_defined(model.extract_interfaces(descendants)).length
-               self.ditud = ud_path_to_object.length
-               self.ditcud = ud_class_path_to_object.length
-               self.ditiud = ud_interface_path_to_object.length
-       end
+# An abstract metric used to collect data about inheritance usage
+#
+# The metric is based on a module
+abstract class InheritanceMetric
+       super FloatMetric[MModule]
+       fun collect(mmodule: MModule, mainmodule: MModule) is abstract
+end
 
-       # Return the longest path from class to root hierarchy
-       private fun path_to_object: Array[MClass] do
-               var path = new Array[MClass]
-               var max_dit: nullable Int = null
-               var max_parent: nullable MClass = null
-               var parent_path: nullable Array[MClass] = null
+# Module metric: proportion of MClasses Defined Using Inheritance
+#
+# Count MClasses that have another parents than Object
+class MDUI
+       super InheritanceMetric
+       redef fun name do return "mdui"
+       redef fun desc do return "proportion of mclass defined using inheritance (has other parent than Object)"
 
-               for p in parents do
-                       var dit = p.path_to_object.length
-                       if max_dit == null or dit >= max_dit then
-                               max_dit = dit
-                               max_parent = p
-                               parent_path = p.path_to_object
-                       end
+       redef fun collect(mmodule, mainmodule) do
+               var count = 0
+               for mclass in mmodule.intro_mclasses do
+                       if mclass.in_hierarchy(mainmodule).greaters.length > 2 then count += 1
                end
-
-               if max_parent != null and parent_path != null then
-                       path.add(max_parent)
-                       path.add_all(parent_path)
+               if mmodule.intro_mclasses.is_empty then
+                       values[mmodule] = 0.0
+               else
+                       values[mmodule] = count.to_f / mmodule.intro_mclasses.length.to_f
                end
-
-               return path
        end
+end
 
-       # Return the longest path from class to root hierarchy
-       private fun ud_path_to_object: Array[MClass] do
-               var path = new Array[MClass]
-               if not self.is_user_defined then return path
-               var max_dit: nullable Int = null
-               var max_parent: nullable MClass = null
-               var parent_path: nullable Array[MClass] = null
+# Module metric: proportion of abstract, concrete and extern Classes Defined Using Inheritance
+#
+# Count classes that have another parents than Object
+class MDUIC
+       super InheritanceMetric
+       redef fun name do return "mduic"
+       redef fun desc do return "proportion of class_kind defined using inheritance"
 
-               for p in parents do
-                       var dit = p.ud_path_to_object.length
-                       if max_dit == null or dit >= max_dit then
-                               max_dit = dit
-                               max_parent = p
-                               parent_path = p.ud_path_to_object
+       redef fun collect(mmodule, mainmodule) do
+               var count = 0
+               var nb = 0
+               for mclass in mmodule.intro_mclasses do
+                       if mclass.kind == abstract_kind or mclass.kind == concrete_kind or mclass.kind == extern_kind then
+                               if mclass.in_hierarchy(mainmodule).greaters.length > 2 then count += 1
                        end
+                       nb += 1
                end
-
-               if max_parent != null and parent_path != null then
-                       path.add(max_parent)
-                       path.add_all(parent_path)
+               if mmodule.intro_mclasses.is_empty then
+                       values[mmodule] = 0.0
+               else
+                       values[mmodule] = count.to_f / nb.to_f
                end
-
-               return path
        end
+end
 
-       # Return the longest path from class to root hierarchy following only classes relations
-       private fun class_path_to_object: Array[MClass] do
-               var path = new Array[MClass]
-               if not self.is_class then return path
-               var max_dit: nullable Int = null
-               var max_parent: nullable MClass = null
-               var parent_path: nullable Array[MClass] = null
+# Module metric: proportion of Interface Defined Using Inheritance
+#
+# Count interface that have another parents than Object
+class MDUII
+       super InheritanceMetric
+       redef fun name do return "mduii"
+       redef fun desc do return "proportion of interface_kind defined using inheritance"
 
-               for p in parents do
-                       var dit = p.class_path_to_object.length
-                       if max_dit == null or dit >= max_dit then
-                               max_dit = dit
-                               max_parent = p
-                               parent_path = p.class_path_to_object
+       redef fun collect(mmodule, mainmodule) do
+               var count = 0
+               var nb = 0
+               for mclass in mmodule.intro_mclasses do
+                       if mclass.kind == interface_kind then
+                               if mclass.in_hierarchy(mainmodule).greaters.length > 2 then count += 1
                        end
+                       nb += 1
                end
-
-               if max_parent != null and parent_path != null then
-                       path.add(max_parent)
-                       path.add_all(parent_path)
+               if mmodule.intro_mclasses.is_empty then
+                       values[mmodule] = 0.0
+               else
+                       values[mmodule] = count.to_f / nb.to_f
                end
-
-               return path
        end
+end
 
-       # Return the longest path from class to root hierarchy following only interfaces relations
-       private fun interface_path_to_object: Array[MClass] do
-               var path = new Array[MClass]
-               if not self.is_interface then return path
-               var max_dit: nullable Int = null
-               var max_parent: nullable MClass = null
-               var parent_path: nullable Array[MClass] = null
+# Module metric: proportion of MClass Inherited From
+#
+# Count classes that have at least a child
+class MIF
+       super InheritanceMetric
+       redef fun name do return "mif"
+       redef fun desc do return "proportion of mclass inherited from"
 
-               for p in parents do
-                       var dit = p.interface_path_to_object.length
-                       if max_dit == null or dit >= max_dit then
-                               max_dit = dit
-                               max_parent = p
-                               parent_path = p.interface_path_to_object
-                       end
+       redef fun collect(mmodule, mainmodule) do
+               var count = 0
+               for mclass in mmodule.intro_mclasses do
+                       if mclass.in_hierarchy(mainmodule).direct_smallers.length > 0 then count += 1
                end
-
-               if max_parent != null and parent_path != null then
-                       path.add(max_parent)
-                       path.add_all(parent_path)
+               if mmodule.intro_mclasses.is_empty then
+                       values[mmodule] = 0.0
+               else
+                       values[mmodule] = count.to_f / mmodule.intro_mclasses.length.to_f
                end
-
-               return path
        end
+end
 
-       # Return the longest path from class to root hierarchy following only ud classes relations
-       private fun ud_class_path_to_object: Array[MClass] do
-               var path = new Array[MClass]
-               if not self.is_class or not self.is_user_defined then return path
-               var max_dit: nullable Int = null
-               var max_parent: nullable MClass = null
-               var parent_path: nullable Array[MClass] = null
+# Module metric: proportion of abstract, concrete and extern Class Inherited From
+#
+# Count classes that have at least a child
+class MIFC
+       super InheritanceMetric
+       redef fun name do return "mifc"
+       redef fun desc do return "proportion of class_kind inherited from"
 
-               for p in parents do
-                       var dit = p.ud_class_path_to_object.length
-                       if max_dit == null or dit >= max_dit then
-                               max_dit = dit
-                               max_parent = p
-                               parent_path = p.ud_class_path_to_object
+       redef fun collect(mmodule, mainmodule) do
+               var count = 0
+               var nb = 0
+               for mclass in mmodule.intro_mclasses do
+                       if mclass.kind == abstract_kind or mclass.kind == concrete_kind or mclass.kind == extern_kind then
+                               if mclass.in_hierarchy(mainmodule).direct_smallers.length > 0 then count += 1
                        end
+                       nb += 1
                end
-
-               if max_parent != null and parent_path != null then
-                       path.add(max_parent)
-                       path.add_all(parent_path)
+               if mmodule.intro_mclasses.is_empty then
+                       values[mmodule] = 0.0
+               else
+                       values[mmodule] = count.to_f / nb.to_f
                end
-
-               return path
        end
+end
 
-       # Return the longest path from class to root hierarchy following only ud interfaces relations
-       private fun ud_interface_path_to_object: Array[MClass] do
-               var path = new Array[MClass]
-               if not self.is_interface or not self.is_user_defined then return path
-               var max_dit: nullable Int = null
-               var max_parent: nullable MClass = null
-               var parent_path: nullable Array[MClass] = null
+# Module metric: proportion of Interface Inherited From
+#
+# Count interfaces that have at least a child
+class MIFI
+       super InheritanceMetric
+       redef fun name do return "mifi"
+       redef fun desc do return "proportion of interface_kind inherited from"
 
-               for p in parents do
-                       var dit = p.ud_interface_path_to_object.length
-                       if max_dit == null or dit >= max_dit then
-                               max_dit = dit
-                               max_parent = p
-                               parent_path = p.ud_interface_path_to_object
+       redef fun collect(mmodule, mainmodule) do
+               var count = 0
+               var nb = 0
+               for mclass in mmodule.intro_mclasses do
+                       if mclass.kind == interface_kind then
+                               if mclass.in_hierarchy(mainmodule).direct_smallers.length > 0 then count += 1
                        end
+                       nb += 1
                end
-
-               if max_parent != null and parent_path != null then
-                       path.add(max_parent)
-                       path.add_all(parent_path)
+               if mmodule.intro_mclasses.is_empty then
+                       values[mmodule] = 0.0
+               else
+                       values[mmodule] = count.to_f / nb.to_f
                end
-
-               return path
        end
+end
 
-       # * -> * DUI
+# MClass metric: Number of Class Ancestors
+#
+# Count only absrtract, concrete and extern classes
+class CNOAC
+       super MClassMetric
+       redef fun name do return "cnoac"
+       redef fun desc do return "number of class_kind ancestor"
 
-       private fun is_dui_eligible: Bool do
-               for parent in parents do if parent.name != "Object" then return true
-               return false
-       end
-       private fun is_ccdui_eligible: Bool do
-               if not is_class then return false
-               for parent in parents do if parent.name != "Object" and parent.is_class then return true
-               return false
-       end
-       private fun is_cidui_eligible: Bool do
-               if not is_class then return false
-               for parent in parents do if parent.name != "Object" and parent.is_interface then return true
-               return false
-       end
-       private fun is_iidui_eligible: Bool do
-               if not is_interface then return false
-               for parent in parents do if parent.name != "Object" and parent.is_interface then return true
-               return false
-       end
-       private fun is_if_eligible(model: Model): Bool do return not children.is_empty
-       private fun is_ccif_eligible(model: Model): Bool do
-               if not is_class then return false
-               for child in children do if child.is_class then return true
-               return false
-       end
-       private fun is_icif_eligible(model: Model): Bool do
-               if not is_interface then return false
-               for child in children do if child.is_class then return true
-               return false
-       end
-       private fun is_iiif_eligible(model: Model): Bool do
-               if not is_interface then return false
-               for child in children do if child.is_interface then return true
-               return false
+       redef fun collect(mclass, mainmodule) do
+               var count = 0
+               for parent in mclass.in_hierarchy(mainmodule).greaters do
+                       if parent == mclass then continue
+                       if parent.kind == abstract_kind or parent.kind == concrete_kind or parent.kind == extern_kind then
+                               count += 1
+                       end
+               end
+               values[mclass] = count
        end
+end
 
-       # SL -> * DUI
+# MClass metric: Number of Class Parents
+#
+# Count only absrtract, concrete and extern classes
+class CNOPC
+       super MClassMetric
+       redef fun name do return "cnopc"
+       redef fun desc do return "number of class_kind parent"
 
-       private fun is_sldui_eligible: Bool do
-               if is_user_defined then return false
-               for parent in parents do if parent.name != "Object" then return true
-               return false
-       end
-       private fun is_slccdui_eligible: Bool do
-               if is_user_defined then return false
-               if not is_class then return false
-               for parent in parents do if parent.name != "Object" and parent.is_class then return true
-               return false
-       end
-       private fun is_slcidui_eligible: Bool do
-               if is_user_defined then return false
-               if not is_class then return false
-               for parent in parents do if parent.name != "Object" and parent.is_interface then return true
-               return false
-       end
-       private fun is_sliidui_eligible: Bool do
-               if is_user_defined then return false
-               if not is_interface then return false
-               for parent in parents do if parent.name != "Object" and parent.is_interface then return true
-               return false
-       end
-       private fun is_slif_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               return not children.is_empty
-       end
-       private fun is_slccif_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if not is_class then return false
-               for child in children do if child.is_class then return true
-               return false
-       end
-       private fun is_slicif_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if child.is_class then return true
-               return false
-       end
-       private fun is_sliiif_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if child.is_interface then return true
-               return false
+       redef fun collect(mclass, mainmodule) do
+               var count = 0
+               for parent in mclass.in_hierarchy(mainmodule).direct_greaters do
+                       if parent == mclass then continue
+                       if parent.kind == abstract_kind or parent.kind == concrete_kind or parent.kind == extern_kind then
+                               count += 1
+                       end
+               end
+               values[mclass] = count
        end
+end
 
-       # SL -> SL
+# MClass metric: Number of Class Children
+#
+# Count only absrtract, concrete and extern classes
+class CNOCC
+       super MClassMetric
+       redef fun name do return "cnocc"
+       redef fun desc do return "number of class_kind children"
 
-       private fun is_slifsl_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               for child in children do if not child.is_user_defined then return true
-               return false
-       end
-       private fun is_slccifsl_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if is_class then return false
-               for child in children do if not child.is_user_defined and child.is_class then return true
-               return false
-       end
-       private fun is_slicifsl_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if not child.is_user_defined and child.is_class then return true
-               return false
-       end
-       private fun is_sliiifsl_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if not child.is_user_defined and child.is_interface then return true
-               return false
+       redef fun collect(mclass, mainmodule) do
+               var count = 0
+               for parent in mclass.in_hierarchy(mainmodule).direct_smallers do
+                       if parent == mclass then continue
+                       if parent.kind == abstract_kind or parent.kind == concrete_kind or parent.kind == extern_kind then
+                               count += 1
+                       end
+               end
+               values[mclass] = count
        end
+end
 
-       # SL -> UD
+# MClass metric: Number of Class Descendants
+#
+# Count only absrtract, concrete and extern classes
+class CNODC
+       super MClassMetric
+       redef fun name do return "cnodc"
+       redef fun desc do return "number of class_kind descendants"
 
-       private fun is_slifud_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               for child in children do if child.is_user_defined then return true
-               return false
-       end
-       private fun is_slccifud_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if not is_class then return false
-               for child in children do if child.is_user_defined and child.is_class then return true
-               return false
-       end
-       private fun is_slicifud_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if child.is_user_defined and child.is_class then return true
-               return false
-       end
-       private fun is_sliiifud_eligible(model: Model): Bool do
-               if is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if child.is_user_defined and child.is_interface then return true
-               return false
+       redef fun collect(mclass, mainmodule) do
+               var count = 0
+               for parent in mclass.in_hierarchy(mainmodule).smallers do
+                       if parent == mclass then continue
+                       if parent.kind == abstract_kind or parent.kind == concrete_kind or parent.kind == extern_kind then
+                               count += 1
+                       end
+               end
+               values[mclass] = count
        end
+end
 
-       # UD -> *
+# MClass metric: Number of Interface Ancestors
+#
+# Count only interfaces
+class CNOAI
+       super MClassMetric
+       redef fun name do return "cnoai"
+       redef fun desc do return "number of interface_kind ancestor"
 
-       private fun is_uddui_eligible: Bool do
-               if not is_user_defined then return false
-               for parent in parents do if parent.name != "Object" then return true
-               return false
-       end
-       private fun is_udccdui_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_class then return false
-               for parent in parents do if parent.name != "Object" and parent.is_class then return true
-               return false
-       end
-       private fun is_udcidui_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_class then return false
-               for parent in parents do if parent.name != "Object" and parent.is_interface then return true
-               return false
-       end
-       private fun is_udiidui_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_interface then return false
-               for parent in parents do if parent.name != "Object" and parent.is_interface then return true
-               return false
-       end
-       private fun is_udif_eligible(model: Model): Bool do
-               if not is_user_defined then return false
-               return not children.is_empty
-       end
-       private fun is_udccif_eligible(model: Model): Bool do
-               if not is_user_defined then return false
-               if not is_class then return false
-               for child in children do if child.is_class then return true
-               return false
-       end
-       private fun is_udicif_eligible(model: Model): Bool do
-               if not is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if child.is_class then return true
-               return false
-       end
-       private fun is_udiiif_eligible(model: Model): Bool do
-               if not is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if child.is_interface then return true
-               return false
+       redef fun collect(mclass, mainmodule) do
+               var count = 0
+               for parent in mclass.in_hierarchy(mainmodule).greaters do
+                       if parent == mclass then continue
+                       if parent.kind == interface_kind then
+                               count += 1
+                       end
+               end
+               values[mclass] = count
        end
+end
 
-       # UD -> SL
+# MClass metric: Number of Interface Parents
+#
+# Count only interfaces
+class CNOPI
+       super MClassMetric
+       redef fun name do return "cnopi"
+       redef fun desc do return "number of interface_kind parent"
 
-       private fun is_udduisl_eligible: Bool do
-               if not is_user_defined then return false
-               for parent in parents do if not parent.is_user_defined and parent.name != "Object" then return true
-               return false
-       end
-       private fun is_udccduisl_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_class then return false
-               for parent in parents do if not parent.is_user_defined and parent.name != "Object" and parent.is_class then return true
-               return false
-       end
-       private fun is_udciduisl_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_class then return false
-               for parent in parents do if not parent.is_user_defined and parent.name != "Object" and parent.is_interface then return true
-               return false
-       end
-       private fun is_udiiduisl_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_interface then return false
-               for parent in parents do if not parent.is_user_defined and parent.name != "Object" and parent.is_interface then return true
-               return false
+       redef fun collect(mclass, mainmodule) do
+               var count = 0
+               for parent in mclass.in_hierarchy(mainmodule).direct_greaters do
+                       if parent == mclass then continue
+                       if parent.kind == interface_kind then
+                               count += 1
+                       end
+               end
+               values[mclass] = count
        end
+end
 
-       # UD -> UD
+# MClass metric: Number of Interface Children
+#
+# Count only interfaces
+class CNOCI
+       super MClassMetric
+       redef fun name do return "cnoci"
+       redef fun desc do return "number of interface_kind children"
 
-       private fun is_udduiud_eligible: Bool do
-               if not is_user_defined then return false
-               for parent in parents do if parent.name != "Object" and parent.is_user_defined then return true
-               return false
-       end
-       private fun is_udccduiud_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_class then return false
-               for parent in parents do if parent.name != "Object" and parent.is_class and parent.is_user_defined then return true
-               return false
-       end
-       private fun is_udciduiud_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_class then return false
-               for parent in parents do if parent.name != "Object" and parent.is_interface and parent.is_user_defined then return true
-               return false
-       end
-       private fun is_udiiduiud_eligible: Bool do
-               if not is_user_defined then return false
-               if not is_interface then return false
-               for parent in parents do if parent.name != "Object" and parent.is_interface and parent.is_user_defined then return true
-               return false
-       end
-       private fun is_udifud_eligible(model: Model): Bool do
-               if not is_user_defined then return false
-               return not children.is_empty
-       end
-       private fun is_udccifud_eligible(model: Model): Bool do
-               if not is_user_defined then return false
-               if not is_class then return false
-               for child in children do if child.is_user_defined and child.is_class then return true
-               return false
-       end
-       private fun is_udicifud_eligible(model: Model): Bool do
-               if not is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if child.is_user_defined and child.is_class then return true
-               return false
-       end
-       private fun is_udiiifud_eligible(model: Model): Bool do
-               if not is_user_defined then return false
-               if not is_interface then return false
-               for child in children do if child.is_user_defined and child.is_interface then return true
-               return false
+       redef fun collect(mclass, mainmodule) do
+               var count = 0
+               for parent in mclass.in_hierarchy(mainmodule).direct_smallers do
+                       if parent == mclass then continue
+                       if parent.kind == interface_kind then
+                               count += 1
+                       end
+               end
+               values[mclass] = count
        end
 end
 
-redef class MModule
-
-       private var nm: Int = 0                 # (NC)  Number of Modules
-       private var nc: Int = 0                 # (NC)  Number of Classes
-       private var ni: Int = 0                 # (NI)  Number of Interfaces
-       private var nac : Int = 0               # (NAC) Number of Abstract Classes
-       private var ngc : Int = 0               # (NGC) Number of Generic Classes
-       private var ngi : Int = 0               # (NGI) Number of Generic Interfaces
-
-       private var dit = ""                    # (DIT) Global Depth in Inheritance Tree
-       private var dui = ""                    # (DUI) Proportion of types that either implement an interface or extend another type other than Object
-       private var ccdui = ""                  # (CCDUI) Proportion of classes that extend some other class.
-       private var cidui = ""                  # (CIDUI) Proportion of classes that implement some other interface.
-       private var iidui = ""                  # (IIDUI) Proportion of interfaces that extend some other interface.
-       private var inhf = ""                   # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented
-       private var ccif = ""                   # (CCIF) Proportion of classes extended by some other class.
-       private var icif = ""                   # (ICIF) Proportion of interfaces implemented by some other class.
-       private var iiif = ""                   # (IIIF) Proportion of interfaces extended by some other interface.
+# MClass metric: Number of Interface Descendants
+#
+# Count only interfaces
+class CNODI
+       super MClassMetric
+       redef fun name do return "cnodi"
+       redef fun desc do return "number of interface_kind descendants"
 
-       private fun compute_module_inheritance_metrics(model: Model) do
-               var ditsum = 0
-               var dui_count = 0
-               var ccdui_count = 0
-               var cidui_count = 0
-               var iidui_count = 0
-               var if_count = 0
-               var ccif_count = 0
-               var icif_count = 0
-               var iiif_count = 0
+       redef fun collect(mclass, mainmodule) do
                var count = 0
-               for mmodule in self.in_nesting.greaters do
-                       for mclass in mmodule.intro_mclasses do
+               for parent in mclass.in_hierarchy(mainmodule).smallers do
+                       if parent == mclass then continue
+                       if parent.kind == interface_kind then
                                count += 1
-                               if mclass.is_class then nc += 1
-                               if mclass.is_class and mclass.arity > 0 then ngc += 1
-                               if mclass.is_class and mclass.is_abstract then nac += 1
-                               if mclass.is_interface then ni += 1
-                               if mclass.is_interface and mclass.arity > 0 then ngi += 1
-                               ditsum += mclass.path_to_object.length
-                               if mclass.is_dui_eligible then dui_count += 1
-                               if mclass.is_ccdui_eligible then ccdui_count += 1
-                               if mclass.is_cidui_eligible then cidui_count += 1
-                               if mclass.is_iidui_eligible then iidui_count += 1
-                               if mclass.is_if_eligible(model) then if_count += 1
-                               if mclass.is_ccif_eligible(model) then ccif_count += 1
-                               if mclass.is_icif_eligible(model) then icif_count += 1
-                               if mclass.is_iiif_eligible(model) then iiif_count += 1
                        end
                end
-
-               self.nm = self.in_nesting.greaters.length
-               dit = div(ditsum, count)
-               dui = div(dui_count * 100, count)
-               ccdui = div(ccdui_count * 100, nc)
-               cidui = div(cidui_count * 100, nc)
-               iidui = div(iidui_count * 100, ni)
-               inhf = div(if_count * 100, count)
-               ccif = div(ccif_count * 100, nc)
-               icif = div(icif_count * 100, ni)
-               iiif = div(iiif_count * 100, ni)
+               values[mclass] = count
        end
 end
 
-# Print inheritance usage metrics
-fun compute_inheritance_metrics(toolcontext: ToolContext, model: Model)
-do
-       # global summary metrics
-       var nmd: Int = 0                        # (NMD) Number of Modules
-       var nc: Int = 0                         # (NC)  Number of Classes
-       var ni: Int = 0                         # (NI)  Number of Interfaces
-       var nac : Int = 0                       # (NAC) Number of Abstract Classes
-       var ngc : Int = 0                       # (NGC) Number of Generic Classes
-       var ngi : Int = 0                       # (NGI) Number of Generic Interfaces
-       # (SL) Std-Lib summary metrics
-       var nmdsl: Int = 0                      # (NMDSL) Number of Modules in Std-Lib
-       var ncsl: Int = 0                       # (NCSL) Number of Classes in Std-Lib
-       var nisl: Int = 0                       # (NISL) Number of Interfaces in Std-Lib
-       var nacsl : Int = 0             # (NACSL) Number of Abstract Classes in Std-Lib
-       var ngcsl : Int = 0             # (NGCSL) Number of Generic Classes in Std-Lib
-       var ngisl : Int = 0             # (NGISL) Number of Generic Interfaces in Std-Lib
-       # (UD) User-Defined summary metrics
-       var nmdud: Int = 0                      # (NMDUD) Number of Modules User Defined
-       var ncud: Int = 0                       # (NCUD) Number of Classes User Defined
-       var niud: Int = 0                       # (NIUD) Number of Interfaces User Defined
-       var nacud : Int = 0                     # (NACUD) Number of Abstract Classes User Defined
-       var ngcud : Int = 0                     # (NGCUD) Number of Generic Classes User Defined
-       var ngiud : Int = 0                     # (NGIUD) Number of Generic Interfaces User Defined
-
-       # global summary inheritance metrics
-       var dit = ""                            # (DIT) Global Depth in Inheritance Tree
-       var dui = ""                            # (DUI) Proportion of types that either implement an interface or extend another type other than Object
-       var ccdui = ""                          # (CCDUI) Proportion of classes that extend some other class.
-       var cidui = ""                          # (CIDUI) Proportion of classes that implement some other interface.
-       var iidui = ""                          # (IIDUI) Proportion of interfaces that extend some other interface.
-       var inhf = ""                           # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented
-       var ccif = ""                           # (CCIF) Proportion of classes extended by some other class.
-       var icif = ""                           # (ICIF) Proportion of interfaces implemented by some other class.
-       var iiif = ""                           # (IIIF) Proportion of interfaces extended by some other interface.
-
-       # (SL -> *) Std-Lib summary inheritance metrics
-       var sldui = ""                          # (SLDUI) Proportion of std-lib types that either implement an interface or extend another std-lib type other than Object
-       var slccdui = ""                        # (SLCCDUI) Proportion of std-lib classes that extend some other std-lib class.
-       var slcidui = ""                        # (SLCIDUI) Proportion of std-lib classes that implement some other std-lib interface.
-       var sliidui = ""                        # (SLIIDUI) Proportion of std-lib interfaces that extend some other std-lib interface.
-       var slinhf = ""                         # (SLIF) Proportion of SL types Inherited From, that is, those types that are either extended or implemented
-       var slccif = ""                         # (SLCCIF) Proportion of SL classes extended by some other class.
-       var slicif = ""                         # (SLICIF) Proportion of SL interfaces implemented by some other class.
-       var sliiif = ""                         # (SLIIIF) Proportion of SL interfaces extended by some other interface.
-
-       # (SL -> SL) Std-Lib summary inheritance metrics
-       var slinhfsl = ""                               # (SLIFSL) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a SL type
-       var slccifsl = ""                               # (SLCCIFSL) Proportion of SL classes extended by some other SL class.
-       var slicifsl = ""                               # (SLICIFSL) Proportion of SL interfaces implemented by some other SL class.
-       var sliiifsl = ""                               # (SLIIIFSL) Proportion of SL interfaces extended by some other SL interface.
-
-       # (SL -> UD) Std-Lib summary inheritance metrics
-       var slinhfud = ""                               # (SLIFUD) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a UD type
-       var slccifud = ""                               # (SLCCIFUD) Proportion of SL classes extended by some other UD class.
-       var slicifud = ""                               # (SLICIFUD) Proportion of SL interfaces implemented by some other UD class.
-       var sliiifud = ""                               # (SLIIIFUD) Proportion of SL interfaces extended by some other UD interface.
-
-       # (UD -> *) User-defined summary inheritance metrics
-       var uddui = ""                          # (UDDUI) Proportion user-defined of types that either implement an interface or extend another type
-       var udccdui = ""                        # (UDCCDUI) Proportion of user-defined classes that extend some other class.
-       var udcidui = ""                        # (UDCIDUI) Proportion of user-defined classes that implement some other interface.
-       var udiidui = ""                        # (UDIIDUI) Proportion of user-defined interfaces that extend some other interface.
-       var udinhf = ""                         # (UDIF) Proportion of UD types Inherited From, that is, those types that are either extended or implemented
-       var udccif = ""                         # (UDCCIF) Proportion of UD classes extended by some other class.
-       var udicif = ""                         # (UDICIF) Proportion of UD interfaces implemented by some other class.
-       var udiiif = ""                         # (UDIIIF) Proportion of UD interfaces extended by some other interface.
-
-       # (UD -> SL) User-defined summary inheritance metrics
-       var udduisl = ""                        # (UDDUISL) Proportion user-defined of types that either implement an interface or extend another type SL
-       var udccduisl = ""                      # (UDCCDUISL) Proportion of user-defined classes that extend some other SL class.
-       var udciduisl = ""                      # (UDCIDUISL) Proportion of user-defined classes that implement some other SL interface.
-       var udiiduisl = ""                      # (UDIIDUISL) Proportion of user-defined interfaces that extend some other SL interface.
-
-       # (UD -> UD) User-defined summary inheritance metrics
-       var ditud = ""
-       var udduiud = ""                        # (UDDUIUD) Proportion user-defined of types that either implement an interface or extend another type user-defined
-       var udccduiud = ""                      # (UDCCDUIUD) Proportion of user-defined classes that extend some other user-defined class.
-       var udciduiud = ""                      # (UDCIDUIUD) Proportion of user-defined classes that implement some other user-defined interface.
-       var udiiduiud = ""                      # (UDIIDUIUD) Proportion of user-defined interfaces that extend some other user-defined interface.
-       var udinhfud = ""                       # (UDIFUD) Proportion of UD types Inherited From, that is, those types that are either extended or implemented by another UD type
-       var udccifud = ""                       # (UDCCIFUD) Proportion of UD classes extended by some other UD class.
-       var udicifud = ""                       # (UDICIFUD) Proportion of UD interfaces implemented by some other UD class.
-       var udiiifud = ""                       # (UDIIIFUD) Proportion of UD interfaces extended by some other UD interface.
-
-       # compute modules scalar metrics
-       for mmodule in model.mmodules do
-               mmodule.compute_module_inheritance_metrics(model)
-       end
+# MClass metric: Class Depth in Inheritance Tree
+#
+# Following the longest path composed only of extends edges from self to Object
+class CDITC
+       super MClassMetric
+       redef fun name do return "cditc"
+       redef fun desc do return "depth in class tree following only class, abstract, extern kind"
 
-       # compute class scalar metrics
-       for mclass in model.mclasses do
-               mclass.compute_class_inheritance_metrics(model)
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.ditc(mainmodule)
        end
+end
 
-       # compute summary metrics
-
-       # compute global summary metrics
-       nmd = model.mmodules.length
-       nc = model.extract_classes(model.mclasses).length
-       ni = model.extract_interfaces(model.mclasses).length
-       nac = model.extract_abstracts(model.mclasses).length
-       ngc = model.extract_generics(model.extract_classes(model.mclasses)).length
-       ngi = model.extract_generics(model.extract_interfaces(model.mclasses)).length
-       # compute std-lib summary metrics
-       nmdsl = model.extract_stdlib_modules(model.mmodules).length
-       ncsl = model.extract_stdlib(model.extract_classes(model.mclasses)).length
-       nisl = model.extract_stdlib(model.extract_interfaces(model.mclasses)).length
-       nacsl = model.extract_stdlib(model.extract_abstracts(model.mclasses)).length
-       ngcsl = model.extract_stdlib(model.extract_generics(model.extract_classes(model.mclasses))).length
-       ngisl = model.extract_stdlib(model.extract_generics(model.extract_interfaces(model.mclasses))).length
-       # compute user-defined summary metrics
-       nmdud = model.extract_user_defined_modules(model.mmodules).length
-       ncud = model.extract_user_defined(model.extract_classes(model.mclasses)).length
-       niud = model.extract_user_defined(model.extract_interfaces(model.mclasses)).length
-       nacud = model.extract_user_defined(model.extract_abstracts(model.mclasses)).length
-       ngcud = model.extract_user_defined(model.extract_generics(model.extract_classes(model.mclasses))).length
-       ngiud = model.extract_user_defined(model.extract_generics(model.extract_interfaces(model.mclasses))).length
-
-       # compute inheritance summary metrics
-
-       # * -> *
-       var ditsum = 0
-       var ditudsum = 0
-
-       var dui_count = 0
-       var ccdui_count = 0
-       var cidui_count = 0
-       var iidui_count = 0
-       var if_count = 0
-       var ccif_count = 0
-       var icif_count = 0
-       var iiif_count = 0
-
-       # SL -> *
-       var sldui_count = 0
-       var slccdui_count = 0
-       var slcidui_count = 0
-       var sliidui_count = 0
-       var slif_count = 0
-       var slccif_count = 0
-       var slicif_count = 0
-       var sliiif_count = 0
-
-       # SL -> SL
-       var slifsl_count = 0
-       var slccifsl_count = 0
-       var slicifsl_count = 0
-       var sliiifsl_count = 0
-
-       # SL -> UD
-       var slifud_count = 0
-       var slccifud_count = 0
-       var slicifud_count = 0
-       var sliiifud_count = 0
-
-       # UD -> *
-       var uddui_count = 0
-       var udccdui_count = 0
-       var udcidui_count = 0
-       var udiidui_count = 0
-       var udif_count = 0
-       var udccif_count = 0
-       var udicif_count = 0
-       var udiiif_count = 0
-
-       # UD -> SL
-       var udduisl_count = 0
-       var udccduisl_count = 0
-       var udciduisl_count = 0
-       var udiiduisl_count = 0
-
-       # UD -> UD
-       var udduiud_count = 0
-       var udccduiud_count = 0
-       var udciduiud_count = 0
-       var udiiduiud_count = 0
-       var udifud_count = 0
-       var udccifud_count = 0
-       var udicifud_count = 0
-       var udiiifud_count = 0
-
-       for mclass in model.mclasses do
-               ditsum += mclass.dit
-               ditudsum += mclass.ditud
-
-               # * -> *
-               if mclass.is_dui_eligible then dui_count += 1
-               if mclass.is_ccdui_eligible then ccdui_count += 1
-               if mclass.is_cidui_eligible then cidui_count += 1
-               if mclass.is_iidui_eligible then iidui_count += 1
-               if mclass.is_if_eligible(model) then if_count += 1
-               if mclass.is_ccif_eligible(model) then ccif_count += 1
-               if mclass.is_icif_eligible(model) then icif_count += 1
-               if mclass.is_iiif_eligible(model) then iiif_count += 1
-
-               # SL -> *
-               if mclass.is_sldui_eligible then sldui_count += 1
-               if mclass.is_slccdui_eligible then slccdui_count += 1
-               if mclass.is_slcidui_eligible then slcidui_count += 1
-               if mclass.is_sliidui_eligible then sliidui_count += 1
-               if mclass.is_slif_eligible(model) then slif_count += 1
-               if mclass.is_slccif_eligible(model) then slccif_count += 1
-               if mclass.is_slicif_eligible(model) then slicif_count += 1
-               if mclass.is_sliiif_eligible(model) then sliiif_count += 1
-
-               # SL -> SL
-               if mclass.is_slifsl_eligible(model) then slifsl_count += 1
-               if mclass.is_slccifsl_eligible(model) then slccifsl_count += 1
-               if mclass.is_slicifsl_eligible(model) then slicifsl_count += 1
-               if mclass.is_sliiifsl_eligible(model) then sliiifsl_count += 1
-
-               # SL -> UD
-               if mclass.is_slifud_eligible(model) then slifud_count += 1
-               if mclass.is_slccifud_eligible(model) then slccifud_count += 1
-               if mclass.is_slicifud_eligible(model) then slicifud_count += 1
-               if mclass.is_sliiifud_eligible(model) then sliiifud_count += 1
-
-               # UD -> *
-               if mclass.is_uddui_eligible then uddui_count += 1
-               if mclass.is_udccdui_eligible then udccdui_count += 1
-               if mclass.is_udcidui_eligible then udcidui_count += 1
-               if mclass.is_udiidui_eligible then udiidui_count += 1
-               if mclass.is_udif_eligible(model) then udif_count += 1
-               if mclass.is_udccif_eligible(model) then udccif_count += 1
-               if mclass.is_udicif_eligible(model) then udicif_count += 1
-               if mclass.is_udiiif_eligible(model) then udiiif_count += 1
-
-               # UD -> SL
-               if mclass.is_udduisl_eligible then udduisl_count += 1
-               if mclass.is_udccduisl_eligible then udccduisl_count += 1
-               if mclass.is_udciduisl_eligible then udciduisl_count += 1
-               if mclass.is_udiiduisl_eligible then udiiduisl_count += 1
+# MClass metric: Interface Depth in Inheritance Tree
+#
+# Following the longest path composed only of implements edges from self to Object
+class CDITI
+       super MClassMetric
+       redef fun name do return "cditi"
+       redef fun desc do return "depth in class tree following only interface_kind"
 
-               # UD -> UD
-               if mclass.is_udduiud_eligible then udduiud_count += 1
-               if mclass.is_udccduiud_eligible then udccduiud_count += 1
-               if mclass.is_udciduiud_eligible then udciduiud_count += 1
-               if mclass.is_udiiduiud_eligible then udiiduiud_count += 1
-               if mclass.is_udifud_eligible(model) then udifud_count += 1
-               if mclass.is_udccifud_eligible(model) then udccifud_count += 1
-               if mclass.is_udicifud_eligible(model) then udicifud_count += 1
-               if mclass.is_udiiifud_eligible(model) then udiiifud_count += 1
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.diti(mainmodule)
        end
+end
 
-       # * -> *
-       dit = div(ditsum, model.mclasses.length)
-       ditud = div(ditudsum, ncud + niud)
-       dui = div(dui_count * 100, model.mclasses.length)
-       ccdui = div(ccdui_count * 100, nc)
-       cidui = div(cidui_count * 100, nc)
-       iidui = div(iidui_count * 100, ni)
-       inhf = div(if_count * 100, nc + ni)
-       ccif = div(ccif_count * 100, nc)
-       icif = div(icif_count * 100, ni)
-       iiif = div(iiif_count * 100, ni)
-
-       # SL -> *
-       sldui = div(sldui_count * 100, ncsl + nisl)
-       slccdui = div(slccdui_count * 100, ncsl)
-       slcidui = div(slcidui_count * 100, ncsl)
-       sliidui = div(sliidui_count * 100, nisl)
-       slinhf = div(slif_count * 100, ncsl + nisl)
-       slccif = div(slccif_count * 100, ncsl)
-       slicif = div(slicif_count * 100, nisl)
-       sliiif = div(sliiif_count * 100, nisl)
-
-       # SL -> SL
-       slinhfsl = div(slifsl_count * 100, ncsl + nisl)
-       slccifsl = div(slccifsl_count * 100, ncsl)
-       slicifsl = div(slicifsl_count * 100, nisl)
-       sliiifsl = div(sliiifsl_count * 100, nisl)
-
-       # SL -> UD
-       slinhfud = div(slifud_count * 100, ncsl + nisl)
-       slccifud = div(slccifud_count * 100, ncsl)
-       slicifud = div(slicifud_count * 100, nisl)
-       sliiifud = div(sliiifud_count * 100, nisl)
-
-       # UD -> *
-       uddui = div(uddui_count * 100, ncud + niud)
-       udccdui = div(udccdui_count * 100, ncud)
-       udcidui = div(udcidui_count * 100, ncud)
-       udiidui = div(udiidui_count * 100, niud)
-       udinhf = div(if_count * 100, ncud + niud)
-       udccif = div(ccif_count * 100, ncud)
-       udicif = div(icif_count * 100, niud)
-       udiiif = div(iiif_count * 100, niud)
-
-       # UD -> SL
-       udduisl = div(udduisl_count * 100, ncud + niud)
-       udccduisl = div(udccduisl_count * 100, ncud)
-       udciduisl = div(udciduisl_count * 100, ncud)
-       udiiduisl = div(udiiduisl_count * 100, niud)
-
-       # UD -> UD
-       udduiud = div(udduiud_count * 100, ncud + niud)
-       udccduiud = div(udccduiud_count * 100, ncud)
-       udciduiud = div(udciduiud_count * 100, ncud)
-       udiiduiud = div(udiiduiud_count * 100, niud)
-       udinhfud = div(udifud_count * 100, ncud + niud)
-       udccifud = div(udccifud_count * 100, ncud)
-       udicifud = div(udicifud_count * 100, niud)
-       udiiifud = div(udiiifud_count * 100, niud)
+# model redef
 
-       # CSV generation
-       if toolcontext.opt_generate_csv.value then
-               # summary_metrics
-               var summaryCSV = new CSVDocument(toolcontext.output_dir.join_path("summary_metrics.csv"))
-               summaryCSV.set_header("scope", "NMD", "NC", "NI", "NAC", "NGC", "NGI")
-               summaryCSV.add_line("global", nmd, nc, ni, nac, ngc, ngi)
-               summaryCSV.add_line("std-lib", nmdsl, ncsl, nisl, nacsl, ngcsl, ngisl)
-               summaryCSV.add_line("user-defined", nmdud, ncud, niud, nacud, ngcud, ngiud)
-               for m in model.mmodules do
-                       summaryCSV.add_line(m.name, m.nm, m.nc, m.ni, m.nac, m.ngc, m.ngi)
+redef class MClass
+               
+       # Class Depth in Inheritance Tree
+       #
+       # Following the longest path composed only of extends edges from self to Object
+       fun ditc(mainmodule: MModule): Int do
+               if in_hierarchy(mainmodule).direct_greaters.is_empty then
+                       return 0
                end
-               summaryCSV.save
-
-               # inheritance metrics
-               var inheritanceCSV = new CSVDocument(toolcontext.output_dir.join_path("inheritance_metrics.csv"))
-               inheritanceCSV.set_header("scope", "DIT", "DUI", "CCDUI", "CIDUI", "IIDUI", "IF", "CCIF", "ICIF", "IIIF")
-               inheritanceCSV.add_line("global", dit, dui, ccdui, cidui, iidui, inhf, ccif, icif, iiif)
-               inheritanceCSV.add_line("SL -> *", "", sldui, slccdui, slcidui, sliidui, slinhf, slccif, slicif, sliiif)
-               inheritanceCSV.add_line("SL -> SL", "", sldui, slccdui, slcidui, sliidui, slinhfsl, slccifsl, slicifsl, sliiifsl)
-               inheritanceCSV.add_line("SL -> UD", "", 0, 0, 0, 0, slinhfud, slccifud, slicifud, sliiifud)
-               inheritanceCSV.add_line("UD -> *", "", uddui, udccdui, udcidui, udiidui, udinhf, udccif, udicif, udiiif)
-               inheritanceCSV.add_line("UD -> SL", "", udduisl, udccduisl, udciduisl, udiiduisl, 0, 0, 0, 0)
-               inheritanceCSV.add_line("UD -> UD", ditud, udduiud, udccduiud, udciduiud, udiiduiud, udinhfud, udccifud, udicifud, udiiifud)
-               for m in model.mmodules do
-                       if m.intro_mclasses.is_empty and m.in_nesting.greaters.length == 1 then continue
-                       inheritanceCSV.add_line(m.name, m.dit, m.dui, m.ccdui, m.cidui, m.iidui, m.inhf, m.ccif, m.icif, m.iiif)
+               var min = -1
+               for p in in_hierarchy(mainmodule).direct_greaters do
+                       if p.kind != abstract_kind and p.kind != concrete_kind and p.kind != extern_kind then continue
+                       var d = p.ditc(mainmodule) + 1
+                       if min == -1 or d < min then
+                               min = d
+                       end
                end
-               inheritanceCSV.save
+               if min == -1 then min = 0
+               return min
+       end
 
-               # scalar metrics
-               var scalarCSV = new CSVDocument(toolcontext.output_dir.join_path("global_scalar_metrics.csv"))
-               var udscalarCSV = new CSVDocument(toolcontext.output_dir.join_path("ud_scalar_metrics.csv"))
-               scalarCSV.set_header("mclass", "type", "FT", "DIT", "DITC", "DITI", "NOP", "NOPC", "NOPI", "NOA", "NOAC", "NOAI", "NOC", "NOCC", "NOCI", "NOD", "NODC", "NODI")
-               udscalarCSV.set_header("mclass", "type", "FT","DITUD", "DITCUD", "DITIUD", "NOPUD", "NOPCUD", "NOPIUD", "NOAUD", "NOACUD", "NOAIUD", "NOCUD", "NOCCUD", "NOCIUD", "NODUD", "NODCUD", "NODIUD")
-               for mclass in model.mclasses do
-                       var name = mclass.name
-                       var typ = "class"
-                       if mclass.is_interface then typ = "interface"
-                       scalarCSV.add_line(name, typ, mclass.arity, mclass.dit, mclass.ditc, mclass.diti, mclass.nop, mclass.nopc, mclass.nopi, mclass.noa, mclass.noac, mclass.noai, mclass.noc, mclass.nocc, mclass.noci, mclass.nod, mclass.nodc, mclass.nodi)
-                       udscalarCSV.add_line(name, typ, mclass.arity, mclass.ditud, mclass.ditcud, mclass.ditiud, mclass.nopud, mclass.nopcud, mclass.nopiud, mclass.noaud, mclass.noacud, mclass.noaiud, mclass.nocud, mclass.noccud, mclass.nociud, mclass.nodud, mclass.nodcud, mclass.nodiud)
+       # Interface Depth in Inheritance Tree
+       #
+       # Following the longest path composed only of implements edges from self to Object
+       fun diti(mainmodule: MModule): Int do
+               if in_hierarchy(mainmodule).direct_greaters.is_empty then
+                       return 0
                end
-               scalarCSV.save
-               udscalarCSV.save
+               var min = -1
+               for p in in_hierarchy(mainmodule).direct_greaters do
+                       if p.kind != interface_kind then continue
+                       var d = p.diti(mainmodule) + 1
+                       if min == -1 or d < min then
+                               min = d
+                       end
+               end
+               if min == -1 then min = 0
+               return min
        end
-
-       print "--- Global Summary metrics ---"
-       print "(NMD) Number of Modules: {nmd}"
-       print "(NC)  Number of Classes: {nc}"
-       print "(NI)  Number of Interfaces: {ni}"
-       print "(NAC)  Number of Abstract Classes: {nac}"
-       print "(NGC)  Number of Generic Classes: {ngc}"
-       print "(NGI)  Number of Generic Interfaces: {ngi}"
-       print "--- (SL) Std-Lib Summary metrics ---"
-       print "(NMDSL) Number of Modules: {nmdsl}"
-       print "(NCSL)  Number of Classes: {ncsl}"
-       print "(NISL)  Number of Interfaces: {nisl}"
-       print "(NACSL)  Number of Abstract Classes: {nacsl}"
-       print "(NGCSL)  Number of Generic Classes: {ngcsl}"
-       print "(NGISL)  Number of Generic Interfaces: {ngisl}"
-       print "--- (UD) User-Defined Summary metrics ---"
-       print "(NMDUD) Number of Modules: {nmdud}"
-       print "(NCUD)  Number of Classes: {ncud}"
-       print "(NIUD)  Number of Interfaces: {niud}"
-       print "(NACUD)  Number of Abstract Classes: {nacud}"
-       print "(NGCUD)  Number of Generic Classes: {ngcud}"
-       print "(NGIUD)  Number of Generic Interfaces: {ngiud}"
-       print ""
-       print "--- Global Inheritance metrics ---"
-       print "(DIT) Global Depth in Inheritance Tree: {dit}"
-       print "(DUI) Proportion of types inheriting another type other than Object: {dui}%"
-       print "(CCDUI) Proportion of classes that extend some other class: {ccdui}%"
-       print "(CIDUI) Proportion of classes that implement some other interface: {cidui}%"
-       print "(IIDUI) Proportion of interfaces that extend some other interface: {iidui}%"
-       print "(IF) Proportion of types Inherited From: {inhf}%"
-       print "(CCIF) Proportion of classes extended by class: {ccif}%"
-       print "(ICIF) Proportion of interfaces implemented by class: {icif}%"
-       print "(IIIF) Proportion of interfaces extended by interface: {iiif}%"
-       print ""
-       print "--- (SL -> *) Std-Lib Inheritance metrics ---"
-       print "(SLDUI) Proportion of SL types inheriting another type other than Object: {sldui}%"
-       print "(SLCCDUI) Proportion of SL classes that extend some other class: {slccdui}%"
-       print "(SLCIDUI) Proportion of SL classes that implement some other interface: {slcidui}%"
-       print "(SLIIDUI) Proportion of SL interfaces that extend some other interface: {sliidui}%"
-       print "(SLIF) Proportion of SL types Inherited From: {slinhf}%"
-       print "(SLCCIF) Proportion of SL classes extended by class: {slccif}%"
-       print "(SLICIF) Proportion of SL interfaces implemented by class: {slicif}%"
-       print "(SLIIIF) Proportion of SL interfaces extended by interface: {sliiif}%"
-       print ""
-       print "--- (SL -> SL) Std-Lib Inheritance metrics ---"
-       print "(SLIFSL) Proportion of SL types Inherited From by SL type: {slinhfsl}%"
-       print "(SLCCIFSL) Proportion of SL classes extended by SL class: {slccifsl}%"
-       print "(SLICIFSL) Proportion of SL interfaces implemented by SL class: {slicifsl}%"
-       print "(SLIIIFSL) Proportion of SL interfaces extended by SL interface: {sliiifsl}%"
-       print ""
-       print "--- (SL->UD) Std-Lib Inheritance metrics ---"
-       print "(SLIFUD) Proportion of SL types Inherited From by UD type: {slinhfud}%"
-       print "(SLCCIFUD) Proportion of SL classes extended by UD class: {slccifud}%"
-       print "(SLICIFUD) Proportion of SL interfaces implemented by UD class: {slicifud}%"
-       print "(SLIIIFUD) Proportion of SL interfaces extended by UD interface: {sliiifud}%"
-       print ""
-       print "--- (UD->*) User-Defined Inheritance metrics ---"
-       print "(UDDUI) Proportion of UD types inheriting another type other than Object: {uddui}%"
-       print "(UDCCDUI) Proportion of UD classes that extend some other class: {udccdui}%"
-       print "(UDCIDUI) Proportion of UD classes that implement some other interface: {udcidui}%"
-       print "(UDIIDUI) Proportion of UD interfaces that extend some other interface: {udiidui}%"
-       print "(UDIF) Proportion of UD types Inherited From: {udinhf}%"
-       print "(UDCCIF) Proportion of UD classes extended by class: {udccif}%"
-       print "(UDICIF) Proportion of UD interfaces implemented by class: {udicif}%"
-       print "(UDIIIF) Proportion of UD interfaces extended by interface: {udiiif}%"
-       print ""
-       print "--- (UD -> SL) User-Defined Inheritance metrics ---"
-       print "(UDDUISL) Proportion of UD types inheriting another type other SL type: {udduisl}%"
-       print "(UDCCDUISL) Proportion of UD classes that extend some other SL class: {udccduisl}%"
-       print "(UDCIDUISL) Proportion of UD classes that implement some other SL interface: {udciduisl}%"
-       print "(UDIIDUISL) Proportion of UD interfaces that extend some other SL interface: {udiiduisl}%"
-       print ""
-       print "--- (UD -> UD) User-Defined Inheritance metrics ---"
-       print "(UDDUIUD) Proportion of UD types inheriting another type other UD type: {udduiud}%"
-       print "(UDCCDUIUD) Proportion of UD classes that extend some other UD class: {udccduiud}%"
-       print "(UDCIDUIUD) Proportion of UD classes that implement some other UD interface: {udciduiud}%"
-       print "(UDIIDUIUD) Proportion of UD interfaces that extend some other UD interface: {udiiduiud}%"
-       print "(UDIFUD) Proportion of UD types Inherited From: {udinhfud}%"
-       print "(UDCCIFUD) Proportion of UD classes extended by UD class: {udccifud}%"
-       print "(UDICIFUD) Proportion of UD interfaces implemented by UD class: {udicifud}%"
-       print "(UDIIIFUD) Proportion of UD interfaces extended by UD interface: {udiiifud}%"
 end
 
-# TODO Third-Party metrics
-# TODO gnu-plot generation
diff --git a/src/metrics/mclasses_metrics.nit b/src/metrics/mclasses_metrics.nit
new file mode 100644 (file)
index 0000000..c48cb35
--- /dev/null
@@ -0,0 +1,231 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexandre Terrasa <alexandre@moz-code.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Collect common metrics about mclasses
+module mclasses_metrics
+
+import model
+import metrics_base
+import phase
+import frontend
+
+redef class ToolContext
+       var mclasses_metrics_phase = new MClassesMetricsPhase(self, null)
+end
+
+# Extract metrics about mclasses from model.
+private class MClassesMetricsPhase
+       super Phase
+       redef fun process_mainmodule(mainmodule)
+       do
+               if not toolcontext.opt_mclasses.value and not toolcontext.opt_all.value then return
+
+               print toolcontext.format_h1("\n# MClasses metrics")
+
+               var metrics = new MClassMetricSet
+               metrics.register(new CNOA, new CNOP, new CNOC, new CNOD, new CDIT)
+               metrics.register(new CNBIP, new CNBRP, new CNBHP)
+               #TODO metrics.register(new CNBI) # nb init
+               #TODO metrics.register(new CNBA) # nb attrs
+               #TODO metrics.register(new CNBM) # nb methods
+               #TODO metrics.register(new CNBV) # nb vtypes
+
+               var model = toolcontext.modelbuilder.model
+               var mclasses = new HashSet[MClass]
+               for mproject in model.mprojects do
+
+                       print toolcontext.format_h2("\n ## project {mproject}")
+
+                       for mgroup in mproject.mgroups do
+                               if mgroup.mmodules.is_empty then continue
+
+                               # Scalar metrics
+                               print toolcontext.format_h3("  `- group {mgroup.full_name}")
+
+                               var mod_mclasses = new HashSet[MClass]
+                               for mmodule in mgroup.mmodules do mod_mclasses.add_all(mmodule.intro_mclasses)
+                               if mod_mclasses.is_empty then continue
+                               mclasses.add_all(mod_mclasses)
+                               metrics.collect(new HashSet[MClass].from(mod_mclasses), mainmodule)
+                               for name, metric in metrics.metrics do
+                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                       print toolcontext.format_p("\t    avg: {metric.avg}")
+                                       var max = metric.max
+                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                       var min = metric.min
+                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               end
+                       end
+               end
+               if not mclasses.is_empty then
+                       # Global metrics
+                       print toolcontext.format_h2("\n ## global metrics")
+
+                       metrics.collect(mclasses, mainmodule)
+                       for name, metric in metrics.metrics do
+                               print toolcontext.format_h4("\t{name}: {metric.desc}")
+                               print toolcontext.format_p("\t    avg: {metric.avg}")
+                               var max = metric.max
+                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                               var min = metric.min
+                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                       end
+               end
+       end
+end
+
+# An MetricSet for MClasses metrics
+class MClassMetricSet
+       super MetricSet
+       redef type METRIC: MClassMetric
+
+       # Collect all the metrics on the set of MClasses
+       fun collect(mclasses: Set[MClass], mainmodule: MModule) do
+               clear
+               for metric in metrics.values do
+                       for mclass in mclasses do
+                               metric.collect(mclass, mainmodule)
+                       end
+               end
+       end
+end
+
+# An abstract metric about MClass
+abstract class MClassMetric
+       super IntMetric[MClass]
+       # Collect the metric value for this mclass
+       fun collect(mclass: MClass, mainmodule: MModule) is abstract
+end
+
+# Class Metric: Number of Ancestors
+class CNOA
+       super MClassMetric
+       redef fun name do return "cnoa"
+       redef fun desc do return "number of ancestor classes"
+
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.in_hierarchy(mainmodule).greaters.length - 1
+       end
+end
+
+# Class Metric: Number of Parents
+class CNOP
+       super MClassMetric
+       redef fun name do return "cnop"
+       redef fun desc do return "number of parent classes"
+
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.in_hierarchy(mainmodule).direct_greaters.length
+       end
+end
+
+# Class Metric: Number of Children
+class CNOC
+       super MClassMetric
+       redef fun name do return "cnoc"
+       redef fun desc do return "number of child classes"
+
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.in_hierarchy(mainmodule).direct_smallers.length
+       end
+end
+
+# Class Metric: Number of Descendants
+class CNOD
+       super MClassMetric
+       redef fun name do return "cnod"
+       redef fun desc do return "number of descendant classes"
+
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.in_hierarchy(mainmodule).smallers.length - 1
+       end
+end
+
+# Class Metric: Depth in Inheritance Tree
+class CDIT
+       super MClassMetric
+       redef fun name do return "cdit"
+       redef fun desc do return "depth in class tree"
+
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.in_hierarchy(mainmodule).depth
+       end
+end
+
+# Class Metric: Number of Introduced MProperties
+class CNBIP
+       super MClassMetric
+       redef fun name do return "cnbip"
+       redef fun desc do return "number of introduced properties"
+
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.intro_mproperties.length
+       end
+end
+
+# Class Metric: Number of Refined MProperties
+class CNBRP
+       super MClassMetric
+       redef fun name do return "cnbrp"
+       redef fun desc do return "number of redefined properties"
+
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.redef_mproperties.length
+       end
+end
+
+# Class Metric: Number of Inherited MProperties
+class CNBHP
+       super MClassMetric
+       redef fun name do return "cnbhp"
+       redef fun desc do return "number of inherited properties"
+
+       redef fun collect(mclass, mainmodule) do
+               values[mclass] = mclass.inherited_mproperties2(mainmodule).length
+       end
+end
+
+redef class MClass
+       # FIXME wait for cleaning in model_utils
+       redef fun intro_mproperties: Set[MProperty] do
+               var set = new HashSet[MProperty]
+               for mclassdef in mclassdefs do
+                       set.add_all(mclassdef.intro_mproperties)
+               end
+               return set
+       end
+
+       # FIXME wait for cleaning in model_utils
+       redef fun redef_mproperties: Set[MProperty] do
+               var set = new HashSet[MProperty]
+               for mclassdef in mclassdefs do
+                       for mpropdef in mclassdef.mpropdefs do
+                               if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
+                       end
+               end
+               return set
+       end
+
+       # FIXME wait for cleaning in model_utils
+       fun inherited_mproperties2(mainmodule: MModule): Set[MProperty] do
+               var set = new HashSet[MProperty]
+               for parent in in_hierarchy(mainmodule).direct_greaters do
+                       set.add_all(parent.intro_mproperties)
+                       set.add_all(parent.inherited_mproperties2(mainmodule))
+               end
+               return set
+       end
+end
index c1f1830..3d693af 100644 (file)
@@ -18,6 +18,8 @@
 module metrics
 
 import metrics_base
+import mmodules_metrics
+import mclasses_metrics
 import inheritance_metrics
 import refinement_metrics
 import static_types_metrics
index c68947b..77878a9 100644 (file)
@@ -1,6 +1,7 @@
 # This file is part of NIT ( http://www.nitlanguage.org ).
 #
 # Copyright 2012 Jean Privat <jean@pryen.org>
+# Copyright 2014 Alexandre Terrasa <alexandre@moz-code.org>
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -20,12 +21,18 @@ module metrics_base
 import model_utils
 import csv
 import counter
+import console
 
 redef class ToolContext
 
        # --all
        var opt_all = new OptionBool("Compute all metrics", "--all")
 
+       # --mmodules
+       var opt_mmodules = new OptionBool("Compute metrics about mmodules", "--mmodules")
+       # --mclassses
+       var opt_mclasses = new OptionBool("Compute metrics about mclasses", "--mclasses")
+
        # --inheritance
        var opt_inheritance = new OptionBool("Compute metrics about inheritance usage", "--inheritance")
        # --genericity
@@ -49,6 +56,10 @@ redef class ToolContext
        # --poset
        var opt_poset = new OptionBool("Complete metrics on posets", "--poset")
 
+       # --no-colors
+       var opt_nocolors = new OptionBool("Disable colors in console outputs", "--no-colors")
+
+
        var opt_dir = new OptionString("Directory where some statistics files are generated", "-d", "--dir")
        var output_dir: String = "."
 
@@ -56,6 +67,8 @@ redef class ToolContext
        do
                super
                self.option_context.add_option(opt_all)
+               self.option_context.add_option(opt_mmodules)
+               self.option_context.add_option(opt_mclasses)
                self.option_context.add_option(opt_inheritance)
                self.option_context.add_option(opt_refinement)
                self.option_context.add_option(opt_self)
@@ -68,6 +81,7 @@ redef class ToolContext
                self.option_context.add_option(opt_generate_hyperdoc)
                self.option_context.add_option(opt_poset)
                self.option_context.add_option(opt_dir)
+               self.option_context.add_option(opt_nocolors)
        end
 
        redef fun process_options
@@ -80,48 +94,150 @@ redef class ToolContext
                        self.output_dir = val
                end
        end
-end
 
-redef class Model
-
-       # List of modules in std lib
-       # FIXME this is quite ugly, find a dynamic way...
-       fun std_modules: Set[String] do
-               if self.std_modules_cache == null then
-                       self.std_modules_cache = new HashSet[String]
-                       self.std_modules_cache.add("collection")
-                       self.std_modules_cache.add("abstract_collection")
-                       self.std_modules_cache.add("array")
-                       self.std_modules_cache.add("hash_collection")
-                       self.std_modules_cache.add("list")
-                       self.std_modules_cache.add("range")
-                       self.std_modules_cache.add("sorter")
-                       self.std_modules_cache.add("environ")
-                       self.std_modules_cache.add("exec")
-                       self.std_modules_cache.add("file")
-                       self.std_modules_cache.add("gc")
-                       self.std_modules_cache.add("hash")
-                       self.std_modules_cache.add("kernel")
-                       self.std_modules_cache.add("math")
-                       self.std_modules_cache.add("standard")
-                       self.std_modules_cache.add("stream")
-                       self.std_modules_cache.add("string")
-                       self.std_modules_cache.add("string_search")
-                       self.std_modules_cache.add("time")
-               end
-               return self.std_modules_cache.as(not null)
+       # colorize heading 1 for console output
+       fun format_h1(str: String): String do
+               if opt_nocolors.value then return str
+               return str.yellow.bold
+       end
+
+       fun format_h2(str: String): String do
+               if opt_nocolors.value then return str
+               return str.bold
+       end
+
+       fun format_h3(str: String): String do
+               if opt_nocolors.value then return str
+               return str
+       end
+
+       fun format_h4(str: String): String do
+               if opt_nocolors.value then return str
+               return str.green
+       end
+
+       fun format_p(str: String): String do
+               if opt_nocolors.value then return str
+               return str.light_gray
        end
-       private var std_modules_cache: nullable Set[String]
+
 end
 
 redef class MClass
-       fun is_user_defined: Bool do
-               return self.intro_mmodule.is_user_defined
+       # is the class imported from standard lib?
+       fun is_standard: Bool do
+               return self.intro_mmodule.mgroup.mproject.name == "standard"
        end
 end
 
 redef class MModule
-       fun is_user_defined: Bool do
-               return not self.model.std_modules.has(self.name)
+       # is the module imported from standard lib?
+       fun is_standard: Bool do
+               return self.mgroup.mproject.name == "standard"
+       end
+end
+
+# A Metric is used to collect data about things
+#
+# The concept is reified here for a better organization and documentation
+interface Metric
+       fun name: String is abstract
+       fun desc: String is abstract
+       # clear all results for this metric
+       fun clear is abstract
+end
+
+# A Metric that collects integer data
+#
+# Used to count things
+class IntMetric[E: Object]
+       super Metric
+
+       var values = new Counter[E]
+
+       redef fun clear do values.clear
+
+       # Return the couple with the highest value
+       fun max: Couple[E, Int] do
+               assert not values.is_empty
+               var elem = values.max.as(not null)
+               var value = values[elem]
+               return new Couple[E, Int](elem, value)
        end
+
+       # Return the couple with the lowest value
+       fun min: Couple[E, Int] do
+               assert not values.is_empty
+               var elem = values.min.as(not null)
+               var value = values[elem]
+               return new Couple[E, Int](elem, value)
+       end
+
+       # Values average
+       fun avg: Float do return values.avg
+end
+
+# A Metric that collects float datas
+#
+# Used sor summarization
+class FloatMetric[E: Object]
+       super Metric
+
+       var values: Map[E, Float] = new HashMap[E, Float]
+
+       redef fun clear do values.clear
+
+       # Return the couple with the highest value
+       fun max: Couple[E, Float] do
+               assert not values.is_empty
+               var max: nullable Float = null
+               var elem: nullable E = null
+               for e, v in values do
+                       if max == null or v > max then
+                               max = v
+                               elem = e
+                       end
+               end
+               return new Couple[E, Float](elem.as(not null), max.as(not null))
+       end
+
+       # Return the couple with the lowest value
+       fun min: Couple[E, Float] do
+               assert not values.is_empty
+               var min: nullable Float = null
+               var elem: nullable E = null
+               for e, v in values do
+                       if min == null or v < min then
+                               min = v
+                               elem = e
+                       end
+               end
+               return new Couple[E, Float](elem.as(not null), min.as(not null))
+       end
+
+       # Values average
+       fun avg: Float do
+               if values.is_empty then return 0.0
+               var sum = 0.0
+               for value in values.values do
+                       sum += value
+               end
+               return sum / values.length.to_f
+       end
+end
+
+# A MetricSet is a metric holder
+#
+# It purpose is to be extended with a metric collect service
+class MetricSet
+       type METRIC: Metric
+
+       # Metrics to compute
+       var metrics: Map[String, METRIC] = new HashMap[String, METRIC]
+
+       # Add a metric to the set
+       fun register(metrics: METRIC...) do for metric in metrics do self.metrics[metric.name] = metric
+
+       # Clear all results for all metrics
+       fun clear do for metric in metrics.values do metric.clear
 end
diff --git a/src/metrics/mmodules_metrics.nit b/src/metrics/mmodules_metrics.nit
new file mode 100644 (file)
index 0000000..fc3a781
--- /dev/null
@@ -0,0 +1,248 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexandre Terrasa <alexandre@moz-code.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Collect common metrics about modules
+module mmodules_metrics
+
+import model
+import metrics_base
+import phase
+import frontend
+
+redef class ToolContext
+       var mmodules_metrics_phase = new MModulesMetricsPhase(self, null)
+end
+
+# Extract metrics about modules from the model.
+private class MModulesMetricsPhase
+       super Phase
+       redef fun process_mainmodule(mainmodule)
+       do
+               if not toolcontext.opt_mmodules.value and not toolcontext.opt_all.value then return
+
+               print toolcontext.format_h1("\n# MModules metrics")
+
+               var metrics = new MModuleMetricSet
+               metrics.register(new MNOA, new MNOP, new MNOC, new MNOD, new MDIT)
+               metrics.register(new MNBI, new MNBR, new MNBCC, new MNBAC, new MNBIC)
+
+               var model = toolcontext.modelbuilder.model
+               var mmodules = new HashSet[MModule]
+               for mproject in model.mprojects do
+
+                       print  toolcontext.format_h2("\n ## project {mproject}")
+
+                       for mgroup in mproject.mgroups do
+                               if mgroup.mmodules.is_empty then continue
+
+                               # Scalar metrics
+                               print  toolcontext.format_h3("  `- group {mgroup.full_name}")
+
+                               mmodules.add_all(mgroup.mmodules)
+                               metrics.collect(new HashSet[MModule].from(mgroup.mmodules), mainmodule)
+                               for name, metric in metrics.metrics do
+                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
+                                       print toolcontext.format_p("\t    avg: {metric.avg}")
+                                       var max = metric.max
+                                       print  toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                                       var min = metric.min
+                                       print  toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                               end
+                       end
+               end
+               if not mmodules.is_empty then
+                       # Global metrics
+                       print  toolcontext.format_h2("\n ## global metrics")
+
+                       metrics.collect(mmodules, mainmodule)
+                       for name, metric in metrics.metrics do
+                               print toolcontext.format_h4( "\t{name}: {metric.desc}")
+                               print  toolcontext.format_p("\t    avg: {metric.avg}")
+                               var max = metric.max
+                               print  toolcontext.format_p("\t    max: {max.first} ({max.second})")
+                               var min = metric.min
+                               print  toolcontext.format_p("\t    min: {min.first} ({min.second})")
+                       end
+               end
+       end
+end
+
+# A MetricSet for metrics about MModules
+class MModuleMetricSet
+       super MetricSet
+       redef type METRIC: MModuleMetric
+
+       # Collect all the metrics on the set of MModules
+       fun collect(mmodules: Set[MModule], mainmodule: MModule) do
+               clear
+               for metric in metrics.values do
+                       for mmodule in mmodules do
+                               metric.collect(mmodule, mainmodule)
+                       end
+               end
+       end
+end
+
+# An abstract Metric on MModules
+abstract class MModuleMetric
+       super IntMetric[MModule]
+       # Collect the metric on the MModule
+       #
+       # Results are stored in the property `values`
+       fun collect(mmodule: MModule, mainmodule: MModule) is abstract
+end
+
+# Module Metric: Number of Ancestors
+class MNOA
+       super MModuleMetric
+       redef fun name do return "mnoa"
+       redef fun desc do return "number of ancestor modules"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = mmodule.in_importation.greaters.length - 1
+       end
+end
+
+# Module Metric: Number of Parents
+class MNOP
+       super MModuleMetric
+       redef fun name do return "mnop"
+       redef fun desc do return "number of parent modules"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = mmodule.in_importation.direct_greaters.length
+       end
+end
+
+# Module Metric: Number of Children
+class MNOC
+       super MModuleMetric
+       redef fun name do return "mnoc"
+       redef fun desc do return "number of child modules"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = mmodule.in_importation.direct_smallers.length
+       end
+end
+
+# Module Metric: Number of Descendants
+class MNOD
+       super MModuleMetric
+       redef fun name do return "mnod"
+       redef fun desc do return "number of descendant modules"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = mmodule.in_importation.smallers.length - 1
+       end
+end
+
+# Module Metric: Depth in Tree
+class MDIT
+       super MModuleMetric
+       redef fun name do return "mdit"
+       redef fun desc do return "depth in module tree"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = mmodule.in_importation.depth
+       end
+end
+
+# Module Metric: Number of Introduction (of all kind)
+#
+# count all mclasses introduced by the module
+class MNBI
+       super MModuleMetric
+       redef fun name do return "mnbi"
+       redef fun desc do return "number of introduction in module"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = mmodule.intro_mclasses.length
+       end
+end
+
+# Module Metric: Number of Refinement
+#
+# count all mclasses refined in the module
+class MNBR
+       super MModuleMetric
+       redef fun name do return "mnbr"
+       redef fun desc do return "number of refinement in module"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = 0
+               for mclassdef in mmodule.mclassdefs do
+                       if not mclassdef.is_intro then values.inc(mmodule)
+               end
+       end
+end
+
+# Module Metric: Number of Concrete Class in module (intro + redef)
+class MNBCC
+       super MModuleMetric
+       redef fun name do return "mnbcc"
+       redef fun desc do return "number of concrete class in module (intro + redef)"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = 0
+               for mclassdef in mmodule.mclassdefs do
+                       if mclassdef.mclass.kind == concrete_kind then values.inc(mmodule)
+               end
+       end
+end
+
+# Module Metric: Number of Abstract Class in module (intro + redef)
+class MNBAC
+       super MModuleMetric
+       redef fun name do return "mnbac"
+       redef fun desc do return "number of abstract class in module (intro + redef)"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = 0
+               for mclassdef in mmodule.mclassdefs do
+                       if mclassdef.mclass.kind == abstract_kind then values.inc(mmodule)
+               end
+       end
+end
+
+# Module Metric: Number of Interface in module (intro + redef)
+class MNBIC
+       super MModuleMetric
+       redef fun name do return "mnbic"
+       redef fun desc do return "number of interface in module (intro + redef)"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = 0
+               for mclassdef in mmodule.mclassdefs do
+                       if mclassdef.mclass.kind == interface_kind then values.inc(mmodule)
+               end
+       end
+end
+
+# Module Metric: Number of Enum in module (intro + redef)
+class MNBEC
+       super MModuleMetric
+       redef fun name do return "mnbec"
+       redef fun desc do return "number of enum in module (intro + redef)"
+
+       redef fun collect(mmodule, main) do
+               values[mmodule] = 0
+               for mclassdef in mmodule.mclassdefs do
+                       if mclassdef.mclass.kind == enum_kind then values.inc(mmodule)
+               end
+       end
+end
+
+
index ec647ea..d788260 100644 (file)
@@ -76,7 +76,7 @@ end
 # Visit the AST and print metrics about the usage of send on nullable reciever.
 fun compute_nullables_metrics(modelbuilder: ModelBuilder)
 do
-       print "--- Sends on Nullable Reciever ---"
+       print "--- Sends on Nullable Receiver ---"
        var total_sends = 0
        var nullable_sends = 0
        var buggy_sends = 0
index 03d9a8a..85b012a 100644 (file)
@@ -40,10 +40,10 @@ redef class MType
        private var nlvt: Int = 0
        private var nlct: Int = 0
 
-       private fun is_user_defined: Bool do
+       private fun is_standard: Bool do
                var mtype = self
                if mtype isa MNullableType then mtype = mtype.mtype
-               return self.as(MClassType).mclass.is_user_defined
+               return self.as(MClassType).mclass.is_standard
        end
 
        private fun get_depth: Int do
@@ -93,7 +93,7 @@ do
                mtype.mclass.nlvt += 1
                mtype.mclass.live_types.add(mtype)
                if mtype isa MGenericType then nlvtg += 1
-               if mtype.is_user_defined then
+               if not mtype.is_standard then
                        nlvtudud += 1
                        if mtype isa MGenericType then nlvtgudud += 1
                else
@@ -110,7 +110,7 @@ do
                mtype.mclass.nlct += 1
                mtype.mclass.cast_types.add(mtype)
                if mtype isa MGenericType then nlctg += 1
-               if mtype.is_user_defined then
+               if not mtype.is_standard then
                        nlctudud += 1
                        if mtype isa MGenericType then nlctgudud += 1
                else
@@ -136,7 +136,7 @@ do
                for mtype in mtypes do
                        var arity = 0
                        if mtype isa MGenericType then arity = mtype.arguments.length
-                       if mtype.is_user_defined then
+                       if not mtype.is_standard then
                                udscalarCSV.add_line(mtype, arity, mtype.get_depth, mtype.nlvt, mtype.nlct)
                        end
                        scalarCSV.add_line(mtype, arity, mtype.get_depth, mtype.nlvt, mtype.nlct)
@@ -151,7 +151,7 @@ do
 
                for mclass in modelbuilder.model.mclasses do
                        if not mclass.is_class or mclass.is_abstract then continue
-                       if mclass.is_user_defined then
+                       if not mclass.is_standard then
                                udscalarCSV.add_line(mclass.mclass_type, mclass.arity, mclass.live_types.length, mclass.nlvt)
                        end
                        scalarCSV.add_line(mclass.mclass_type, mclass.arity, mclass.live_types.length, mclass.nlvt)
index d946c12..89eb0f3 100644 (file)
@@ -882,6 +882,9 @@ redef class ATypePropdef
 
        redef fun check_signature(modelbuilder, nclassdef)
        do
+               var mpropdef = self.mpropdef
+               if mpropdef == null then return # Error thus skiped
+
                var bound = self.mpropdef.bound
 
                # Fast case: the bound is not a formal type
index 76b11fa..896cfb6 100644 (file)
@@ -347,9 +347,7 @@ private class NaiveInterpreter
                        self.discover_call_trace.add mpropdef
                        self.debug("Discovered {mpropdef}")
                end
-               if args.length < mpropdef.msignature.arity + 1 or args.length > mpropdef.msignature.arity + 1 then
-                       fatal("NOT YET IMPLEMENTED: Invalid arity for {mpropdef}. {args.length} arguments given.")
-               end
+               assert args.length == mpropdef.msignature.arity + 1 else debug("Invalid arity for {mpropdef}. {args.length} arguments given.")
 
                # Look for the AST node that implements the property
                var mproperty = mpropdef.mproperty
@@ -398,8 +396,8 @@ private class NaiveInterpreter
                        else if mproperty.name == "!=" then
                                return self.bool_instance(args[0] != args[1])
                        end
-                       #fatal("Reciever is null. {mproperty}. {args.join(" ")} {self.frame.current_node.class_name}")
-                       fatal("Reciever is null")
+                       #fatal("Receiver is null. {mproperty}. {args.join(" ")} {self.frame.current_node.class_name}")
+                       fatal("Receiver is null")
                end
                return null
        end
@@ -602,12 +600,12 @@ redef class AConcreteMethPropdef
                return null
        end
 
-       private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, args: Array[Instance], f: Frame)
+       private fun call_commons(v: NaiveInterpreter, mpropdef: MMethodDef, arguments: Array[Instance], f: Frame)
        do
                for i in [0..mpropdef.msignature.arity[ do
                        var variable = self.n_signature.n_params[i].variable
                        assert variable != null
-                       f.map[variable] = args[i+1]
+                       f.map[variable] = arguments[i+1]
                end
 
                v.frames.unshift(f)
@@ -615,13 +613,13 @@ redef class AConcreteMethPropdef
                # Call the implicit super-init
                var auto_super_inits = self.auto_super_inits
                if auto_super_inits != null then
-                       var selfarg = [args.first]
+                       var args = [arguments.first]
                        for auto_super_init in auto_super_inits do
-                               if auto_super_init.intro.msignature.arity == 0 then
-                                       v.send(auto_super_init, selfarg)
-                               else
-                                       v.send(auto_super_init, args)
+                               args.clear
+                               for i in [0..auto_super_init.intro.msignature.arity+1[ do
+                                       args.add(arguments[i])
                                end
+                               v.send(auto_super_init, args)
                        end
                end
 
@@ -1241,6 +1239,8 @@ redef class AForExpr
        do
                var col = v.expr(self.n_expr)
                if col == null then return
+               if col.mtype isa MNullType then fatal(v, "Receiver is null")
+
                #self.debug("col {col}")
                var iter = v.send(v.force_get_primitive_method("iterator", col.mtype), [col]).as(not null)
                #self.debug("iter {iter}")
@@ -1560,20 +1560,24 @@ redef class ASuperExpr
                        if i == null then return null
                        args.add(i)
                end
-               if args.length == 1 then
-                       args = v.frame.arguments
-               end
 
                var callsite = self.callsite
                if callsite != null then
-                       if callsite.mproperty.intro.msignature.arity == 0 then
-                               args = [recv]
+                       # Add additionnals arguments for the super init call
+                       if args.length == 1 then
+                               for i in [0..callsite.mproperty.intro.msignature.arity[ do
+                                       args.add(v.frame.arguments[i+1])
+                               end
                        end
                        # Super init call
                        var res = v.send(callsite.mproperty, args)
                        return res
                end
 
+               if args.length == 1 then
+                       args = v.frame.arguments
+               end
+
                # stantard call-next-method
                var mpropdef = v.frame.mpropdef
                mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
@@ -1609,7 +1613,7 @@ redef class AAttrExpr
        do
                var recv = v.expr(self.n_expr)
                if recv == null then return null
-               if recv.mtype isa MNullType then fatal(v, "Reciever is null")
+               if recv.mtype isa MNullType then fatal(v, "Receiver is null")
                var mproperty = self.mproperty.as(not null)
                return v.read_attribute(mproperty, recv)
        end
@@ -1620,7 +1624,7 @@ redef class AAttrAssignExpr
        do
                var recv = v.expr(self.n_expr)
                if recv == null then return
-               if recv.mtype isa MNullType then fatal(v, "Reciever is null")
+               if recv.mtype isa MNullType then fatal(v, "Receiver is null")
                var i = v.expr(self.n_value)
                if i == null then return
                var mproperty = self.mproperty.as(not null)
@@ -1634,7 +1638,7 @@ redef class AAttrReassignExpr
        do
                var recv = v.expr(self.n_expr)
                if recv == null then return
-               if recv.mtype isa MNullType then fatal(v, "Reciever is null")
+               if recv.mtype isa MNullType then fatal(v, "Receiver is null")
                var value = v.expr(self.n_value)
                if value == null then return
                var mproperty = self.mproperty.as(not null)
@@ -1651,7 +1655,7 @@ redef class AIssetAttrExpr
        do
                var recv = v.expr(self.n_expr)
                if recv == null then return null
-               if recv.mtype isa MNullType then fatal(v, "Reciever is null")
+               if recv.mtype isa MNullType then fatal(v, "Receiver is null")
                var mproperty = self.mproperty.as(not null)
                assert recv isa MutableInstance
                return v.bool_instance(recv.attributes.has_key(mproperty))
index 280e273..4a5e68e 100644 (file)
@@ -42,6 +42,7 @@ class NitdocContext
        private var opt_dir = new OptionString("Directory where doc is generated", "-d", "--dir")
        private var opt_source = new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
        private var opt_sharedir = new OptionString("Directory containing the nitdoc files", "--sharedir")
+       private var opt_shareurl = new OptionString("Do not copy shared files, link JS and CSS file to share url instead", "--shareurl")
        private var opt_nodot = new OptionBool("Do not generate graphes with graphviz", "--no-dot")
        private var opt_private: OptionBool = new OptionBool("Generate the private API", "--private")
 
@@ -60,7 +61,7 @@ class NitdocContext
        init do
                toolcontext.option_context.add_option(opt_dir)
                toolcontext.option_context.add_option(opt_source)
-               toolcontext.option_context.add_option(opt_sharedir)
+               toolcontext.option_context.add_option(opt_sharedir, opt_shareurl)
                toolcontext.option_context.add_option(opt_nodot)
                toolcontext.option_context.add_option(opt_private)
                toolcontext.option_context.add_option(opt_custom_title)
@@ -119,17 +120,11 @@ class NitdocContext
                                print "Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
                                abort
                        end
-                       dir = "{share_dir.to_s}/scripts/js-facilities.js"
-                       if share_dir == null then
-                               print "Error: Invalid nitdoc share files. Check --sharedir or envvar NIT_DIR"
-                               abort
-                       end
-
-                       if opt_private.value then
-                               min_visibility = none_visibility
-                       else
-                               min_visibility = protected_visibility
-                       end
+               end
+               if opt_private.value then
+                       min_visibility = none_visibility
+               else
+                       min_visibility = protected_visibility
                end
                var gh_upstream = opt_github_upstream.value
                var gh_base_sha = opt_github_base_sha1.value
@@ -150,7 +145,11 @@ class NitdocContext
        fun generate_nitdoc do
                # Create destination dir if it's necessary
                if not output_dir.file_exists then output_dir.mkdir
-               sys.system("cp -r {share_dir.to_s}/* {output_dir.to_s}/")
+               if opt_shareurl.value == null then
+                       sys.system("cp -r {share_dir.to_s}/* {output_dir.to_s}/")
+               else
+                       sys.system("cp -r {share_dir.to_s}/resources/ {output_dir.to_s}/resources/")
+               end
                self.dot_dir = null
                if not opt_nodot.value then self.dot_dir = output_dir.to_s
                overview
@@ -224,25 +223,20 @@ end
 abstract class NitdocPage
 
        var ctx: NitdocContext
+       var shareurl = "."
 
        init(ctx: NitdocContext) do
                self.ctx = ctx
+               if ctx.opt_shareurl.value != null then shareurl = ctx.opt_shareurl.value.as(not null)
        end
 
        protected fun head do
                append("<meta charset='utf-8'/>")
-               append("<script type='text/javascript' src='scripts/jquery-1.7.1.min.js'></script>")
-               append("<script type='text/javascript' src='scripts/ZeroClipboard.min.js'></script>")
-               append("<script type='text/javascript' src='scripts/Nitdoc.UI.js'></script>")
-               append("<script type='text/javascript' src='scripts/Markdown.Converter.js'></script>")
-               append("<script type='text/javascript' src='scripts/base64.js'></script>")
-               append("<script type='text/javascript' src='scripts/Nitdoc.GitHub.js'></script>")
-               append("<script type='text/javascript' src='quicksearch-list.js'></script>")
-               append("<script type='text/javascript' src='scripts/Nitdoc.QuickSearch.js'></script>")
-               append("<link rel='stylesheet' href='styles/main.css' type='text/css' media='screen'/>")
-               append("<link rel='stylesheet' href='styles/Nitdoc.UI.css' type='text/css' media='screen'/>")
-               append("<link rel='stylesheet' href='styles/Nitdoc.QuickSearch.css' type='text/css' media='screen'/>")
-               append("<link rel='stylesheet' href='styles/Nitdoc.GitHub.css' type='text/css' media='screen'/>")
+               append("<link rel='stylesheet' href='{shareurl}/css/main.css' type='text/css'/>")
+               append("<link rel='stylesheet' href='{shareurl}/css/Nitdoc.UI.css' type='text/css''/>")
+               append("<link rel='stylesheet' href='{shareurl}/css/Nitdoc.QuickSearch.css' type='text/css'/>")
+               append("<link rel='stylesheet' href='{shareurl}/css/Nitdoc.GitHub.css' type='text/css'/>")
+               append("<link rel='stylesheet' href='{shareurl}/css/Nitdoc.ModalBox.css' type='text/css'/>")
                var title = ""
                if ctx.opt_custom_title.value != null then
                        title = " | {ctx.opt_custom_title.value.to_s}"
@@ -318,6 +312,7 @@ abstract class NitdocPage
                head
                append("</head>")
                append("<body")
+               append(" data-bootstrap-share='{shareurl}'")
                if ctx.opt_github_upstream.value != null and ctx.opt_github_base_sha1.value != null then
                        append(" data-github-upstream='{ctx.opt_github_upstream.value.as(not null)}'")
                        append(" data-github-base-sha1='{ctx.opt_github_base_sha1.value.as(not null)}'")
@@ -328,6 +323,9 @@ abstract class NitdocPage
                if ctx.opt_custom_footer_text.value != null then footed = "footed"
                append("<div class='page {footed}'>")
                content
+               append("</div>")
+               footer
+               append("<script data-main=\"{shareurl}/js/nitdoc\" src=\"{shareurl}/js/lib/require.js\"></script>")
 
                # piwik tracking
                var tracker_url = ctx.opt_piwik_tracker.value
@@ -348,8 +346,6 @@ abstract class NitdocPage
                        append(" </script>")
                        append("<!-- End Piwik Code -->")
                end
-               append("</div>")
-               footer
                append("</body>")
        end
 
@@ -1823,11 +1819,13 @@ redef class AModule
                return ""
        end
 
+       # The doc location or the first line of the block if doc node is null
        private fun doc_location: Location do
                if n_moduledecl != null and n_moduledecl.n_doc != null then
                        return n_moduledecl.n_doc.location
                end
-               return location
+               var l = location
+               return new Location(l.file, l.line_start, l.line_start, l.column_start, l.column_start)
        end
 end
 
@@ -1847,9 +1845,11 @@ redef class AStdClassdef
                return ""
        end
 
+       # The doc location or the first line of the block if doc node is null
        private fun doc_location: Location do
                if n_doc != null then return n_doc.location
-               return location
+               var l = location
+               return new Location(l.file, l.line_start, l.line_start, l.column_start, l.column_start)
        end
 end
 
@@ -1871,7 +1871,9 @@ redef class APropdef
 
        private fun doc_location: Location do
                if n_doc != null then return n_doc.location
-               return location
+               var l = location
+               return new Location(l.file, l.line_start, l.line_start, l.column_start, l.column_start)
+
        end
 end
 
index 9bce4bd..09545e4 100644 (file)
@@ -906,8 +906,10 @@ class SeparateCompiler
        
        redef fun finalize_ffi_for_module(nmodule)
        do
+               var old_module = self.mainmodule
                self.mainmodule = nmodule.mmodule.as(not null)
                super
+               self.mainmodule = old_module
        end
 end
 
@@ -993,6 +995,8 @@ class SeparateCompilerVisitor
 
        private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
        do
+               assert arguments.length == mmethod.intro.msignature.arity + 1 else debug("Invalid arity for {mmethod}. {arguments.length} arguments given.")
+
                var res: nullable RuntimeVariable
                var msignature = mmethod.intro.msignature.resolve_for(mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.mmodule, true)
                var ret = msignature.return_mtype
@@ -1047,7 +1051,7 @@ class SeparateCompilerVisitor
                                        self.add("{res} = 1; /* {arg.inspect} cannot be null */")
                                end
                        else
-                               self.add_abort("Reciever is null")
+                               self.add_abort("Receiver is null")
                        end
                        self.add("\} else \{")
                end
@@ -1088,6 +1092,8 @@ class SeparateCompilerVisitor
 
        redef fun call(mmethoddef, recvtype, arguments)
        do
+               assert arguments.length == mmethoddef.msignature.arity + 1 else debug("Invalid arity for {mmethoddef}. {arguments.length} arguments given.")
+
                var res: nullable RuntimeVariable
                var ret = mmethoddef.msignature.return_mtype
                if mmethoddef.mproperty.is_new then
index 719fae2..6838784 100644 (file)
@@ -823,6 +823,11 @@ redef class AForExpr
 
        private fun do_type_iterator(v: TypeVisitor, mtype: MType)
        do
+               if mtype isa MNullType then
+                       v.error(self, "Type error: 'for' cannot iterate over 'null'")
+                       return
+               end
+
                # get obj class
                var objcla = v.get_mclass(self, "Object")
                if objcla == null then return
@@ -831,7 +836,7 @@ redef class AForExpr
                var unsafe_type = v.anchor_to(mtype)
                if v.try_get_mproperty_by_name2(self, unsafe_type, "iterator") == null then
                        if v.try_get_mproperty_by_name2(self, unsafe_type, "iterate") == null then
-                               v.error(self, "Type Error: Expected method 'iterator' in type {mtype}")
+                               v.error(self, "Type Error: 'for' expects a type providing 'iterator' method, got '{mtype}'.")
                        else
                                v.modelbuilder.error(self, "NOT YET IMPLEMENTED: Do 'for' on {mtype}")
                        end
@@ -840,7 +845,7 @@ redef class AForExpr
 
                var itdef = v.get_method(self, mtype, "iterator", true)
                if itdef == null then
-                       v.error(self, "Type Error: Expected method 'iterator' in type {mtype}")
+                       v.error(self, "Type Error: 'for' expects a type providing 'iterator' method, got '{mtype}'.")
                        return
                end
                self.method_iterator = itdef.mproperty
@@ -848,7 +853,7 @@ redef class AForExpr
                # check that iterator return something
                var ittype = itdef.msignature.return_mtype
                if ittype == null then
-                       v.error(self, "Type Error: Expected method 'iterator' to return an Iterator or MapIterator type")
+                       v.error(self, "Type Error: 'for' expects method 'iterator' to return an 'Iterator' or 'MapIterator' type'.")
                        return
                end
 
@@ -863,7 +868,7 @@ redef class AForExpr
                        var coltype = ittype.supertype_to(v.mmodule, v.anchor, colit_cla)
                        var variables =  self.variables
                        if variables.length != 1 then
-                               v.error(self, "Type Error: Expected one variable")
+                               v.error(self, "Type Error: 'for' expects only one variable when using 'Iterator'.")
                        else
                                variables.first.declared_type = coltype.arguments.first
                        end
@@ -875,7 +880,7 @@ redef class AForExpr
                        var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla)
                        var variables = self.variables
                        if variables.length != 2 then
-                               v.error(self, "Type Error: Expected two variables")
+                               v.error(self, "Type Error: 'for' expects two variables when using 'MapIterator'.")
                        else
                                variables[0].declared_type = coltype.arguments[0]
                                variables[1].declared_type = coltype.arguments[1]
@@ -884,33 +889,34 @@ redef class AForExpr
                end
 
                if not is_col and not is_map then
-                       v.error(self, "Type Error: Expected method 'iterator' to return an Iterator of MapIterator type")
+                       v.error(self, "Type Error: 'for' expects method 'iterator' to return an 'Iterator' or 'MapIterator' type'.")
                        return
                end
 
                # anchor formal and virtual types
                if mtype.need_anchor then mtype = v.anchor_to(mtype)
 
+               if mtype isa MNullableType then mtype = mtype.mtype
                self.coltype = mtype.as(MClassType)
 
                # get methods is_ok, next, item
                var ikdef = v.get_method(self, ittype, "is_ok", false)
                if ikdef == null then
-                       v.error(self, "Type Error: Expected method 'is_ok' in Iterator type {ittype}")
+                       v.error(self, "Type Error: 'for' expects a method 'is_ok' in 'Iterator' type {ittype}.")
                        return
                end
                self.method_is_ok = ikdef.mproperty
 
                var itemdef = v.get_method(self, ittype, "item", false)
                if itemdef == null then
-                       v.error(self, "Type Error: Expected method 'item' in Iterator type {ittype}")
+                       v.error(self, "Type Error: 'for' expects a method 'item' in 'Iterator' type {ittype}.")
                        return
                end
                self.method_item = itemdef.mproperty
 
                var nextdef = v.get_method(self, ittype, "next", false)
                if nextdef == null then
-                       v.error(self, "Type Error: Expected method 'next' in Iterator type {ittype}")
+                       v.error(self, "Type Error: 'for' expects a method 'next' in 'Iterator' type {ittype}.")
                        return
                end
                self.method_next = nextdef.mproperty
@@ -918,7 +924,7 @@ redef class AForExpr
                if is_map then
                        var keydef = v.get_method(self, ittype, "key", false)
                        if keydef == null then
-                               v.error(self, "Type Error: Expected method 'key' in Iterator type {ittype}")
+                               v.error(self, "Type Error: 'for' expects a method 'key' in 'Iterator' type {ittype}.")
                                return
                        end
                        self.method_key = keydef.mproperty
@@ -1452,7 +1458,9 @@ redef class ASuperExpr
        private fun process_superinit(v: TypeVisitor)
        do
                var recvtype = v.nclassdef.mclassdef.bound_mtype
-               var mproperty = v.mpropdef.mproperty
+               var mpropdef = v.mpropdef
+               assert mpropdef isa MMethodDef
+               var mproperty = mpropdef.mproperty
                var superprop: nullable MMethodDef = null
                for msupertype in v.nclassdef.mclassdef.supertypes do
                        msupertype = msupertype.anchor_to(v.mmodule, recvtype)
@@ -1490,7 +1498,21 @@ redef class ASuperExpr
                if args.length > 0 then
                        callsite.check_signature(v, args)
                else
-                       # TODO: Check signature
+                       # Check there is at least enough parameters
+                       if mpropdef.msignature.arity < msignature.arity then
+                               v.error(self, "Error: Not enough implicit arguments to pass. Got {mpropdef.msignature.arity}, expected at least {msignature.arity}. Signature is {msignature}")
+                               return
+                       end
+                       # Check that each needed parameter is conform
+                       var i = 0
+                       for sp in msignature.mparameters do
+                               var p = mpropdef.msignature.mparameters[i]
+                               if not v.is_subtype(p.mtype, sp.mtype) then
+                                       v.error(self, "Type error: expected argument #{i} of type {sp.mtype}, got implicit argument {p.name} of type {p.mtype}. Signature is {msignature}")
+                                       return
+                               end
+                               i += 1
+                       end
                end
 
                self.is_typed = true
diff --git a/tests/base_for_nullable.nit b/tests/base_for_nullable.nit
new file mode 100644 (file)
index 0000000..4fd3253
--- /dev/null
@@ -0,0 +1,22 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import array
+
+var list: nullable Array[Int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+#alt1# if true then list = null
+#alt2# list = null
+
+for i in list do i.output
+
diff --git a/tests/base_init_super_call.nit b/tests/base_init_super_call.nit
new file mode 100644 (file)
index 0000000..5d863ab
--- /dev/null
@@ -0,0 +1,142 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+       init(i: Int) do i.output
+end
+
+class B1
+       super A
+       #alt1#init do super
+end
+
+class B2
+       super A
+       init do super(3)
+end
+
+class B3
+       super A
+       #alt2#init do super(true)
+end
+
+class B4
+       super A
+       #alt3#init do end
+end
+
+class C1
+       super A
+       init(j: Int) do
+               super
+               j.output
+       end
+end
+
+class D1
+       super A
+       init(j) do
+               super
+               j.output
+       end
+end
+
+class E1
+       super A
+       init(j: Bool) do
+               super(8)#alt4#super
+               j.output
+       end
+end
+
+class C2
+       super A
+       init(j: Int) do
+               super(j)
+               j.output
+       end
+end
+
+class D2
+       super A
+       init(j) do
+               super(j)
+               j.output
+       end
+end
+
+class E2
+       super A
+       init(j: Bool) do
+               super(11)#alt5#super(j)
+               j.output
+       end
+end
+
+class C3
+       super A
+       init(j: Int) do
+               j.output
+       end
+end
+
+class D3
+       super A
+       init(j) do
+               j.output
+       end
+end
+
+class E3
+       super A
+       init(j: Bool) do
+               super(14)#alt6#
+               j.output
+       end
+end
+
+class F1
+       super A
+       init(j: Int, k: Bool) do
+               super
+               j.output
+       end
+end
+
+class F2
+       super A
+       init(j: Int, k: Bool) do
+               j.output
+       end
+end
+
+var x
+x = new A(1)
+x = new B1(2) #alt1# x = new B1
+x = new B2
+x = new B3(4) #alt2# x = new B3
+x = new B4(5) #alt3# x = new B4
+x = new C1(6)
+x = new D1(7)
+x = new E1(true)
+x = new C2(9)
+x = new D2(10)
+x = new E2(true)
+x = new C3(12)
+x = new D3(13)
+x = new E3(true)
+x = new F1(15,true)
+x = new F2(16,true)
diff --git a/tests/base_init_super_call2.nit b/tests/base_init_super_call2.nit
new file mode 100644 (file)
index 0000000..f229ddb
--- /dev/null
@@ -0,0 +1,158 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+       var i: Int
+end
+
+class B1
+       super A
+       #alt1#init do super
+end
+
+class B2
+       super A
+       init do super(3)
+end
+
+class B3
+       super A
+       #alt2#init do super(true)
+end
+
+class B4
+       super A
+       #alt3#init do end
+end
+
+class C1
+       super A
+       init(j: Int) do
+               super
+               j.output
+       end
+end
+
+class D1
+       super A
+       init(j) do
+               super
+               j.output
+       end
+end
+
+class E1
+       super A
+       init(j: Bool) do
+               super(8)#alt4#super
+               j.output
+       end
+end
+
+class C2
+       super A
+       init(j: Int) do
+               super(j)
+               j.output
+       end
+end
+
+class D2
+       super A
+       init(j) do
+               super(j)
+               j.output
+       end
+end
+
+class E2
+       super A
+       init(j: Bool) do
+               super(11)#alt5#super(j)
+               j.output
+       end
+end
+
+class C3
+       super A
+       init(j: Int) do
+               j.output
+       end
+end
+
+class D3
+       super A
+       init(j) do
+               j.output
+       end
+end
+
+class E3
+       super A
+       init(j: Bool) do
+               super(14)#alt6#
+               j.output
+       end
+end
+
+class F1
+       super A
+       init(j: Int, k: Bool) do
+               super
+               j.output
+       end
+end
+
+class F2
+       super A
+       init(j: Int, k: Bool) do
+               j.output
+       end
+end
+
+var x
+x = new A(1)
+x.i.output
+x = new B1(2) #alt1# x = new B1
+x.i.output
+x = new B2
+x.i.output
+x = new B3(4) #alt2# x = new B3
+x.i.output
+x = new B4(5) #alt3# x = new B4
+x.i.output
+x = new C1(6)
+x.i.output
+x = new D1(7)
+x.i.output
+x = new E1(true)
+x.i.output
+x = new C2(9)
+x.i.output
+x = new D2(10)
+x.i.output
+x = new E2(true)
+x.i.output
+x = new C3(12)
+x.i.output
+x = new D3(13)
+x.i.output
+x = new E3(true)
+x.i.output
+x = new F1(15,true)
+x.i.output
+x = new F2(16,true)
+x.i.output
diff --git a/tests/base_virtual_type_redef.nit b/tests/base_virtual_type_redef.nit
new file mode 100644 (file)
index 0000000..837bd46
--- /dev/null
@@ -0,0 +1,26 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+interface Number
+       type OTHER: Number
+end
+
+redef class Int
+       super Number
+
+       redef type OTHER: Int
+end
+
index b9b7ac8..c78ec94 100644 (file)
@@ -47,7 +47,7 @@ end
 #alt2#for i in new Collection[Int] do i.output
 #alt3#var s = "str"
 #alt4#var s2 = "str{5}str"
-#alt5#var r = [1..10]
+#alt5# #var r = [1..10] # DISABLE
 #alt6#var r = [1..10[
 #alt7#fun foo(x: Int...) do end
 #alt7#foo(1, 2, 3)
index 4615356..fa1fe20 100644 (file)
@@ -4,3 +4,4 @@ init_linext
 inline
 test_extern
 nitc
+opengles2_hello_triangle
index 3555fdb..f5d9c95 100644 (file)
@@ -1 +1 @@
---all base_simple3.nit -d $WRITE
+--no-colors --all base_simple3.nit -d $WRITE
index afe7755..48d1ef7 100644 (file)
@@ -1 +1 @@
-Runtime error: Reciever is null (base_attr_gen.nit:26)
+Runtime error: Receiver is null (base_attr_gen.nit:26)
diff --git a/tests/sav/base_for_nullable.res b/tests/sav/base_for_nullable.res
new file mode 100644 (file)
index 0000000..8b1acc1
--- /dev/null
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/tests/sav/base_for_nullable_alt1.res b/tests/sav/base_for_nullable_alt1.res
new file mode 100644 (file)
index 0000000..c28bd5a
--- /dev/null
@@ -0,0 +1 @@
+Runtime error: Receiver is null (alt/base_for_nullable_alt1.nit:21)
diff --git a/tests/sav/base_for_nullable_alt2.res b/tests/sav/base_for_nullable_alt2.res
new file mode 100644 (file)
index 0000000..30e9b42
--- /dev/null
@@ -0,0 +1 @@
+alt/base_for_nullable_alt2.nit:21,1--25: Type error: 'for' cannot iterate over 'null'
diff --git a/tests/sav/base_init_super_call.res b/tests/sav/base_init_super_call.res
new file mode 100644 (file)
index 0000000..0f283aa
--- /dev/null
@@ -0,0 +1,27 @@
+1
+2
+3
+4
+5
+6
+6
+7
+7
+8
+true
+9
+9
+10
+10
+11
+true
+12
+12
+13
+13
+14
+true
+15
+15
+16
+16
diff --git a/tests/sav/base_init_super_call2.res b/tests/sav/base_init_super_call2.res
new file mode 100644 (file)
index 0000000..5e26c1f
--- /dev/null
@@ -0,0 +1,27 @@
+1
+2
+3
+4
+5
+6
+6
+7
+7
+true
+8
+9
+9
+10
+10
+true
+11
+12
+12
+13
+13
+true
+14
+15
+15
+16
+16
diff --git a/tests/sav/base_init_super_call2_alt1.res b/tests/sav/base_init_super_call2_alt1.res
new file mode 100644 (file)
index 0000000..b4d9a32
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call2_alt1.nit:23,10--14: Error: Not enough implicit arguments to pass. Got 0, expected at least 1. Signature is (i: Int)
diff --git a/tests/sav/base_init_super_call2_alt2.res b/tests/sav/base_init_super_call2_alt2.res
new file mode 100644 (file)
index 0000000..4cc34a8
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call2_alt2.nit:33,16--19: Type error: expected Int, got Bool
diff --git a/tests/sav/base_init_super_call2_alt3.res b/tests/sav/base_init_super_call2_alt3.res
new file mode 100644 (file)
index 0000000..6c513f8
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call2_alt3.nit:38,2--5: Error: Cannot do an implicit constructor call to base_init_super_call2_alt3#A#init(i: Int). Expected at least 1 arguments, got 0.
diff --git a/tests/sav/base_init_super_call2_alt4.res b/tests/sav/base_init_super_call2_alt4.res
new file mode 100644 (file)
index 0000000..6a5c1cf
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call2_alt4.nit:60,3--7: Type error: expected argument #0 of type Int, got implicit argument j of type Bool. Signature is (i: Int)
diff --git a/tests/sav/base_init_super_call2_alt5.res b/tests/sav/base_init_super_call2_alt5.res
new file mode 100644 (file)
index 0000000..2e15e41
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call2_alt5.nit:84,9: Type error: expected Int, got Bool
diff --git a/tests/sav/base_init_super_call2_alt6.res b/tests/sav/base_init_super_call2_alt6.res
new file mode 100644 (file)
index 0000000..0650fe9
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call2_alt6.nit:105,2--5: Error: Cannot do an implicit constructor call to base_init_super_call2_alt6#A#init(i: Int). Expected argument #0 of type Int, got implicit argument j of type Bool.
diff --git a/tests/sav/base_init_super_call_alt1.res b/tests/sav/base_init_super_call_alt1.res
new file mode 100644 (file)
index 0000000..73082d3
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call_alt1.nit:23,10--14: Error: Not enough implicit arguments to pass. Got 0, expected at least 1. Signature is (i: Int)
diff --git a/tests/sav/base_init_super_call_alt2.res b/tests/sav/base_init_super_call_alt2.res
new file mode 100644 (file)
index 0000000..ca41f99
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call_alt2.nit:33,16--19: Type error: expected Int, got Bool
diff --git a/tests/sav/base_init_super_call_alt3.res b/tests/sav/base_init_super_call_alt3.res
new file mode 100644 (file)
index 0000000..ca3da80
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call_alt3.nit:38,2--5: Error: Cannot do an implicit constructor call to base_init_super_call_alt3#A#init(i: Int). Expected at least 1 arguments, got 0.
diff --git a/tests/sav/base_init_super_call_alt4.res b/tests/sav/base_init_super_call_alt4.res
new file mode 100644 (file)
index 0000000..cc3d485
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call_alt4.nit:60,3--7: Type error: expected argument #0 of type Int, got implicit argument j of type Bool. Signature is (i: Int)
diff --git a/tests/sav/base_init_super_call_alt5.res b/tests/sav/base_init_super_call_alt5.res
new file mode 100644 (file)
index 0000000..481ff08
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call_alt5.nit:84,9: Type error: expected Int, got Bool
diff --git a/tests/sav/base_init_super_call_alt6.res b/tests/sav/base_init_super_call_alt6.res
new file mode 100644 (file)
index 0000000..3352bce
--- /dev/null
@@ -0,0 +1 @@
+alt/base_init_super_call_alt6.nit:105,2--5: Error: Cannot do an implicit constructor call to base_init_super_call_alt6#A#init(i: Int). Expected argument #0 of type Int, got implicit argument j of type Bool.
index e07734d..e7c9557 100644 (file)
@@ -1,5 +1,5 @@
-base_iterator3.nit:35,1--25: Type Error: Expected method 'iterator' to return an Iterator of MapIterator type
-base_iterator3.nit:39,1--25: Type Error: Expected method 'iterator' to return an Iterator or MapIterator type
-base_iterator3.nit:43,1--25: Type Error: Expected method 'iterator' in type Test3
-base_iterator3.nit:46,1--48: Type Error: Expected one variable
-base_iterator3.nit:47,1--47: Type Error: Expected two variables
+base_iterator3.nit:35,1--25: Type Error: 'for' expects method 'iterator' to return an 'Iterator' or 'MapIterator' type'.
+base_iterator3.nit:39,1--25: Type Error: 'for' expects method 'iterator' to return an 'Iterator' or 'MapIterator' type'.
+base_iterator3.nit:43,1--25: Type Error: 'for' expects a type providing 'iterator' method, got 'Test3'.
+base_iterator3.nit:46,1--48: Type Error: 'for' expects only one variable when using 'Iterator'.
+base_iterator3.nit:47,1--47: Type Error: 'for' expects two variables when using 'MapIterator'.
index 873d14f..ece7b8c 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Reciever is null (alt/base_primitive_null_alt1.nit:34)
+Runtime error: Receiver is null (alt/base_primitive_null_alt1.nit:34)
 I
 true
 true
index bef3335..b1f28ea 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Reciever is null (alt/base_primitive_null_alt2.nit:43)
+Runtime error: Receiver is null (alt/base_primitive_null_alt2.nit:43)
 I
 true
 true
index ba81322..d29cdb6 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Reciever is null (alt/base_primitive_null_alt3.nit:52)
+Runtime error: Receiver is null (alt/base_primitive_null_alt3.nit:52)
 I
 true
 true
diff --git a/tests/sav/base_virtual_type_redef.res b/tests/sav/base_virtual_type_redef.res
new file mode 100644 (file)
index 0000000..0a956f4
--- /dev/null
@@ -0,0 +1,2 @@
+base_virtual_type_redef.nit:24,13--17: Ambigous property name 'OTHER' for Int; conflict between base_virtual_type_redef::Number::OTHER and standard::kernel::Comparable::OTHER
+base_virtual_type_redef.nit:24,2--22: Error: No property Int::OTHER is inherited. Remove the redef keyword to define a new property.
diff --git a/tests/sav/egl.res b/tests/sav/egl.res
new file mode 100644 (file)
index 0000000..e69de29
index 79de0b8..9a470bf 100644 (file)
@@ -21,7 +21,7 @@ alt/error_expr_not_ok_alt4.nit:66,7--10: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt4.nit:66,21: Type error: expected A, got Int
 alt/error_expr_not_ok_alt4.nit:67,1--18: Warning: use 'loop' instead of 'while true do'.
 alt/error_expr_not_ok_alt4.nit:69,24: Type error: expected A, got Int
-alt/error_expr_not_ok_alt4.nit:69,1--25: Type Error: Expected method 'iterator' in type Int
+alt/error_expr_not_ok_alt4.nit:69,1--25: Type Error: 'for' expects a type providing 'iterator' method, got 'Int'.
 alt/error_expr_not_ok_alt4.nit:71,8--11: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt4.nit:72,7--15: Type error: expected A, got Int
 alt/error_expr_not_ok_alt4.nit:73,7--10: Type error: expected Bool, got Int
index ea9447d..0896d50 100644 (file)
@@ -17,7 +17,7 @@ alt/error_expr_not_ok_alt5.nit:66,7--10: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt5.nit:66,21: Type error: expected A, got Int
 alt/error_expr_not_ok_alt5.nit:67,1--18: Warning: use 'loop' instead of 'while true do'.
 alt/error_expr_not_ok_alt5.nit:69,24: Type error: expected A, got Int
-alt/error_expr_not_ok_alt5.nit:69,1--25: Type Error: Expected method 'iterator' in type Int
+alt/error_expr_not_ok_alt5.nit:69,1--25: Type Error: 'for' expects a type providing 'iterator' method, got 'Int'.
 alt/error_expr_not_ok_alt5.nit:71,8--11: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt5.nit:72,7--15: Type error: expected A, got Int
 alt/error_expr_not_ok_alt5.nit:73,7--10: Type error: expected Bool, got Int
index 5320e63..9e3b463 100644 (file)
@@ -21,7 +21,7 @@ alt/error_expr_not_ok_alt6.nit:66,7--10: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt6.nit:66,21: Type error: expected A, got Int
 alt/error_expr_not_ok_alt6.nit:67,1--18: Warning: use 'loop' instead of 'while true do'.
 alt/error_expr_not_ok_alt6.nit:69,24: Type error: expected A, got Int
-alt/error_expr_not_ok_alt6.nit:69,1--25: Type Error: Expected method 'iterator' in type Int
+alt/error_expr_not_ok_alt6.nit:69,1--25: Type Error: 'for' expects a type providing 'iterator' method, got 'Int'.
 alt/error_expr_not_ok_alt6.nit:71,8--11: Type error: expected Bool, got Int
 alt/error_expr_not_ok_alt6.nit:72,7--15: Type error: expected A, got Int
 alt/error_expr_not_ok_alt6.nit:73,7--10: Type error: expected Bool, got Int
index cfcda5e..b3ba3de 100644 (file)
@@ -1 +1 @@
-error_for_coll.nit:17,1--18,3: Type Error: Expected method 'iterator' in type Int
+error_for_coll.nit:17,1--18,3: Type Error: 'for' expects a type providing 'iterator' method, got 'Int'.
index ce6b6db..802c302 100644 (file)
@@ -1,2 +1,2 @@
 alt/error_needed_method_alt2.nit:47,10--27: Cannot instantiate interface Collection[Int].
-alt/error_needed_method_alt2.nit:47,1--40: Type Error: Expected method 'iterator' in type Collection[Int]
+alt/error_needed_method_alt2.nit:47,1--40: Type Error: 'for' expects a type providing 'iterator' method, got 'Collection[Int]'.
index e0c62db..59a8aed 100644 (file)
@@ -1 +1 @@
-alt/error_needed_types_alt8.nit:21,1--22,3: Type Error: Expected method 'iterator' in type L
+alt/error_needed_types_alt8.nit:21,1--22,3: Type Error: 'for' expects a type providing 'iterator' method, got 'L'.
diff --git a/tests/sav/glesv2.res b/tests/sav/glesv2.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/nitc/base_for_nullable.res b/tests/sav/nitc/base_for_nullable.res
new file mode 100644 (file)
index 0000000..a75893d
--- /dev/null
@@ -0,0 +1 @@
+base_for_nullable.nit:21,10--13: Type error: 'for' on a nullable expression.
diff --git a/tests/sav/nitc/base_for_nullable_alt1.res b/tests/sav/nitc/base_for_nullable_alt1.res
new file mode 100644 (file)
index 0000000..1baed81
--- /dev/null
@@ -0,0 +1 @@
+alt/base_for_nullable_alt1.nit:21,10--13: Type error: 'for' on a nullable expression.
diff --git a/tests/sav/nitc/base_for_nullable_alt2.res b/tests/sav/nitc/base_for_nullable_alt2.res
new file mode 100644 (file)
index 0000000..14de0ee
--- /dev/null
@@ -0,0 +1 @@
+alt/base_for_nullable_alt2.nit:21,10--13: Type error: 'for' on a nullable expression.
index 243fc46..61f2d87 100644 (file)
@@ -14,6 +14,7 @@ usage: nitdoc [options] file...
   -d, --dir                Directory where doc is generated
   --source                 What link for source (%f for filename, %l for first line, %L for last line)
   --sharedir               Directory containing the nitdoc files
+  --shareurl               Do not copy shared files, link JS and CSS file to share url instead
   --no-dot                 Do not generate graphes with graphviz
   --private                Generate the private API
   --custom-title           Title displayed in the top of the Overview page and as suffix of all page names
index 7c2f531..4a272d5 100644 (file)
@@ -1,9 +1,9 @@
-ZeroClipboard.swf
 class_module_0_Int.html
 class_module_0_Object.html
 class_module_0_Sys.html
 class_module_1_A.html
 class_module_1_B.html
+css/
 dep.dot
 dep.map
 dep.png
@@ -37,10 +37,9 @@ dep_module_1.map
 dep_module_1.png
 dep_module_1.s.dot
 index.html
+js/
 module_module_0.html
 module_module_1.html
 quicksearch-list.js
 resources/
-scripts/
 search.html
-styles/
index 8ba93ce..6f84637 100644 (file)
@@ -11,6 +11,8 @@
   --only-parse            Only proceed to parse step of loaders
   --only-metamodel        Stop after meta-model processing
   --all                   Compute all metrics
+  --mmodules              Compute metrics about mmodules
+  --mclasses              Compute metrics about mclasses
   --inheritance           Compute metrics about inheritance usage
   --refinement            Compute metrics about refinement usage
   --self                  Compute metrics about the usage of explicit and implicit self
@@ -23,3 +25,4 @@
   --generate_hyperdoc     Generate Hyperdoc
   --poset                 Complete metrics on posets
   -d, --dir               Directory where some statistics files are generated
+  --no-colors             Disable colors in console outputs
index adcfffd..2e82c7f 100644 (file)
@@ -1,4 +1,162 @@
 *** METRICS ***
+
+# MModules metrics
+
+ ## project base_simple3
+  `- group base_simple3
+       mnoa: number of ancestor modules
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnop: number of parent modules
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnoc: number of child modules
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnod: number of descendant modules
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mdit: depth in module tree
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnbi: number of introduction in module
+           avg: 7.0
+           max: base_simple3 (7)
+           min: base_simple3 (7)
+       mnbr: number of refinement in module
+           avg: 1.0
+           max: base_simple3 (1)
+           min: base_simple3 (1)
+       mnbcc: number of concrete class in module (intro + redef)
+           avg: 4.0
+           max: base_simple3 (4)
+           min: base_simple3 (4)
+       mnbac: number of abstract class in module (intro + redef)
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnbic: number of interface in module (intro + redef)
+           avg: 2.0
+           max: base_simple3 (2)
+           min: base_simple3 (2)
+
+ ## global metrics
+       mnoa: number of ancestor modules
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnop: number of parent modules
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnoc: number of child modules
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnod: number of descendant modules
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mdit: depth in module tree
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnbi: number of introduction in module
+           avg: 7.0
+           max: base_simple3 (7)
+           min: base_simple3 (7)
+       mnbr: number of refinement in module
+           avg: 1.0
+           max: base_simple3 (1)
+           min: base_simple3 (1)
+       mnbcc: number of concrete class in module (intro + redef)
+           avg: 4.0
+           max: base_simple3 (4)
+           min: base_simple3 (4)
+       mnbac: number of abstract class in module (intro + redef)
+           avg: 0.0
+           max: base_simple3 (0)
+           min: base_simple3 (0)
+       mnbic: number of interface in module (intro + redef)
+           avg: 2.0
+           max: base_simple3 (2)
+           min: base_simple3 (2)
+
+# MClasses metrics
+
+ ## project base_simple3
+  `- group base_simple3
+       cnoa: number of ancestor classes
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnop: number of parent classes
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnoc: number of child classes
+           avg: 0.857
+           max: Object (6)
+           min: Bool (0)
+       cnod: number of descendant classes
+           avg: 0.857
+           max: Object (6)
+           min: Bool (0)
+       cdit: depth in class tree
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnbip: number of introduced properties
+           avg: 2.714
+           max: C (7)
+           min: Bool (0)
+       cnbrp: number of redefined properties
+           avg: 0.0
+           max: Object (0)
+           min: Object (0)
+       cnbhp: number of inherited properties
+           avg: 2.571
+           max: Bool (3)
+           min: Object (0)
+
+ ## global metrics
+       cnoa: number of ancestor classes
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnop: number of parent classes
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnoc: number of child classes
+           avg: 0.857
+           max: Object (6)
+           min: Bool (0)
+       cnod: number of descendant classes
+           avg: 0.857
+           max: Object (6)
+           min: Bool (0)
+       cdit: depth in class tree
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnbip: number of introduced properties
+           avg: 2.714
+           max: C (7)
+           min: Bool (0)
+       cnbrp: number of redefined properties
+           avg: 0.0
+           max: Object (0)
+           min: Object (0)
+       cnbhp: number of inherited properties
+           avg: 2.571
+           max: Bool (3)
+           min: Object (0)
 --- Poset metrics ---
 ## Module importation hierarchy
 Number of nodes: 1
@@ -186,86 +344,6 @@ Distribution of direct smallers
   b: 2 (3.70%)
   Object: 1 (1.85%)
   Bool: 1 (1.85%)
---- Global Summary metrics ---
-(NMD) Number of Modules: 1
-(NC)  Number of Classes: 4
-(NI)  Number of Interfaces: 1
-(NAC)  Number of Abstract Classes: 0
-(NGC)  Number of Generic Classes: 0
-(NGI)  Number of Generic Interfaces: 0
---- (SL) Std-Lib Summary metrics ---
-(NMDSL) Number of Modules: 0
-(NCSL)  Number of Classes: 0
-(NISL)  Number of Interfaces: 0
-(NACSL)  Number of Abstract Classes: 0
-(NGCSL)  Number of Generic Classes: 0
-(NGISL)  Number of Generic Interfaces: 0
---- (UD) User-Defined Summary metrics ---
-(NMDUD) Number of Modules: 1
-(NCUD)  Number of Classes: 4
-(NIUD)  Number of Interfaces: 1
-(NACUD)  Number of Abstract Classes: 0
-(NGCUD)  Number of Generic Classes: 0
-(NGIUD)  Number of Generic Interfaces: 0
-
---- Global Inheritance metrics ---
-(DIT) Global Depth in Inheritance Tree: 0.85
-(DUI) Proportion of types inheriting another type other than Object: 0.0%
-(CCDUI) Proportion of classes that extend some other class: 0.0%
-(CIDUI) Proportion of classes that implement some other interface: 0.0%
-(IIDUI) Proportion of interfaces that extend some other interface: 0.0%
-(IF) Proportion of types Inherited From: 20.00%
-(CCIF) Proportion of classes extended by class: 0.0%
-(ICIF) Proportion of interfaces implemented by class: 100.00%
-(IIIF) Proportion of interfaces extended by interface: 100.00%
-
---- (SL -> *) Std-Lib Inheritance metrics ---
-(SLDUI) Proportion of SL types inheriting another type other than Object: na%
-(SLCCDUI) Proportion of SL classes that extend some other class: na%
-(SLCIDUI) Proportion of SL classes that implement some other interface: na%
-(SLIIDUI) Proportion of SL interfaces that extend some other interface: na%
-(SLIF) Proportion of SL types Inherited From: na%
-(SLCCIF) Proportion of SL classes extended by class: na%
-(SLICIF) Proportion of SL interfaces implemented by class: na%
-(SLIIIF) Proportion of SL interfaces extended by interface: na%
-
---- (SL -> SL) Std-Lib Inheritance metrics ---
-(SLIFSL) Proportion of SL types Inherited From by SL type: na%
-(SLCCIFSL) Proportion of SL classes extended by SL class: na%
-(SLICIFSL) Proportion of SL interfaces implemented by SL class: na%
-(SLIIIFSL) Proportion of SL interfaces extended by SL interface: na%
-
---- (SL->UD) Std-Lib Inheritance metrics ---
-(SLIFUD) Proportion of SL types Inherited From by UD type: na%
-(SLCCIFUD) Proportion of SL classes extended by UD class: na%
-(SLICIFUD) Proportion of SL interfaces implemented by UD class: na%
-(SLIIIFUD) Proportion of SL interfaces extended by UD interface: na%
-
---- (UD->*) User-Defined Inheritance metrics ---
-(UDDUI) Proportion of UD types inheriting another type other than Object: 0.0%
-(UDCCDUI) Proportion of UD classes that extend some other class: 0.0%
-(UDCIDUI) Proportion of UD classes that implement some other interface: 0.0%
-(UDIIDUI) Proportion of UD interfaces that extend some other interface: 0.0%
-(UDIF) Proportion of UD types Inherited From: 20.00%
-(UDCCIF) Proportion of UD classes extended by class: 0.0%
-(UDICIF) Proportion of UD interfaces implemented by class: 100.00%
-(UDIIIF) Proportion of UD interfaces extended by interface: 100.00%
-
---- (UD -> SL) User-Defined Inheritance metrics ---
-(UDDUISL) Proportion of UD types inheriting another type other SL type: 0.0%
-(UDCCDUISL) Proportion of UD classes that extend some other SL class: 0.0%
-(UDCIDUISL) Proportion of UD classes that implement some other SL interface: 0.0%
-(UDIIDUISL) Proportion of UD interfaces that extend some other SL interface: 0.0%
-
---- (UD -> UD) User-Defined Inheritance metrics ---
-(UDDUIUD) Proportion of UD types inheriting another type other UD type: 0.0%
-(UDCCDUIUD) Proportion of UD classes that extend some other UD class: 0.0%
-(UDCIDUIUD) Proportion of UD classes that implement some other UD interface: 0.0%
-(UDIIDUIUD) Proportion of UD interfaces that extend some other UD interface: 0.0%
-(UDIFUD) Proportion of UD types Inherited From: 20.00%
-(UDCCIFUD) Proportion of UD classes extended by UD class: 0.0%
-(UDICIFUD) Proportion of UD interfaces implemented by UD class: 100.00%
-(UDIIIFUD) Proportion of UD interfaces extended by UD interface: 100.00%
 --- Metrics of refinement usage ---
 Number of modules: 1
 
@@ -303,7 +381,7 @@ Statistics of type usage:
   C: 1 (11.11%)
   B: 1 (11.11%)
   A: 1 (11.11%)
---- Sends on Nullable Reciever ---
+--- Sends on Nullable Receiver ---
 Total number of sends: 19
 Number of sends on a nullable receiver: 0 (0.0%)
 Number of buggy sends (cannot determine the type of the receiver): 0 (0.0%)
@@ -328,6 +406,117 @@ Number of live runtime cast types (ie used in as and isa): 0
 Number of dead method definitions of live methods: 0
 generating out/nitmetrics_args1.write/project_hierarchy.dot
 generating out/nitmetrics_args1.write/module_hierarchy.dot
+
+# Inheritance metrics
+
+ ## project base_simple3
+  `- group base_simple3
+       cnoa: number of ancestor classes
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnop: number of parent classes
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnoc: number of child classes
+           avg: 0.857
+           max: Object (6)
+           min: Bool (0)
+       cnodc: number of class_kind descendants
+           avg: 0.571
+           max: Object (4)
+           min: Bool (0)
+       cnodi: number of interface_kind descendants
+           avg: 0.0
+           max: Object (0)
+           min: Object (0)
+       cdit: depth in class tree
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cditi: depth in class tree following only interface_kind
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       mdui: proportion of mclass defined using inheritance (has other parent than Object)
+           avg: 0.0
+           max: base_simple3 (0.0)
+           min: base_simple3 (0.0)
+       mduic: proportion of class_kind defined using inheritance
+           avg: 0.0
+           max: base_simple3 (0.0)
+           min: base_simple3 (0.0)
+       mduii: proportion of interface_kind defined using inheritance
+           avg: 0.0
+           max: base_simple3 (0.0)
+           min: base_simple3 (0.0)
+       mif: proportion of mclass inherited from
+           avg: 0.143
+           max: base_simple3 (0.143)
+           min: base_simple3 (0.143)
+       mifc: proportion of class_kind inherited from
+           avg: 0.0
+           max: base_simple3 (0.0)
+           min: base_simple3 (0.0)
+       mifi: proportion of interface_kind inherited from
+           avg: 0.143
+           max: base_simple3 (0.143)
+           min: base_simple3 (0.143)
+
+ ## global metrics
+       cnoa: number of ancestor classes
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnop: number of parent classes
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cnoc: number of child classes
+           avg: 0.857
+           max: Object (6)
+           min: Bool (0)
+       cnodc: number of class_kind descendants
+           avg: 0.571
+           max: Object (4)
+           min: Bool (0)
+       cnodi: number of interface_kind descendants
+           avg: 0.0
+           max: Object (0)
+           min: Object (0)
+       cdit: depth in class tree
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       cditi: depth in class tree following only interface_kind
+           avg: 0.857
+           max: Bool (1)
+           min: Object (0)
+       mdui: proportion of mclass defined using inheritance (has other parent than Object)
+           avg: 0.0
+           max: base_simple3 (0.0)
+           min: base_simple3 (0.0)
+       mduic: proportion of class_kind defined using inheritance
+           avg: 0.0
+           max: base_simple3 (0.0)
+           min: base_simple3 (0.0)
+       mduii: proportion of interface_kind defined using inheritance
+           avg: 0.0
+           max: base_simple3 (0.0)
+           min: base_simple3 (0.0)
+       mif: proportion of mclass inherited from
+           avg: 0.143
+           max: base_simple3 (0.143)
+           min: base_simple3 (0.143)
+       mifc: proportion of class_kind inherited from
+           avg: 0.0
+           max: base_simple3 (0.0)
+           min: base_simple3 (0.0)
+       mifi: proportion of interface_kind inherited from
+           avg: 0.143
+           max: base_simple3 (0.143)
+           min: base_simple3 (0.143)
 class_hierarchy.dot
 classdef_hierarchy.dot
 model.html
diff --git a/tests/sav/opengles2_hello_triangle.res b/tests/sav/opengles2_hello_triangle.res
new file mode 100644 (file)
index 0000000..e69de29
index 10ec001..f965cb5 100644 (file)
@@ -1 +1 @@
-Runtime error: Reciever is null (alt/rterror_attr_def_alt6.nit:30)
+Runtime error: Receiver is null (alt/rterror_attr_def_alt6.nit:30)
index 15d798d..66ef874 100644 (file)
@@ -1,2 +1,2 @@
-Runtime error: Reciever is null (alt/rterror_attr_def_alt8.nit:49)
+Runtime error: Receiver is null (alt/rterror_attr_def_alt8.nit:49)
 c1
index 5fdc7c0..b53ad44 100644 (file)
@@ -1,3 +1,3 @@
-Runtime error: Reciever is null (alt/rterror_null_receiver_alt1.nit:26)
+Runtime error: Receiver is null (alt/rterror_null_receiver_alt1.nit:26)
 true
 false
index e1716a3..9b883f5 100644 (file)
@@ -1,3 +1,3 @@
-Runtime error: Reciever is null (alt/rterror_null_receiver_alt2.nit:27)
+Runtime error: Receiver is null (alt/rterror_null_receiver_alt2.nit:27)
 true
 false
index 45aa239..bc40609 100644 (file)
@@ -1,3 +1,3 @@
-Runtime error: Reciever is null (alt/rterror_null_receiver_alt3.nit:28)
+Runtime error: Receiver is null (alt/rterror_null_receiver_alt3.nit:28)
 true
 false
index 322a95b..920c2aa 100644 (file)
@@ -1,3 +1,3 @@
-Runtime error: Reciever is null (alt/rterror_null_receiver_alt4.nit:29)
+Runtime error: Receiver is null (alt/rterror_null_receiver_alt4.nit:29)
 true
 false
index 4e1643d..2c638a5 100644 (file)
@@ -1,3 +1,3 @@
-Runtime error: Reciever is null (alt/rterror_null_receiver_alt5.nit:30)
+Runtime error: Receiver is null (alt/rterror_null_receiver_alt5.nit:30)
 true
 false
index 40840ce..35be98a 100644 (file)
@@ -1,3 +1,3 @@
-Runtime error: Reciever is null (alt/rterror_null_receiver_alt6.nit:31)
+Runtime error: Receiver is null (alt/rterror_null_receiver_alt6.nit:31)
 true
 false
diff --git a/tests/sav/test_ffi_cpp_callbacks.res b/tests/sav/test_ffi_cpp_callbacks.res
new file mode 100644 (file)
index 0000000..46f13fb
--- /dev/null
@@ -0,0 +1,10 @@
+4
+3
+2
+1
+Vector is empty!
+1234
+Vector is empty!
+1234
+Vector is empty!
+1234
diff --git a/tests/sav/test_ffi_cpp_header.res b/tests/sav/test_ffi_cpp_header.res
new file mode 100644 (file)
index 0000000..2240262
--- /dev/null
@@ -0,0 +1,4 @@
+4
+3
+2
+1
diff --git a/tests/sav/test_ffi_cpp_simple_fun.res b/tests/sav/test_ffi_cpp_simple_fun.res
new file mode 100644 (file)
index 0000000..802992c
--- /dev/null
@@ -0,0 +1 @@
+Hello world
diff --git a/tests/sav/test_ffi_cpp_strings.res b/tests/sav/test_ffi_cpp_strings.res
new file mode 100644 (file)
index 0000000..e61acab
--- /dev/null
@@ -0,0 +1,10 @@
+4
+3
+2
+1
+Vector is empty!
+1234
+3rd safe pop
+1234
+4th safe pop
+1234
diff --git a/tests/sav/test_ffi_cpp_types.res b/tests/sav/test_ffi_cpp_types.res
new file mode 100644 (file)
index 0000000..2240262
--- /dev/null
@@ -0,0 +1,4 @@
+4
+3
+2
+1
diff --git a/tests/sav/test_file_copy.res b/tests/sav/test_file_copy.res
new file mode 100644 (file)
index 0000000..632da3c
--- /dev/null
@@ -0,0 +1,26 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var dir = "out/test_file_copy/"
+if not dir.file_exists then dir.mkdir
+
+var src = "test_file_copy.nit"
+var dst = "{dir}/copy.nit"
+src.file_copy_to dst
+
+var file = new IFStream.open(dst)
+printn file.read_all
+file.close
diff --git a/tests/sav/x11.res b/tests/sav/x11.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/test_ffi_cpp_callbacks.nit b/tests/test_ffi_cpp_callbacks.nit
new file mode 100644 (file)
index 0000000..e212c32
--- /dev/null
@@ -0,0 +1,71 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Module wrapping the C++ class vector<int>
+module test_ffi_cpp_callbacks
+
+in "C++ Header" `{
+       #include <vector>
+
+       using namespace std;
+`}
+
+# Nit class over C++'s vector<int>
+extern class CppVector in "C++" `{vector<int>*`}
+
+       # Extern constructor
+       new in "C++" `{
+               return new vector<int>();
+       `}
+
+       # Adds an element to the end of the vector
+       fun push(v: Int) in "C++" `{
+               recv->push_back(v);
+       `}
+
+       # Pops an element from the end of the vector
+       fun pop: Int in "C++" `{
+               long val = recv->back();
+               recv->pop_back();
+               return val;
+       `}
+
+       fun safe_pop_with_default(default_return: Int): Int import report_error in "C++" `{
+               if (recv->empty()) {
+                       CppVector_report_error(recv);
+                       return default_return;
+               } else {
+                       long val = recv->back();
+                       recv->pop_back();
+                       return val;
+               }
+       `}
+
+       private fun report_error do print "Vector is empty!"
+end
+
+var a = new CppVector
+a.push(1)
+a.push(2)
+a.push(3)
+a.push(4)
+print a.pop
+print a.pop
+print a.pop
+print a.safe_pop_with_default(1234)
+print a.safe_pop_with_default(1234)
+print a.safe_pop_with_default(1234)
+print a.safe_pop_with_default(1234)
diff --git a/tests/test_ffi_cpp_header.nit b/tests/test_ffi_cpp_header.nit
new file mode 100644 (file)
index 0000000..9dbe759
--- /dev/null
@@ -0,0 +1,47 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_ffi_cpp_header
+
+in "C++" `{
+       #include <vector>
+
+       using namespace std;
+
+       vector<long> vec;
+`}
+
+class CppVector
+       fun push(v: Int) in "C++" `{
+               vec.push_back(v);
+       `}
+
+       fun pop: Int in "C++" `{
+               long val = vec.back();
+               vec.pop_back();
+               return val;
+       `}
+end
+
+var a = new CppVector
+a.push(1)
+a.push(2)
+a.push(3)
+a.push(4)
+print a.pop
+print a.pop
+print a.pop
+print a.pop
diff --git a/tests/test_ffi_cpp_simple_fun.nit b/tests/test_ffi_cpp_simple_fun.nit
new file mode 100644 (file)
index 0000000..9c0c5f4
--- /dev/null
@@ -0,0 +1,26 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_ffi_cpp_simple_fun
+
+class A
+       fun foo in "C++" `{
+               std::cout << "Hello world\n";
+       `}
+end
+
+var a = new A
+a.foo
diff --git a/tests/test_ffi_cpp_strings.nit b/tests/test_ffi_cpp_strings.nit
new file mode 100644 (file)
index 0000000..5b6c59f
--- /dev/null
@@ -0,0 +1,88 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Module wrapping the C++ class vector<int>
+module test_ffi_cpp_strings
+
+import cpp # gives us String.to_cpp_string and the CppString class
+
+in "C++ Header" `{
+       #include <vector>
+
+       using namespace std;
+`}
+
+# Nit class over C++'s vector<int>
+extern class CppVector in "C++" `{vector<int>*`}
+
+       # Extern constructor
+       new in "C++" `{
+               return new vector<int>();
+       `}
+
+       # Adds an element to the end of the vector
+       fun push(v: Int) in "C++" `{
+               recv->push_back(v);
+       `}
+
+       # Pops an element from the end of the vector
+       fun pop: Int in "C++" `{
+               long val = recv->back();
+               recv->pop_back();
+               return val;
+       `}
+
+       # Uses a callback to report when receiver is empty
+       fun safe_pop_with_default(default_return: Int): Int import report_error in "C++" `{
+               if (recv->empty()) {
+                       CppVector_report_error(recv);
+                       return default_return;
+               } else {
+                       long val = recv->back();
+                       recv->pop_back();
+                       return val;
+               }
+       `}
+
+       # Callback for `safe_pop_with_default`
+       private fun report_error do print "Vector is empty!"
+
+       # Prints the given string when receiver is empty
+       fun safe_pop_with_custom_error(default_return: Int, error_msg: String): Int import String.to_cpp_string in "C++" `{
+               if (recv->empty()) {
+                       string *cpp_error_msg = String_to_cpp_string(error_msg);
+                       cout << *cpp_error_msg << "\n";
+                       return default_return;
+               } else {
+                       long val = recv->back();
+                       recv->pop_back();
+                       return val;
+               }
+       `}
+end
+
+var a = new CppVector
+a.push(1)
+a.push(2)
+a.push(3)
+a.push(4)
+print a.pop
+print a.pop
+print a.pop
+print a.safe_pop_with_default(1234)
+print a.safe_pop_with_default(1234)
+print a.safe_pop_with_custom_error(1234, "3rd safe pop")
+print a.safe_pop_with_custom_error(1234, "4th safe pop")
diff --git a/tests/test_ffi_cpp_types.nit b/tests/test_ffi_cpp_types.nit
new file mode 100644 (file)
index 0000000..6cdd3f5
--- /dev/null
@@ -0,0 +1,55 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Module wrapping the C++ class vector<int>
+module test_ffi_cpp_types
+
+in "C++ Header" `{
+       #include <vector>
+
+       using namespace std;
+`}
+
+# Nit class over C++'s vector<int>
+extern class CppVector in "C++" `{vector<int>*`}
+
+       # Extern constructor
+       new in "C++" `{
+               return new vector<int>();
+       `}
+
+       # Adds an element to the end of the vector
+       fun push(v: Int) in "C++" `{
+               recv->push_back(v);
+       `}
+
+       # Pops an element from the end of the vector
+       fun pop: Int in "C++" `{
+               long val = recv->back();
+               recv->pop_back();
+               return val;
+       `}
+end
+
+var a = new CppVector
+a.push(1)
+a.push(2)
+a.push(3)
+a.push(4)
+print a.pop
+print a.pop
+print a.pop
+print a.pop
diff --git a/tests/test_file_copy.nit b/tests/test_file_copy.nit
new file mode 100644 (file)
index 0000000..632da3c
--- /dev/null
@@ -0,0 +1,26 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var dir = "out/test_file_copy/"
+if not dir.file_exists then dir.mkdir
+
+var src = "test_file_copy.nit"
+var dst = "{dir}/copy.nit"
+src.file_copy_to dst
+
+var file = new IFStream.open(dst)
+printn file.read_all
+file.close