As discussed in #2133, contribution guidelines are hard to find.
This PR is an attempt to ease the process by giving newcomer friendly advices and some more insight on the contribution process for Nit.
@tonygaetani, do you think a document like this one would have been helpful for you ? Is there anything you would change to make it friendlier/clearer ?
Close #2133
Pull-Request: #2134
Reviewed-by: Jean Privat <jean@pryen.org>
c_src/** -diff
tests/sav/**/*.res -whitespace
-lib/popcorn/tests/res/*.res -whitespace
+*.res -whitespace
*.patch -whitespace
2015 Jean-Philippe Caissy <jean-philippe.caissy@shopify.com>
2015 Alexandre Blondin Massé <alexandre.blondin.masse@gmail.com>
2015-2016 Guilherme Mansur <guilhermerpmansur@gmail.com>
+ 2016 Tony Gaetani <tony.gaetani@gmail.com>
License: Apache 2.0 (see LICENSE)
Comment: The main license of the work, except for the following exceptions
* gcc http://gcc.gnu.org/ (or a compatible C compiler)
* pkg-config http://www.freedesktop.org/wiki/Software/pkg-config/
* ccache http://ccache.samba.org/ to improve recompilation
- * libgc-dev http://www.hpl.hp.com/personal/Hans_Boehm/gc/
+ * libgc-dev http://hboehm.info/gc/
* graphviz http://www.graphviz.org/ to enable graphs with the nitdoc tool
* libunwind http://nongnu.org/libunwind
app.user = null
return true
else if res isa BenitluxError then
- app.feedback((res.user_message or else res.message).t)
+ feedback((res.user_message or else res.message).t)
return true
else if res isa Error then
- app.feedback res.message.t
+ feedback res.message.t
return true
end
return false
end
+
+ # Show feedback pertinent to the user, defaults to a platform specific popup
+ fun feedback(text: String) do app.feedback text
end
# Async request with services to act on the windows of the app
map["Welcome %0!"] = "Bienvenue %0!"
map["Logged in as %0"] = "Connecté en tant que %0"
map["Username"] = "Nom d'utilisateur"
- map["Invalid name"] = "Nom d'utilisateur invalide"
map["Password"] = "Mot de passe"
- map["Passwords must be composed of at least 6 characters."] = "Le mot de passe doit avoir au moins 6 charactères."
+ map["Repeat password"] = "Répéter le mot de passe"
map["Email"] = "Courriel"
map["Login"] = "Se connecter"
+ map["Loging in..."] = "Authentification..."
map["Logout"] = "Se déconnecter"
map["Signup"] = "Créer un compte"
+ map["Signing up..."] = "Création du compte..."
+
+ map["Passwords must be composed of at least 6 characters."] = "Le mot de passe doit avoir au moins 6 charactères."
+ map["Fill the following fields to sign up."] = "Remplissez les champs suivants pour créer un compte."
+
+ map["Passwords do not match."] = "Les mots de passe ne correspondent pas."
+ map["Invalid username."] = "Nom d'utilisateur invalide."
+ map["Invalid password."] = "Mot de passe invalide."
+ map["Username already in use."] = "Le nom d'utilisateur est déjà réservé."
+ map["Invalid username and password combination."] = "La combinaison de nom et mot de passe n'est pas reconnue."
# Social views
map["Follow"] = "Suivre"
class SignupWindow
super Window
- # Main window layout
- var layout = new ListLayout(parent=self)
+ private var list = new ListLayout(parent=self)
+ private var lbl_feedback = new Label(parent=list, text="Welcome")
- private var lbl_welcome = new Label(parent=layout, text="Welcome")
+ private var layout_login = new VerticalLayout(parent=list)
+
+ # ---
+ # First the login options
# Name
- private var name_line = new HorizontalLayout(parent=layout)
+ private var name_line = new HorizontalLayout(parent=layout_login)
private var lbl_name = new Label(parent=name_line, text="Username".t)
private var txt_name = new TextInput(parent=name_line, text=app.user)
- # Pass
- private var pass_line = new HorizontalLayout(parent=layout)
+ # Password
+ private var pass_line = new HorizontalLayout(parent=layout_login)
private var lbl_pass = new Label(parent=pass_line, text="Password".t)
private var txt_pass = new TextInput(parent=pass_line, is_password=true)
- private var lbl_pass_desc = new Label(parent=layout,
+ private var lbl_pass_desc = new Label(parent=layout_login, size = 0.5,
text="Passwords must be composed of at least 6 characters.".t)
- private var but_login = new Button(parent=layout, text="Login".t)
+ private var but_login = new Button(parent=layout_login, text="Login".t)
+
+ # ---
+ # Then, the signup options
+
+ private var layout_register = new VerticalLayout(parent=list)
+
+ private var lbl_signup_desc = new Label(parent=layout_register, size = 0.5,
+ text="Fill the following fields to sign up.".t)
+
+ # Repeat password
+ private var pass_line2 = new HorizontalLayout(parent=layout_register)
+ private var lbl_pass2 = new Label(parent=pass_line2, text="Repeat password".t)
+ private var txt_pass2 = new TextInput(parent=pass_line2, is_password=true)
# Email
- private var email_line = new HorizontalLayout(parent=layout)
+ private var email_line = new HorizontalLayout(parent=layout_register)
private var lbl_email = new Label(parent=email_line, text="Email".t)
private var txt_email = new TextInput(parent=email_line)
- private var but_signup = new Button(parent=layout, text="Signup".t)
-
- private var lbl_feedback = new Label(parent=layout, text="")
+ private var but_signup = new Button(parent=layout_register, text="Signup".t)
init
do
- lbl_pass_desc.size = 0.5
-
for c in [but_login, but_signup] do
c.observers.add self
end
var name = txt_name.text
if name == null or not name.name_is_ok then
- feedback "Invalid name".t
+ feedback "Invalid username.".t
return
end
var pass = txt_pass.text
if pass == null or not pass.pass_is_ok then
- feedback "Invalid password".t
+ feedback "Invalid password.".t
return
end
if sender == but_login then
+ feedback "Logging in...".t
(new LoginOrSignupAction(self, "rest/login?name={name}&pass={pass.pass_hash}")).start
else if sender == but_signup then
+ if pass != txt_pass2.text then
+ feedback "Passwords do not match.".t
+ return
+ end
+
var email = txt_email.text
if email == null or email.is_empty then
feedback "Invalid email".t
return
end
+ feedback "Signing up...".t
(new LoginOrSignupAction(self, "rest/signup?name={name}&pass={pass.pass_hash}&email={email}")).start
end
end
app.on_log_in
end
-end
-
-# Async request for signing up
-class SignupAction
- super WindowHttpRequest
- redef type W: SignupWindow
-
- init do affected_views.add_all([window.but_signup])
-
- redef fun on_load(res)
- do
- if intercept_error(res) then return
-
- if not res isa LoginResult then
- on_fail new Error("Server sent unexpected data {res or else "null"}")
- return
- end
-
- app.token = res.token
- app.user = res.user.name
- app.on_log_in
- end
+ redef fun feedback(text) do window.feedback text
end
# Check if already in user
var stmt = select("ROWID FROM users WHERE lower({user.to_sql_string}) = lower(name)")
assert stmt != null else print_error "Select 'sign_up' failed with: {error or else "?"}"
- if not stmt.iterator.to_a.is_empty then return "Username already in use"
+ if not stmt.iterator.to_a.is_empty then return "Username already in use."
# Check email use
stmt = select("ROWID FROM users WHERE lower({email.to_sql_string}) = lower(email)")
var entry = entries[path]
if not entry.is_dirty then continue
var name = entry.name
- if entry.has_source then name = entry.src_path.to_s
+ if entry.has_source then name = entry.src_path.as(not null)
if entry.is_new then
print " + {name}"
else
fun need_render(src, target: String): Bool do
if force_render then return true
if not target.file_exists then return true
- return src.file_stat.mtime >= target.file_stat.mtime
+ return src.file_stat.as(not null).mtime >= target.file_stat.as(not null).mtime
end
# Create a new `WikiSection`.
# Used to translate ids in beautiful page names.
fun pretty_name(name: String): String do
name = name.replace("_", " ")
- name = name.capitalized
+ name = name.capitalized(keep_upper=true)
return name
end
end
# Returns `-1` if not `has_source`.
fun create_time: Int do
if not has_source then return -1
- return src_full_path.file_stat.ctime
+ return src_full_path.as(not null).file_stat.as(not null).ctime
end
# Entry last modification time.
# Returns `-1` if not `has_source`.
fun last_edit_time: Int do
if not has_source then return -1
- return src_full_path.file_stat.mtime
+ return src_full_path.as(not null).file_stat.as(not null).mtime
end
# Entry list rendering time.
# Returns `-1` if `is_new`.
fun last_render_time: Int do
if is_new then return -1
- return out_full_path.file_stat.mtime
+ return out_full_path.file_stat.as(not null).mtime
end
# Entries hierarchy
# then returns the main wiki template file.
fun template_file: String do
if is_root then return wiki.config.template_file
- return parent.template_file
+ return parent.as(not null).template_file
end
# Header template file for `self`.
# Behave like `template_file`.
fun header_file: String do
if is_root then return wiki.config.header_file
- return parent.header_file
+ return parent.as(not null).header_file
end
# Footer template file for `self`.
# Behave like `template_file`.
fun footer_file: String do
if is_root then return wiki.config.footer_file
- return parent.footer_file
+ return parent.as(not null).footer_file
end
# Menu template file for `self`.
# Behave like `template_file`.
fun menu_file: String do
if is_root then return wiki.config.menu_file
- return parent.menu_file
+ return parent.as(not null).menu_file
end
# Display the entry `name`.
redef fun title do
if has_config then
- var title = config.title
+ var title = config.as(not null).title
if title != null then return title
end
return super
#
# Hidden section are rendered but not linked in menus.
fun is_hidden: Bool do
- if has_config then return config.is_hidden
+ if has_config then return config.as(not null).is_hidden
return false
end
if parent == null then
return wiki.config.source_dir
else
- return wiki.expand_path(parent.src_path, name)
+ return wiki.expand_path(parent.as(not null).src_path, name)
end
end
# Also check custom config.
redef fun template_file do
if has_config then
- var tpl = config.template_file
+ var tpl = config.as(not null).template_file
if tpl != null then return tpl
end
if is_root then return wiki.config.template_file
- return parent.template_file
+ return parent.as(not null).template_file
end
# Also check custom config.
redef fun header_file do
if has_config then
- var tpl = config.header_file
+ var tpl = config.as(not null).header_file
if tpl != null then return tpl
end
if is_root then return wiki.config.header_file
- return parent.header_file
+ return parent.as(not null).header_file
end
# Also check custom config.
redef fun footer_file do
if has_config then
- var tpl = config.footer_file
+ var tpl = config.as(not null).footer_file
if tpl != null then return tpl
end
if is_root then return wiki.config.footer_file
- return parent.footer_file
+ return parent.as(not null).footer_file
end
# Also check custom config.
redef fun menu_file do
if has_config then
- var tpl = config.menu_file
+ var tpl = config.as(not null).menu_file
if tpl != null then return tpl
end
if is_root then return wiki.config.menu_file
- return parent.menu_file
+ return parent.as(not null).menu_file
end
end
# Articles can only have `WikiSection` as parents.
redef type PARENT: WikiSection
- redef fun title: String do
+ redef fun title do
+ var parent = self.parent
if name == "index" and parent != null then return parent.title
return super
end
content = md
end
- redef var src_full_path: nullable String = null
+ redef var src_full_path = null
redef fun src_path do
var src_full_path = self.src_full_path
# REQUIRE: `has_source`.
var md: nullable String is lazy do
if not has_source then return null
- var file = new FileReader.open(src_full_path.to_s)
+ var file = new FileReader.open(src_full_path.as(not null))
var md = file.read_all
file.close
return md
redef fun is_dirty do
if super then return true
if has_source then
- return wiki.need_render(src_full_path.to_s, out_full_path)
+ return wiki.need_render(src_full_path.as(not null), out_full_path)
end
return false
end
var sidebar_blocks: Array[String] is lazy do
var res = new Array[String]
if not has_key("wiki.sidebar.blocks") then return res
- for val in at("wiki.sidebar.blocks").values do
+ for val in at("wiki.sidebar.blocks").as(not null).values do
res.add val
end
return res
redef class WikiSection
# Output directory (where to ouput the HTML pages for this section).
- redef fun out_path: String do
+ redef fun out_path do
+ var parent = self.parent
if parent == null then
return wiki.config.out_dir
else
# Copy attached files from `src_path` to `out_path`.
private fun copy_files do
assert has_source
- var dir = src_full_path.to_s
+ var dir = src_full_path.as(not null).to_s
for name in dir.files do
if name == wiki.config_filename then continue
if name.has_suffix(".md") then continue
redef class WikiArticle
- redef fun out_path: String do
+ redef fun out_path do
+ var parent = self.parent
if parent == null then
return wiki.expand_path(wiki.config.out_dir, "{name}.html")
else
# Returns `null` if no article can be found.
fun lookup_entry_by_name(context: WikiEntry, name: String): nullable WikiEntry do
var section: nullable WikiEntry = context.parent or else context
- var res = section.lookup_entry_by_name(name)
+ var res = section.as(not null).lookup_entry_by_name(name)
if res != null then return res
while section != null do
if section.name == name then return section
# Returns `null` if no article can be found.
fun lookup_entry_by_title(context: WikiEntry, title: String): nullable WikiEntry do
var section: nullable WikiEntry = context.parent or else context
- var res = section.lookup_entry_by_title(title)
+ var res = section.as(not null).lookup_entry_by_title(title)
if res != null then return res
while section != null do
if section.title.to_lower == title.to_lower then return section
fun is_index: Bool do return name == "index"
redef fun href do
+ var parent = self.parent
if parent == null then
return "{name}.html"
else
# limitations under the License.
# Test tools for NitRPG.
-module test_helper is test_suite
+module test_helper
import test_suite
import game
tags=educ,web,cli
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
license=Apache-2.0
+[source]
+exclude=src/parser/parser_abs.nit
[upstream]
browse=https://github.com/nitlang/nit/tree/master/contrib/pep8analysis/
git=https://github.com/nitlang/nit.git
if json isa JsonParseError then
die("Wrong input file ({json.message})")
abort
+ else if json == null then
+ die("Unable to parse input file as json (got null)")
+ abort
else if not json isa JsonObject then
die("Wrong input type (expected JsonObject got {json.class_name})")
abort
return new RefundStats.from_json(content)
end
- redef fun save_stats(stats: RefundStats) do
+ redef fun save_stats(stats) do
write_output(stats.to_json.to_pretty_json, stats_file)
end
end
proc.check_key(json, "reclamations")
var res = new Array[Reclamation]
var recls = json["reclamations"]
- if not recls isa JsonArray then
+ if recls == null then
+ proc.die("Wrong type for `number` (expected JsonArray got null)")
+ abort
+ else if not recls isa JsonArray then
proc.die("Wrong type for `number` (expected JsonArray got {recls.class_name})")
abort
end
var i = 0
for obj in recls do
- if not obj isa JsonObject then
+ if obj == null then
+ proc.die("Wrong type for `reclamations#{i}` (expected JsonObject got null)")
+ abort
+ else if not obj isa JsonObject then
proc.die("Wrong type for `reclamations#{i}` " +
"(expected JsonObject got {obj.class_name})")
abort
init from_json(proc: RefundProcessor, json: JsonObject) do
proc.check_key(json, "dossier")
var id = json["dossier"]
- if not id isa String then
+ if id == null then
+ proc.die("Wrong type for `dossier` (expected String got null)")
+ abort
+ else if not id isa String then
proc.die("Wrong type for `dossier` (expected String got {id.class_name})")
abort
end
init from_json(proc: RefundProcessor, json: JsonObject) do
proc.check_key(json, "mois")
var month = json["mois"]
- if not month isa String then
+ if month == null then
+ proc.die("Wrong type for `mois` (expected String got null)")
+ return
+ else if not month isa String then
proc.die("Wrong type for `mois` (expected String got {month.class_name})")
return
end
init from_json(proc: RefundProcessor, json: JsonObject) do
proc.check_key(json, "date")
var date = json["date"]
- if not date isa String then
+ if date == null then
+ proc.die("Wrong type for `date` (expected String got null)")
+ abort
+ else if not date isa String then
proc.die("Wrong type for `date` (expected String got {date.class_name})")
abort
end
private fun parse_care_id(proc: RefundProcessor, json: JsonObject): Int do
proc.check_key(json, "soin")
var id = json["soin"]
- if not id isa Int then
+ if id == null then
+ proc.die("Wrong type for `soin` (expected Int got null)")
+ abort
+ else if not id isa Int then
proc.die("Wrong type for `soin` (expected Int got {id.class_name})")
abort
end
private fun parse_fees(proc: RefundProcessor, json: JsonObject): Dollar do
proc.check_key(json, "montant")
var fees = json["montant"]
- if not fees isa String then
+ if fees == null then
+ proc.die("Wrong type for `fees` (expected String got null)")
+ abort
+ else if not fees isa String then
proc.die("Wrong type for `fees` (expected String got {fees.class_name})")
abort
end
print n.message
exit 1
end
- n = n.children.first.children.first.as(not null)
+ n = n.children.first.as(not null).children.first.as(not null)
if n isa Nplan then
print "Error: expected a problem, got a plan."
exit 1
assert n isa Nproblem
# Load all locations
- for n2 in n.n_locations.n_list.children do
+ for n2 in n.n_locations.n_list.as(not null).children do
var e = new Location(locations.length, n2.n_name.text, n2.n_x.text.to_f, n2.n_y.text.to_f)
assert not locations.has_key(e.name)
locations[e.name] = e
# Load all roads
var nbr = 0
- for n2 in n.n_roads.n_list.children do
+ for n2 in n.n_roads.n_list.as(not null).children do
var o = locations.get_or_null(n2.n_orig.text)
var d = locations.get_or_null(n2.n_dest.text)
assert o != null and d != null
# Load the robot
var robot = null
- for n2 in n.n_robots.n_list.children do
+ for n2 in n.n_robots.n_list.as(not null).children do
var name = n2.n_name.text
robot = locations.get_or_null(n2.n_emplacement.text)
assert name == robot_name and robot != null
# Load the parcels
var parcel_locations = new Array[nullable Location]
- for n2 in n.n_parcels.n_list.children do
+ for n2 in n.n_parcels.n_list.as(not null).children do
var name = n2.n_name.text
var e = locations.get_or_null(n2.n_emplacement.text)
assert e != null
print "# {parcels.length} parcels"
# Load the goal of parcels
- for n2 in n.n_goal.n_list.children do
+ for n2 in n.n_goal.n_list.as(not null).children do
var parcel = parcel_by_name.get_or_null(n2.n_name.text)
var e = locations.get_or_null(n2.n_emplacement.text)
assert parcel != null and e != null
print n.message
exit 1
end
- n = n.children.first.children.first.as(not null)
+ n = n.children.first.as(not null).children.first.as(not null)
if n isa Nproblem then
print "Error: expected a plan, got a problem."
exit 1
var res = new Plan(self)
var e = initial_state
var cost = 0.0
- for n2 in n.n_actions.children do
+ for n2 in n.n_actions.as(not null).children do
if n2 isa Naction_load then
var parcel = parcel_by_name.get_or_null(n2.n_parcel.text)
assert parcel != null
# Calculate the self-th element of the fibonacci sequence.
fun fibonacci: Int
do
- if self < 2 then
- return 1
- else
- return (self-2).fibonacci + (self-1).fibonacci
- end
- end
+ if self < 2 then return self
+ return (self-2).fibonacci + (self-1).fibonacci
+ end
end
# Print usage and exit.
* Life-cycle
* User interface
* Persistence
+* Async HTTP requests
* Package metadata
* Compilation and packaging
The features offered by _app.nit_ are common to all platforms, but
may not be available on all devices.
-## Application Life-Cycle
+# Application Life-Cycle
The _app.nit_ application life-cycle is compatible with all target platforms.
It relies on the following sequence of events, represented here by their callback method name:
Other UI elements, from the `ui` submodule, are notified of the same events using a simple depth first visit.
So all UI elements can react separately to live-cycle events.
-## User Interface
+# User Interface
The `app::ui` module defines an abstract API to build a portable graphical application.
The API is composed of interactive `Control`s, visible `View`s and an active `Window`.
* Add an observer to a `Button` instance, and implement `on_event` in the observer.
-### Usage Example
+## Usage Example
The calculator example (at `../../examples/calculator/src/calculator.nit`) is a concrete,
simple and complete use of the _app.nit_ portable UI.
-### Platform-specific UI
+## Platform-specific UI
You can go beyond the portable UI API of _app.nit_ by using the natives services of a platform.
The suggested approach is to use platform specific modules to customize the application on a precise platform.
-This module redefine `Window::on_start` to call the native language of the platform and setup a native UI.
+See the calculator example for an adaptation of the UI on Android,
+the interesting module is in this repository at ../../examples/calculator/src/android_calculator.nit
-_TODO complete description and add concrete examples_
-
-## Persistent State with data\_store
+# Persistent State with data\_store
_app.nit_ offers the submodule `app::data_store` to easily save the application state and user preferences.
The service is accessible by the method `App::data_store`. The `DataStore` itself defines 2 methods:
* `DataStore::[]` returns the object associated to a `String` key.
It returns `null` if nothing is associated to the key.
-### Usage Example
+## Usage Example
~~~
import app::data_store
end
~~~
-## Metadata annotations
+# Async HTTP request
+
+The module `app::http_request` provides services to execute asynchronous HTTP request.
+The class `AsyncHttpRequest` hides the complex parallel logic and
+lets the user implement methods acting only on the UI thread.
+See the documentation of `AsyncHttpRequest` for more information.
+
+# Metadata annotations
The _app.nit_ framework defines three annotations to customize the application package.
The special function `git_revision` will use the prefix of the hash of the latest git commit.
By default, the version is 0.1.
-### Usage Example
+## Usage Example
~~~
module my_module is
end
~~~
-## Compiling and Packaging an Application
+# Compiling and Packaging an Application
The Nit compiler detects the target platform from the importations and generates the appropriate application format and package.
Applications using only the portable services of _app.nit_ require some special care at compilation.
Such an application, let's say `calculator.nit`, does not depend on a specific platform and use the portable UI.
-The target platform must be specifed to the compiler for it to produce the correct application package.
+The target platform must be specified to the compiler for it to produce the correct application package.
There is two main ways to achieve this goal:
-* The the mixin option (`-m path`) loads an additionnal module before compiling.
+* The mixin option (`-m module`) imports an additional module before compiling.
It can be used to load platform specific implementations of the _app.nit_ portable UI.
~~~
# GNU/Linux version, using GTK
- nitc calculator.nit -m NIT_DIR/lib/linux/ui.nit
+ nitc calculator.nit -m linux
# Android version
- nitc calculator.nit -m NIT_DIR/lib/android/ui/
+ nitc calculator.nit -m android
+
+ # iOS version
+ nitc calculator.nit -m ios
~~~
* A common alternative for larger projects is to use platform specific modules.
- Continuing with the `calculator.nit` example, it can be accompagnied by the module `calculator_linux.nit`.
- This module imports both `calculator` and `linux::ui`, and can also use other GNU/Linux specific code.
+ Continuing with the calculator example, it is adapted for Android by the module `android_calculator.nit`.
+ This module imports both `calculator` and `android`, it can then use Android specific code.
~~~
- module calculator_linux
+ module android_calculator
import calculator
- import linux::ui
+ import android
+
+ # ...
~~~
fun run_on_ui_thread(task: Task) is abstract
end
-# Thread executing an HTTP request and deserializing JSON asynchronously
+# Thread executing an HTTP request asynchronously
#
-# This class defines four methods acting on the main/UI thread,
-# they should be implemented as needed:
-# * before
-# * on_load
-# * on_fail
-# * after
+# The request is sent to `rest_server_uri / rest_action`.
+#
+# If `deserialize_json`, the default behavior, the response is deserialized from JSON
+#
+# If `delay > 0.0`, sending the reqest is delayed by the given `delay` in seconds.
+# It can be used to delay resending a request on error.
+#
+# Four callback methods act on the main/UI thread,
+# they should be implemented as needed in subclasses:
+# * `before`
+# * `on_load`
+# * `on_fail`
+# * `after`
class AsyncHttpRequest
super Thread
[package]
name=app
-tags=lib
+tags=lib,mobile
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
license=Apache-2.0
[upstream]
# Offers the base 64 encoding and decoding algorithms
module base64
-redef class NativeString
- # Alphabet used by the base64 algorithm
- private fun base64_chars : SequenceRead[Byte]
- do
- return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".bytes
+redef class Char
+ # Is `self` a valid Base64 character ?
+ fun is_base64_char: Bool do
+ if code_point >= 127 then return false
+ return ascii.is_base64_char
end
+end
- # Reversed alphabet for base64
- private fun inverted_base64_chars : HashMap[Byte, Byte]
- do
- var inv_base64_chars = new HashMap[Byte, Byte]
- var l = base64_chars.length
- for k in [0 .. l[ do
- inv_base64_chars[base64_chars[k]] = k.to_b
+redef class Byte
+ # Is `self` a valid Base64 character ?
+ fun is_base64_char: Bool do
+ if self == b'+' then return true
+ if self == b'/' then return true
+ if self > b'Z' then
+ if self < b'a' then return false
+ if self <= b'z' then return true
+ return false
+ end
+ if self >= b'A' then return true
+ if self <= b'9' and self >= b'0' then return true
+ return false
+ end
+
+ # Returns the `base64` equivalent of `self`
+ #
+ # REQUIRE `self`.`is_base64_char`
+ fun to_base64_char: Byte do
+ if self == b'+' then return 62u8
+ if self == b'/' then return 63u8
+ if self > b'Z' then
+ if self < b'a' then abort
+ if self <= b'z' then return self - 71u8
+ abort
end
- return inv_base64_chars
+ if self >= b'A' then return self - 0x41u8
+ if self <= b'9' and self >= b'0' then return self + 4u8
+ abort
+ end
+end
+
+redef class NativeString
+ # Alphabet used by the base64 algorithm
+ private fun base64_chars : Bytes
+ do
+ return b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
end
# Encodes `self` to base64.
# By default, uses "=" for padding.
#
# assert "string".encode_base64 == "c3RyaW5n"
- private fun encode_base64(length: Int, padding: nullable Byte): Bytes do
+ private fun encode_base64(length: Int): Bytes do
var base64_bytes = once base64_chars
- if padding == null then padding = '='.ascii
var steps = length / 3
var bytes_in_last_step = length % 3
var result_length = steps * 4
result.add base64_bytes[((self[in_off + 1] & 0b0000_1111u8) << 2).to_i]
end
var rempad = if bytes_in_last_step > 0 then 3 - bytes_in_last_step else 0
- for i in [0 .. rempad[ do result.add padding
+ for i in [0 .. rempad[ do result.add b'='
return result
end
# Decodes `self` from base64
#
- # assert "c3RyaW5n".decode_base64 == "string"
- # assert "c3Rya\nW5n".decode_base64 == "string"
+ # assert "c3RyaW5n".decode_base64.to_s == "string"
+ # assert "c3Rya\nW5n".decode_base64.to_s == "string"
+ # assert "c3RyaW5nCg==".decode_base64.to_s == "string\n"
+ # assert "c3RyaW5nCg".decode_base64.to_s == "string\n"
+ # assert "c3RyaW5neQo=".decode_base64.to_s == "stringy\n"
+ # assert "c3RyaW5neQo".decode_base64.to_s == "stringy\n"
#
- # REQUIRE: `length % 4 == 0`
- private fun decode_base64(length: Int, padding: nullable Byte): Bytes do
- if padding == null then padding = '='.ascii
- var inv = once inverted_base64_chars
+ private fun decode_base64(length: Int): Bytes do
if length == 0 then return new Bytes.empty
- # Remove non-base64 chars
- var bytes = new Bytes.with_capacity(length)
- for k in [0 .. length[ do
- var byte = self[k]
- if inv.has_key(byte) or byte == padding then bytes.add(byte)
+ # Avoids constant unboxing
+ var pad = b'='
+
+ var result = new Bytes.with_capacity((length / 4 + 1) * 3)
+
+ var curr = 0
+ var cnt = 0
+ var endpos = -1
+ for i in [0 .. length[ do
+ var b = self[i]
+ if b == pad then
+ endpos = i
+ break
+ end
+ # Ignore whitespaces
+ if b <= 0x20u8 then continue
+ if not b.is_base64_char then continue
+ curr <<= 6
+ curr += b.to_base64_char.to_i
+ cnt += 1
+ if cnt == 4 then
+ result.add(((curr & 0xFF0000) >> 16).to_b)
+ result.add(((curr & 0xFF00) >> 8).to_b)
+ result.add((curr & 0xFF).to_b)
+ curr = 0
+ cnt = 0
+ end
end
- length = bytes.length
-
- var steps = length / 4
- var result_length = steps * 3
-
- var epos = length - 1
- var padding_len = 0
- while epos >= 0 and bytes[epos] == padding do
- epos -= 1
- padding_len += 1
+ if endpos != -1 or cnt != 0 then
+ var pads = 0
+ for i in [endpos .. length[ do
+ var b = self[i]
+ if b <= 0x20u8 then continue
+ pads += 1
+ end
+ if cnt == 2 then
+ curr >>= 4
+ result.add(curr.to_b)
+ else if cnt == 3 then
+ curr >>= 2
+ result.add(((curr & 0xFF00) >> 8).to_b)
+ result.add((curr & 0xFF).to_b)
+ end
end
+ return result
+ end
- if padding_len != 0 then steps -= 1
- if padding_len == 1 then result_length -= 1
- if padding_len == 2 then result_length -= 2
-
- var result = new Bytes.with_capacity(result_length + 1)
+ # Is `self` a well-formed Base64 entity ?
+ #
+ # ~~~nit
+ # assert "Qn03".is_base64
+ # assert not "#sd=".is_base64
+ # ~~~
+ fun is_base64(length: Int): Bool do return check_base64(length) == null
- for s in [0 .. steps[ do
- var c0 = inv[bytes[s * 4]]
- var c1 = inv[bytes[s * 4 + 1]]
- var c2 = inv[bytes[s * 4 + 2]]
- var c3 = inv[bytes[s * 4 + 3]]
- result.add (((c0 & 0b0011_1111u8) << 2) | ((c1 & 0b0011_0000u8) >> 4))
- result.add (((c1 & 0b0000_1111u8) << 4) | ((c2 & 0b0011_1100u8) >> 2))
- result.add (((c2 & 0b0000_0011u8) << 6) | (c3 & 0b0011_1111u8))
+ # Is `self` a well-formed Base64 entity ?
+ #
+ # Will return an Error otherwise with info on which part is erroneous.
+ fun check_base64(length: Int): nullable Error do
+ var rlen = 0
+ var opos = length
+ for i in [0 .. length[ do
+ if self[i] == b'=' then
+ opos = i
+ break
+ end
+ if self[i].is_whitespace then continue
+ if not self[i].is_base64_char then return new Error("Invalid Base64 character at position {i}: {self[i].ascii}")
+ rlen += 1
+ if rlen > 4 then rlen -= 4
end
-
- var last_start = steps * 4
- if padding_len == 1 then
- var c0 = inv[bytes[last_start]]
- var c1 = inv[bytes[last_start + 1]]
- var c2 = inv[bytes[last_start + 2]]
- result.add (((c0 & 0b0011_1111u8) << 2) | ((c1 & 0b0011_0000u8) >> 4))
- result.add (((c1 & 0b0000_1111u8) << 4) | ((c2 & 0b0011_1100u8) >> 2))
- else if padding_len == 2 then
- var c0 = inv[bytes[last_start]]
- var c1 = inv[bytes[last_start + 1]]
- result.add (((c0 & 0b0011_1111u8) << 2) | ((c1 & 0b0011_0000u8) >> 4))
+ var pad = 0
+ for i in [opos .. length[ do
+ if self[i].is_whitespace then continue
+ if self[i] != b'=' then return new Error("Invalid padding character {self[i].ascii} at position {i}")
+ pad += 1
end
-
- return result
+ if rlen + pad != 4 then return new Error("Invalid padding length")
+ return null
end
end
# Encodes the receiver string to base64 using a custom padding character.
#
# If using the default padding character `=`, see `encode_base64`.
- fun encode_base64(padding: nullable Byte): Bytes
- do
- return items.encode_base64(length, padding)
- end
+ fun encode_base64: Bytes do return items.encode_base64(length)
# Decodes the receiver string to base64 using a custom padding character.
#
# Default padding character `=`
- fun decode_base64(padding : nullable Byte) : Bytes
- do
- return items.decode_base64(length, padding)
- end
+ fun decode_base64: Bytes do return items.decode_base64(length)
+
+ # Is `self` a well-formed Base64 entity ?
+ fun is_base64: Bool do return items.is_base64(length)
+
+ # Is `self` a well-formed Base64 entity ?
+ #
+ # Will return an Error otherwise with info on which part is erroneous.
+ fun check_base64: nullable Error do return items.check_base64(length)
end
-redef class String
+redef class Text
# Encodes the receiver string to base64 using a custom padding character.
#
# If using the default padding character `=`, see `encode_base64`.
- fun encode_base64(padding: nullable Byte): String
- do
- return to_cstring.encode_base64(bytelen, padding).to_s
- end
+ fun encode_base64: String do return to_cstring.encode_base64(bytelen).to_s
# Decodes the receiver string to base64 using a custom padding character.
#
# Default padding character `=`
- fun decode_base64(padding : nullable Byte) : String
- do
- return to_cstring.decode_base64(bytelen, padding).to_s
- end
+ fun decode_base64: Bytes do return to_cstring.decode_base64(bytelen)
+
+ # Is `self` a well-formed Base64 entity ?
+ fun is_base64: Bool do return to_cstring.is_base64(bytelen)
+
+ # Is `self` a well-formed Base64 entity ?
+ #
+ # Will return an Error otherwise with info on which part is erroneous.
+ fun check_base64: nullable Error do return to_cstring.check_base64(bytelen)
+end
+
+redef class FlatText
+ redef fun encode_base64 do return fast_cstring.encode_base64(bytelen).to_s
+
+ redef fun decode_base64 do return fast_cstring.decode_base64(bytelen)
+
+ redef fun is_base64 do return fast_cstring.is_base64(bytelen)
+
+ redef fun check_base64 do return fast_cstring.check_base64(bytelen)
end
var res = 23 + length
# Note: the order of the elements must not change the hash value.
# So, unlike usual hash functions, the accumulator is not combined with itself.
- for e in self do res += e.hash
+ for e in self do
+ if e != null then res += e.hash
+ end
return res
end
redef fun [](index)
do
assert index: index >= 0 and index < _length
- return _items[index]
+ return _items.as(not null)[index]
end
redef fun []=(index, item)
if _length <= index then
_length = index + 1
end
- _items[index] = item
+ _items.as(not null)[index] = item
end
redef fun add(item)
enlarge(l + 1)
end
_length = l + 1
- _items[l] = item
+ _items.as(not null)[l] = item
end
# Slight optimization for arrays
if items isa Array[E] then
var k = 0
while l < nl do
- _items[l] = items._items[k]
+ _items.as(not null)[l] = items._items.as(not null)[k]
l += 1
k += 1
end
else
for item in items do
- _items[l] = item
+ _items.as(not null)[l] = item
l += 1
end
end
if cap <= c then return
while c <= cap do c = c * 2 + 2
var a = new NativeArray[E](c)
- if _capacity > 0 then _items.copy_to(a, _length)
+ if _capacity > 0 then _items.as(not null).copy_to(a, _length)
_items = a
_capacity = c
end
# Efficient implementation
var l = length
if l != o.length then return false
+ if l == 0 then return true
var i = 0
- var it = _items
- var oit = o._items
+ var it = _items.as(not null)
+ var oit = o._items.as(not null)
while i < l do
if it[i] != oit[i] then return false
i += 1
redef fun <=>(o)
do
- var it = _items
- var oit = o._items
var i = 0
var l = length
+ if l == 0 then return 0
+ var it = _items.as(not null)
+ var oit = o._items.as(not null)
var ol = o.length
var len
if l < ol then len = l else len = ol
# Access
- redef fun [](index) do return get_node(index).item
+ redef fun [](index) do return get_node(index).as(not null).item
- redef fun []=(index, item) do get_node(index).item = item
+ redef fun []=(index, item) do get_node(index).as(not null).item = item
# O(1)
- redef fun first do return _head.item
+ redef fun first do return _head.as(not null).item
# O(1)
- redef fun first=(e) do _head.item = e
+ redef fun first=(e) do _head.as(not null).item = e
# O(1)
- redef fun last do return _tail.item
+ redef fun last do return _tail.as(not null).item
# O(1)
- redef fun last=(e) do _tail.item = e
+ redef fun last=(e) do _tail.as(not null).item = e
# Queries
redef fun push(e)
do
var node = new ListNode[E](e)
- if _tail == null then
+ var tail = _tail
+ if tail == null then
_head = node
else
- _tail.next = node
- node.prev = _tail
+ tail.next = node
+ node.prev = tail
end
_tail = node
length += 1
redef fun unshift(e)
do
var node = new ListNode[E](e)
- if _head == null then
+ var head = _head
+ if head == null then
_tail = node
else
- node.next = _head
- _head.prev = node
+ node.next = head
+ head.prev = node
end
_head = node
length += 1
# O(1)
fun link(l: List[E])
do
- if _tail == null then
+ var tail = _tail
+ if tail == null then
_head = l._head
else if l._head != null then
- _tail.next = l._head
- _tail.next.prev = _tail
+ tail.next = l._head
+ tail.next.as(not null).prev = tail
end
_tail = l._tail
length += l.length
# O(1)
redef fun pop
do
- var node = _tail
+ var node = _tail.as(not null)
_tail = node.prev
node.prev = null
if _tail == null then
_head = null
else
- _tail.next = null
+ _tail.as(not null).next = null
end
length -= 1
return node.item
# O(1)
redef fun shift
do
- var node = _head
+ var node = _head.as(not null)
_head = node.next
node.next = null
if _head == null then
_tail = null
else
- _head.prev = null
+ _head.as(not null).prev = null
end
length -= 1
return node.item
if node.next == null then
_tail = null
else
- node.next.prev = null
+ node.next.as(not null).prev = null
end
else if node.next == null then
_tail = node.prev
- node.prev.next = null
+ node.prev.as(not null).next = null
else
- node.prev.next = node.next
- node.next.prev = node.prev
+ node.prev.as(not null).next = node.next
+ node.next.as(not null).prev = node.prev
end
end
# This is the iterator class of List
class ListIterator[E]
super IndexedIterator[E]
- redef fun item do return _node.item
+ redef fun item do return _node.as(not null).item
# Set item `e` at self `index`.
- fun item=(e: E) do _node.item = e
+ fun item=(e: E) do _node.as(not null).item = e
redef fun is_ok do return not _node == null
redef fun next
do
- _node = _node.next
+ _node = _node.as(not null).next
_index += 1
end
redef fun next
do
- _node = _node.prev
+ _node = _node.as(not null).prev
_index -= 1
end
redef fun to_s do
var e = maybe_error
if e != null then return e.to_s
- return value.to_s
+ return value.as(not null).to_s
end
end
var args = new FlatBuffer
var l = 1 # Number of elements in args
args.append(command)
+ var arguments = self.arguments
if arguments != null then
for a in arguments do
args.add('\0')
# Return null in case of error
fun file_stat: nullable FileStat
do
- var stat = _file.file_stat
+ var stat = _file.as(not null).file_stat
if stat.address_is_null then return null
return new FileStat(stat)
end
# File descriptor of this file
- fun fd: Int do return _file.fileno
+ fun fd: Int do return _file.as(not null).fileno
redef fun close
do
- if _file == null then return
- if _file.address_is_null then
+ var file = _file
+ if file == null then return
+ if file.address_is_null then
if last_error != null then return
last_error = new IOError("Cannot close unopened file")
return
end
- var i = _file.io_close
+ var i = file.io_close
if i != 0 then
last_error = new IOError("Close failed due to error {sys.errno.strerror}")
end
# * `buffer_mode_none`
fun set_buffering_mode(buf_size, mode: Int) do
if buf_size <= 0 then buf_size = 512
- if _file.set_buffering_type(buf_size, mode) != 0 then
+ if _file.as(not null).set_buffering_type(buf_size, mode) != 0 then
last_error = new IOError("Error while changing buffering type for FileStream, returned error {sys.errno.strerror}")
end
end
# assert l == f.read_line
fun reopen
do
- if not eof and not _file.address_is_null then close
+ if not eof and not _file.as(not null).address_is_null then close
last_error = null
- _file = new NativeFile.io_open_read(path.to_cstring)
- if _file.address_is_null then
+ _file = new NativeFile.io_open_read(path.as(not null).to_cstring)
+ if _file.as(not null).address_is_null then
last_error = new IOError("Cannot open `{path.as(not null)}`: {sys.errno.strerror}")
end_reached = true
return
redef fun fill_buffer
do
- var nb = _file.io_read(_buffer, _buffer_capacity)
- if last_error == null and _file.ferror then
+ var nb = _file.as(not null).io_read(_buffer, _buffer_capacity)
+ if last_error == null and _file.as(not null).ferror then
last_error = new IOError("Cannot read `{path.as(not null)}`: {sys.errno.strerror}")
end_reached = true
end
self.path = path
prepare_buffer(100)
_file = new NativeFile.io_open_read(path.to_cstring)
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
end_reached = true
end
self.path = ""
prepare_buffer(1)
_file = fd.fd_to_stream(read_only)
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Error: Converting fd {fd} to stream failed with '{sys.errno.strerror}'")
end_reached = true
end
last_error = new IOError("Cannot write to non-writable stream")
return
end
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Writing on a null stream")
_is_writable = false
return
end
- var err = _file.write_byte(value)
+ var err = _file.as(not null).write_byte(value)
if err != 1 then
# Big problem
last_error = new IOError("Problem writing a byte: {err}")
last_error = new IOError("Cannot write to non-writable stream")
return
end
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Writing on a null stream")
_is_writable = false
return
end
- var err = _file.io_write(native, from, len)
+ var err = _file.as(not null).io_write(native, from, len)
if err != len then
# Big problem
last_error = new IOError("Problem in writing : {err} {len} \n")
_file = new NativeFile.io_open_write(path.to_cstring)
self.path = path
_is_writable = true
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
is_writable = false
end
self.path = ""
_file = fd.fd_to_stream(wipe_write)
_is_writable = true
- if _file.address_is_null then
+ if _file.as(not null).address_is_null then
last_error = new IOError("Error: Opening stream from file descriptor {fd} failed with '{sys.errno.strerror}'")
_is_writable = false
end
return self
end
end
+
+ # Is `self` an ASCII whitespace ?
+ fun is_whitespace: Bool do return self == 0x7Fu8 or self <= 0x20u8
end
# Native integer numbers.
end
return res
end
+
+ # Is `self` a power of two ?
+ #
+ # ~~~nit
+ # assert not 3.is_pow2
+ # assert 2.is_pow2
+ # assert 1.is_pow2
+ # assert not 0.is_pow2
+ # ~~~
+ fun is_pow2: Bool do return self != 0 and (self & self - 1) == 0
end
redef class Byte
# Cache of a single `regmatch_t` to prevent many calls to `malloc`
private var native_match: NativeMatchArray is lazy do
native_match_is_init = true
- return new NativeMatchArray.malloc(native.re_nsub+1)
+ return new NativeMatchArray.malloc(native.as(not null).re_nsub+1)
end
private var native_match_is_init = false
return res.to_s
end
- # Escape " \ ' and non printable characters using the rules of literal C strings and characters
+ # Escape `"` `\` `'`, trigraphs and non printable characters using the rules of literal C strings and characters
#
- # assert "abAB12<>&".escape_to_c == "abAB12<>&"
+ # assert "abAB12<>&".escape_to_c == "abAB12<>&"
# assert "\n\"'\\".escape_to_c == "\\n\\\"\\'\\\\"
+ # assert "allo???!".escape_to_c == "allo??\\?!"
+ # assert "??=??/??'??(??)".escape_to_c == "?\\?=?\\?/??\\'?\\?(?\\?)"
+ # assert "??!??<??>??-".escape_to_c == "?\\?!?\\?<?\\?>?\\?-"
#
# Most non-printable characters (bellow ASCII 32) are escaped to an octal form `\nnn`.
# Three digits are always used to avoid following digits to be interpreted as an element
b.append("\\\'")
else if c == '\\' then
b.append("\\\\")
+ else if c == '?' then
+ # Escape if it is the last question mark of a ANSI C trigraph.
+ var j = i + 1
+ if j < length then
+ var next = chars[j]
+ # We ignore `??'` because it will be escaped as `??\'`.
+ if
+ next == '!' or
+ next == '(' or
+ next == ')' or
+ next == '-' or
+ next == '/' or
+ next == '<' or
+ next == '=' or
+ next == '>'
+ then b.add('\\')
+ end
+ b.add('?')
else if c.code_point < 32 then
b.add('\\')
var oct = c.code_point.to_base(8)
# The result might no be legal in C but be used in other languages
#
# assert "ab|\{\}".escape_more_to_c("|\{\}") == "ab\\|\\\{\\\}"
+ # assert "allo???!".escape_more_to_c("") == "allo??\\?!"
fun escape_more_to_c(chars: String): String
do
var b = new Buffer
# Letters that follow a letter are lowercased
# Letters that follow a non-letter are upcased.
#
+ # If `keep_upper = true`, already uppercase letters are not lowercased.
+ #
# SEE : `Char::is_letter` for the definition of letter.
#
# assert "jAVASCRIPT".capitalized == "Javascript"
# assert "i am root".capitalized == "I Am Root"
# assert "ab_c -ab0c ab\nc".capitalized == "Ab_C -Ab0C Ab\nC"
- fun capitalized: SELFTYPE do
+ # assert "preserve my ACRONYMS".capitalized(keep_upper=true) == "Preserve My ACRONYMS"
+ fun capitalized(keep_upper: nullable Bool): SELFTYPE do
if length == 0 then return self
var buf = new Buffer.with_cap(length)
-
- var curr = chars[0].to_upper
- var prev = curr
- buf[0] = curr
-
- for i in [1 .. length[ do
- prev = curr
- curr = self[i]
- if prev.is_letter then
- buf[i] = curr.to_lower
- else
- buf[i] = curr.to_upper
- end
- end
-
+ buf.capitalize(keep_upper=keep_upper, src=self)
return buf.to_s
end
end
# Letters that follow a letter are lowercased
# Letters that follow a non-letter are upcased.
#
+ # If `keep_upper = true`, uppercase letters are not lowercased.
+ #
+ # When `src` is specified, this method reads from `src` instead of `self`
+ # but it still writes the result to the beginning of `self`.
+ # This requires `self` to have the capacity to receive all of the
+ # capitalized content of `src`.
+ #
# SEE: `Char::is_letter` for the definition of a letter.
#
# var b = new FlatBuffer.from("jAVAsCriPt")
# b = new FlatBuffer.from("ab_c -ab0c ab\nc")
# b.capitalize
# assert b == "Ab_C -Ab0C Ab\nC"
- fun capitalize do
+ #
+ # b = new FlatBuffer.from("12345")
+ # b.capitalize(src="foo")
+ # assert b == "Foo45"
+ #
+ # b = new FlatBuffer.from("preserve my ACRONYMS")
+ # b.capitalize(keep_upper=true)
+ # assert b == "Preserve My ACRONYMS"
+ fun capitalize(keep_upper: nullable Bool, src: nullable Text) do
+ src = src or else self
+ var length = src.length
if length == 0 then return
- var c = self[0].to_upper
+ keep_upper = keep_upper or else false
+
+ var c = src[0].to_upper
self[0] = c
var prev = c
for i in [1 .. length[ do
prev = c
- c = self[i]
+ c = src[i]
if prev.is_letter then
- self[i] = c.to_lower
+ if keep_upper then
+ self[i] = c
+ else
+ self[i] = c.to_lower
+ end
else
self[i] = c.to_upper
end
# see `alpha_comparator`
private class AlphaComparator
super Comparator
- redef fun compare(a, b) do return a.to_s <=> b.to_s
+ redef fun compare(a, b) do
+ if a == b then return 0
+ if a == null then return -1
+ if b == null then return 1
+ return a.to_s <=> b.to_s
+ end
end
# Stateless comparator that naively use `to_s` to compare things.
req_esc += 1
else if c == 0x5Cu8 then
req_esc += 1
+ else if c == 0x3Fu8 then
+ var j = pos + 1
+ if j < length then
+ var next = its[j]
+ # We ignore `??'` because it will be escaped as `??\'`.
+ if
+ next == 0x21u8 or
+ next == 0x28u8 or
+ next == 0x29u8 or
+ next == 0x2Du8 or
+ next == 0x2Fu8 or
+ next == 0x3Cu8 or
+ next == 0x3Du8 or
+ next == 0x3Eu8
+ then req_esc += 1
+ end
else if c < 32u8 then
req_esc += 3
end
nns[opos] = 0x5Cu8
nns[opos + 1] = 0x5Cu8
opos += 2
+ else if c == 0x3Fu8 then
+ var j = pos + 1
+ if j < length then
+ var next = its[j]
+ # We ignore `??'` because it will be escaped as `??\'`.
+ if
+ next == 0x21u8 or
+ next == 0x28u8 or
+ next == 0x29u8 or
+ next == 0x2Du8 or
+ next == 0x2Fu8 or
+ next == 0x3Cu8 or
+ next == 0x3Du8 or
+ next == 0x3Eu8
+ then
+ nns[opos] = 0x5Cu8
+ opos += 1
+ end
+ end
+ nns[opos] = 0x3Fu8
+ opos += 1
else if c < 32u8 then
nns[opos] = 0x5Cu8
nns[opos + 1] = 0x30u8
redef fun next do
if pos < 0 then return
var curr = iter.prev
- var currit = curr.node
+ var currit = curr.as(not null).node
while curr != null do
currit = curr.node
if not currit isa Concat then
redef fun next do
pos += str.length
if pos > max then return
- var it = iter.prev
+ var it = iter.prev.as(not null)
var rnod = it.node
loop
if not rnod isa Concat then
it.ldone = true
it.rdone = true
str = rnod.as(FlatString)
- iter = it.as(not null)
+ iter = it
break
end
if not it.ldone then
rnod = rnod._right
it = new RopeCharIteratorPiece(rnod, false, false, it)
else
- it = it.prev
+ it = it.prev.as(not null)
rnod = it.node
continue
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# This file is free software, which comes along with NIT. This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. You can modify it is you want, provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You are allowed to redistribute it and sell it, alone or is a part of
+# another product.
+
+module test_abstract_text is test_suite
+
+import test_suite
+import text
+intrude import ropes
+
+class TestText
+ super TestSuite
+
+ private var factories: Collection[TextFactory] = [
+ new ConcatFactory,
+ new RopeBufferFactory,
+ new FlatBufferFactory
+ : TextFactory]
+
+ fun test_escape_to_c do
+ for f in factories do
+ assert f.create("abAB12<>&").escape_to_c == "abAB12<>&"
+ assert f.create("\n\"'\\").escape_to_c == "\\n\\\"\\'\\\\"
+ assert f.create("allo???!").escape_to_c == "allo??\\?!"
+ assert f.create("??=??/??'??(??)").escape_to_c == "?\\?=?\\?/??\\'?\\?(?\\?)"
+ assert f.create("??!??<??>??-").escape_to_c == "?\\?!?\\?<?\\?>?\\?-"
+ end
+ end
+end
+
+# A factory that creates instances of a particular implementation of `Text`
+interface TextFactory
+
+ # Create a `Text` instance from the specified string
+ fun create(s: String): Text is abstract
+end
+
+
+class ConcatFactory
+ super TextFactory
+
+ redef fun create(s) do return new Concat("", s)
+end
+
+class RopeBufferFactory
+ super TextFactory
+
+ redef fun create(s) do return new RopeBuffer.from(s)
+end
+
+class FlatBufferFactory
+ super TextFactory
+
+ redef fun create(s) do return new FlatBuffer.from(s)
+end
import nitcorn
+# Nitcorn Action used to answer requests.
class HTCPCPAction
super Action
+
+ # Brewing status.
var brewing = false
- var is_teapot = false
+
+ # Teapot status.
+ var is_teapot = false
redef fun answer(http_request, turi) do
var message: String
var method = http_request.method
- var headers = http_request.header
var response: HttpResponse
if is_teapot == true then
end
end
-
+# Nitcorn server.
class HTCPCServer
+
+ # Port to listen to.
var port: Int
+ # Start listening.
fun run do
var vh = new VirtualHost("localhost:{port}")
vh.routes.add new Route("/", new HTCPCPAction)
# A request received over HTTP, is build by `HttpRequestParser`
class HttpRequest
- private init do end
+ private init is old_style_init do end
# HTTP protocol version
var http_version: String
# Words of the first line
private var first_line = new Array[String]
+ # Parse the `first_line`, `header_fields` and `body` of `full_request`.
fun parse_http_request(full_request: String): nullable HttpRequest
do
clear_data
# All know code and their message
var codes = new HashMap[Int, String]
- protected init do insert_status_codes
+ # Init the status `codes` list.
+ protected init is old_style_init do insert_status_codes
# Get the message associated to the status `code`, return `null` in unknown
fun [](code: Int): nullable String
# Map of known MIME types
class MediaTypes
+
+ # MIME types by extensions.
protected var types = new HashMap[String, String]
# Get the type/subtype associated to a file extension `ext`
end
end
+# MIME types list.
fun media_types: MediaTypes do return once new MediaTypes
NITUNIT=../../bin/nitunit
check:
- $(NITUNIT) README.md
- $(NITUNIT) pop_routes.nit
- $(NITUNIT) pop_handlers.nit
- $(NITUNIT) popcorn.nit
- cd tests; make check
+ $(NITUNIT) .
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_angular is test_suite
+
+import pop_tests
import example_angular
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleAngular
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/counter"
system "curl -s {host}:{port}/counter -X POST"
system "curl -s {host}:{port}/counter"
system "curl -s {host}:{port}/not_found" # handled by angular controller
- return null
end
-end
-
-var app = new App
-app.use("/counter", new CounterAPI)
-app.use("/*", new StaticHandler("../examples/angular/www/", "index.html"))
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/counter", new CounterAPI)
+ app.use("/*", new StaticHandler("../examples/angular/www/", "index.html"))
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_post_handler is test_suite
+
+import pop_tests
import example_post_handler
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleQueryString
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/ -X POST"
system "curl -s {host}:{port}/ --data 'user'"
system "curl -s {host}:{port}/ --data 'user=Morriar'"
system "curl -s {host}:{port}/ --data 'user=\&order=desc'"
system "curl -s {host}:{port}/ --data 'user=Morriar\&order=desc'"
-
system "curl -s {host}:{port}/"
- return null
end
-end
-
-var app = new App
-app.use("/", new PostHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_glob_route do
+ var app = new App
+ app.use("/", new PostHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_query_string is test_suite
+
+import pop_tests
import example_query_string
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleQueryString
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/?user=Morriar"
system "curl -s {host}:{port}/?reload"
system "curl -s {host}:{port}/?foo\\&bar=baz"
system "curl -s {host}:{port}/?items=10\\&order=asc"
- return null
end
-end
-
-var app = new App
-app.use("/", new QueryStringHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_glob_route do
+ var app = new App
+ app.use("/", new QueryStringHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_hello is test_suite
+
+import pop_tests
import example_hello
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleHello
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}"
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}///////////"
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/not_found/not_found"
- return null
end
-end
-
-var app = new App
-app.use("/", new HelloHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_hello do
+ var app = new App
+ app.use("/", new HelloHandler)
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_advanced_logger is test_suite
+
+import pop_tests
import example_advanced_logger
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleAdvancedLogger
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/about"
- return null
end
-end
-
-var app = new App
-app.use_before("/*", new RequestTimeHandler)
-app.use("/", new HelloHandler)
-app.use_after("/*", new LogHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use_before("/*", new RequestTimeHandler)
+ app.use("/", new HelloHandler)
+ app.use_after("/*", new LogHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_html_error_handler is test_suite
+
+import pop_tests
import example_html_error_handler
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleHtmlErrorHandler
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/about"
- return null
end
-end
-
-var app = new App
-app.use("/*", new HtmlErrorHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/*", new HtmlErrorHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_simple_error_handler is test_suite
+
+import pop_tests
import example_simple_error_handler
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleSimpleErrorHandler
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/about"
- return null
end
-end
-
-var app = new App
-app.use("/", new HelloHandler)
-app.use("/*", new SimpleErrorHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/", new HelloHandler)
+ app.use("/*", new SimpleErrorHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_simple_logger is test_suite
+
+import pop_tests
import example_simple_logger
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleSimpleLogger
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/about"
- return null
end
-end
-
-var app = new App
-app.use_before("/*", new LogHandler)
-app.use("/", new HelloHandler)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use_before("/*", new LogHandler)
+ app.use("/", new HelloHandler)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_glob_route is test_suite
+
+import pop_tests
import example_glob_route
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleGlobRoute
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/user/Morriar/item/10"
system "curl -s {host}:{port}/user/Morriar/item/10/"
system "curl -s {host}:{port}/user/Morriar/item/10/profile"
system "curl -s {host}:{port}/user/Morriar/item/10/profile/settings"
-
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/not_found/not_found"
- return null
end
-end
-
-var app = new App
-app.use("/user/:user/item/:item/*", new UserItem)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_glob_route do
+ var app = new App
+ app.use("/user/:user/item/:item/*", new UserItem)
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_param_route is test_suite
+
+import pop_tests
import example_param_route
-import base_tests
-class TestClient
- super ClientThread
+class TestExampleParamRoute
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/Morriar"
system "curl -s {host}:{port}//"
-
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/not_found/not_found"
- return null
end
-end
-
-var app = new App
-app.use("/:user", new UserHome)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/:user", new UserHome)
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_router is test_suite
+
+import pop_tests
import example_router
-import base_tests
-class HelloClient
- super ClientThread
+class TestExampleRouter
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}"
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/user"
system "curl -s {host}:{port}/user/"
system "curl -s {host}:{port}/user/profile"
-
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/user/not_found"
system "curl -s {host}:{port}/products/not_found"
- return null
end
-end
-
-var user_router = new Router
-user_router.use("/*", new UserLogger)
-user_router.use("/", new UserHome)
-user_router.use("/profile", new UserProfile)
-
-var app = new App
-app.use("/", new AppHome)
-app.use("/user", user_router)
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new HelloClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_router do
+ var user_router = new Router
+ user_router.use("/*", new UserLogger)
+ user_router.use("/", new UserHome)
+ user_router.use("/profile", new UserProfile)
+ var app = new App
+ app.use("/", new AppHome)
+ app.use("/user", user_router)
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
# See the License for the specific language governing permissions and
# limitations under the License.
+module test_example_session is test_suite
+
+import pop_tests
import example_session
-import base_tests
-class HelloClient
- super ClientThread
+class TestExampleSession
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/"
system "curl -s {host}:{port}/ -X POST"
-
system "curl -s {host}:{port}/not_found"
system "curl -s {host}:{port}/user/not_found"
system "curl -s {host}:{port}/products/not_found"
- return null
end
-end
-
-var app = new App
-app.use("/*", new SessionInit)
-app.use("/", new AppLogin)
-
-var host = test_host
-var port = test_port
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new HelloClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+ fun test_example_param_route do
+ var app = new App
+ app.use("/*", new SessionInit)
+ app.use("/", new AppLogin)
+ run_test(app)
+ end
+end
# See the License for the specific language governing permissions and
# limitations under the License.
-import base_tests
+module test_example_static is test_suite
+
+import pop_tests
import example_static
-class TestClient
- super ClientThread
+class TestExampleStatic
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/css/style.css"
system "curl -s {host}:{port}/js/app.js"
system "curl -s {host}:{port}/hello.html"
system "curl -s {host}:{port}/"
-
system "curl -s {host}:{port}/css/not_found.nit"
system "curl -s {host}:{port}/static/css/not_found.nit"
system "curl -s {host}:{port}/not_found.nit"
+ end
- return null
+ fun test_example_param_route do
+ var app = new App
+ app.use("/", new StaticHandler("../examples/static_files/public/"))
+ run_test(app)
end
end
-
-var app = new App
-app.use("/", new StaticHandler("../examples/static_files/public/"))
-
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
# See the License for the specific language governing permissions and
# limitations under the License.
-import base_tests
+module test_example_static_default is test_suite
+
+import pop_tests
import example_static_default
-class TestClient
- super ClientThread
+class TestExampleStaticDefault
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/css/style.css"
system "curl -s {host}:{port}/js/app.js"
system "curl -s {host}:{port}/hello.html"
system "curl -s {host}:{port}/"
-
system "curl -s {host}:{port}/css/not_found.nit"
system "curl -s {host}:{port}/static/css/not_found.nit"
system "curl -s {host}:{port}/not_found.nit"
+ end
- return null
+ fun test_example_param_route do
+ var app = new App
+ app.use("/", new StaticHandler("../examples/static_files/public/", "default.html"))
+ run_test(app)
end
end
-
-var app = new App
-app.use("/", new StaticHandler("../examples/static_files/public/", "default.html"))
-
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
# See the License for the specific language governing permissions and
# limitations under the License.
-import base_tests
+module test_example_static_multiple is test_suite
+
+import pop_tests
import example_static_multiple
-class TestClient
- super ClientThread
+class TestExampleStaticMultiple
+ super TestPopcorn
- redef fun main do
+ redef fun client_test do
system "curl -s {host}:{port}/css/style.css"
system "curl -s {host}:{port}/js/app.js"
system "curl -s {host}:{port}/hello.html"
system "curl -s {host}:{port}/"
-
system "curl -s {host}:{port}/static/css/style.css"
system "curl -s {host}:{port}/static/js/app.js"
system "curl -s {host}:{port}/static/hello.html"
system "curl -s {host}:{port}/static/"
-
system "curl -s {host}:{port}/css/not_found.nit"
system "curl -s {host}:{port}/static/css/not_found.nit"
system "curl -s {host}:{port}/not_found.nit"
+ end
- return null
+ fun test_example_param_route do
+ var app = new App
+ app.use("/", new StaticHandler("../examples/static_files/public/"))
+ app.use("/", new StaticHandler("../examples/static_files/files/"))
+ app.use("/static", new StaticHandler("../examples/static_files/public/"))
+ app.use("/static", new StaticHandler("../examples/static_files/files/"))
+ run_test(app)
end
end
-
-var app = new App
-app.use("/", new StaticHandler("../examples/static_files/public/"))
-app.use("/", new StaticHandler("../examples/static_files/files/"))
-app.use("/static", new StaticHandler("../examples/static_files/public/"))
-app.use("/static", new StaticHandler("../examples/static_files/files/"))
-
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new TestClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
--- /dev/null
+# 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.
+
+# Popcorn testing services
+#
+# ## Blackbox testing
+#
+# Popcorn allows you to test your apps using nitunit blackbox testing.
+#
+# With blackbox testing you compare the output of your program with a result file.
+#
+# To get started with blackbox testing, create a nitunit test suite and imports
+# the `pop_tests` module.
+#
+# You then need to build the app that will be tested by nitunit as shown in the
+# `test_example_hello` method.
+# Calling `run_test` will automatically set the `host` and `port` used for testing.
+#
+# Redefine the `client_test` method to write your scenario.
+# Here we use `curl` to access some URI on the app.
+#
+# ~~~nitish
+# module test_example_hello is test_suite
+#
+# import pop_tests
+# import example_hello
+#
+# class TestExampleHello
+# super TestPopcorn
+#
+# fun test_example_hello do
+# var app = new App
+# app.use("/", new HelloHandler)
+# run_test(app)
+# end
+#
+# redef fun client_test do
+# system "curl -s {host}:{port}"
+# system "curl -s {host}:{port}/"
+# system "curl -s {host}:{port}///////////"
+# system "curl -s {host}:{port}/not_found"
+# system "curl -s {host}:{port}/not_found/not_found"
+# end
+# end
+# ~~~
+#
+# The blackbox testing needs a reference result file against wich the test output
+# will be compared.
+# Create your expected result file in `test_example_hello.sav/test_example_hello.res`.
+#
+# Test your app by running nitunit:
+#
+# ~~~bash
+# nitunit ./example_hello.nit
+# ~~~
+#
+# See `examples/hello_world` for the complete example.
+module pop_tests
+
+import test_suite
+import popcorn
+import pthreads
+
+redef class Sys
+
+ # Use localhost for testing
+ var test_host = "localhost"
+
+ # Return a new port for each instance
+ fun test_port: Int do
+ srand
+ return 10000+20000.rand
+ end
+end
+
+# Thread running the App to test.
+class AppThread
+ super Thread
+
+ # Host used by tested App.
+ var host: String
+
+ # Port used by tested App.
+ var port: Int
+
+ # App to test.
+ var app: App
+
+ redef fun main
+ do
+ # Hide testing concept to force nitcorn to actually run
+ "NIT_TESTING".setenv("false")
+ app.quiet = true
+ app.listen(host, port)
+ return null
+ end
+end
+
+# Thread running the test client.
+class ClientThread
+ super Thread
+
+ # Test suite to execute.
+ var test_suite: TestPopcorn
+
+ redef fun main do
+ test_suite.client_test
+ print ""
+ return null
+ end
+end
+
+# TestSuite for Popcorn blackbox testing.
+class TestPopcorn
+ super TestSuite
+
+ # Host used to run App.
+ var host: String = test_host
+
+ # Port used to run App.
+ var port: Int = test_port
+
+ # Run the test suite on the App.
+ fun run_test(app: App) do
+ var server = new AppThread(host, port, app)
+ server.start
+ 0.1.sleep
+
+ var client = new ClientThread(self)
+ client.start
+ client.join
+ 0.1.sleep
+
+ exit 0
+ end
+
+ # Redefine this method to implement your test scenario.
+ fun client_test do end
+
+ # Regex to catch and hide the port from the output to get consistent results
+ var host_re: Regex = "localhost:\[0-9\]+".to_re
+
+ # Execute a System function.
+ fun system(cmd: String, title: nullable String)
+ do
+ title = title or else cmd
+ title = title.replace(host_re, "localhost:*****")
+ print "\n[Client] {title}"
+ sys.system cmd
+ end
+end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2016 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.
+
+module test_popcorn is test_suite
+
+import pop_tests
+import popcorn
+
+class TestHandler
+ super Handler
+
+ var marker: String
+
+ redef fun get(req, res) do res.send marker
+end
+
+class TestPopcornRouter
+ super TestPopcorn
+
+ redef fun client_test do
+ system "curl -s {host}:{port}"
+ system "curl -s {host}:{port}/"
+ system "curl -s {host}:{port}/user"
+ system "curl -s {host}:{port}/user/"
+ system "curl -s {host}:{port}/user/settings"
+ system "curl -s {host}:{port}/products"
+ system "curl -s {host}:{port}/products/"
+ system "curl -s {host}:{port}/products/list"
+ system "curl -s {host}:{port}/not_found"
+ system "curl -s {host}:{port}/user/not_found"
+ system "curl -s {host}:{port}/products/not_found"
+ end
+
+ fun test_router do
+ var app = new App
+ app.use("/", new TestHandler("/"))
+ app.use("/about", new TestHandler("/about"))
+
+ var router1 = new App
+ router1.use("/", new TestHandler("/user"))
+ router1.use("/settings", new TestHandler("/user/settings"))
+ app.use("/user", router1)
+
+ var router2 = new App
+ router2.use("/", new TestHandler("/products"))
+ router2.use("/list", new TestHandler("/products/list"))
+ app.use("/products", router2)
+
+ run_test(app)
+ end
+end
+
+class TestPopcornRoutes
+ super TestPopcorn
+
+ redef fun client_test do
+ system "curl -s {host}:{port}"
+ system "curl -s {host}:{port}/"
+ system "curl -s {host}:{port}/misc"
+ system "curl -s {host}:{port}/misc/foo"
+ system "curl -s {host}:{port}/misc/foo/bar"
+ system "curl -s {host}:{port}/misc/foo/baz"
+ system "curl -s {host}:{port}/user"
+ system "curl -s {host}:{port}/user/"
+ system "curl -s {host}:{port}/user/id"
+ system "curl -s {host}:{port}/user/id/profile"
+ system "curl -s {host}:{port}/user/id/misc/foo"
+ system "curl -s {host}:{port}/user/id/misc/foo/bar"
+ system "curl -s {host}:{port}/user/id/misc/foo/bar/baz"
+ system "curl -s {host}:{port}/not_found"
+ system "curl -s {host}:{port}/user/id/not_found"
+ end
+
+ fun test_routes do
+ var app = new App
+ app.use("/", new TestHandler("/"))
+ app.use("/user", new TestHandler("/user"))
+ app.use("/misc/*", new TestHandler("/misc/everything"))
+ app.use("/user/:id", new TestHandler("/user/id"))
+ app.use("/user/:id/profile", new TestHandler("/user/id/profile"))
+ app.use("/user/:id/misc/*", new TestHandler("/user/id/misc/everything"))
+ run_test(app)
+ end
+end
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
<body>
<h1>404 Not Found</h1>
</body>
- </html>
\ No newline at end of file
+ </html>
+++ /dev/null
-# 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 popcorn
-import pthreads
-
-redef class Sys
- var test_host = "localhost"
-
- # Return a new port for each instance
- fun test_port: Int do
- srand
- return 10000+20000.rand
- end
-end
-
-class AppThread
- super Thread
-
- var host: String
- var port: Int
- var app: App
-
- redef fun main
- do
- # Hide testing concept to force nitcorn to actually run
- "NIT_TESTING".setenv("false")
- app.quiet = true
- app.listen(host, port)
- return null
- end
-end
-
-class ClientThread
- super Thread
-
- var host: String
- var port: Int
-
- redef fun main do return null
-
- # Regex to catch and hide the port from the output to get consistent results
- var host_re: Regex = "localhost:\[0-9\]+".to_re
-
- fun system(cmd: String, title: nullable String)
- do
- title = title or else cmd
- title = title.replace(host_re, "localhost:*****")
- print "\n[Client] {title}"
- sys.system cmd
- end
-end
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2016 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.
-
-import base_tests
-
-class TestHandler
- super Handler
-
- var marker: String
-
- redef fun get(req, res) do res.send marker
-end
-
-class HelloClient
- super ClientThread
-
- redef fun main do
- system "curl -s {host}:{port}"
- system "curl -s {host}:{port}/"
- system "curl -s {host}:{port}/user"
- system "curl -s {host}:{port}/user/"
- system "curl -s {host}:{port}/user/settings"
- system "curl -s {host}:{port}/products"
- system "curl -s {host}:{port}/products/"
- system "curl -s {host}:{port}/products/list"
-
- system "curl -s {host}:{port}/not_found"
- system "curl -s {host}:{port}/user/not_found"
- system "curl -s {host}:{port}/products/not_found"
- return null
- end
-end
-
-var app = new App
-app.use("/", new TestHandler("/"))
-app.use("/about", new TestHandler("/about"))
-
-var router1 = new App
-router1.use("/", new TestHandler("/user"))
-router1.use("/settings", new TestHandler("/user/settings"))
-app.use("/user", router1)
-
-var router2 = new App
-router2.use("/", new TestHandler("/products"))
-router2.use("/list", new TestHandler("/products/list"))
-app.use("/products", router2)
-
-var host = test_host
-var port = test_port
-
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-var client = new HelloClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-exit 0
+++ /dev/null
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2016 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.
-
-import base_tests
-
-class TestHandler
- super Handler
-
- var marker: String
-
- redef fun get(req, res) do res.send marker
-end
-
-class HelloClient
- super ClientThread
-
- redef fun main do
- system "curl -s {host}:{port}"
- system "curl -s {host}:{port}/"
-
- system "curl -s {host}:{port}/misc"
- system "curl -s {host}:{port}/misc/foo"
- system "curl -s {host}:{port}/misc/foo/bar"
- system "curl -s {host}:{port}/misc/foo/baz"
-
- system "curl -s {host}:{port}/user"
- system "curl -s {host}:{port}/user/"
- system "curl -s {host}:{port}/user/id"
- system "curl -s {host}:{port}/user/id/profile"
- system "curl -s {host}:{port}/user/id/misc/foo"
- system "curl -s {host}:{port}/user/id/misc/foo/bar"
- system "curl -s {host}:{port}/user/id/misc/foo/bar/baz"
-
- system "curl -s {host}:{port}/not_found"
- system "curl -s {host}:{port}/user/id/not_found"
- return null
- end
-end
-
-var app = new App
-app.use("/", new TestHandler("/"))
-app.use("/user", new TestHandler("/user"))
-app.use("/misc/*", new TestHandler("/misc/everything"))
-app.use("/user/:id", new TestHandler("/user/id"))
-app.use("/user/:id/profile", new TestHandler("/user/id/profile"))
-app.use("/user/:id/misc/*", new TestHandler("/user/id/misc/everything"))
-
-var host = test_host
-var port = test_port
-
-# First, launch a server in the background
-var server = new AppThread(host, port, app)
-server.start
-0.1.sleep
-
-# Then, launch a client running test requests
-var client = new HelloClient(host, port)
-client.start
-client.join
-0.1.sleep
-
-# Force quit the server
-exit 0
+++ /dev/null
-#!/bin/bash
-
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2016 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.
-
-BIN=../bin
-OUT=./out
-RES=./res
-
-NITC=../../../bin/nitc
-
-compile() {
- local test="$1"
- $NITC $test.nit -o $OUT/$test.bin 1>&2 2> $OUT/$test.cmp_err
-}
-
-test_prog()
-{
- local test="$1"
-
- chmod +x $OUT/$test.bin 2> $OUT/$test.err
- $OUT/$test.bin > $OUT/$test.res 2> $OUT/$test.err
-
- diff $OUT/$test.res $RES/$test.res > $OUT/$test.diff 2> /dev/null
-}
-
-# return
-# 0 if the sav not exists
-# 1 if the file does match
-# 2 if the file does not match
-check_result() {
- local test="$1"
-
- if [ -s "$OUT/$test.cmp_err" ]; then
- return 0
- elif [ -s "$OUT/$test.err" ]; then
- return 1
- elif [ ! -r "$RES/$test.res" ]; then
- return 2
- elif [ -s "$OUT/$test.diff" ]; then
- return 3
- else
- return 4
- fi
-}
-
-echo "Testing..."
-echo ""
-
-rm -rf $OUT 2>/dev/null
-mkdir $OUT 2>/dev/null
-
-all=0
-ok=0
-ko=0
-sk=0
-
-for file in `ls test_*.nit`; do
- ((all++))
- test="${file%.*}"
- echo -n "* $test: "
-
- compile $test
- test_prog $test
- check_result $test
-
- case "$?" in
- 0)
- echo "compile error (cat $OUT/$test.cmp_err)"
- ((ko++))
- ;;
- 1)
- echo "error (cat $OUT/$test.cmp_err)"
- ((ko++))
- ;;
- 2)
- echo "skip ($test.res not found)"
- ((sk++))
- continue;;
- 3)
- echo "error (diff $OUT/$test.res $RES/$test.res)"
- ((ko++))
- ;;
- 4)
- echo "success"
- ((ok++))
- ;;
-
- esac
-done
-echo ""
-echo "==> success $ok/$all ($ko tests failed, $sk skipped)"
-
-# return result
-test "$ok" == "$all"
--- /dev/null
+[package]
+name=readline
+tags=lib
+maintainer=Frédéric Vachon <fredvac@gmail.com>
+license=Apache-2.0
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/lib/readline.nit
+git=https://github.com/nitlang/nit.git
+git.directory=lib/readline.nit
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Copyright 2016 Frédéric Vachon <fredvac@gmail.com>
+#
+# 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.
+
+# GNU readline library wrapper
+module readline is ldflags "-lreadline"
+
+in "C" `{
+ #include <readline/readline.h>
+ #include <readline/history.h>
+`}
+
+private fun native_readline(prompt: NativeString): NativeString `{
+ return readline(prompt);
+`}
+
+private fun native_add_history(data: NativeString) `{
+ if (data == NULL) return;
+ add_history(data);
+`}
+
+# Set emacs keybindings mode
+fun set_vi_mode `{ rl_editing_mode = 0; `}
+
+# Set emacs keybindings mode
+fun set_emacs_mode `{ rl_editing_mode = 1; `}
+
+# Use the GNU Library readline function
+# Returns `null` if EOF is read
+# If `with_history` is true, it will save all commands in the history except
+# empty strings and white characters strings
+fun readline(message: String, with_history: nullable Bool): nullable String do
+ var line = native_readline(message.to_cstring)
+ if line.address_is_null then return null
+
+ var nit_str = line.to_s
+
+ if with_history != null and with_history then
+ if nit_str.trim != "" then native_add_history(line)
+ end
+
+ return nit_str
+end
+
+# Adds the data String to the history no matter what it contains
+fun add_history(data: String) do native_add_history data.to_cstring
nit [*options*] FILE [ARG]...
+nit [*options*] - [ARG]...
+
nit [*options*] -e COMMAND [ARG]...
# DESCRIPTION
$ nit examples/hello_world.nit
hello world
+If `-` is used instead of a module, then the program is read from the standard input.
+The whole program is read before its interpretation starts.
+
The Nit interpreter is usable and valid as a *shebang* interpreted directive.
It is however recommended to use with `/usr/bin/env` because the location of the executable is not standardized.
### `--no-shortcut-equal`
Always call == in a polymorphic way.
-### `--no-tag-primitive`
+### `--no-tag-primitives`
Use only boxes for primitive types.
The separate compiler uses tagged values to encode common primitive types like Int, Bool and Char.
Just add the trampolines of `--substitute-monomorph` without doing any additionnal optimizations.
-### `--no-tag-primitives`
-Use only boxes for primitive types.
-
## INTERNAL OPTIONS
These options can be used to control the fine behavior of the tool.
## Working with `TestSuites`
-TestSuites are Nit files that define a set of TestCases for a particular module.
+TestSuites are Nit modules that define a set of TestCases.
-The test suite must be called `test_` followed by the name of the module to test.
-So for the module `foo.nit` the test suite will be called `test_foo.nit`.
+A test suite is a module that uses the annotation `is test_suite`.
+
+It is common that a test suite focuses on testing a single module.
+In this case, the name of the test_suite is often `test_foo.nit` where `foo.nit` is the tested module.
The structure of a test suite is the following:
~~~~
# test suite for module `foo`
-module test_foo
+module test_foo is test_suite
+
+import test_suite
import foo # can be intrude to test private things
+
class TestFoo
+ super TestSuite
+
# test case for `foo::Foo::baz`
fun test_baz do
var subject = new Foo
$ nitunit foo.nit
-`nitunit` will execute a test for each method named `test_*` in a class named `Test*`
-so multiple tests can be executed for a single method:
+`nitunit` will execute a test for each method named `test_*` in a class
+subclassing `TestSuite` so multiple tests can be executed for a single method:
~~~~
class TestFoo
+ super TestSuite
+
fun test_baz_1 do
var subject = new Foo
assert subject.baz(1, 2) == 3
Sometimes, it is easier to validate a `TestCase` by comparing its output with a text file containing the expected result.
-For each TestCase `test_bar` of a TestSuite `test_mod.nit`, if the corresponding file `test_mod.sav/test_bar.res` exists, then the output of the test is compared with the file.
+For each TestCase `test_bar` of a TestSuite `test_mod.nit`, a corresponding file with the expected output is looked for:
+
+* "test_mod.sav/test_bar.res". I.e. test-cases grouped by test-suites.
+
+ This is the default and is useful if there is a lot of test-suites and test-cases in a directory
+
+* "sav/test_bar.res". I.e. all test-cases grouped in a common sub-directory.
+
+ Useful if there is a lot of test-suites OR test-cases in a directory.
+
+* "test_bar.res" raw in the directory.
+
+ Useful is there is a few test-suites and test-cases in a directory.
+
+All 3 are exclusive. If more than one exists, the test-case is failed.
+
+If a corresponding file then the output of the test-case is compared with the file.
The `diff(1)` command is used to perform the comparison.
The test is failed if non-zero is returned by `diff`.
~~~
module test_mod is test_suite
+
class TestFoo
+ super TestSuite
+
fun test_bar do
print "Hello!"
end
If no corresponding `.res` file exists, then the output of the TestCase is ignored.
+To helps the management of the expected results, the option `--autosav` can be used to automatically create and update them.
+
+
## Configuring TestSuites
-`TestSuites` also provide methods to configure the test run:
+`TestSuite`s also provide methods to configure the test run:
`before_test` and `after_test`: methods called before/after each test case.
They can be used to factorize repetitive tasks:
~~~~
class TestFoo
+ super TestSuite
var subject: Foo
# Mandatory empty init
init do end
`nitunit` produces a XML file compatible with JUnit.
### `--dir`
-Working directory (default is '.nitunit').
+Working directory (default is 'nitunit.out').
In order to execute the tests, nit files are generated then compiled and executed in the giver working directory.
+In case of success, the directory is removed.
+In case of failure, it is kept as is so files can be investigated.
+
### `--nitc`
nitc compiler to use.
Examples: `TestFoo`, `TestFoo*`, `TestFoo::test_foo`, `TestFoo::test_foo*`, `test_foo`, `test_foo*`
-### `-t`, `--target-file`
-Specify test suite location.
+### `--autosav`
+Automatically create/update .res files for black box testing.
+
+If a black block test fails because a difference between the expected result and the current result then the expected result file is updated (and the test is passed).
+
+If a test-case of a test-suite passes but that some output is generated, then an expected result file is created.
+
+It is expected that the created/updated files are checked since the tests are considered passed.
+A VCS like `git` is often a good tool to check the creation and modification of those files.
## SUITE GENERATION
--- /dev/null
+<div ng-if='listContributors.length > 0'>
+ <h3 id={{listId}}>
+ <span>{{listTitle}}</span>
+ </h3>
+ <ul class='list-unstyled user-list'>
+ <li ng-repeat='contributor in listContributors'>
+ <img class='avatar' src="https://secure.gravatar.com/avatar/{{contributor.hash}}?size=20&default=retro">
+ {{contributor.name}}
+ </li>
+ </ul>
+</div>
--- /dev/null
+<div class='card'>
+ <div class='card-left text-center'>
+ <entity-tag mentity='mentity' />
+ </div>
+ <div class='card-body'>
+ <h5 class='card-heading'>
+ <entity-signature mentity='mentity'/>
+ </h5>
+ <span class='synopsis' ng-bind-html='mentity.mdoc.html_synopsis' />
+ </div>
+</div>
--- /dev/null
+<div class='card card-xl' ng-class='{active: focus.full_name == definition.full_name}'>
+ <div class='card-body'>
+ <h5 class='text-muted'>
+ <span ng-if='definition.is_intro'>
+ <span class='glyphicon glyphicon-plus' /> Introduction</span>
+ </span>
+ <span ng-if='!definition.is_intro'>
+ <span class='glyphicon glyphicon-asterisk' /> Redefinition</span>
+ </span>
+ <span ng-if='definition.mclass'>
+ of <entity-link mentity='definition.mclass' />
+ </span>
+ <span ng-if='definition.mproperty'>
+ of <entity-link mentity='definition.mproperty' />
+ </span>
+ <span ng-if='definition.mclassdef'>
+ in <entity-link mentity='definition.mmodule' />
+ :: <entity-link mentity='definition.mclassdef' />
+ </span>
+ <span ng-if='!definition.mclassdef'>
+ in <entity-link mentity='definition.mmodule' />
+ </span>
+ <div class='btn-bar'>
+ <button class='btn btn-link' aria-expanded='false'
+ data-target='#{{codeId}}' ng-click='loadCardCode()'
+ aria-controls='{{codeId}}'>
+ <span class='glyphicon glyphicon-console'
+ title='Show code' />
+ </button>
+ </div>
+ </h5>
+ <div id='{{codeId}}' class='collapse'>
+ <pre ng-bind-html='code' />
+ </div>
+ <entity-location mentity='definition' />
+ </div>
+</div>
--- /dev/null
+<div class='card' ng-if='mentity.mdoc'>
+ <div class='card-body'>
+ <div ng-bind-html='mentity.mdoc.html_documentation'></div>
+ </div>
+</div>
--- /dev/null
+<div class='entity-list' ng-if='listEntities.length'>
+ <h3>{{listTitle}}</h3>
+ <div class='card-list'>
+ <div ng-repeat='def in listEntities'>
+ <entity-def definition='def' focus='listFocus' />
+ <h4 ng-if='!$last' class='text-muted text-center'>
+ <span class='glyphicon glyphicon-chevron-up'></span>
+ </h4>
+ </div>
+ </div>
+</div>
--- /dev/null
+<span>
+ <a ng-href='{{mentity.web_url}}'>{{mentity.name}}</a>
+</span>
--- /dev/null
+<div class='entity-list'
+ ng-if='(listEntities | filter:listObjectFilter).length > 0'>
+ <h3 id={{listId}}>
+ <span>{{listTitle}}</span>
+ <button class='btn btn-link btn-xs pull-right btn-filter' ng-click='toggleFilters()'>
+ <span class='glyphicon glyphicon-filter text-muted' />
+ </button>
+ </h3>
+ <div ng-if='showFilters'>
+ <ui-filter-form
+ search-filter='listObjectFilter'
+ visibility-filter='visibilityFilter'>
+ </div>
+ <div class='card-list'>
+ <entity-card mentity='mentity'
+ ng-repeat='mentity in listEntities | filter:listObjectFilter | visibility:visibilityFilter' />
+ </div>
+ </div>
+</div>
--- /dev/null
+<span ng-if='mentity.location'>
+ <a ng-href="{{mentity.web_url}}">{{mentity.location.file}}
+ <span ng-if='mentity.location.line_start'>:{{mentity.location.line_start}}</span>
+ </a>
+</span>
--- /dev/null
+<span class='signature'>
+ <span ng-repeat='modifier in mentity.modifiers'>
+ <span ng-if='modifier != "public"' class='modifier'>{{modifier}}</span>
+ </span>
+ <span class='name'>
+ <entity-link mentity='mentity' />
+ </span>
+ <span ng-if='mentity.mparameters'>
+ <span ng-if='mentity.mparameters.length > 0'>
+ <span>[</span>
+ <span ng-repeat='mparam in mentity.mparameters'>
+ <span>
+ <span>{{mparam.name}}</span>
+ <span>: </span>
+ <entity-signature mentity='mparam.mtype' />
+ </span>
+ <span ng-if='$middle'>, </span>
+ </span>
+ <span>]</span>
+ </span>
+ </span>
+ <span ng-if='mentity.msignature'>
+ <span ng-if='mentity.msignature.arity > 0'>
+ <span>(</span>
+ <span ng-repeat='mparam in mentity.msignature.mparams'>
+ <span>
+ <span>{{mparam.name}}</span>
+ <span ng-if='mentity.is_intro !== false'>
+ <span>: </span>
+ <entity-signature mentity='mparam.mtype' />
+ </span>
+ <span ng-if='mparam.is_vararg'>...</span>
+ </span>
+ <span ng-if='!first && !$last'>, </span>
+ </span>
+ <span>)</span>
+ </span>
+ <span ng-if='mentity.is_intro !== false && mentity.msignature.return_mtype'>
+ <span>: </span>
+ <entity-signature mentity='mentity.msignature.return_mtype' />
+ </span>
+ </span>
+ <span ng-if='mentity.is_intro !== false && mentity.static_mtype'>
+ <span>: </span>
+ <entity-signature mentity='mentity.static_mtype' />
+ </span>
+ <span ng-if='mentity.bound'>
+ <span>: </span>
+ <entity-signature mentity='mentity.bound' />
+ </span>
+</span>
--- /dev/null
+<span class="glyphicon glyphicon-tag" ng-class='{
+ "text-success": mentity.visibility == "public",
+ "text-warning": mentity.visibility == "protected",
+ "text-danger": mentity.visibility == "private",
+}' />
--- /dev/null
+<div class='media'>
+ <div class='media-left text-center' ng-if='mentity.visibility' ng-class='{
+ "text-success": mentity.visibility == "public",
+ "text-warning": mentity.visibility == "protected",
+ "text-danger": mentity.visibility == "private",
+ }'>
+ <span class="glyphicon glyphicon-tag"></span>
+ </div>
+ <div class='media-body'>
+ <h5 class='media-heading'>
+ <entity-signature mentity='mentity'/>
+ </h5>
+ <span class='synopsis'>{{mentity.mdoc.synopsis}}</span>
+ <div ng-if='recursive && mentity.mgroups'>
+ <group-block mentity-id='mgroup' ng-repeat='mgroup in mentity.mgroups' />
+ </div>
+ <div ng-if='recursive && mentity.mmodules'>
+ <module-block mentity-id='mmodule' ng-repeat='mmodule in mentity.mmodules' />
+ </div>
+ </div>
+</div>
--- /dev/null
+<button
+ class='btn btn-link btn-xs'
+ ng-click='toggle()'>
+ <span ng-if='property' ng-class='classesOn'/>
+ <span ng-if='!property' ng-class='classesOff'/>
+</button>
--- /dev/null
+<div class='form-group has-icon'>
+ <input type='text' class='form-control' ng-model='property' placeholder='Filter...'>
+ <span class='glyphicon glyphicon-search form-control-icon text-muted'></span>
+</div>
--- /dev/null
+<form class='form-inline'>
+ <ui-filter-field property='searchFilter.$' />
+ <div class='pull-right'>
+ <ui-filter-group-vis property='visibilityFilter' />
+ </div>
+</form>
--- /dev/null
+<div class='form-group'>
+ <ui-filter-button-vis property='property.public'
+ classes-on='"glyphicon glyphicon-eye-open text-success"'
+ classes-off='"glyphicon glyphicon-eye-close text-success"'
+ title='Toggle public' />
+ <ui-filter-button-vis property='property.protected'
+ classes-on='"glyphicon glyphicon-eye-open text-warning"'
+ classes-off='"glyphicon glyphicon-eye-close text-warning"'
+ title='Toggle protected' />
+ <ui-filter-button-vis property='property.private'
+ classes-on='"glyphicon glyphicon-eye-open text-danger"'
+ classes-off='"glyphicon glyphicon-eye-close text-danger"'
+ title='Toggle private' />
+</div>
--- /dev/null
+<!DOCTYPE html>
+<html lang='en' ng-app='nitweb'>
+ <head>
+ <base href='/'>
+ <meta charset='utf-8'>
+ <meta http-equiv='X-UA-Compatible' content='IE=edge'>
+ <meta name='viewport' content='width=device-width, initial-scale=1'>
+ <title>ng-doc</title>
+
+ <link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'
+ integrity='sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7'
+ crossorigin='anonymous' rel='stylesheet'>
+
+ <link href='/stylesheets/nitweb_bootstrap.css' rel='stylesheet'>
+ <link href='/stylesheets/nitweb.css' rel='stylesheet'>
+ </head>
+ <body>
+ <nav class='navbar navbar-default navbar-fixed-top'>
+ <div class='container-fluid'>
+ <div class='col-xs-3 navbar-header'>
+ <a class='navbar-brand' ng-href='/'>Nitdoc</a>
+ </div>
+ <div class='col-xs-7'>
+ <form ng-controller='SearchCtrl as searchCtrl' >
+ <div class='form-group has-icon'>
+ <input placeholder='Search...' type='text' class='form-control search-input'
+ ng-model-options='{ debounce: 150 }' ng-model='query'
+ ng-keydown='update($event)' ng-change='search()'>
+ <span class='glyphicon glyphicon-search form-control-icon text-muted'></span>
+ </div>
+ <div ng-if='results.length > 0' class='search-results'>
+ <div class='card-list'>
+ <entity-card ng-click='reset()' ng-class='{active: activeItem == $index}' mentity='mentity' ng-repeat='mentity in results' />
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ </nav>
+ <div ng-view></div>
+
+ <script src='https://code.jquery.com/jquery-1.12.4.min.js'
+ integrity='sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ='
+ crossorigin='anonymous''></script>
+ <script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js'
+ integrity='sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS'
+ crossorigin='anonymous'></script>
+ <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js'>
+ </script>
+ <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular-route.js'>
+ </script>
+ <script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular-sanitize.js'>
+ </script>
+
+ <script src='/javascripts/nitweb.js'></script>
+ <script src='/javascripts/model.js'></script>
+ <script src='/javascripts/entities.js'></script>
+ <script src='/javascripts/ui.js'></script>
+ <script src='/javascripts/index.js'></script>
+ </body>
+</html>
--- /dev/null
+/*
+ * Copyright 2016 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.
+ */
+
+(function() {
+ angular
+ .module('entities', ['ui', 'model'])
+
+ .controller('EntityCtrl', ['Model', '$routeParams', '$scope', function(Model, $routeParams, $scope) {
+ this.loadEntityLinearization = function() {
+ Model.loadEntityLinearization($routeParams.id,
+ function(data) {
+ $scope.linearization = data;
+ }, function(err) {
+ $scope.error = err;
+ });
+ };
+
+ this.loadEntityDefs = function() {
+ Model.loadEntityDefs($routeParams.id,
+ function(data) {
+ $scope.defs = data;
+ }, function(err) {
+ $scope.error = err;
+ });
+ };
+
+ this.loadEntityCode = function() {
+ Model.loadEntityCode($routeParams.id,
+ function(data) {
+ $scope.code = data;
+ }, function(err) {
+ $scope.code = err;
+ });
+ };
+
+ Model.loadEntity($routeParams.id,
+ function(data) {
+ $scope.mentity = data;
+ }, function(err) {
+ $scope.error = err;
+ });
+ }])
+
+ .directive('entityLink', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ mentity: '='
+ },
+ templateUrl: '/directives/entity/link.html'
+ };
+ })
+
+ .directive('entityDoc', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ mentity: '='
+ },
+ templateUrl: '/directives/entity/doc.html'
+ };
+ })
+
+ .directive('entitySignature', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ mentity: '='
+ },
+ templateUrl: '/directives/entity/signature.html'
+ };
+ })
+
+ .directive('entityTag', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ mentity: '='
+ },
+ replace: true,
+ templateUrl: '/directives/entity/tag.html'
+ };
+ })
+
+ .directive('entityLocation', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ mentity: '='
+ },
+ templateUrl: '/directives/entity/location.html'
+ };
+ })
+
+ .directive('entityCard', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ mentity: '='
+ },
+ replace: true,
+ templateUrl: '/directives/entity/card.html'
+ };
+ })
+
+ .directive('entityList', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ listEntities: '=',
+ listId: '@',
+ listTitle: '@',
+ listObjectFilter: '=',
+ },
+ templateUrl: '/directives/entity/list.html',
+ link: function ($scope, element, attrs) {
+ $scope.showFilters = false;
+ if(!$scope.listObjectFilter) {
+ $scope.listObjectFilter = {};
+ }
+ if(!$scope.visibilityFilter) {
+ $scope.visibilityFilter = {
+ public: true,
+ protected: true,
+ private: false
+ };
+ }
+ $scope.toggleFilters = function() {
+ $scope.showFilters = !$scope.showFilters;
+ };
+ }
+ };
+ })
+
+ .directive('entityLinearization', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ listEntities: '=',
+ listTitle: '@',
+ listFocus: '='
+ },
+ templateUrl: '/directives/entity/linearization.html'
+ };
+ })
+
+ .directive('entityDef', ['Model', function(Model, Code) {
+ return {
+ restrict: 'E',
+ scope: {
+ definition: '=',
+ focus: '='
+ },
+ templateUrl: '/directives/entity/defcard.html',
+ link: function ($scope, element, attrs) {
+ $scope.codeId = 'code_' + $scope.definition.full_name.replace(/[^a-zA-Z0-9]/g, '_');
+ $scope.loadCardCode = function() {
+ if(!$scope.code) {
+ Model.loadEntityCode($scope.definition.full_name,
+ function(data) {
+ $scope.code = data;
+ setTimeout(function() { // smooth collapse
+ $('#' + $scope.codeId).collapse('show')
+ }, 1);
+ }, function(err) {
+ $scope.code = err;
+ });
+ } else {
+ if($('#' + $scope.codeId).hasClass('in')) {
+ $('#' + $scope.codeId).collapse('hide');
+ } else {
+ $('#' + $scope.codeId).collapse('show');
+ }
+ }
+ };
+ }
+ };
+ }])
+})();
--- /dev/null
+/*
+ * Copyright 2016 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.
+ */
+
+(function() {
+ angular
+ .module('index', ['model', 'ngSanitize'])
+
+ .run(['$anchorScroll', function($anchorScroll) {
+ $anchorScroll.yOffset = 80;
+ }])
+
+ .controller('IndexCtrl', ['Catalog', '$routeParams', '$sce', '$scope', '$location', '$anchorScroll', function(Catalog, $routeParams, $sce, $scope, $location, $anchorScroll) {
+ this.loadHighlighted = function() {
+ Catalog.loadHightlighted(
+ function(data) {
+ $scope.highlighted = data;
+ }, function(err) {
+ $scope.error = err;
+ });
+ };
+
+ this.loadMostRequired = function() {
+ Catalog.loadMostRequired(
+ function(data) {
+ $scope.required = data;
+ }, function(err) {
+ $scope.error = err;
+ });
+ };
+
+ this.loadByTags = function() {
+ Catalog.loadByTags(
+ function(data) {
+ $scope.bytags = data;
+ }, function(err) {
+ $scope.error = err;
+ });
+ };
+
+ this.loadStats = function() {
+ Catalog.loadStats(
+ function(data) {
+ $scope.stats = data;
+ }, function(err) {
+ $scope.error = err;
+ });
+ };
+
+ this.loadContributors = function() {
+ Catalog.loadContributors(
+ function(data) {
+ $scope.contributors = data;
+ }, function(err) {
+ $scope.error = err;
+ });
+ };
+
+
+ this.scrollTo = function(hash) {
+ $anchorScroll(hash);
+ }
+
+ this.loadHighlighted();
+ this.loadStats();
+ this.loadContributors();
+ }])
+
+ .directive('contributorList', ['Model', function(Model) {
+ return {
+ restrict: 'E',
+ scope: {
+ listId: '@',
+ listTitle: '@',
+ listContributors: '='
+ },
+ templateUrl: '/directives/contributor-list.html'
+ };
+ }])
+})();
--- /dev/null
+/*
+ * Copyright 2016 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.
+ */
+
+(function() {
+ var apiUrl = '/api';
+
+ angular
+ .module('model', [])
+
+ .factory('Model', [ '$http', function($http) {
+ return {
+
+ loadEntity: function(id, cb, cbErr) {
+ $http.get(apiUrl + '/entity/' + id)
+ .success(cb)
+ .error(cbErr);
+ },
+
+ loadEntityLinearization: function(id, cb, cbErr) {
+ $http.get(apiUrl + '/linearization/' + id)
+ .success(cb)
+ .error(cbErr);
+ },
+
+ loadEntityDefs: function(id, cb, cbErr) {
+ $http.get(apiUrl + '/defs/' + id)
+ .success(cb)
+ .error(cbErr);
+ },
+
+ loadEntityCode: function(id, cb, cbErr) {
+ $http.get(apiUrl + '/code/' + id)
+ .success(cb)
+ .error(cbErr);
+ },
+
+ search: function(q, n, cb, cbErr) {
+ $http.get(apiUrl + '/search?q=' + q + '&n=' + n)
+ .success(cb)
+ .error(cbErr);
+ }
+ };
+ }])
+
+ .factory('Catalog', [ '$http', function($http) {
+ return {
+ loadHightlighted: function(cb, cbErr) {
+ $http.get(apiUrl + '/catalog/highlighted')
+ .success(cb)
+ .error(cbErr);
+ },
+
+ loadMostRequired: function(cb, cbErr) {
+ $http.get(apiUrl + '/catalog/required')
+ .success(cb)
+ .error(cbErr);
+ },
+
+ loadByTags: function(cb, cbErr) {
+ $http.get(apiUrl + '/catalog/bytags')
+ .success(cb)
+ .error(cbErr);
+ },
+
+ loadStats: function(cb, cbErr) {
+ $http.get(apiUrl + '/catalog/stats')
+ .success(cb)
+ .error(cbErr);
+ },
+
+ loadContributors: function(cb, cbErr) {
+ $http.get(apiUrl + '/catalog/contributors')
+ .success(cb)
+ .error(cbErr);
+ },
+ }
+ }])
+})();
--- /dev/null
+/*
+ * Copyright 2016 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.
+ */
+
+(function() {
+ angular.module('nitweb', ['ngRoute', 'ngSanitize', 'entities', 'index'])
+
+ .config(function($routeProvider, $locationProvider) {
+ $routeProvider
+ .when('/', {
+ templateUrl: 'views/index.html',
+ controller: 'IndexCtrl',
+ controllerAs: 'indexCtrl'
+ })
+ .when('/package/:id', {
+ templateUrl: 'views/package.html',
+ controller: 'EntityCtrl',
+ controllerAs: 'entityCtrl'
+ })
+ .when('/group/:id', {
+ templateUrl: 'views/group.html',
+ controller: 'EntityCtrl',
+ controllerAs: 'entityCtrl'
+ })
+ .when('/module/:id', {
+ templateUrl: 'views/module.html',
+ controller: 'EntityCtrl',
+ controllerAs: 'entityCtrl'
+ })
+ .when('/class/:id', {
+ templateUrl: 'views/class.html',
+ controller: 'EntityCtrl',
+ controllerAs: 'entityCtrl'
+ })
+ .when('/classdef/:id', {
+ templateUrl: 'views/classdef.html',
+ controller: 'EntityCtrl',
+ controllerAs: 'entityCtrl'
+ })
+ .when('/property/:id', {
+ templateUrl: 'views/property.html',
+ controller: 'EntityCtrl',
+ controllerAs: 'entityCtrl'
+ })
+ .when('/propdef/:id', {
+ templateUrl: 'views/propdef.html',
+ controller: 'EntityCtrl',
+ controllerAs: 'entityCtrl'
+ })
+ .otherwise({
+ redirectTo: '/'
+ });
+ $locationProvider.html5Mode(true);
+ });
+})();
--- /dev/null
+/*
+ * Copyright 2016 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.
+ */
+
+(function() {
+ angular
+ .module('ui', [ 'model' ])
+
+ .controller('SearchCtrl', ['Model', '$routeParams', '$scope', '$window', function(Model, $routeParams, $scope, $window) {
+ $scope.query = '';
+
+ $scope.reset = function() {
+ $scope.activeItem = 0;
+ $scope.results = [];
+ }
+
+ $scope.update = function(e) {
+ if(e.keyCode == 38) {
+ $scope.selectUp();
+ } else if(e.keyCode == 40) {
+ $scope.selectDown();
+ } else if(e.keyCode == 27) {
+ $scope.selectEscape();
+ } else if(e.keyCode == 13) {
+ $scope.selectEnter();
+ }
+ }
+
+ $scope.selectUp = function() {
+ if($scope.activeItem > 0) {
+ $scope.activeItem -= 1;
+ }
+ }
+
+ $scope.selectDown = function() {
+ if($scope.activeItem < $scope.results.length - 1) {
+ $scope.activeItem += 1;
+ }
+ }
+
+ $scope.selectEnter = function() {
+ $window.location.href = $scope.results[$scope.activeItem].web_url;
+ $scope.reset();
+ }
+
+ $scope.selectEscape = function() {
+ $scope.reset();
+ }
+
+ $scope.search = function() {
+ if(!$scope.query) {
+ $scope.reset();
+ return;
+ }
+ Model.search($scope.query, 10,
+ function(data) {
+ $scope.reset();
+ $scope.results = data;
+ }, function(err) {
+ $scope.reset();
+ $scope.error = err;
+ });
+ }
+
+ $scope.reset();
+ }])
+
+ .directive('uiFilters', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ property: '=',
+ classesOn: '=',
+ classesOff: '='
+ },
+ replace: true,
+ templateUrl: '/directives/ui-filter-button-vis.html',
+ link: function ($scope, element, attrs) {
+ $scope.toggle = function() {
+ $scope.property = !$scope.property;
+ }
+ }
+ };
+ })
+
+ .filter('visibility', function() {
+ return function(input, visibilityFilter) {
+ var res = [];
+ input.forEach(function(entry) {
+ if(visibilityFilter.public == false && entry.visibility == "public") {
+ return;
+ }
+ if(visibilityFilter.protected == false && entry.visibility == "protected") {
+ return;
+ }
+ if(visibilityFilter.private == false && entry.visibility == "private") {
+ return;
+ }
+ res.push(entry);
+ });
+ return res;
+ };
+ })
+
+ .directive('uiFilterForm', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ searchFilter: '=',
+ visibilityFilter: '='
+ },
+ replace: true,
+ templateUrl: '/directives/ui-filter-form.html'
+ };
+ })
+
+ .directive('uiFilterField', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ property: '='
+ },
+ replace: true,
+ templateUrl: '/directives/ui-filter-field.html'
+ };
+ })
+
+ .directive('uiFilterGroupVis', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ property: '='
+ },
+ replace: true,
+ templateUrl: '/directives/ui-filter-group-vis.html'
+ };
+ })
+
+ .directive('uiFilterButtonVis', function() {
+ return {
+ restrict: 'E',
+ scope: {
+ property: '=',
+ classesOn: '=',
+ classesOff: '='
+ },
+ replace: true,
+ templateUrl: '/directives/ui-filter-button-vis.html',
+ link: function ($scope, element, attrs) {
+ $scope.toggle = function() {
+ $scope.property = !$scope.property;
+ }
+ }
+ };
+ })
+})();
--- /dev/null
+/* Body */
+
+body {
+ background: #f2f2f2;
+ margin-top: 70px;
+ margin-bottom: 70px;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #666;
+}
+
+a {
+ cursor: pointer;
+}
+
+.nitdoc h1, .nitdoc h2, .nitdoc h3, .nitdoc h4, .nitdoc h5, .nitdoc h6 {
+ color: #333;
+}
+
+.page-header {
+ margin-top: 0;
+ border: none;
+}
+
+/* cards */
+
+.card.active {
+ border: 1px solid #1E9431;
+}
+
+.card, .card-body { overflow: hidden; }
+
+.card-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+
+.card {
+ background: #fff;
+ border: 1px solid #ccc;
+ margin-top: 10px;
+ box-shadow: 0 -1px 0 #e5e5e5,0 0 2px rgba(0,0,0,.12),0 2px 4px rgba(0,0,0,.24);
+}
+
+.card-body {
+ padding: 15px;
+ width: 10000px;
+}
+
+.card-body, .card-right, .card-left {
+ display: table-cell;
+ vertical-align: top;
+}
+
+.card-left, .card>.pull-left {
+ padding: 15px;
+ padding-right: 0px;
+}
+.card-right, .card>.pull-right {
+ padding: 15px;
+ padding-left: 0px;
+}
+
+.card-list {
+ margin-top: 10px;
+}
+
+.card-list > .card:first-child {
+ border-top: 1px solid #ccc;
+}
+
+.card-list > .card {
+ margin-top: 0;
+ border-top: none;
+}
+
+/* ui */
+
+.btn-bar { margin-top: -5px; float: right }
+.btn-bar .btn { padding: 5px 10px; }
+
+entity-list .btn-filter {
+ visibility: hidden;
+}
+
+entity-list:hover .btn-filter {
+ visibility: visible;
+}
+
+/* doc */
+
+.nitdoc .synopsys {
+ font-size: 2em;
+}
+
+.signature {
+ color: #666;
+ font-family: monospace;
+}
+
+.signature .name {
+ font-weight: bold;
+}
+
+.page-header .signature .name, .signature .signature .name {
+ font-weight: normal;
+}
+
+.signature .signature a {
+ color: #666;
+ font-family: monospace;
+}
+
+/* tabs */
+
+.nav-tabs li { cursor: pointer; }
+
+.nav>li.warning>a {
+ color: #fff;
+ background-color: #f0ad4e;
+}
+
+.nav>li.warning>a:focus, .nav>li.warning>a:hover {
+ background-color: #ff9c0f;
+}
+
+/* forms */
+
+.has-icon {
+ position: relative;
+}
+
+.has-icon .form-control {
+ padding-left: 35px;
+}
+
+.form-control-icon {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 2;
+ display: block;
+ width: 34px;
+ height: 34px;
+ line-height: 34px;
+ text-align: center;
+ pointer-events: none;
+}
+
+/* search */
+
+.search-input {
+ width: 100%;
+}
+
+.search-results {
+ position: absolute;
+ right: 0;
+}
+
+.search-results .card.active {
+ background: #eee;
+ border-color: #eee;
+}
+
+/* navs */
+
+.nav-tabs li { cursor: pointer; }
+
+.navbar-fixed-top {
+ background-color: #1E9431;
+ box-shadow: 0 0 4px rgba(0,0,0,.14),0 4px 8px rgba(0,0,0,.28);
+}
+
+.navbar-fixed-top .form-control:hover, .navbar-fixed-top .form-control:focus {
+ background: rgba(255, 255, 255, 0.2);
+}
+
+.navbar-fixed-top .form-control {
+ background: rgba(255, 255, 255, 0.1);
+ border: none;
+ color: #fff;
+ box-shadow: none;
+}
+
+.navbar-fixed-top .form-control-icon {
+ color: #fff;
+}
+
+.navbar-fixed-top *::-webkit-input-placeholder {
+ color: #fff;
+}
+.navbar-fixed-top *:-moz-placeholder {
+ /* FF 4-18 */
+ color: #fff;
+}
+.navbar-fixed-top *::-moz-placeholder {
+ /* FF 19+ */
+ color: #fff;
+}
+.navbar-fixed-top *:-ms-input-placeholder {
+ /* IE 10+ */
+ color: #fff;
+}
+
+.navbar-fixed-top .form-group {
+ margin-top: 8px;
+ margin-bottom: 0px;
+}
+/*
+ * Users
+ */
+
+.avatar {
+ border-radius: 2px;
+}
+
+/*
+ * Code Highlighting
+ */
+
+.nitcode a { color: inherit; text-decoration: inherit; } /* hide links */
+.nitcode a:hover { text-decoration: underline; } /* underline links */
+.nitcode span[title]:hover { text-decoration: underline; } /* underline titles */
+/* lexical raw tokens. independent of usage or semantic: */
+.nitcode .nc_c { color: gray; font-style: italic; } /* comment */
+.nitcode .nc_d { color: #3D8127; font-style: italic; } /* documentation comments */
+.nitcode .nc_k { font-weight: bold; } /* keyword */
+.nitcode .nc_o {} /* operator */
+.nitcode .nc_i {} /* standard identifier */
+.nitcode .nc_t { color: #445588; font-weight: bold; } /* type/class identifier */
+.nitcode .nc_a { color: #445588; font-style: italic; } /* old style attribute identifier */
+.nitcode .nc_l { color: #009999; } /* char and number literal */
+.nitcode .nc_s { color: #8F1546; } /* string literal */
+/* syntactic token usage. added because of their position in the AST */
+.nitcode .nc_ast { color: blue; } /* assert label */
+.nitcode .nc_la { color: blue; } /* break/continue label */
+.nitcode .nc_m { color: #445588; } /* module name */
+/* syntactic groups */
+.nitcode .nc_def { font-weight: bold; color: blue; } /* name used in a definition */
+.nitcode .nc_def.nc_a { color: blue; } /* name used in a attribute definition */
+.nitcode .nc_def.nc_t { color: blue; } /* name used in a class or vt definition */
+.nitcode .nc_ss { color: #9E6BEB; } /* superstrings */
+.nitcode .nc_cdef {} /* A whole class definition */
+.nitcode .nc_pdef {} /* A whole property definition */
+/* semantic token usage */
+.nitcode .nc_v { font-style: italic; } /* local variable or parameter */
+.nitcode .nc_vt { font-style: italic; } /* virtual type or formal type */
+.nitcode .nc_error { border: 1px red solid;} /* not used */
--- /dev/null
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */\r
+html {\r
+ font-family: sans-serif;\r
+ -ms-text-size-adjust: 100%;\r
+ -webkit-text-size-adjust: 100%;\r
+}\r
+body {\r
+ margin: 0;\r
+}\r
+article,\r
+aside,\r
+details,\r
+figcaption,\r
+figure,\r
+footer,\r
+header,\r
+hgroup,\r
+main,\r
+nav,\r
+section,\r
+summary {\r
+ display: block;\r
+}\r
+audio,\r
+canvas,\r
+progress,\r
+video {\r
+ display: inline-block;\r
+ vertical-align: baseline;\r
+}\r
+audio:not([controls]) {\r
+ display: none;\r
+ height: 0;\r
+}\r
+[hidden],\r
+template {\r
+ display: none;\r
+}\r
+a {\r
+ background: transparent;\r
+}\r
+a:active,\r
+a:hover {\r
+ outline: 0;\r
+}\r
+abbr[title] {\r
+ border-bottom: 1px dotted;\r
+}\r
+b,\r
+strong {\r
+ font-weight: bold;\r
+}\r
+dfn {\r
+ font-style: italic;\r
+}\r
+h1 {\r
+ font-size: 2em;\r
+ margin: 0.67em 0;\r
+}\r
+mark {\r
+ background: #ff0;\r
+ color: #000;\r
+}\r
+small {\r
+ font-size: 80%;\r
+}\r
+sub,\r
+sup {\r
+ font-size: 75%;\r
+ line-height: 0;\r
+ position: relative;\r
+ vertical-align: baseline;\r
+}\r
+sup {\r
+ top: -0.5em;\r
+}\r
+sub {\r
+ bottom: -0.25em;\r
+}\r
+img {\r
+ border: 0;\r
+}\r
+svg:not(:root) {\r
+ overflow: hidden;\r
+}\r
+figure {\r
+ margin: 1em 40px;\r
+}\r
+hr {\r
+ -moz-box-sizing: content-box;\r
+ box-sizing: content-box;\r
+ height: 0;\r
+}\r
+pre {\r
+ overflow: auto;\r
+}\r
+code,\r
+kbd,\r
+pre,\r
+samp {\r
+ font-family: monospace, monospace;\r
+ font-size: 1em;\r
+}\r
+button,\r
+input,\r
+optgroup,\r
+select,\r
+textarea {\r
+ color: inherit;\r
+ font: inherit;\r
+ margin: 0;\r
+}\r
+button {\r
+ overflow: visible;\r
+}\r
+button,\r
+select {\r
+ text-transform: none;\r
+}\r
+button,\r
+html input[type="button"],\r
+input[type="reset"],\r
+input[type="submit"] {\r
+ -webkit-appearance: button;\r
+ cursor: pointer;\r
+}\r
+button[disabled],\r
+html input[disabled] {\r
+ cursor: default;\r
+}\r
+button::-moz-focus-inner,\r
+input::-moz-focus-inner {\r
+ border: 0;\r
+ padding: 0;\r
+}\r
+input {\r
+ line-height: normal;\r
+}\r
+input[type="checkbox"],\r
+input[type="radio"] {\r
+ box-sizing: border-box;\r
+ padding: 0;\r
+}\r
+input[type="number"]::-webkit-inner-spin-button,\r
+input[type="number"]::-webkit-outer-spin-button {\r
+ height: auto;\r
+}\r
+input[type="search"] {\r
+ -webkit-appearance: textfield;\r
+ -moz-box-sizing: content-box;\r
+ -webkit-box-sizing: content-box;\r
+ box-sizing: content-box;\r
+}\r
+input[type="search"]::-webkit-search-cancel-button,\r
+input[type="search"]::-webkit-search-decoration {\r
+ -webkit-appearance: none;\r
+}\r
+fieldset {\r
+ border: 1px solid #c0c0c0;\r
+ margin: 0 2px;\r
+ padding: 0.35em 0.625em 0.75em;\r
+}\r
+legend {\r
+ border: 0;\r
+ padding: 0;\r
+}\r
+textarea {\r
+ overflow: auto;\r
+}\r
+optgroup {\r
+ font-weight: bold;\r
+}\r
+table {\r
+ border-collapse: collapse;\r
+ border-spacing: 0;\r
+}\r
+td,\r
+th {\r
+ padding: 0;\r
+}\r
+@media print {\r
+ * {\r
+ text-shadow: none !important;\r
+ color: #000 !important;\r
+ background: transparent !important;\r
+ box-shadow: none !important;\r
+ }\r
+ a,\r
+ a:visited {\r
+ text-decoration: underline;\r
+ }\r
+ a[href]:after {\r
+ content: " (" attr(href) ")";\r
+ }\r
+ abbr[title]:after {\r
+ content: " (" attr(title) ")";\r
+ }\r
+ a[href^="javascript:"]:after,\r
+ a[href^="#"]:after {\r
+ content: "";\r
+ }\r
+ pre,\r
+ blockquote {\r
+ border: 1px solid #999;\r
+ page-break-inside: avoid;\r
+ }\r
+ thead {\r
+ display: table-header-group;\r
+ }\r
+ tr,\r
+ img {\r
+ page-break-inside: avoid;\r
+ }\r
+ img {\r
+ max-width: 100% !important;\r
+ }\r
+ p,\r
+ h2,\r
+ h3 {\r
+ orphans: 3;\r
+ widows: 3;\r
+ }\r
+ h2,\r
+ h3 {\r
+ page-break-after: avoid;\r
+ }\r
+ select {\r
+ background: #fff !important;\r
+ }\r
+ .navbar {\r
+ display: none;\r
+ }\r
+ .table td,\r
+ .table th {\r
+ background-color: #fff !important;\r
+ }\r
+ .btn > .caret,\r
+ .dropup > .btn > .caret {\r
+ border-top-color: #000 !important;\r
+ }\r
+ .label {\r
+ border: 1px solid #000;\r
+ }\r
+ .table {\r
+ border-collapse: collapse !important;\r
+ }\r
+ .table-bordered th,\r
+ .table-bordered td {\r
+ border: 1px solid #ddd !important;\r
+ }\r
+}\r
+* {\r
+ -webkit-box-sizing: border-box;\r
+ -moz-box-sizing: border-box;\r
+ box-sizing: border-box;\r
+}\r
+*:before,\r
+*:after {\r
+ -webkit-box-sizing: border-box;\r
+ -moz-box-sizing: border-box;\r
+ box-sizing: border-box;\r
+}\r
+html {\r
+ font-size: 62.5%;\r
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\r
+}\r
+body {\r
+ font-family: sans-serif;\r
+ font-size: 14px;\r
+ line-height: 1.428571429;\r
+ color: #333333;\r
+ background-color: #f2f2f2;\r
+}\r
+input,\r
+button,\r
+select,\r
+textarea {\r
+ font-family: inherit;\r
+ font-size: inherit;\r
+ line-height: inherit;\r
+}\r
+a {\r
+ color: #0d8921;\r
+ text-decoration: none;\r
+}\r
+a:hover,\r
+a:focus {\r
+ color: #064310;\r
+ text-decoration: underline;\r
+}\r
+a:focus {\r
+ outline: thin dotted;\r
+ outline: 5px auto -webkit-focus-ring-color;\r
+ outline-offset: -2px;\r
+}\r
+figure {\r
+ margin: 0;\r
+}\r
+img {\r
+ vertical-align: middle;\r
+}\r
+.img-responsive,\r
+.thumbnail > img,\r
+.thumbnail a > img,\r
+.carousel-inner > .item > img,\r
+.carousel-inner > .item > a > img {\r
+ display: block;\r
+ max-width: 100%;\r
+ height: auto;\r
+}\r
+.img-rounded {\r
+ border-radius: 0px;\r
+}\r
+.img-thumbnail {\r
+ padding: 4px;\r
+ line-height: 1.428571429;\r
+ background-color: #f2f2f2;\r
+ border: 1px solid #dddddd;\r
+ border-radius: 0px;\r
+ -webkit-transition: all 0.2s ease-in-out;\r
+ transition: all 0.2s ease-in-out;\r
+ display: inline-block;\r
+ max-width: 100%;\r
+ height: auto;\r
+}\r
+.img-circle {\r
+ border-radius: 50%;\r
+}\r
+hr {\r
+ margin-top: 20px;\r
+ margin-bottom: 20px;\r
+ border: 0;\r
+ border-top: 1px solid #eeeeee;\r
+}\r
+.sr-only {\r
+ position: absolute;\r
+ width: 1px;\r
+ height: 1px;\r
+ margin: -1px;\r
+ padding: 0;\r
+ overflow: hidden;\r
+ clip: rect(0, 0, 0, 0);\r
+ border: 0;\r
+}\r
+h1,\r
+h2,\r
+h3,\r
+h4,\r
+h5,\r
+h6,\r
+.h1,\r
+.h2,\r
+.h3,\r
+.h4,\r
+.h5,\r
+.h6 {\r
+ font-family: sans-serif;\r
+ font-weight: 500;\r
+ line-height: 1.1;\r
+ color: inherit;\r
+}\r
+h1 small,\r
+h2 small,\r
+h3 small,\r
+h4 small,\r
+h5 small,\r
+h6 small,\r
+.h1 small,\r
+.h2 small,\r
+.h3 small,\r
+.h4 small,\r
+.h5 small,\r
+.h6 small,\r
+h1 .small,\r
+h2 .small,\r
+h3 .small,\r
+h4 .small,\r
+h5 .small,\r
+h6 .small,\r
+.h1 .small,\r
+.h2 .small,\r
+.h3 .small,\r
+.h4 .small,\r
+.h5 .small,\r
+.h6 .small {\r
+ font-weight: normal;\r
+ line-height: 1;\r
+ color: #999999;\r
+}\r
+h1,\r
+.h1,\r
+h2,\r
+.h2,\r
+h3,\r
+.h3 {\r
+ margin-top: 20px;\r
+ margin-bottom: 10px;\r
+}\r
+h1 small,\r
+.h1 small,\r
+h2 small,\r
+.h2 small,\r
+h3 small,\r
+.h3 small,\r
+h1 .small,\r
+.h1 .small,\r
+h2 .small,\r
+.h2 .small,\r
+h3 .small,\r
+.h3 .small {\r
+ font-size: 65%;\r
+}\r
+h4,\r
+.h4,\r
+h5,\r
+.h5,\r
+h6,\r
+.h6 {\r
+ margin-top: 10px;\r
+ margin-bottom: 10px;\r
+}\r
+h4 small,\r
+.h4 small,\r
+h5 small,\r
+.h5 small,\r
+h6 small,\r
+.h6 small,\r
+h4 .small,\r
+.h4 .small,\r
+h5 .small,\r
+.h5 .small,\r
+h6 .small,\r
+.h6 .small {\r
+ font-size: 75%;\r
+}\r
+h1,\r
+.h1 {\r
+ font-size: 36px;\r
+}\r
+h2,\r
+.h2 {\r
+ font-size: 30px;\r
+}\r
+h3,\r
+.h3 {\r
+ font-size: 23px;\r
+}\r
+h4,\r
+.h4 {\r
+ font-size: 17px;\r
+}\r
+h5,\r
+.h5 {\r
+ font-size: 14px;\r
+}\r
+h6,\r
+.h6 {\r
+ font-size: 11px;\r
+}\r
+p {\r
+ margin: 0 0 10px;\r
+}\r
+.lead {\r
+ margin-bottom: 20px;\r
+ font-size: 16px;\r
+ font-weight: 200;\r
+ line-height: 1.4;\r
+}\r
+@media (min-width: 768px) {\r
+ .lead {\r
+ font-size: 21px;\r
+ }\r
+}\r
+small,\r
+.small {\r
+ font-size: 85%;\r
+}\r
+cite {\r
+ font-style: normal;\r
+}\r
+.text-left {\r
+ text-align: left;\r
+}\r
+.text-right {\r
+ text-align: right;\r
+}\r
+.text-center {\r
+ text-align: center;\r
+}\r
+.text-justify {\r
+ text-align: justify;\r
+}\r
+.text-muted {\r
+ color: #999999;\r
+}\r
+.text-primary {\r
+ color: #0d8921;\r
+}\r
+a.text-primary:hover {\r
+ color: #095a16;\r
+}\r
+.text-success {\r
+ color: #5cb85c;\r
+}\r
+a.text-success:hover {\r
+ color: #449d44;\r
+}\r
+.text-info {\r
+ color: #5bc0de;\r
+}\r
+a.text-info:hover {\r
+ color: #31b0d5;\r
+}\r
+.text-warning {\r
+ color: #f0ad4e;\r
+}\r
+a.text-warning:hover {\r
+ color: #ec971f;\r
+}\r
+.text-danger {\r
+ color: #d9534f;\r
+}\r
+a.text-danger:hover {\r
+ color: #c9302c;\r
+}\r
+.bg-primary {\r
+ color: #fff;\r
+ background-color: #0d8921;\r
+}\r
+a.bg-primary:hover {\r
+ background-color: #095a16;\r
+}\r
+.bg-success {\r
+ background-color: #dff0d8;\r
+}\r
+a.bg-success:hover {\r
+ background-color: #c1e2b3;\r
+}\r
+.bg-info {\r
+ background-color: #d9edf7;\r
+}\r
+a.bg-info:hover {\r
+ background-color: #afd9ee;\r
+}\r
+.bg-warning {\r
+ background-color: #fcf8e3;\r
+}\r
+a.bg-warning:hover {\r
+ background-color: #f7ecb5;\r
+}\r
+.bg-danger {\r
+ background-color: #f2dede;\r
+}\r
+a.bg-danger:hover {\r
+ background-color: #e4b9b9;\r
+}\r
+.page-header {\r
+ padding-bottom: 9px;\r
+ margin: 40px 0 20px;\r
+ border-bottom: 1px solid #eeeeee;\r
+}\r
+ul,\r
+ol {\r
+ margin-top: 0;\r
+ margin-bottom: 10px;\r
+}\r
+ul ul,\r
+ol ul,\r
+ul ol,\r
+ol ol {\r
+ margin-bottom: 0;\r
+}\r
+.list-unstyled {\r
+ padding-left: 0;\r
+ list-style: none;\r
+}\r
+.list-inline {\r
+ padding-left: 0;\r
+ list-style: none;\r
+}\r
+.list-inline > li {\r
+ display: inline-block;\r
+ padding-left: 5px;\r
+ padding-right: 5px;\r
+}\r
+.list-inline > li:first-child {\r
+ padding-left: 0;\r
+}\r
+dl {\r
+ margin-top: 0;\r
+ margin-bottom: 20px;\r
+}\r
+dt,\r
+dd {\r
+ line-height: 1.428571429;\r
+}\r
+dt {\r
+ font-weight: bold;\r
+}\r
+dd {\r
+ margin-left: 0;\r
+}\r
+@media (min-width: 768px) {\r
+ .dl-horizontal dt {\r
+ float: left;\r
+ width: 160px;\r
+ clear: left;\r
+ text-align: right;\r
+ overflow: hidden;\r
+ text-overflow: ellipsis;\r
+ white-space: nowrap;\r
+ }\r
+ .dl-horizontal dd {\r
+ margin-left: 180px;\r
+ }\r
+}\r
+abbr[title],\r
+abbr[data-original-title] {\r
+ cursor: help;\r
+ border-bottom: 1px dotted #999999;\r
+}\r
+.initialism {\r
+ font-size: 90%;\r
+ text-transform: uppercase;\r
+}\r
+blockquote {\r
+ padding: 10px 20px;\r
+ margin: 0 0 20px;\r
+ font-size: 17.5px;\r
+ border-left: 5px solid #eeeeee;\r
+}\r
+blockquote p:last-child,\r
+blockquote ul:last-child,\r
+blockquote ol:last-child {\r
+ margin-bottom: 0;\r
+}\r
+blockquote footer,\r
+blockquote small,\r
+blockquote .small {\r
+ display: block;\r
+ font-size: 80%;\r
+ line-height: 1.428571429;\r
+ color: #999999;\r
+}\r
+blockquote footer:before,\r
+blockquote small:before,\r
+blockquote .small:before {\r
+ content: '\2014 \00A0';\r
+}\r
+.blockquote-reverse,\r
+blockquote.pull-right {\r
+ padding-right: 15px;\r
+ padding-left: 0;\r
+ border-right: 5px solid #eeeeee;\r
+ border-left: 0;\r
+ text-align: right;\r
+}\r
+.blockquote-reverse footer:before,\r
+blockquote.pull-right footer:before,\r
+.blockquote-reverse small:before,\r
+blockquote.pull-right small:before,\r
+.blockquote-reverse .small:before,\r
+blockquote.pull-right .small:before {\r
+ content: '';\r
+}\r
+.blockquote-reverse footer:after,\r
+blockquote.pull-right footer:after,\r
+.blockquote-reverse small:after,\r
+blockquote.pull-right small:after,\r
+.blockquote-reverse .small:after,\r
+blockquote.pull-right .small:after {\r
+ content: '\00A0 \2014';\r
+}\r
+blockquote:before,\r
+blockquote:after {\r
+ content: "";\r
+}\r
+address {\r
+ margin-bottom: 20px;\r
+ font-style: normal;\r
+ line-height: 1.428571429;\r
+}\r
+code,\r
+kbd,\r
+pre,\r
+samp {\r
+ font-family: monospace;\r
+}\r
+code {\r
+ padding: 2px 4px;\r
+ font-size: 90%;\r
+ color: #c7254e;\r
+ background-color: #f9f2f4;\r
+ white-space: nowrap;\r
+ border-radius: 0px;\r
+}\r
+kbd {\r
+ padding: 2px 4px;\r
+ font-size: 90%;\r
+ color: #ffffff;\r
+ background-color: #333333;\r
+ border-radius: 0px;\r
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\r
+}\r
+pre {\r
+ display: block;\r
+ padding: 9.5px;\r
+ margin: 0 0 10px;\r
+ font-size: 13px;\r
+ line-height: 1.428571429;\r
+ word-break: break-all;\r
+ word-wrap: break-word;\r
+ color: #333333;\r
+ background-color: #f5f5f5;\r
+ border: 1px solid #cccccc;\r
+ border-radius: 0px;\r
+}\r
+pre code {\r
+ padding: 0;\r
+ font-size: inherit;\r
+ color: inherit;\r
+ white-space: pre-wrap;\r
+ background-color: transparent;\r
+ border-radius: 0;\r
+}\r
+.pre-scrollable {\r
+ max-height: 340px;\r
+ overflow-y: scroll;\r
+}\r
+.container {\r
+ margin-right: auto;\r
+ margin-left: auto;\r
+ padding-left: 15px;\r
+ padding-right: 15px;\r
+}\r
+@media (min-width: 768px) {\r
+ .container {\r
+ width: 750px;\r
+ }\r
+}\r
+@media (min-width: 992px) {\r
+ .container {\r
+ width: 970px;\r
+ }\r
+}\r
+@media (min-width: 1200px) {\r
+ .container {\r
+ width: 1170px;\r
+ }\r
+}\r
+.container-fluid {\r
+ margin-right: auto;\r
+ margin-left: auto;\r
+ padding-left: 15px;\r
+ padding-right: 15px;\r
+}\r
+.row {\r
+ margin-left: -15px;\r
+ margin-right: -15px;\r
+}\r
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\r
+ position: relative;\r
+ min-height: 1px;\r
+ padding-left: 15px;\r
+ padding-right: 15px;\r
+}\r
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\r
+ float: left;\r
+}\r
+.col-xs-12 {\r
+ width: 100%;\r
+}\r
+.col-xs-11 {\r
+ width: 91.66666666666666%;\r
+}\r
+.col-xs-10 {\r
+ width: 83.33333333333334%;\r
+}\r
+.col-xs-9 {\r
+ width: 75%;\r
+}\r
+.col-xs-8 {\r
+ width: 66.66666666666666%;\r
+}\r
+.col-xs-7 {\r
+ width: 58.333333333333336%;\r
+}\r
+.col-xs-6 {\r
+ width: 50%;\r
+}\r
+.col-xs-5 {\r
+ width: 41.66666666666667%;\r
+}\r
+.col-xs-4 {\r
+ width: 33.33333333333333%;\r
+}\r
+.col-xs-3 {\r
+ width: 25%;\r
+}\r
+.col-xs-2 {\r
+ width: 16.666666666666664%;\r
+}\r
+.col-xs-1 {\r
+ width: 8.333333333333332%;\r
+}\r
+.col-xs-pull-12 {\r
+ right: 100%;\r
+}\r
+.col-xs-pull-11 {\r
+ right: 91.66666666666666%;\r
+}\r
+.col-xs-pull-10 {\r
+ right: 83.33333333333334%;\r
+}\r
+.col-xs-pull-9 {\r
+ right: 75%;\r
+}\r
+.col-xs-pull-8 {\r
+ right: 66.66666666666666%;\r
+}\r
+.col-xs-pull-7 {\r
+ right: 58.333333333333336%;\r
+}\r
+.col-xs-pull-6 {\r
+ right: 50%;\r
+}\r
+.col-xs-pull-5 {\r
+ right: 41.66666666666667%;\r
+}\r
+.col-xs-pull-4 {\r
+ right: 33.33333333333333%;\r
+}\r
+.col-xs-pull-3 {\r
+ right: 25%;\r
+}\r
+.col-xs-pull-2 {\r
+ right: 16.666666666666664%;\r
+}\r
+.col-xs-pull-1 {\r
+ right: 8.333333333333332%;\r
+}\r
+.col-xs-pull-0 {\r
+ right: 0%;\r
+}\r
+.col-xs-push-12 {\r
+ left: 100%;\r
+}\r
+.col-xs-push-11 {\r
+ left: 91.66666666666666%;\r
+}\r
+.col-xs-push-10 {\r
+ left: 83.33333333333334%;\r
+}\r
+.col-xs-push-9 {\r
+ left: 75%;\r
+}\r
+.col-xs-push-8 {\r
+ left: 66.66666666666666%;\r
+}\r
+.col-xs-push-7 {\r
+ left: 58.333333333333336%;\r
+}\r
+.col-xs-push-6 {\r
+ left: 50%;\r
+}\r
+.col-xs-push-5 {\r
+ left: 41.66666666666667%;\r
+}\r
+.col-xs-push-4 {\r
+ left: 33.33333333333333%;\r
+}\r
+.col-xs-push-3 {\r
+ left: 25%;\r
+}\r
+.col-xs-push-2 {\r
+ left: 16.666666666666664%;\r
+}\r
+.col-xs-push-1 {\r
+ left: 8.333333333333332%;\r
+}\r
+.col-xs-push-0 {\r
+ left: 0%;\r
+}\r
+.col-xs-offset-12 {\r
+ margin-left: 100%;\r
+}\r
+.col-xs-offset-11 {\r
+ margin-left: 91.66666666666666%;\r
+}\r
+.col-xs-offset-10 {\r
+ margin-left: 83.33333333333334%;\r
+}\r
+.col-xs-offset-9 {\r
+ margin-left: 75%;\r
+}\r
+.col-xs-offset-8 {\r
+ margin-left: 66.66666666666666%;\r
+}\r
+.col-xs-offset-7 {\r
+ margin-left: 58.333333333333336%;\r
+}\r
+.col-xs-offset-6 {\r
+ margin-left: 50%;\r
+}\r
+.col-xs-offset-5 {\r
+ margin-left: 41.66666666666667%;\r
+}\r
+.col-xs-offset-4 {\r
+ margin-left: 33.33333333333333%;\r
+}\r
+.col-xs-offset-3 {\r
+ margin-left: 25%;\r
+}\r
+.col-xs-offset-2 {\r
+ margin-left: 16.666666666666664%;\r
+}\r
+.col-xs-offset-1 {\r
+ margin-left: 8.333333333333332%;\r
+}\r
+.col-xs-offset-0 {\r
+ margin-left: 0%;\r
+}\r
+@media (min-width: 768px) {\r
+ .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\r
+ float: left;\r
+ }\r
+ .col-sm-12 {\r
+ width: 100%;\r
+ }\r
+ .col-sm-11 {\r
+ width: 91.66666666666666%;\r
+ }\r
+ .col-sm-10 {\r
+ width: 83.33333333333334%;\r
+ }\r
+ .col-sm-9 {\r
+ width: 75%;\r
+ }\r
+ .col-sm-8 {\r
+ width: 66.66666666666666%;\r
+ }\r
+ .col-sm-7 {\r
+ width: 58.333333333333336%;\r
+ }\r
+ .col-sm-6 {\r
+ width: 50%;\r
+ }\r
+ .col-sm-5 {\r
+ width: 41.66666666666667%;\r
+ }\r
+ .col-sm-4 {\r
+ width: 33.33333333333333%;\r
+ }\r
+ .col-sm-3 {\r
+ width: 25%;\r
+ }\r
+ .col-sm-2 {\r
+ width: 16.666666666666664%;\r
+ }\r
+ .col-sm-1 {\r
+ width: 8.333333333333332%;\r
+ }\r
+ .col-sm-pull-12 {\r
+ right: 100%;\r
+ }\r
+ .col-sm-pull-11 {\r
+ right: 91.66666666666666%;\r
+ }\r
+ .col-sm-pull-10 {\r
+ right: 83.33333333333334%;\r
+ }\r
+ .col-sm-pull-9 {\r
+ right: 75%;\r
+ }\r
+ .col-sm-pull-8 {\r
+ right: 66.66666666666666%;\r
+ }\r
+ .col-sm-pull-7 {\r
+ right: 58.333333333333336%;\r
+ }\r
+ .col-sm-pull-6 {\r
+ right: 50%;\r
+ }\r
+ .col-sm-pull-5 {\r
+ right: 41.66666666666667%;\r
+ }\r
+ .col-sm-pull-4 {\r
+ right: 33.33333333333333%;\r
+ }\r
+ .col-sm-pull-3 {\r
+ right: 25%;\r
+ }\r
+ .col-sm-pull-2 {\r
+ right: 16.666666666666664%;\r
+ }\r
+ .col-sm-pull-1 {\r
+ right: 8.333333333333332%;\r
+ }\r
+ .col-sm-pull-0 {\r
+ right: 0%;\r
+ }\r
+ .col-sm-push-12 {\r
+ left: 100%;\r
+ }\r
+ .col-sm-push-11 {\r
+ left: 91.66666666666666%;\r
+ }\r
+ .col-sm-push-10 {\r
+ left: 83.33333333333334%;\r
+ }\r
+ .col-sm-push-9 {\r
+ left: 75%;\r
+ }\r
+ .col-sm-push-8 {\r
+ left: 66.66666666666666%;\r
+ }\r
+ .col-sm-push-7 {\r
+ left: 58.333333333333336%;\r
+ }\r
+ .col-sm-push-6 {\r
+ left: 50%;\r
+ }\r
+ .col-sm-push-5 {\r
+ left: 41.66666666666667%;\r
+ }\r
+ .col-sm-push-4 {\r
+ left: 33.33333333333333%;\r
+ }\r
+ .col-sm-push-3 {\r
+ left: 25%;\r
+ }\r
+ .col-sm-push-2 {\r
+ left: 16.666666666666664%;\r
+ }\r
+ .col-sm-push-1 {\r
+ left: 8.333333333333332%;\r
+ }\r
+ .col-sm-push-0 {\r
+ left: 0%;\r
+ }\r
+ .col-sm-offset-12 {\r
+ margin-left: 100%;\r
+ }\r
+ .col-sm-offset-11 {\r
+ margin-left: 91.66666666666666%;\r
+ }\r
+ .col-sm-offset-10 {\r
+ margin-left: 83.33333333333334%;\r
+ }\r
+ .col-sm-offset-9 {\r
+ margin-left: 75%;\r
+ }\r
+ .col-sm-offset-8 {\r
+ margin-left: 66.66666666666666%;\r
+ }\r
+ .col-sm-offset-7 {\r
+ margin-left: 58.333333333333336%;\r
+ }\r
+ .col-sm-offset-6 {\r
+ margin-left: 50%;\r
+ }\r
+ .col-sm-offset-5 {\r
+ margin-left: 41.66666666666667%;\r
+ }\r
+ .col-sm-offset-4 {\r
+ margin-left: 33.33333333333333%;\r
+ }\r
+ .col-sm-offset-3 {\r
+ margin-left: 25%;\r
+ }\r
+ .col-sm-offset-2 {\r
+ margin-left: 16.666666666666664%;\r
+ }\r
+ .col-sm-offset-1 {\r
+ margin-left: 8.333333333333332%;\r
+ }\r
+ .col-sm-offset-0 {\r
+ margin-left: 0%;\r
+ }\r
+}\r
+@media (min-width: 992px) {\r
+ .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\r
+ float: left;\r
+ }\r
+ .col-md-12 {\r
+ width: 100%;\r
+ }\r
+ .col-md-11 {\r
+ width: 91.66666666666666%;\r
+ }\r
+ .col-md-10 {\r
+ width: 83.33333333333334%;\r
+ }\r
+ .col-md-9 {\r
+ width: 75%;\r
+ }\r
+ .col-md-8 {\r
+ width: 66.66666666666666%;\r
+ }\r
+ .col-md-7 {\r
+ width: 58.333333333333336%;\r
+ }\r
+ .col-md-6 {\r
+ width: 50%;\r
+ }\r
+ .col-md-5 {\r
+ width: 41.66666666666667%;\r
+ }\r
+ .col-md-4 {\r
+ width: 33.33333333333333%;\r
+ }\r
+ .col-md-3 {\r
+ width: 25%;\r
+ }\r
+ .col-md-2 {\r
+ width: 16.666666666666664%;\r
+ }\r
+ .col-md-1 {\r
+ width: 8.333333333333332%;\r
+ }\r
+ .col-md-pull-12 {\r
+ right: 100%;\r
+ }\r
+ .col-md-pull-11 {\r
+ right: 91.66666666666666%;\r
+ }\r
+ .col-md-pull-10 {\r
+ right: 83.33333333333334%;\r
+ }\r
+ .col-md-pull-9 {\r
+ right: 75%;\r
+ }\r
+ .col-md-pull-8 {\r
+ right: 66.66666666666666%;\r
+ }\r
+ .col-md-pull-7 {\r
+ right: 58.333333333333336%;\r
+ }\r
+ .col-md-pull-6 {\r
+ right: 50%;\r
+ }\r
+ .col-md-pull-5 {\r
+ right: 41.66666666666667%;\r
+ }\r
+ .col-md-pull-4 {\r
+ right: 33.33333333333333%;\r
+ }\r
+ .col-md-pull-3 {\r
+ right: 25%;\r
+ }\r
+ .col-md-pull-2 {\r
+ right: 16.666666666666664%;\r
+ }\r
+ .col-md-pull-1 {\r
+ right: 8.333333333333332%;\r
+ }\r
+ .col-md-pull-0 {\r
+ right: 0%;\r
+ }\r
+ .col-md-push-12 {\r
+ left: 100%;\r
+ }\r
+ .col-md-push-11 {\r
+ left: 91.66666666666666%;\r
+ }\r
+ .col-md-push-10 {\r
+ left: 83.33333333333334%;\r
+ }\r
+ .col-md-push-9 {\r
+ left: 75%;\r
+ }\r
+ .col-md-push-8 {\r
+ left: 66.66666666666666%;\r
+ }\r
+ .col-md-push-7 {\r
+ left: 58.333333333333336%;\r
+ }\r
+ .col-md-push-6 {\r
+ left: 50%;\r
+ }\r
+ .col-md-push-5 {\r
+ left: 41.66666666666667%;\r
+ }\r
+ .col-md-push-4 {\r
+ left: 33.33333333333333%;\r
+ }\r
+ .col-md-push-3 {\r
+ left: 25%;\r
+ }\r
+ .col-md-push-2 {\r
+ left: 16.666666666666664%;\r
+ }\r
+ .col-md-push-1 {\r
+ left: 8.333333333333332%;\r
+ }\r
+ .col-md-push-0 {\r
+ left: 0%;\r
+ }\r
+ .col-md-offset-12 {\r
+ margin-left: 100%;\r
+ }\r
+ .col-md-offset-11 {\r
+ margin-left: 91.66666666666666%;\r
+ }\r
+ .col-md-offset-10 {\r
+ margin-left: 83.33333333333334%;\r
+ }\r
+ .col-md-offset-9 {\r
+ margin-left: 75%;\r
+ }\r
+ .col-md-offset-8 {\r
+ margin-left: 66.66666666666666%;\r
+ }\r
+ .col-md-offset-7 {\r
+ margin-left: 58.333333333333336%;\r
+ }\r
+ .col-md-offset-6 {\r
+ margin-left: 50%;\r
+ }\r
+ .col-md-offset-5 {\r
+ margin-left: 41.66666666666667%;\r
+ }\r
+ .col-md-offset-4 {\r
+ margin-left: 33.33333333333333%;\r
+ }\r
+ .col-md-offset-3 {\r
+ margin-left: 25%;\r
+ }\r
+ .col-md-offset-2 {\r
+ margin-left: 16.666666666666664%;\r
+ }\r
+ .col-md-offset-1 {\r
+ margin-left: 8.333333333333332%;\r
+ }\r
+ .col-md-offset-0 {\r
+ margin-left: 0%;\r
+ }\r
+}\r
+@media (min-width: 1200px) {\r
+ .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\r
+ float: left;\r
+ }\r
+ .col-lg-12 {\r
+ width: 100%;\r
+ }\r
+ .col-lg-11 {\r
+ width: 91.66666666666666%;\r
+ }\r
+ .col-lg-10 {\r
+ width: 83.33333333333334%;\r
+ }\r
+ .col-lg-9 {\r
+ width: 75%;\r
+ }\r
+ .col-lg-8 {\r
+ width: 66.66666666666666%;\r
+ }\r
+ .col-lg-7 {\r
+ width: 58.333333333333336%;\r
+ }\r
+ .col-lg-6 {\r
+ width: 50%;\r
+ }\r
+ .col-lg-5 {\r
+ width: 41.66666666666667%;\r
+ }\r
+ .col-lg-4 {\r
+ width: 33.33333333333333%;\r
+ }\r
+ .col-lg-3 {\r
+ width: 25%;\r
+ }\r
+ .col-lg-2 {\r
+ width: 16.666666666666664%;\r
+ }\r
+ .col-lg-1 {\r
+ width: 8.333333333333332%;\r
+ }\r
+ .col-lg-pull-12 {\r
+ right: 100%;\r
+ }\r
+ .col-lg-pull-11 {\r
+ right: 91.66666666666666%;\r
+ }\r
+ .col-lg-pull-10 {\r
+ right: 83.33333333333334%;\r
+ }\r
+ .col-lg-pull-9 {\r
+ right: 75%;\r
+ }\r
+ .col-lg-pull-8 {\r
+ right: 66.66666666666666%;\r
+ }\r
+ .col-lg-pull-7 {\r
+ right: 58.333333333333336%;\r
+ }\r
+ .col-lg-pull-6 {\r
+ right: 50%;\r
+ }\r
+ .col-lg-pull-5 {\r
+ right: 41.66666666666667%;\r
+ }\r
+ .col-lg-pull-4 {\r
+ right: 33.33333333333333%;\r
+ }\r
+ .col-lg-pull-3 {\r
+ right: 25%;\r
+ }\r
+ .col-lg-pull-2 {\r
+ right: 16.666666666666664%;\r
+ }\r
+ .col-lg-pull-1 {\r
+ right: 8.333333333333332%;\r
+ }\r
+ .col-lg-pull-0 {\r
+ right: 0%;\r
+ }\r
+ .col-lg-push-12 {\r
+ left: 100%;\r
+ }\r
+ .col-lg-push-11 {\r
+ left: 91.66666666666666%;\r
+ }\r
+ .col-lg-push-10 {\r
+ left: 83.33333333333334%;\r
+ }\r
+ .col-lg-push-9 {\r
+ left: 75%;\r
+ }\r
+ .col-lg-push-8 {\r
+ left: 66.66666666666666%;\r
+ }\r
+ .col-lg-push-7 {\r
+ left: 58.333333333333336%;\r
+ }\r
+ .col-lg-push-6 {\r
+ left: 50%;\r
+ }\r
+ .col-lg-push-5 {\r
+ left: 41.66666666666667%;\r
+ }\r
+ .col-lg-push-4 {\r
+ left: 33.33333333333333%;\r
+ }\r
+ .col-lg-push-3 {\r
+ left: 25%;\r
+ }\r
+ .col-lg-push-2 {\r
+ left: 16.666666666666664%;\r
+ }\r
+ .col-lg-push-1 {\r
+ left: 8.333333333333332%;\r
+ }\r
+ .col-lg-push-0 {\r
+ left: 0%;\r
+ }\r
+ .col-lg-offset-12 {\r
+ margin-left: 100%;\r
+ }\r
+ .col-lg-offset-11 {\r
+ margin-left: 91.66666666666666%;\r
+ }\r
+ .col-lg-offset-10 {\r
+ margin-left: 83.33333333333334%;\r
+ }\r
+ .col-lg-offset-9 {\r
+ margin-left: 75%;\r
+ }\r
+ .col-lg-offset-8 {\r
+ margin-left: 66.66666666666666%;\r
+ }\r
+ .col-lg-offset-7 {\r
+ margin-left: 58.333333333333336%;\r
+ }\r
+ .col-lg-offset-6 {\r
+ margin-left: 50%;\r
+ }\r
+ .col-lg-offset-5 {\r
+ margin-left: 41.66666666666667%;\r
+ }\r
+ .col-lg-offset-4 {\r
+ margin-left: 33.33333333333333%;\r
+ }\r
+ .col-lg-offset-3 {\r
+ margin-left: 25%;\r
+ }\r
+ .col-lg-offset-2 {\r
+ margin-left: 16.666666666666664%;\r
+ }\r
+ .col-lg-offset-1 {\r
+ margin-left: 8.333333333333332%;\r
+ }\r
+ .col-lg-offset-0 {\r
+ margin-left: 0%;\r
+ }\r
+}\r
+table {\r
+ max-width: 100%;\r
+ background-color: transparent;\r
+}\r
+th {\r
+ text-align: left;\r
+}\r
+.table {\r
+ width: 100%;\r
+ margin-bottom: 20px;\r
+}\r
+.table > thead > tr > th,\r
+.table > tbody > tr > th,\r
+.table > tfoot > tr > th,\r
+.table > thead > tr > td,\r
+.table > tbody > tr > td,\r
+.table > tfoot > tr > td {\r
+ padding: 8px;\r
+ line-height: 1.428571429;\r
+ vertical-align: top;\r
+ border-top: 1px solid #dddddd;\r
+}\r
+.table > thead > tr > th {\r
+ vertical-align: bottom;\r
+ border-bottom: 2px solid #dddddd;\r
+}\r
+.table > caption + thead > tr:first-child > th,\r
+.table > colgroup + thead > tr:first-child > th,\r
+.table > thead:first-child > tr:first-child > th,\r
+.table > caption + thead > tr:first-child > td,\r
+.table > colgroup + thead > tr:first-child > td,\r
+.table > thead:first-child > tr:first-child > td {\r
+ border-top: 0;\r
+}\r
+.table > tbody + tbody {\r
+ border-top: 2px solid #dddddd;\r
+}\r
+.table .table {\r
+ background-color: #f2f2f2;\r
+}\r
+.table-condensed > thead > tr > th,\r
+.table-condensed > tbody > tr > th,\r
+.table-condensed > tfoot > tr > th,\r
+.table-condensed > thead > tr > td,\r
+.table-condensed > tbody > tr > td,\r
+.table-condensed > tfoot > tr > td {\r
+ padding: 5px;\r
+}\r
+.table-bordered {\r
+ border: 1px solid #dddddd;\r
+}\r
+.table-bordered > thead > tr > th,\r
+.table-bordered > tbody > tr > th,\r
+.table-bordered > tfoot > tr > th,\r
+.table-bordered > thead > tr > td,\r
+.table-bordered > tbody > tr > td,\r
+.table-bordered > tfoot > tr > td {\r
+ border: 1px solid #dddddd;\r
+}\r
+.table-bordered > thead > tr > th,\r
+.table-bordered > thead > tr > td {\r
+ border-bottom-width: 2px;\r
+}\r
+.table-striped > tbody > tr:nth-child(odd) > td,\r
+.table-striped > tbody > tr:nth-child(odd) > th {\r
+ background-color: #f9f9f9;\r
+}\r
+.table-hover > tbody > tr:hover > td,\r
+.table-hover > tbody > tr:hover > th {\r
+ background-color: #dbdbdb;\r
+}\r
+table col[class*="col-"] {\r
+ position: static;\r
+ float: none;\r
+ display: table-column;\r
+}\r
+table td[class*="col-"],\r
+table th[class*="col-"] {\r
+ position: static;\r
+ float: none;\r
+ display: table-cell;\r
+}\r
+.table > thead > tr > td.active,\r
+.table > tbody > tr > td.active,\r
+.table > tfoot > tr > td.active,\r
+.table > thead > tr > th.active,\r
+.table > tbody > tr > th.active,\r
+.table > tfoot > tr > th.active,\r
+.table > thead > tr.active > td,\r
+.table > tbody > tr.active > td,\r
+.table > tfoot > tr.active > td,\r
+.table > thead > tr.active > th,\r
+.table > tbody > tr.active > th,\r
+.table > tfoot > tr.active > th {\r
+ background-color: #dbdbdb;\r
+}\r
+.table-hover > tbody > tr > td.active:hover,\r
+.table-hover > tbody > tr > th.active:hover,\r
+.table-hover > tbody > tr.active:hover > td,\r
+.table-hover > tbody > tr.active:hover > th {\r
+ background-color: #cecece;\r
+}\r
+.table > thead > tr > td.success,\r
+.table > tbody > tr > td.success,\r
+.table > tfoot > tr > td.success,\r
+.table > thead > tr > th.success,\r
+.table > tbody > tr > th.success,\r
+.table > tfoot > tr > th.success,\r
+.table > thead > tr.success > td,\r
+.table > tbody > tr.success > td,\r
+.table > tfoot > tr.success > td,\r
+.table > thead > tr.success > th,\r
+.table > tbody > tr.success > th,\r
+.table > tfoot > tr.success > th {\r
+ background-color: #dff0d8;\r
+}\r
+.table-hover > tbody > tr > td.success:hover,\r
+.table-hover > tbody > tr > th.success:hover,\r
+.table-hover > tbody > tr.success:hover > td,\r
+.table-hover > tbody > tr.success:hover > th {\r
+ background-color: #d0e9c6;\r
+}\r
+.table > thead > tr > td.info,\r
+.table > tbody > tr > td.info,\r
+.table > tfoot > tr > td.info,\r
+.table > thead > tr > th.info,\r
+.table > tbody > tr > th.info,\r
+.table > tfoot > tr > th.info,\r
+.table > thead > tr.info > td,\r
+.table > tbody > tr.info > td,\r
+.table > tfoot > tr.info > td,\r
+.table > thead > tr.info > th,\r
+.table > tbody > tr.info > th,\r
+.table > tfoot > tr.info > th {\r
+ background-color: #d9edf7;\r
+}\r
+.table-hover > tbody > tr > td.info:hover,\r
+.table-hover > tbody > tr > th.info:hover,\r
+.table-hover > tbody > tr.info:hover > td,\r
+.table-hover > tbody > tr.info:hover > th {\r
+ background-color: #c4e3f3;\r
+}\r
+.table > thead > tr > td.warning,\r
+.table > tbody > tr > td.warning,\r
+.table > tfoot > tr > td.warning,\r
+.table > thead > tr > th.warning,\r
+.table > tbody > tr > th.warning,\r
+.table > tfoot > tr > th.warning,\r
+.table > thead > tr.warning > td,\r
+.table > tbody > tr.warning > td,\r
+.table > tfoot > tr.warning > td,\r
+.table > thead > tr.warning > th,\r
+.table > tbody > tr.warning > th,\r
+.table > tfoot > tr.warning > th {\r
+ background-color: #fcf8e3;\r
+}\r
+.table-hover > tbody > tr > td.warning:hover,\r
+.table-hover > tbody > tr > th.warning:hover,\r
+.table-hover > tbody > tr.warning:hover > td,\r
+.table-hover > tbody > tr.warning:hover > th {\r
+ background-color: #faf2cc;\r
+}\r
+.table > thead > tr > td.danger,\r
+.table > tbody > tr > td.danger,\r
+.table > tfoot > tr > td.danger,\r
+.table > thead > tr > th.danger,\r
+.table > tbody > tr > th.danger,\r
+.table > tfoot > tr > th.danger,\r
+.table > thead > tr.danger > td,\r
+.table > tbody > tr.danger > td,\r
+.table > tfoot > tr.danger > td,\r
+.table > thead > tr.danger > th,\r
+.table > tbody > tr.danger > th,\r
+.table > tfoot > tr.danger > th {\r
+ background-color: #f2dede;\r
+}\r
+.table-hover > tbody > tr > td.danger:hover,\r
+.table-hover > tbody > tr > th.danger:hover,\r
+.table-hover > tbody > tr.danger:hover > td,\r
+.table-hover > tbody > tr.danger:hover > th {\r
+ background-color: #ebcccc;\r
+}\r
+@media (max-width: 767px) {\r
+ .table-responsive {\r
+ width: 100%;\r
+ margin-bottom: 15px;\r
+ overflow-y: hidden;\r
+ overflow-x: scroll;\r
+ -ms-overflow-style: -ms-autohiding-scrollbar;\r
+ border: 1px solid #dddddd;\r
+ -webkit-overflow-scrolling: touch;\r
+ }\r
+ .table-responsive > .table {\r
+ margin-bottom: 0;\r
+ }\r
+ .table-responsive > .table > thead > tr > th,\r
+ .table-responsive > .table > tbody > tr > th,\r
+ .table-responsive > .table > tfoot > tr > th,\r
+ .table-responsive > .table > thead > tr > td,\r
+ .table-responsive > .table > tbody > tr > td,\r
+ .table-responsive > .table > tfoot > tr > td {\r
+ white-space: nowrap;\r
+ }\r
+ .table-responsive > .table-bordered {\r
+ border: 0;\r
+ }\r
+ .table-responsive > .table-bordered > thead > tr > th:first-child,\r
+ .table-responsive > .table-bordered > tbody > tr > th:first-child,\r
+ .table-responsive > .table-bordered > tfoot > tr > th:first-child,\r
+ .table-responsive > .table-bordered > thead > tr > td:first-child,\r
+ .table-responsive > .table-bordered > tbody > tr > td:first-child,\r
+ .table-responsive > .table-bordered > tfoot > tr > td:first-child {\r
+ border-left: 0;\r
+ }\r
+ .table-responsive > .table-bordered > thead > tr > th:last-child,\r
+ .table-responsive > .table-bordered > tbody > tr > th:last-child,\r
+ .table-responsive > .table-bordered > tfoot > tr > th:last-child,\r
+ .table-responsive > .table-bordered > thead > tr > td:last-child,\r
+ .table-responsive > .table-bordered > tbody > tr > td:last-child,\r
+ .table-responsive > .table-bordered > tfoot > tr > td:last-child {\r
+ border-right: 0;\r
+ }\r
+ .table-responsive > .table-bordered > tbody > tr:last-child > th,\r
+ .table-responsive > .table-bordered > tfoot > tr:last-child > th,\r
+ .table-responsive > .table-bordered > tbody > tr:last-child > td,\r
+ .table-responsive > .table-bordered > tfoot > tr:last-child > td {\r
+ border-bottom: 0;\r
+ }\r
+}\r
+fieldset {\r
+ padding: 0;\r
+ margin: 0;\r
+ border: 0;\r
+ min-width: 0;\r
+}\r
+legend {\r
+ display: block;\r
+ width: 100%;\r
+ padding: 0;\r
+ margin-bottom: 20px;\r
+ font-size: 21px;\r
+ line-height: inherit;\r
+ color: #333333;\r
+ border: 0;\r
+ border-bottom: 1px solid #e5e5e5;\r
+}\r
+label {\r
+ display: inline-block;\r
+ margin-bottom: 5px;\r
+ font-weight: bold;\r
+}\r
+input[type="search"] {\r
+ -webkit-box-sizing: border-box;\r
+ -moz-box-sizing: border-box;\r
+ box-sizing: border-box;\r
+}\r
+input[type="radio"],\r
+input[type="checkbox"] {\r
+ margin: 4px 0 0;\r
+ margin-top: 1px \9;\r
+ /* IE8-9 */\r
+\r
+ line-height: normal;\r
+}\r
+input[type="file"] {\r
+ display: block;\r
+}\r
+input[type="range"] {\r
+ display: block;\r
+ width: 100%;\r
+}\r
+select[multiple],\r
+select[size] {\r
+ height: auto;\r
+}\r
+input[type="file"]:focus,\r
+input[type="radio"]:focus,\r
+input[type="checkbox"]:focus {\r
+ outline: thin dotted;\r
+ outline: 5px auto -webkit-focus-ring-color;\r
+ outline-offset: -2px;\r
+}\r
+output {\r
+ display: block;\r
+ padding-top: 7px;\r
+ font-size: 14px;\r
+ line-height: 1.428571429;\r
+ color: #555555;\r
+}\r
+.form-control {\r
+ display: block;\r
+ width: 100%;\r
+ height: 34px;\r
+ padding: 6px 12px;\r
+ font-size: 14px;\r
+ line-height: 1.428571429;\r
+ color: #555555;\r
+ background-color: #ffffff;\r
+ background-image: none;\r
+ border: 1px solid #cccccc;\r
+ border-radius: 0px;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\r
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\r
+ -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\r
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\r
+}\r
+.form-control:focus {\r
+ border-color: #66afe9;\r
+ outline: 0;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\r
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\r
+}\r
+.form-control::-moz-placeholder {\r
+ color: #999999;\r
+ opacity: 1;\r
+}\r
+.form-control:-ms-input-placeholder {\r
+ color: #999999;\r
+}\r
+.form-control::-webkit-input-placeholder {\r
+ color: #999999;\r
+}\r
+.form-control[disabled],\r
+.form-control[readonly],\r
+fieldset[disabled] .form-control {\r
+ cursor: not-allowed;\r
+ background-color: #eeeeee;\r
+ opacity: 1;\r
+}\r
+textarea.form-control {\r
+ height: auto;\r
+}\r
+input[type="search"] {\r
+ -webkit-appearance: none;\r
+}\r
+input[type="date"] {\r
+ line-height: 34px;\r
+}\r
+.form-group {\r
+ margin-bottom: 15px;\r
+}\r
+.radio,\r
+.checkbox {\r
+ display: block;\r
+ min-height: 20px;\r
+ margin-top: 10px;\r
+ margin-bottom: 10px;\r
+ padding-left: 20px;\r
+}\r
+.radio label,\r
+.checkbox label {\r
+ display: inline;\r
+ font-weight: normal;\r
+ cursor: pointer;\r
+}\r
+.radio input[type="radio"],\r
+.radio-inline input[type="radio"],\r
+.checkbox input[type="checkbox"],\r
+.checkbox-inline input[type="checkbox"] {\r
+ float: left;\r
+ margin-left: -20px;\r
+}\r
+.radio + .radio,\r
+.checkbox + .checkbox {\r
+ margin-top: -5px;\r
+}\r
+.radio-inline,\r
+.checkbox-inline {\r
+ display: inline-block;\r
+ padding-left: 20px;\r
+ margin-bottom: 0;\r
+ vertical-align: middle;\r
+ font-weight: normal;\r
+ cursor: pointer;\r
+}\r
+.radio-inline + .radio-inline,\r
+.checkbox-inline + .checkbox-inline {\r
+ margin-top: 0;\r
+ margin-left: 10px;\r
+}\r
+input[type="radio"][disabled],\r
+input[type="checkbox"][disabled],\r
+.radio[disabled],\r
+.radio-inline[disabled],\r
+.checkbox[disabled],\r
+.checkbox-inline[disabled],\r
+fieldset[disabled] input[type="radio"],\r
+fieldset[disabled] input[type="checkbox"],\r
+fieldset[disabled] .radio,\r
+fieldset[disabled] .radio-inline,\r
+fieldset[disabled] .checkbox,\r
+fieldset[disabled] .checkbox-inline {\r
+ cursor: not-allowed;\r
+}\r
+.input-sm {\r
+ height: 30px;\r
+ padding: 5px 10px;\r
+ font-size: 12px;\r
+ line-height: 1.5;\r
+ border-radius: 0px;\r
+}\r
+select.input-sm {\r
+ height: 30px;\r
+ line-height: 30px;\r
+}\r
+textarea.input-sm,\r
+select[multiple].input-sm {\r
+ height: auto;\r
+}\r
+.input-lg {\r
+ height: 45px;\r
+ padding: 10px 16px;\r
+ font-size: 18px;\r
+ line-height: 1.33;\r
+ border-radius: 0px;\r
+}\r
+select.input-lg {\r
+ height: 45px;\r
+ line-height: 45px;\r
+}\r
+textarea.input-lg,\r
+select[multiple].input-lg {\r
+ height: auto;\r
+}\r
+.has-feedback {\r
+ position: relative;\r
+}\r
+.has-feedback .form-control {\r
+ padding-right: 42.5px;\r
+}\r
+.has-feedback .form-control-feedback {\r
+ position: absolute;\r
+ top: 25px;\r
+ right: 0;\r
+ display: block;\r
+ width: 34px;\r
+ height: 34px;\r
+ line-height: 34px;\r
+ text-align: center;\r
+}\r
+.has-success .help-block,\r
+.has-success .control-label,\r
+.has-success .radio,\r
+.has-success .checkbox,\r
+.has-success .radio-inline,\r
+.has-success .checkbox-inline {\r
+ color: #5cb85c;\r
+}\r
+.has-success .form-control {\r
+ border-color: #5cb85c;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\r
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\r
+}\r
+.has-success .form-control:focus {\r
+ border-color: #449d44;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;\r
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;\r
+}\r
+.has-success .input-group-addon {\r
+ color: #5cb85c;\r
+ border-color: #5cb85c;\r
+ background-color: #dff0d8;\r
+}\r
+.has-success .form-control-feedback {\r
+ color: #5cb85c;\r
+}\r
+.has-warning .help-block,\r
+.has-warning .control-label,\r
+.has-warning .radio,\r
+.has-warning .checkbox,\r
+.has-warning .radio-inline,\r
+.has-warning .checkbox-inline {\r
+ color: #f0ad4e;\r
+}\r
+.has-warning .form-control {\r
+ border-color: #f0ad4e;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\r
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\r
+}\r
+.has-warning .form-control:focus {\r
+ border-color: #ec971f;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;\r
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;\r
+}\r
+.has-warning .input-group-addon {\r
+ color: #f0ad4e;\r
+ border-color: #f0ad4e;\r
+ background-color: #fcf8e3;\r
+}\r
+.has-warning .form-control-feedback {\r
+ color: #f0ad4e;\r
+}\r
+.has-error .help-block,\r
+.has-error .control-label,\r
+.has-error .radio,\r
+.has-error .checkbox,\r
+.has-error .radio-inline,\r
+.has-error .checkbox-inline {\r
+ color: #d9534f;\r
+}\r
+.has-error .form-control {\r
+ border-color: #d9534f;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\r
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\r
+}\r
+.has-error .form-control:focus {\r
+ border-color: #c9302c;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;\r
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;\r
+}\r
+.has-error .input-group-addon {\r
+ color: #d9534f;\r
+ border-color: #d9534f;\r
+ background-color: #f2dede;\r
+}\r
+.has-error .form-control-feedback {\r
+ color: #d9534f;\r
+}\r
+.form-control-static {\r
+ margin-bottom: 0;\r
+}\r
+.help-block {\r
+ display: block;\r
+ margin-top: 5px;\r
+ margin-bottom: 10px;\r
+ color: #737373;\r
+}\r
+@media (min-width: 768px) {\r
+ .form-inline .form-group {\r
+ display: inline-block;\r
+ margin-bottom: 0;\r
+ vertical-align: middle;\r
+ }\r
+ .form-inline .form-control {\r
+ display: inline-block;\r
+ width: auto;\r
+ vertical-align: middle;\r
+ }\r
+ .form-inline .input-group > .form-control {\r
+ width: 100%;\r
+ }\r
+ .form-inline .control-label {\r
+ margin-bottom: 0;\r
+ vertical-align: middle;\r
+ }\r
+ .form-inline .radio,\r
+ .form-inline .checkbox {\r
+ display: inline-block;\r
+ margin-top: 0;\r
+ margin-bottom: 0;\r
+ padding-left: 0;\r
+ vertical-align: middle;\r
+ }\r
+ .form-inline .radio input[type="radio"],\r
+ .form-inline .checkbox input[type="checkbox"] {\r
+ float: none;\r
+ margin-left: 0;\r
+ }\r
+ .form-inline .has-feedback .form-control-feedback {\r
+ top: 0;\r
+ }\r
+}\r
+.form-horizontal .control-label,\r
+.form-horizontal .radio,\r
+.form-horizontal .checkbox,\r
+.form-horizontal .radio-inline,\r
+.form-horizontal .checkbox-inline {\r
+ margin-top: 0;\r
+ margin-bottom: 0;\r
+ padding-top: 7px;\r
+}\r
+.form-horizontal .radio,\r
+.form-horizontal .checkbox {\r
+ min-height: 27px;\r
+}\r
+.form-horizontal .form-group {\r
+ margin-left: -15px;\r
+ margin-right: -15px;\r
+}\r
+.form-horizontal .form-control-static {\r
+ padding-top: 7px;\r
+}\r
+@media (min-width: 768px) {\r
+ .form-horizontal .control-label {\r
+ text-align: right;\r
+ }\r
+}\r
+.form-horizontal .has-feedback .form-control-feedback {\r
+ top: 0;\r
+ right: 15px;\r
+}\r
+.btn {\r
+ display: inline-block;\r
+ margin-bottom: 0;\r
+ font-weight: normal;\r
+ text-align: center;\r
+ vertical-align: middle;\r
+ cursor: pointer;\r
+ background-image: none;\r
+ border: 1px solid transparent;\r
+ white-space: nowrap;\r
+ padding: 6px 12px;\r
+ font-size: 14px;\r
+ line-height: 1.428571429;\r
+ border-radius: 0px;\r
+ -webkit-user-select: none;\r
+ -moz-user-select: none;\r
+ -ms-user-select: none;\r
+ -o-user-select: none;\r
+ user-select: none;\r
+}\r
+.btn:focus {\r
+ outline: thin dotted;\r
+ outline: 5px auto -webkit-focus-ring-color;\r
+ outline-offset: -2px;\r
+}\r
+.btn:hover,\r
+.btn:focus {\r
+ color: #333333;\r
+ text-decoration: none;\r
+}\r
+.btn:active,\r
+.btn.active {\r
+ outline: 0;\r
+ background-image: none;\r
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\r
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\r
+}\r
+.btn.disabled,\r
+.btn[disabled],\r
+fieldset[disabled] .btn {\r
+ cursor: not-allowed;\r
+ pointer-events: none;\r
+ opacity: 0.65;\r
+ filter: alpha(opacity=65);\r
+ -webkit-box-shadow: none;\r
+ box-shadow: none;\r
+}\r
+.btn-default {\r
+ color: #333333;\r
+ background-color: #ffffff;\r
+ border-color: #cccccc;\r
+}\r
+.btn-default:hover,\r
+.btn-default:focus,\r
+.btn-default:active,\r
+.btn-default.active,\r
+.open .dropdown-toggle.btn-default {\r
+ color: #333333;\r
+ background-color: #ebebeb;\r
+ border-color: #adadad;\r
+}\r
+.btn-default:active,\r
+.btn-default.active,\r
+.open .dropdown-toggle.btn-default {\r
+ background-image: none;\r
+}\r
+.btn-default.disabled,\r
+.btn-default[disabled],\r
+fieldset[disabled] .btn-default,\r
+.btn-default.disabled:hover,\r
+.btn-default[disabled]:hover,\r
+fieldset[disabled] .btn-default:hover,\r
+.btn-default.disabled:focus,\r
+.btn-default[disabled]:focus,\r
+fieldset[disabled] .btn-default:focus,\r
+.btn-default.disabled:active,\r
+.btn-default[disabled]:active,\r
+fieldset[disabled] .btn-default:active,\r
+.btn-default.disabled.active,\r
+.btn-default[disabled].active,\r
+fieldset[disabled] .btn-default.active {\r
+ background-color: #ffffff;\r
+ border-color: #cccccc;\r
+}\r
+.btn-default .badge {\r
+ color: #ffffff;\r
+ background-color: #333333;\r
+}\r
+.btn-primary {\r
+ color: #ffffff;\r
+ background-color: #0d8921;\r
+ border-color: #0b721b;\r
+}\r
+.btn-primary:hover,\r
+.btn-primary:focus,\r
+.btn-primary:active,\r
+.btn-primary.active,\r
+.open .dropdown-toggle.btn-primary {\r
+ color: #ffffff;\r
+ background-color: #096418;\r
+ border-color: #053a0e;\r
+}\r
+.btn-primary:active,\r
+.btn-primary.active,\r
+.open .dropdown-toggle.btn-primary {\r
+ background-image: none;\r
+}\r
+.btn-primary.disabled,\r
+.btn-primary[disabled],\r
+fieldset[disabled] .btn-primary,\r
+.btn-primary.disabled:hover,\r
+.btn-primary[disabled]:hover,\r
+fieldset[disabled] .btn-primary:hover,\r
+.btn-primary.disabled:focus,\r
+.btn-primary[disabled]:focus,\r
+fieldset[disabled] .btn-primary:focus,\r
+.btn-primary.disabled:active,\r
+.btn-primary[disabled]:active,\r
+fieldset[disabled] .btn-primary:active,\r
+.btn-primary.disabled.active,\r
+.btn-primary[disabled].active,\r
+fieldset[disabled] .btn-primary.active {\r
+ background-color: #0d8921;\r
+ border-color: #0b721b;\r
+}\r
+.btn-primary .badge {\r
+ color: #0d8921;\r
+ background-color: #ffffff;\r
+}\r
+.btn-success {\r
+ color: #ffffff;\r
+ background-color: #5cb85c;\r
+ border-color: #4cae4c;\r
+}\r
+.btn-success:hover,\r
+.btn-success:focus,\r
+.btn-success:active,\r
+.btn-success.active,\r
+.open .dropdown-toggle.btn-success {\r
+ color: #ffffff;\r
+ background-color: #47a447;\r
+ border-color: #398439;\r
+}\r
+.btn-success:active,\r
+.btn-success.active,\r
+.open .dropdown-toggle.btn-success {\r
+ background-image: none;\r
+}\r
+.btn-success.disabled,\r
+.btn-success[disabled],\r
+fieldset[disabled] .btn-success,\r
+.btn-success.disabled:hover,\r
+.btn-success[disabled]:hover,\r
+fieldset[disabled] .btn-success:hover,\r
+.btn-success.disabled:focus,\r
+.btn-success[disabled]:focus,\r
+fieldset[disabled] .btn-success:focus,\r
+.btn-success.disabled:active,\r
+.btn-success[disabled]:active,\r
+fieldset[disabled] .btn-success:active,\r
+.btn-success.disabled.active,\r
+.btn-success[disabled].active,\r
+fieldset[disabled] .btn-success.active {\r
+ background-color: #5cb85c;\r
+ border-color: #4cae4c;\r
+}\r
+.btn-success .badge {\r
+ color: #5cb85c;\r
+ background-color: #ffffff;\r
+}\r
+.btn-info {\r
+ color: #ffffff;\r
+ background-color: #5bc0de;\r
+ border-color: #46b8da;\r
+}\r
+.btn-info:hover,\r
+.btn-info:focus,\r
+.btn-info:active,\r
+.btn-info.active,\r
+.open .dropdown-toggle.btn-info {\r
+ color: #ffffff;\r
+ background-color: #39b3d7;\r
+ border-color: #269abc;\r
+}\r
+.btn-info:active,\r
+.btn-info.active,\r
+.open .dropdown-toggle.btn-info {\r
+ background-image: none;\r
+}\r
+.btn-info.disabled,\r
+.btn-info[disabled],\r
+fieldset[disabled] .btn-info,\r
+.btn-info.disabled:hover,\r
+.btn-info[disabled]:hover,\r
+fieldset[disabled] .btn-info:hover,\r
+.btn-info.disabled:focus,\r
+.btn-info[disabled]:focus,\r
+fieldset[disabled] .btn-info:focus,\r
+.btn-info.disabled:active,\r
+.btn-info[disabled]:active,\r
+fieldset[disabled] .btn-info:active,\r
+.btn-info.disabled.active,\r
+.btn-info[disabled].active,\r
+fieldset[disabled] .btn-info.active {\r
+ background-color: #5bc0de;\r
+ border-color: #46b8da;\r
+}\r
+.btn-info .badge {\r
+ color: #5bc0de;\r
+ background-color: #ffffff;\r
+}\r
+.btn-warning {\r
+ color: #ffffff;\r
+ background-color: #f0ad4e;\r
+ border-color: #eea236;\r
+}\r
+.btn-warning:hover,\r
+.btn-warning:focus,\r
+.btn-warning:active,\r
+.btn-warning.active,\r
+.open .dropdown-toggle.btn-warning {\r
+ color: #ffffff;\r
+ background-color: #ed9c28;\r
+ border-color: #d58512;\r
+}\r
+.btn-warning:active,\r
+.btn-warning.active,\r
+.open .dropdown-toggle.btn-warning {\r
+ background-image: none;\r
+}\r
+.btn-warning.disabled,\r
+.btn-warning[disabled],\r
+fieldset[disabled] .btn-warning,\r
+.btn-warning.disabled:hover,\r
+.btn-warning[disabled]:hover,\r
+fieldset[disabled] .btn-warning:hover,\r
+.btn-warning.disabled:focus,\r
+.btn-warning[disabled]:focus,\r
+fieldset[disabled] .btn-warning:focus,\r
+.btn-warning.disabled:active,\r
+.btn-warning[disabled]:active,\r
+fieldset[disabled] .btn-warning:active,\r
+.btn-warning.disabled.active,\r
+.btn-warning[disabled].active,\r
+fieldset[disabled] .btn-warning.active {\r
+ background-color: #f0ad4e;\r
+ border-color: #eea236;\r
+}\r
+.btn-warning .badge {\r
+ color: #f0ad4e;\r
+ background-color: #ffffff;\r
+}\r
+.btn-danger {\r
+ color: #ffffff;\r
+ background-color: #d9534f;\r
+ border-color: #d43f3a;\r
+}\r
+.btn-danger:hover,\r
+.btn-danger:focus,\r
+.btn-danger:active,\r
+.btn-danger.active,\r
+.open .dropdown-toggle.btn-danger {\r
+ color: #ffffff;\r
+ background-color: #d2322d;\r
+ border-color: #ac2925;\r
+}\r
+.btn-danger:active,\r
+.btn-danger.active,\r
+.open .dropdown-toggle.btn-danger {\r
+ background-image: none;\r
+}\r
+.btn-danger.disabled,\r
+.btn-danger[disabled],\r
+fieldset[disabled] .btn-danger,\r
+.btn-danger.disabled:hover,\r
+.btn-danger[disabled]:hover,\r
+fieldset[disabled] .btn-danger:hover,\r
+.btn-danger.disabled:focus,\r
+.btn-danger[disabled]:focus,\r
+fieldset[disabled] .btn-danger:focus,\r
+.btn-danger.disabled:active,\r
+.btn-danger[disabled]:active,\r
+fieldset[disabled] .btn-danger:active,\r
+.btn-danger.disabled.active,\r
+.btn-danger[disabled].active,\r
+fieldset[disabled] .btn-danger.active {\r
+ background-color: #d9534f;\r
+ border-color: #d43f3a;\r
+}\r
+.btn-danger .badge {\r
+ color: #d9534f;\r
+ background-color: #ffffff;\r
+}\r
+.btn-link {\r
+ color: #0d8921;\r
+ font-weight: normal;\r
+ cursor: pointer;\r
+ border-radius: 0;\r
+}\r
+.btn-link,\r
+.btn-link:active,\r
+.btn-link[disabled],\r
+fieldset[disabled] .btn-link {\r
+ background-color: transparent;\r
+ -webkit-box-shadow: none;\r
+ box-shadow: none;\r
+}\r
+.btn-link,\r
+.btn-link:hover,\r
+.btn-link:focus,\r
+.btn-link:active {\r
+ border-color: transparent;\r
+}\r
+.btn-link:hover,\r
+.btn-link:focus {\r
+ color: #064310;\r
+ text-decoration: underline;\r
+ background-color: transparent;\r
+}\r
+.btn-link[disabled]:hover,\r
+fieldset[disabled] .btn-link:hover,\r
+.btn-link[disabled]:focus,\r
+fieldset[disabled] .btn-link:focus {\r
+ color: #999999;\r
+ text-decoration: none;\r
+}\r
+.btn-lg,\r
+.btn-group-lg > .btn {\r
+ padding: 10px 16px;\r
+ font-size: 18px;\r
+ line-height: 1.33;\r
+ border-radius: 0px;\r
+}\r
+.btn-sm,\r
+.btn-group-sm > .btn {\r
+ padding: 5px 10px;\r
+ font-size: 12px;\r
+ line-height: 1.5;\r
+ border-radius: 0px;\r
+}\r
+.btn-xs,\r
+.btn-group-xs > .btn {\r
+ padding: 1px 5px;\r
+ font-size: 12px;\r
+ line-height: 1.5;\r
+ border-radius: 0px;\r
+}\r
+.btn-block {\r
+ display: block;\r
+ width: 100%;\r
+ padding-left: 0;\r
+ padding-right: 0;\r
+}\r
+.btn-block + .btn-block {\r
+ margin-top: 5px;\r
+}\r
+input[type="submit"].btn-block,\r
+input[type="reset"].btn-block,\r
+input[type="button"].btn-block {\r
+ width: 100%;\r
+}\r
+.fade {\r
+ opacity: 0;\r
+ -webkit-transition: opacity 0.15s linear;\r
+ transition: opacity 0.15s linear;\r
+}\r
+.fade.in {\r
+ opacity: 1;\r
+}\r
+.collapse {\r
+ display: none;\r
+}\r
+.collapse.in {\r
+ display: block;\r
+}\r
+.collapsing {\r
+ position: relative;\r
+ height: 0;\r
+ overflow: hidden;\r
+ -webkit-transition: height 0.35s ease;\r
+ transition: height 0.35s ease;\r
+}\r
+@font-face {\r
+ font-family: 'Glyphicons Halflings';\r
+ src: url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.eot');\r
+ src: url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.woff') format('woff'), url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\r
+}\r
+.glyphicon {\r
+ position: relative;\r
+ top: 1px;\r
+ display: inline-block;\r
+ font-family: 'Glyphicons Halflings';\r
+ font-style: normal;\r
+ font-weight: normal;\r
+ line-height: 1;\r
+ -webkit-font-smoothing: antialiased;\r
+ -moz-osx-font-smoothing: grayscale;\r
+}\r
+.glyphicon-asterisk:before {\r
+ content: "\2a";\r
+}\r
+.glyphicon-plus:before {\r
+ content: "\2b";\r
+}\r
+.glyphicon-euro:before {\r
+ content: "\20ac";\r
+}\r
+.glyphicon-minus:before {\r
+ content: "\2212";\r
+}\r
+.glyphicon-cloud:before {\r
+ content: "\2601";\r
+}\r
+.glyphicon-envelope:before {\r
+ content: "\2709";\r
+}\r
+.glyphicon-pencil:before {\r
+ content: "\270f";\r
+}\r
+.glyphicon-glass:before {\r
+ content: "\e001";\r
+}\r
+.glyphicon-music:before {\r
+ content: "\e002";\r
+}\r
+.glyphicon-search:before {\r
+ content: "\e003";\r
+}\r
+.glyphicon-heart:before {\r
+ content: "\e005";\r
+}\r
+.glyphicon-star:before {\r
+ content: "\e006";\r
+}\r
+.glyphicon-star-empty:before {\r
+ content: "\e007";\r
+}\r
+.glyphicon-user:before {\r
+ content: "\e008";\r
+}\r
+.glyphicon-film:before {\r
+ content: "\e009";\r
+}\r
+.glyphicon-th-large:before {\r
+ content: "\e010";\r
+}\r
+.glyphicon-th:before {\r
+ content: "\e011";\r
+}\r
+.glyphicon-th-list:before {\r
+ content: "\e012";\r
+}\r
+.glyphicon-ok:before {\r
+ content: "\e013";\r
+}\r
+.glyphicon-remove:before {\r
+ content: "\e014";\r
+}\r
+.glyphicon-zoom-in:before {\r
+ content: "\e015";\r
+}\r
+.glyphicon-zoom-out:before {\r
+ content: "\e016";\r
+}\r
+.glyphicon-off:before {\r
+ content: "\e017";\r
+}\r
+.glyphicon-signal:before {\r
+ content: "\e018";\r
+}\r
+.glyphicon-cog:before {\r
+ content: "\e019";\r
+}\r
+.glyphicon-trash:before {\r
+ content: "\e020";\r
+}\r
+.glyphicon-home:before {\r
+ content: "\e021";\r
+}\r
+.glyphicon-file:before {\r
+ content: "\e022";\r
+}\r
+.glyphicon-time:before {\r
+ content: "\e023";\r
+}\r
+.glyphicon-road:before {\r
+ content: "\e024";\r
+}\r
+.glyphicon-download-alt:before {\r
+ content: "\e025";\r
+}\r
+.glyphicon-download:before {\r
+ content: "\e026";\r
+}\r
+.glyphicon-upload:before {\r
+ content: "\e027";\r
+}\r
+.glyphicon-inbox:before {\r
+ content: "\e028";\r
+}\r
+.glyphicon-play-circle:before {\r
+ content: "\e029";\r
+}\r
+.glyphicon-repeat:before {\r
+ content: "\e030";\r
+}\r
+.glyphicon-refresh:before {\r
+ content: "\e031";\r
+}\r
+.glyphicon-list-alt:before {\r
+ content: "\e032";\r
+}\r
+.glyphicon-lock:before {\r
+ content: "\e033";\r
+}\r
+.glyphicon-flag:before {\r
+ content: "\e034";\r
+}\r
+.glyphicon-headphones:before {\r
+ content: "\e035";\r
+}\r
+.glyphicon-volume-off:before {\r
+ content: "\e036";\r
+}\r
+.glyphicon-volume-down:before {\r
+ content: "\e037";\r
+}\r
+.glyphicon-volume-up:before {\r
+ content: "\e038";\r
+}\r
+.glyphicon-qrcode:before {\r
+ content: "\e039";\r
+}\r
+.glyphicon-barcode:before {\r
+ content: "\e040";\r
+}\r
+.glyphicon-tag:before {\r
+ content: "\e041";\r
+}\r
+.glyphicon-tags:before {\r
+ content: "\e042";\r
+}\r
+.glyphicon-book:before {\r
+ content: "\e043";\r
+}\r
+.glyphicon-bookmark:before {\r
+ content: "\e044";\r
+}\r
+.glyphicon-print:before {\r
+ content: "\e045";\r
+}\r
+.glyphicon-camera:before {\r
+ content: "\e046";\r
+}\r
+.glyphicon-font:before {\r
+ content: "\e047";\r
+}\r
+.glyphicon-bold:before {\r
+ content: "\e048";\r
+}\r
+.glyphicon-italic:before {\r
+ content: "\e049";\r
+}\r
+.glyphicon-text-height:before {\r
+ content: "\e050";\r
+}\r
+.glyphicon-text-width:before {\r
+ content: "\e051";\r
+}\r
+.glyphicon-align-left:before {\r
+ content: "\e052";\r
+}\r
+.glyphicon-align-center:before {\r
+ content: "\e053";\r
+}\r
+.glyphicon-align-right:before {\r
+ content: "\e054";\r
+}\r
+.glyphicon-align-justify:before {\r
+ content: "\e055";\r
+}\r
+.glyphicon-list:before {\r
+ content: "\e056";\r
+}\r
+.glyphicon-indent-left:before {\r
+ content: "\e057";\r
+}\r
+.glyphicon-indent-right:before {\r
+ content: "\e058";\r
+}\r
+.glyphicon-facetime-video:before {\r
+ content: "\e059";\r
+}\r
+.glyphicon-picture:before {\r
+ content: "\e060";\r
+}\r
+.glyphicon-map-marker:before {\r
+ content: "\e062";\r
+}\r
+.glyphicon-adjust:before {\r
+ content: "\e063";\r
+}\r
+.glyphicon-tint:before {\r
+ content: "\e064";\r
+}\r
+.glyphicon-edit:before {\r
+ content: "\e065";\r
+}\r
+.glyphicon-share:before {\r
+ content: "\e066";\r
+}\r
+.glyphicon-check:before {\r
+ content: "\e067";\r
+}\r
+.glyphicon-move:before {\r
+ content: "\e068";\r
+}\r
+.glyphicon-step-backward:before {\r
+ content: "\e069";\r
+}\r
+.glyphicon-fast-backward:before {\r
+ content: "\e070";\r
+}\r
+.glyphicon-backward:before {\r
+ content: "\e071";\r
+}\r
+.glyphicon-play:before {\r
+ content: "\e072";\r
+}\r
+.glyphicon-pause:before {\r
+ content: "\e073";\r
+}\r
+.glyphicon-stop:before {\r
+ content: "\e074";\r
+}\r
+.glyphicon-forward:before {\r
+ content: "\e075";\r
+}\r
+.glyphicon-fast-forward:before {\r
+ content: "\e076";\r
+}\r
+.glyphicon-step-forward:before {\r
+ content: "\e077";\r
+}\r
+.glyphicon-eject:before {\r
+ content: "\e078";\r
+}\r
+.glyphicon-chevron-left:before {\r
+ content: "\e079";\r
+}\r
+.glyphicon-chevron-right:before {\r
+ content: "\e080";\r
+}\r
+.glyphicon-plus-sign:before {\r
+ content: "\e081";\r
+}\r
+.glyphicon-minus-sign:before {\r
+ content: "\e082";\r
+}\r
+.glyphicon-remove-sign:before {\r
+ content: "\e083";\r
+}\r
+.glyphicon-ok-sign:before {\r
+ content: "\e084";\r
+}\r
+.glyphicon-question-sign:before {\r
+ content: "\e085";\r
+}\r
+.glyphicon-info-sign:before {\r
+ content: "\e086";\r
+}\r
+.glyphicon-screenshot:before {\r
+ content: "\e087";\r
+}\r
+.glyphicon-remove-circle:before {\r
+ content: "\e088";\r
+}\r
+.glyphicon-ok-circle:before {\r
+ content: "\e089";\r
+}\r
+.glyphicon-ban-circle:before {\r
+ content: "\e090";\r
+}\r
+.glyphicon-arrow-left:before {\r
+ content: "\e091";\r
+}\r
+.glyphicon-arrow-right:before {\r
+ content: "\e092";\r
+}\r
+.glyphicon-arrow-up:before {\r
+ content: "\e093";\r
+}\r
+.glyphicon-arrow-down:before {\r
+ content: "\e094";\r
+}\r
+.glyphicon-share-alt:before {\r
+ content: "\e095";\r
+}\r
+.glyphicon-resize-full:before {\r
+ content: "\e096";\r
+}\r
+.glyphicon-resize-small:before {\r
+ content: "\e097";\r
+}\r
+.glyphicon-exclamation-sign:before {\r
+ content: "\e101";\r
+}\r
+.glyphicon-gift:before {\r
+ content: "\e102";\r
+}\r
+.glyphicon-leaf:before {\r
+ content: "\e103";\r
+}\r
+.glyphicon-fire:before {\r
+ content: "\e104";\r
+}\r
+.glyphicon-eye-open:before {\r
+ content: "\e105";\r
+}\r
+.glyphicon-eye-close:before {\r
+ content: "\e106";\r
+}\r
+.glyphicon-warning-sign:before {\r
+ content: "\e107";\r
+}\r
+.glyphicon-plane:before {\r
+ content: "\e108";\r
+}\r
+.glyphicon-calendar:before {\r
+ content: "\e109";\r
+}\r
+.glyphicon-random:before {\r
+ content: "\e110";\r
+}\r
+.glyphicon-comment:before {\r
+ content: "\e111";\r
+}\r
+.glyphicon-magnet:before {\r
+ content: "\e112";\r
+}\r
+.glyphicon-chevron-up:before {\r
+ content: "\e113";\r
+}\r
+.glyphicon-chevron-down:before {\r
+ content: "\e114";\r
+}\r
+.glyphicon-retweet:before {\r
+ content: "\e115";\r
+}\r
+.glyphicon-shopping-cart:before {\r
+ content: "\e116";\r
+}\r
+.glyphicon-folder-close:before {\r
+ content: "\e117";\r
+}\r
+.glyphicon-folder-open:before {\r
+ content: "\e118";\r
+}\r
+.glyphicon-resize-vertical:before {\r
+ content: "\e119";\r
+}\r
+.glyphicon-resize-horizontal:before {\r
+ content: "\e120";\r
+}\r
+.glyphicon-hdd:before {\r
+ content: "\e121";\r
+}\r
+.glyphicon-bullhorn:before {\r
+ content: "\e122";\r
+}\r
+.glyphicon-bell:before {\r
+ content: "\e123";\r
+}\r
+.glyphicon-certificate:before {\r
+ content: "\e124";\r
+}\r
+.glyphicon-thumbs-up:before {\r
+ content: "\e125";\r
+}\r
+.glyphicon-thumbs-down:before {\r
+ content: "\e126";\r
+}\r
+.glyphicon-hand-right:before {\r
+ content: "\e127";\r
+}\r
+.glyphicon-hand-left:before {\r
+ content: "\e128";\r
+}\r
+.glyphicon-hand-up:before {\r
+ content: "\e129";\r
+}\r
+.glyphicon-hand-down:before {\r
+ content: "\e130";\r
+}\r
+.glyphicon-circle-arrow-right:before {\r
+ content: "\e131";\r
+}\r
+.glyphicon-circle-arrow-left:before {\r
+ content: "\e132";\r
+}\r
+.glyphicon-circle-arrow-up:before {\r
+ content: "\e133";\r
+}\r
+.glyphicon-circle-arrow-down:before {\r
+ content: "\e134";\r
+}\r
+.glyphicon-globe:before {\r
+ content: "\e135";\r
+}\r
+.glyphicon-wrench:before {\r
+ content: "\e136";\r
+}\r
+.glyphicon-tasks:before {\r
+ content: "\e137";\r
+}\r
+.glyphicon-filter:before {\r
+ content: "\e138";\r
+}\r
+.glyphicon-briefcase:before {\r
+ content: "\e139";\r
+}\r
+.glyphicon-fullscreen:before {\r
+ content: "\e140";\r
+}\r
+.glyphicon-dashboard:before {\r
+ content: "\e141";\r
+}\r
+.glyphicon-paperclip:before {\r
+ content: "\e142";\r
+}\r
+.glyphicon-heart-empty:before {\r
+ content: "\e143";\r
+}\r
+.glyphicon-link:before {\r
+ content: "\e144";\r
+}\r
+.glyphicon-phone:before {\r
+ content: "\e145";\r
+}\r
+.glyphicon-pushpin:before {\r
+ content: "\e146";\r
+}\r
+.glyphicon-usd:before {\r
+ content: "\e148";\r
+}\r
+.glyphicon-gbp:before {\r
+ content: "\e149";\r
+}\r
+.glyphicon-sort:before {\r
+ content: "\e150";\r
+}\r
+.glyphicon-sort-by-alphabet:before {\r
+ content: "\e151";\r
+}\r
+.glyphicon-sort-by-alphabet-alt:before {\r
+ content: "\e152";\r
+}\r
+.glyphicon-sort-by-order:before {\r
+ content: "\e153";\r
+}\r
+.glyphicon-sort-by-order-alt:before {\r
+ content: "\e154";\r
+}\r
+.glyphicon-sort-by-attributes:before {\r
+ content: "\e155";\r
+}\r
+.glyphicon-sort-by-attributes-alt:before {\r
+ content: "\e156";\r
+}\r
+.glyphicon-unchecked:before {\r
+ content: "\e157";\r
+}\r
+.glyphicon-expand:before {\r
+ content: "\e158";\r
+}\r
+.glyphicon-collapse-down:before {\r
+ content: "\e159";\r
+}\r
+.glyphicon-collapse-up:before {\r
+ content: "\e160";\r
+}\r
+.glyphicon-log-in:before {\r
+ content: "\e161";\r
+}\r
+.glyphicon-flash:before {\r
+ content: "\e162";\r
+}\r
+.glyphicon-log-out:before {\r
+ content: "\e163";\r
+}\r
+.glyphicon-new-window:before {\r
+ content: "\e164";\r
+}\r
+.glyphicon-record:before {\r
+ content: "\e165";\r
+}\r
+.glyphicon-save:before {\r
+ content: "\e166";\r
+}\r
+.glyphicon-open:before {\r
+ content: "\e167";\r
+}\r
+.glyphicon-saved:before {\r
+ content: "\e168";\r
+}\r
+.glyphicon-import:before {\r
+ content: "\e169";\r
+}\r
+.glyphicon-export:before {\r
+ content: "\e170";\r
+}\r
+.glyphicon-send:before {\r
+ content: "\e171";\r
+}\r
+.glyphicon-floppy-disk:before {\r
+ content: "\e172";\r
+}\r
+.glyphicon-floppy-saved:before {\r
+ content: "\e173";\r
+}\r
+.glyphicon-floppy-remove:before {\r
+ content: "\e174";\r
+}\r
+.glyphicon-floppy-save:before {\r
+ content: "\e175";\r
+}\r
+.glyphicon-floppy-open:before {\r
+ content: "\e176";\r
+}\r
+.glyphicon-credit-card:before {\r
+ content: "\e177";\r
+}\r
+.glyphicon-transfer:before {\r
+ content: "\e178";\r
+}\r
+.glyphicon-cutlery:before {\r
+ content: "\e179";\r
+}\r
+.glyphicon-header:before {\r
+ content: "\e180";\r
+}\r
+.glyphicon-compressed:before {\r
+ content: "\e181";\r
+}\r
+.glyphicon-earphone:before {\r
+ content: "\e182";\r
+}\r
+.glyphicon-phone-alt:before {\r
+ content: "\e183";\r
+}\r
+.glyphicon-tower:before {\r
+ content: "\e184";\r
+}\r
+.glyphicon-stats:before {\r
+ content: "\e185";\r
+}\r
+.glyphicon-sd-video:before {\r
+ content: "\e186";\r
+}\r
+.glyphicon-hd-video:before {\r
+ content: "\e187";\r
+}\r
+.glyphicon-subtitles:before {\r
+ content: "\e188";\r
+}\r
+.glyphicon-sound-stereo:before {\r
+ content: "\e189";\r
+}\r
+.glyphicon-sound-dolby:before {\r
+ content: "\e190";\r
+}\r
+.glyphicon-sound-5-1:before {\r
+ content: "\e191";\r
+}\r
+.glyphicon-sound-6-1:before {\r
+ content: "\e192";\r
+}\r
+.glyphicon-sound-7-1:before {\r
+ content: "\e193";\r
+}\r
+.glyphicon-copyright-mark:before {\r
+ content: "\e194";\r
+}\r
+.glyphicon-registration-mark:before {\r
+ content: "\e195";\r
+}\r
+.glyphicon-cloud-download:before {\r
+ content: "\e197";\r
+}\r
+.glyphicon-cloud-upload:before {\r
+ content: "\e198";\r
+}\r
+.glyphicon-tree-conifer:before {\r
+ content: "\e199";\r
+}\r
+.glyphicon-tree-deciduous:before {\r
+ content: "\e200";\r
+}\r
+.caret {\r
+ display: inline-block;\r
+ width: 0;\r
+ height: 0;\r
+ margin-left: 2px;\r
+ vertical-align: middle;\r
+ border-top: 4px solid;\r
+ border-right: 4px solid transparent;\r
+ border-left: 4px solid transparent;\r
+}\r
+.dropdown {\r
+ position: relative;\r
+}\r
+.dropdown-toggle:focus {\r
+ outline: 0;\r
+}\r
+.dropdown-menu {\r
+ position: absolute;\r
+ top: 100%;\r
+ left: 0;\r
+ z-index: 1000;\r
+ display: none;\r
+ float: left;\r
+ min-width: 160px;\r
+ padding: 5px 0;\r
+ margin: 2px 0 0;\r
+ list-style: none;\r
+ font-size: 14px;\r
+ background-color: #ffffff;\r
+ border: 1px solid #cccccc;\r
+ border: 1px solid rgba(0, 0, 0, 0.15);\r
+ border-radius: 0px;\r
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\r
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\r
+ background-clip: padding-box;\r
+}\r
+.dropdown-menu.pull-right {\r
+ right: 0;\r
+ left: auto;\r
+}\r
+.dropdown-menu .divider {\r
+ height: 1px;\r
+ margin: 9px 0;\r
+ overflow: hidden;\r
+ background-color: #e5e5e5;\r
+}\r
+.dropdown-menu > li > a {\r
+ display: block;\r
+ padding: 3px 20px;\r
+ clear: both;\r
+ font-weight: normal;\r
+ line-height: 1.428571429;\r
+ color: #333333;\r
+ white-space: nowrap;\r
+}\r
+.dropdown-menu > li > a:hover,\r
+.dropdown-menu > li > a:focus {\r
+ text-decoration: none;\r
+ color: #ffffff;\r
+ background-color: #0d8921;\r
+}\r
+.dropdown-menu > .active > a,\r
+.dropdown-menu > .active > a:hover,\r
+.dropdown-menu > .active > a:focus {\r
+ color: #ffffff;\r
+ text-decoration: none;\r
+ outline: 0;\r
+ background-color: #0d8921;\r
+}\r
+.dropdown-menu > .disabled > a,\r
+.dropdown-menu > .disabled > a:hover,\r
+.dropdown-menu > .disabled > a:focus {\r
+ color: #999999;\r
+}\r
+.dropdown-menu > .disabled > a:hover,\r
+.dropdown-menu > .disabled > a:focus {\r
+ text-decoration: none;\r
+ background-color: transparent;\r
+ background-image: none;\r
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\r
+ cursor: not-allowed;\r
+}\r
+.open > .dropdown-menu {\r
+ display: block;\r
+}\r
+.open > a {\r
+ outline: 0;\r
+}\r
+.dropdown-menu-right {\r
+ left: auto;\r
+ right: 0;\r
+}\r
+.dropdown-menu-left {\r
+ left: 0;\r
+ right: auto;\r
+}\r
+.dropdown-header {\r
+ display: block;\r
+ padding: 3px 20px;\r
+ font-size: 12px;\r
+ line-height: 1.428571429;\r
+ color: #999999;\r
+}\r
+.dropdown-backdrop {\r
+ position: fixed;\r
+ left: 0;\r
+ right: 0;\r
+ bottom: 0;\r
+ top: 0;\r
+ z-index: 990;\r
+}\r
+.pull-right > .dropdown-menu {\r
+ right: 0;\r
+ left: auto;\r
+}\r
+.dropup .caret,\r
+.navbar-fixed-bottom .dropdown .caret {\r
+ border-top: 0;\r
+ border-bottom: 4px solid;\r
+ content: "";\r
+}\r
+.dropup .dropdown-menu,\r
+.navbar-fixed-bottom .dropdown .dropdown-menu {\r
+ top: auto;\r
+ bottom: 100%;\r
+ margin-bottom: 1px;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-right .dropdown-menu {\r
+ left: auto;\r
+ right: 0;\r
+ }\r
+ .navbar-right .dropdown-menu-left {\r
+ left: 0;\r
+ right: auto;\r
+ }\r
+}\r
+.btn-group,\r
+.btn-group-vertical {\r
+ position: relative;\r
+ display: inline-block;\r
+ vertical-align: middle;\r
+}\r
+.btn-group > .btn,\r
+.btn-group-vertical > .btn {\r
+ position: relative;\r
+ float: left;\r
+}\r
+.btn-group > .btn:hover,\r
+.btn-group-vertical > .btn:hover,\r
+.btn-group > .btn:focus,\r
+.btn-group-vertical > .btn:focus,\r
+.btn-group > .btn:active,\r
+.btn-group-vertical > .btn:active,\r
+.btn-group > .btn.active,\r
+.btn-group-vertical > .btn.active {\r
+ z-index: 2;\r
+}\r
+.btn-group > .btn:focus,\r
+.btn-group-vertical > .btn:focus {\r
+ outline: none;\r
+}\r
+.btn-group .btn + .btn,\r
+.btn-group .btn + .btn-group,\r
+.btn-group .btn-group + .btn,\r
+.btn-group .btn-group + .btn-group {\r
+ margin-left: -1px;\r
+}\r
+.btn-toolbar {\r
+ margin-left: -5px;\r
+}\r
+.btn-toolbar .btn-group,\r
+.btn-toolbar .input-group {\r
+ float: left;\r
+}\r
+.btn-toolbar > .btn,\r
+.btn-toolbar > .btn-group,\r
+.btn-toolbar > .input-group {\r
+ margin-left: 5px;\r
+}\r
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\r
+ border-radius: 0;\r
+}\r
+.btn-group > .btn:first-child {\r
+ margin-left: 0;\r
+}\r
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\r
+ border-bottom-right-radius: 0;\r
+ border-top-right-radius: 0;\r
+}\r
+.btn-group > .btn:last-child:not(:first-child),\r
+.btn-group > .dropdown-toggle:not(:first-child) {\r
+ border-bottom-left-radius: 0;\r
+ border-top-left-radius: 0;\r
+}\r
+.btn-group > .btn-group {\r
+ float: left;\r
+}\r
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\r
+ border-radius: 0;\r
+}\r
+.btn-group > .btn-group:first-child > .btn:last-child,\r
+.btn-group > .btn-group:first-child > .dropdown-toggle {\r
+ border-bottom-right-radius: 0;\r
+ border-top-right-radius: 0;\r
+}\r
+.btn-group > .btn-group:last-child > .btn:first-child {\r
+ border-bottom-left-radius: 0;\r
+ border-top-left-radius: 0;\r
+}\r
+.btn-group .dropdown-toggle:active,\r
+.btn-group.open .dropdown-toggle {\r
+ outline: 0;\r
+}\r
+.btn-group > .btn + .dropdown-toggle {\r
+ padding-left: 8px;\r
+ padding-right: 8px;\r
+}\r
+.btn-group > .btn-lg + .dropdown-toggle {\r
+ padding-left: 12px;\r
+ padding-right: 12px;\r
+}\r
+.btn-group.open .dropdown-toggle {\r
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\r
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\r
+}\r
+.btn-group.open .dropdown-toggle.btn-link {\r
+ -webkit-box-shadow: none;\r
+ box-shadow: none;\r
+}\r
+.btn .caret {\r
+ margin-left: 0;\r
+}\r
+.btn-lg .caret {\r
+ border-width: 5px 5px 0;\r
+ border-bottom-width: 0;\r
+}\r
+.dropup .btn-lg .caret {\r
+ border-width: 0 5px 5px;\r
+}\r
+.btn-group-vertical > .btn,\r
+.btn-group-vertical > .btn-group,\r
+.btn-group-vertical > .btn-group > .btn {\r
+ display: block;\r
+ float: none;\r
+ width: 100%;\r
+ max-width: 100%;\r
+}\r
+.btn-group-vertical > .btn-group > .btn {\r
+ float: none;\r
+}\r
+.btn-group-vertical > .btn + .btn,\r
+.btn-group-vertical > .btn + .btn-group,\r
+.btn-group-vertical > .btn-group + .btn,\r
+.btn-group-vertical > .btn-group + .btn-group {\r
+ margin-top: -1px;\r
+ margin-left: 0;\r
+}\r
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\r
+ border-radius: 0;\r
+}\r
+.btn-group-vertical > .btn:first-child:not(:last-child) {\r
+ border-top-right-radius: 0px;\r
+ border-bottom-right-radius: 0;\r
+ border-bottom-left-radius: 0;\r
+}\r
+.btn-group-vertical > .btn:last-child:not(:first-child) {\r
+ border-bottom-left-radius: 0px;\r
+ border-top-right-radius: 0;\r
+ border-top-left-radius: 0;\r
+}\r
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\r
+ border-radius: 0;\r
+}\r
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\r
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\r
+ border-bottom-right-radius: 0;\r
+ border-bottom-left-radius: 0;\r
+}\r
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\r
+ border-top-right-radius: 0;\r
+ border-top-left-radius: 0;\r
+}\r
+.btn-group-justified {\r
+ display: table;\r
+ width: 100%;\r
+ table-layout: fixed;\r
+ border-collapse: separate;\r
+}\r
+.btn-group-justified > .btn,\r
+.btn-group-justified > .btn-group {\r
+ float: none;\r
+ display: table-cell;\r
+ width: 1%;\r
+}\r
+.btn-group-justified > .btn-group .btn {\r
+ width: 100%;\r
+}\r
+[data-toggle="buttons"] > .btn > input[type="radio"],\r
+[data-toggle="buttons"] > .btn > input[type="checkbox"] {\r
+ display: none;\r
+}\r
+.input-group {\r
+ position: relative;\r
+ display: table;\r
+ border-collapse: separate;\r
+}\r
+.input-group[class*="col-"] {\r
+ float: none;\r
+ padding-left: 0;\r
+ padding-right: 0;\r
+}\r
+.input-group .form-control {\r
+ float: left;\r
+ width: 100%;\r
+ margin-bottom: 0;\r
+}\r
+.input-group-lg > .form-control,\r
+.input-group-lg > .input-group-addon,\r
+.input-group-lg > .input-group-btn > .btn {\r
+ height: 45px;\r
+ padding: 10px 16px;\r
+ font-size: 18px;\r
+ line-height: 1.33;\r
+ border-radius: 0px;\r
+}\r
+select.input-group-lg > .form-control,\r
+select.input-group-lg > .input-group-addon,\r
+select.input-group-lg > .input-group-btn > .btn {\r
+ height: 45px;\r
+ line-height: 45px;\r
+}\r
+textarea.input-group-lg > .form-control,\r
+textarea.input-group-lg > .input-group-addon,\r
+textarea.input-group-lg > .input-group-btn > .btn,\r
+select[multiple].input-group-lg > .form-control,\r
+select[multiple].input-group-lg > .input-group-addon,\r
+select[multiple].input-group-lg > .input-group-btn > .btn {\r
+ height: auto;\r
+}\r
+.input-group-sm > .form-control,\r
+.input-group-sm > .input-group-addon,\r
+.input-group-sm > .input-group-btn > .btn {\r
+ height: 30px;\r
+ padding: 5px 10px;\r
+ font-size: 12px;\r
+ line-height: 1.5;\r
+ border-radius: 0px;\r
+}\r
+select.input-group-sm > .form-control,\r
+select.input-group-sm > .input-group-addon,\r
+select.input-group-sm > .input-group-btn > .btn {\r
+ height: 30px;\r
+ line-height: 30px;\r
+}\r
+textarea.input-group-sm > .form-control,\r
+textarea.input-group-sm > .input-group-addon,\r
+textarea.input-group-sm > .input-group-btn > .btn,\r
+select[multiple].input-group-sm > .form-control,\r
+select[multiple].input-group-sm > .input-group-addon,\r
+select[multiple].input-group-sm > .input-group-btn > .btn {\r
+ height: auto;\r
+}\r
+.input-group-addon,\r
+.input-group-btn,\r
+.input-group .form-control {\r
+ display: table-cell;\r
+}\r
+.input-group-addon:not(:first-child):not(:last-child),\r
+.input-group-btn:not(:first-child):not(:last-child),\r
+.input-group .form-control:not(:first-child):not(:last-child) {\r
+ border-radius: 0;\r
+}\r
+.input-group-addon,\r
+.input-group-btn {\r
+ width: 1%;\r
+ white-space: nowrap;\r
+ vertical-align: middle;\r
+}\r
+.input-group-addon {\r
+ padding: 6px 12px;\r
+ font-size: 14px;\r
+ font-weight: normal;\r
+ line-height: 1;\r
+ color: #555555;\r
+ text-align: center;\r
+ background-color: #eeeeee;\r
+ border: 1px solid #cccccc;\r
+ border-radius: 0px;\r
+}\r
+.input-group-addon.input-sm {\r
+ padding: 5px 10px;\r
+ font-size: 12px;\r
+ border-radius: 0px;\r
+}\r
+.input-group-addon.input-lg {\r
+ padding: 10px 16px;\r
+ font-size: 18px;\r
+ border-radius: 0px;\r
+}\r
+.input-group-addon input[type="radio"],\r
+.input-group-addon input[type="checkbox"] {\r
+ margin-top: 0;\r
+}\r
+.input-group .form-control:first-child,\r
+.input-group-addon:first-child,\r
+.input-group-btn:first-child > .btn,\r
+.input-group-btn:first-child > .btn-group > .btn,\r
+.input-group-btn:first-child > .dropdown-toggle,\r
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\r
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\r
+ border-bottom-right-radius: 0;\r
+ border-top-right-radius: 0;\r
+}\r
+.input-group-addon:first-child {\r
+ border-right: 0;\r
+}\r
+.input-group .form-control:last-child,\r
+.input-group-addon:last-child,\r
+.input-group-btn:last-child > .btn,\r
+.input-group-btn:last-child > .btn-group > .btn,\r
+.input-group-btn:last-child > .dropdown-toggle,\r
+.input-group-btn:first-child > .btn:not(:first-child),\r
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\r
+ border-bottom-left-radius: 0;\r
+ border-top-left-radius: 0;\r
+}\r
+.input-group-addon:last-child {\r
+ border-left: 0;\r
+}\r
+.input-group-btn {\r
+ position: relative;\r
+ font-size: 0;\r
+ white-space: nowrap;\r
+}\r
+.input-group-btn > .btn {\r
+ position: relative;\r
+}\r
+.input-group-btn > .btn + .btn {\r
+ margin-left: -1px;\r
+}\r
+.input-group-btn > .btn:hover,\r
+.input-group-btn > .btn:focus,\r
+.input-group-btn > .btn:active {\r
+ z-index: 2;\r
+}\r
+.input-group-btn:first-child > .btn,\r
+.input-group-btn:first-child > .btn-group {\r
+ margin-right: -1px;\r
+}\r
+.input-group-btn:last-child > .btn,\r
+.input-group-btn:last-child > .btn-group {\r
+ margin-left: -1px;\r
+}\r
+.nav {\r
+ margin-bottom: 0;\r
+ padding-left: 0;\r
+ list-style: none;\r
+}\r
+.nav > li {\r
+ position: relative;\r
+ display: block;\r
+}\r
+.nav > li > a {\r
+ position: relative;\r
+ display: block;\r
+ padding: 10px 15px;\r
+}\r
+.nav > li > a:hover,\r
+.nav > li > a:focus {\r
+ text-decoration: none;\r
+ background-color: #dddddd;\r
+}\r
+.nav > li.disabled > a {\r
+ color: #999999;\r
+}\r
+.nav > li.disabled > a:hover,\r
+.nav > li.disabled > a:focus {\r
+ color: #999999;\r
+ text-decoration: none;\r
+ background-color: transparent;\r
+ cursor: not-allowed;\r
+}\r
+.nav .open > a,\r
+.nav .open > a:hover,\r
+.nav .open > a:focus {\r
+ background-color: #dddddd;\r
+ border-color: #0d8921;\r
+}\r
+.nav .nav-divider {\r
+ height: 1px;\r
+ margin: 9px 0;\r
+ overflow: hidden;\r
+ background-color: #e5e5e5;\r
+}\r
+.nav > li > a > img {\r
+ max-width: none;\r
+}\r
+.nav-tabs {\r
+ border-bottom: 1px solid #dddddd;\r
+}\r
+.nav-tabs > li {\r
+ float: left;\r
+ margin-bottom: -1px;\r
+}\r
+.nav-tabs > li > a {\r
+ margin-right: 2px;\r
+ line-height: 1.428571429;\r
+ border: 1px solid transparent;\r
+ border-radius: 0px 0px 0 0;\r
+}\r
+.nav-tabs > li > a:hover {\r
+ border-color: #eeeeee #eeeeee #dddddd;\r
+}\r
+.nav-tabs > li.active > a,\r
+.nav-tabs > li.active > a:hover,\r
+.nav-tabs > li.active > a:focus {\r
+ color: #555555;\r
+ background-color: #f2f2f2;\r
+ border: 1px solid #dddddd;\r
+ border-bottom-color: transparent;\r
+ cursor: default;\r
+}\r
+.nav-tabs.nav-justified {\r
+ width: 100%;\r
+ border-bottom: 0;\r
+}\r
+.nav-tabs.nav-justified > li {\r
+ float: none;\r
+}\r
+.nav-tabs.nav-justified > li > a {\r
+ text-align: center;\r
+ margin-bottom: 5px;\r
+}\r
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {\r
+ top: auto;\r
+ left: auto;\r
+}\r
+@media (min-width: 768px) {\r
+ .nav-tabs.nav-justified > li {\r
+ display: table-cell;\r
+ width: 1%;\r
+ }\r
+ .nav-tabs.nav-justified > li > a {\r
+ margin-bottom: 0;\r
+ }\r
+}\r
+.nav-tabs.nav-justified > li > a {\r
+ margin-right: 0;\r
+ border-radius: 0px;\r
+}\r
+.nav-tabs.nav-justified > .active > a,\r
+.nav-tabs.nav-justified > .active > a:hover,\r
+.nav-tabs.nav-justified > .active > a:focus {\r
+ border: 1px solid #dddddd;\r
+}\r
+@media (min-width: 768px) {\r
+ .nav-tabs.nav-justified > li > a {\r
+ border-bottom: 1px solid #dddddd;\r
+ border-radius: 0px 0px 0 0;\r
+ }\r
+ .nav-tabs.nav-justified > .active > a,\r
+ .nav-tabs.nav-justified > .active > a:hover,\r
+ .nav-tabs.nav-justified > .active > a:focus {\r
+ border-bottom-color: #f2f2f2;\r
+ }\r
+}\r
+.nav-pills > li {\r
+ float: left;\r
+}\r
+.nav-pills > li > a {\r
+ border-radius: 0px;\r
+}\r
+.nav-pills > li + li {\r
+ margin-left: 2px;\r
+}\r
+.nav-pills > li.active > a,\r
+.nav-pills > li.active > a:hover,\r
+.nav-pills > li.active > a:focus {\r
+ color: #ffffff;\r
+ background-color: #0d8921;\r
+}\r
+.nav-stacked > li {\r
+ float: none;\r
+}\r
+.nav-stacked > li + li {\r
+ margin-top: 2px;\r
+ margin-left: 0;\r
+}\r
+.nav-justified {\r
+ width: 100%;\r
+}\r
+.nav-justified > li {\r
+ float: none;\r
+}\r
+.nav-justified > li > a {\r
+ text-align: center;\r
+ margin-bottom: 5px;\r
+}\r
+.nav-justified > .dropdown .dropdown-menu {\r
+ top: auto;\r
+ left: auto;\r
+}\r
+@media (min-width: 768px) {\r
+ .nav-justified > li {\r
+ display: table-cell;\r
+ width: 1%;\r
+ }\r
+ .nav-justified > li > a {\r
+ margin-bottom: 0;\r
+ }\r
+}\r
+.nav-tabs-justified {\r
+ border-bottom: 0;\r
+}\r
+.nav-tabs-justified > li > a {\r
+ margin-right: 0;\r
+ border-radius: 0px;\r
+}\r
+.nav-tabs-justified > .active > a,\r
+.nav-tabs-justified > .active > a:hover,\r
+.nav-tabs-justified > .active > a:focus {\r
+ border: 1px solid #dddddd;\r
+}\r
+@media (min-width: 768px) {\r
+ .nav-tabs-justified > li > a {\r
+ border-bottom: 1px solid #dddddd;\r
+ border-radius: 0px 0px 0 0;\r
+ }\r
+ .nav-tabs-justified > .active > a,\r
+ .nav-tabs-justified > .active > a:hover,\r
+ .nav-tabs-justified > .active > a:focus {\r
+ border-bottom-color: #f2f2f2;\r
+ }\r
+}\r
+.tab-content > .tab-pane {\r
+ display: none;\r
+}\r
+.tab-content > .active {\r
+ display: block;\r
+}\r
+.nav-tabs .dropdown-menu {\r
+ margin-top: -1px;\r
+ border-top-right-radius: 0;\r
+ border-top-left-radius: 0;\r
+}\r
+.navbar {\r
+ position: relative;\r
+ min-height: 50px;\r
+ margin-bottom: 20px;\r
+ border: 1px solid transparent;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar {\r
+ border-radius: 0px;\r
+ }\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-header {\r
+ float: left;\r
+ }\r
+}\r
+.navbar-collapse {\r
+ max-height: 340px;\r
+ overflow-x: visible;\r
+ padding-right: 15px;\r
+ padding-left: 15px;\r
+ border-top: 1px solid transparent;\r
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\r
+ -webkit-overflow-scrolling: touch;\r
+}\r
+.navbar-collapse.in {\r
+ overflow-y: auto;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-collapse {\r
+ width: auto;\r
+ border-top: 0;\r
+ box-shadow: none;\r
+ }\r
+ .navbar-collapse.collapse {\r
+ display: block !important;\r
+ height: auto !important;\r
+ padding-bottom: 0;\r
+ overflow: visible !important;\r
+ }\r
+ .navbar-collapse.in {\r
+ overflow-y: visible;\r
+ }\r
+ .navbar-fixed-top .navbar-collapse,\r
+ .navbar-static-top .navbar-collapse,\r
+ .navbar-fixed-bottom .navbar-collapse {\r
+ padding-left: 0;\r
+ padding-right: 0;\r
+ }\r
+}\r
+.container > .navbar-header,\r
+.container-fluid > .navbar-header,\r
+.container > .navbar-collapse,\r
+.container-fluid > .navbar-collapse {\r
+ margin-right: -15px;\r
+ margin-left: -15px;\r
+}\r
+@media (min-width: 768px) {\r
+ .container > .navbar-header,\r
+ .container-fluid > .navbar-header,\r
+ .container > .navbar-collapse,\r
+ .container-fluid > .navbar-collapse {\r
+ margin-right: 0;\r
+ margin-left: 0;\r
+ }\r
+}\r
+.navbar-static-top {\r
+ z-index: 1000;\r
+ border-width: 0 0 1px;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-static-top {\r
+ border-radius: 0;\r
+ }\r
+}\r
+.navbar-fixed-top,\r
+.navbar-fixed-bottom {\r
+ position: fixed;\r
+ right: 0;\r
+ left: 0;\r
+ z-index: 1030;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-fixed-top,\r
+ .navbar-fixed-bottom {\r
+ border-radius: 0;\r
+ }\r
+}\r
+.navbar-fixed-top {\r
+ top: 0;\r
+ border-width: 0 0 1px;\r
+}\r
+.navbar-fixed-bottom {\r
+ bottom: 0;\r
+ margin-bottom: 0;\r
+ border-width: 1px 0 0;\r
+}\r
+.navbar-brand {\r
+ float: left;\r
+ padding: 15px 15px;\r
+ font-size: 18px;\r
+ line-height: 20px;\r
+ height: 50px;\r
+}\r
+.navbar-brand:hover,\r
+.navbar-brand:focus {\r
+ text-decoration: none;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar > .container .navbar-brand,\r
+ .navbar > .container-fluid .navbar-brand {\r
+ margin-left: -15px;\r
+ }\r
+}\r
+.navbar-toggle {\r
+ position: relative;\r
+ float: right;\r
+ margin-right: 15px;\r
+ padding: 9px 10px;\r
+ margin-top: 8px;\r
+ margin-bottom: 8px;\r
+ background-color: transparent;\r
+ background-image: none;\r
+ border: 1px solid transparent;\r
+ border-radius: 0px;\r
+}\r
+.navbar-toggle:focus {\r
+ outline: none;\r
+}\r
+.navbar-toggle .icon-bar {\r
+ display: block;\r
+ width: 22px;\r
+ height: 2px;\r
+ border-radius: 1px;\r
+}\r
+.navbar-toggle .icon-bar + .icon-bar {\r
+ margin-top: 4px;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-toggle {\r
+ display: none;\r
+ }\r
+}\r
+.navbar-nav {\r
+ margin: 7.5px -15px;\r
+}\r
+.navbar-nav > li > a {\r
+ padding-top: 10px;\r
+ padding-bottom: 10px;\r
+ line-height: 20px;\r
+}\r
+@media (max-width: 767px) {\r
+ .navbar-nav .open .dropdown-menu {\r
+ position: static;\r
+ float: none;\r
+ width: auto;\r
+ margin-top: 0;\r
+ background-color: transparent;\r
+ border: 0;\r
+ box-shadow: none;\r
+ }\r
+ .navbar-nav .open .dropdown-menu > li > a,\r
+ .navbar-nav .open .dropdown-menu .dropdown-header {\r
+ padding: 5px 15px 5px 25px;\r
+ }\r
+ .navbar-nav .open .dropdown-menu > li > a {\r
+ line-height: 20px;\r
+ }\r
+ .navbar-nav .open .dropdown-menu > li > a:hover,\r
+ .navbar-nav .open .dropdown-menu > li > a:focus {\r
+ background-image: none;\r
+ }\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-nav {\r
+ float: left;\r
+ margin: 0;\r
+ }\r
+ .navbar-nav > li {\r
+ float: left;\r
+ }\r
+ .navbar-nav > li > a {\r
+ padding-top: 15px;\r
+ padding-bottom: 15px;\r
+ }\r
+ .navbar-nav.navbar-right:last-child {\r
+ margin-right: -15px;\r
+ }\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-left {\r
+ float: left !important;\r
+ }\r
+ .navbar-right {\r
+ float: right !important;\r
+ }\r
+}\r
+.navbar-form {\r
+ margin-left: -15px;\r
+ margin-right: -15px;\r
+ padding: 10px 15px;\r
+ border-top: 1px solid transparent;\r
+ border-bottom: 1px solid transparent;\r
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\r
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\r
+ margin-top: 8px;\r
+ margin-bottom: 8px;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-form .form-group {\r
+ display: inline-block;\r
+ margin-bottom: 0;\r
+ vertical-align: middle;\r
+ }\r
+ .navbar-form .form-control {\r
+ display: inline-block;\r
+ width: auto;\r
+ vertical-align: middle;\r
+ }\r
+ .navbar-form .input-group > .form-control {\r
+ width: 100%;\r
+ }\r
+ .navbar-form .control-label {\r
+ margin-bottom: 0;\r
+ vertical-align: middle;\r
+ }\r
+ .navbar-form .radio,\r
+ .navbar-form .checkbox {\r
+ display: inline-block;\r
+ margin-top: 0;\r
+ margin-bottom: 0;\r
+ padding-left: 0;\r
+ vertical-align: middle;\r
+ }\r
+ .navbar-form .radio input[type="radio"],\r
+ .navbar-form .checkbox input[type="checkbox"] {\r
+ float: none;\r
+ margin-left: 0;\r
+ }\r
+ .navbar-form .has-feedback .form-control-feedback {\r
+ top: 0;\r
+ }\r
+}\r
+@media (max-width: 767px) {\r
+ .navbar-form .form-group {\r
+ margin-bottom: 5px;\r
+ }\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-form {\r
+ width: auto;\r
+ border: 0;\r
+ margin-left: 0;\r
+ margin-right: 0;\r
+ padding-top: 0;\r
+ padding-bottom: 0;\r
+ -webkit-box-shadow: none;\r
+ box-shadow: none;\r
+ }\r
+ .navbar-form.navbar-right:last-child {\r
+ margin-right: -15px;\r
+ }\r
+}\r
+.navbar-nav > li > .dropdown-menu {\r
+ margin-top: 0;\r
+ border-top-right-radius: 0;\r
+ border-top-left-radius: 0;\r
+}\r
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\r
+ border-bottom-right-radius: 0;\r
+ border-bottom-left-radius: 0;\r
+}\r
+.navbar-btn {\r
+ margin-top: 8px;\r
+ margin-bottom: 8px;\r
+}\r
+.navbar-btn.btn-sm {\r
+ margin-top: 10px;\r
+ margin-bottom: 10px;\r
+}\r
+.navbar-btn.btn-xs {\r
+ margin-top: 14px;\r
+ margin-bottom: 14px;\r
+}\r
+.navbar-text {\r
+ margin-top: 15px;\r
+ margin-bottom: 15px;\r
+}\r
+@media (min-width: 768px) {\r
+ .navbar-text {\r
+ float: left;\r
+ margin-left: 15px;\r
+ margin-right: 15px;\r
+ }\r
+ .navbar-text.navbar-right:last-child {\r
+ margin-right: 0;\r
+ }\r
+}\r
+.navbar-default {\r
+ background-color: #0d8921;\r
+ border-color: none;\r
+}\r
+.navbar-default .navbar-brand {\r
+ color: #ffffff;\r
+}\r
+.navbar-default .navbar-brand:hover,\r
+.navbar-default .navbar-brand:focus {\r
+ color: #e6e6e6;\r
+ background-color: transparent;\r
+}\r
+.navbar-default .navbar-text {\r
+ color: #ffffff;\r
+}\r
+.navbar-default .navbar-nav > li > a {\r
+ color: #ffffff;\r
+}\r
+.navbar-default .navbar-nav > li > a:hover,\r
+.navbar-default .navbar-nav > li > a:focus {\r
+ color: #dddddd;\r
+ background-color: transparent;\r
+}\r
+.navbar-default .navbar-nav > .active > a,\r
+.navbar-default .navbar-nav > .active > a:hover,\r
+.navbar-default .navbar-nav > .active > a:focus {\r
+ color: #ffffff;\r
+ background-color: #0a6b1a;\r
+}\r
+.navbar-default .navbar-nav > .disabled > a,\r
+.navbar-default .navbar-nav > .disabled > a:hover,\r
+.navbar-default .navbar-nav > .disabled > a:focus {\r
+ color: #cccccc;\r
+ background-color: transparent;\r
+}\r
+.navbar-default .navbar-toggle {\r
+ border-color: #dddddd;\r
+}\r
+.navbar-default .navbar-toggle:hover,\r
+.navbar-default .navbar-toggle:focus {\r
+ background-color: #dddddd;\r
+}\r
+.navbar-default .navbar-toggle .icon-bar {\r
+ background-color: #ffffff;\r
+}\r
+.navbar-default .navbar-collapse,\r
+.navbar-default .navbar-form {\r
+ border-color: none;\r
+}\r
+.navbar-default .navbar-nav > .open > a,\r
+.navbar-default .navbar-nav > .open > a:hover,\r
+.navbar-default .navbar-nav > .open > a:focus {\r
+ background-color: #0a6b1a;\r
+ color: #ffffff;\r
+}\r
+@media (max-width: 767px) {\r
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a {\r
+ color: #ffffff;\r
+ }\r
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\r
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\r
+ color: #dddddd;\r
+ background-color: transparent;\r
+ }\r
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\r
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\r
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\r
+ color: #ffffff;\r
+ background-color: #0a6b1a;\r
+ }\r
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\r
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\r
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\r
+ color: #cccccc;\r
+ background-color: transparent;\r
+ }\r
+}\r
+.navbar-default .navbar-link {\r
+ color: #ffffff;\r
+}\r
+.navbar-default .navbar-link:hover {\r
+ color: #dddddd;\r
+}\r
+.navbar-inverse {\r
+ background-color: #222222;\r
+ border-color: #080808;\r
+}\r
+.navbar-inverse .navbar-brand {\r
+ color: #999999;\r
+}\r
+.navbar-inverse .navbar-brand:hover,\r
+.navbar-inverse .navbar-brand:focus {\r
+ color: #ffffff;\r
+ background-color: transparent;\r
+}\r
+.navbar-inverse .navbar-text {\r
+ color: #999999;\r
+}\r
+.navbar-inverse .navbar-nav > li > a {\r
+ color: #999999;\r
+}\r
+.navbar-inverse .navbar-nav > li > a:hover,\r
+.navbar-inverse .navbar-nav > li > a:focus {\r
+ color: #ffffff;\r
+ background-color: transparent;\r
+}\r
+.navbar-inverse .navbar-nav > .active > a,\r
+.navbar-inverse .navbar-nav > .active > a:hover,\r
+.navbar-inverse .navbar-nav > .active > a:focus {\r
+ color: #ffffff;\r
+ background-color: #080808;\r
+}\r
+.navbar-inverse .navbar-nav > .disabled > a,\r
+.navbar-inverse .navbar-nav > .disabled > a:hover,\r
+.navbar-inverse .navbar-nav > .disabled > a:focus {\r
+ color: #444444;\r
+ background-color: transparent;\r
+}\r
+.navbar-inverse .navbar-toggle {\r
+ border-color: #333333;\r
+}\r
+.navbar-inverse .navbar-toggle:hover,\r
+.navbar-inverse .navbar-toggle:focus {\r
+ background-color: #333333;\r
+}\r
+.navbar-inverse .navbar-toggle .icon-bar {\r
+ background-color: #ffffff;\r
+}\r
+.navbar-inverse .navbar-collapse,\r
+.navbar-inverse .navbar-form {\r
+ border-color: #101010;\r
+}\r
+.navbar-inverse .navbar-nav > .open > a,\r
+.navbar-inverse .navbar-nav > .open > a:hover,\r
+.navbar-inverse .navbar-nav > .open > a:focus {\r
+ background-color: #080808;\r
+ color: #ffffff;\r
+}\r
+@media (max-width: 767px) {\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\r
+ border-color: #080808;\r
+ }\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\r
+ background-color: #080808;\r
+ }\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\r
+ color: #999999;\r
+ }\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\r
+ color: #ffffff;\r
+ background-color: transparent;\r
+ }\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\r
+ color: #ffffff;\r
+ background-color: #080808;\r
+ }\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\r
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\r
+ color: #444444;\r
+ background-color: transparent;\r
+ }\r
+}\r
+.navbar-inverse .navbar-link {\r
+ color: #999999;\r
+}\r
+.navbar-inverse .navbar-link:hover {\r
+ color: #ffffff;\r
+}\r
+.breadcrumb {\r
+ padding: 8px 15px;\r
+ margin-bottom: 20px;\r
+ list-style: none;\r
+ background-color: #f5f5f5;\r
+ border-radius: 0px;\r
+}\r
+.breadcrumb > li {\r
+ display: inline-block;\r
+}\r
+.breadcrumb > li + li:before {\r
+ content: "\00a0";\r
+ padding: 0 5px;\r
+ color: #cccccc;\r
+}\r
+.breadcrumb > .active {\r
+ color: #999999;\r
+}\r
+.pagination {\r
+ display: inline-block;\r
+ padding-left: 0;\r
+ margin: 20px 0;\r
+ border-radius: 0px;\r
+}\r
+.pagination > li {\r
+ display: inline;\r
+}\r
+.pagination > li > a,\r
+.pagination > li > span {\r
+ position: relative;\r
+ float: left;\r
+ padding: 6px 12px;\r
+ line-height: 1.428571429;\r
+ text-decoration: none;\r
+ color: #0d8921;\r
+ background-color: #ffffff;\r
+ border: 1px solid #dddddd;\r
+ margin-left: -1px;\r
+}\r
+.pagination > li:first-child > a,\r
+.pagination > li:first-child > span {\r
+ margin-left: 0;\r
+ border-bottom-left-radius: 0px;\r
+ border-top-left-radius: 0px;\r
+}\r
+.pagination > li:last-child > a,\r
+.pagination > li:last-child > span {\r
+ border-bottom-right-radius: 0px;\r
+ border-top-right-radius: 0px;\r
+}\r
+.pagination > li > a:hover,\r
+.pagination > li > span:hover,\r
+.pagination > li > a:focus,\r
+.pagination > li > span:focus {\r
+ color: #064310;\r
+ background-color: #eeeeee;\r
+ border-color: #dddddd;\r
+}\r
+.pagination > .active > a,\r
+.pagination > .active > span,\r
+.pagination > .active > a:hover,\r
+.pagination > .active > span:hover,\r
+.pagination > .active > a:focus,\r
+.pagination > .active > span:focus {\r
+ z-index: 2;\r
+ color: #ffffff;\r
+ background-color: #0d8921;\r
+ border-color: #0d8921;\r
+ cursor: default;\r
+}\r
+.pagination > .disabled > span,\r
+.pagination > .disabled > span:hover,\r
+.pagination > .disabled > span:focus,\r
+.pagination > .disabled > a,\r
+.pagination > .disabled > a:hover,\r
+.pagination > .disabled > a:focus {\r
+ color: #999999;\r
+ background-color: #ffffff;\r
+ border-color: #dddddd;\r
+ cursor: not-allowed;\r
+}\r
+.pagination-lg > li > a,\r
+.pagination-lg > li > span {\r
+ padding: 10px 16px;\r
+ font-size: 18px;\r
+}\r
+.pagination-lg > li:first-child > a,\r
+.pagination-lg > li:first-child > span {\r
+ border-bottom-left-radius: 0px;\r
+ border-top-left-radius: 0px;\r
+}\r
+.pagination-lg > li:last-child > a,\r
+.pagination-lg > li:last-child > span {\r
+ border-bottom-right-radius: 0px;\r
+ border-top-right-radius: 0px;\r
+}\r
+.pagination-sm > li > a,\r
+.pagination-sm > li > span {\r
+ padding: 5px 10px;\r
+ font-size: 12px;\r
+}\r
+.pagination-sm > li:first-child > a,\r
+.pagination-sm > li:first-child > span {\r
+ border-bottom-left-radius: 0px;\r
+ border-top-left-radius: 0px;\r
+}\r
+.pagination-sm > li:last-child > a,\r
+.pagination-sm > li:last-child > span {\r
+ border-bottom-right-radius: 0px;\r
+ border-top-right-radius: 0px;\r
+}\r
+.pager {\r
+ padding-left: 0;\r
+ margin: 20px 0;\r
+ list-style: none;\r
+ text-align: center;\r
+}\r
+.pager li {\r
+ display: inline;\r
+}\r
+.pager li > a,\r
+.pager li > span {\r
+ display: inline-block;\r
+ padding: 5px 14px;\r
+ background-color: #ffffff;\r
+ border: 1px solid #dddddd;\r
+ border-radius: 15px;\r
+}\r
+.pager li > a:hover,\r
+.pager li > a:focus {\r
+ text-decoration: none;\r
+ background-color: #eeeeee;\r
+}\r
+.pager .next > a,\r
+.pager .next > span {\r
+ float: right;\r
+}\r
+.pager .previous > a,\r
+.pager .previous > span {\r
+ float: left;\r
+}\r
+.pager .disabled > a,\r
+.pager .disabled > a:hover,\r
+.pager .disabled > a:focus,\r
+.pager .disabled > span {\r
+ color: #999999;\r
+ background-color: #ffffff;\r
+ cursor: not-allowed;\r
+}\r
+.label {\r
+ display: inline;\r
+ padding: .2em .6em .3em;\r
+ font-size: 75%;\r
+ font-weight: bold;\r
+ line-height: 1;\r
+ color: #ffffff;\r
+ text-align: center;\r
+ white-space: nowrap;\r
+ vertical-align: baseline;\r
+ border-radius: .25em;\r
+}\r
+.label[href]:hover,\r
+.label[href]:focus {\r
+ color: #ffffff;\r
+ text-decoration: none;\r
+ cursor: pointer;\r
+}\r
+.label:empty {\r
+ display: none;\r
+}\r
+.btn .label {\r
+ position: relative;\r
+ top: -1px;\r
+}\r
+.label-default {\r
+ background-color: #999999;\r
+}\r
+.label-default[href]:hover,\r
+.label-default[href]:focus {\r
+ background-color: #808080;\r
+}\r
+.label-primary {\r
+ background-color: #0d8921;\r
+}\r
+.label-primary[href]:hover,\r
+.label-primary[href]:focus {\r
+ background-color: #095a16;\r
+}\r
+.label-success {\r
+ background-color: #5cb85c;\r
+}\r
+.label-success[href]:hover,\r
+.label-success[href]:focus {\r
+ background-color: #449d44;\r
+}\r
+.label-info {\r
+ background-color: #5bc0de;\r
+}\r
+.label-info[href]:hover,\r
+.label-info[href]:focus {\r
+ background-color: #31b0d5;\r
+}\r
+.label-warning {\r
+ background-color: #f0ad4e;\r
+}\r
+.label-warning[href]:hover,\r
+.label-warning[href]:focus {\r
+ background-color: #ec971f;\r
+}\r
+.label-danger {\r
+ background-color: #d9534f;\r
+}\r
+.label-danger[href]:hover,\r
+.label-danger[href]:focus {\r
+ background-color: #c9302c;\r
+}\r
+.badge {\r
+ display: inline-block;\r
+ min-width: 10px;\r
+ padding: 3px 7px;\r
+ font-size: 12px;\r
+ font-weight: bold;\r
+ color: : #fff;\r
+ line-height: 1;\r
+ vertical-align: baseline;\r
+ white-space: nowrap;\r
+ text-align: center;\r
+ background-color: #999999;\r
+ border-radius: 10px;\r
+}\r
+.badge:empty {\r
+ display: none;\r
+}\r
+.btn .badge {\r
+ position: relative;\r
+ top: -1px;\r
+}\r
+.btn-xs .badge {\r
+ top: 0;\r
+ padding: 1px 5px;\r
+}\r
+a.badge:hover,\r
+a.badge:focus {\r
+ color: #ffffff;\r
+ text-decoration: none;\r
+ cursor: pointer;\r
+}\r
+a.list-group-item.active > .badge,\r
+.nav-pills > .active > a > .badge {\r
+ color: #0d8921;\r
+ background-color: #ffffff;\r
+}\r
+.nav-pills > li > a > .badge {\r
+ margin-left: 3px;\r
+}\r
+.jumbotron {\r
+ padding: 30px;\r
+ margin-bottom: 30px;\r
+ color: inherit;\r
+ background-color: #ffffff;\r
+}\r
+.jumbotron h1,\r
+.jumbotron .h1 {\r
+ color: inherit;\r
+}\r
+.jumbotron p {\r
+ margin-bottom: 15px;\r
+ font-size: 21px;\r
+ font-weight: 200;\r
+}\r
+.container .jumbotron {\r
+ border-radius: 0px;\r
+}\r
+.jumbotron .container {\r
+ max-width: 100%;\r
+}\r
+@media screen and (min-width: 768px) {\r
+ .jumbotron {\r
+ padding-top: 48px;\r
+ padding-bottom: 48px;\r
+ }\r
+ .container .jumbotron {\r
+ padding-left: 60px;\r
+ padding-right: 60px;\r
+ }\r
+ .jumbotron h1,\r
+ .jumbotron .h1 {\r
+ font-size: 63px;\r
+ }\r
+}\r
+.thumbnail {\r
+ display: block;\r
+ padding: 4px;\r
+ margin-bottom: 20px;\r
+ line-height: 1.428571429;\r
+ background-color: #f2f2f2;\r
+ border: 1px solid #dddddd;\r
+ border-radius: 0px;\r
+ -webkit-transition: all 0.2s ease-in-out;\r
+ transition: all 0.2s ease-in-out;\r
+}\r
+.thumbnail > img,\r
+.thumbnail a > img {\r
+ margin-left: auto;\r
+ margin-right: auto;\r
+}\r
+a.thumbnail:hover,\r
+a.thumbnail:focus,\r
+a.thumbnail.active {\r
+ border-color: #0d8921;\r
+}\r
+.thumbnail .caption {\r
+ padding: 9px;\r
+ color: #333333;\r
+}\r
+.alert {\r
+ padding: 15px;\r
+ margin-bottom: 20px;\r
+ border: 1px solid transparent;\r
+ border-radius: 0px;\r
+}\r
+.alert h4 {\r
+ margin-top: 0;\r
+ color: inherit;\r
+}\r
+.alert .alert-link {\r
+ font-weight: bold;\r
+}\r
+.alert > p,\r
+.alert > ul {\r
+ margin-bottom: 0;\r
+}\r
+.alert > p + p {\r
+ margin-top: 5px;\r
+}\r
+.alert-dismissable {\r
+ padding-right: 35px;\r
+}\r
+.alert-dismissable .close {\r
+ position: relative;\r
+ top: -2px;\r
+ right: -21px;\r
+ color: inherit;\r
+}\r
+.alert-success {\r
+ background-color: #dff0d8;\r
+ border-color: #d6e9c6;\r
+ color: #5cb85c;\r
+}\r
+.alert-success hr {\r
+ border-top-color: #c9e2b3;\r
+}\r
+.alert-success .alert-link {\r
+ color: #449d44;\r
+}\r
+.alert-info {\r
+ background-color: #d9edf7;\r
+ border-color: #bce8f1;\r
+ color: #5bc0de;\r
+}\r
+.alert-info hr {\r
+ border-top-color: #a6e1ec;\r
+}\r
+.alert-info .alert-link {\r
+ color: #31b0d5;\r
+}\r
+.alert-warning {\r
+ background-color: #fcf8e3;\r
+ border-color: #fbeed5;\r
+ color: #f0ad4e;\r
+}\r
+.alert-warning hr {\r
+ border-top-color: #f8e5be;\r
+}\r
+.alert-warning .alert-link {\r
+ color: #ec971f;\r
+}\r
+.alert-danger {\r
+ background-color: #f2dede;\r
+ border-color: #eed3d7;\r
+ color: #d9534f;\r
+}\r
+.alert-danger hr {\r
+ border-top-color: #e6c1c7;\r
+}\r
+.alert-danger .alert-link {\r
+ color: #c9302c;\r
+}\r
+@-webkit-keyframes progress-bar-stripes {\r
+ from {\r
+ background-position: 40px 0;\r
+ }\r
+ to {\r
+ background-position: 0 0;\r
+ }\r
+}\r
+@keyframes progress-bar-stripes {\r
+ from {\r
+ background-position: 40px 0;\r
+ }\r
+ to {\r
+ background-position: 0 0;\r
+ }\r
+}\r
+.progress {\r
+ overflow: hidden;\r
+ height: 20px;\r
+ margin-bottom: 20px;\r
+ background-color: #f5f5f5;\r
+ border-radius: 0px;\r
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\r
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\r
+}\r
+.progress-bar {\r
+ float: left;\r
+ width: 0%;\r
+ height: 100%;\r
+ font-size: 12px;\r
+ line-height: 20px;\r
+ color: #ffffff;\r
+ text-align: center;\r
+ background-color: #0d8921;\r
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\r
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\r
+ -webkit-transition: width 0.6s ease;\r
+ transition: width 0.6s ease;\r
+}\r
+.progress-striped .progress-bar {\r
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+ background-size: 40px 40px;\r
+}\r
+.progress.active .progress-bar {\r
+ -webkit-animation: progress-bar-stripes 2s linear infinite;\r
+ animation: progress-bar-stripes 2s linear infinite;\r
+}\r
+.progress-bar-success {\r
+ background-color: #5cb85c;\r
+}\r
+.progress-striped .progress-bar-success {\r
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+}\r
+.progress-bar-info {\r
+ background-color: #5bc0de;\r
+}\r
+.progress-striped .progress-bar-info {\r
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+}\r
+.progress-bar-warning {\r
+ background-color: #f0ad4e;\r
+}\r
+.progress-striped .progress-bar-warning {\r
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+}\r
+.progress-bar-danger {\r
+ background-color: #d9534f;\r
+}\r
+.progress-striped .progress-bar-danger {\r
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\r
+}\r
+.media,\r
+.media-body {\r
+ overflow: hidden;\r
+ zoom: 1;\r
+}\r
+.media,\r
+.media .media {\r
+ margin-top: 15px;\r
+}\r
+.media:first-child {\r
+ margin-top: 0;\r
+}\r
+.media-object {\r
+ display: block;\r
+}\r
+.media-heading {\r
+ margin: 0 0 5px;\r
+}\r
+.media > .pull-left {\r
+ margin-right: 10px;\r
+}\r
+.media > .pull-right {\r
+ margin-left: 10px;\r
+}\r
+.media-list {\r
+ padding-left: 0;\r
+ list-style: none;\r
+}\r
+.list-group {\r
+ margin-bottom: 20px;\r
+ padding-left: 0;\r
+}\r
+.list-group-item {\r
+ position: relative;\r
+ display: block;\r
+ padding: 10px 15px;\r
+ margin-bottom: -1px;\r
+ background-color: #ffffff;\r
+ border: 1px solid #dddddd;\r
+}\r
+.list-group-item:first-child {\r
+ border-top-right-radius: 0px;\r
+ border-top-left-radius: 0px;\r
+}\r
+.list-group-item:last-child {\r
+ margin-bottom: 0;\r
+ border-bottom-right-radius: 0px;\r
+ border-bottom-left-radius: 0px;\r
+}\r
+.list-group-item > .badge {\r
+ float: right;\r
+}\r
+.list-group-item > .badge + .badge {\r
+ margin-right: 5px;\r
+}\r
+a.list-group-item {\r
+ color: #555555;\r
+}\r
+a.list-group-item .list-group-item-heading {\r
+ color: #333333;\r
+}\r
+a.list-group-item:hover,\r
+a.list-group-item:focus {\r
+ text-decoration: none;\r
+ background-color: #f5f5f5;\r
+}\r
+a.list-group-item.active,\r
+a.list-group-item.active:hover,\r
+a.list-group-item.active:focus {\r
+ z-index: 2;\r
+ color: #ffffff;\r
+ background-color: #0d8921;\r
+ border-color: #0d8921;\r
+}\r
+a.list-group-item.active .list-group-item-heading,\r
+a.list-group-item.active:hover .list-group-item-heading,\r
+a.list-group-item.active:focus .list-group-item-heading {\r
+ color: inherit;\r
+}\r
+a.list-group-item.active .list-group-item-text,\r
+a.list-group-item.active:hover .list-group-item-text,\r
+a.list-group-item.active:focus .list-group-item-text {\r
+ color: #cccccc;\r
+}\r
+.list-group-item-success {\r
+ color: #5cb85c;\r
+ background-color: #dff0d8;\r
+}\r
+a.list-group-item-success {\r
+ color: #5cb85c;\r
+}\r
+a.list-group-item-success .list-group-item-heading {\r
+ color: inherit;\r
+}\r
+a.list-group-item-success:hover,\r
+a.list-group-item-success:focus {\r
+ color: #5cb85c;\r
+ background-color: #d0e9c6;\r
+}\r
+a.list-group-item-success.active,\r
+a.list-group-item-success.active:hover,\r
+a.list-group-item-success.active:focus {\r
+ color: #fff;\r
+ background-color: #5cb85c;\r
+ border-color: #5cb85c;\r
+}\r
+.list-group-item-info {\r
+ color: #5bc0de;\r
+ background-color: #d9edf7;\r
+}\r
+a.list-group-item-info {\r
+ color: #5bc0de;\r
+}\r
+a.list-group-item-info .list-group-item-heading {\r
+ color: inherit;\r
+}\r
+a.list-group-item-info:hover,\r
+a.list-group-item-info:focus {\r
+ color: #5bc0de;\r
+ background-color: #c4e3f3;\r
+}\r
+a.list-group-item-info.active,\r
+a.list-group-item-info.active:hover,\r
+a.list-group-item-info.active:focus {\r
+ color: #fff;\r
+ background-color: #5bc0de;\r
+ border-color: #5bc0de;\r
+}\r
+.list-group-item-warning {\r
+ color: #f0ad4e;\r
+ background-color: #fcf8e3;\r
+}\r
+a.list-group-item-warning {\r
+ color: #f0ad4e;\r
+}\r
+a.list-group-item-warning .list-group-item-heading {\r
+ color: inherit;\r
+}\r
+a.list-group-item-warning:hover,\r
+a.list-group-item-warning:focus {\r
+ color: #f0ad4e;\r
+ background-color: #faf2cc;\r
+}\r
+a.list-group-item-warning.active,\r
+a.list-group-item-warning.active:hover,\r
+a.list-group-item-warning.active:focus {\r
+ color: #fff;\r
+ background-color: #f0ad4e;\r
+ border-color: #f0ad4e;\r
+}\r
+.list-group-item-danger {\r
+ color: #d9534f;\r
+ background-color: #f2dede;\r
+}\r
+a.list-group-item-danger {\r
+ color: #d9534f;\r
+}\r
+a.list-group-item-danger .list-group-item-heading {\r
+ color: inherit;\r
+}\r
+a.list-group-item-danger:hover,\r
+a.list-group-item-danger:focus {\r
+ color: #d9534f;\r
+ background-color: #ebcccc;\r
+}\r
+a.list-group-item-danger.active,\r
+a.list-group-item-danger.active:hover,\r
+a.list-group-item-danger.active:focus {\r
+ color: #fff;\r
+ background-color: #d9534f;\r
+ border-color: #d9534f;\r
+}\r
+.list-group-item-heading {\r
+ margin-top: 0;\r
+ margin-bottom: 5px;\r
+}\r
+.list-group-item-text {\r
+ margin-bottom: 0;\r
+ line-height: 1.3;\r
+}\r
+.panel {\r
+ margin-bottom: 20px;\r
+ background-color: #ffffff;\r
+ border: 1px solid transparent;\r
+ border-radius: 0px;\r
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\r
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\r
+}\r
+.panel-body {\r
+ padding: 15px;\r
+}\r
+.panel-heading {\r
+ padding: 10px 15px;\r
+ border-bottom: 1px solid transparent;\r
+ border-top-right-radius: -1px;\r
+ border-top-left-radius: -1px;\r
+}\r
+.panel-heading > .dropdown .dropdown-toggle {\r
+ color: inherit;\r
+}\r
+.panel-title {\r
+ margin-top: 0;\r
+ margin-bottom: 0;\r
+ font-size: 16px;\r
+ color: inherit;\r
+}\r
+.panel-title > a {\r
+ color: inherit;\r
+}\r
+.panel-footer {\r
+ padding: 10px 15px;\r
+ background-color: #f5f5f5;\r
+ border-top: 1px solid #dddddd;\r
+ border-bottom-right-radius: -1px;\r
+ border-bottom-left-radius: -1px;\r
+}\r
+.panel > .list-group {\r
+ margin-bottom: 0;\r
+}\r
+.panel > .list-group .list-group-item {\r
+ border-width: 1px 0;\r
+ border-radius: 0;\r
+}\r
+.panel > .list-group .list-group-item:first-child {\r
+ border-top: 0;\r
+}\r
+.panel > .list-group .list-group-item:last-child {\r
+ border-bottom: 0;\r
+}\r
+.panel > .list-group:first-child .list-group-item:first-child {\r
+ border-top-right-radius: -1px;\r
+ border-top-left-radius: -1px;\r
+}\r
+.panel > .list-group:last-child .list-group-item:last-child {\r
+ border-bottom-right-radius: -1px;\r
+ border-bottom-left-radius: -1px;\r
+}\r
+.panel-heading + .list-group .list-group-item:first-child {\r
+ border-top-width: 0;\r
+}\r
+.panel > .table,\r
+.panel > .table-responsive > .table {\r
+ margin-bottom: 0;\r
+}\r
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\r
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\r
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\r
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\r
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\r
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\r
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\r
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\r
+ border-top-left-radius: -1px;\r
+}\r
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\r
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\r
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\r
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\r
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\r
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\r
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\r
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\r
+ border-top-right-radius: -1px;\r
+}\r
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\r
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\r
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\r
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\r
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\r
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\r
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\r
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\r
+ border-bottom-left-radius: -1px;\r
+}\r
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\r
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\r
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\r
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\r
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\r
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\r
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\r
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\r
+ border-bottom-right-radius: -1px;\r
+}\r
+.panel > .panel-body + .table,\r
+.panel > .panel-body + .table-responsive {\r
+ border-top: 1px solid #dddddd;\r
+}\r
+.panel > .table > tbody:first-child > tr:first-child th,\r
+.panel > .table > tbody:first-child > tr:first-child td {\r
+ border-top: 0;\r
+}\r
+.panel > .table-bordered,\r
+.panel > .table-responsive > .table-bordered {\r
+ border: 0;\r
+}\r
+.panel > .table-bordered > thead > tr > th:first-child,\r
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\r
+.panel > .table-bordered > tbody > tr > th:first-child,\r
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\r
+.panel > .table-bordered > tfoot > tr > th:first-child,\r
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\r
+.panel > .table-bordered > thead > tr > td:first-child,\r
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\r
+.panel > .table-bordered > tbody > tr > td:first-child,\r
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\r
+.panel > .table-bordered > tfoot > tr > td:first-child,\r
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\r
+ border-left: 0;\r
+}\r
+.panel > .table-bordered > thead > tr > th:last-child,\r
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\r
+.panel > .table-bordered > tbody > tr > th:last-child,\r
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\r
+.panel > .table-bordered > tfoot > tr > th:last-child,\r
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\r
+.panel > .table-bordered > thead > tr > td:last-child,\r
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\r
+.panel > .table-bordered > tbody > tr > td:last-child,\r
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\r
+.panel > .table-bordered > tfoot > tr > td:last-child,\r
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\r
+ border-right: 0;\r
+}\r
+.panel > .table-bordered > thead > tr:first-child > td,\r
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\r
+.panel > .table-bordered > tbody > tr:first-child > td,\r
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\r
+.panel > .table-bordered > thead > tr:first-child > th,\r
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\r
+.panel > .table-bordered > tbody > tr:first-child > th,\r
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\r
+ border-bottom: 0;\r
+}\r
+.panel > .table-bordered > tbody > tr:last-child > td,\r
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\r
+.panel > .table-bordered > tfoot > tr:last-child > td,\r
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\r
+.panel > .table-bordered > tbody > tr:last-child > th,\r
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\r
+.panel > .table-bordered > tfoot > tr:last-child > th,\r
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\r
+ border-bottom: 0;\r
+}\r
+.panel > .table-responsive {\r
+ border: 0;\r
+ margin-bottom: 0;\r
+}\r
+.panel-group {\r
+ margin-bottom: 20px;\r
+}\r
+.panel-group .panel {\r
+ margin-bottom: 0;\r
+ border-radius: 0px;\r
+ overflow: hidden;\r
+}\r
+.panel-group .panel + .panel {\r
+ margin-top: 5px;\r
+}\r
+.panel-group .panel-heading {\r
+ border-bottom: 0;\r
+}\r
+.panel-group .panel-heading + .panel-collapse .panel-body {\r
+ border-top: 1px solid #dddddd;\r
+}\r
+.panel-group .panel-footer {\r
+ border-top: 0;\r
+}\r
+.panel-group .panel-footer + .panel-collapse .panel-body {\r
+ border-bottom: 1px solid #dddddd;\r
+}\r
+.panel-default {\r
+ border-color: #dddddd;\r
+}\r
+.panel-default > .panel-heading {\r
+ color: #333333;\r
+ background-color: #f5f5f5;\r
+ border-color: #dddddd;\r
+}\r
+.panel-default > .panel-heading + .panel-collapse .panel-body {\r
+ border-top-color: #dddddd;\r
+}\r
+.panel-default > .panel-footer + .panel-collapse .panel-body {\r
+ border-bottom-color: #dddddd;\r
+}\r
+.panel-primary {\r
+ border-color: #0d8921;\r
+}\r
+.panel-primary > .panel-heading {\r
+ color: #ffffff;\r
+ background-color: #0d8921;\r
+ border-color: #0d8921;\r
+}\r
+.panel-primary > .panel-heading + .panel-collapse .panel-body {\r
+ border-top-color: #0d8921;\r
+}\r
+.panel-primary > .panel-footer + .panel-collapse .panel-body {\r
+ border-bottom-color: #0d8921;\r
+}\r
+.panel-success {\r
+ border-color: #d6e9c6;\r
+}\r
+.panel-success > .panel-heading {\r
+ color: #5cb85c;\r
+ background-color: #dff0d8;\r
+ border-color: #d6e9c6;\r
+}\r
+.panel-success > .panel-heading + .panel-collapse .panel-body {\r
+ border-top-color: #d6e9c6;\r
+}\r
+.panel-success > .panel-footer + .panel-collapse .panel-body {\r
+ border-bottom-color: #d6e9c6;\r
+}\r
+.panel-info {\r
+ border-color: #bce8f1;\r
+}\r
+.panel-info > .panel-heading {\r
+ color: #5bc0de;\r
+ background-color: #d9edf7;\r
+ border-color: #bce8f1;\r
+}\r
+.panel-info > .panel-heading + .panel-collapse .panel-body {\r
+ border-top-color: #bce8f1;\r
+}\r
+.panel-info > .panel-footer + .panel-collapse .panel-body {\r
+ border-bottom-color: #bce8f1;\r
+}\r
+.panel-warning {\r
+ border-color: #fbeed5;\r
+}\r
+.panel-warning > .panel-heading {\r
+ color: #f0ad4e;\r
+ background-color: #fcf8e3;\r
+ border-color: #fbeed5;\r
+}\r
+.panel-warning > .panel-heading + .panel-collapse .panel-body {\r
+ border-top-color: #fbeed5;\r
+}\r
+.panel-warning > .panel-footer + .panel-collapse .panel-body {\r
+ border-bottom-color: #fbeed5;\r
+}\r
+.panel-danger {\r
+ border-color: #eed3d7;\r
+}\r
+.panel-danger > .panel-heading {\r
+ color: #d9534f;\r
+ background-color: #f2dede;\r
+ border-color: #eed3d7;\r
+}\r
+.panel-danger > .panel-heading + .panel-collapse .panel-body {\r
+ border-top-color: #eed3d7;\r
+}\r
+.panel-danger > .panel-footer + .panel-collapse .panel-body {\r
+ border-bottom-color: #eed3d7;\r
+}\r
+.well {\r
+ min-height: 20px;\r
+ padding: 19px;\r
+ margin-bottom: 20px;\r
+ background-color: #f5f5f5;\r
+ border: 1px solid #e3e3e3;\r
+ border-radius: 0px;\r
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\r
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\r
+}\r
+.well blockquote {\r
+ border-color: #ddd;\r
+ border-color: rgba(0, 0, 0, 0.15);\r
+}\r
+.well-lg {\r
+ padding: 24px;\r
+ border-radius: 0px;\r
+}\r
+.well-sm {\r
+ padding: 9px;\r
+ border-radius: 0px;\r
+}\r
+.close {\r
+ float: right;\r
+ font-size: 21px;\r
+ font-weight: bold;\r
+ line-height: 1;\r
+ color: #000000;\r
+ text-shadow: 0 1px 0 #ffffff;\r
+ opacity: 0.2;\r
+ filter: alpha(opacity=20);\r
+}\r
+.close:hover,\r
+.close:focus {\r
+ color: #000000;\r
+ text-decoration: none;\r
+ cursor: pointer;\r
+ opacity: 0.5;\r
+ filter: alpha(opacity=50);\r
+}\r
+button.close {\r
+ padding: 0;\r
+ cursor: pointer;\r
+ background: transparent;\r
+ border: 0;\r
+ -webkit-appearance: none;\r
+}\r
+.modal-open {\r
+ overflow: hidden;\r
+}\r
+.modal {\r
+ display: none;\r
+ overflow: auto;\r
+ overflow-y: scroll;\r
+ position: fixed;\r
+ top: 0;\r
+ right: 0;\r
+ bottom: 0;\r
+ left: 0;\r
+ z-index: 1050;\r
+ -webkit-overflow-scrolling: touch;\r
+ outline: 0;\r
+}\r
+.modal.fade .modal-dialog {\r
+ -webkit-transform: translate(0, -25%);\r
+ -ms-transform: translate(0, -25%);\r
+ transform: translate(0, -25%);\r
+ -webkit-transition: -webkit-transform 0.3s ease-out;\r
+ -moz-transition: -moz-transform 0.3s ease-out;\r
+ -o-transition: -o-transform 0.3s ease-out;\r
+ transition: transform 0.3s ease-out;\r
+}\r
+.modal.in .modal-dialog {\r
+ -webkit-transform: translate(0, 0);\r
+ -ms-transform: translate(0, 0);\r
+ transform: translate(0, 0);\r
+}\r
+.modal-dialog {\r
+ position: relative;\r
+ width: auto;\r
+ margin: 10px;\r
+}\r
+.modal-content {\r
+ position: relative;\r
+ background-color: #ffffff;\r
+ border: 1px solid #999999;\r
+ border: 1px solid rgba(0, 0, 0, 0.2);\r
+ border-radius: 0px;\r
+ -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\r
+ box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\r
+ background-clip: padding-box;\r
+ outline: none;\r
+}\r
+.modal-backdrop {\r
+ position: fixed;\r
+ top: 0;\r
+ right: 0;\r
+ bottom: 0;\r
+ left: 0;\r
+ z-index: 1040;\r
+ background-color: #000000;\r
+}\r
+.modal-backdrop.fade {\r
+ opacity: 0;\r
+ filter: alpha(opacity=0);\r
+}\r
+.modal-backdrop.in {\r
+ opacity: 0.5;\r
+ filter: alpha(opacity=50);\r
+}\r
+.modal-header {\r
+ padding: 15px;\r
+ border-bottom: 1px solid #e5e5e5;\r
+ min-height: 16.428571429px;\r
+}\r
+.modal-header .close {\r
+ margin-top: -2px;\r
+}\r
+.modal-title {\r
+ margin: 0;\r
+ line-height: 1.428571429;\r
+}\r
+.modal-body {\r
+ position: relative;\r
+ padding: 20px;\r
+}\r
+.modal-footer {\r
+ margin-top: 15px;\r
+ padding: 19px 20px 20px;\r
+ text-align: right;\r
+ border-top: 1px solid #e5e5e5;\r
+}\r
+.modal-footer .btn + .btn {\r
+ margin-left: 5px;\r
+ margin-bottom: 0;\r
+}\r
+.modal-footer .btn-group .btn + .btn {\r
+ margin-left: -1px;\r
+}\r
+.modal-footer .btn-block + .btn-block {\r
+ margin-left: 0;\r
+}\r
+@media (min-width: 768px) {\r
+ .modal-dialog {\r
+ width: 600px;\r
+ margin: 30px auto;\r
+ }\r
+ .modal-content {\r
+ -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\r
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\r
+ }\r
+ .modal-sm {\r
+ width: 300px;\r
+ }\r
+}\r
+@media (min-width: 992px) {\r
+ .modal-lg {\r
+ width: 900px;\r
+ }\r
+}\r
+.tooltip {\r
+ position: absolute;\r
+ z-index: 1030;\r
+ display: block;\r
+ visibility: visible;\r
+ font-size: 12px;\r
+ line-height: 1.4;\r
+ opacity: 0;\r
+ filter: alpha(opacity=0);\r
+}\r
+.tooltip.in {\r
+ opacity: 0.9;\r
+ filter: alpha(opacity=90);\r
+}\r
+.tooltip.top {\r
+ margin-top: -3px;\r
+ padding: 5px 0;\r
+}\r
+.tooltip.right {\r
+ margin-left: 3px;\r
+ padding: 0 5px;\r
+}\r
+.tooltip.bottom {\r
+ margin-top: 3px;\r
+ padding: 5px 0;\r
+}\r
+.tooltip.left {\r
+ margin-left: -3px;\r
+ padding: 0 5px;\r
+}\r
+.tooltip-inner {\r
+ max-width: 200px;\r
+ padding: 3px 8px;\r
+ color: #ffffff;\r
+ text-align: center;\r
+ text-decoration: none;\r
+ background-color: #000000;\r
+ border-radius: 0px;\r
+}\r
+.tooltip-arrow {\r
+ position: absolute;\r
+ width: 0;\r
+ height: 0;\r
+ border-color: transparent;\r
+ border-style: solid;\r
+}\r
+.tooltip.top .tooltip-arrow {\r
+ bottom: 0;\r
+ left: 50%;\r
+ margin-left: -5px;\r
+ border-width: 5px 5px 0;\r
+ border-top-color: #000000;\r
+}\r
+.tooltip.top-left .tooltip-arrow {\r
+ bottom: 0;\r
+ left: 5px;\r
+ border-width: 5px 5px 0;\r
+ border-top-color: #000000;\r
+}\r
+.tooltip.top-right .tooltip-arrow {\r
+ bottom: 0;\r
+ right: 5px;\r
+ border-width: 5px 5px 0;\r
+ border-top-color: #000000;\r
+}\r
+.tooltip.right .tooltip-arrow {\r
+ top: 50%;\r
+ left: 0;\r
+ margin-top: -5px;\r
+ border-width: 5px 5px 5px 0;\r
+ border-right-color: #000000;\r
+}\r
+.tooltip.left .tooltip-arrow {\r
+ top: 50%;\r
+ right: 0;\r
+ margin-top: -5px;\r
+ border-width: 5px 0 5px 5px;\r
+ border-left-color: #000000;\r
+}\r
+.tooltip.bottom .tooltip-arrow {\r
+ top: 0;\r
+ left: 50%;\r
+ margin-left: -5px;\r
+ border-width: 0 5px 5px;\r
+ border-bottom-color: #000000;\r
+}\r
+.tooltip.bottom-left .tooltip-arrow {\r
+ top: 0;\r
+ left: 5px;\r
+ border-width: 0 5px 5px;\r
+ border-bottom-color: #000000;\r
+}\r
+.tooltip.bottom-right .tooltip-arrow {\r
+ top: 0;\r
+ right: 5px;\r
+ border-width: 0 5px 5px;\r
+ border-bottom-color: #000000;\r
+}\r
+.popover {\r
+ position: absolute;\r
+ top: 0;\r
+ left: 0;\r
+ z-index: 1010;\r
+ display: none;\r
+ max-width: 276px;\r
+ padding: 1px;\r
+ text-align: left;\r
+ background-color: #ffffff;\r
+ background-clip: padding-box;\r
+ border: 1px solid #cccccc;\r
+ border: 1px solid rgba(0, 0, 0, 0.2);\r
+ border-radius: 0px;\r
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\r
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\r
+ white-space: normal;\r
+}\r
+.popover.top {\r
+ margin-top: -10px;\r
+}\r
+.popover.right {\r
+ margin-left: 10px;\r
+}\r
+.popover.bottom {\r
+ margin-top: 10px;\r
+}\r
+.popover.left {\r
+ margin-left: -10px;\r
+}\r
+.popover-title {\r
+ margin: 0;\r
+ padding: 8px 14px;\r
+ font-size: 14px;\r
+ font-weight: normal;\r
+ line-height: 18px;\r
+ background-color: #f7f7f7;\r
+ border-bottom: 1px solid #ebebeb;\r
+ border-radius: 5px 5px 0 0;\r
+}\r
+.popover-content {\r
+ padding: 9px 14px;\r
+}\r
+.popover > .arrow,\r
+.popover > .arrow:after {\r
+ position: absolute;\r
+ display: block;\r
+ width: 0;\r
+ height: 0;\r
+ border-color: transparent;\r
+ border-style: solid;\r
+}\r
+.popover > .arrow {\r
+ border-width: 11px;\r
+}\r
+.popover > .arrow:after {\r
+ border-width: 10px;\r
+ content: "";\r
+}\r
+.popover.top > .arrow {\r
+ left: 50%;\r
+ margin-left: -11px;\r
+ border-bottom-width: 0;\r
+ border-top-color: #999999;\r
+ border-top-color: rgba(0, 0, 0, 0.25);\r
+ bottom: -11px;\r
+}\r
+.popover.top > .arrow:after {\r
+ content: " ";\r
+ bottom: 1px;\r
+ margin-left: -10px;\r
+ border-bottom-width: 0;\r
+ border-top-color: #ffffff;\r
+}\r
+.popover.right > .arrow {\r
+ top: 50%;\r
+ left: -11px;\r
+ margin-top: -11px;\r
+ border-left-width: 0;\r
+ border-right-color: #999999;\r
+ border-right-color: rgba(0, 0, 0, 0.25);\r
+}\r
+.popover.right > .arrow:after {\r
+ content: " ";\r
+ left: 1px;\r
+ bottom: -10px;\r
+ border-left-width: 0;\r
+ border-right-color: #ffffff;\r
+}\r
+.popover.bottom > .arrow {\r
+ left: 50%;\r
+ margin-left: -11px;\r
+ border-top-width: 0;\r
+ border-bottom-color: #999999;\r
+ border-bottom-color: rgba(0, 0, 0, 0.25);\r
+ top: -11px;\r
+}\r
+.popover.bottom > .arrow:after {\r
+ content: " ";\r
+ top: 1px;\r
+ margin-left: -10px;\r
+ border-top-width: 0;\r
+ border-bottom-color: #ffffff;\r
+}\r
+.popover.left > .arrow {\r
+ top: 50%;\r
+ right: -11px;\r
+ margin-top: -11px;\r
+ border-right-width: 0;\r
+ border-left-color: #999999;\r
+ border-left-color: rgba(0, 0, 0, 0.25);\r
+}\r
+.popover.left > .arrow:after {\r
+ content: " ";\r
+ right: 1px;\r
+ border-right-width: 0;\r
+ border-left-color: #ffffff;\r
+ bottom: -10px;\r
+}\r
+.carousel {\r
+ position: relative;\r
+}\r
+.carousel-inner {\r
+ position: relative;\r
+ overflow: hidden;\r
+ width: 100%;\r
+}\r
+.carousel-inner > .item {\r
+ display: none;\r
+ position: relative;\r
+ -webkit-transition: 0.6s ease-in-out left;\r
+ transition: 0.6s ease-in-out left;\r
+}\r
+.carousel-inner > .item > img,\r
+.carousel-inner > .item > a > img {\r
+ line-height: 1;\r
+}\r
+.carousel-inner > .active,\r
+.carousel-inner > .next,\r
+.carousel-inner > .prev {\r
+ display: block;\r
+}\r
+.carousel-inner > .active {\r
+ left: 0;\r
+}\r
+.carousel-inner > .next,\r
+.carousel-inner > .prev {\r
+ position: absolute;\r
+ top: 0;\r
+ width: 100%;\r
+}\r
+.carousel-inner > .next {\r
+ left: 100%;\r
+}\r
+.carousel-inner > .prev {\r
+ left: -100%;\r
+}\r
+.carousel-inner > .next.left,\r
+.carousel-inner > .prev.right {\r
+ left: 0;\r
+}\r
+.carousel-inner > .active.left {\r
+ left: -100%;\r
+}\r
+.carousel-inner > .active.right {\r
+ left: 100%;\r
+}\r
+.carousel-control {\r
+ position: absolute;\r
+ top: 0;\r
+ left: 0;\r
+ bottom: 0;\r
+ width: 15%;\r
+ opacity: 0.5;\r
+ filter: alpha(opacity=50);\r
+ font-size: 20px;\r
+ color: #ffffff;\r
+ text-align: center;\r
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\r
+}\r
+.carousel-control.left {\r
+ background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0%), color-stop(rgba(0, 0, 0, 0.0001) 100%));\r
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\r
+ background-repeat: repeat-x;\r
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\r
+}\r
+.carousel-control.right {\r
+ left: auto;\r
+ right: 0;\r
+ background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0%), color-stop(rgba(0, 0, 0, 0.5) 100%));\r
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\r
+ background-repeat: repeat-x;\r
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\r
+}\r
+.carousel-control:hover,\r
+.carousel-control:focus {\r
+ outline: none;\r
+ color: #ffffff;\r
+ text-decoration: none;\r
+ opacity: 0.9;\r
+ filter: alpha(opacity=90);\r
+}\r
+.carousel-control .icon-prev,\r
+.carousel-control .icon-next,\r
+.carousel-control .glyphicon-chevron-left,\r
+.carousel-control .glyphicon-chevron-right {\r
+ position: absolute;\r
+ top: 50%;\r
+ z-index: 5;\r
+ display: inline-block;\r
+}\r
+.carousel-control .icon-prev,\r
+.carousel-control .glyphicon-chevron-left {\r
+ left: 50%;\r
+}\r
+.carousel-control .icon-next,\r
+.carousel-control .glyphicon-chevron-right {\r
+ right: 50%;\r
+}\r
+.carousel-control .icon-prev,\r
+.carousel-control .icon-next {\r
+ width: 20px;\r
+ height: 20px;\r
+ margin-top: -10px;\r
+ margin-left: -10px;\r
+ font-family: serif;\r
+}\r
+.carousel-control .icon-prev:before {\r
+ content: '\2039';\r
+}\r
+.carousel-control .icon-next:before {\r
+ content: '\203a';\r
+}\r
+.carousel-indicators {\r
+ position: absolute;\r
+ bottom: 10px;\r
+ left: 50%;\r
+ z-index: 15;\r
+ width: 60%;\r
+ margin-left: -30%;\r
+ padding-left: 0;\r
+ list-style: none;\r
+ text-align: center;\r
+}\r
+.carousel-indicators li {\r
+ display: inline-block;\r
+ width: 10px;\r
+ height: 10px;\r
+ margin: 1px;\r
+ text-indent: -999px;\r
+ border: 1px solid #ffffff;\r
+ border-radius: 10px;\r
+ cursor: pointer;\r
+ background-color: #000 \9;\r
+ background-color: rgba(0, 0, 0, 0);\r
+}\r
+.carousel-indicators .active {\r
+ margin: 0;\r
+ width: 12px;\r
+ height: 12px;\r
+ background-color: #ffffff;\r
+}\r
+.carousel-caption {\r
+ position: absolute;\r
+ left: 15%;\r
+ right: 15%;\r
+ bottom: 20px;\r
+ z-index: 10;\r
+ padding-top: 20px;\r
+ padding-bottom: 20px;\r
+ color: #ffffff;\r
+ text-align: center;\r
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\r
+}\r
+.carousel-caption .btn {\r
+ text-shadow: none;\r
+}\r
+@media screen and (min-width: 768px) {\r
+ .carousel-control .glyphicons-chevron-left,\r
+ .carousel-control .glyphicons-chevron-right,\r
+ .carousel-control .icon-prev,\r
+ .carousel-control .icon-next {\r
+ width: 30px;\r
+ height: 30px;\r
+ margin-top: -15px;\r
+ margin-left: -15px;\r
+ font-size: 30px;\r
+ }\r
+ .carousel-caption {\r
+ left: 20%;\r
+ right: 20%;\r
+ padding-bottom: 30px;\r
+ }\r
+ .carousel-indicators {\r
+ bottom: 20px;\r
+ }\r
+}\r
+.clearfix:before,\r
+.clearfix:after,\r
+.container:before,\r
+.container:after,\r
+.container-fluid:before,\r
+.container-fluid:after,\r
+.row:before,\r
+.row:after,\r
+.form-horizontal .form-group:before,\r
+.form-horizontal .form-group:after,\r
+.btn-toolbar:before,\r
+.btn-toolbar:after,\r
+.btn-group-vertical > .btn-group:before,\r
+.btn-group-vertical > .btn-group:after,\r
+.nav:before,\r
+.nav:after,\r
+.navbar:before,\r
+.navbar:after,\r
+.navbar-header:before,\r
+.navbar-header:after,\r
+.navbar-collapse:before,\r
+.navbar-collapse:after,\r
+.pager:before,\r
+.pager:after,\r
+.panel-body:before,\r
+.panel-body:after,\r
+.modal-footer:before,\r
+.modal-footer:after {\r
+ content: " ";\r
+ display: table;\r
+}\r
+.clearfix:after,\r
+.container:after,\r
+.container-fluid:after,\r
+.row:after,\r
+.form-horizontal .form-group:after,\r
+.btn-toolbar:after,\r
+.btn-group-vertical > .btn-group:after,\r
+.nav:after,\r
+.navbar:after,\r
+.navbar-header:after,\r
+.navbar-collapse:after,\r
+.pager:after,\r
+.panel-body:after,\r
+.modal-footer:after {\r
+ clear: both;\r
+}\r
+.center-block {\r
+ display: block;\r
+ margin-left: auto;\r
+ margin-right: auto;\r
+}\r
+.pull-right {\r
+ float: right !important;\r
+}\r
+.pull-left {\r
+ float: left !important;\r
+}\r
+.hide {\r
+ display: none !important;\r
+}\r
+.show {\r
+ display: block !important;\r
+}\r
+.invisible {\r
+ visibility: hidden;\r
+}\r
+.text-hide {\r
+ font: 0/0 a;\r
+ color: transparent;\r
+ text-shadow: none;\r
+ background-color: transparent;\r
+ border: 0;\r
+}\r
+.hidden {\r
+ display: none !important;\r
+ visibility: hidden !important;\r
+}\r
+.affix {\r
+ position: fixed;\r
+}\r
+@-ms-viewport {\r
+ width: device-width;\r
+}\r
+.visible-xs,\r
+.visible-sm,\r
+.visible-md,\r
+.visible-lg {\r
+ display: none !important;\r
+}\r
+@media (max-width: 767px) {\r
+ .visible-xs {\r
+ display: block !important;\r
+ }\r
+ table.visible-xs {\r
+ display: table;\r
+ }\r
+ tr.visible-xs {\r
+ display: table-row !important;\r
+ }\r
+ th.visible-xs,\r
+ td.visible-xs {\r
+ display: table-cell !important;\r
+ }\r
+}\r
+@media (min-width: 768px) and (max-width: 991px) {\r
+ .visible-sm {\r
+ display: block !important;\r
+ }\r
+ table.visible-sm {\r
+ display: table;\r
+ }\r
+ tr.visible-sm {\r
+ display: table-row !important;\r
+ }\r
+ th.visible-sm,\r
+ td.visible-sm {\r
+ display: table-cell !important;\r
+ }\r
+}\r
+@media (min-width: 992px) and (max-width: 1199px) {\r
+ .visible-md {\r
+ display: block !important;\r
+ }\r
+ table.visible-md {\r
+ display: table;\r
+ }\r
+ tr.visible-md {\r
+ display: table-row !important;\r
+ }\r
+ th.visible-md,\r
+ td.visible-md {\r
+ display: table-cell !important;\r
+ }\r
+}\r
+@media (min-width: 1200px) {\r
+ .visible-lg {\r
+ display: block !important;\r
+ }\r
+ table.visible-lg {\r
+ display: table;\r
+ }\r
+ tr.visible-lg {\r
+ display: table-row !important;\r
+ }\r
+ th.visible-lg,\r
+ td.visible-lg {\r
+ display: table-cell !important;\r
+ }\r
+}\r
+@media (max-width: 767px) {\r
+ .hidden-xs {\r
+ display: none !important;\r
+ }\r
+}\r
+@media (min-width: 768px) and (max-width: 991px) {\r
+ .hidden-sm {\r
+ display: none !important;\r
+ }\r
+}\r
+@media (min-width: 992px) and (max-width: 1199px) {\r
+ .hidden-md {\r
+ display: none !important;\r
+ }\r
+}\r
+@media (min-width: 1200px) {\r
+ .hidden-lg {\r
+ display: none !important;\r
+ }\r
+}\r
+.visible-print {\r
+ display: none !important;\r
+}\r
+@media print {\r
+ .visible-print {\r
+ display: block !important;\r
+ }\r
+ table.visible-print {\r
+ display: table;\r
+ }\r
+ tr.visible-print {\r
+ display: table-row !important;\r
+ }\r
+ th.visible-print,\r
+ td.visible-print {\r
+ display: table-cell !important;\r
+ }\r
+}\r
+@media print {\r
+ .hidden-print {\r
+ display: none !important;\r
+ }\r
+}\r
+ \r
--- /dev/null
+<div class='container-fluid'>
+ <div class='page-header'>
+ <h2><entity-signature mentity='mentity.intro'/></h2>
+ <entity-link mentity='mentity.mpackage' /> :: {{mentity.name}}
+ </div>
+
+ <ul class='nav nav-tabs'>
+ <li role='presentation' class='active'>
+ <a data-toggle='tab' data-target='#doc'>
+ <span class='glyphicon glyphicon-book'/> Doc
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' data-target='#all_props'>
+ <span class='glyphicon glyphicon-tags'/> All properties
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' role='tab' data-target='#linearization' aria-controls='linearization' ng-click='entityCtrl.loadEntityLinearization()'>
+ <span class='glyphicon glyphicon-arrow-down'/> Linearization
+ </a>
+ </li>
+ </ul>
+
+ <div class='tab-content'>
+ <div role='tabpanel' class='tab-pane fade in active' id='doc'>
+ <entity-doc mentity='mentity.intro'/>
+
+ <entity-list list-title='Parents'
+ list-entities='mentity.parents'
+ list-object-filter='{}' />
+
+ <entity-list list-title='Constructors'
+ list-entities='mentity.all_mproperties'
+ list-object-filter='{is_init: true}' />
+
+ <entity-list list-title='Introduced properties'
+ list-entities='mentity.intro_mproperties'
+ list-object-filter='{is_init: "!true"}' />
+
+ <entity-list list-title='Redefined properties'
+ list-entities='mentity.redef_mproperties'
+ list-object-filter='{is_init: "!true"}' />
+ </div>
+ <div role='tabpanel' class='tab-pane fade' id='all_props'>
+ <entity-list list-title='All properties' list-entities='mentity.all_mproperties'
+ list-object-filter='{}' />
+ </div>
+ <div role='tabpanel' class='tab-pane fade' id='linearization'>
+ <entity-linearization
+ list-title='Class definitions'
+ list-entities='linearization'
+ list-focus='mentity.intro' />
+ </div>
+ </div>
+</div>
--- /dev/null
+<div class='container-fluid' ng-init='entityCtrl.loadEntityLinearization()'>
+ <div class='page-header'>
+ <h2><entity-signature mentity='mentity'/></h2>
+ <entity-link mentity='mentity.mpackage' />
+ :: <entity-link mentity='mentity.mmodule' />
+ :: {{mentity.name}}
+ </div>
+
+ <ul class='nav nav-tabs' role='tablist'>
+ <li role='presentation' class='warning'>
+ <a ng-href='{{mentity.mclass.web_url}}'>
+ <span class='glyphicon glyphicon-chevron-left'/> Go to class
+ </a>
+ </li>
+ <li role='presentation' class='active'>
+ <a data-toggle='tab' role='tab' data-target='#linearization' aria-controls='linearization'>
+ <span class='glyphicon glyphicon-arrow-down'/> Linearization
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' data-target='#code' ng-click="entityCtrl.loadEntityCode()">
+ <span class='glyphicon glyphicon-console'/> Code
+ </a>
+ </li>
+ </ul>
+
+ <div class='tab-content'>
+ <div role='tabpanel' class='tab-pane fade in active' id='linearization'>
+ <entity-linearization
+ list-title='Class definitions'
+ list-entities='linearization'
+ list-focus='mentity' />
+ </div>
+ <div role='tabpanel' class='tab-pane fade' id='code'>
+ <div class='card'>
+ <div class='card-body'>
+ <pre ng-bind-html='code' />
+ <entity-location mentity='mentity' />
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
--- /dev/null
+<div class='container-fluid'>
+ <div class='page-header'>
+ <h2><entity-signature mentity='mentity' /></h2>
+ <entity-link mentity='mentity.mpackage' /> :: {{mentity.name}}
+ </div>
+
+ <ul class='nav nav-tabs'>
+ <li class='active'>
+ <a data-toggle='tab' data-target='#doc'>
+ <span class='glyphicon glyphicon-book'/> Doc
+ </a>
+ </li>
+ </ul>
+
+ <div class='tab-content'>
+ <div class='tab-pane fade in active' id='doc'>
+ <entity-doc mentity='mentity'/>
+
+ <entity-list list-title='Parent group' list-entities='[mentity.parent]'
+ list-object-filter='{}' ng-if='mentity.parent' />
+
+ <entity-list list-title='Subgroups' list-entities='mentity.mgroups'
+ list-object-filter='{}' />
+
+ <entity-list list-title='Modules' list-entities='mentity.mmodules'
+ list-object-filter='{}' />
+ </div>
+ </div>
+ </div>
+</div>
--- /dev/null
+<div class='container-fluid'>
+ <div class='page-header'>
+ <h2>Welcome to NitWeb!</h2>
+ <p class='text-muted'>The Nit knowledge base.</p>
+ </div>
+
+ <ul class='nav nav-tabs' role='tablist'>
+ <li role='presentation' class='active'>
+ <a data-toggle='tab' role='tab' data-target='#highlighted' aria-controls='highlighted'>
+ <span class='glyphicon glyphicon-book'/> Highlighed
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' role='tab' data-target='#required' aria-controls='required'
+ ng-click='indexCtrl.loadMostRequired()'>
+ <span class='glyphicon glyphicon-book'/> Most required
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' role='tab' data-target='#bytags' aria-controls='bytags'
+ ng-click='indexCtrl.loadByTags()'>
+ <span class='glyphicon glyphicon-book'/> By tags
+ </a>
+ </li>
+ </ul>
+ <table class='table'>
+ <tr>
+ <td ng-repeat='(key, value) in stats'>
+ <h5><strong>{{value}}</strong> <span>{{key}}</span></h5>
+ </td>
+ </tr>
+ </table>
+
+ <div class='container-fluid'>
+ <div class='col-xs-9'>
+ <div class='tab-content'>
+ <div role='tabpanel' class='tab-pane fade in active' id='highlighted'>
+ <entity-list list-title='Highlighted packages'
+ list-entities='highlighted'
+ list-object-filter='{}' />
+ </div>
+ <div role='tabpanel' class='tab-pane fade' id='required'>
+ <entity-list list-title='Most required'
+ list-entities='required'
+ list-object-filter='{}' />
+ </div>
+ <div role='tabpanel' class='tab-pane fade' id='bytags'>
+ <h3>Tags</h3>
+ <div class='container-fluid'>
+ <div class='col-xs-3' ng-repeat='(tag, packages) in bytags'>
+ <span class='badge'>{{packages.length}}</span>
+ <a ng-click='indexCtrl.scrollTo(tag)'>{{tag}}</a>
+ </div>
+ </div>
+ <div ng-repeat='(tag, packages) in bytags'>
+ <entity-list list-id='{{tag}}' list-title='{{tag}}'
+ list-entities='packages'
+ list-object-filter='{}' />
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class='col-xs-3'>
+ <contributor-list list-title='Maintainers'
+ list-contributors='contributors.maintainers' />
+ <contributor-list list-title='Contributors'
+ list-contributors='contributors.contributors' />
+ </div>
+ </div>
+</div>
--- /dev/null
+<div class='container-fluid'>
+ <div class='page-header'>
+ <h2><entity-signature mentity='mentity'/></h2>
+ <entity-link mentity='mentity.mpackage' /> :: {{mentity.name}}
+ </div>
+
+ <ul class='nav nav-tabs'>
+ <li role='presentation' class='active'>
+ <a data-toggle='tab' data-target='#doc'>
+ <span class='glyphicon glyphicon-book'/> Doc
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' data-target='#code' ng-click="entityCtrl.loadEntityCode()">
+ <span class='glyphicon glyphicon-console'/> Code
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' data-target='#defs' ng-click="entityCtrl.loadEntityDefs()">
+ <span class='glyphicon glyphicon-asterisk'/> Class definitions
+ </a>
+ </li>
+ </ul>
+
+ <div class='tab-content'>
+ <div role='tabpanel' class='tab-pane fade in active' id='doc'>
+ <entity-doc mentity='mentity'/>
+
+ <entity-list list-title='Imported modules' list-entities='mentity.imports'
+ list-object-filter='{}' />
+
+ <entity-list list-title='Introduced classes' list-entities='mentity.intro_mclasses'
+ list-object-filter='{}' />
+
+ <entity-list list-title='Class redefinitions' list-entities='mentity.redef_mclassdefs'
+ list-object-filter='{}' />
+
+ </div>
+ <div class='tab-pane fade' id='code'>
+ <div class='card'>
+ <div class='card-body'>
+ <pre ng-bind-html='code' />
+ <entity-location mentity='mentity' />
+ </div>
+ </div>
+ </div>
+ <div role='tabpanel' class='tab-pane fade' id='defs'>
+ <entity-list list-title='Class definitions' list-entities='defs'
+ list-object-filter='{}' />
+ </div>
+ </div>
+</div>
--- /dev/null
+<div class='container-fluid'>
+ <div class='page-header'>
+ <h2><entity-signature mentity='mentity'/></h2>
+ </div>
+
+ <ul class='nav nav-tabs' role='tablist'>
+ <li role='presentation' class='active'>
+ <a data-toggle='tab' role='tab' data-target='#doc' aria-controls="doc">
+ <span class='glyphicon glyphicon-book'/> Doc
+ </a>
+ </li>
+ </ul>
+
+ <div class='tab-content'>
+ <div role='tabpanel' class='tab-pane fade in active' id='doc'>
+ <entity-doc mentity='mentity'/>
+
+ <entity-list list-title='Groups' list-entities='mentity.mgroups'
+ list-object-filter='{}' />
+ </div>
+ </div>
+</div>
--- /dev/null
+<div class='container-fluid' ng-init='entityCtrl.loadEntityLinearization()'>
+ <div class='page-header'>
+ <h2><entity-signature mentity='mentity'/></h2>
+ <entity-link mentity='mentity.mpackage' />
+ :: <entity-link mentity='mentity.mmodule' />
+ :: <entity-link mentity='mentity.mclassdef' />
+ :: {{mentity.name}}
+ </div>
+
+ <ul class='nav nav-tabs'>
+ <li role='presentation' class='warning'>
+ <a href='{{mentity.mproperty.web_url}}'>
+ <span class='glyphicon glyphicon-chevron-left'/> Go to property
+ </a>
+ </li>
+ <li role='presentation' class='active'>
+ <a data-toggle='tab' role='tab' data-target='#linearization' aria-controls='linearization'>
+ <span class='glyphicon glyphicon-arrow-down'/> Linearization
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' data-target='#code' ng-click="entityCtrl.loadEntityCode()">
+ <span class='glyphicon glyphicon-console'/> Code
+ </a>
+ </li>
+ </ul>
+
+ <div class='tab-content'>
+ <div role='tabpanel' class='tab-pane fade in active' id='linearization'>
+ <entity-linearization
+ list-title='Class definitions'
+ list-entities='linearization'
+ list-focus='mentity' />
+ </div>
+ <div role='tabpanel' class='tab-pane fade' id='code'>
+ <div class='card'>
+ <div class='card-body'>
+ <pre ng-bind-html='code' />
+ <entity-location mentity='mentity' />
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
--- /dev/null
+<div class='container-fluid'>
+
+ <div class='page-header'>
+ <h2><entity-signature mentity='mentity.intro'/></h2>
+ <entity-link mentity='mentity.mpackage' />
+ :: <entity-link mentity='mentity.intro_mclassdef' />
+ :: {{mentity.name}}
+ </div>
+
+ <ul class='nav nav-tabs'>
+ <li role='presentation' class='active'>
+ <a data-toggle='tab' data-target='#doc'>
+ <span class='glyphicon glyphicon-book'/> Doc
+ </a>
+ </li>
+ <li role='presentation'>
+ <a data-toggle='tab' role='tab' data-target='#linearization' aria-controls='linearization' ng-click='entityCtrl.loadEntityLinearization()'>
+ <span class='glyphicon glyphicon-arrow-down'/> Linearization
+ </a>
+ </li>
+ </ul>
+
+ <div class='tab-content'>
+ <div role='tabpanel' class='tab-pane fade in active' id='doc'>
+ <entity-doc mentity='mentity.intro'/>
+ </div>
+ <div role='tabpanel' class='tab-pane fade' id='linearization'>
+ <entity-linearization
+ list-title='Class definitions'
+ list-entities='linearization'
+ list-focus='mentity.intro' />
+ </div>
+ </div>
+</div>
var doc_score = 0.0
for g in mpackage.mgroups do
mmodules += g.mmodules.length
- entity_score += 1.0
- if g.mdoc != null then doc_score += 1.0
+ var gs = 1.0
+ entity_score += gs
+ if g.mdoc != null then doc_score += gs
for m in g.mmodules do
var source = m.location.file
if source != null then
loc += file.line_starts.length - 1
end
end
- entity_score += 1.0
- if m.mdoc != null then doc_score += 1.0
+ var ms = gs
+ if m.is_test_suite then ms /= 100.0
+ entity_score += ms
+ if m.mdoc != null then doc_score += ms else ms /= 10.0
for cd in m.mclassdefs do
- var s = 0.2
- if not cd.is_intro then s /= 10.0
- if not cd.mclass.visibility <= private_visibility then s /= 10.0
- entity_score += s
- if cd.mdoc != null then doc_score += s
+ var cs = ms * 0.2
+ if not cd.is_intro then cs /= 100.0
+ if not cd.mclass.visibility <= private_visibility then cs /= 100.0
+ entity_score += cs
+ if cd.mdoc != null then doc_score += cs
mclasses += 1
for pd in cd.mpropdefs do
- s = 0.1
- if not pd.is_intro then s /= 10.0
- if not pd.mproperty.visibility <= private_visibility then s /= 10.0
- entity_score += s
- if pd.mdoc != null then doc_score += s
+ var ps = ms * 0.1
+ if not pd.is_intro then ps /= 100.0
+ if not pd.mproperty.visibility <= private_visibility then ps /= 100.0
+ entity_score += ps
+ if pd.mdoc != null then doc_score += ps
if not pd isa MMethodDef then continue
mmethods += 1
end
var mgrouppath = path.join_path("..").simplify_path
var mgroup = identify_group(mgrouppath)
+ if mgroup != null then
+ var mpackage = mgroup.mpackage
+ if not mpackage.accept(path) then
+ mgroup = null
+ toolcontext.info("module `{path}` excluded from package `{mpackage}`", 2)
+ end
+ end
if mgroup == null then
# singleton package
var loc = new Location.opaque_file(path)
if not stopper.file_exists then
# Recursively get the parent group
parent = identify_group(parentpath)
+ if parent != null then do
+ var mpackage = parent.mpackage
+ if not mpackage.accept(dirpath) then
+ toolcontext.info("directory `{dirpath}` excluded from package `{mpackage}`", 2)
+ parent = null
+ end
+ end
if parent == null then
# Parent is not a group, thus we are not a group either
mgroups[rdp] = null
if decl != null then
var decl_name = decl.n_name.n_id.text
if decl_name != mmodule.name then
- error(decl.n_name, "Error: module name mismatch; declared {decl_name} file named {mmodule.name}.")
+ warning(decl.n_name, "module-name-mismatch", "Error: module name mismatch; declared {decl_name} file named {mmodule.name}.")
end
end
#
# Some packages, like stand-alone packages or virtual packages have no `ini` file associated.
var ini: nullable ConfigTree = null
+
+ # Array of relative source paths excluded according to the `source.exclude` key of the `ini`
+ var excludes: nullable Array[String] is lazy do
+ var ini = self.ini
+ if ini == null then return null
+ var exclude = ini["source.exclude"]
+ if exclude == null then return null
+ var excludes = exclude.split(":")
+ return excludes
+ end
+
+ # Does the source inclusion/inclusion rules of the package `ini` accept such path?
+ fun accept(filepath: String): Bool
+ do
+ var excludes = self.excludes
+ if excludes != null then
+ var relpath = root.filepath.relpath(filepath)
+ if excludes.has(relpath) then return false
+ end
+ return true
+ end
end
redef class MGroup
fun collect_modifiers: Array[String] do
return new Array[String]
end
+
+ # Collect `self` linearization anchored on `mainmodule`.
+ fun collect_linearization(mainmodule: MModule): nullable Array[MEntity] do
+ return null
+ end
end
redef class MPackage
redef fun collect_modifiers do return intro.collect_modifiers
+ redef fun collect_linearization(mainmodule) do
+ var mclassdefs = self.mclassdefs.to_a
+ mainmodule.linearize_mclassdefs(mclassdefs)
+ return mclassdefs
+ end
+
# Collect direct parents of `self` with `visibility >= to min_visibility`.
fun collect_parents(view: ModelView): Set[MClass] do
var res = new HashSet[MClass]
redef class MClassDef
+ redef fun collect_linearization(mainmodule) do
+ var mclassdefs = new Array[MClassDef]
+ for mclassdef in in_hierarchy.as(not null).greaters do
+ if mclassdef.mclass == self.mclass then mclassdefs.add mclassdef
+ end
+ mainmodule.linearize_mclassdefs(mclassdefs)
+ return mclassdefs
+ end
+
# Collect mpropdefs in 'self' with `visibility >= min_visibility`.
fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
var res = new HashSet[MPropDef]
redef class MProperty
redef fun collect_modifiers do return intro.collect_modifiers
+
+ redef fun collect_linearization(mainmodule) do
+ var mpropdefs = self.mpropdefs.to_a
+ mainmodule.linearize_mpropdefs(mpropdefs)
+ return mpropdefs
+ end
end
redef class MPropDef
end
return res
end
+
+ redef fun collect_linearization(mainmodule) do
+ var mpropdefs = new Array[MPropDef]
+ var mentity = self
+ while not mentity.is_intro do
+ mpropdefs.add mentity
+ mentity = mentity.lookup_next_definition(mainmodule, mentity.mclassdef.bound_mtype)
+ end
+ mpropdefs.add mentity
+ mainmodule.linearize_mpropdefs(mpropdefs)
+ return mpropdefs
+ end
end
var name = qid.n_id.text
var qname = qid.full_name
+ if bad_class_names[mmodule].has(qname) then
+ error(qid, "Error: class `{qname}` not found in module `{mmodule}`.")
+ return
+ end
+ bad_class_names[mmodule].add(qname)
+
var all_classes = model.get_mclasses_by_name(name)
var hints = new Array[String]
error(qid, "Error: class `{qname}` not found in module `{mmodule}`.")
end
+ # List of already reported bad class names.
+ # Used to not perform and repeat hints again and again.
+ private var bad_class_names = new MultiHashMap[MModule, String]
+
# Return the static type associated to the node `ntype`.
# `mmodule` and `mclassdef` is the context where the call is made (used to understand formal types)
# In case of problem, an error is displayed on `ntype` and null is returned.
modelbuilder.load_rt_module(parent, amodule, "-")
mmodules = [amodule.mmodule.as(not null)]
+else if progname == "-" then
+ var content = stdin.read_all
+ var amodule = toolcontext.parse_module(content)
+ toolcontext.check_errors
+ modelbuilder.load_rt_module(null, amodule, "-")
+ mmodules = [amodule.mmodule.as(not null)]
else
mmodules = modelbuilder.parse([progname])
end
# Get files or groups
var args = tc.option_context.rest
+var mmodules
if opt_no_parse.value then
- modelbuilder.scan_full(args)
+ mmodules = modelbuilder.scan_full(args)
else
- modelbuilder.parse_full(args)
+ mmodules = modelbuilder.parse_full(args)
+end
+var mpackages = new Set[MPackage]
+for m in mmodules do
+ var p = m.mpackage
+ if p != null then mpackages.add p
end
# Scan packages and compute information
end
end
-if not opt_no_git.value then for p in model.mpackages do
+if not opt_no_git.value then for p in mpackages do
catalog.git_info(p)
end
# PAGES
-for p in model.mpackages do
+for p in mpackages do
# print p
var f = "p/{p.name}.html"
catalog.package_page(p)
if catalog.deps.not_empty then
index.add "<h2>Most Required</h2>\n"
var reqs = new Counter[MPackage]
- for p in model.mpackages do
+ for p in mpackages do
reqs[p] = catalog.deps[p].smallers.length - 1
end
index.add catalog.list_best(reqs)
<div class="sidebar">
<h3>Stats</h3>
<ul class="box">
-<li>{{{model.mpackages.length}}} packages</li>
+<li>{{{mpackages.length}}} packages</li>
<li>{{{catalog.maint2proj.length}}} maintainers</li>
<li>{{{catalog.contrib2proj.length}}} contributors</li>
<li>{{{catalog.tag2proj.length}}} tags</li>
page.more_head.add "<title>Projets of Nit</title>"
page.add """<div class="content">\n<h1>People of Nit</h1>\n"""
page.add "<h2>Table of Projets</h2>\n"
-page.add catalog.table_packages(model.mpackages)
+page.add catalog.table_packages(mpackages.to_a)
page.add "</div>\n"
page.write_to_file(out/"table.html")
var pa = mp.mgroup
while pa != null and not pa.is_interesting do pa = pa.parent
ot.add(pa, mp)
- if pa != null then mgroups.add pa
+ while pa != null do
+ mgroups.add pa
+ pa = pa.parent
+ end
end
for g in mgroups do
var pa = g.parent
var toolcontext = new ToolContext
-toolcontext.option_context.add_option(toolcontext.opt_full, toolcontext.opt_output, toolcontext.opt_dir, toolcontext.opt_noact, toolcontext.opt_pattern, toolcontext.opt_file, toolcontext.opt_gen_unit, toolcontext.opt_gen_force, toolcontext.opt_gen_private, toolcontext.opt_gen_show, toolcontext.opt_nitc)
+toolcontext.option_context.add_option(toolcontext.opt_full, toolcontext.opt_output, toolcontext.opt_dir, toolcontext.opt_noact, toolcontext.opt_pattern, toolcontext.opt_autosav, toolcontext.opt_gen_unit, toolcontext.opt_gen_force, toolcontext.opt_gen_private, toolcontext.opt_gen_show, toolcontext.opt_nitc)
toolcontext.tooldescription = "Usage: nitunit [OPTION]... <file.nit>...\nExecutes the unit tests from Nit source files."
toolcontext.process_options(args)
print "Option --pattern cannot be used with --gen-suite"
exit(0)
end
- if toolcontext.opt_file.value != null then
- print "Option --target-file cannot be used with --gen-suite"
- exit(0)
- end
else
if toolcontext.opt_gen_force.value then
print "Option --force must be used with --gen-suite"
for m in mmodules do
page.add modelbuilder.test_markdown(m)
- page.add modelbuilder.test_unit(m)
+ var ts = modelbuilder.test_unit(m)
+ if ts != null then page.add ts
end
var file = toolcontext.opt_output.value
if file == null then file = "nitunit.xml"
page.write_to_file(file)
-# print docunits results
-print "DocUnits:"
-if modelbuilder.unit_entities == 0 then
- print "No doc units found"
-else if modelbuilder.failed_entities == 0 and not toolcontext.opt_noact.value then
- print "DocUnits Success"
+
+# Print results
+printn "Docunits: Entities: {modelbuilder.total_entities}; Documented ones: {modelbuilder.doc_entities}; With nitunits: {modelbuilder.unit_entities}"
+if modelbuilder.unit_entities == 0 or toolcontext.opt_noact.value then
+ print ""
+else
+ printn "; Failures: "
+ var cpt = modelbuilder.failed_entities
+ if toolcontext.opt_no_color.value then
+ print cpt
+ else if cpt == 0 then
+ print "0".green.bold
+ else
+ print cpt.to_s.red.bold
+ end
end
-print "Entities: {modelbuilder.total_entities}; Documented ones: {modelbuilder.doc_entities}; With nitunits: {modelbuilder.unit_entities}; Failures: {modelbuilder.failed_entities}"
-# print testsuites results
-print "\nTestSuites:"
-if modelbuilder.total_tests == 0 then
- print "No test cases found"
-else if modelbuilder.failed_tests == 0 and not toolcontext.opt_noact.value then
- print "TestSuites Success"
+printn "Test suites: Classes: {modelbuilder.total_classes}; Test Cases: {modelbuilder.total_tests}"
+if modelbuilder.total_tests == 0 or toolcontext.opt_noact.value then
+ print ""
+else
+ printn "; Failures: "
+ var cpt = modelbuilder.failed_tests
+ if toolcontext.opt_no_color.value then
+ print cpt
+ else if cpt == 0 then
+ print "0".green.bold
+ else
+ print cpt.to_s.red.bold
+ end
end
-print "Class suites: {modelbuilder.total_classes}; Test Cases: {modelbuilder.total_tests}; Failures: {modelbuilder.failed_tests}"
+
+var total = modelbuilder.unit_entities + modelbuilder.total_tests
+var fail = modelbuilder.failed_entities + modelbuilder.failed_tests
+if toolcontext.opt_noact.value then
+ # nothing
+else if total == 0 then
+ var head = "[NOTHING]"
+ if not toolcontext.opt_no_color.value then
+ head = head.yellow
+ end
+ print "{head} No unit tests to execute."
+else if fail == 0 then
+ var head = "[SUCCESS]"
+ if not toolcontext.opt_no_color.value then
+ head = head.green.bold
+ end
+ print "{head} All {total} tests passed."
+else
+ var head = "[FAILURE]"
+ if not toolcontext.opt_no_color.value then
+ head = head.red.bold
+ end
+ print "{head} {fail}/{total} tests failed."
+
+ print "`{test_dir}` is not removed for investigation."
+ exit 1
+end
+
+test_dir.rmdir
var model = mainmodule.model
var modelbuilder = toolcontext.modelbuilder
+ # Build catalog
+ var catalog = new Catalog(modelbuilder)
+ for mpackage in model.mpackages do
+ catalog.deps.add_node(mpackage)
+ for mgroup in mpackage.mgroups do
+ for mmodule in mgroup.mmodules do
+ for imported in mmodule.in_importation.direct_greaters do
+ var ip = imported.mpackage
+ if ip == null or ip == mpackage then continue
+ catalog.deps.add_edge(mpackage, ip)
+ end
+ end
+ end
+ catalog.git_info(mpackage)
+ catalog.package_page(mpackage)
+ end
+
# Run the server
var host = toolcontext.opt_host.value or else "localhost"
var port = toolcontext.opt_port.value
var app = new App
- app.use("/random", new RandomAction(model))
- app.use("/doc/:namespace", new DocAction(model, modelbuilder))
- app.use("/code/:namespace", new CodeAction(model, modelbuilder))
- app.use("/search/:namespace", new SearchAction(model))
- app.use("/uml/:namespace", new UMLDiagramAction(model, mainmodule))
- app.use("/", new TreeAction(model))
+
+ app.use_before("/*", new RequestClock)
+ app.use("/api", new APIRouter(model, modelbuilder, mainmodule, catalog))
+ app.use("/doc/:namespace", new DocAction(model, mainmodule, modelbuilder))
+ app.use("/*", new StaticHandler(toolcontext.share_dir / "nitweb", "index.html"))
+ app.use_after("/*", new ConsoleLog)
app.listen(host, port.to_i)
end
end
+# Group all api handlers in one router.
+class APIRouter
+ super Router
+
+ # Model to pass to handlers.
+ var model: Model
+
+ # ModelBuilder to pass to handlers.
+ var modelbuilder: ModelBuilder
+
+ # Mainmodule to pass to handlers.
+ var mainmodule: MModule
+
+ # Catalog to pass to handlers.
+ var catalog: Catalog
+
+ init do
+ use("/catalog", new APICatalogRouter(model, mainmodule, catalog))
+ use("/list", new APIList(model, mainmodule))
+ use("/search", new APISearch(model, mainmodule))
+ use("/random", new APIRandom(model, mainmodule))
+ use("/entity/:id", new APIEntity(model, mainmodule))
+ use("/code/:id", new APIEntityCode(model, mainmodule, modelbuilder))
+ use("/uml/:id", new APIEntityUML(model, mainmodule))
+ use("/linearization/:id", new APIEntityLinearization(model, mainmodule))
+ use("/defs/:id", new APIEntityDefs(model, mainmodule))
+ end
+end
+
# build toolcontext
var toolcontext = new ToolContext
var tpl = new Template
tags=devel,cli
maintainer=Jean Privat <jean@pryen.org>
license=Apache-2.0
+[source]
+exclude=parser/parser_abs.nit:parser/.parser-nofact.nit
[upstream]
browse=https://github.com/nitlang/nit/tree/master/src
git=https://github.com/nitlang/nit.git
add_cast(paramtype)
end
+ if mmethoddef.is_abstract then continue
+
var npropdef = modelbuilder.mpropdef2node(mmethoddef)
if npropdef isa AClassdef then
if not check_depth(rt) then continue
#print "{ot}/{t} -> {rt}"
live_types.add(rt)
- todo_types.add(rt)
+ # unshift means a deep-first visit.
+ # So that the `check_depth` limit is reached sooner.
+ todo_types.unshift(rt)
end
end
#print "MType {live_types.length}: {live_types.join(", ")}"
# Working directory for testing.
fun test_dir: String do
var dir = opt_dir.value
- if dir == null then return ".nitunit"
+ if dir == null then return "nitunit.out"
return dir
end
# Show a single-line status to use as a progression.
#
- # Note that the line starts with `'\r'` and is not ended by a `'\n'`.
+ # If `has_progress_bar` is true, then the output is a progress bar.
+ # The printed the line starts with `'\r'` and is not ended by a `'\n'`.
# So it is expected that:
# * no other output is printed between two calls
# * the last `show_unit_status` is followed by a new-line
- fun show_unit_status(name: String, tests: SequenceRead[UnitTest], more_message: nullable String)
+ #
+ # If `has_progress_bar` is false, then only the first and last state is shown
+ fun show_unit_status(name: String, tests: SequenceRead[UnitTest])
do
var esc = 27.code_point.to_s
- var line = "\r{esc}[K* {name} ["
+ var line = "\r\x1B[K==== {name} ["
var done = tests.length
+ var fails = 0
for t in tests do
if not t.is_done then
line += " "
line += ".".green.bold
else
line += "X".red.bold
+ fails += 1
+ end
+ end
+
+ if not has_progress_bar then
+ if done == 0 then
+ print "==== {name} | tests: {tests.length}"
end
+ return
end
- line += "] {done}/{tests.length}"
- if more_message != null then
- line += " " + more_message
+
+ if done < tests.length then
+ line += "] {done}/{tests.length}"
+ else
+ line += "] tests: {tests.length} "
+ if fails == 0 then
+ line += "OK".green.bold
+ else
+ line += "KO: {fails}".red.bold
+ end
end
printn "{line}"
end
+ # Is a progress bar printed?
+ #
+ # true if color (because and non-verbose mode
+ # (because verbose mode messes up with the progress bar).
+ fun has_progress_bar: Bool
+ do
+ return not opt_no_color.value and opt_verbose.value <= 0
+ end
+
+ # Clear the line if `has_progress_bar` (no-op else)
+ fun clear_progress_bar
+ do
+ if has_progress_bar then printn "\r\x1B[K"
+ end
+
+ # Show the full description of the test-case.
+ #
+ # The output honors `--no-color`.
+ #
+ # `more message`, if any, is added after the error message.
+ fun show_unit(test: UnitTest, more_message: nullable String) do
+ print test.to_screen(more_message, not opt_no_color.value)
+ end
end
# A unit test is an elementary test discovered, run and reported by nitunit.
# The location where the error occurred, if it makes sense.
var error_location: nullable Location = null is writable
+ # Additional noteworthy information when a test success.
+ var info: nullable String = null
+
# A colorful `[OK]` or `[KO]`.
- fun status_tag: String do
+ fun status_tag(color: nullable Bool): String do
+ color = color or else true
if not is_done then
return "[ ]"
else if error != null then
- return "[KO]".red.bold
+ var res = "[KO]"
+ if color then res = res.red.bold
+ return res
else
- return "[OK]".green.bold
+ var res = "[OK]"
+ if color then res = res.green.bold
+ return res
end
end
# The full (color) description of the test-case.
#
# `more message`, if any, is added after the error message.
- fun to_screen(more_message: nullable String): String do
+ fun to_screen(more_message: nullable String, color: nullable Bool): String do
+ color = color or else true
var res
var error = self.error
if error != null then
if more_message != null then error += " " + more_message
var loc = error_location or else location
- res = "{status_tag} {full_name}\n {loc.to_s.yellow}: {error}\n{loc.colored_line("1;31")}"
+ if color then
+ res = "{status_tag(color)} {full_name}\n {loc.to_s.yellow}: {error}\n{loc.colored_line("1;31")}"
+ else
+ res = "{status_tag(color)} {full_name}\n {loc}: {error}"
+ end
var output = self.raw_output
if output != null then
res += "\n Output\n\t{output.chomp.replace("\n", "\n\t")}\n"
end
else
- res = "{status_tag} {full_name}"
+ res = "{status_tag(color)} {full_name}"
if more_message != null then res += more_message
+ var info = self.info
+ if info != null then
+ res += "\n {info}"
+ end
end
return res
end
# All extracted docunits
var docunits = new Array[DocUnit]
- fun show_status(more_message: nullable String)
+ fun show_status
do
- toolcontext.show_unit_status(name, docunits, more_message)
+ toolcontext.show_unit_status(name, docunits)
end
fun mark_done(du: DocUnit)
do
du.is_done = true
- show_status(du.full_name + " " + du.status_tag)
+ toolcontext.clear_progress_bar
+ toolcontext.show_unit(du)
+ show_status
end
# Execute all the docunits
return
end
+ # Try to group each nitunit into a single source file to fasten the compilation
var simple_du = new Array[DocUnit]
show_status
for du in docunits do
# Skip existing errors
if du.error != null then
- mark_done(du)
continue
end
var ast = toolcontext.parse_something(du.block)
if ast isa AExpr then
simple_du.add du
+ end
+ end
+ test_simple_docunits(simple_du)
+
+ # Now test them in order
+ for du in docunits do
+ if du.error != null then
+ # Nothing to execute. Conclude
+ else if du.test_file != null then
+ # Already compiled. Execute it.
+ execute_simple_docunit(du)
else
+ # Need to try to compile it, then execute it
test_single_docunit(du)
end
+ mark_done(du)
end
- test_simple_docunits(simple_du)
-
+ # Final status
show_status
print ""
for du in docunits do
- print du.to_screen
- end
-
- for du in docunits do
testsuite.add du.to_xml
end
end
if res != 0 then
# Compilation error.
- # Fall-back to individual modes:
- for du in dus do
- test_single_docunit(du)
- end
+ # They will be executed independently
return
end
+ # Compilation was a success.
+ # Store what need to be executed for each one.
i = 0
for du in dus do
i += 1
- toolcontext.info("Execute doc-unit {du.full_name} in {file} {i}", 1)
- var res2 = toolcontext.safe_exec("{file.to_program_name}.bin {i} >'{file}.out1' 2>&1 </dev/null")
- du.was_exec = true
+ du.test_file = file
+ du.test_arg = i
+ end
+ end
- var content = "{file}.out1".to_path.read_all
- du.raw_output = content
+ # Execute a docunit compiled by `test_single_docunit`
+ fun execute_simple_docunit(du: DocUnit)
+ do
+ var file = du.test_file.as(not null)
+ var i = du.test_arg.as(not null)
+ toolcontext.info("Execute doc-unit {du.full_name} in {file} {i}", 1)
+ var res2 = toolcontext.safe_exec("{file.to_program_name}.bin {i} >'{file}.out1' 2>&1 </dev/null")
+ du.was_exec = true
- if res2 != 0 then
- du.error = "Runtime error in {file} with argument {i}"
- toolcontext.modelbuilder.failed_entities += 1
- end
- mark_done(du)
+ var content = "{file}.out1".to_path.read_all
+ du.raw_output = content
+
+ if res2 != 0 then
+ du.error = "Runtime error in {file} with argument {i}"
+ toolcontext.modelbuilder.failed_entities += 1
end
end
du.error = "Runtime error in {file}"
toolcontext.modelbuilder.failed_entities += 1
end
- mark_done(du)
end
# Create and fill the header of a unit file `file`.
if mmodule != null then
opts.add "-I {mmodule.filepath.dirname}"
end
- var cmd = "{nitc} --ignore-visibility --no-color '{file}' {opts.join(" ")} >'{file}.out1' 2>&1 </dev/null -o '{file}.bin'"
+ var cmd = "{nitc} --ignore-visibility --no-color -q '{file}' {opts.join(" ")} >'{file}.out1' 2>&1 </dev/null -o '{file}.bin'"
var res = toolcontext.safe_exec(cmd)
return res
end
var mdoc = executor.mdoc
assert mdoc != null
- var next_number = 0
+ var next_number = 1
var name = executor.xml_name
if executor.docunits.not_empty and executor.docunits.last.mdoc == mdoc then
next_number = executor.docunits.last.number + 1
- name += "+" + next_number.to_s
+ name += "#" + next_number.to_s
end
var res = new DocUnit(mdoc, next_number, "", executor.xml_classname, name)
# The numbering of self in mdoc (starting with 0)
var number: Int
+ # The generated Nit source file that contains the unit-test
+ #
+ # Note that a same generated file can be used for multiple tests.
+ # See `test_arg` that is used to distinguish them
+ var test_file: nullable String = null
+
+ # The command-line argument to use when executing the test, if any.
+ var test_arg: nullable Int = null
+
redef fun full_name do
var mentity = mdoc.original_mentity
if mentity != null then
- return mentity.full_name
+ var res = mentity.full_name
+ if number > 1 then
+ res += "#{number}"
+ end
+ return res
else
return xml_classname + "." + xml_name
end
fun test_mdoc(mdoc: MDoc): HTMLTag
do
var ts = new HTMLTag("testsuite")
- var file = mdoc.location.to_s
+ var file = mdoc.location.file.filename
toolcontext.info("nitunit: doc-unit file {file}", 2)
private import annotation
redef class ToolContext
- # -- target-file
- var opt_file = new OptionString("Specify test suite location", "-t", "--target-file")
# --pattern
var opt_pattern = new OptionString("Only run test case with name that match pattern", "-p", "--pattern")
+ # --autosav
+ var opt_autosav = new OptionBool("Automatically create/update .res files for black box testing", "--autosav")
end
# Used to test nitunit test files.
# `ModelBuilder` used to parse test files.
var mbuilder: ModelBuilder
- # Parse a file and return the contained `MModule`.
- private fun parse_module_unit(file: String): nullable MModule do
- var mmodule = mbuilder.parse([file]).first
- if mbuilder.get_mmodule_annotation("test_suite", mmodule) == null then return null
- mbuilder.run_phases
- return mmodule
- end
-
- # Compile and execute the test suite for a NitUnit `file`.
- fun test_module_unit(file: String): nullable TestSuite do
+ # Compile and execute `mmodule` as a test suite.
+ fun test_module_unit(mmodule: MModule): TestSuite do
var toolcontext = mbuilder.toolcontext
- var mmodule = parse_module_unit(file)
- # is the module a test_suite?
- if mmodule == null then return null
var suite = new TestSuite(mmodule, toolcontext)
# method to execute before all tests in the module
var before_module = mmodule.before_test
# Test to be executed after the whole test suite.
var after_module: nullable TestCase = null
- fun show_status(more_message: nullable String)
+ fun show_status
do
- toolcontext.show_unit_status("Test-suite of module " + mmodule.full_name, test_cases, more_message)
+ toolcontext.show_unit_status("Test-suite of module " + mmodule.full_name, test_cases)
end
# Execute the test suite
if not before_module == null then before_module.run
for case in test_cases do
case.run
- show_status(case.full_name + " " + case.status_tag)
+ toolcontext.clear_progress_bar
+ toolcontext.show_unit(case)
+ show_status
end
- show_status
- print ""
-
var after_module = self.after_module
if not after_module == null then after_module.run
- for case in test_cases do
- print case.to_screen
- end
+
+ show_status
+ print ""
end
# Write the test unit for `self` in a nit compilable file.
return
end
var include_dir = module_file.filename.dirname
- var cmd = "{nitc} --no-color '{file}.nit' -I {include_dir} -o '{file}.bin' > '{file}.out' 2>&1 </dev/null"
+ var cmd = "{nitc} --no-color -q '{file}.nit' -I {include_dir} -o '{file}.bin' > '{file}.out' 2>&1 </dev/null"
var res = toolcontext.safe_exec(cmd)
var f = new FileReader.open("{file}.out")
var msg = f.read_all
var test_file = test_suite.test_file
var res_name = "{test_file}_{method_name.escape_to_c}"
var res = toolcontext.safe_exec("{test_file}.bin {method_name} > '{res_name}.out1' 2>&1 </dev/null")
- self.raw_output = "{res_name}.out1".to_path.read_all
+ var raw_output = "{res_name}.out1".to_path.read_all
+ self.raw_output = raw_output
# set test case result
if res != 0 then
error = "Runtime Error in file {test_file}.nit"
var mmodule = test_method.mclassdef.mmodule
var file = mmodule.filepath
if file != null then
- var sav = file.dirname / mmodule.name + ".sav" / test_method.name + ".res"
- if sav.file_exists then
+ var tries = [ file.dirname / mmodule.name + ".sav" / test_method.name + ".res",
+ file.dirname / "sav" / test_method.name + ".res" ,
+ file.dirname / test_method.name + ".res" ]
+ var savs = [ for t in tries do if t.file_exists then t ]
+ if savs.length == 1 then
+ var sav = savs.first
toolcontext.info("Diff output with {sav}", 1)
res = toolcontext.safe_exec("diff -u --label 'expected:{sav}' --label 'got:{res_name}.out1' '{sav}' '{res_name}.out1' > '{res_name}.diff' 2>&1 </dev/null")
- if res != 0 then
+ if res == 0 then
+ # OK
+ else if toolcontext.opt_autosav.value then
+ raw_output.write_to_file(sav)
+ info = "Expected output updated: {sav} (--autoupdate)"
+ else
self.raw_output = "Diff\n" + "{res_name}.diff".to_path.read_all
error = "Difference with expected output: diff -u {sav} {res_name}.out1"
toolcontext.modelbuilder.failed_tests += 1
end
- else
- toolcontext.info("No diff: {sav} not found", 2)
+ else if savs.length > 1 then
+ toolcontext.info("Conflicting diffs: {savs.join(", ")}", 1)
+ error = "Conflicting expected output: {savs.join(", ", " and ")} all exist"
+ toolcontext.modelbuilder.failed_tests += 1
+ else if not raw_output.is_empty then
+ toolcontext.info("No diff: {tries.join(", ", " or ")} not found", 1)
+ if toolcontext.opt_autosav.value then
+ var sav = tries.first
+ sav.dirname.mkdir
+ raw_output.write_to_file(sav)
+ info = "Expected output saved: {sav} (--autoupdate)"
+ end
end
end
end
redef class MClassDef
# Is the class a TestClass?
- # i.e. begins with "Test"
+ # i.e. is a subclass of `TestSuite`
private fun is_test: Bool do
var in_hierarchy = self.in_hierarchy
if in_hierarchy == null then return false
# Number of failed tests.
var failed_tests = 0
- # Run NitUnit test file for mmodule (if exists).
- fun test_unit(mmodule: MModule): HTMLTag do
- var ts = new HTMLTag("testsuite")
- toolcontext.info("nitunit: test-suite test_{mmodule}", 2)
- var f = toolcontext.opt_file.value
- var test_file = "test_{mmodule.name}.nit"
- if f != null then
- test_file = f
- else if not test_file.file_exists then
- var module_file = mmodule.location.file
- if module_file == null then
- toolcontext.info("Skip test for {mmodule}, no file found", 2)
- return ts
- end
- var include_dir = module_file.filename.dirname
- test_file = "{include_dir}/{test_file}"
- end
- if not test_file.file_exists then
- toolcontext.info("Skip test for {mmodule}, no file {test_file} found", 2)
- return ts
- end
+ # Run NitUnit test suite for `mmodule` (if it is one).
+ fun test_unit(mmodule: MModule): nullable HTMLTag do
+ # is the module a test_suite?
+ if get_mmodule_annotation("test_suite", mmodule) == null then return null
+ toolcontext.info("nitunit: test-suite {mmodule}", 2)
+
var tester = new NitUnitTester(self)
- var res = tester.test_module_unit(test_file)
- if res == null then
- toolcontext.info("Skip test for {mmodule}, no test suite found", 2)
- return ts
- end
+ var res = tester.test_module_unit(mmodule)
return res.to_xml
end
end
--- /dev/null
+# 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.
+
+module api_catalog
+
+import web_base
+import catalog
+
+# Group all api handlers in one router.
+class APICatalogRouter
+ super Router
+
+ # Model to pass to handlers.
+ var model: Model
+
+ # Mainmodule to pass to handlers.
+ var mainmodule: MModule
+
+ # Catalog to pass to handlers.
+ var catalog: Catalog
+
+ init do
+ use("/highlighted", new APICatalogHighLighted(model, mainmodule, catalog))
+ use("/required", new APICatalogMostRequired(model, mainmodule, catalog))
+ use("/bytags", new APICatalogByTags(model, mainmodule, catalog))
+ use("/contributors", new APICatalogContributors(model, mainmodule, catalog))
+ use("/stats", new APICatalogStats(model, mainmodule, catalog))
+ end
+end
+
+abstract class APICatalogHandler
+ super APIHandler
+
+ var catalog: Catalog
+
+ # List the 10 best packages from `cpt`
+ fun list_best(cpt: Counter[MPackage]): JsonArray do
+ var res = new JsonArray
+ var best = cpt.sort
+ for i in [1..10] do
+ if i > best.length then break
+ res.add best[best.length-i]
+ end
+ return res
+ end
+
+ # List packages by group.
+ fun list_by(map: MultiHashMap[Object, MPackage]): JsonObject do
+ var res = new JsonObject
+ var keys = map.keys.to_a
+ alpha_comparator.sort(keys)
+ for k in keys do
+ var projs = map[k].to_a
+ alpha_comparator.sort(projs)
+ res[k.to_s.html_escape] = new JsonArray.from(projs)
+ end
+ return res
+ end
+end
+
+class APICatalogStats
+ super APICatalogHandler
+
+ redef fun get(req, res) do
+ var obj = new JsonObject
+ obj["packages"] = model.mpackages.length
+ obj["maintainers"] = catalog.maint2proj.length
+ obj["contributors"] = catalog.contrib2proj.length
+ obj["modules"] = catalog.mmodules.sum
+ obj["classes"] = catalog.mclasses.sum
+ obj["methods"] = catalog.mmethods.sum
+ obj["loc"] = catalog.loc.sum
+ res.json obj
+ end
+end
+
+class APICatalogHighLighted
+ super APICatalogHandler
+
+ redef fun get(req, res) do res.json list_best(catalog.score)
+end
+
+class APICatalogMostRequired
+ super APICatalogHandler
+
+ redef fun get(req, res) do
+ if catalog.deps.not_empty then
+ var reqs = new Counter[MPackage]
+ for p in model.mpackages do
+ reqs[p] = catalog.deps[p].smallers.length - 1
+ end
+ res.json list_best(reqs)
+ return
+ end
+ res.json new JsonArray
+ end
+end
+
+class APICatalogByTags
+ super APICatalogHandler
+
+ redef fun get(req, res) do res.json list_by(catalog.tag2proj)
+end
+
+class APICatalogContributors
+ super APICatalogHandler
+
+ redef fun get(req, res) do
+ var obj = new JsonObject
+ obj["maintainers"] = new JsonArray.from(catalog.maint2proj.keys)
+ obj["contributors"] = new JsonArray.from(catalog.contrib2proj.keys)
+ res.json obj
+ end
+end
+
+redef class Person
+ super Jsonable
+
+ redef fun to_json do
+ var obj = new JsonObject
+ obj["name"] = name
+ obj["email"] = email
+ obj["page"] = page
+ obj["hash"] = (email or else "").md5.to_lower
+ return obj.to_json
+ end
+end
--- /dev/null
+# 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.
+
+module model_api
+
+import web_base
+import highlight
+import uml
+
+# List all mentities.
+#
+# MEntities can be filtered on their kind using the `k` parameter.
+# Allowed kinds are `package`, `group`, `module`, `class`, `classdef`, `property`, `propdef`.
+#
+# List size can be limited with the `n` parameter.
+#
+# Example: `GET /list?k=module?n=10`
+class APIList
+ super APIHandler
+
+ # List mentities depending on the `k` kind parameter.
+ fun list_mentities(req: HttpRequest): Array[MEntity] do
+ var k = req.string_arg("k")
+ var mentities = new Array[MEntity]
+ if k == "package" then
+ for mentity in view.mpackages do mentities.add mentity
+ else if k == "group" then
+ for mentity in view.mgroups do mentities.add mentity
+ else if k == "module" then
+ for mentity in view.mmodules do mentities.add mentity
+ else if k == "class" then
+ for mentity in view.mclasses do mentities.add mentity
+ else if k == "classdef" then
+ for mentity in view.mclassdefs do mentities.add mentity
+ else if k == "property" then
+ for mentity in view.mproperties do mentities.add mentity
+ else if k == "propdef" then
+ for mentity in view.mpropdefs do mentities.add mentity
+ else
+ for mentity in view.mentities do mentities.add mentity
+ end
+ return mentities
+ end
+
+ # Limit mentities depending on the `n` parameter.
+ fun limit_mentities(req: HttpRequest, mentities: Array[MEntity]): Array[MEntity] do
+ var n = req.int_arg("n")
+ if n != null then
+ return mentities.sub(0, n)
+ end
+ return mentities
+ end
+
+ redef fun get(req, res) do
+ var mentities = list_mentities(req)
+ mentities = limit_mentities(req, mentities)
+ res.json new JsonArray.from(mentities)
+ end
+end
+
+# Search mentities from a query string.
+#
+# Example: `GET /search?q=Arr`
+class APISearch
+ super APIList
+
+ redef fun list_mentities(req) do
+ var q = req.string_arg("q")
+ var mentities = new Array[MEntity]
+ if q == null then return mentities
+ for mentity in view.mentities do
+ if mentity.name.has_prefix(q) then mentities.add mentity
+ end
+ return mentities
+ end
+end
+
+# Return a random list of MEntities.
+#
+# Example: `GET /random?n=10&k=module`
+class APIRandom
+ super APIList
+
+ # Randomize mentities order.
+ fun randomize_mentities(req: HttpRequest, mentities: Array[MEntity]): Array[MEntity] do
+ var res = mentities.to_a
+ res.shuffle
+ return res
+ end
+
+ redef fun get(req, res) do
+ var mentities = list_mentities(req)
+ mentities = limit_mentities(req, mentities)
+ mentities = randomize_mentities(req, mentities)
+ res.json new JsonArray.from(mentities)
+ end
+end
+
+# Return the JSON representation of a MEntity.
+#
+# Example: `GET /entity/core::Array`
+class APIEntity
+ super APIHandler
+
+ redef fun get(req, res) do
+ var mentity = mentity_from_uri(req, res)
+ if mentity == null then return
+ res.json mentity.api_json(self)
+ end
+end
+
+# Linearize super definitions of a MClassDef or a MPropDef if any.
+#
+# Example: `GET /entity/core::Array/linearization`
+class APIEntityLinearization
+ super APIHandler
+
+ redef fun get(req, res) do
+ var mentity = mentity_from_uri(req, res)
+ if mentity == null then
+ res.error 404
+ return
+ end
+ var lin = mentity.collect_linearization(mainmodule)
+ if lin == null then
+ res.error 404
+ return
+ end
+ res.json new JsonArray.from(lin)
+ end
+end
+
+# List definitions of a MEntity.
+#
+# Example: `GET /defs/core::Array`
+class APIEntityDefs
+ super APIHandler
+
+ redef fun get(req, res) do
+ var mentity = mentity_from_uri(req, res)
+ var arr = new JsonArray
+ if mentity isa MModule then
+ for mclassdef in mentity.mclassdefs do arr.add mclassdef
+ else if mentity isa MClass then
+ for mclassdef in mentity.mclassdefs do arr.add mclassdef
+ else if mentity isa MClassDef then
+ for mpropdef in mentity.mpropdefs do arr.add mpropdef
+ else if mentity isa MProperty then
+ for mpropdef in mentity.mpropdefs do arr.add mpropdef
+ else
+ res.error 404
+ return
+ end
+ res.json arr
+ end
+end
+
+# Return a UML representation of MEntity.
+#
+# Example: `GET /entity/core::Array/uml`
+class APIEntityUML
+ super APIHandler
+
+ redef fun get(req, res) do
+ var mentity = mentity_from_uri(req, res)
+ var dot
+ if mentity isa MClassDef then mentity = mentity.mclass
+ if mentity isa MClass then
+ var uml = new UMLModel(view, mainmodule)
+ dot = uml.generate_class_uml.write_to_string
+ else if mentity isa MModule then
+ var uml = new UMLModel(view, mentity)
+ dot = uml.generate_package_uml.write_to_string
+ else
+ res.error 404
+ return
+ end
+ res.send render_svg(dot)
+ end
+
+ # Render a `dot` string as a svg image.
+ fun render_svg(dot: String): String do
+ var proc = new ProcessDuplex("dot", "-Tsvg")
+ var svg = proc.write_and_read(dot)
+ proc.close
+ proc.wait
+ return svg
+ end
+end
+
+# Return the source code of MEntity.
+#
+# Example: `GET /entity/core::Array/code`
+class APIEntityCode
+ super APIHandler
+
+ # Modelbuilder used to access sources.
+ var modelbuilder: ModelBuilder
+
+ redef fun get(req, res) do
+ var mentity = mentity_from_uri(req, res)
+ if mentity == null then return
+ var source = render_source(mentity)
+ if source == null then
+ res.error 404
+ return
+ end
+ res.send source
+ end
+
+ # Highlight `mentity` source code.
+ private fun render_source(mentity: MEntity): nullable HTMLTag do
+ var node = modelbuilder.mentity2node(mentity)
+ if node == null then return null
+ var hl = new HighlightVisitor
+ hl.enter_visit node
+ return hl.html
+ end
+end
module web
import web_actions
+import model_api
+import api_catalog
# Display the tree of all loaded mentities.
class TreeAction
- super ModelAction
+ super ModelHandler
redef fun get(req, res) do
var model = init_model_view(req)
end
end
-# Display the list of mentities matching `namespace`.
-class SearchAction
- super ModelAction
-
- # TODO handle more than full namespaces.
- redef fun get(req, res) do
- var namespace = req.param("namespace")
- var model = init_model_view(req)
- var mentity = find_mentity(model, namespace)
- if mentity == null then
- res.error(404)
- return
- end
- if req.is_json_asked then
- res.json(mentity.to_json)
- return
- end
- var view = new HtmlResultPage(namespace or else "null", [mentity])
- res.send_view(view)
- end
-end
-
-# Display a MEntity source code.
-class CodeAction
- super ModelAction
-
- # Modelbuilder used to access sources.
- var modelbuilder: ModelBuilder
-
- redef fun get(req, res) do
- var namespace = req.param("namespace")
- var model = init_model_view(req)
- var mentity = find_mentity(model, namespace)
- if mentity == null then
- res.error(404)
- return
- end
- var view = new HtmlSourcePage(modelbuilder, mentity)
- res.send_view(view)
- end
-end
-
# Display the doc of a MEntity.
class DocAction
- super ModelAction
+ super ModelHandler
# Modelbuilder used to access sources.
var modelbuilder: ModelBuilder
res.error(404)
return
end
- if req.is_json_asked then
- res.json(mentity.to_json)
- return
- end
-
var view = new HtmlDocPage(modelbuilder, mentity)
res.send_view(view)
end
end
-
-# Return an UML diagram for `namespace`.
-class UMLDiagramAction
- super ModelAction
-
- # Mainmodule used for hierarchy flattening.
- var mainmodule: MModule
-
- redef fun get(req, res) do
- var namespace = req.param("namespace")
- var model = init_model_view(req)
- var mentity = find_mentity(model, namespace)
- if mentity == null then
- res.error(404)
- return
- end
-
- var dot
- if mentity isa MClassDef then mentity = mentity.mclass
- if mentity isa MClass then
- var uml = new UMLModel(model, mainmodule)
- dot = uml.generate_class_uml.write_to_string
- else if mentity isa MModule then
- var uml = new UMLModel(model, mentity)
- dot = uml.generate_package_uml.write_to_string
- else
- res.error(404)
- return
- end
- var view = new HtmlDotPage(dot, mentity.as(not null).html_name)
- res.send_view(view)
- end
-end
-
-# Return a random list of MEntities.
-class RandomAction
- super ModelAction
-
- redef fun get(req, res) do
- var n = req.int_arg("n") or else 10
- var k = req.string_arg("k") or else "modules"
- var model = init_model_view(req)
- var mentities: Array[MEntity]
- if k == "modules" then
- mentities = model.mmodules.to_a
- else if k == "classdefs" then
- mentities = model.mclassdefs.to_a
- else
- mentities = model.mpropdefs.to_a
- end
- mentities.shuffle
- mentities = mentities.sub(0, n)
- if req.is_json_asked then
- var json = new JsonArray
- for mentity in mentities do
- json.add mentity.to_json
- end
- res.json(json)
- return
- end
- var view = new HtmlResultPage("random", mentities)
- res.send_view(view)
- end
-end
import model::model_views
import model::model_json
+import doc_down
import popcorn
# Specific nitcorn Action that uses a Model
-class ModelAction
+class ModelHandler
super Handler
# Model to use.
var model: Model
+ # MModule used to flatten model.
+ var mainmodule: MModule
+
# Find the MEntity ` with `full_name`.
fun find_mentity(model: ModelView, full_name: nullable String): nullable MEntity do
if full_name == null then return null
end
end
+# Specific handler for nitweb API.
+abstract class APIHandler
+ super ModelHandler
+
+ # The JSON API does not filter anything by default.
+ #
+ # So we can cache the model view.
+ var view: ModelView is lazy do
+ var view = new ModelView(model)
+ view.min_visibility = private_visibility
+ view.include_fictive = true
+ view.include_empty_doc = true
+ view.include_attribute = true
+ view.include_test_suite = true
+ return view
+ end
+
+ # Try to load the mentity from uri with `/:id`.
+ #
+ # Send 400 if `:id` is null.
+ # Send 404 if no entity is found.
+ # Return null in both cases.
+ fun mentity_from_uri(req: HttpRequest, res: HttpResponse): nullable MEntity do
+ var id = req.param("id")
+ if id == null then
+ res.error 400
+ return null
+ end
+ var mentity = find_mentity(view, id)
+ if mentity == null then
+ res.error 404
+ end
+ return mentity
+ end
+end
+
# A NitView is rendered by an action.
interface NitView
# Renders this view and returns something that can be written to a HTTP response.
fun send_view(view: NitView, status: nullable Int) do send(view.render, status)
end
-redef class HttpRequest
- # Does the client asked for a json formatted response?
- #
- # Checks the URL get parameter `?json=true`.
- fun is_json_asked: Bool do return bool_arg("json") or else false
+redef class MEntity
+
+ # URL to `self` within the web interface.
+ fun web_url: String is abstract
+
+ # URL to `self` within the JSON api.
+ fun api_url: String do return "/api/entity/" / full_name
+
+ redef fun json do
+ var obj = super
+ obj["web_url"] = web_url
+ obj["api_url"] = api_url
+ return obj
+ end
+
+ # Get the full json repesentation of `self` with MEntityRefs resolved.
+ fun api_json(handler: ModelHandler): JsonObject do return json
+end
+
+redef class MEntityRef
+ redef fun json do
+ var obj = super
+ obj["web_url"] = mentity.web_url
+ obj["api_url"] = mentity.api_url
+ obj["name"] = mentity.name
+ obj["mdoc"] = mentity.mdoc_or_fallback
+ obj["visibility"] = mentity.visibility
+ obj["location"] = mentity.location
+ var modifiers = new JsonArray
+ for modifier in mentity.collect_modifiers do
+ modifiers.add modifier
+ end
+ obj["modifiers"] = modifiers
+ return obj
+ end
+end
+
+redef class MDoc
+
+ # Add doc down processing
+ redef fun json do
+ var obj = super
+ obj["synopsis"] = synopsis
+ obj["documentation"] = documentation
+ obj["comment"] = comment
+ obj["html_synopsis"] = html_synopsis.write_to_string
+ obj["html_documentation"] = html_documentation.write_to_string
+ obj["html_comment"] = html_comment.write_to_string
+ return obj
+ end
+end
+
+redef class MPackage
+ redef var web_url = "/package/{full_name}" is lazy
+end
+
+redef class MGroup
+ redef var web_url = "/group/{full_name}" is lazy
+end
+
+redef class MModule
+ redef var web_url = "/module/{full_name}" is lazy
+
+ redef fun api_json(handler) do
+ var obj = super
+ obj["intro_mclassdefs"] = to_mentity_refs(collect_intro_mclassdefs(private_view))
+ obj["redef_mclassdefs"] = to_mentity_refs(collect_redef_mclassdefs(private_view))
+ obj["imports"] = to_mentity_refs(in_importation.direct_greaters)
+ return obj
+ end
+end
+
+redef class MClass
+ redef var web_url = "/class/{full_name}" is lazy
+
+ redef fun api_json(handler) do
+ var obj = super
+ obj["all_mproperties"] = to_mentity_refs(collect_accessible_mproperties(private_view))
+ obj["intro_mproperties"] = to_mentity_refs(collect_intro_mproperties(private_view))
+ obj["redef_mproperties"] = to_mentity_refs(collect_redef_mproperties(private_view))
+ var poset = hierarchy_poset(handler.mainmodule, private_view)
+ obj["parents"] = to_mentity_refs(poset[self].direct_greaters)
+ return obj
+ end
+end
+
+redef class MClassDef
+ redef var web_url = "/classdef/{full_name}" is lazy
+
+ redef fun json do
+ var obj = super
+ obj["intro"] = to_mentity_ref(mclass.intro)
+ obj["mpackage"] = to_mentity_ref(mmodule.mpackage)
+ return obj
+ end
+
+ redef fun api_json(handler) do
+ var obj = super
+ obj["intro_mpropdefs"] = to_mentity_refs(collect_intro_mpropdefs(private_view))
+ obj["redef_mpropdefs"] = to_mentity_refs(collect_redef_mpropdefs(private_view))
+ return obj
+ end
+end
+
+redef class MProperty
+ redef var web_url = "/property/{full_name}" is lazy
+
+ redef fun json do
+ var obj = super
+ obj["intro_mclass"] = to_mentity_ref(intro_mclassdef.mclass)
+ obj["mpackage"] = to_mentity_ref(intro_mclassdef.mmodule.mpackage)
+ return obj
+ end
+end
+
+redef class MPropDef
+ redef var web_url = "/propdef/{full_name}" is lazy
+
+ redef fun json do
+ var obj = super
+ obj["intro"] = to_mentity_ref(mproperty.intro)
+ obj["intro_mclassdef"] = to_mentity_ref(mproperty.intro.mclassdef)
+ obj["mmodule"] = to_mentity_ref(mclassdef.mmodule)
+ obj["mgroup"] = to_mentity_ref(mclassdef.mmodule.mgroup)
+ obj["mpackage"] = to_mentity_ref(mclassdef.mmodule.mpackage)
+ return obj
+ end
+end
+
+redef class MClassType
+ redef var web_url = mclass.web_url is lazy
+end
+
+redef class MNullableType
+ redef var web_url = mtype.web_url is lazy
+end
+
+redef class MParameterType
+ redef var web_url = mclass.web_url is lazy
+end
+
+redef class MVirtualType
+ redef var web_url = mproperty.web_url is lazy
end
end
end
-# Display a search results list.
-class HtmlResultPage
- super NitView
-
- # Initial query.
- var query: String
-
- # Result set
- var results: Array[MEntity]
-
- redef fun render do
- var tpl = new Template
- tpl.add new Header(1, "Results for {query}")
- if results.is_empty then
- tpl.add "<p>No result for {query}.<p>"
- return tpl
- end
- var list = new UnorderedList
- for mentity in results do
- var link = mentity.html_link
- link.text = mentity.html_full_name
- list.add_li new ListItem(link)
- end
- tpl.add list
- return tpl
- end
-end
-
# Display the source for each mentities
class HtmlSourcePage
super NitView
return tpl
end
end
-
-# Display the source for each mentities
-class HtmlDotPage
- super NitView
-
- # Dot to process.
- var dot: Text
-
- # Page title.
- var title: String
-
- redef fun render do
- var tpl = new Template
- tpl.add new Header(1, title)
- tpl.add render_dot
- return tpl
- end
-
- private fun render_dot: String do
- var proc = new ProcessDuplex("dot", "-Tsvg", "-Tcmapx")
- var svg = proc.write_and_read(dot)
- proc.close
- proc.wait
- return svg
- end
-end
mpi
emscripten
ui_test
+readline
--- /dev/null
+# 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 end
+
+interface Object
+ type SELF: Object
+ fun output_class_name is intern
+end
+
+class A[E]
+ new do return new B[E]
+end
+
+class B[E]
+ super A[E]
+
+ fun foo: A[E] do return new A[SELF]
+end
+
+(new B[Object]).foo.output_class_name
-e 'print "hello world"'
-n -e 'print line' test_prog/README.md test_prog/test_prog.nit
test_ffi_c_interpreter.nit
+-
--- /dev/null
+print "Hello!"
nit_args4
nit_args5
nit_args6
+nit_args8
nitvm_args1
nitvm_args3
nitc_args1
-t -r base_simple3.nit project1
-s base_simple3.nit project1
-M base_simple3.nit base_simple_import.nit
--td project1/module3.nit
+-td project1/module3.nit project1/subdir/subdir2/subdir3/submodule.nit
+test_prog --no-color
+test_prog/game/excluded.nit test_prog/game/excluded_dir/more.nit -t --no-color
--no-color -W test_advice_repeated_types.nit
--no-color base_simple3.nit; echo $?
--no-color error_mod_unk.nit; echo $?
+--no-color test_prog
-test_nitunit.nit --no-color -o $WRITE
+test_nitunit.nit test_test_nitunit.nit --no-color -o $WRITE
test_nitunit.nit --gen-suite --only-show
test_nitunit.nit --gen-suite --only-show --private
-test_nitunit2.nit -o $WRITE
+test_nitunit2.nit --no-color -o $WRITE
test_doc2.nit --no-color -o $WRITE
test_nitunit3 --no-color -o $WRITE
test_nitunit_md.md --no-color -o $WRITE
nit_args4
nit_args5
nit_args6
+nit_args8
nitvm_args1
nitvm_args3
nitc_args1
--- /dev/null
+import module0
--- /dev/null
+B[B[Object]]
../lib/core/kernel.nit:431,1--486,3: Error: `kernel$Numeric` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
../lib/core/kernel.nit:492,1--515,3: Error: `kernel$Bool` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
../lib/core/kernel.nit:517,1--599,3: Error: `kernel$Float` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:601,1--702,3: Error: `kernel$Byte` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:704,1--882,3: Error: `kernel$Int` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:884,1--1052,3: Error: `kernel$Char` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:1054,1--1061,3: Error: `kernel$Pointer` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:1063,1--1072,3: Error: `kernel$Task` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:601,1--705,3: Error: `kernel$Byte` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:707,1--885,3: Error: `kernel$Int` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:887,1--1055,3: Error: `kernel$Char` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:1057,1--1064,3: Error: `kernel$Pointer` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:1066,1--1075,3: Error: `kernel$Task` does not specialize `module_0$Object`. Possible duplication of the root class `Object`?
<h3>Quality</h3>
<ul class="box">
<li>28 warnings (63/kloc)</li>
-<li>93% documented</li>
+<li>95% documented</li>
</ul>
<h3>Tags</h3>
<a href="../index.html#tag_test">test</a>, <a href="../index.html#tag_game">game</a><h3>Requirements</h3>
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728)
11
21
31
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728)
11
21
31
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728)
11
21
31
--- /dev/null
+Fatal Error: limitation in the rapidtype analysis engine: a type depth of 256 is too important, the problematic type is `A[A[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[Sys]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`.
--- /dev/null
+Fatal Error: limitation in the rapidtype analysis engine: a type depth of 256 is too important, the problematic type is `A[A[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[Sys]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`.
--- /dev/null
+Fatal Error: limitation in the rapidtype analysis engine: a type depth of 256 is too important, the problematic type is `A[A[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[B[Sys]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]`.
+Empty README for group `excluded` (readme-warning)
+Errors: 0. Warnings: 1.
+MGroupPage excluded
+ # excluded.section
+ ## excluded.intro
+ ## excluded.concerns
+ ## excluded.concern
+ ## excluded.concern
+ ## excluded-.concern
+ ### excluded-.definition
+ #### excluded-.intros_redefs
+ ##### list.group
+ ###### excluded-.intros
+ ###### excluded-.redefs
+
+MModulePage excluded
+ # excluded.section
+ ## excluded-.intro
+ ## excluded-.importation
+ ### excluded-.graph
+ ### list.group
+ #### excluded-.imports
+ #### excluded-.clients
+
OverviewPage Overview
# home.article
## packages.section
+ ### excluded.definition
### test_prog.definition
+ReadmePage excluded
+
ReadmePage test_prog
# mdarticle-0
#### test_prog__rpg__rpg.imports
#### test_prog__rpg__rpg.clients
-Generated 96 pages
+Generated 99 pages
list:
- MPropertyPage: 58 (60.41%)
- MClassPage: 20 (20.83%)
- MModulePage: 8 (8.33%)
- MGroupPage: 4 (4.16%)
- ReadmePage: 4 (4.16%)
- SearchPage: 1 (1.04%)
- OverviewPage: 1 (1.04%)
-Found 182 mentities
+ MPropertyPage: 58 (58.58%)
+ MClassPage: 20 (20.20%)
+ MModulePage: 9 (9.09%)
+ ReadmePage: 5 (5.05%)
+ MGroupPage: 5 (5.05%)
+ SearchPage: 1 (1.01%)
+ OverviewPage: 1 (1.01%)
+Found 185 mentities
list:
- MMethodDef: 68 (37.36%)
- MMethod: 57 (31.31%)
- MClassDef: 22 (12.08%)
- MClass: 20 (10.98%)
- MModule: 8 (4.39%)
- MGroup: 4 (2.19%)
+ MMethodDef: 68 (36.75%)
+ MMethod: 57 (30.81%)
+ MClassDef: 22 (11.89%)
+ MClass: 20 (10.81%)
+ MModule: 9 (4.86%)
+ MGroup: 5 (2.70%)
+ MPackage: 2 (1.08%)
MVirtualTypeDef: 1 (0.54%)
MVirtualTypeProp: 1 (0.54%)
- MPackage: 1 (0.54%)
quicksearch-list.js
|--\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
`--subdir (\e[33mproject1/subdir\e[m)
|--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
- `--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
+ |--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
+ `--subdir2 (\e[33mproject1/subdir/subdir2\e[m)
+ `--subdir3 (\e[33mproject1/subdir/subdir2/subdir3\e[m)
+ `--\e[1msubmodule\e[m (\e[33mproject1/subdir/subdir2/subdir3/submodule.nit\e[m)
|--\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
`--subdir (\e[33mproject1/subdir\e[m)
|--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
- `--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
+ |--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
+ `--subdir2 (\e[33mproject1/subdir/subdir2\e[m)
+ `--subdir3 (\e[33mproject1/subdir/subdir2/subdir3\e[m)
+ `--\e[1msubmodule\e[m (\e[33mproject1/subdir/subdir2/subdir3/submodule.nit\e[m)
|--\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
`--subdir (\e[33mproject1/subdir\e[m)
|--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
- `--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
+ |--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
+ `--subdir2 (\e[33mproject1/subdir/subdir2\e[m)
+ `--subdir3 (\e[33mproject1/subdir/subdir2/subdir3\e[m)
+ `--\e[1msubmodule\e[m (\e[33mproject1/subdir/subdir2/subdir3/submodule.nit\e[m)
project2 (\e[33mproject1/project2\e[m)
|--\e[1mfoo\e[m (\e[33mproject1/project2/foo.nit\e[m)
`--\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
project1>\e[1mmodule_01\e[m (\e[33mproject1/module_01.nit\e[m)
project1>\e[1mmodule_02\e[m (\e[33mproject1/module_02.nit\e[m)
project1>\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
+project1>subdir>subdir2>subdir3>\e[1msubmodule\e[m (\e[33mproject1/subdir/subdir2/subdir3/submodule.nit\e[m)
|--\e[1mmodule1\e[m (\e[33mproject1/module1.nit\e[m)
|--\e[1mmodule3\e[m (\e[33mproject1/module3.nit\e[m)\e[37m (module4)\e[m
`--subdir (\e[33mproject1/subdir\e[m)
- `--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)\e[37m (module1)\e[m
+ |--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)\e[37m (module1)\e[m
+ `--subdir2 (\e[33mproject1/subdir/subdir2\e[m)
+ `--subdir3 (\e[33mproject1/subdir/subdir2/subdir3\e[m)
+ `--\e[1msubmodule\e[m (\e[33mproject1/subdir/subdir2/subdir3/submodule.nit\e[m)
--- /dev/null
+test_prog: Test program for model tools. (test_prog)
+|--game: Gaming group (test_prog/game)
+| `--\e[1mgame\e[m: A game abstraction for RPG. (test_prog/game/game.nit)
+|--platform: Fictive Crappy Platform. (test_prog/platform)
+| `--\e[1mplatform\e[m: Declares base types allowed on the platform. (test_prog/platform/platform.nit)
+|--rpg: Role Playing Game group (test_prog/rpg)
+| |--\e[1mcareers\e[m: Careers of the game. (test_prog/rpg/careers.nit)
+| |--\e[1mcharacter\e[m: Characters are playable entity in the world. (test_prog/rpg/character.nit)
+| |--\e[1mcombat\e[m: COmbat interactions between characters. (test_prog/rpg/combat.nit)
+| |--\e[1mraces\e[m: Races of the game. (test_prog/rpg/races.nit)
+| `--\e[1mrpg\e[m: A worlg RPG abstraction. (test_prog/rpg/rpg.nit)
+`--\e[1mtest_prog\e[m: A test program with a fake model to check model tools. (test_prog/test_prog.nit)
--- /dev/null
+\e[1mexcluded\e[m (test_prog/game/excluded.nit)
+\e[1mmore\e[m (test_prog/game/excluded_dir/more.nit)
Numeric -> Float [dir=back arrowtail=open style=dashed];
Byte [
- label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l}"
+ label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l+ is_whitespace(): Bool\l}"
]
Discrete -> Byte [dir=back arrowtail=open style=dashed];
Numeric -> Byte [dir=back arrowtail=open style=dashed];
Numeric -> Float [dir=back arrowtail=open style=dashed];
Byte [
- label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l}"
+ label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l+ is_whitespace(): Bool\l}"
]
Discrete -> Byte [dir=back arrowtail=open style=dashed];
Numeric -> Byte [dir=back arrowtail=open style=dashed];
-\r\e[K* Docunits of module test_nitunit::test_nitunit [ ] 0/4\r\e[K* Docunits of module test_nitunit::test_nitunit [ \e[1m\e[31mX\e[m\e[m] 1/4 test_nitunit$X$foo1 \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of module test_nitunit::test_nitunit [\e[1m\e[32m.\e[m\e[m \e[1m\e[31mX\e[m\e[m] 2/4 test_nitunit::test_nitunit \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Docunits of module test_nitunit::test_nitunit [\e[1m\e[32m.\e[m\e[m\e[1m\e[31mX\e[m\e[m \e[1m\e[31mX\e[m\e[m] 3/4 test_nitunit$X \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of module test_nitunit::test_nitunit [\e[1m\e[32m.\e[m\e[m\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m] 4/4 test_nitunit$X$foo \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of module test_nitunit::test_nitunit [\e[1m\e[32m.\e[m\e[m\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m] 4/4
-\e[1m\e[32m[OK]\e[m\e[m test_nitunit::test_nitunit
-\e[1m\e[31m[KO]\e[m\e[m test_nitunit$X
- \e[33mtest_nitunit.nit:21,7--22,0\e[m: Runtime error in .nitunit/test_nitunit-2.nit
- # \e[1;31massert false\e[0m
- ^
+==== Docunits of module test_nitunit::test_nitunit | tests: 4
+[OK] test_nitunit::test_nitunit
+[KO] test_nitunit$X
+ test_nitunit.nit:21,7--22,0: Runtime error in nitunit.out/test_nitunit-2.nit
Output
- Runtime error: Assert failed (.nitunit/test_nitunit-2.nit:5)
+ Runtime error: Assert failed (nitunit.out/test_nitunit-2.nit:5)
-\e[1m\e[31m[KO]\e[m\e[m test_nitunit$X$foo
- \e[33mtest_nitunit.nit:24,8--25,0\e[m: Compilation error in .nitunit/test_nitunit-3.nit
- # \e[1;31massert undefined_identifier\e[0m
- ^
+[KO] test_nitunit$X$foo
+ test_nitunit.nit:24,8--25,0: Compilation error in nitunit.out/test_nitunit-3.nit
Output
- .nitunit/test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
+ nitunit.out/test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
-\e[1m\e[31m[KO]\e[m\e[m test_nitunit$X$foo1
- \e[33mtest_nitunit.nit:28,15\e[m: Syntax Error: unexpected operator '!'.
- # assert \e[1;31m!\e[0m@#$%^&*()
- ^
-\r\e[K* Test-suite of module test_test_nitunit::test_test_nitunit [ ] 0/3\r\e[K* Test-suite of module test_test_nitunit::test_test_nitunit [\e[1m\e[32m.\e[m\e[m ] 1/3 test_test_nitunit$TestX$test_foo \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Test-suite of module test_test_nitunit::test_test_nitunit [\e[1m\e[32m.\e[m\e[m\e[1m\e[31mX\e[m\e[m ] 2/3 test_test_nitunit$TestX$test_foo1 \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Test-suite of module test_test_nitunit::test_test_nitunit [\e[1m\e[32m.\e[m\e[m\e[1m\e[31mX\e[m\e[m\e[1m\e[32m.\e[m\e[m] 3/3 test_test_nitunit$TestX$test_foo2 \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Test-suite of module test_test_nitunit::test_test_nitunit [\e[1m\e[32m.\e[m\e[m\e[1m\e[31mX\e[m\e[m\e[1m\e[32m.\e[m\e[m] 3/3
-\e[1m\e[32m[OK]\e[m\e[m test_test_nitunit$TestX$test_foo
-\e[1m\e[31m[KO]\e[m\e[m test_test_nitunit$TestX$test_foo1
- \e[33mtest_test_nitunit.nit:36,2--40,4\e[m: Runtime Error in file .nitunit/gen_test_test_nitunit.nit
- \e[1;31m# will fail\e[0m
- ^
+[KO] test_nitunit$X$foo1
+ test_nitunit.nit:28,15: Syntax Error: unexpected operator '!'.
+
+==== Test-suite of module test_test_nitunit::test_test_nitunit | tests: 3
+[OK] test_test_nitunit$TestX$test_foo
+[KO] test_test_nitunit$TestX$test_foo1
+ test_test_nitunit.nit:36,2--40,4: Runtime Error in file nitunit.out/gen_test_test_nitunit.nit
Output
Runtime error: Assert failed (test_test_nitunit.nit:39)
-\e[1m\e[32m[OK]\e[m\e[m test_test_nitunit$TestX$test_foo2
-DocUnits:
-Entities: 27; Documented ones: 4; With nitunits: 4; Failures: 3
+[OK] test_test_nitunit$TestX$test_foo2
-TestSuites:
-Class suites: 1; Test Cases: 3; Failures: 1
+Docunits: Entities: 34; Documented ones: 6; With nitunits: 4; Failures: 3
+Test suites: Classes: 1; Test Cases: 3; Failures: 1
+[FAILURE] 4/7 tests failed.
+`nitunit.out` is not removed for investigation.
<testsuites><testsuite package="test_nitunit::test_nitunit"><testcase classname="nitunit.test_nitunit::test_nitunit.<module>" name="<module>"><system-err></system-err><system-out>assert true
-</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="<class>"><error>Runtime error in .nitunit/test_nitunit-2.nit</error><system-err>Runtime error: Assert failed (.nitunit/test_nitunit-2.nit:5)
+</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="<class>"><error>Runtime error in nitunit.out/test_nitunit-2.nit</error><system-err>Runtime error: Assert failed (nitunit.out/test_nitunit-2.nit:5)
</system-err><system-out>assert false
-</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="test_nitunit::X::foo"><failure>Compilation error in .nitunit/test_nitunit-3.nit</failure><system-err>.nitunit/test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
+</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="test_nitunit::X::foo"><failure>Compilation error in nitunit.out/test_nitunit-3.nit</failure><system-err>nitunit.out/test_nitunit-3.nit:5,8--27: Error: method or variable `undefined_identifier` unknown in `Sys`.
</system-err><system-out>assert undefined_identifier
</system-out></testcase><testcase classname="nitunit.test_nitunit::test_nitunit.test_nitunit::X" name="test_nitunit::X::foo1"><failure>Syntax Error: unexpected operator '!'.</failure><system-out>assert !@#$%^&*()
-</system-out></testcase></testsuite><testsuite package="test_test_nitunit"><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo"><system-err></system-err></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo1"><error>Runtime Error in file .nitunit/gen_test_test_nitunit.nit</error><system-err>Runtime error: Assert failed (test_test_nitunit.nit:39)
+</system-out></testcase></testsuite><testsuite package="test_test_nitunit::test_test_nitunit"></testsuite><testsuite package="test_test_nitunit"><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo"><system-err></system-err></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo1"><error>Runtime Error in file nitunit.out/gen_test_test_nitunit.nit</error><system-err>Runtime error: Assert failed (test_test_nitunit.nit:39)
</system-err></testcase><testcase classname="nitunit.test_test_nitunit::test_test_nitunit.test_test_nitunit::TestX" name="test_test_nitunit::TestX::test_foo2"><system-err></system-err></testcase></testsuite></testsuites>
\ No newline at end of file
-\r\e[K* Docunits of module test_nitunit2::test_nitunit2 [ ] 0/3\r\e[K* Docunits of module test_nitunit2::test_nitunit2 [\e[1m\e[32m.\e[m\e[m ] 1/3 test_nitunit2::test_nitunit2$core::Sys$foo1 \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Docunits of module test_nitunit2::test_nitunit2 [\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m ] 2/3 test_nitunit2::test_nitunit2$core::Sys$bar2 \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Docunits of module test_nitunit2::test_nitunit2 [\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m] 3/3 test_nitunit2::test_nitunit2$core::Sys$foo3 \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Docunits of module test_nitunit2::test_nitunit2 [\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m] 3/3
-\e[1m\e[32m[OK]\e[m\e[m test_nitunit2::test_nitunit2$core::Sys$foo1
-\e[1m\e[32m[OK]\e[m\e[m test_nitunit2::test_nitunit2$core::Sys$bar2
-\e[1m\e[32m[OK]\e[m\e[m test_nitunit2::test_nitunit2$core::Sys$foo3
-DocUnits:
-DocUnits Success
-Entities: 4; Documented ones: 3; With nitunits: 3; Failures: 0
+==== Docunits of module test_nitunit2::test_nitunit2 | tests: 3
+[OK] test_nitunit2::test_nitunit2$core::Sys$foo1
+[OK] test_nitunit2::test_nitunit2$core::Sys$bar2
+[OK] test_nitunit2::test_nitunit2$core::Sys$foo3
-TestSuites:
-No test cases found
-Class suites: 0; Test Cases: 0; Failures: 0
+Docunits: Entities: 4; Documented ones: 3; With nitunits: 3; Failures: 0
+Test suites: Classes: 0; Test Cases: 0
+[SUCCESS] All 3 tests passed.
<testsuites><testsuite package="test_nitunit2::test_nitunit2"><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::foo1"><system-err></system-err><system-out>if true then
assert true
</system-out></testcase><testcase classname="nitunit.test_nitunit2::test_nitunit2.core::Sys" name="test_nitunit2::test_nitunit2::Sys::foo3"><system-err></system-err><system-out>var a = 1
assert a == 1
assert a == 1
-</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
-\r\e[K* Docunits of module test_doc2::test_doc2 [ ] 0/3\r\e[K* Docunits of module test_doc2::test_doc2 [\e[1m\e[32m.\e[m\e[m ] 1/3 test_doc2::test_doc2$core::Sys$foo1 \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Docunits of module test_doc2::test_doc2 [\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m ] 2/3 test_doc2::test_doc2$core::Sys$foo2 \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Docunits of module test_doc2::test_doc2 [\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m] 3/3 test_doc2::test_doc2$core::Sys$foo3 \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Docunits of module test_doc2::test_doc2 [\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m\e[1m\e[32m.\e[m\e[m] 3/3
-\e[1m\e[32m[OK]\e[m\e[m test_doc2::test_doc2$core::Sys$foo1
-\e[1m\e[32m[OK]\e[m\e[m test_doc2::test_doc2$core::Sys$foo2
-\e[1m\e[32m[OK]\e[m\e[m test_doc2::test_doc2$core::Sys$foo3
-DocUnits:
-DocUnits Success
-Entities: 6; Documented ones: 5; With nitunits: 3; Failures: 0
+==== Docunits of module test_doc2::test_doc2 | tests: 3
+[OK] test_doc2::test_doc2$core::Sys$foo1
+[OK] test_doc2::test_doc2$core::Sys$foo2
+[OK] test_doc2::test_doc2$core::Sys$foo3
-TestSuites:
-No test cases found
-Class suites: 0; Test Cases: 0; Failures: 0
+Docunits: Entities: 6; Documented ones: 5; With nitunits: 3; Failures: 0
+Test suites: Classes: 0; Test Cases: 0
+[SUCCESS] All 3 tests passed.
<testsuites><testsuite package="test_doc2::test_doc2"><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo1"><system-err></system-err><system-out>assert true # tested
</system-out></testcase><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo2"><system-err></system-err><system-out>assert true # tested
</system-out></testcase><testcase classname="nitunit.test_doc2::test_doc2.core::Sys" name="test_doc2::test_doc2::Sys::foo3"><system-err></system-err><system-out>assert true # tested
-</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
-\r\e[K* Docunits of group test_nitunit3> [ ] 0/2\r\e[K* Docunits of group test_nitunit3> [ \e[1m\e[31mX\e[m\e[m] 1/2 test_nitunit3> \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of group test_nitunit3> [\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m] 2/2 test_nitunit3> \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of group test_nitunit3> [\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m] 2/2
-\e[1m\e[31m[KO]\e[m\e[m test_nitunit3>
- \e[33mtest_nitunit3/README.md:4,2--15,0\e[m: Runtime error in .nitunit/test_nitunit3-0.nit with argument 1
- ~\e[1;31m~\e[0m
- ^
+==== Docunits of group test_nitunit3> | tests: 2
+[KO] test_nitunit3>
+ test_nitunit3/README.md:4,2--15,0: Runtime error in nitunit.out/test_nitunit3-0.nit with argument 1
Output
- Runtime error: Assert failed (.nitunit/test_nitunit3-0.nit:7)
+ Runtime error: Assert failed (nitunit.out/test_nitunit3-0.nit:7)
-\e[1m\e[31m[KO]\e[m\e[m test_nitunit3>
- \e[33mtest_nitunit3/README.md:7,3--5\e[m: Syntax Error: unexpected malformed character '\].
- ~~\e[1;31m~
-;\e[0m
- ^
-\r\e[K* Docunits of module test_nitunit3::test_nitunit3 [ ] 0/1\r\e[K* Docunits of module test_nitunit3::test_nitunit3 [\e[1m\e[32m.\e[m\e[m] 1/1 test_nitunit3::test_nitunit3 \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Docunits of module test_nitunit3::test_nitunit3 [\e[1m\e[32m.\e[m\e[m] 1/1
-\e[1m\e[32m[OK]\e[m\e[m test_nitunit3::test_nitunit3
-DocUnits:
-Entities: 2; Documented ones: 2; With nitunits: 3; Failures: 2
+[KO] test_nitunit3>#2
+ test_nitunit3/README.md:7,3--5: Syntax Error: unexpected malformed character '\].
-TestSuites:
-No test cases found
-Class suites: 0; Test Cases: 0; Failures: 0
-<testsuites><testsuite package="test_nitunit3>"><testcase classname="nitunit.test_nitunit3>" name="<group>"><error>Runtime error in .nitunit/test_nitunit3-0.nit with argument 1</error><system-err>Runtime error: Assert failed (.nitunit/test_nitunit3-0.nit:7)
+==== Docunits of module test_nitunit3::test_nitunit3 | tests: 1
+[OK] test_nitunit3::test_nitunit3
+
+Docunits: Entities: 2; Documented ones: 2; With nitunits: 3; Failures: 2
+Test suites: Classes: 0; Test Cases: 0
+[FAILURE] 2/3 tests failed.
+`nitunit.out` is not removed for investigation.
+<testsuites><testsuite package="test_nitunit3>"><testcase classname="nitunit.test_nitunit3>" name="<group>"><error>Runtime error in nitunit.out/test_nitunit3-0.nit with argument 1</error><system-err>Runtime error: Assert failed (nitunit.out/test_nitunit3-0.nit:7)
</system-err><system-out>assert false
assert true
-</system-out></testcase><testcase classname="nitunit.test_nitunit3>" name="<group>+1"><failure>Syntax Error: unexpected malformed character '\].</failure><system-out>;'\][]
+</system-out></testcase><testcase classname="nitunit.test_nitunit3>" name="<group>#2"><failure>Syntax Error: unexpected malformed character '\].</failure><system-out>;'\][]
</system-out></testcase></testsuite><testsuite package="test_nitunit3::test_nitunit3"><testcase classname="nitunit.test_nitunit3::test_nitunit3.<module>" name="<module>"><system-err></system-err><system-out>assert true
-</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
-\r\e[K* Docunits of file test_nitunit_md.md:1,0--15,0 [ ] 0/1\r\e[K* Docunits of file test_nitunit_md.md:1,0--15,0 [\e[1m\e[31mX\e[m\e[m] 1/1 nitunit.<file>.test_nitunit_md.md:1,0--15,0 \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of file test_nitunit_md.md:1,0--15,0 [\e[1m\e[31mX\e[m\e[m] 1/1
-\e[1m\e[31m[KO]\e[m\e[m nitunit.<file>.test_nitunit_md.md:1,0--15,0
- \e[33mtest_nitunit_md.md:4,2--16,0\e[m: Runtime error in .nitunit/file-0.nit with argument 1
- ~\e[1;31m~\e[0m
- ^
+==== Docunits of file test_nitunit_md.md | tests: 1
+[KO] nitunit.<file>.test_nitunit_md.md
+ test_nitunit_md.md:4,2--16,0: Runtime error in nitunit.out/file-0.nit with argument 1
Output
- Runtime error: Assert failed (.nitunit/file-0.nit:8)
+ Runtime error: Assert failed (nitunit.out/file-0.nit:8)
-DocUnits:
-Entities: 1; Documented ones: 1; With nitunits: 1; Failures: 1
-TestSuites:
-No test cases found
-Class suites: 0; Test Cases: 0; Failures: 0
-<testsuites><testsuite package="test_nitunit_md.md:1,0--15,0"><testcase classname="nitunit.<file>" name="test_nitunit_md.md:1,0--15,0"><error>Runtime error in .nitunit/file-0.nit with argument 1</error><system-err>Runtime error: Assert failed (.nitunit/file-0.nit:8)
+Docunits: Entities: 1; Documented ones: 1; With nitunits: 1; Failures: 1
+Test suites: Classes: 0; Test Cases: 0
+[FAILURE] 1/1 tests failed.
+`nitunit.out` is not removed for investigation.
+<testsuites><testsuite package="test_nitunit_md.md"><testcase classname="nitunit.<file>" name="test_nitunit_md.md"><error>Runtime error in nitunit.out/file-0.nit with argument 1</error><system-err>Runtime error: Assert failed (nitunit.out/file-0.nit:8)
</system-err><system-out>var a = 1
assert 1 == 1
assert false
-\r\e[K* Docunits of module test_doc3::test_doc3 [ ] 0/3\r\e[K* Docunits of module test_doc3::test_doc3 [\e[1m\e[31mX\e[m\e[m ] 1/3 test_doc3::test_doc3$core::Sys$foo1 \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of module test_doc3::test_doc3 [\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m ] 2/3 test_doc3::test_doc3$core::Sys$foo2 \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of module test_doc3::test_doc3 [\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m] 3/3 test_doc3::test_doc3$core::Sys$foo3 \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Docunits of module test_doc3::test_doc3 [\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m\e[1m\e[31mX\e[m\e[m] 3/3
-\e[1m\e[31m[KO]\e[m\e[m test_doc3::test_doc3$core::Sys$foo1
- \e[33mtest_doc3.nit:17,9--15\e[m: Syntax Error: unexpected identifier 'garbage'.
- # *\e[1;31mgarbage\e[0m*
- ^
-\e[1m\e[31m[KO]\e[m\e[m test_doc3::test_doc3$core::Sys$foo2
- \e[33mtest_doc3.nit:23,4--10\e[m: Syntax Error: unexpected identifier 'garbage'.
- # *\e[1;31mgarbage\e[0m*
- ^
-\e[1m\e[31m[KO]\e[m\e[m test_doc3::test_doc3$core::Sys$foo3
- \e[33mtest_doc3.nit:30,4--10\e[m: Syntax Error: unexpected identifier 'garbage'.
- # *\e[1;31mgarbage\e[0m*
- ^
-DocUnits:
-Entities: 6; Documented ones: 5; With nitunits: 3; Failures: 3
+==== Docunits of module test_doc3::test_doc3 | tests: 3
+[KO] test_doc3::test_doc3$core::Sys$foo1
+ test_doc3.nit:17,9--15: Syntax Error: unexpected identifier 'garbage'.
+[KO] test_doc3::test_doc3$core::Sys$foo2
+ test_doc3.nit:23,4--10: Syntax Error: unexpected identifier 'garbage'.
+[KO] test_doc3::test_doc3$core::Sys$foo3
+ test_doc3.nit:30,4--10: Syntax Error: unexpected identifier 'garbage'.
-TestSuites:
-No test cases found
-Class suites: 0; Test Cases: 0; Failures: 0
+Docunits: Entities: 6; Documented ones: 5; With nitunits: 3; Failures: 3
+Test suites: Classes: 0; Test Cases: 0
+[FAILURE] 3/3 tests failed.
+`nitunit.out` is not removed for investigation.
<testsuites><testsuite package="test_doc3::test_doc3"><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo1"><failure>Syntax Error: unexpected identifier 'garbage'.</failure><system-out> *garbage*
</system-out></testcase><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo2"><failure>Syntax Error: unexpected identifier 'garbage'.</failure><system-out>*garbage*
</system-out></testcase><testcase classname="nitunit.test_doc3::test_doc3.core::Sys" name="test_doc3::test_doc3::Sys::foo3"><failure>Syntax Error: unexpected identifier 'garbage'.</failure><system-out>*garbage*
-</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-out></testcase></testsuite></testsuites>
\ No newline at end of file
-\r\e[K* Test-suite of module test_nitunit4::test_nitunit4 [ ] 0/3\r\e[K* Test-suite of module test_nitunit4::test_nitunit4 [\e[1m\e[31mX\e[m\e[m ] 1/3 test_nitunit4$TestTestSuite$test_foo \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Test-suite of module test_nitunit4::test_nitunit4 [\e[1m\e[31mX\e[m\e[m\e[1m\e[32m.\e[m\e[m ] 2/3 test_nitunit4$TestTestSuite$test_bar \e[1m\e[32m[OK]\e[m\e[m\r\e[K* Test-suite of module test_nitunit4::test_nitunit4 [\e[1m\e[31mX\e[m\e[m\e[1m\e[32m.\e[m\e[m\e[1m\e[31mX\e[m\e[m] 3/3 test_nitunit4$TestTestSuite$test_baz \e[1m\e[31m[KO]\e[m\e[m\r\e[K* Test-suite of module test_nitunit4::test_nitunit4 [\e[1m\e[31mX\e[m\e[m\e[1m\e[32m.\e[m\e[m\e[1m\e[31mX\e[m\e[m] 3/3
-\e[1m\e[31m[KO]\e[m\e[m test_nitunit4$TestTestSuite$test_foo
- \e[33mtest_nitunit4/test_nitunit4.nit:22,2--26,4\e[m: Runtime Error in file .nitunit/gen_test_nitunit4.nit
- \e[1;31mfun test_foo do\e[0m
- ^
+==== Test-suite of module test_nitunit4::test_nitunit4 | tests: 4
+[KO] test_nitunit4$TestTestSuite$test_foo
+ test_nitunit4/test_nitunit4.nit:22,2--26,4: Runtime Error in file nitunit.out/gen_test_nitunit4.nit
Output
Before Test
Tested method
After Test
Runtime error: Assert failed (test_nitunit4/test_nitunit4_base.nit:31)
-\e[1m\e[32m[OK]\e[m\e[m test_nitunit4$TestTestSuite$test_bar
-\e[1m\e[31m[KO]\e[m\e[m test_nitunit4$TestTestSuite$test_baz
- \e[33mtest_nitunit4/test_nitunit4.nit:32,2--34,4\e[m: Difference with expected output: diff -u test_nitunit4/test_nitunit4.sav/test_baz.res .nitunit/gen_test_nitunit4_test_baz.out1
- \e[1;31mfun test_baz do\e[0m
- ^
+[OK] test_nitunit4$TestTestSuite$test_bar
+[KO] test_nitunit4$TestTestSuite$test_baz
+ test_nitunit4/test_nitunit4.nit:32,2--34,4: Difference with expected output: diff -u test_nitunit4/test_baz.res nitunit.out/gen_test_nitunit4_test_baz.out1
Output
Diff
- --- expected:test_nitunit4/test_nitunit4.sav/test_baz.res
- +++ got:.nitunit/gen_test_nitunit4_test_baz.out1
+ --- expected:test_nitunit4/test_baz.res
+ +++ got:nitunit.out/gen_test_nitunit4_test_baz.out1
@@ -1 +1,3 @@
-Bad result file
+Before Test
+Tested method
+After Test
-DocUnits:
-No doc units found
-Entities: 12; Documented ones: 0; With nitunits: 0; Failures: 0
+[KO] test_nitunit4$TestTestSuite$test_sav_conflict
+ test_nitunit4/test_nitunit4.nit:36,2--38,4: Conflicting expected output: test_nitunit4/test_nitunit4.sav/test_sav_conflict.res, test_nitunit4/sav/test_sav_conflict.res and test_nitunit4/test_sav_conflict.res all exist
+ Output
+ Before Test
+ Tested method
+ After Test
-TestSuites:
-Class suites: 1; Test Cases: 3; Failures: 2
-<testsuites><testsuite package="test_nitunit4>"></testsuite><testsuite package="test_nitunit4::nitunit4"></testsuite><testsuite package="test_nitunit4"><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_foo"><error>Runtime Error in file .nitunit/gen_test_nitunit4.nit</error><system-err>Before Test
+
+==== Test-suite of module test_nitunit4::test_nitunit4_base | tests: 0
+==== Test-suite of module test_nitunit4::test_nitunit4_base | tests: 0
+
+Docunits: Entities: 13; Documented ones: 0; With nitunits: 0
+Test suites: Classes: 2; Test Cases: 4; Failures: 3
+[FAILURE] 3/4 tests failed.
+`nitunit.out` is not removed for investigation.
+<testsuites><testsuite package="test_nitunit4>"></testsuite><testsuite package="test_nitunit4::nitunit4"></testsuite><testsuite package="test_nitunit4::test_nitunit4"></testsuite><testsuite package="test_nitunit4"><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_foo"><error>Runtime Error in file nitunit.out/gen_test_nitunit4.nit</error><system-err>Before Test
Tested method
After Test
Runtime error: Assert failed (test_nitunit4/test_nitunit4_base.nit:31)
</system-err></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_bar"><system-err>Before Test
Tested method
After Test
-</system-err></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_baz"><error>Difference with expected output: diff -u test_nitunit4/test_nitunit4.sav/test_baz.res .nitunit/gen_test_nitunit4_test_baz.out1</error><system-err>Diff
---- expected:test_nitunit4/test_nitunit4.sav/test_baz.res
-+++ got:.nitunit/gen_test_nitunit4_test_baz.out1
+</system-err></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_baz"><error>Difference with expected output: diff -u test_nitunit4/test_baz.res nitunit.out/gen_test_nitunit4_test_baz.out1</error><system-err>Diff
+--- expected:test_nitunit4/test_baz.res
++++ got:nitunit.out/gen_test_nitunit4_test_baz.out1
@@ -1 +1,3 @@
-Bad result file
+Before Test
+Tested method
+After Test
-</system-err></testcase></testsuite><testsuite package="test_nitunit4::test_nitunit4"></testsuite><testsuite></testsuite><testsuite package="test_nitunit4::test_nitunit4_base"></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
+</system-err></testcase><testcase classname="nitunit.test_nitunit4::test_nitunit4.test_nitunit4::TestTestSuite" name="test_nitunit4::TestTestSuite::test_sav_conflict"><error>Conflicting expected output: test_nitunit4/test_nitunit4.sav/test_sav_conflict.res, test_nitunit4/sav/test_sav_conflict.res and test_nitunit4/test_sav_conflict.res all exist</error><system-err>Before Test
+Tested method
+After Test
+</system-err></testcase></testsuite><testsuite package="test_nitunit4::test_nitunit4_base"></testsuite><testsuite package="test_nitunit4_base"></testsuite></testsuites>
\ No newline at end of file
Zm9vYg==: foob
Zm9vYmE=: fooba
Zm9vYmFy: foobar
+Zm9vYg: foob
+Zm9vYmE: fooba
+Zm9v*Yg: foob
+:
+Znm=.is_base64? true
+Znm===.is_base64? false
+Z.sd=.is_base64? false
+Z==D.is_base64? false
+:
+Znm=: No error
+Znm===: Invalid padding length
+Z.sd=: Invalid Base64 character at position 1: .
+Z==D: Invalid padding character D at position 3
population: 3
minimum value: 2
- maximum value: 11
- total value: 16
- average value: 5.33
+ maximum value: 12
+ total value: 22
+ average value: 7.33
distribution:
- <=2: sub-population=1 (33.33%); cumulated value=2 (12.50%)
- <=4: sub-population=1 (33.33%); cumulated value=3 (18.75%)
- <=16: sub-population=1 (33.33%); cumulated value=11 (68.75%)
+ <=2: sub-population=1 (33.33%); cumulated value=2 (9.09%)
+ <=8: sub-population=1 (33.33%); cumulated value=8 (36.36%)
+ <=16: sub-population=1 (33.33%); cumulated value=12 (54.54%)
list:
- nit: 11 (68.75%)
- : 3 (18.75%)
- ini: 2 (12.50%)
+ nit: 12 (54.54%)
+ : 8 (36.36%)
+ ini: 2 (9.09%)
# mpackages:
-test_prog
+excluded test_prog
------------------------------------
-test_prog
+excluded test_prog
# mmodules:
-careers character combat game platform races rpg test_prog
+careers character combat excluded game platform races rpg test_prog
------------------------------------
-careers character combat game platform races rpg test_prog
+careers character combat excluded game platform races rpg test_prog
# mclasses:
Alcoholic Bool Career Character Combatable Dwarf Elf Float Game Human Int List Magician Object Race Starter String Sys Warrior Weapon
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/core/collection/array.nit:989)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/core/collection/array.nit:991)
NativeString
0x4e
Nit
--- /dev/null
+prompt>line 1
+line 1
+prompt>line 2
+line 2
+prompt>line 2bis
+line 2bis
+prompt>line 3 \b \bine\b \b\b \b\b \b3\b \b
+line 3
+prompt>
\ No newline at end of file
|--test_prog/README.md
|--test_prog/game
| |--test_prog/game/README.md
+| |--test_prog/game/excluded.nit
+| |--test_prog/game/excluded_dir
+| | `--test_prog/game/excluded_dir/more.nit
| `--test_prog/game/game.nit
|--test_prog/package.ini
|--test_prog/platform
print "fooba: " + "fooba".encode_base64
print "foobar: " + "foobar".encode_base64
-print ":" + "".decode_base64
-print "Zg==: " + "Zg==".decode_base64
-print "Zm8=: " + "Zm8=".decode_base64
-print "Zm9v: " + "Zm9v".decode_base64
-print "Zm9vYg==: " + "Zm9vYg==".decode_base64
-print "Zm9vYmE=: " + "Zm9vYmE=".decode_base64
-print "Zm9vYmFy: " + "Zm9vYmFy".decode_base64
+print ":" + "".decode_base64.to_s
+print "Zg==: " + "Zg==".decode_base64.to_s
+print "Zm8=: " + "Zm8=".decode_base64.to_s
+print "Zm9v: " + "Zm9v".decode_base64.to_s
+print "Zm9vYg==: " + "Zm9vYg==".decode_base64.to_s
+print "Zm9vYmE=: " + "Zm9vYmE=".decode_base64.to_s
+print "Zm9vYmFy: " + "Zm9vYmFy".decode_base64.to_s
+
+print "Zm9vYg: " + "Zm9vYg".decode_base64.to_s
+print "Zm9vYmE: " + "Zm9vYmE".decode_base64.to_s
+print "Zm9v*Yg: " + "Zm9v*Yg".decode_base64.to_s
+
+print ":"
+print "Znm=.is_base64? " + "Znm=".is_base64.to_s
+print "Znm===.is_base64? " + "Znm===".is_base64.to_s
+print "Z.sd=.is_base64? " + "Z.sd=".is_base64.to_s
+print "Z==D.is_base64? " + "Z==D".is_base64.to_s
+
+print ":"
+printn "Znm=: "
+print "Znm=".check_base64 or else "No error"
+printn "Znm===: "
+print "Znm===".check_base64 or else "No error"
+printn "Z.sd=: "
+print "Z.sd=".check_base64 or else "No error"
+printn "Z==D: "
+print "Z==D".check_base64 or else "No error"
fun test_baz do
print "Tested method"
end
+
+ fun test_sav_conflict do
+ print "Tested method"
+ end
end
--- /dev/null
+This is not a valid Nit program
--- /dev/null
+This is not a valid Nit program
maintainer=John Doe <jdoe@example.com> (http://www.example.com/~jdoe), Spider-Man
more_contributors=Riri <riri@example.com>, Fifi (http://www.example.com/~fifi), Loulou
license=Apache-2.0
+[source]
+exclude=game/excluded.nit:game/excluded_dir
[upstream]
browse=https://github.com/nitlang/nit/tree/master/tests/test_prog
git=https://github.com/nitlang/nit.git
--- /dev/null
+line 1
+line 2
+line 2bis
+line 3 \bine\b\b\b3\b
-# Copyright 2013 Alexandre Terrasa <alexandre@moz-code.org>.
+# 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.
# See the License for the specific language governing permissions and
# limitations under the License.
-all: tests
+import readline
-check: clean
- ./tests.sh
-
-clean:
- rm -rf out/
+loop
+ var line = readline("prompt>", true)
+ if line == null then break
+ print line
+end