diff --git a/.travis.yml b/.travis.yml index b0c9e01..74a90c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: node_js node_js: - - "0.10" + - '5.6' jdk: - oraclejdk7 # Needed for neo4j @@ -9,15 +9,35 @@ jdk: env: global: - NEO4J_VERSION="2.1.7" + - CXX=g++-4.8 + +addons: + apt: + + sources: + - ubuntu-toolchain-r-test + + packages: + - g++-4.8 before_install: - wget dist.neo4j.org/neo4j-community-$NEO4J_VERSION-unix.tar.gz - tar -xzf neo4j-community-$NEO4J_VERSION-unix.tar.gz - echo org.neo4j.server.database.location=src/test/dump > neo4j-community-$NEO4J_VERSION/conf/neo4j-server.properties - neo4j-community-$NEO4J_VERSION/bin/neo4j start + - npm install -g npm@latest + +after_install: + - npm config set tag-version-prefix "" --global + - npm config set tag-version-prefix "" before_script: - - gulp manifest + - npm version `git describe --tags` --no-git-tag + - cat package.json | grep version + +script: + - gulp build + - gulp test - gulp docs after_success: diff --git a/gulpfile.js b/gulpfile.js index f0b9f32..65f426f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,6 +1,12 @@ +/* globals require, module */ 'use strict'; -/* globals require, module */ +var traceur = require('traceur'); + +require('traceur-source-maps').install(traceur); +traceur.require.makeDefault(function (filePath) { + return !~filePath.indexOf('node_modules'); +}); var gulp = require('gulp'); var protractor = require('gulp-protractor'); @@ -13,7 +19,8 @@ gulp.task('libs', [ 'lib-copy' ]); gulp.task('styles', [], require('./src/scripts/styles')); gulp.task('manifest', [ 'code', 'styles' ], require('./src/scripts/manifest')); gulp.task('selenium-update', protractor['webdriver_update']); -gulp.task('test', [ 'test-unit', 'test-e2e' ]); +gulp.task('test', [ 'test-unit', 'test-api', 'test-e2e' ]); gulp.task('test-unit', require('./src/scripts/test-unit')); +gulp.task('test-api', require('./src/scripts/test-api')); gulp.task('test-e2e', [ 'selenium-update' ], require('./src/scripts/test-e2e')); gulp.task('docs', require('./src/scripts/docs')); diff --git a/index.js b/index.js index a76e07b..3d38ec0 100644 --- a/index.js +++ b/index.js @@ -1,18 +1,19 @@ /* globals require, process, JSON, console */ +var traceur = require('traceur'); + +require('traceur-source-maps').install(traceur); +traceur.require.makeDefault(function (filePath) { + return !~filePath.indexOf('node_modules'); +}); + var config = require('./src/server/config'); console.log('process.env: ' + JSON.stringify(process.env, null)); console.log('config: ' + JSON.stringify(config, null)); -// Load up all the rest endpoints. -require('./src/server/rest'); - // start the server. -require('./src/server/express').listen(config.port, function() { - console.log('Starting application on port ' + config.port); - -}).on('error', function(error) { +require('./src/server/server').start().catch(function(error) { console.error(error.stack); }); diff --git a/package.json b/package.json index eacd664..50a09a5 100644 --- a/package.json +++ b/package.json @@ -31,26 +31,30 @@ "angular-ui-router": "~0.2.13", "angulartics": "^0.17.2", "bootstrap-sass": "^3.3.1", + "chai": "^3.2.0", + "es6-module-loader": "^0.17.6", "gulp": "^3.8.11", "gulp-angular-protractor": "0.0.2", "gulp-apidoc": "^0.1.4", "gulp-cache-manifest": "0.0.1", "gulp-clean": "^0.3.1", "gulp-concat": "^2.5.2", + "gulp-less": "^3.0.5", "gulp-minify-css": "^1.1.0", "gulp-mocha": "^2.1.0", "gulp-nodemon": "^1.0.4", "gulp-protractor": "^1.0.0", "gulp-rename": "^1.2.0", - "gulp-sass": "^1.2.4", "gulp-sourcemaps": "^1.5.2", "gulp-uglify": "^1.2.0", "gulp-util": "^3.0.5", "lunr": "^0.5.9", + "mocha-traceur": "^2.1.0", "moment": "^2.9.0", "ngstorage": "^0.3.4", "phantomjs": "^1.9.17", "protractor": "^2.1.0", + "request-promise": "^0.4.3", "requirejs": "^2.1.18", "requirejs-text": "^2.0.12", "sinon": "^1.15.3", @@ -58,19 +62,25 @@ "sockit-express": "aetheric/sockit-express", "stream-reduce": "~1.0.3", "through2": "^0.6.5", + "traceur": "0.0.91", "vinyl-sourcemaps-apply": "^0.1.4" }, "dependencies": { "body-parser": "^1.13.2", + "cypher-query": "0.0.12", "errorhandler": "^1.3.6", "express": "^4.11.0", + "express-hateoas": "0.1.x", "express-session": "^1.11.3", "helmet": "^0.9.1", "jade": "^1.11.0", - "neo4j": "^2.0.0-RC1", - "promise": "^7.0.1", + "neo4j-simple": "^0.7.12", + "node-sass": "^3.3.3", "session-file-store": "0.0.14", - "suit": "^0.4.0", - "underscore": "^1.8.3" + "traceur": "0.0.102", + "traceur-runner": "^2.0.1", + "traceur-source-maps": "^1.0.6", + "underscore": "^1.8.3", + "http-constants": "1.1.x" } } diff --git a/src/server/static/_imports.scss b/src/client/_imports.scss similarity index 100% rename from src/server/static/_imports.scss rename to src/client/_imports.scss diff --git a/src/server/static/action/action-submit-directive.js b/src/client/action/action-submit-directive.js similarity index 100% rename from src/server/static/action/action-submit-directive.js rename to src/client/action/action-submit-directive.js diff --git a/src/server/static/alert/alert-directive.js b/src/client/alert/alert-directive.js similarity index 100% rename from src/server/static/alert/alert-directive.js rename to src/client/alert/alert-directive.js diff --git a/src/server/static/alert/alert-service.js b/src/client/alert/alert-service.js similarity index 100% rename from src/server/static/alert/alert-service.js rename to src/client/alert/alert-service.js diff --git a/src/server/static/angular-bootstrap.js b/src/client/angular-bootstrap.js similarity index 100% rename from src/server/static/angular-bootstrap.js rename to src/client/angular-bootstrap.js diff --git a/src/server/static/angular-module.js b/src/client/angular-module.js similarity index 100% rename from src/server/static/angular-module.js rename to src/client/angular-module.js diff --git a/src/server/static/banner/_banner-style.scss b/src/client/banner/_banner-style.scss similarity index 100% rename from src/server/static/banner/_banner-style.scss rename to src/client/banner/_banner-style.scss diff --git a/src/server/static/banner/banner-directive.js b/src/client/banner/banner-directive.js similarity index 100% rename from src/server/static/banner/banner-directive.js rename to src/client/banner/banner-directive.js diff --git a/src/server/static/banner/banner-template.html b/src/client/banner/banner-template.html similarity index 100% rename from src/server/static/banner/banner-template.html rename to src/client/banner/banner-template.html diff --git a/src/server/static/components/account/account-detail.html b/src/client/components/account/account-detail.html similarity index 100% rename from src/server/static/components/account/account-detail.html rename to src/client/components/account/account-detail.html diff --git a/src/server/static/components/account/account-detail.js b/src/client/components/account/account-detail.js similarity index 100% rename from src/server/static/components/account/account-detail.js rename to src/client/components/account/account-detail.js diff --git a/src/server/static/components/account/account-service.js b/src/client/components/account/account-service.js similarity index 100% rename from src/server/static/components/account/account-service.js rename to src/client/components/account/account-service.js diff --git a/src/server/static/components/admin/admin-character-list.html b/src/client/components/admin/admin-character-list.html similarity index 100% rename from src/server/static/components/admin/admin-character-list.html rename to src/client/components/admin/admin-character-list.html diff --git a/src/server/static/components/admin/admin-character-list.js b/src/client/components/admin/admin-character-list.js similarity index 100% rename from src/server/static/components/admin/admin-character-list.js rename to src/client/components/admin/admin-character-list.js diff --git a/src/server/static/components/character/character-detail.html b/src/client/components/character/character-detail.html similarity index 100% rename from src/server/static/components/character/character-detail.html rename to src/client/components/character/character-detail.html diff --git a/src/server/static/components/character/character-detail.js b/src/client/components/character/character-detail.js similarity index 100% rename from src/server/static/components/character/character-detail.js rename to src/client/components/character/character-detail.js diff --git a/src/server/static/components/character/character-list.html b/src/client/components/character/character-list.html similarity index 100% rename from src/server/static/components/character/character-list.html rename to src/client/components/character/character-list.html diff --git a/src/server/static/components/character/character-list.js b/src/client/components/character/character-list.js similarity index 100% rename from src/server/static/components/character/character-list.js rename to src/client/components/character/character-list.js diff --git a/src/server/static/components/entities/entity-detail.html b/src/client/components/entities/entity-detail.html similarity index 100% rename from src/server/static/components/entities/entity-detail.html rename to src/client/components/entities/entity-detail.html diff --git a/src/server/static/components/entities/entity-detail.js b/src/client/components/entities/entity-detail.js similarity index 100% rename from src/server/static/components/entities/entity-detail.js rename to src/client/components/entities/entity-detail.js diff --git a/src/server/static/components/entities/entity-list.html b/src/client/components/entities/entity-list.html similarity index 100% rename from src/server/static/components/entities/entity-list.html rename to src/client/components/entities/entity-list.html diff --git a/src/server/static/components/entities/entity-list.js b/src/client/components/entities/entity-list.js similarity index 100% rename from src/server/static/components/entities/entity-list.js rename to src/client/components/entities/entity-list.js diff --git a/src/server/static/components/entities/entity-search.js b/src/client/components/entities/entity-search.js similarity index 100% rename from src/server/static/components/entities/entity-search.js rename to src/client/components/entities/entity-search.js diff --git a/src/client/docs/api_data.js b/src/client/docs/api_data.js new file mode 100644 index 0000000..122395a --- /dev/null +++ b/src/client/docs/api_data.js @@ -0,0 +1,38 @@ +define({ "api": [ + { + "type": "get", + "url": "/api/auth", + "title": "Checks that the authentication for the current user is valid.", + "name": "GetUser", + "group": "Authentication", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "

String

", + "optional": false, + "field": "email", + "description": "

The email of the user.

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "

Object

", + "optional": false, + "field": "user", + "description": "

The user record currently in the session.

" + } + ] + } + }, + "version": "0.0.0", + "filename": "src/server/api/auth/auth-check.js", + "groupTitle": "Authentication" + } +] }); \ No newline at end of file diff --git a/src/client/docs/api_data.json b/src/client/docs/api_data.json new file mode 100644 index 0000000..4dfcfde --- /dev/null +++ b/src/client/docs/api_data.json @@ -0,0 +1,38 @@ +[ + { + "type": "get", + "url": "/api/auth", + "title": "Checks that the authentication for the current user is valid.", + "name": "GetUser", + "group": "Authentication", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "

String

", + "optional": false, + "field": "email", + "description": "

The email of the user.

" + } + ] + } + }, + "success": { + "fields": { + "Success 200": [ + { + "group": "Success 200", + "type": "

Object

", + "optional": false, + "field": "user", + "description": "

The user record currently in the session.

" + } + ] + } + }, + "version": "0.0.0", + "filename": "src/server/api/auth/auth-check.js", + "groupTitle": "Authentication" + } +] \ No newline at end of file diff --git a/src/client/docs/api_project.js b/src/client/docs/api_project.js new file mode 100644 index 0000000..ed0de66 --- /dev/null +++ b/src/client/docs/api_project.js @@ -0,0 +1,13 @@ +define({ + "name": "animus", + "version": "0.0.1", + "description": "A management utility for the NZ Crucible LARP.", + "sampleUrl": false, + "apidoc": "0.2.0", + "generator": { + "name": "apidoc", + "time": "2015-07-08T22:09:25.946Z", + "url": "http://apidocjs.com", + "version": "0.13.1" + } +}); \ No newline at end of file diff --git a/src/client/docs/api_project.json b/src/client/docs/api_project.json new file mode 100644 index 0000000..e58f404 --- /dev/null +++ b/src/client/docs/api_project.json @@ -0,0 +1,13 @@ +{ + "name": "animus", + "version": "0.0.1", + "description": "A management utility for the NZ Crucible LARP.", + "sampleUrl": false, + "apidoc": "0.2.0", + "generator": { + "name": "apidoc", + "time": "2015-07-08T22:09:25.946Z", + "url": "http://apidocjs.com", + "version": "0.13.1" + } +} \ No newline at end of file diff --git a/src/client/docs/css/style.css b/src/client/docs/css/style.css new file mode 100644 index 0000000..cdf5f0c --- /dev/null +++ b/src/client/docs/css/style.css @@ -0,0 +1,538 @@ +/* ------------------------------------------------------------------------------------------ + * Content + * ------------------------------------------------------------------------------------------ */ +body { + min-width: 980px; + max-width: 1280px; +} + +body, p, a, div, th, td { + font-family: "Source Sans Pro", sans-serif; + font-weight: 400; + font-size: 16px; +} + +td.code { + font-size: 14px; + font-family: "Source Code Pro"; + font-style: normal; + font-weight: 400; +} + +#content { + padding-top: 16px; + z-Index: -1; + margin-left: 270px; +} + +p { + color: #808080; +} + +h1 { + font-family: "Source Sans Pro Semibold", sans-serif; + font-weight: normal; + font-size: 44px; + line-height: 50px; + margin: 0 0 10px 0; + padding: 0; +} + +h2 { + font-family: "Source Sans Pro", sans-serif; + font-weight: normal; + font-size: 24px; + line-height: 40px; + margin: 0 0 20px 0; + padding: 0; +} + +section { + border-top: 1px solid #ebebeb; + padding: 30px 0; +} + +section h1 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 700; + font-size: 32px; + line-height: 40px; + padding-bottom: 14px; + margin: 0 0 20px 0; + padding: 0; +} + +article { + padding: 14px 0 30px 0; +} + +article h1 { + font-family: "Source Sans Pro Bold", sans-serif; + font-weight: 600; + font-size: 24px; + line-height: 26px; +} + +article h2 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + font-size: 18px; + line-height: 24px; + margin: 0 0 10px 0; +} + +article h3 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + font-size: 16px; + line-height: 18px; + margin: 0 0 10px 0; +} + +article h4 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + font-size: 14px; + line-height: 16px; + margin: 0 0 8px 0; +} + +table { + border-collapse: collapse; + width: 100%; + margin: 0 0 20px 0; +} + +th { + background-color: #f5f5f5; + text-align: left; + font-family: "Source Sans Pro", sans-serif; + font-weight: 700; + padding: 4px 8px; + border: #e0e0e0 1px solid; +} + +td { + vertical-align: top; + padding: 2px 8px; + border: #e0e0e0 1px solid; +} + +#generator .content { + color: #b0b0b0; + border-top: 1px solid #ebebeb; + padding: 10px 0; +} + +.label-optional { + float: right; +} + +.open-left { + right: 0; + left: auto; +} + +/* ------------------------------------------------------------------------------------------ + * apidoc - intro + * ------------------------------------------------------------------------------------------ */ + +#apidoc .apidoc { + border-top: 1px solid #ebebeb; + padding: 30px 0; +} + +#apidoc h1 { + font-family: "Source Sans Pro", sans-serif; + font-weight: 700; + font-size: 32px; + line-height: 40px; + padding-bottom: 14px; + margin: 0 0 20px 0; + padding: 0; +} + +#apidoc h2 { + font-family: "Source Sans Pro Bold", sans-serif; + font-weight: 600; + font-size: 22px; + line-height: 26px; + padding-top: 14px; +} + +/* ------------------------------------------------------------------------------------------ + * pre / code + * ------------------------------------------------------------------------------------------ */ +pre { + background-color: #292b36; + color: #ffffff; + padding: 10px; + border-radius: 6px; + position: relative; + margin: 10px 0 20px 0; +} + +code.language-text { + word-wrap: break-word; +} + +pre.language-json { + overflow: auto; +} + +pre.language-html { + margin: 40px 0 20px 0; +} + +pre.language-html:before { + content: attr(data-type); + position: absolute; + top: -30px; + left: 0; + font-family: "Source Sans Pro", sans-serif; + font-weight: 600; + font-size: 15px; + display: inline-block; + padding: 2px 5px; + border-radius: 6px; + text-transform: uppercase; + background-color: #3387CC; + color: #ffffff; +} + +pre.language-html[data-type="get"]:before { + background-color: green; +} + +pre.language-html[data-type="put"]:before { + background-color: #e5c500; +} + +pre.language-html[data-type="post"]:before { + background-color: #4070ec; +} + +pre.language-html[data-type="delete"]:before { + background-color: #ed0039; +} + +pre.language-api .str { + color: #ffffff; +} + +pre.language-api .pln, +pre.language-api .pun { + color: #65B042; +} + +pre code { + display: block; + font-size: 14px; + font-family: "Source Code Pro"; + font-style: normal; + font-weight: 400; + word-wrap: normal; + white-space: pre; +} + +/* +pre.language-json { + background: #f5f5f5; + border: #e0e0e0 1px solid; +} + +pre.language-json .pln, +pre.language-json .pun { + color: #3a3a3a; +} +*/ + +/* ------------------------------------------------------------------------------------------ + * Sidenav + * ------------------------------------------------------------------------------------------ */ +.sidenav { + width: 228px; + margin: 0; + padding: 20px; + position: fixed; + top: 0; + left: 0; + bottom: 0; + overflow-x: hidden; + overflow-y: auto; + background-color: #f5f5f5; + z-index: 10; +} + +.sidenav > li > a { + display: block; + width: 192px; + margin: 0; + padding: 2px 11px; + border: 0; + border-left: transparent 4px solid; + border-right: transparent 4px solid; + font-family: "Source Sans Pro", sans-serif; + font-weight: 400; + font-size: 14px; +} + +.sidenav > li.nav-header > a { + padding: 5px 15px; + border: 1px solid #e5e5e5; + width: 190px; + font-family: "Source Sans Pro", sans-serif; + font-weight: 700; + font-size: 16px; + background-color: #ffffff; +} + +.sidenav > li.nav-header.active > a { + background-color: #0088cc; +} + +.sidenav > .active > a { + position: relative; + z-index: 2; +} + +.sidenav > li > a:hover { + background-color: #ffffff; +} + +.sidenav > li.has-modifications a { + border-right: #60d060 4px solid; +} + +.sidenav > li.is-new a { + border-left: #e5e5e5 4px solid; +} + +/* ------------------------------------------------------------------------------------------ + * Compare + * ------------------------------------------------------------------------------------------ */ + +ins { + background: #60d060; + text-decoration: none; + color: #000000; +} + +del { + background: #f05050; + color: #000000; +} + +.label-ins { + background-color: #60d060; +} + +.label-del { + background-color: #f05050; + text-decoration: line-through; +} + +pre.ins { + background-color: #60d060; +} + +pre.del { + background-color: #f05050; + text-decoration: line-through; +} + +table.ins th, +table.ins td { + background-color: #60d060; +} + +table.del th, +table.del td { + background-color: #f05050; + text-decoration: line-through; +} + +tr.ins td { + background-color: #60d060; +} + +tr.del td { + background-color: #f05050; + text-decoration: line-through; +} + +/* ------------------------------------------------------------------------------------------ + * Spinner + * ------------------------------------------------------------------------------------------ */ + +#loader { + position: absolute; + width: 100%; +} + +#loader p { + padding-top: 80px; + margin-left: -4px; +} + +.spinner { + margin: 200px auto; + width: 60px; + height: 60px; + position: relative; +} + +.container1 > div, .container2 > div, .container3 > div { + width: 14px; + height: 14px; + background-color: #0088cc; + + border-radius: 100%; + position: absolute; + -webkit-animation: bouncedelay 1.2s infinite ease-in-out; + animation: bouncedelay 1.2s infinite ease-in-out; + /* Prevent first frame from flickering when animation starts */ + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +.spinner .spinner-container { + position: absolute; + width: 100%; + height: 100%; +} + +.container2 { + -webkit-transform: rotateZ(45deg); + transform: rotateZ(45deg); +} + +.container3 { + -webkit-transform: rotateZ(90deg); + transform: rotateZ(90deg); +} + +.circle1 { top: 0; left: 0; } +.circle2 { top: 0; right: 0; } +.circle3 { right: 0; bottom: 0; } +.circle4 { left: 0; bottom: 0; } + +.container2 .circle1 { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; +} + +.container3 .circle1 { + -webkit-animation-delay: -1.0s; + animation-delay: -1.0s; +} + +.container1 .circle2 { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; +} + +.container2 .circle2 { + -webkit-animation-delay: -0.8s; + animation-delay: -0.8s; +} + +.container3 .circle2 { + -webkit-animation-delay: -0.7s; + animation-delay: -0.7s; +} + +.container1 .circle3 { + -webkit-animation-delay: -0.6s; + animation-delay: -0.6s; +} + +.container2 .circle3 { + -webkit-animation-delay: -0.5s; + animation-delay: -0.5s; +} + +.container3 .circle3 { + -webkit-animation-delay: -0.4s; + animation-delay: -0.4s; +} + +.container1 .circle4 { + -webkit-animation-delay: -0.3s; + animation-delay: -0.3s; +} + +.container2 .circle4 { + -webkit-animation-delay: -0.2s; + animation-delay: -0.2s; +} + +.container3 .circle4 { + -webkit-animation-delay: -0.1s; + animation-delay: -0.1s; +} + +@-webkit-keyframes bouncedelay { + 0%, 80%, 100% { -webkit-transform: scale(0.0) } + 40% { -webkit-transform: scale(1.0) } +} + +@keyframes bouncedelay { + 0%, 80%, 100% { + transform: scale(0.0); + -webkit-transform: scale(0.0); + } 40% { + transform: scale(1.0); + -webkit-transform: scale(1.0); + } +} + +/* ------------------------------------------------------------------------------------------ + * Tabs + * ------------------------------------------------------------------------------------------ */ +ul.nav-tabs { + margin: 0; +} + +/* ------------------------------------------------------------------------------------------ + * Print + * ------------------------------------------------------------------------------------------ */ + +@media print { + + #sidenav, + #version, + #versions, + section .version, + section .versions { + display: none; + } + + #content { + margin-left: 0; + } + + a { + text-decoration: none; + color: inherit; + } + + a:after { + content: " [" attr(href) "] "; + } + + p { + color: #000000 + } + + pre { + background-color: #ffffff; + color: #000000; + padding: 10px; + border: #808080 1px solid; + border-radius: 6px; + position: relative; + margin: 10px 0 20px 0; + } + +} /* /@media print */ diff --git a/src/client/docs/img/favicon.ico b/src/client/docs/img/favicon.ico new file mode 100644 index 0000000..c307a04 Binary files /dev/null and b/src/client/docs/img/favicon.ico differ diff --git a/src/client/docs/img/glyphicons-halflings-white.png b/src/client/docs/img/glyphicons-halflings-white.png new file mode 100644 index 0000000..3bf6484 Binary files /dev/null and b/src/client/docs/img/glyphicons-halflings-white.png differ diff --git a/src/client/docs/img/glyphicons-halflings.png b/src/client/docs/img/glyphicons-halflings.png new file mode 100644 index 0000000..a996999 Binary files /dev/null and b/src/client/docs/img/glyphicons-halflings.png differ diff --git a/src/client/docs/index.html b/src/client/docs/index.html new file mode 100644 index 0000000..8a2b95d --- /dev/null +++ b/src/client/docs/index.html @@ -0,0 +1,658 @@ + + + + Loading... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+

Loading...

+
+
+ + + + diff --git a/src/client/docs/locales/de.js b/src/client/docs/locales/de.js new file mode 100644 index 0000000..f66420d --- /dev/null +++ b/src/client/docs/locales/de.js @@ -0,0 +1,25 @@ +define({ + de: { + 'Allowed values:' : 'Erlaubte Werte:', + 'Compare all with predecessor': 'Vergleiche alle mit ihren Vorgängern', + 'compare changes to:' : 'vergleiche Änderungen mit:', + 'compared to' : 'verglichen mit', + 'Default value:' : 'Standardwert:', + 'Description' : 'Beschreibung', + 'Field' : 'Feld', + 'General' : 'Allgemein', + 'Generated with' : 'Erstellt mit', + 'Name' : 'Name', + 'No response values.' : 'Keine Rückgabewerte.', + 'optional' : 'optional', + 'Parameter' : 'Parameter', + 'Permission:' : 'Berechtigung:', + 'Response' : 'Antwort', + 'Send' : 'Senden', + 'Send a Sample Request' : 'Eine Beispielanfrage senden', + 'show up to version:' : 'zeige bis zur Version:', + 'Size range:' : 'Größenbereich:', + 'Type' : 'Typ', + 'url' : 'url' + } +}); diff --git a/src/client/docs/locales/fr.js b/src/client/docs/locales/fr.js new file mode 100644 index 0000000..280bec7 --- /dev/null +++ b/src/client/docs/locales/fr.js @@ -0,0 +1,25 @@ +define({ + fr: { + 'Allowed values:' : 'Valeurs autorisées :', + 'Compare all with predecessor': 'Tout comparer avec ...', + 'compare changes to:' : 'comparer les changements à :', + 'compared to' : 'comparer à', + 'Default value:' : 'Valeur par défaut :', + 'Description' : 'Description', + 'Field' : 'Champ', + 'General' : 'Général', + 'Generated with' : 'Généré avec', + 'Name' : 'Nom', + 'No response values.' : 'Aucune valeur de réponse.', + 'optional' : 'optionel', + 'Parameter' : 'Paramètre', + 'Permission:' : 'Permission :', + 'Response' : 'Réponse', + 'Send' : 'Envoyer', + 'Send a Sample Request' : 'Envoyer une requête représentative', + 'show up to version:' : 'Montrer à partir de la version :', + 'Size range:' : 'Ordre de grandeur :', + 'Type' : 'Type', + 'url' : 'url' + } +}); \ No newline at end of file diff --git a/src/client/docs/locales/locale.js b/src/client/docs/locales/locale.js new file mode 100644 index 0000000..366e980 --- /dev/null +++ b/src/client/docs/locales/locale.js @@ -0,0 +1,43 @@ +define([ + './locales/de.js', + './locales/fr.js', + './locales/nl.js', + './locales/pl.js', + './locales/pt_br.js', + './locales/ru.js', + './locales/zh.js' +], function() { + var langId = (navigator.language || navigator.userLanguage).toLowerCase(); + var language = langId.substr(0, 2); + var locales = {}; + + for (index in arguments) { + for (property in arguments[index]) + locales[property] = arguments[index][property]; + } + if ( ! locales['en']) + locales['en'] = {}; + + if ( ! locales[langId] && ! locales[language]) + language = 'en'; + + var locale = (locales[langId] ? locales[langId] : locales[language]); + + function __(text) { + var index = locale[text]; + if (index === undefined) + return text; + return index; + }; + + function setLanguage(language) { + locale = locales[language]; + } + + return { + __ : __, + locales : locales, + locale : locale, + setLanguage: setLanguage + }; +}); diff --git a/src/client/docs/locales/nl.js b/src/client/docs/locales/nl.js new file mode 100644 index 0000000..bddfeeb --- /dev/null +++ b/src/client/docs/locales/nl.js @@ -0,0 +1,25 @@ +define({ + nl: { + 'Allowed values:' : 'Toegestane waarden:', + 'Compare all with predecessor': 'Vergelijk alle met voorgaande versie', + 'compare changes to:' : 'vergelijk veranderingen met:', + 'compared to' : 'vergelijk met', + 'Default value:' : 'Standaard waarde:', + 'Description' : 'Omschrijving', + 'Field' : 'Veld', + 'General' : 'Algemeen', + 'Generated with' : 'Gegenereerd met', + 'Name' : 'Naam', + 'No response values.' : 'Geen response waardes.', + 'optional' : 'optioneel', + 'Parameter' : 'Parameter', + 'Permission:' : 'Permissie:', + 'Response' : 'Antwoorden', + 'Send' : 'Sturen', + 'Send a Sample Request' : 'Stuur een sample aanvragen', + 'show up to version:' : 'toon tot en met versie:', + 'Size range:' : 'Maatbereik:', + 'Type' : 'Type', + 'url' : 'url' + } +}); diff --git a/src/client/docs/locales/pl.js b/src/client/docs/locales/pl.js new file mode 100644 index 0000000..1cda0da --- /dev/null +++ b/src/client/docs/locales/pl.js @@ -0,0 +1,25 @@ +define({ + pl: { + 'Allowed values:' : 'Dozwlone wartości:', + 'Compare all with predecessor': 'Porównaj z poprzednimi wersjami', + 'compare changes to:' : 'porównaj zmiany do:', + 'compared to' : 'porównaj do:', + 'Default value:' : 'Wartość domyślna:', + 'Description' : 'Opis', + 'Field' : 'Pole', + 'General' : 'Generalnie', + 'Generated with' : 'Wygenerowano z', + 'Name' : 'Nazwa', + 'No response values.' : 'Brak odpowiedzi.', + 'optional' : 'opcjonalny', + 'Parameter' : 'Parametr', + 'Permission:' : 'Uprawnienia:', + 'Response' : 'Odpowiedź', + 'Send' : 'Wyślij', + 'Send a Sample Request' : 'Wyślij przykładowe żądanie', + 'show up to version:' : 'pokaż do wersji:', + 'Size range:' : 'Zakres rozmiaru:', + 'Type' : 'Typ', + 'url' : 'url' + } +}); diff --git a/src/client/docs/locales/pt_br.js b/src/client/docs/locales/pt_br.js new file mode 100644 index 0000000..2bd78b0 --- /dev/null +++ b/src/client/docs/locales/pt_br.js @@ -0,0 +1,25 @@ +define({ + 'pt_br': { + 'Allowed values:' : 'Valores permitidos:', + 'Compare all with predecessor': 'Compare todos com antecessores', + 'compare changes to:' : 'comparar alterações com:', + 'compared to' : 'comparado com', + 'Default value:' : 'Valor padrão:', + 'Description' : 'Descrição', + 'Field' : 'Campo', + 'General' : 'Geral', + 'Generated with' : 'Gerado com', + 'Name' : 'Nome', + 'No response values.' : 'Sem valores de resposta.', + 'optional' : 'opcional', + 'Parameter' : 'Parâmetro', + 'Permission:' : 'Permissão:', + 'Response' : 'Resposta', + 'Send' : 'Enviar', + 'Send a Sample Request' : 'Enviar um Exemplo de Pedido', + 'show up to version:' : 'aparecer para a versão:', + 'Size range:' : 'Faixa de tamanho:', + 'Type' : 'Tipo', + 'url' : 'url' + } +}); diff --git a/src/client/docs/locales/ru.js b/src/client/docs/locales/ru.js new file mode 100644 index 0000000..c5f3382 --- /dev/null +++ b/src/client/docs/locales/ru.js @@ -0,0 +1,25 @@ +define({ + ru: { + 'Allowed values:' : 'Допустимые значения:', + 'Compare all with predecessor': 'Сравнить с предыдущей версией', + 'compare changes to:' : 'сравнить с:', + 'compared to' : 'в сравнении с', + 'Default value:' : 'По умолчанию:', + 'Description' : 'Описание', + 'Field' : 'Название', + 'General' : 'Общая информация', + 'Generated with' : 'Сгенерировано с помощью', + 'Name' : 'Название', + 'No response values.' : 'Нет значений для ответа.', + 'optional' : 'необязательный', + 'Parameter' : 'Параметр', + 'Permission:' : 'Разрешено:', + 'Response' : 'Ответ', + 'Send' : 'Отправить', + 'Send a Sample Request' : 'Отправить тестовый запрос', + 'show up to version:' : 'показать версию:', + 'Size range:' : 'Ограничения:', + 'Type' : 'Тип', + 'url' : 'URL' + } +}); diff --git a/src/client/docs/locales/zh.js b/src/client/docs/locales/zh.js new file mode 100644 index 0000000..91d85c3 --- /dev/null +++ b/src/client/docs/locales/zh.js @@ -0,0 +1,25 @@ +define({ + zh: { + 'Allowed values:' : '允許值:', + 'Compare all with predecessor': '预先比较所有', + 'compare changes to:' : '比较变更:', + 'compared to' : '对比', + 'Default value:' : '默认值:', + 'Description' : '描述', + 'Field' : '字段', + 'General' : '概括', + 'Generated with' : '生成工具', + 'Name' : '名称', + 'No response values.' : '无响应值.', + 'optional' : '选项', + 'Parameter' : '参数', + 'Permission:' : '允许:', + 'Response' : '響應', + 'Send' : '發送', + 'Send a Sample Request' : '發送樣品申請', + 'show up to version:' : '显示到版本:', + 'Size range:' : '尺寸範圍:', + 'Type' : '类型', + 'url' : '網址' + } +}); diff --git a/src/client/docs/main.js b/src/client/docs/main.js new file mode 100644 index 0000000..01e1cb8 --- /dev/null +++ b/src/client/docs/main.js @@ -0,0 +1,691 @@ +require.config({ + paths: { + bootstrap: './vendor/bootstrap.min', + diffMatchPatch: './vendor/diff_match_patch.min', + handlebars: './vendor/handlebars.min', + handlebarsExtended: './utils/handlebars_helper', + jquery: './vendor/jquery.min', + locales: './locales/locale', + lodash: './vendor/lodash.min', + pathToRegexp: './vendor/path-to-regexp/index', + prettify: './vendor/prettify/prettify', + utilsSampleRequest: './utils/send_sample_request', + }, + shim: { + bootstrap: { + deps: ['jquery'] + }, + diffMatchPatch: { + exports: 'diff_match_patch' + }, + handlebars: { + exports: 'Handlebars' + }, + handlebarsExtended: { + deps: ['jquery', 'handlebars'], + exports: 'Handlebars' + }, + prettify: { + exports: 'prettyPrint' + } + }, + urlArgs: 'v=' + (new Date()).getTime(), + waitSeconds: 15 +}); + +require([ + 'jquery', + 'lodash', + 'locales', + 'handlebarsExtended', + './api_project.js', + './api_data.js', + 'prettify', + 'utilsSampleRequest', + 'bootstrap', + 'pathToRegexp' +], function($, _, locale, Handlebars, apiProject, apiData, prettyPrint, sampleRequest) { + + // load google web fonts + loadGoogleFontCss(); + + var api = apiData.api; + + // + // Templates + // + var templateHeader = Handlebars.compile( $('#template-header').html() ); + var templateFooter = Handlebars.compile( $('#template-footer').html() ); + var templateArticle = Handlebars.compile( $('#template-article').html() ); + var templateCompareArticle = Handlebars.compile( $('#template-compare-article').html() ); + var templateGenerator = Handlebars.compile( $('#template-generator').html() ); + var templateProject = Handlebars.compile( $('#template-project').html() ); + var templateSections = Handlebars.compile( $('#template-sections').html() ); + var templateSidenav = Handlebars.compile( $('#template-sidenav').html() ); + + // + // apiProject defaults + // + if ( ! apiProject.template) + apiProject.template = {}; + + if (apiProject.template.withCompare == null) + apiProject.template.withCompare = true; + + if (apiProject.template.withGenerator == null) + apiProject.template.withGenerator = true; + + if (apiProject.template.forceLanguage) + locale.setLanguage(apiProject.template.forceLanguage); + + // Setup jQuery Ajax + $.ajaxSetup(apiProject.template.jQueryAjaxSetup); + + // + // Data transform + // + // grouped by group + var apiByGroup = _.groupBy(api, function(entry) { + return entry.group; + }); + + // grouped by group and name + var apiByGroupAndName = {}; + $.each(apiByGroup, function(index, entries) { + apiByGroupAndName[index] = _.groupBy(entries, function(entry) { + return entry.name; + }); + }); + + // + // sort api within a group by title ASC and custom order + // + var newList = []; + var umlauts = { 'ä': 'ae', 'ü': 'ue', 'ö': 'oe', 'ß': 'ss' }; // TODO: remove in version 1.0 + $.each (apiByGroupAndName, function(index, groupEntries) { + // get titles from the first entry of group[].name[] (name has versioning) + var titles = []; + $.each (groupEntries, function(titleName, entries) { + var title = entries[0].title; + if(title !== undefined) { + title.toLowerCase().replace(/[äöüß]/g, function($0) { return umlauts[$0]; }); + titles.push(title + '#~#' + titleName); // '#~#' keep reference to titleName after sorting + } + }); + // sort by name ASC + titles.sort(); + + // custom order + if (apiProject.order) + titles = sortByOrder(titles, apiProject.order, '#~#'); + + // add single elements to the new list + titles.forEach(function(name) { + var values = name.split('#~#'); + var key = values[1]; + groupEntries[key].forEach(function(entry) { + newList.push(entry); + }); + }); + }); + // api overwrite with ordered list + api = newList; + + // + // Group- and Versionlists + // + var apiGroups = {}; + var apiGroupTitles = {}; + var apiVersions = {}; + apiVersions[apiProject.version] = 1; + + $.each(api, function(index, entry) { + apiGroups[entry.group] = 1; + apiGroupTitles[entry.group] = entry.groupTitle || entry.group; + apiVersions[entry.version] = 1; + }); + + // sort groups + apiGroups = Object.keys(apiGroups); + apiGroups.sort(); + + // custom order + if (apiProject.order) + apiGroups = sortByOrder(apiGroups, apiProject.order); + + // sort versions DESC + apiVersions = Object.keys(apiVersions); + apiVersions.sort(); + apiVersions.reverse(); + + // + // create Navigationlist + // + var nav = []; + apiGroups.forEach(function(group) { + // Mainmenu entry + nav.push({ + group: group, + isHeader: true, + title: apiGroupTitles[group] + }); + + // Submenu + var oldName = ''; + api.forEach(function(entry) { + if (entry.group === group) { + if (oldName !== entry.name) { + nav.push({ + title: entry.title, + group: group, + name: entry.name, + type: entry.type, + version: entry.version + }); + } else { + nav.push({ + title: entry.title, + group: group, + hidden: true, + name: entry.name, + type: entry.type, + version: entry.version + }); + } + oldName = entry.name; + } + }); + }); + + // Mainmenu Header entry + if (apiProject.header) { + nav.unshift({ + group: '_', + isHeader: true, + title: (apiProject.header.title == null) ? locale.__('General') : apiProject.header.title, + isFixed: true + }); + } + + // Mainmenu Footer entry + if (apiProject.footer && apiProject.footer.title != null) { + nav.push({ + group: '_footer', + isHeader: true, + title: apiProject.footer.title, + isFixed: true + }); + } + + // render pagetitle + var title = apiProject.title ? apiProject.title : 'apiDoc: ' + apiProject.name + ' - ' + apiProject.version; + $(document).attr('title', title); + + // remove loader + $('#loader').remove(); + + // render sidenav + var fields = { + nav: nav + }; + $('#sidenav').append( templateSidenav(fields) ); + + // render Generator + $('#generator').append( templateGenerator(apiProject) ); + + // render Project + _.extend(apiProject, { versions: apiVersions}); + $('#project').append( templateProject(apiProject) ); + + // render apiDoc, header/footer documentation + if (apiProject.header) + $('#header').append( templateHeader(apiProject.header) ); + + if (apiProject.footer) + $('#footer').append( templateFooter(apiProject.footer) ); + + // + // Render Sections and Articles + // + var articleVersions = {}; + var content = ''; + apiGroups.forEach(function(groupEntry) { + var articles = []; + var oldName = ''; + var fields = {}; + var title = groupEntry; + var description = ''; + articleVersions[groupEntry] = {}; + + // render all articles of a group + api.forEach(function(entry) { + if(groupEntry === entry.group) { + if (oldName !== entry.name) { + // determine versions + api.forEach(function(versionEntry) { + if (groupEntry === versionEntry.group && entry.name === versionEntry.name) { + if ( ! articleVersions[entry.group][entry.name]) + articleVersions[entry.group][entry.name] = []; + + articleVersions[entry.group][entry.name].push(versionEntry.version); + } + }); + fields = { + article: entry, + versions: articleVersions[entry.group][entry.name] + }; + } else { + fields = { + article: entry, + hidden: true, + versions: articleVersions[entry.group][entry.name] + }; + } + + // add prefix URL for endpoint + if (apiProject.url) + fields.article.url = apiProject.url + fields.article.url; + + addArticleSettings(fields, entry); + + if (entry.groupTitle) + title = entry.groupTitle; + + // TODO: make groupDescription compareable with older versions (not important for the moment) + if (entry.groupDescription) + description = entry.groupDescription; + + articles.push({ + article: templateArticle(fields), + group: entry.group, + name: entry.name + }); + oldName = entry.name; + } + }); + + // render Section with Articles + var fields = { + group: groupEntry, + title: title, + description: description, + articles: articles + }; + content += templateSections(fields); + }); + $('#sections').append( content ); + + // Bootstrap Scrollspy + var $scrollSpy = $(this).scrollspy({ target: '#scrollingNav', offset: 18 }); + $('[data-spy="scroll"]').each(function () { + $scrollSpy('refresh'); + }); + + // Content-Scroll on Navigation click. + $('.sidenav').find('a').on('click', function(e) { + e.preventDefault(); + var id = $(this).attr('href'); + if ($(id).length > 0) + $('html,body').animate({ scrollTop: parseInt($(id).offset().top) }, 400); + window.location.hash = $(this).attr('href'); + }); + + // Quickjump on Pageload to hash position. + if(window.location.hash) { + var id = window.location.hash; + if ($(id).length > 0) + $('html,body').animate({ scrollTop: parseInt($(id).offset().top) }, 0); + } + + /** + * Check if Parameter (sub) List has a type Field. + * Example: @apiSuccess varname1 No type. + * @apiSuccess {String} varname2 With type. + * + * @param {Object} fields + */ + function _hasTypeInFields(fields) { + var result = false; + $.each(fields, function(name) { + if (_.any(fields[name], function(item) { return item.type; }) ) + result = true; + }); + return result; + } + + /** + * On Template changes, recall plugins. + */ + function initDynamic() { + // bootstrap popover + $('a[data-toggle=popover]') + .popover() + .click(function(e) { + e.preventDefault(); + }) + ; + + var version = $('#version strong').html(); + $('#sidenav li').removeClass('is-new'); + if (apiProject.template.withCompare) { + $('#sidenav li[data-version=\'' + version + '\']').each(function(){ + var group = $(this).data('group'); + var name = $(this).data('name'); + var length = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').length; + var index = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').index($(this)); + if (length === 1 || index === (length - 1)) + $(this).addClass('is-new'); + }); + } + + // tabs + $('.nav-tabs-examples a').click(function (e) { + e.preventDefault(); + $(this).tab('show'); + }); + $('.nav-tabs-examples').find('a:first').tab('show'); + + // sample request switch + $('.sample-request-switch').click(function (e) { + var name = '.' + $(this).attr('name') + '-fields'; + $(name).addClass('hide'); + $(this).parent().next(name).removeClass('hide'); + }); + + // init modules + sampleRequest.initDynamic(); + } + initDynamic(); + + // Pre- / Code-Format + prettyPrint(); + + // + // HTML-Template specific jQuery-Functions + // + // Change Main Version + $('#versions li.version a').on('click', function(e) { + e.preventDefault(); + + var selectedVersion = $(this).html(); + $('#version strong').html(selectedVersion); + + // hide all + $('article').addClass('hide'); + $('#sidenav li:not(.nav-fixed)').addClass('hide'); + + // show 1st equal or lower Version of each entry + $('article[data-version]').each(function(index) { + var group = $(this).data('group'); + var name = $(this).data('name'); + var version = $(this).data('version'); + + if (version <= selectedVersion) { + if($('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible').length === 0) { + // enable Article + $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide'); + // enable Navigation + $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide'); + $('#sidenav li.nav-header[data-group=\'' + group + '\']').removeClass('hide'); + } + } + }); + + initDynamic(); + return; + }); + + // compare all article with their predecessor + $('#compareAllWithPredecessor').on('click', changeAllVersionCompareTo); + + // change version of an article + $('article .versions li.version a').on('click', changeVersionCompareTo); + + // compare url-parameter + $.urlParam = function(name) { + var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href); + return (results && results[1]) ? results[1] : null; + }; + + if ($.urlParam('compare')) { + // URL Paramter ?compare=1 is set + $('#compareAllWithPredecessor').trigger('click'); + + if (window.location.hash) { + var id = window.location.hash; + $('html,body').animate({ scrollTop: parseInt($(id).offset().top) - 18 }, 0); + } + } + + /** + * Change version of an article to compare it to an other version. + */ + function changeVersionCompareTo(e) { + e.preventDefault(); + + var $root = $(this).parents('article'); + var selectedVersion = $(this).html(); + var $button = $root.find('.version'); + var currentVersion = $button.find('strong').html(); + $button.find('strong').html(selectedVersion); + + var group = $root.data('group'); + var name = $root.data('name'); + var version = $root.data('version'); + + var compareVersion = $root.data('compare-version'); + + if (compareVersion === selectedVersion) + return; + + if ( ! compareVersion && version == selectedVersion) + return; + + if (compareVersion && articleVersions[group][name][0] === selectedVersion || version === selectedVersion) { + // the version of the entry is set to the highest version (reset) + resetArticle(group, name, version); + } else { + var $compareToArticle = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + selectedVersion + '\']'); + + var sourceEntry = {}; + var compareEntry = {}; + $.each(apiByGroupAndName[group][name], function(index, entry) { + if (entry.version === version) + sourceEntry = entry; + if (entry.version === selectedVersion) + compareEntry = entry; + }); + + var fields = { + article: sourceEntry, + compare: compareEntry, + versions: articleVersions[group][name] + }; + + // add unique id + // TODO: replace all group-name-version in template with id. + fields.article.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version; + fields.article.id = fields.article.id.replace(/\./g, '_'); + + fields.compare.id = fields.compare.group + '-' + fields.compare.name + '-' + fields.compare.version; + fields.compare.id = fields.compare.id.replace(/\./g, '_'); + + var entry = sourceEntry; + if (entry.parameter && entry.parameter.fields) + fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); + + if (entry.error && entry.error.fields) + fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); + + if (entry.success && entry.success.fields) + fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); + + if (entry.info && entry.info.fields) + fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); + + var entry = compareEntry; + if (fields._hasTypeInParameterFields !== true && entry.parameter && entry.parameter.fields) + fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); + + if (fields._hasTypeInErrorFields !== true && entry.error && entry.error.fields) + fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); + + if (fields._hasTypeInSuccessFields !== true && entry.success && entry.success.fields) + fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); + + if (fields._hasTypeInInfoFields !== true && entry.info && entry.info.fields) + fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); + + var content = templateCompareArticle(fields); + $root.after(content); + var $content = $root.next(); + + // Event on.click re-assign + $content.find('.versions li.version a').on('click', changeVersionCompareTo); + + // select navigation + $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + currentVersion + '\']').addClass('has-modifications'); + + $root.remove(); + // TODO: on change main version or select the highest version re-render + } + + initDynamic(); + } + + /** + * Compare all currently selected Versions with their predecessor. + */ + function changeAllVersionCompareTo(e) { + e.preventDefault(); + $('article:visible .versions').each(function(){ + var $root = $(this).parents('article'); + var currentVersion = $root.data('version'); + var $foundElement = null; + $(this).find('li.version a').each(function() { + var selectVersion = $(this).html(); + if (selectVersion < currentVersion && ! $foundElement) + $foundElement = $(this); + }); + + if($foundElement) + $foundElement.trigger('click'); + }); + initDynamic(); + } + + /** + * Add article settings. + */ + function addArticleSettings(fields, entry) { + // add unique id + // TODO: replace all group-name-version in template with id. + fields.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version; + fields.id = fields.id.replace(/\./g, '_'); + + if (entry.header && entry.header.fields) + fields._hasTypeInHeaderFields = _hasTypeInFields(entry.header.fields); + + if (entry.parameter && entry.parameter.fields) + fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); + + if (entry.error && entry.error.fields) + fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); + + if (entry.success && entry.success.fields) + fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); + + if (entry.info && entry.info.fields) + fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); + + // add template settings + fields.template = apiProject.template; + } + + /** + * Render Article. + */ + function renderArticle(group, name, version) { + var entry = {}; + $.each(apiByGroupAndName[group][name], function(index, currentEntry) { + if (currentEntry.version === version) + entry = currentEntry; + }); + var fields = { + article: entry, + versions: articleVersions[group][name] + }; + + addArticleSettings(fields, entry); + + return templateArticle(fields); + } + + /** + * Render original Article and remove the current visible Article. + */ + function resetArticle(group, name, version) { + var $root = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible'); + var content = renderArticle(group, name, version); + + $root.after(content); + var $content = $root.next(); + + // Event on.click muss neu zugewiesen werden (sollte eigentlich mit on automatisch funktionieren... sollte) + $content.find('.versions li.version a').on('click', changeVersionCompareTo); + + $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('has-modifications'); + + $root.remove(); + return; + } + + /** + * Load google fonts. + */ + function loadGoogleFontCss() { + var host = document.location.hostname.toLowerCase(); + var protocol = document.location.protocol.toLowerCase(); + var googleCss = '//fonts.googleapis.com/css?family=Source+Code+Pro|Source+Sans+Pro:400,600,700'; + if (host == 'localhost' || !host.length || protocol === 'file:') + googleCss = 'http:' + googleCss; + + $('', { + rel: 'stylesheet', + type: 'text/css', + href: googleCss + }).appendTo('head'); + } + + /** + * Return ordered entries by custom order and append not defined entries to the end. + * @param {String[]} elements + * @param {String[]} order + * @param {String} splitBy + * @return {String[]} Custom ordered list. + */ + function sortByOrder(elements, order, splitBy) { + var results = []; + order.forEach (function(name) { + if (splitBy) + elements.forEach (function(element) { + var parts = element.split(splitBy); + var key = parts[1]; // reference keep for sorting + if (key == name) + results.push(element); + }); + else + elements.forEach (function(key) { + if (key == name) + results.push(name); + }); + }); + // Append all other entries that ar not defined in order + elements.forEach(function(element) { + if (results.indexOf(element) === -1) + results.push(element); + }); + return results; + } + +}); diff --git a/src/client/docs/utils/handlebars_helper.js b/src/client/docs/utils/handlebars_helper.js new file mode 100644 index 0000000..b01113b --- /dev/null +++ b/src/client/docs/utils/handlebars_helper.js @@ -0,0 +1,327 @@ +define([ + 'locales', + 'handlebars', + 'diffMatchPatch' +], function(locale, Handlebars, DiffMatchPatch) { + + /** + * start/stop timer for simple performance check. + */ + var timer; + Handlebars.registerHelper('startTimer', function(text) { + timer = new Date(); + return ''; + }); + + Handlebars.registerHelper('stopTimer', function(text) { + console.log(new Date() - timer); + return ''; + }); + + /** + * Return localized Text. + * @param string text + */ + Handlebars.registerHelper('__', function(text) { + return locale.__(text); + }); + + /** + * Console log. + * @param mixed obj + */ + Handlebars.registerHelper('cl', function(obj) { + console.log(obj); + return ''; + }); + + /** + * Replace underscore with space. + * @param string text + */ + Handlebars.registerHelper('underscoreToSpace', function(text) { + return text.replace(/(_+)/g, ' '); + }); + + /** + * + */ + Handlebars.registerHelper('assign', function(name) { + if(arguments.length > 0) { + var type = typeof(arguments[1]); + var arg = null; + if(type === 'string' || type === 'number' || type === 'boolean') arg = arguments[1]; + Handlebars.registerHelper(name, function() { return arg; }); + } + return ''; + }); + + /** + * + */ + Handlebars.registerHelper('nl2br', function(text) { + return _handlebarsNewlineToBreak(text); + }); + + /** + * + */ + Handlebars.registerHelper('if_eq', function(context, options) { + var compare = context; + // Get length if context is an object + if (context instanceof Object && ! (options.hash.compare instanceof Object)) + compare = Object.keys(context).length; + + if (compare === options.hash.compare) + return options.fn(this); + + return options.inverse(this); + }); + + /** + * + */ + Handlebars.registerHelper('if_gt', function(context, options) { + var compare = context; + // Get length if context is an object + if (context instanceof Object && ! (options.hash.compare instanceof Object)) + compare = Object.keys(context).length; + + if(compare > options.hash.compare) + return options.fn(this); + + return options.inverse(this); + }); + + /** + * + */ + var templateCache = {}; + Handlebars.registerHelper('subTemplate', function(name, sourceContext) { + if ( ! templateCache[name]) + templateCache[name] = Handlebars.compile($('#template-' + name).html()); + + var template = templateCache[name]; + var templateContext = $.extend({}, this, sourceContext.hash); + return new Handlebars.SafeString( template(templateContext) ); + }); + + /** + * + */ + Handlebars.registerHelper('toLowerCase', function(value) { + return (value && typeof value === 'string') ? value.toLowerCase() : ''; + }); + + /** + * + */ + Handlebars.registerHelper('splitFill', function(value, splitChar, fillChar) { + var splits = value.split(splitChar); + return new Array(splits.length).join(fillChar) + splits[splits.length - 1]; + }); + + /** + * Convert Newline to HTML-Break (nl2br). + * + * @param {String} text + * @returns {String} + */ + function _handlebarsNewlineToBreak(text) { + return ('' + text).replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2'); + } + + /** + * + */ + Handlebars.registerHelper('each_compare_list_field', function(source, compare, options) { + var fieldName = options.hash.field; + var newSource = []; + if (source) { + source.forEach(function(entry) { + var values = entry; + values['key'] = entry[fieldName]; + newSource.push(values); + }); + } + + var newCompare = []; + if (compare) { + compare.forEach(function(entry) { + var values = entry; + values['key'] = entry[fieldName]; + newCompare.push(values); + }); + } + return _handlebarsEachCompared('key', newSource, newCompare, options); + }); + + /** + * + */ + Handlebars.registerHelper('each_compare_keys', function(source, compare, options) { + var newSource = []; + if (source) { + var sourceFields = Object.keys(source); + sourceFields.forEach(function(name) { + var values = {}; + values['value'] = source[name]; + values['key'] = name; + newSource.push(values); + }); + } + + var newCompare = []; + if (compare) { + var compareFields = Object.keys(compare); + compareFields.forEach(function(name) { + var values = {}; + values['value'] = compare[name]; + values['key'] = name; + newCompare.push(values); + }); + } + return _handlebarsEachCompared('key', newSource, newCompare, options); + }); + + /** + * + */ + Handlebars.registerHelper('each_compare_field', function(source, compare, options) { + return _handlebarsEachCompared('field', source, compare, options); + }); + + /** + * + */ + Handlebars.registerHelper('each_compare_title', function(source, compare, options) { + return _handlebarsEachCompared('title', source, compare, options); + }); + + /** + * + */ + Handlebars.registerHelper('showDiff', function(source, compare, options) { + var ds = ''; + if(source === compare) { + ds = source; + } else { + if( ! source) + return compare; + + if( ! compare) + return source; + + var d = diffMatchPatch.diff_main(compare, source); + diffMatchPatch.diff_cleanupSemantic(d); + ds = diffMatchPatch.diff_prettyHtml(d); + ds = ds.replace(/¶/gm, ''); + } + if(options === 'nl2br') + ds = _handlebarsNewlineToBreak(ds); + + return ds; + }); + + /** + * + */ + function _handlebarsEachCompared(fieldname, source, compare, options) + { + var dataList = []; + var index = 0; + if(source) { + source.forEach(function(sourceEntry) { + var found = false; + if (compare) { + compare.forEach(function(compareEntry) { + if(sourceEntry[fieldname] === compareEntry[fieldname]) { + var data = { + typeSame: true, + source: sourceEntry, + compare: compareEntry, + index: index + }; + dataList.push(data); + found = true; + index++; + } + }); + } + if ( ! found) { + var data = { + typeIns: true, + source: sourceEntry, + index: index + }; + dataList.push(data); + index++; + } + }); + } + + if (compare) { + compare.forEach(function(compareEntry) { + var found = false; + if (source) { + source.forEach(function(sourceEntry) { + if(sourceEntry[fieldname] === compareEntry[fieldname]) + found = true; + }); + } + if ( ! found) { + var data = { + typeDel: true, + compare: compareEntry, + index: index + }; + dataList.push(data); + index++; + } + }); + } + + var ret = ''; + var length = dataList.length; + for (var index in dataList) { + if(index == (length - 1)) + dataList[index]['_last'] = true; + ret = ret + options.fn(dataList[index]); + } + return ret; + } + + var diffMatchPatch = new DiffMatchPatch(); + + /** + * Overwrite Colors + */ + DiffMatchPatch.prototype.diff_prettyHtml = function(diffs) { + var html = []; + var pattern_amp = /&/g; + var pattern_lt = //g; + var pattern_para = /\n/g; + for (var x = 0; x < diffs.length; x++) { + var op = diffs[x][0]; // Operation (insert, delete, equal) + var data = diffs[x][1]; // Text of change. + var text = data.replace(pattern_amp, '&').replace(pattern_lt, '<') + .replace(pattern_gt, '>').replace(pattern_para, '¶
'); + switch (op) { + case DIFF_INSERT: + html[x] = '' + text + ''; + break; + case DIFF_DELETE: + html[x] = '' + text + ''; + break; + case DIFF_EQUAL: + html[x] = '' + text + ''; + break; + } + } + return html.join(''); + }; + + // Exports + return Handlebars; +}); diff --git a/src/client/docs/utils/send_sample_request.js b/src/client/docs/utils/send_sample_request.js new file mode 100644 index 0000000..f0124bd --- /dev/null +++ b/src/client/docs/utils/send_sample_request.js @@ -0,0 +1,158 @@ +define([ + 'jquery' +], function($) { + + var initDynamic = function() { + // Button send + $(".sample-request-send").off("click"); + $(".sample-request-send").on("click", function(e) { + e.preventDefault(); + var $root = $(this).parents("article"); + var group = $root.data("group"); + var name = $root.data("name"); + var version = $root.data("version"); + sendSampleRequest(group, name, version, $(this).data("sample-request-type")); + }); + + // Button clear + $(".sample-request-clear").off("click"); + $(".sample-request-clear").on("click", function(e) { + e.preventDefault(); + var $root = $(this).parents("article"); + var group = $root.data("group"); + var name = $root.data("name"); + var version = $root.data("version"); + clearSampleRequest(group, name, version); + }); + }; // initDynamic + + function sendSampleRequest(group, name, version, type) + { + var $root = $('article[data-group="' + group + '"][data-name="' + name + '"][data-version="' + version + '"]'); + + // Optional header + var header = {}; + $root.find(".sample-request-header:checked").each(function(i, element) { + var group = $(element).data("sample-request-header-group-id"); + $root.find("[data-sample-request-header-group=\"" + group + "\"]").each(function(i, element) { + var key = $(element).data("sample-request-header-name"); + var value = element.value; + header[key] = $.type(value) === "string" ? escapeHtml(value) : value; + }); + }); + + // create JSON dictionary of parameters + var param = {}; + $root.find(".sample-request-param:checked").each(function(i, element) { + var group = $(element).data("sample-request-param-group-id"); + $root.find("[data-sample-request-param-group=\"" + group + "\"]").each(function(i, element) { + var key = $(element).data("sample-request-param-name"); + var value = element.value; + param[key] = $.type(value) === "string" ? escapeHtml(value) : value; + }); + }); + + // grab user-inputted URL + var url = $root.find(".sample-request-url").val(); + + // Insert url parameter + var pattern = pathToRegexp(url, null); + var matches = pattern.exec(url); + for (var i = 1; i < matches.length; i++) { + var key = matches[i].substr(1); + if (param[key] !== undefined) { + url = url.replace(matches[i], encodeURIComponent(param[key])); + + // remove URL parameters from list + delete param[key]; + } + } // for + + // send AJAX request, catch success or error callback + $.ajax({ + url: url, + dataType: "json", + contentType: "application/json", + data: JSON.stringify(param), + headers: header, + type: type.toUpperCase(), + success: displaySuccess, + error: displayError + }); + + function displaySuccess(data) { + var jsonResponse; + try { + jsonResponse = JSON.stringify(data, null, 4); + } catch (e) { + jsonResponse = data; + } + $root.find(".sample-request-response").fadeTo(250, 1); + $root.find(".sample-request-response-json").html(jsonResponse); + refreshScrollSpy(); + }; + + function displayError(jqXHR, textStatus, error) { + var message = "Error " + jqXHR.status + ": " + error; + var jsonResponse; + try { + jsonResponse = JSON.parse(jqXHR.responseText); + jsonResponse = JSON.stringify(jsonResponse, null, 4); + } catch (e) { + jsonResponse = jqXHR.responseText; + } + + if (jsonResponse) + message += "
" + jsonResponse; + + // flicker on previous error to make clear that there is a new response + if($root.find(".sample-request-response").is(":visible")) + $root.find(".sample-request-response").fadeTo(1, 0.1); + + $root.find(".sample-request-response").fadeTo(250, 1); + $root.find(".sample-request-response-json").html(message); + refreshScrollSpy(); + }; + } + + function clearSampleRequest(group, name, version) + { + var $root = $('article[data-group="' + group + '"][data-name="' + name + '"][data-version="' + version + '"]'); + + // hide sample response + $root.find(".sample-request-response-json").html(""); + $root.find(".sample-request-response").hide(); + + // reset value of parameters + $root.find(".sample-request-param").each(function(i, element) { + element.value = ""; + }); + + // restore default URL + var $urlElement = $root.find(".sample-request-url"); + $urlElement.val($urlElement.prop("defaultValue")); + + refreshScrollSpy(); + } + + function refreshScrollSpy() + { + $('[data-spy="scroll"]').each(function () { + $(this).scrollspy("refresh"); + }); + } + + function escapeHtml(str) { + var div = document.createElement("div"); + div.appendChild(document.createTextNode(str)); + return div.innerHTML; + } + + /** + * Exports. + */ + return { + initDynamic: initDynamic + }; + +}); diff --git a/src/client/docs/vendor/path-to-regexp/LICENSE b/src/client/docs/vendor/path-to-regexp/LICENSE new file mode 100644 index 0000000..983fbe8 --- /dev/null +++ b/src/client/docs/vendor/path-to-regexp/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/client/docs/vendor/path-to-regexp/index.js b/src/client/docs/vendor/path-to-regexp/index.js new file mode 100644 index 0000000..7f2a9ca --- /dev/null +++ b/src/client/docs/vendor/path-to-regexp/index.js @@ -0,0 +1,205 @@ +var isarray = Array.isArray || function (arr) { + return Object.prototype.toString.call(arr) == '[object Array]'; +}; + +/** + * Expose `pathToRegexp`. + */ +// module.exports = pathToRegexp + +/** + * The main path matching regexp utility. + * + * @type {RegExp} + */ +var PATH_REGEXP = new RegExp([ + // Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)', + // Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?"] + // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined] + '([\\/.])?(?:\\:(\\w+)(?:\\(((?:\\\\.|[^)])*)\\))?|\\(((?:\\\\.|[^)])*)\\))([+*?])?', + // Match regexp special characters that are always escaped. + '([.+*?=^!:${}()[\\]|\\/])' +].join('|'), 'g') + +/** + * Escape the capturing group by escaping special characters and meaning. + * + * @param {String} group + * @return {String} + */ +function escapeGroup (group) { + return group.replace(/([=!:$\/()])/g, '\\$1') +} + +/** + * Attach the keys as a property of the regexp. + * + * @param {RegExp} re + * @param {Array} keys + * @return {RegExp} + */ +function attachKeys (re, keys) { + re.keys = keys + return re +} + +/** + * Get the flags for a regexp from the options. + * + * @param {Object} options + * @return {String} + */ +function flags (options) { + return options.sensitive ? '' : 'i' +} + +/** + * Pull out keys from a regexp. + * + * @param {RegExp} path + * @param {Array} keys + * @return {RegExp} + */ +function regexpToRegexp (path, keys) { + // Use a negative lookahead to match only capturing groups. + var groups = path.source.match(/\((?!\?)/g) + + if (groups) { + for (var i = 0; i < groups.length; i++) { + keys.push({ + name: i, + delimiter: null, + optional: false, + repeat: false + }) + } + } + + return attachKeys(path, keys) +} + +/** + * Transform an array into a regexp. + * + * @param {Array} path + * @param {Array} keys + * @param {Object} options + * @return {RegExp} + */ +function arrayToRegexp (path, keys, options) { + var parts = [] + + for (var i = 0; i < path.length; i++) { + parts.push(pathToRegexp(path[i], keys, options).source) + } + + var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)) + return attachKeys(regexp, keys) +} + +/** + * Replace the specific tags with regexp strings. + * + * @param {String} path + * @param {Array} keys + * @return {String} + */ +function replacePath (path, keys) { + var index = 0 + + function replace (_, escaped, prefix, key, capture, group, suffix, escape) { + if (escaped) { + return escaped + } + + if (escape) { + return '\\' + escape + } + + var repeat = suffix === '+' || suffix === '*' + var optional = suffix === '?' || suffix === '*' + + keys.push({ + name: key || index++, + delimiter: prefix || '/', + optional: optional, + repeat: repeat + }) + + prefix = prefix ? ('\\' + prefix) : '' + capture = escapeGroup(capture || group || '[^' + (prefix || '\\/') + ']+?') + + if (repeat) { + capture = capture + '(?:' + prefix + capture + ')*' + } + + if (optional) { + return '(?:' + prefix + '(' + capture + '))?' + } + + // Basic parameter support. + return prefix + '(' + capture + ')' + } + + return path.replace(PATH_REGEXP, replace) +} + +/** + * Normalize the given path string, returning a regular expression. + * + * An empty array can be passed in for the keys, which will hold the + * placeholder key descriptions. For example, using `/user/:id`, `keys` will + * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. + * + * @param {(String|RegExp|Array)} path + * @param {Array} [keys] + * @param {Object} [options] + * @return {RegExp} + */ +function pathToRegexp (path, keys, options) { + keys = keys || [] + + if (!isarray(keys)) { + options = keys + keys = [] + } else if (!options) { + options = {} + } + + if (path instanceof RegExp) { + return regexpToRegexp(path, keys, options) + } + + if (isarray(path)) { + return arrayToRegexp(path, keys, options) + } + + var strict = options.strict + var end = options.end !== false + var route = replacePath(path, keys) + var endsWithSlash = path.charAt(path.length - 1) === '/' + + // In non-strict mode we allow a slash at the end of match. If the path to + // match already ends with a slash, we remove it for consistency. The slash + // is valid at the end of a path match, not in the middle. This is important + // in non-ending mode, where "/test/" shouldn't match "/test//route". + if (!strict) { + route = (endsWithSlash ? route.slice(0, -2) : route) + '(?:\\/(?=$))?' + } + + if (end) { + route += '$' + } else { + // In non-ending mode, we need the capturing groups to match as much as + // possible by using a positive lookahead to the end or next path segment. + route += strict && endsWithSlash ? '' : '(?=\\/|$)' + } + + return attachKeys(new RegExp('^' + route, flags(options)), keys) +} + diff --git a/src/client/docs/vendor/polyfill.js b/src/client/docs/vendor/polyfill.js new file mode 100644 index 0000000..1a186a5 --- /dev/null +++ b/src/client/docs/vendor/polyfill.js @@ -0,0 +1,100 @@ +// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys +if (!Object.keys) { + Object.keys = (function () { + 'use strict'; + var hasOwnProperty = Object.prototype.hasOwnProperty, + hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), + dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ], + dontEnumsLength = dontEnums.length; + + return function (obj) { + if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { + throw new TypeError('Object.keys called on non-object'); + } + + var result = [], prop, i; + + for (prop in obj) { + if (hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + + if (hasDontEnumBug) { + for (i = 0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) { + result.push(dontEnums[i]); + } + } + } + return result; + }; + }()); +} + +//Production steps of ECMA-262, Edition 5, 15.4.4.18 +//Reference: http://es5.github.com/#x15.4.4.18 +if (!Array.prototype.forEach) { + +Array.prototype.forEach = function (callback, thisArg) { + + var T, k; + + if (this == null) { + throw new TypeError(" this is null or not defined"); + } + + // 1. Let O be the result of calling ToObject passing the |this| value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If IsCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== "function") { + throw new TypeError(callback + " is not a function"); + } + + // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 1) { + T = thisArg; + } + + // 6. Let k be 0 + k = 0; + + // 7. Repeat, while k < len + while (k < len) { + + var kValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal method of O with argument Pk. + kValue = O[k]; + + // ii. Call the Call internal method of callback with T as the this value and + // argument list containing kValue, k, and O. + callback.call(T, kValue, k, O); + } + // d. Increase k by 1. + k++; + } + // 8. return undefined +}; +} diff --git a/src/client/docs/vendor/prettify.css b/src/client/docs/vendor/prettify.css new file mode 100644 index 0000000..35687dd --- /dev/null +++ b/src/client/docs/vendor/prettify.css @@ -0,0 +1,101 @@ +/* Pretty printing styles. Used with prettify.js. */ +/* Vim sunburst theme by David Leibovic */ +pre .str { + color: #65B042; +} +/* string - green */ +pre .kwd { + color: #E28964; +} +/* keyword - dark pink */ +pre .com { + color: #AEAEAE; + font-style: italic; +} +/* comment - gray */ +pre .typ { + color: #89bdff; +} +/* type - light blue */ +pre .lit { + color: #3387CC; +} +/* literal - blue */ +pre .pun { + color: #fff; +} +/* punctuation - white */ +pre .pln { + color: #fff; +} +/* plaintext - white */ +pre .tag { + color: #89bdff; +} +/* html/xml tag - light blue */ +pre .atn { + color: #bdb76b; +} +/* html/xml attribute name - khaki */ +pre .atv { + color: #65B042; +} +/* html/xml attribute value - green */ +pre .dec { + color: #3387CC; +} +/* decimal - blue */ +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; + color: #AEAEAE; +} +/* IE indents via margin-left */ +li.L0, +li.L1, +li.L2, +li.L3, +li.L5, +li.L6, +li.L7, +li.L8 { + list-style-type: none; +} +/* Alternate shading for lines */ +@media print { + pre .str { + color: #060; + } + pre .kwd { + color: #006; + font-weight: bold; + } + pre .com { + color: #600; + font-style: italic; + } + pre .typ { + color: #404; + font-weight: bold; + } + pre .lit { + color: #044; + } + pre .pun { + color: #440; + } + pre .pln { + color: #000; + } + pre .tag { + color: #006; + font-weight: bold; + } + pre .atn { + color: #404; + } + pre .atv { + color: #060; + } +} \ No newline at end of file diff --git a/src/client/docs/vendor/prettify/lang-apollo.js b/src/client/docs/vendor/prettify/lang-apollo.js new file mode 100644 index 0000000..99e4a97 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-apollo.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/, +null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]); diff --git a/src/client/docs/vendor/prettify/lang-basic.js b/src/client/docs/vendor/prettify/lang-basic.js new file mode 100644 index 0000000..6b784d4 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-basic.js @@ -0,0 +1,3 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["str",/^"(?:[^\n\r"\\]|\\.)*(?:"|$)/,a,'"'],["pln",/^\s+/,a," \r\n\t\u00a0"]],[["com",/^REM[^\n\r]*/,a],["kwd",/^\b(?:AND|CLOSE|CLR|CMD|CONT|DATA|DEF ?FN|DIM|END|FOR|GET|GOSUB|GOTO|IF|INPUT|LET|LIST|LOAD|NEW|NEXT|NOT|ON|OPEN|OR|POKE|PRINT|READ|RESTORE|RETURN|RUN|SAVE|STEP|STOP|SYS|THEN|TO|VERIFY|WAIT)\b/,a],["pln",/^[a-z][^\W_]?(?:\$|%)?/i,a],["lit",/^(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/i,a,"0123456789"],["pun", +/^.[^\s\w"$%.]*/,a]]),["basic","cbm"]); diff --git a/src/client/docs/vendor/prettify/lang-clj.js b/src/client/docs/vendor/prettify/lang-clj.js new file mode 100644 index 0000000..1bb539c --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-clj.js @@ -0,0 +1,18 @@ +/* + Copyright (C) 2011 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a], +["typ",/^:[\dA-Za-z-]+/]]),["clj"]); diff --git a/src/client/docs/vendor/prettify/lang-css.js b/src/client/docs/vendor/prettify/lang-css.js new file mode 100644 index 0000000..d7a4640 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n\u000c"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]+)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//], +["com",/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}\b/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/src/client/docs/vendor/prettify/lang-dart.js b/src/client/docs/vendor/prettify/lang-dart.js new file mode 100644 index 0000000..eefccc9 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-dart.js @@ -0,0 +1,3 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"]],[["com",/^#!.*/],["kwd",/^\b(?:import|library|part of|part|as|show|hide)\b/i],["com",/^\/\/.*/],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["kwd",/^\b(?:class|interface)\b/i],["kwd",/^\b(?:assert|break|case|catch|continue|default|do|else|finally|for|if|in|is|new|return|super|switch|this|throw|try|while)\b/i],["kwd",/^\b(?:abstract|const|extends|factory|final|get|implements|native|operator|set|static|typedef|var)\b/i], +["typ",/^\b(?:bool|double|dynamic|int|num|object|string|void)\b/i],["kwd",/^\b(?:false|null|true)\b/i],["str",/^r?'''[\S\s]*?[^\\]'''/],["str",/^r?"""[\S\s]*?[^\\]"""/],["str",/^r?'('|[^\n\f\r]*?[^\\]')/],["str",/^r?"("|[^\n\f\r]*?[^\\]")/],["pln",/^[$_a-z]\w*/i],["pun",/^[!%&*+/:<-?^|~-]/],["lit",/^\b0x[\da-f]+/i],["lit",/^\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i],["lit",/^\b\.\d+(?:e[+-]?\d+)?/i],["pun",/^[(),.;[\]{}]/]]), +["dart"]); diff --git a/src/client/docs/vendor/prettify/lang-erlang.js b/src/client/docs/vendor/prettify/lang-erlang.js new file mode 100644 index 0000000..27214a5 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-erlang.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["lit",/^[a-z]\w*/],["lit",/^'(?:[^\n\f\r'\\]|\\[^&])+'?/,null,"'"],["lit",/^\?[^\t\n ({]+/,null,"?"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^%[^\n]*/],["kwd",/^(?:module|attributes|do|let|in|letrec|apply|call|primop|case|of|end|when|fun|try|catch|receive|after|char|integer|float,atom,string,var)\b/], +["kwd",/^-[_a-z]+/],["typ",/^[A-Z_]\w*/],["pun",/^[,.;]/]]),["erlang","erl"]); diff --git a/src/client/docs/vendor/prettify/lang-go.js b/src/client/docs/vendor/prettify/lang-go.js new file mode 100644 index 0000000..1caca23 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-go.js @@ -0,0 +1 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]); diff --git a/src/client/docs/vendor/prettify/lang-hs.js b/src/client/docs/vendor/prettify/lang-hs.js new file mode 100644 index 0000000..ff3729b --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-hs.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/, +null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]); diff --git a/src/client/docs/vendor/prettify/lang-lisp.js b/src/client/docs/vendor/prettify/lang-lisp.js new file mode 100644 index 0000000..9c8cfa5 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-lisp.js @@ -0,0 +1,3 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a], +["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","lsp","scm","ss","rkt"]); diff --git a/src/client/docs/vendor/prettify/lang-llvm.js b/src/client/docs/vendor/prettify/lang-llvm.js new file mode 100644 index 0000000..16fade2 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-llvm.js @@ -0,0 +1 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^!?"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["com",/^;[^\n\r]*/,null,";"]],[["pln",/^[!%@](?:[$\-.A-Z_a-z][\w$\-.]*|\d+)/],["kwd",/^[^\W\d]\w*/,null],["lit",/^\d+\.\d+/],["lit",/^(?:\d+|0[Xx][\dA-Fa-f]+)/],["pun",/^[(-*,:<->[\]{}]|\.\.\.$/]]),["llvm","ll"]); diff --git a/src/client/docs/vendor/prettify/lang-lua.js b/src/client/docs/vendor/prettify/lang-lua.js new file mode 100644 index 0000000..7e44cca --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-lua.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i], +["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]); diff --git a/src/client/docs/vendor/prettify/lang-matlab.js b/src/client/docs/vendor/prettify/lang-matlab.js new file mode 100644 index 0000000..d0d3516 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-matlab.js @@ -0,0 +1,6 @@ +var a=null,b=window.PR,c=[[b.PR_PLAIN,/^[\t-\r \xa0]+/,a," \t\r\n\u000b\u000c\u00a0"],[b.PR_COMMENT,/^%{[^%]*%+(?:[^%}][^%]*%+)*}/,a],[b.PR_COMMENT,/^%[^\n\r]*/,a,"%"],["syscmd",/^![^\n\r]*/,a,"!"]],d=[["linecont",/^\.\.\.\s*[\n\r]/,a],["err",/^\?\?\? [^\n\r]*/,a],["wrn",/^Warning: [^\n\r]*/,a],["codeoutput",/^>>\s+/,a],["codeoutput",/^octave:\d+>\s+/,a],["lang-matlab-operators",/^((?:[A-Za-z]\w*(?:\.[A-Za-z]\w*)*|[).\]}])')/,a],["lang-matlab-identifiers",/^([A-Za-z]\w*(?:\.[A-Za-z]\w*)*)(?!')/,a], +[b.PR_STRING,/^'(?:[^']|'')*'/,a],[b.PR_LITERAL,/^[+-]?\.?\d+(?:\.\d*)?(?:[Ee][+-]?\d+)?[ij]?/,a],[b.PR_TAG,/^[()[\]{}]/,a],[b.PR_PUNCTUATION,/^[!&*-/:->@\\^|~]/,a]],e=[["lang-matlab-identifiers",/^([A-Za-z]\w*(?:\.[A-Za-z]\w*)*)/,a],[b.PR_TAG,/^[()[\]{}]/,a],[b.PR_PUNCTUATION,/^[!&*-/:->@\\^|~]/,a],["transpose",/^'/,a]]; +b.registerLangHandler(b.createSimpleLexer([],[[b.PR_KEYWORD,/^\b(?:break|case|catch|classdef|continue|else|elseif|end|for|function|global|if|otherwise|parfor|persistent|return|spmd|switch|try|while)\b/,a],["const",/^\b(?:true|false|inf|Inf|nan|NaN|eps|pi|ans|nargin|nargout|varargin|varargout)\b/,a],[b.PR_TYPE,/^\b(?:cell|struct|char|double|single|logical|u?int(?:8|16|32|64)|sparse)\b/,a],["fun",/^\b(?:abs|accumarray|acos(?:d|h)?|acot(?:d|h)?|acsc(?:d|h)?|actxcontrol(?:list|select)?|actxGetRunningServer|actxserver|addlistener|addpath|addpref|addtodate|airy|align|alim|all|allchild|alpha|alphamap|amd|ancestor|and|angle|annotation|any|area|arrayfun|asec(?:d|h)?|asin(?:d|h)?|assert|assignin|atan[2dh]?|audiodevinfo|audioplayer|audiorecorder|aufinfo|auread|autumn|auwrite|avifile|aviinfo|aviread|axes|axis|balance|bar(?:3|3h|h)?|base2dec|beep|BeginInvoke|bench|bessel[h-ky]|beta|betainc|betaincinv|betaln|bicg|bicgstab|bicgstabl|bin2dec|bitand|bitcmp|bitget|bitmax|bitnot|bitor|bitset|bitshift|bitxor|blanks|blkdiag|bone|box|brighten|brush|bsxfun|builddocsearchdb|builtin|bvp4c|bvp5c|bvpget|bvpinit|bvpset|bvpxtend|calendar|calllib|callSoapService|camdolly|cameratoolbar|camlight|camlookat|camorbit|campan|campos|camproj|camroll|camtarget|camup|camva|camzoom|cart2pol|cart2sph|cast|cat|caxis|cd|cdf2rdf|cdfepoch|cdfinfo|cdflib(?:.(?:close|closeVar|computeEpoch|computeEpoch16|create|createAttr|createVar|delete|deleteAttr|deleteAttrEntry|deleteAttrgEntry|deleteVar|deleteVarRecords|epoch16Breakdown|epochBreakdown|getAttrEntry|getAttrgEntry|getAttrMaxEntry|getAttrMaxgEntry|getAttrName|getAttrNum|getAttrScope|getCacheSize|getChecksum|getCompression|getCompressionCacheSize|getConstantNames|getConstantValue|getCopyright|getFileBackward|getFormat|getLibraryCopyright|getLibraryVersion|getMajority|getName|getNumAttrEntries|getNumAttrgEntries|getNumAttributes|getNumgAttributes|getReadOnlyMode|getStageCacheSize|getValidate|getVarAllocRecords|getVarBlockingFactor|getVarCacheSize|getVarCompression|getVarData|getVarMaxAllocRecNum|getVarMaxWrittenRecNum|getVarName|getVarNum|getVarNumRecsWritten|getVarPadValue|getVarRecordData|getVarReservePercent|getVarsMaxWrittenRecNum|getVarSparseRecords|getVersion|hyperGetVarData|hyperPutVarData|inquire|inquireAttr|inquireAttrEntry|inquireAttrgEntry|inquireVar|open|putAttrEntry|putAttrgEntry|putVarData|putVarRecordData|renameAttr|renameVar|setCacheSize|setChecksum|setCompression|setCompressionCacheSize|setFileBackward|setFormat|setMajority|setReadOnlyMode|setStageCacheSize|setValidate|setVarAllocBlockRecords|setVarBlockingFactor|setVarCacheSize|setVarCompression|setVarInitialRecs|setVarPadValue|SetVarReservePercent|setVarsCacheSize|setVarSparseRecords))?|cdfread|cdfwrite|ceil|cell2mat|cell2struct|celldisp|cellfun|cellplot|cellstr|cgs|checkcode|checkin|checkout|chol|cholinc|cholupdate|circshift|cla|clabel|class|clc|clear|clearvars|clf|clipboard|clock|close|closereq|cmopts|cmpermute|cmunique|colamd|colon|colorbar|colordef|colormap|colormapeditor|colperm|Combine|comet|comet3|commandhistory|commandwindow|compan|compass|complex|computer|cond|condeig|condest|coneplot|conj|containers.Map|contour(?:[3cf]|slice)?|contrast|conv|conv2|convhull|convhulln|convn|cool|copper|copyfile|copyobj|corrcoef|cos(?:d|h)?|cot(?:d|h)?|cov|cplxpair|cputime|createClassFromWsdl|createSoapMessage|cross|csc(?:d|h)?|csvread|csvwrite|ctranspose|cumprod|cumsum|cumtrapz|curl|customverctrl|cylinder|daqread|daspect|datacursormode|datatipinfo|date|datenum|datestr|datetick|datevec|dbclear|dbcont|dbdown|dblquad|dbmex|dbquit|dbstack|dbstatus|dbstep|dbstop|dbtype|dbup|dde23|ddeget|ddesd|ddeset|deal|deblank|dec2base|dec2bin|dec2hex|decic|deconv|del2|delaunay|delaunay3|delaunayn|DelaunayTri|delete|demo|depdir|depfun|det|detrend|deval|diag|dialog|diary|diff|diffuse|dir|disp|display|dither|divergence|dlmread|dlmwrite|dmperm|doc|docsearch|dos|dot|dragrect|drawnow|dsearch|dsearchn|dynamicprops|echo|echodemo|edit|eig|eigs|ellipj|ellipke|ellipsoid|empty|enableNETfromNetworkDrive|enableservice|EndInvoke|enumeration|eomday|eq|erf|erfc|erfcinv|erfcx|erfinv|error|errorbar|errordlg|etime|etree|etreeplot|eval|evalc|evalin|event.(?:EventData|listener|PropertyEvent|proplistener)|exifread|exist|exit|exp|expint|expm|expm1|export2wsdlg|eye|ezcontour|ezcontourf|ezmesh|ezmeshc|ezplot|ezplot3|ezpolar|ezsurf|ezsurfc|factor|factorial|fclose|feather|feature|feof|ferror|feval|fft|fft2|fftn|fftshift|fftw|fgetl|fgets|fieldnames|figure|figurepalette|fileattrib|filebrowser|filemarker|fileparts|fileread|filesep|fill|fill3|filter|filter2|find|findall|findfigs|findobj|findstr|finish|fitsdisp|fitsinfo|fitsread|fitswrite|fix|flag|flipdim|fliplr|flipud|floor|flow|fminbnd|fminsearch|fopen|format|fplot|fprintf|frame2im|fread|freqspace|frewind|fscanf|fseek|ftell|FTP|full|fullfile|func2str|functions|funm|fwrite|fzero|gallery|gamma|gammainc|gammaincinv|gammaln|gca|gcbf|gcbo|gcd|gcf|gco|ge|genpath|genvarname|get|getappdata|getenv|getfield|getframe|getpixelposition|getpref|ginput|gmres|gplot|grabcode|gradient|gray|graymon|grid|griddata(?:3|n)?|griddedInterpolant|gsvd|gt|gtext|guidata|guide|guihandles|gunzip|gzip|h5create|h5disp|h5info|h5read|h5readatt|h5write|h5writeatt|hadamard|handle|hankel|hdf|hdf5|hdf5info|hdf5read|hdf5write|hdfinfo|hdfread|hdftool|help|helpbrowser|helpdesk|helpdlg|helpwin|hess|hex2dec|hex2num|hgexport|hggroup|hgload|hgsave|hgsetget|hgtransform|hidden|hilb|hist|histc|hold|home|horzcat|hostid|hot|hsv|hsv2rgb|hypot|ichol|idivide|ifft|ifft2|ifftn|ifftshift|ilu|im2frame|im2java|imag|image|imagesc|imapprox|imfinfo|imformats|import|importdata|imread|imwrite|ind2rgb|ind2sub|inferiorto|info|inline|inmem|inpolygon|input|inputdlg|inputname|inputParser|inspect|instrcallback|instrfind|instrfindall|int2str|integral(?:2|3)?|interp(?:1|1q|2|3|ft|n)|interpstreamspeed|intersect|intmax|intmin|inv|invhilb|ipermute|isa|isappdata|iscell|iscellstr|ischar|iscolumn|isdir|isempty|isequal|isequaln|isequalwithequalnans|isfield|isfinite|isfloat|isglobal|ishandle|ishghandle|ishold|isinf|isinteger|isjava|iskeyword|isletter|islogical|ismac|ismatrix|ismember|ismethod|isnan|isnumeric|isobject|isocaps|isocolors|isonormals|isosurface|ispc|ispref|isprime|isprop|isreal|isrow|isscalar|issorted|isspace|issparse|isstr|isstrprop|isstruct|isstudent|isunix|isvarname|isvector|javaaddpath|javaArray|javachk|javaclasspath|javacomponent|javaMethod|javaMethodEDT|javaObject|javaObjectEDT|javarmpath|jet|keyboard|kron|lasterr|lasterror|lastwarn|lcm|ldivide|ldl|le|legend|legendre|length|libfunctions|libfunctionsview|libisloaded|libpointer|libstruct|license|light|lightangle|lighting|lin2mu|line|lines|linkaxes|linkdata|linkprop|linsolve|linspace|listdlg|listfonts|load|loadlibrary|loadobj|log|log10|log1p|log2|loglog|logm|logspace|lookfor|lower|ls|lscov|lsqnonneg|lsqr|lt|lu|luinc|magic|makehgtform|mat2cell|mat2str|material|matfile|matlab.io.MatFile|matlab.mixin.(?:Copyable|Heterogeneous(?:.getDefaultScalarElement)?)|matlabrc|matlabroot|max|maxNumCompThreads|mean|median|membrane|memmapfile|memory|menu|mesh|meshc|meshgrid|meshz|meta.(?:class(?:.fromName)?|DynamicProperty|EnumeratedValue|event|MetaData|method|package(?:.(?:fromName|getAllPackages))?|property)|metaclass|methods|methodsview|mex(?:.getCompilerConfigurations)?|MException|mexext|mfilename|min|minres|minus|mislocked|mkdir|mkpp|mldivide|mlint|mlintrpt|mlock|mmfileinfo|mmreader|mod|mode|more|move|movefile|movegui|movie|movie2avi|mpower|mrdivide|msgbox|mtimes|mu2lin|multibandread|multibandwrite|munlock|namelengthmax|nargchk|narginchk|nargoutchk|native2unicode|nccreate|ncdisp|nchoosek|ncinfo|ncread|ncreadatt|ncwrite|ncwriteatt|ncwriteschema|ndgrid|ndims|ne|NET(?:.(?:addAssembly|Assembly|convertArray|createArray|createGeneric|disableAutoRelease|enableAutoRelease|GenericClass|invokeGenericMethod|NetException|setStaticProperty))?|netcdf.(?:abort|close|copyAtt|create|defDim|defGrp|defVar|defVarChunking|defVarDeflate|defVarFill|defVarFletcher32|delAtt|endDef|getAtt|getChunkCache|getConstant|getConstantNames|getVar|inq|inqAtt|inqAttID|inqAttName|inqDim|inqDimID|inqDimIDs|inqFormat|inqGrpName|inqGrpNameFull|inqGrpParent|inqGrps|inqLibVers|inqNcid|inqUnlimDims|inqVar|inqVarChunking|inqVarDeflate|inqVarFill|inqVarFletcher32|inqVarID|inqVarIDs|open|putAtt|putVar|reDef|renameAtt|renameDim|renameVar|setChunkCache|setDefaultFormat|setFill|sync)|newplot|nextpow2|nnz|noanimate|nonzeros|norm|normest|not|notebook|now|nthroot|null|num2cell|num2hex|num2str|numel|nzmax|ode(?:113|15i|15s|23|23s|23t|23tb|45)|odeget|odeset|odextend|onCleanup|ones|open|openfig|opengl|openvar|optimget|optimset|or|ordeig|orderfields|ordqz|ordschur|orient|orth|pack|padecoef|pagesetupdlg|pan|pareto|parseSoapResponse|pascal|patch|path|path2rc|pathsep|pathtool|pause|pbaspect|pcg|pchip|pcode|pcolor|pdepe|pdeval|peaks|perl|perms|permute|pie|pink|pinv|planerot|playshow|plot|plot3|plotbrowser|plotedit|plotmatrix|plottools|plotyy|plus|pol2cart|polar|poly|polyarea|polyder|polyeig|polyfit|polyint|polyval|polyvalm|pow2|power|ppval|prefdir|preferences|primes|print|printdlg|printopt|printpreview|prod|profile|profsave|propedit|propertyeditor|psi|publish|PutCharArray|PutFullMatrix|PutWorkspaceData|pwd|qhull|qmr|qr|qrdelete|qrinsert|qrupdate|quad|quad2d|quadgk|quadl|quadv|questdlg|quit|quiver|quiver3|qz|rand|randi|randn|randperm|RandStream(?:.(?:create|getDefaultStream|getGlobalStream|list|setDefaultStream|setGlobalStream))?|rank|rat|rats|rbbox|rcond|rdivide|readasync|real|reallog|realmax|realmin|realpow|realsqrt|record|rectangle|rectint|recycle|reducepatch|reducevolume|refresh|refreshdata|regexp|regexpi|regexprep|regexptranslate|rehash|rem|Remove|RemoveAll|repmat|reset|reshape|residue|restoredefaultpath|rethrow|rgb2hsv|rgb2ind|rgbplot|ribbon|rmappdata|rmdir|rmfield|rmpath|rmpref|rng|roots|rose|rosser|rot90|rotate|rotate3d|round|rref|rsf2csf|run|save|saveas|saveobj|savepath|scatter|scatter3|schur|sec|secd|sech|selectmoveresize|semilogx|semilogy|sendmail|serial|set|setappdata|setdiff|setenv|setfield|setpixelposition|setpref|setstr|setxor|shading|shg|shiftdim|showplottool|shrinkfaces|sign|sin(?:d|h)?|size|slice|smooth3|snapnow|sort|sortrows|sound|soundsc|spalloc|spaugment|spconvert|spdiags|specular|speye|spfun|sph2cart|sphere|spinmap|spline|spones|spparms|sprand|sprandn|sprandsym|sprank|spring|sprintf|spy|sqrt|sqrtm|squeeze|ss2tf|sscanf|stairs|startup|std|stem|stem3|stopasync|str2double|str2func|str2mat|str2num|strcat|strcmp|strcmpi|stream2|stream3|streamline|streamparticles|streamribbon|streamslice|streamtube|strfind|strjust|strmatch|strncmp|strncmpi|strread|strrep|strtok|strtrim|struct2cell|structfun|strvcat|sub2ind|subplot|subsasgn|subsindex|subspace|subsref|substruct|subvolume|sum|summer|superclasses|superiorto|support|surf|surf2patch|surface|surfc|surfl|surfnorm|svd|svds|swapbytes|symamd|symbfact|symmlq|symrcm|symvar|system|tan(?:d|h)?|tar|tempdir|tempname|tetramesh|texlabel|text|textread|textscan|textwrap|tfqmr|throw|tic|Tiff(?:.(?:getTagNames|getVersion))?|timer|timerfind|timerfindall|times|timeseries|title|toc|todatenum|toeplitz|toolboxdir|trace|transpose|trapz|treelayout|treeplot|tril|trimesh|triplequad|triplot|TriRep|TriScatteredInterp|trisurf|triu|tscollection|tsearch|tsearchn|tstool|type|typecast|uibuttongroup|uicontextmenu|uicontrol|uigetdir|uigetfile|uigetpref|uiimport|uimenu|uiopen|uipanel|uipushtool|uiputfile|uiresume|uisave|uisetcolor|uisetfont|uisetpref|uistack|uitable|uitoggletool|uitoolbar|uiwait|uminus|undocheckout|unicode2native|union|unique|unix|unloadlibrary|unmesh|unmkpp|untar|unwrap|unzip|uplus|upper|urlread|urlwrite|usejava|userpath|validateattributes|validatestring|vander|var|vectorize|ver|verctrl|verLessThan|version|vertcat|VideoReader(?:.isPlatformSupported)?|VideoWriter(?:.getProfiles)?|view|viewmtx|visdiff|volumebounds|voronoi|voronoin|wait|waitbar|waitfor|waitforbuttonpress|warndlg|warning|waterfall|wavfinfo|wavplay|wavread|wavrecord|wavwrite|web|weekday|what|whatsnew|which|whitebg|who|whos|wilkinson|winopen|winqueryreg|winter|wk1finfo|wk1read|wk1write|workspace|xlabel|xlim|xlsfinfo|xlsread|xlswrite|xmlread|xmlwrite|xor|xslt|ylabel|ylim|zeros|zip|zlabel|zlim|zoom)\b/, +a],["fun_tbx",/^\b(?:addedvarplot|andrewsplot|anova[12n]|ansaribradley|aoctool|barttest|bbdesign|beta(?:cdf|fit|inv|like|pdf|rnd|stat)|bino(?:cdf|fit|inv|pdf|rnd|stat)|biplot|bootci|bootstrp|boxplot|candexch|candgen|canoncorr|capability|capaplot|caseread|casewrite|categorical|ccdesign|cdfplot|chi2(?:cdf|gof|inv|pdf|rnd|stat)|cholcov|Classification(?:BaggedEnsemble|Discriminant(?:.(?:fit|make|template))?|Ensemble|KNN(?:.(?:fit|template))?|PartitionedEnsemble|PartitionedModel|Tree(?:.(?:fit|template))?)|classify|classregtree|cluster|clusterdata|cmdscale|combnk|Compact(?:Classification(?:Discriminant|Ensemble|Tree)|Regression(?:Ensemble|Tree)|TreeBagger)|confusionmat|controlchart|controlrules|cophenet|copula(?:cdf|fit|param|pdf|rnd|stat)|cordexch|corr|corrcov|coxphfit|createns|crosstab|crossval|cvpartition|datasample|dataset|daugment|dcovary|dendrogram|dfittool|disttool|dummyvar|dwtest|ecdf|ecdfhist|ev(?:cdf|fit|inv|like|pdf|rnd|stat)|ExhaustiveSearcher|exp(?:cdf|fit|inv|like|pdf|rnd|stat)|factoran|fcdf|ff2n|finv|fitdist|fitensemble|fpdf|fracfact|fracfactgen|friedman|frnd|fstat|fsurfht|fullfact|gagerr|gam(?:cdf|fit|inv|like|pdf|rnd|stat)|GeneralizedLinearModel(?:.fit)?|geo(?:cdf|inv|mean|pdf|rnd|stat)|gev(?:cdf|fit|inv|like|pdf|rnd|stat)|gline|glmfit|glmval|glyphplot|gmdistribution(?:.fit)?|gname|gp(?:cdf|fit|inv|like|pdf|rnd|stat)|gplotmatrix|grp2idx|grpstats|gscatter|haltonset|harmmean|hist3|histfit|hmm(?:decode|estimate|generate|train|viterbi)|hougen|hyge(?:cdf|inv|pdf|rnd|stat)|icdf|inconsistent|interactionplot|invpred|iqr|iwishrnd|jackknife|jbtest|johnsrnd|KDTreeSearcher|kmeans|knnsearch|kruskalwallis|ksdensity|kstest|kstest2|kurtosis|lasso|lassoglm|lassoPlot|leverage|lhsdesign|lhsnorm|lillietest|LinearModel(?:.fit)?|linhyptest|linkage|logn(?:cdf|fit|inv|like|pdf|rnd|stat)|lsline|mad|mahal|maineffectsplot|manova1|manovacluster|mdscale|mhsample|mle|mlecov|mnpdf|mnrfit|mnrnd|mnrval|moment|multcompare|multivarichart|mvn(?:cdf|pdf|rnd)|mvregress|mvregresslike|mvt(?:cdf|pdf|rnd)|NaiveBayes(?:.fit)?|nan(?:cov|max|mean|median|min|std|sum|var)|nbin(?:cdf|fit|inv|pdf|rnd|stat)|ncf(?:cdf|inv|pdf|rnd|stat)|nct(?:cdf|inv|pdf|rnd|stat)|ncx2(?:cdf|inv|pdf|rnd|stat)|NeighborSearcher|nlinfit|nlintool|nlmefit|nlmefitsa|nlparci|nlpredci|nnmf|nominal|NonLinearModel(?:.fit)?|norm(?:cdf|fit|inv|like|pdf|rnd|stat)|normplot|normspec|ordinal|outlierMeasure|parallelcoords|paretotails|partialcorr|pcacov|pcares|pdf|pdist|pdist2|pearsrnd|perfcurve|perms|piecewisedistribution|plsregress|poiss(?:cdf|fit|inv|pdf|rnd|tat)|polyconf|polytool|prctile|princomp|ProbDist(?:Kernel|Parametric|UnivKernel|UnivParam)?|probplot|procrustes|qqplot|qrandset|qrandstream|quantile|randg|random|randsample|randtool|range|rangesearch|ranksum|rayl(?:cdf|fit|inv|pdf|rnd|stat)|rcoplot|refcurve|refline|regress|Regression(?:BaggedEnsemble|Ensemble|PartitionedEnsemble|PartitionedModel|Tree(?:.(?:fit|template))?)|regstats|relieff|ridge|robustdemo|robustfit|rotatefactors|rowexch|rsmdemo|rstool|runstest|sampsizepwr|scatterhist|sequentialfs|signrank|signtest|silhouette|skewness|slicesample|sobolset|squareform|statget|statset|stepwise|stepwisefit|surfht|tabulate|tblread|tblwrite|tcdf|tdfread|tiedrank|tinv|tpdf|TreeBagger|treedisp|treefit|treeprune|treetest|treeval|trimmean|trnd|tstat|ttest|ttest2|unid(?:cdf|inv|pdf|rnd|stat)|unif(?:cdf|inv|it|pdf|rnd|stat)|vartest(?:2|n)?|wbl(?:cdf|fit|inv|like|pdf|rnd|stat)|wblplot|wishrnd|x2fx|xptread|zscore|ztest)\b/, +a],["fun_tbx",/^\b(?:adapthisteq|analyze75info|analyze75read|applycform|applylut|axes2pix|bestblk|blockproc|bwarea|bwareaopen|bwboundaries|bwconncomp|bwconvhull|bwdist|bwdistgeodesic|bweuler|bwhitmiss|bwlabel|bwlabeln|bwmorph|bwpack|bwperim|bwselect|bwtraceboundary|bwulterode|bwunpack|checkerboard|col2im|colfilt|conndef|convmtx2|corner|cornermetric|corr2|cp2tform|cpcorr|cpselect|cpstruct2pairs|dct2|dctmtx|deconvblind|deconvlucy|deconvreg|deconvwnr|decorrstretch|demosaic|dicom(?:anon|dict|info|lookup|read|uid|write)|edge|edgetaper|entropy|entropyfilt|fan2para|fanbeam|findbounds|fliptform|freqz2|fsamp2|fspecial|ftrans2|fwind1|fwind2|getheight|getimage|getimagemodel|getline|getneighbors|getnhood|getpts|getrangefromclass|getrect|getsequence|gray2ind|graycomatrix|graycoprops|graydist|grayslice|graythresh|hdrread|hdrwrite|histeq|hough|houghlines|houghpeaks|iccfind|iccread|iccroot|iccwrite|idct2|ifanbeam|im2bw|im2col|im2double|im2int16|im2java2d|im2single|im2uint16|im2uint8|imabsdiff|imadd|imadjust|ImageAdapter|imageinfo|imagemodel|imapplymatrix|imattributes|imbothat|imclearborder|imclose|imcolormaptool|imcomplement|imcontour|imcontrast|imcrop|imdilate|imdisplayrange|imdistline|imdivide|imellipse|imerode|imextendedmax|imextendedmin|imfill|imfilter|imfindcircles|imfreehand|imfuse|imgca|imgcf|imgetfile|imhandles|imhist|imhmax|imhmin|imimposemin|imlincomb|imline|immagbox|immovie|immultiply|imnoise|imopen|imoverview|imoverviewpanel|impixel|impixelinfo|impixelinfoval|impixelregion|impixelregionpanel|implay|impoint|impoly|impositionrect|improfile|imputfile|impyramid|imreconstruct|imrect|imregconfig|imregionalmax|imregionalmin|imregister|imresize|imroi|imrotate|imsave|imscrollpanel|imshow|imshowpair|imsubtract|imtool|imtophat|imtransform|imview|ind2gray|ind2rgb|interfileinfo|interfileread|intlut|ippl|iptaddcallback|iptcheckconn|iptcheckhandle|iptcheckinput|iptcheckmap|iptchecknargin|iptcheckstrs|iptdemos|iptgetapi|iptGetPointerBehavior|iptgetpref|ipticondir|iptnum2ordinal|iptPointerManager|iptprefs|iptremovecallback|iptSetPointerBehavior|iptsetpref|iptwindowalign|iradon|isbw|isflat|isgray|isicc|isind|isnitf|isrgb|isrset|lab2double|lab2uint16|lab2uint8|label2rgb|labelmatrix|makecform|makeConstrainToRectFcn|makehdr|makelut|makeresampler|maketform|mat2gray|mean2|medfilt2|montage|nitfinfo|nitfread|nlfilter|normxcorr2|ntsc2rgb|openrset|ordfilt2|otf2psf|padarray|para2fan|phantom|poly2mask|psf2otf|qtdecomp|qtgetblk|qtsetblk|radon|rangefilt|reflect|regionprops|registration.metric.(?:MattesMutualInformation|MeanSquares)|registration.optimizer.(?:OnePlusOneEvolutionary|RegularStepGradientDescent)|rgb2gray|rgb2ntsc|rgb2ycbcr|roicolor|roifill|roifilt2|roipoly|rsetwrite|std2|stdfilt|strel|stretchlim|subimage|tformarray|tformfwd|tforminv|tonemap|translate|truesize|uintlut|viscircles|warp|watershed|whitepoint|wiener2|xyz2double|xyz2uint16|ycbcr2rgb)\b/, +a],["fun_tbx",/^\b(?:bintprog|color|fgoalattain|fminbnd|fmincon|fminimax|fminsearch|fminunc|fseminf|fsolve|fzero|fzmult|gangstr|ktrlink|linprog|lsqcurvefit|lsqlin|lsqnonlin|lsqnonneg|optimget|optimset|optimtool|quadprog)\b/,a],["ident",/^[A-Za-z]\w*(?:\.[A-Za-z]\w*)*/,a]]),["matlab-identifiers"]);b.registerLangHandler(b.createSimpleLexer([],e),["matlab-operators"]);b.registerLangHandler(b.createSimpleLexer(c,d),["matlab"]); diff --git a/src/client/docs/vendor/prettify/lang-ml.js b/src/client/docs/vendor/prettify/lang-ml.js new file mode 100644 index 0000000..8ed2b0c --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-ml.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/], +["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]); diff --git a/src/client/docs/vendor/prettify/lang-mumps.js b/src/client/docs/vendor/prettify/lang-mumps.js new file mode 100644 index 0000000..8a6b3fd --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-mumps.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"]|\\.)*"/,null,'"']],[["com",/^;[^\n\r]*/,null,";"],["dec",/^\$(?:d|device|ec|ecode|es|estack|et|etrap|h|horolog|i|io|j|job|k|key|p|principal|q|quit|st|stack|s|storage|sy|system|t|test|tl|tlevel|tr|trestart|x|y|z[a-z]*|a|ascii|c|char|d|data|e|extract|f|find|fn|fnumber|g|get|j|justify|l|length|na|name|o|order|p|piece|ql|qlength|qs|qsubscript|q|query|r|random|re|reverse|s|select|st|stack|t|text|tr|translate|nan)\b/i, +null],["kwd",/^(?:[^$]b|break|c|close|d|do|e|else|f|for|g|goto|h|halt|h|hang|i|if|j|job|k|kill|l|lock|m|merge|n|new|o|open|q|quit|r|read|s|set|tc|tcommit|tre|trestart|tro|trollback|ts|tstart|u|use|v|view|w|write|x|xecute)\b/i,null],["lit",/^[+-]?(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?/i],["pln",/^[a-z][^\W_]*/i],["pun",/^[^\w\t\n\r"$%;^\xa0]|_/]]),["mumps"]); diff --git a/src/client/docs/vendor/prettify/lang-n.js b/src/client/docs/vendor/prettify/lang-n.js new file mode 100644 index 0000000..27812a5 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-n.js @@ -0,0 +1,4 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\u00a0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/, +a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/, +a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]); diff --git a/src/client/docs/vendor/prettify/lang-pascal.js b/src/client/docs/vendor/prettify/lang-pascal.js new file mode 100644 index 0000000..8435fad --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-pascal.js @@ -0,0 +1,3 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["str",/^'(?:[^\n\r'\\]|\\.)*(?:'|$)/,a,"'"],["pln",/^\s+/,a," \r\n\t\u00a0"]],[["com",/^\(\*[\S\s]*?(?:\*\)|$)|^{[\S\s]*?(?:}|$)/,a],["kwd",/^(?:absolute|and|array|asm|assembler|begin|case|const|constructor|destructor|div|do|downto|else|end|external|for|forward|function|goto|if|implementation|in|inline|interface|interrupt|label|mod|not|object|of|or|packed|procedure|program|record|repeat|set|shl|shr|then|to|type|unit|until|uses|var|virtual|while|with|xor)\b/i,a], +["lit",/^(?:true|false|self|nil)/i,a],["pln",/^[a-z][^\W_]*/i,a],["lit",/^(?:\$[\da-f]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)/i,a,"0123456789"],["pun",/^.[^\s\w$'./@]*/,a]]),["pascal"]); diff --git a/src/client/docs/vendor/prettify/lang-proto.js b/src/client/docs/vendor/prettify/lang-proto.js new file mode 100644 index 0000000..f006ad8 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-proto.js @@ -0,0 +1 @@ +PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]); diff --git a/src/client/docs/vendor/prettify/lang-r.js b/src/client/docs/vendor/prettify/lang-r.js new file mode 100644 index 0000000..99af8f8 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-r.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^'\\]|\\[\S\s])*(?:'|$)/,null,"'"]],[["com",/^#.*/],["kwd",/^(?:if|else|for|while|repeat|in|next|break|return|switch|function)(?![\w.])/],["lit",/^0[Xx][\dA-Fa-f]+([Pp]\d+)?[Li]?/],["lit",/^[+-]?(\d+(\.\d+)?|\.\d+)([Ee][+-]?\d+)?[Li]?/],["lit",/^(?:NULL|NA(?:_(?:integer|real|complex|character)_)?|Inf|TRUE|FALSE|NaN|\.\.(?:\.|\d+))(?![\w.])/], +["pun",/^(?:<>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|[!*+/^]|%.*?%|[$=@~]|:{1,3}|[(),;?[\]{}])/],["pln",/^(?:[A-Za-z]+[\w.]*|\.[^\W\d][\w.]*)(?![\w.])/],["str",/^`.+`/]]),["r","s","R","S","Splus"]); diff --git a/src/client/docs/vendor/prettify/lang-rd.js b/src/client/docs/vendor/prettify/lang-rd.js new file mode 100644 index 0000000..7a7e43f --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-rd.js @@ -0,0 +1 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\n\r]*/,null,"%"]],[["lit",/^\\(?:cr|l?dots|R|tab)\b/],["kwd",/^\\[@-Za-z]+/],["kwd",/^#(?:ifn?def|endif)/],["pln",/^\\[{}]/],["pun",/^[()[\]{}]+/]]),["Rd","rd"]); diff --git a/src/client/docs/vendor/prettify/lang-scala.js b/src/client/docs/vendor/prettify/lang-scala.js new file mode 100644 index 0000000..3f97dba --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-scala.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/], +["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]); diff --git a/src/client/docs/vendor/prettify/lang-sql.js b/src/client/docs/vendor/prettify/lang-sql.js new file mode 100644 index 0000000..8ec4280 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-sql.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\n\r]*|\/\*[\S\s]*?(?:\*\/|$))/],["kwd",/^(?:add|all|alter|and|any|apply|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|connect|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|following|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|matched|merge|natural|national|nocheck|nonclustered|nocycle|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|partition|percent|pivot|plan|preceding|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rows?|rule|save|schema|select|session_user|set|setuser|shutdown|some|start|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|unbounded|union|unique|unpivot|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|within|writetext|xml)(?=[^\w-]|$)/i, +null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^[_a-z][\w-]*/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'+\xa0-]*/]]),["sql"]); diff --git a/src/client/docs/vendor/prettify/lang-tcl.js b/src/client/docs/vendor/prettify/lang-tcl.js new file mode 100644 index 0000000..490f562 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-tcl.js @@ -0,0 +1,3 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["opn",/^{+/,a,"{"],["clo",/^}+/,a,"}"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:after|append|apply|array|break|case|catch|continue|error|eval|exec|exit|expr|for|foreach|if|incr|info|proc|return|set|switch|trace|uplevel|upvar|while)\b/,a],["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit", +/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["tcl"]); diff --git a/src/client/docs/vendor/prettify/lang-tex.js b/src/client/docs/vendor/prettify/lang-tex.js new file mode 100644 index 0000000..dcfdadd --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-tex.js @@ -0,0 +1 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]); diff --git a/src/client/docs/vendor/prettify/lang-vb.js b/src/client/docs/vendor/prettify/lang-vb.js new file mode 100644 index 0000000..ddde464 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-vb.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0\u2028\u2029]+/,null,"\t\n\r \u00a0\u2028\u2029"],["str",/^(?:["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})(?:["\u201c\u201d]c|$)|["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})*(?:["\u201c\u201d]|$))/i,null,'"\u201c\u201d'],["com",/^['\u2018\u2019](?:_(?:\r\n?|[^\r]?)|[^\n\r_\u2028\u2029])*/,null,"'\u2018\u2019"]],[["kwd",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\b/i, +null],["com",/^rem\b.*/i],["lit",/^(?:true\b|false\b|nothing\b|\d+(?:e[+-]?\d+[dfr]?|[dfilrs])?|(?:&h[\da-f]+|&o[0-7]+)[ils]?|\d*\.\d+(?:e[+-]?\d+)?[dfr]?|#\s+(?:\d+[/-]\d+[/-]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:am|pm))?)?|\d+:\d+(?::\d+)?(\s*(?:am|pm))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*(?:\[[!#%&@]+])?|\[(?:[a-z]|_\w)\w*])/i],["pun",/^[^\w\t\n\r "'[\]\xa0\u2018\u2019\u201c\u201d\u2028\u2029]+/],["pun",/^(?:\[|])/]]),["vb","vbs"]); diff --git a/src/client/docs/vendor/prettify/lang-vhdl.js b/src/client/docs/vendor/prettify/lang-vhdl.js new file mode 100644 index 0000000..51f3017 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-vhdl.js @@ -0,0 +1,3 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"]],[["str",/^(?:[box]?"(?:[^"]|"")*"|'.')/i],["com",/^--[^\n\r]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i, +null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w.\\]+#(?:[+-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:e[+-]?\d+(?:_\d+)*)?)/i], +["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'\xa0-]*/]]),["vhdl","vhd"]); diff --git a/src/client/docs/vendor/prettify/lang-wiki.js b/src/client/docs/vendor/prettify/lang-wiki.js new file mode 100644 index 0000000..96c1e34 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-wiki.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t \u00a0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]); +PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]); diff --git a/src/client/docs/vendor/prettify/lang-xq.js b/src/client/docs/vendor/prettify/lang-xq.js new file mode 100644 index 0000000..e323ae3 --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-xq.js @@ -0,0 +1,3 @@ +PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[\w-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^@[\w-]+/],["tag",/^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["com",/^\(:[\S\s]*?:\)/],["pln",/^[(),/;[\]{}]$/],["str",/^(?:"(?:[^"\\{]|\\[\S\s])*(?:"|$)|'(?:[^'\\{]|\\[\S\s])*(?:'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/], +["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/], +["pln",/^[\w:-]+/],["pln",/^[\t\n\r \xa0]+/]]),["xq","xquery"]); diff --git a/src/client/docs/vendor/prettify/lang-yaml.js b/src/client/docs/vendor/prettify/lang-yaml.js new file mode 100644 index 0000000..c38729b --- /dev/null +++ b/src/client/docs/vendor/prettify/lang-yaml.js @@ -0,0 +1,2 @@ +var a=null; +PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]); diff --git a/src/client/docs/vendor/prettify/prettify.css b/src/client/docs/vendor/prettify/prettify.css new file mode 100644 index 0000000..d44b3a2 --- /dev/null +++ b/src/client/docs/vendor/prettify/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file diff --git a/src/client/docs/vendor/prettify/prettify.js b/src/client/docs/vendor/prettify/prettify.js new file mode 100644 index 0000000..7b99049 --- /dev/null +++ b/src/client/docs/vendor/prettify/prettify.js @@ -0,0 +1,30 @@ +!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a= +b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com", +/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+ +s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/, +q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d= +c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], +O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, +V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", +/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], +["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}), +["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q, +hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); +p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="
"+a+"
";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1}); +return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i=0;){var M=A[m],T=M.src.match(/^[^#?]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);if(T){z=T[1]||"";M.parentNode.removeChild(M);break}}var S=!0,D= +[],N=[],K=[];z.replace(/[&?]([^&=]+)=([^&]+)/g,function(e,j,w){w=decodeURIComponent(w);j=decodeURIComponent(j);j=="autorun"?S=!/^[0fn]/i.test(w):j=="lang"?D.push(w):j=="skin"?N.push(w):j=="callback"&&K.push(w)});m=0;for(z=D.length;m122||(o<65||k>90||f.push([Math.max(65,k)|32,Math.min(o,90)|32]),o<97||k>122||f.push([Math.max(97,k)&-33,Math.min(o,122)&-33]))}}f.sort(function(f,a){return f[0]- +a[0]||a[1]-f[1]});b=[];g=[];for(a=0;ak[0]&&(k[1]+1>k[0]&&c.push("-"),c.push(h(k[1])));c.push("]");return c.join("")}function e(f){for(var a=f.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],g=0,k=0;g=2&&f==="["?a[g]=b(o):f!=="\\"&&(a[g]=o.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var j=0,F=!1,l=!1,I=0,c=a.length;I=5&&"lang-"===y.substring(0,5))&&!(u&&typeof u[1]==="string"))g=!1,y="src";g||(m[B]=y)}k=c;c+=B.length;if(g){g=u[1];var o=B.indexOf(g),H=o+g.length;u[2]&&(H=B.length-u[2].length,o=H-g.length);y=y.substring(5);n(l+k,B.substring(0,o),h,j);n(l+k+o,g,A(y, +g),j);n(l+k+H,B.substring(H),h,j)}else j.push(l+k,y)}a.g=j}var b={},e;(function(){for(var h=a.concat(d),l=[],i={},c=0,p=h.length;c=0;)b[q.charAt(f)]=m;m=m[1];q=""+m;i.hasOwnProperty(q)||(l.push(m),i[q]=r)}l.push(/[\S\s]/);e=j(l)})();var i=d.length;return h}function t(a){var d=[],h=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/, +r,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,r,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,r,"\"'"]);a.verbatimStrings&&h.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,r]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,r,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/, +r,"#"]),h.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,r])):d.push(["com",/^#[^\n\r]*/,r,"#"]));a.cStyleComments&&(h.push(["com",/^\/\/[^\n\r]*/,r]),h.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,r]));if(b=a.regexLiterals){var e=(b=b>1?"":"\n\r")?".":"[\\S\\s]";h.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+ +("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+e+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+e+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&h.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&h.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),r]);d.push(["pln",/^\s+/,r," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");h.push(["lit",/^@[$_a-z][\w$@]*/i,r],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,r],["pln",/^[$_a-z][\w$@]*/i,r],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i, +r,"0123456789"],["pln",/^\\[\S\s]?/,r],["pun",RegExp(b),r]);return C(d,h)}function z(a,d,h){function b(a){var c=a.nodeType;if(c==1&&!j.test(a.className))if("br"===a.nodeName)e(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&h){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),e(a),c||a.parentNode.removeChild(a)}} +function e(a){function b(a,c){var d=c?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),h=a.nextSibling;f.appendChild(d);for(var e=h;e;e=h)h=e.nextSibling,f.appendChild(e)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var j=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,l=a.ownerDocument,i=l.createElement("li");a.firstChild;)i.appendChild(a.firstChild);for(var c=[i],p=0;p=0;){var b=d[h];U.hasOwnProperty(b)?V.console&&console.warn("cannot override language handler %s",b):U[b]=a}}function A(a,d){if(!a||!U.hasOwnProperty(a))a=/^\s*=o&&(b+=2);h>=H&&(t+=2)}}finally{if(g)g.style.display=k}}catch(v){V.console&&console.log(v&&v.stack||v)}}var V=window,G=["break,continue,do,else,for,if,return,while"],O=[[G,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],J=[O,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],K=[O,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], +L=[K,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],O=[O,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],M=[G,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +N=[G,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],R=[G,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],G=[G,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, +S=/\S/,T=t({keywords:[J,L,O,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",M,N,G],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),U={};i(T,["default-code"]);i(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", +/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);i(C([["pln",/^\s+/,r," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,r,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], +["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);i(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);i(t({keywords:J,hashComments:!0,cStyleComments:!0,types:Q}),["c","cc","cpp","cxx","cyc","m"]);i(t({keywords:"null,true,false"}),["json"]);i(t({keywords:L,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:Q}), +["cs"]);i(t({keywords:K,cStyleComments:!0}),["java"]);i(t({keywords:G,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);i(t({keywords:M,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);i(t({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);i(t({keywords:N, +hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);i(t({keywords:O,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);i(t({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);i(t({keywords:R,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); +i(C([],[["str",/^[\S\s]+/]]),["regex"]);var X=V.PR={createSimpleLexer:C,registerLangHandler:i,sourceDecorator:t,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,e){var b=document.createElement("div");b.innerHTML="
"+a+"
";b=b.firstChild;e&&z(b,e,!0);D({h:d,j:e,c:b,i:1});return b.innerHTML}, +prettyPrint:e=e=function(a,d){function e(){for(var b=V.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p { + // + } +]); diff --git a/src/test/mocha.js b/src/server/api/_api-controller.js similarity index 100% rename from src/test/mocha.js rename to src/server/api/_api-controller.js diff --git a/src/test/server/entity/entity-search.spec.js b/src/server/api/_api-module.js similarity index 100% rename from src/test/server/entity/entity-search.spec.js rename to src/server/api/_api-module.js diff --git a/src/server/api/_api-template.jade b/src/server/api/_api-template.jade new file mode 100644 index 0000000..271c551 --- /dev/null +++ b/src/server/api/_api-template.jade @@ -0,0 +1,17 @@ +doctype xml +doctype html +html(manifest='/') + + head + + meta(name="viewport", content="width=device-width, initial-scale=1, user-scalable=no") + + title Crucible LARP Manager + + script(src='lib/require.js', data-main='/etc/require.js') + + link(rel='stylesheet', href='styles.min.css') + + body + + div(data-ui-view) diff --git a/src/server/api/api-manifest.js b/src/server/api/api-manifest.js new file mode 100644 index 0000000..9af8e34 --- /dev/null +++ b/src/server/api/api-manifest.js @@ -0,0 +1,33 @@ +/* globals module, require */ + +import * as _ from 'underscore'; + +import '../prototypes.js' +import resource from './api-resource.js'; +import hateoas from '../hateoas.js'; + +resource.GET().as('cache-manifest').handler = (request, response) => { + + let cache = ''; + + cache = 'CACHE MANIFEST\n'; + + cache += '\nCACHE:\n'; + + //cache.forEach(function(item) { + // cache += item + '\n'; + //}); + + cache += '\nNETWORK:\n'; + + _.each(hateoas.resources, (resource) => { + cache += resource.path + '\n'; + }); + + cache += '\nFALLBACK:\n'; + + // put _something_ in here. + + resolve(manifest); + +}; diff --git a/src/server/api/api-resource.js b/src/server/api/api-resource.js new file mode 100644 index 0000000..7ad48fc --- /dev/null +++ b/src/server/api/api-resource.js @@ -0,0 +1,6 @@ +/* global */ +'use strict'; + +import hateoas from '../hateoas.js'; + +export default hateoas.resource('/api'); diff --git a/src/server/api/auth/_api-auth-controller.js b/src/server/api/auth/_api-auth-controller.js new file mode 100644 index 0000000..e69de29 diff --git a/src/server/api/auth/_auth-template.jade b/src/server/api/auth/_auth-template.jade new file mode 100644 index 0000000..e69de29 diff --git a/src/server/api/auth/api-auth-login.js b/src/server/api/auth/api-auth-login.js new file mode 100644 index 0000000..a892b75 --- /dev/null +++ b/src/server/api/auth/api-auth-login.js @@ -0,0 +1,82 @@ +/* globals console */ +'use strict'; + +import _ from 'underscore'; +import crypto from 'crypto'; +import httpConst from 'http-constants'; + +import resource from './api-auth-resource.js'; +import query from '../../neo4j.js' + +import '../../prototypes.js' + +const operation = resource.PUT().as('json'); + +const cipher_login = '' + + 'MATCH (user:User { email: {email} })' + + ' RETURN user;'; + +operation.validator = (c) => { + return { + + body: { + + email: [ + c.email, + c.required + ], + + password: [ + c.string, + c.required + ] + + } + + }; +}; + +operation.handler = (request, response, params) => { + + const email = params.body.email; + const password = params.body.password; + console.info(`Starting login for ${email}...`); + + return query(cipher_login, { + email: email + + }).then(function(results) { + + //console.info(JSON.stringify(results, null, '\t')); + + const result = _.first(_.first(_.first(results))); + + if (!result || !result.user) { + console.info(`Couldn't find user for email ${email}`); + return response.status(httpConst.codes.NOT_FOUND).json({}); + } + + const user = _.extend({}, result.user, { + id: result.user._id + }); + + // run crypto hash on supplied password. + const hash = crypto.createHash('md5') + .update(password) + .digest('hex'); + + if (hash !== user.password) { + console.info(`Couldn't validate user's password`); + return response.status(httpConst.codes.UNAUTHORIZED).json({}); + } + + user.token = crypto.createHash('md5') + .update(user.email + hash) + .digest('hex'); + + request.session.user = user; + return response.status(httpConst.codes.OK).json(user); + + }); + +}; diff --git a/src/server/api/auth/api-auth-logout.js b/src/server/api/auth/api-auth-logout.js new file mode 100644 index 0000000..59f36e9 --- /dev/null +++ b/src/server/api/auth/api-auth-logout.js @@ -0,0 +1,30 @@ +/* globals module, require */ +'use strict'; + +import resource from './api-auth-resource.js'; + +const operation = resource.DELETE().as('json'); + +operation.validator = (request) => { + return suit.fit(request, (c) => { + return { + + session: { + user: { + id: [ + c.required, + c.integer + ] + } + } + + }; + }) +}; + +operation.handler = (request, response, params) => { + + request.session.destroy(); + return response.status(200); + +}; diff --git a/src/server/api/auth/api-auth-resource.js b/src/server/api/auth/api-auth-resource.js new file mode 100644 index 0000000..2ff52d2 --- /dev/null +++ b/src/server/api/auth/api-auth-resource.js @@ -0,0 +1,8 @@ +/* global */ +'use strict'; + +import parent from '../api-resource.js'; + +export const name = 'auth'; + +export default parent.child(name); diff --git a/src/server/api/auth/api-auth-signup.js b/src/server/api/auth/api-auth-signup.js new file mode 100644 index 0000000..251d439 --- /dev/null +++ b/src/server/api/auth/api-auth-signup.js @@ -0,0 +1,53 @@ +/* globals module, require */ +'use strict'; + +import _ from 'underscore'; +import crypto from 'crypto'; + +import resource from './api-auth-resource.js'; + +import '../../prototypes.js' +import query from '../../neo4j.js' + +const operation = resource.POST().as('json'); + +let cipher = '' + + 'MATCH (user:User { email: {email} })' + + ' RETURN user;'; + +let whitelist = [ + 'name' +]; + +operation.validator = (data) => { + return suit.fit(data, (c) => { + return { + + body: { + email: [ + c.email, + c.required + ], + + password: [ + c.string, + c.required + ] + } + + }; + }); +}; + +operation.handler = (request, response, params) => { + + // TODO: Query the database for conflicts + + // TODO: Create the User with validation = new guid. + + // TODO: Send email to validate address with callback to /auth/validate + + response.status = 201; + +}; + diff --git a/src/server/api/auth/api-auth-status.js b/src/server/api/auth/api-auth-status.js new file mode 100644 index 0000000..a4418d0 --- /dev/null +++ b/src/server/api/auth/api-auth-status.js @@ -0,0 +1,20 @@ +/* global */ +'use strict'; + +import resource from './api-auth-resource.js'; + +const operation = resource.GET().as('json'); + +operation.handler = (request, response) => { + + const user = request.session.user; + + if (!user) { + return response.status(401).json({ + message: 'No user currently logged-in!' + }); + } + + return response.status(200).json(user); // super-insecure. + +}; diff --git a/src/server/api/auth/index.js b/src/server/api/auth/index.js new file mode 100644 index 0000000..695bf59 --- /dev/null +++ b/src/server/api/auth/index.js @@ -0,0 +1,9 @@ +/* globals */ +'use strict'; + +import './recover/index.js'; + +import './api-auth-login.js'; +import './api-auth-logout.js'; +import './api-auth-signup.js'; +import './api-auth-status.js'; diff --git a/src/server/api/auth/recover/_api-login-recover-controller.js b/src/server/api/auth/recover/_api-login-recover-controller.js new file mode 100644 index 0000000..e69de29 diff --git a/src/server/api/auth/recover/_api-login-recover-template.jade b/src/server/api/auth/recover/_api-login-recover-template.jade new file mode 100644 index 0000000..e69de29 diff --git a/src/server/api/auth/recover/api-auth-recover-confirm.js b/src/server/api/auth/recover/api-auth-recover-confirm.js new file mode 100644 index 0000000..8cc5c06 --- /dev/null +++ b/src/server/api/auth/recover/api-auth-recover-confirm.js @@ -0,0 +1,6 @@ +/* globals */ +'use strict'; + +import resource from './api-auth-recover-resource.js'; + +const operation = resource.PUT().as('json'); diff --git a/src/server/api/auth/recover/api-auth-recover-resource.js b/src/server/api/auth/recover/api-auth-recover-resource.js new file mode 100644 index 0000000..f00a407 --- /dev/null +++ b/src/server/api/auth/recover/api-auth-recover-resource.js @@ -0,0 +1,8 @@ +/* global */ +'use strict'; + +import parent from '../api-auth-resource.js'; + +export const name = 'recover'; + +export default parent.child(name); diff --git a/src/server/api/auth/recover/api-auth-recover-submit.js b/src/server/api/auth/recover/api-auth-recover-submit.js new file mode 100644 index 0000000..9f990ae --- /dev/null +++ b/src/server/api/auth/recover/api-auth-recover-submit.js @@ -0,0 +1,6 @@ +/* globals */ +'use strict'; + +import resource from './api-auth-recover-resource.js'; + +const operation = resource.POST().as('json'); diff --git a/src/server/api/auth/recover/index.js b/src/server/api/auth/recover/index.js new file mode 100644 index 0000000..76e5129 --- /dev/null +++ b/src/server/api/auth/recover/index.js @@ -0,0 +1,5 @@ +/* globals */ +'use strict'; + +import './api-auth-recover-confirm.js'; +import './api-auth-recover-submit.js'; diff --git a/src/server/api/characters/_id/api-characters-_id-delete.js b/src/server/api/characters/_id/api-characters-_id-delete.js new file mode 100644 index 0000000..08f1f26 --- /dev/null +++ b/src/server/api/characters/_id/api-characters-_id-delete.js @@ -0,0 +1,47 @@ +/* globals module, require */ + +var _ = require('underscore'); + +var cipher_list = '' + + 'MATCH (node:Character)-[relationship]-(),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND id(node) = {nodeId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' DELETE node, relationship;'; + +module.exports = { + + method: 'DELETE', + + contentTypes: [ + 'application/json', + 'text/json' + ], + + validator: function(c) { + return { + + id: [ + c.number, + c.required + ] + + }; + }, + + resolver: function(params, session, resolve, reject) { + + query(cipher_list, { + nodeId: params.id, + userId: session.user.id + + }).then(function() { + + return Promise.resolve(); + + }).then(resolve, reject); + + } + +}; diff --git a/src/server/api/characters/_id/api-characters-_id-read.js b/src/server/api/characters/_id/api-characters-_id-read.js new file mode 100644 index 0000000..9615e6e --- /dev/null +++ b/src/server/api/characters/_id/api-characters-_id-read.js @@ -0,0 +1,52 @@ +/* globals module, require */ + +var _ = require('underscore'); + +var cipher_list = '' + + 'MATCH (node:Character),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND id(node) = {nodeId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' RETURN node;'; + +module.exports = { + + method: 'GET', + + contentTypes: [ + 'application/json', + 'text/json' + ], + + validator: function(c) { + return { + + id: [ + c.number, + c.required + ] + + }; + }, + + resolver: function(params, session, resolve, reject) { + + query(cipher_list, { + nodeId: params.id, + userId: session.user.id + + }).then(function(results) { + + var items = _.collect(results, function(result) { + return result['node']; + }); + + return Promise.resolve(items); + + }).then(resolve, reject); + + } + +}; + diff --git a/src/server/api/characters/_id/api-characters-_id-resource.js b/src/server/api/characters/_id/api-characters-_id-resource.js new file mode 100644 index 0000000..2739d45 --- /dev/null +++ b/src/server/api/characters/_id/api-characters-_id-resource.js @@ -0,0 +1,6 @@ +/* globals */ +'use strict'; + +import parent from '../api-characters-resource.js'; + +export default parent.child(':charId'); diff --git a/src/server/api/characters/_id/api-characters-_id-update.js b/src/server/api/characters/_id/api-characters-_id-update.js new file mode 100644 index 0000000..b47b677 --- /dev/null +++ b/src/server/api/characters/_id/api-characters-_id-update.js @@ -0,0 +1,63 @@ +/* globals module, require */ + +import _ from 'underscore'; + +import resource from './api-characters-_id-resource.js'; + +import '../../../prototypes.js' + +const cypher = '' + + 'MATCH (node:Character),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND id(node) = {nodeId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' SET {properties}' + + ' RETURN id(node);'; + +export const name = 'update'; + +const method = resource.PUT().as('json'); + +method.validator = (data) => { + return suit.fit(data, (c) => { + return { + + id: [ + c.number, + c.required + ], + + name: [ + c.string + ] + + }; + }); +}; + +method.handler = (request, response) => { + + var properties = new Map(params.filter(function(key) { + return key in [ 'name' ]; + })); + + return query(cypher, { + userId: request.session.user.id, + properties: properties + + }).then(function(results) { + + if (!results) { + response.status = 404; + return; + } + + response.status = 200; + response.json({ + results: results + }); + + }); + +}; diff --git a/src/server/api/characters/_id/index.js b/src/server/api/characters/_id/index.js new file mode 100644 index 0000000..5105530 --- /dev/null +++ b/src/server/api/characters/_id/index.js @@ -0,0 +1,6 @@ +/* globals */ +'use strict'; + +import './api-characters-_id-delete.js'; +import './api-characters-_id-read.js'; +import './api-characters-_id-update.js'; diff --git a/src/server/api/characters/api-characters-create.js b/src/server/api/characters/api-characters-create.js new file mode 100644 index 0000000..8b98e46 --- /dev/null +++ b/src/server/api/characters/api-characters-create.js @@ -0,0 +1,61 @@ +/* globals module, require */ + +import _ from 'underscore'; + +import resource from './api-characters-resource.js'; + +import '../../prototypes.js' + +const cypher = '' + + 'CREATE (node:Character),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND id(node) = {nodeId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' SET {properties}' + + ' RETURN id(node);'; + +const method = resource.POST().as('json'); + +method.validator = (request) => { + return suit.fit(request, (c) => { + return { + + session: { + user: { + id: [ + c.required, + c.integer + ] + } + } + + }; + }) +}; + +method.resolver = (request, response) => { + + var properties = new Map(params.filter(function(key) { + return key in [ 'name' ]; + })); + + return query(cypher, { + userId: session.user.id, + properties: properties + + }).then(function(results) { + + if (!results) { + response.status = 404; + return; + } + + response.status = 200; + response.json({ + results: results + }); + + }); + +}; diff --git a/src/server/api/characters/api-characters-list.js b/src/server/api/characters/api-characters-list.js new file mode 100644 index 0000000..7fa6c0d --- /dev/null +++ b/src/server/api/characters/api-characters-list.js @@ -0,0 +1,56 @@ +/* globals module, require */ + +import _ from 'underscore'; + +import resource from './api-characters-resource.js'; + +import '../../prototypes.js'; + +const cypher = '' + + 'MATCH (node:Character),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' RETURN id(node);'; + +export const name = 'list'; + +const method = resource.GET().as('json'); + +method.validator = (request) => { + return suit.fit(request, (c) => { + return { + + session: { + user: { + id: [ + c.required, + c.integer + ] + } + } + + }; + }) +}; + +method.resolver = function(request, response) { + + return query(cypher, { + userId: request.session.user.id + + }).then(function(results) { + + if (!results) { + response.status = 404; + return; + } + + response.status = 200; + response.json({ + results: results + }); + + }); + +}; diff --git a/src/server/api/characters/api-characters-resource.js b/src/server/api/characters/api-characters-resource.js new file mode 100644 index 0000000..a9b3c3c --- /dev/null +++ b/src/server/api/characters/api-characters-resource.js @@ -0,0 +1,8 @@ +/* globals */ +'use strict'; + +import parent from '../api-resource.js'; + +export const name = 'characters'; + +export default parent.child(name); diff --git a/src/server/api/characters/index.js b/src/server/api/characters/index.js new file mode 100644 index 0000000..4f5dc81 --- /dev/null +++ b/src/server/api/characters/index.js @@ -0,0 +1,7 @@ +/* globals */ +'use strict'; + +import './_id/index.js'; + +import './api-characters-create.js'; +import './api-characters-list.js'; diff --git a/src/server/api/index.js b/src/server/api/index.js new file mode 100644 index 0000000..62186e9 --- /dev/null +++ b/src/server/api/index.js @@ -0,0 +1,8 @@ +/* globals */ +'use strict'; + +import './auth/index.js'; +import './characters/index.js'; +import './users/index.js'; + +import './api-manifest.js'; diff --git a/src/server/api/users/_api-users-controller.js b/src/server/api/users/_api-users-controller.js new file mode 100644 index 0000000..e69de29 diff --git a/src/server/api/users/_api-users-template.jade b/src/server/api/users/_api-users-template.jade new file mode 100644 index 0000000..e69de29 diff --git a/src/server/api/users/_id/_admin-accounts-_id-controller.js b/src/server/api/users/_id/_admin-accounts-_id-controller.js new file mode 100644 index 0000000..e69de29 diff --git a/src/server/api/users/_id/_admin-accounts-_id-template.jade b/src/server/api/users/_id/_admin-accounts-_id-template.jade new file mode 100644 index 0000000..e69de29 diff --git a/src/server/api/users/_id/api-users-_id-delete.js b/src/server/api/users/_id/api-users-_id-delete.js new file mode 100644 index 0000000..fa36c3f --- /dev/null +++ b/src/server/api/users/_id/api-users-_id-delete.js @@ -0,0 +1,48 @@ +/* globals module, require */ + +import _ from 'underscore'; + +const cipher_list = '' + + 'MATCH (node:User)-[relationship]-(),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND id(node) = {nodeId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' DELETE node, relationship;'; + +module.exports = { + + method: 'DELETE', + + contentTypes: [ + 'application/json', + 'text/json' + ], + + validator: function(c) { + return { + + id: [ + c.number, + c.required + ] + + }; + }, + + resolver: function(params, session, resolve, reject) { + + query(cipher_list, { + nodeId: params.id, + userId: session.user.id + + }).then(function() { + + return Promise.resolve(); + + }).then(resolve, reject); + + } + +}; + diff --git a/src/server/api/users/_id/api-users-_id-read.js b/src/server/api/users/_id/api-users-_id-read.js new file mode 100644 index 0000000..b39482c --- /dev/null +++ b/src/server/api/users/_id/api-users-_id-read.js @@ -0,0 +1,52 @@ +/* globals module, require */ + +var _ = require('underscore'); + +var cipher_list = '' + + 'MATCH (node:User),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND id(node) = {nodeId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' RETURN node;'; + +module.exports = { + + method: 'GET', + + contentTypes: [ + 'application/json', + 'text/json' + ], + + validator: function(c) { + return { + + id: [ + c.number, + c.required + ] + + }; + }, + + resolver: function(params, session, resolve, reject) { + + query(cipher_list, { + nodeId: params.id, + userId: session.user.id + + }).then(function(results) { + + var items = _.collect(results, function(result) { + return result['node']; + }); + + return Promise.resolve(items); + + }).then(resolve, reject); + + } + +}; + diff --git a/src/server/api/users/_id/api-users-_id-resource.js b/src/server/api/users/_id/api-users-_id-resource.js new file mode 100644 index 0000000..8b63a68 --- /dev/null +++ b/src/server/api/users/_id/api-users-_id-resource.js @@ -0,0 +1,8 @@ +/* global */ +'use strict'; + +import parent from '../api-users-resource.js'; + +export const name = ':id'; + +export default parent.child(name); diff --git a/src/server/api/users/_id/api-users-_id-update.js b/src/server/api/users/_id/api-users-_id-update.js new file mode 100644 index 0000000..ede24ce --- /dev/null +++ b/src/server/api/users/_id/api-users-_id-update.js @@ -0,0 +1,61 @@ +/* globals module, require */ + +import '../../../prototypes.js' + +import _ from 'underscore'; + +import resource from './api-users-_id-resource.js'; + +const cipher_list = '' + + 'MATCH (node:User),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND id(node) = {nodeId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' SET {properties}' + + ' RETURN id(node);'; + +const operation = resource.PUT().as('json'); + +let whitelist = [ + 'name' +]; + +operation.validator = (data) => { + return suit.fit(data, (c) => { + return { + + id: [ + c.number, + c.required + ], + + name: [ + c.string + ] + + }; + }); +}; + +operation.handler = function(request, response, params) { + + var properties = new Map(params.filter(function(key) { + return key in whitelist + })); + + return query(cipher_list, { + nodeId: params.id, + userId: session.user.id, + properties: properties + + }).then(function(results) { + + request.status = 200; + + }).catch((error) => { + request.status = 500; + request.json = error; + }); + +}; diff --git a/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-details.js b/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-details.js new file mode 100644 index 0000000..b53fa3b --- /dev/null +++ b/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-details.js @@ -0,0 +1,35 @@ +/* global JSON */ +'use strict'; + +import resource from './api-users-_id-characters-_id-resource.js'; +import neo4j from '../../../../../neo4j.js'; + +export const query = 'MATCH c:Character WHERE id(c) = :charId'; + +const operation = resource.GET().as('json'); + +operation.validator = (data) => { + return suit.fit(data, (c) => { + return { + + charId: [ + c.required(), + c.integer() + ] + + }; + }); +}; + +operation.handler = (request, response, data) => { + + return neo4j(query, data).then((result) => { + return response.status(200) + .body(result); // not actually detailed enough. + + }).catch((error) => { + return response.status(500) + .body(JSON.stringify(error)); // not actually detailed enough. + }); + +}; diff --git a/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-remove.js b/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-remove.js new file mode 100644 index 0000000..b5d06e0 --- /dev/null +++ b/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-remove.js @@ -0,0 +1,36 @@ +/* global JSON */ +'use strict'; + + +import resource from './api-users-_id-characters-_id-resource.js'; +import neo4j from '../../../../../neo4j.js'; + +export const query = 'MATCH c:Character WHERE id(c) = :charId'; + +const operation = resource.DELETE().as('json'); + +operation.validator = (data) => { + return suit.fit(data, (c) => { + return { + + charId: [ + c.required(), + c.integer() + ] + + }; + }); +}; + +operation.handler = (request, response, data) => { + + return neo4j(query, data).then((result) => { + return response.status(200) + .body(result); // not actually detailed enough. + + }).catch((error) => { + return response.status(500) + .body(JSON.stringify(error)); // not actually detailed enough. + }); + +}; diff --git a/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-resource.js b/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-resource.js new file mode 100644 index 0000000..74f4661 --- /dev/null +++ b/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-resource.js @@ -0,0 +1,8 @@ +/* global */ +'use strict'; + +import parent from '../api-users-_id-characters-resource.js'; + +export const name = ':id'; + +export default parent.child(name); diff --git a/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-update.js b/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-update.js new file mode 100644 index 0000000..9fa255e --- /dev/null +++ b/src/server/api/users/_id/characters/_id/api-users-_id-characters-_id-update.js @@ -0,0 +1,34 @@ +/* global */ +'use strict'; + + +import resource from './api-users-_id-characters-_id-resource.js'; +import neo4j from '../../../../../neo4j.js'; + +export const query = 'MATCH c:Character WHERE id(c) = :charId'; + +const operation = resource.PUT().as('json'); + +operation.validator = (data) => { + return suit.fit(data, (c) => { + return { + charId: [ + c.required(), + c.integer() + ] + }; + }); +}; + +operation.handler = (request, response, data) => { + + return neo4j(query, data).then((result) => { + return response.status(200) + .body(result); // not actually detailed enough. + + }).catch((error) => { + return response.status(500) + .body(JSON.stringify(error)); // not actually detailed enough. + }); + +}; diff --git a/src/server/api/users/_id/characters/_id/downtime/api-users-_id-characters-_id-downtime-list.js b/src/server/api/users/_id/characters/_id/downtime/api-users-_id-characters-_id-downtime-list.js new file mode 100644 index 0000000..81c89cf --- /dev/null +++ b/src/server/api/users/_id/characters/_id/downtime/api-users-_id-characters-_id-downtime-list.js @@ -0,0 +1,35 @@ +/* global JSON */ +'use strict'; + +import resource from './api-users-_id-characters-_id-downtime-resource.js'; +import neo4j from '../../../../../../neo4j.js'; + +export const query = 'MATCH c:Character WHERE id(c) = :charId'; + +const operation = resource.GET().as('json'); + +operation.validator = (data) => { + return suit.fit(data, (c) => { + return { + + charId: [ + c.required(), + c.integer() + ] + + }; + }); +}; + +operation.handler = (request, response, data) => { + + return neo4j(query, data).then((result) => { + return response.status(200) + .body(result); // not actually detailed enough. + + }).catch((error) => { + return response.status(500) + .body(JSON.stringify(error)); // not actually detailed enough. + }); + +}; diff --git a/src/server/api/users/_id/characters/_id/downtime/api-users-_id-characters-_id-downtime-resource.js b/src/server/api/users/_id/characters/_id/downtime/api-users-_id-characters-_id-downtime-resource.js new file mode 100644 index 0000000..048c244 --- /dev/null +++ b/src/server/api/users/_id/characters/_id/downtime/api-users-_id-characters-_id-downtime-resource.js @@ -0,0 +1,8 @@ +/* global */ +'use strict'; + +import parent from '../api-users-_id-characters-_id-resource.js'; + +export const name = 'downtime'; + +export default parent.child(name); diff --git a/src/server/api/users/_id/characters/_id/downtime/index.js b/src/server/api/users/_id/characters/_id/downtime/index.js new file mode 100644 index 0000000..b0f74d3 --- /dev/null +++ b/src/server/api/users/_id/characters/_id/downtime/index.js @@ -0,0 +1,4 @@ +/* globals */ +'use strict'; + +import './api-users-_id-characters-_id-downtime-list.js'; diff --git a/src/server/api/users/_id/characters/_id/index.js b/src/server/api/users/_id/characters/_id/index.js new file mode 100644 index 0000000..5a04670 --- /dev/null +++ b/src/server/api/users/_id/characters/_id/index.js @@ -0,0 +1,8 @@ +/* globals */ +'use strict'; + +import './downtime/index.js'; + +import './api-users-_id-characters-_id-details.js'; +import './api-users-_id-characters-_id-remove.js'; +import './api-users-_id-characters-_id-update.js'; diff --git a/src/server/api/users/_id/characters/api-users-_id-characters-create.js b/src/server/api/users/_id/characters/api-users-_id-characters-create.js new file mode 100644 index 0000000..c4bd9fc --- /dev/null +++ b/src/server/api/users/_id/characters/api-users-_id-characters-create.js @@ -0,0 +1,30 @@ +/* global */ +'use strict'; + + +import resource from './api-users-_id-characters-resource.js'; +import neo4j from '../../../../neo4j.js'; + +export const query = 'MATCH u:User'; + +const operation = resource.POST().as('json'); + +operation.validator = (data) => { + return suit.fit(data, (c) => { + return { + } + }); +}; + +operation.handler = (request, response, data) => { + + return neo4j(query, data).then((result) => { + return response.status(200) + .body(result); // not actually detailed enough. + + }).catch((error) => { + return response.status(500) + .body(JSON.stringify(error)); // not actually detailed enough. + }); + +}; diff --git a/src/server/api/users/_id/characters/api-users-_id-characters-list.js b/src/server/api/users/_id/characters/api-users-_id-characters-list.js new file mode 100644 index 0000000..13b4fa5 --- /dev/null +++ b/src/server/api/users/_id/characters/api-users-_id-characters-list.js @@ -0,0 +1,30 @@ +/* global */ +'use strict'; + + +import resource from './api-users-_id-characters-resource.js'; +import neo4j from '../../../../neo4j.js'; + +export const query = 'MATCH c:Character WHERE (c) <- [:plays] <- u:User AND (c) <- [:permission-read] <- u'; + +const operation = resource.GET().as('json'); + +operation.validator = (data) => { + return suit.fit(data, (c) => { + return { + } + }); +}; + +operation.handler = (request, response, data) => { + + return neo4j(query, data).then((result) => { + return response.status(200) + .body(result); // not actually detailed enough. + + }).catch((error) => { + return response.status(500) + .body(JSON.stringify(error)); // not actually detailed enough. + }); + +}; diff --git a/src/server/api/users/_id/characters/api-users-_id-characters-resource.js b/src/server/api/users/_id/characters/api-users-_id-characters-resource.js new file mode 100644 index 0000000..3dfd616 --- /dev/null +++ b/src/server/api/users/_id/characters/api-users-_id-characters-resource.js @@ -0,0 +1,8 @@ +/* global */ +'use strict'; + +import parent from '../api-users-_id-resource.js'; + +export const name = 'characters'; + +export default parent.child(name); diff --git a/src/server/api/users/_id/characters/index.js b/src/server/api/users/_id/characters/index.js new file mode 100644 index 0000000..41e2669 --- /dev/null +++ b/src/server/api/users/_id/characters/index.js @@ -0,0 +1,7 @@ +/* globals */ +'use strict'; + +import './_id/index.js'; + +import './api-users-_id-characters-create.js'; +import './api-users-_id-characters-list.js'; diff --git a/src/server/api/users/_id/index.js b/src/server/api/users/_id/index.js new file mode 100644 index 0000000..fce46e1 --- /dev/null +++ b/src/server/api/users/_id/index.js @@ -0,0 +1,8 @@ +/* globals */ +'use strict'; + +import './characters/index.js'; + +import './api-users-_id-delete.js'; +import './api-users-_id-read.js'; +import './api-users-_id-update.js'; diff --git a/src/server/api/users/api-users-create.js b/src/server/api/users/api-users-create.js new file mode 100644 index 0000000..6e8e95e --- /dev/null +++ b/src/server/api/users/api-users-create.js @@ -0,0 +1,82 @@ +/* globals module, require */ + +import _ from 'underscore'; + +import '../../prototypes.js' +import resource from './api-users-resource.js'; + +let cipher = '' + + 'MATCH (creator:User { _id: {userId} }),(createPermission:Permission { name: \'users-create\' })' + + 'CREATE (node:User)' + + ' WHERE id(user) = {userId}' + + ' AND id(node) = {nodeId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' SET {properties}' + + ' RETURN id(node);'; + +export const name = 'create'; + +const method = resource.POST().as('json'); + +method.validator = (data) => { + return suit.fit((c) => { + return { + + session: { + user: { + id: [ + c.required, + c.integer + ] + } + }, + + body: { + name: [ + c.string, + c.required + ] + } + + } + }); +}; + +method.handler = function(request, response, params) { + + const properties = new Map(params.filter(function(key) { + return key in [ 'name' ] + })); + + query(cipher, { + userId: session.user.id, + properties: properties + + }).then(function(results) { + + if (!results || !results[0]) { + response.status(500); + response.json({ + message: 'Couldn\'t insert record for some reason.' + }); + } + + const userId = results._id; + + response.status(200); + response.json({ + link: `${resource.path}/${userId}` + }); + + }).catch((error) => { + + response.status(500); + response.json({ + message: error.message + }); + + }); + +}; + diff --git a/src/server/api/users/api-users-list.js b/src/server/api/users/api-users-list.js new file mode 100644 index 0000000..530d84c --- /dev/null +++ b/src/server/api/users/api-users-list.js @@ -0,0 +1,45 @@ +/* globals module, require */ + +import _ from 'underscore'; + +import resource from './api-users-resource.js'; +import query from '../../neo4j.js'; + +import '../../prototypes.js' + +const operation = resource.GET().as('json'); + +const cipher_list = '' + + 'MATCH (node:User),(user:User)' + + ' WHERE id(user) = {userId}' + + ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + + ' XOR NOT (node) - [:Requires] -> (:Permission)' + + ' RETURN id(node);'; + +export const name = 'list'; + +operation.validator = (c) => { + return { + }; +}; + +operation.handler = (request, response, params) => { + + const userId = request.session.user && request.session.user.id; + + if (!userId) { + return response.status(401).json({}); + } + + return query(cipher_list, { + userId: userId + + }).then(function(results) { + + console.info(JSON.stringify(results, null, '\t')); + + return Promise.resolve(); + + }); + +}; diff --git a/src/server/api/users/api-users-resource.js b/src/server/api/users/api-users-resource.js new file mode 100644 index 0000000..6ba0b8f --- /dev/null +++ b/src/server/api/users/api-users-resource.js @@ -0,0 +1,8 @@ +/* global */ +'use strict'; + +import parent from '../api-resource.js'; + +export const name = 'users'; + +export default parent.child(name); diff --git a/src/server/api/users/index.js b/src/server/api/users/index.js new file mode 100644 index 0000000..1bfcda6 --- /dev/null +++ b/src/server/api/users/index.js @@ -0,0 +1,7 @@ +/* globals */ +'use strict'; + +import './_id/index.js'; + +import './api-users-create.js'; +import './api-users-list.js'; diff --git a/src/server/config.js b/src/server/config.js index 7a93941..f7321c5 100644 --- a/src/server/config.js +++ b/src/server/config.js @@ -1,6 +1,6 @@ /* globals require, module, __dirname */ -module.exports = { +export default { path: { base: __dirname @@ -34,7 +34,8 @@ module.exports = { EXIT_SOCKET: 3, EXIT_SWARM: 4, EXIT_TIMEOUT: 5, - EXIT_ERROR: 6 + EXIT_ERROR: 6, + EXIT_NEO4J: 7 } diff --git a/src/server/exit.js b/src/server/exit.js index 9e2aa58..f456f7a 100644 --- a/src/server/exit.js +++ b/src/server/exit.js @@ -1,9 +1,8 @@ /* globals require, module, process */ var _ = require('underscore'); -var Promise = require('promise'); -var config = require('./config'); +import config from './config.js'; var listeners = []; var exitCode = 0; @@ -77,10 +76,6 @@ first.then(function(list) { process.exit(max); }); -module.exports = { - - listen: function (callback) { - listeners.push(callback); - } - -}; +export default function (callback) { + listeners.push(callback); +} diff --git a/src/server/express.js b/src/server/express.js index 4c8307e..1468661 100644 --- a/src/server/express.js +++ b/src/server/express.js @@ -1,17 +1,18 @@ /* globals require, module, __dirname */ -var express = require('express'); -var fileStore = require('session-file-store'); -var errorHandler = require('errorhandler'); -var session = require('express-session'); -var helmet = require('helmet'); -var bodyParser = require('body-parser'); +import express from 'express'; +import fileStore from 'session-file-store'; +import errorHandler from 'errorhandler'; +import session from 'express-session'; +import helmet from 'helmet'; +import bodyParser from 'body-parser'; +import paths from 'path'; -var config = require('./config'); +import config from './config'; -var FileStore = fileStore(session); +let FileStore = fileStore(session); -var app = express(); +let app = express(); app.use(errorHandler()); app.use(bodyParser()); @@ -32,20 +33,6 @@ app.use(session({ }) })); -app.use(express.static(config.path.base + '/static', { - index: false -})); - -app.set('view engine', 'jade'); -app.set('views', __dirname); - -app.get('/', function(req, res) { - req.session.touch(); - res.render('main', { - dev: req.query['dev'] - ? req.query['dev'] === 'true' - : config.debug - }); -}); +app.use(express.static('src/server/static')); -module.exports = app; +export default app; diff --git a/src/server/hateoas.js b/src/server/hateoas.js new file mode 100644 index 0000000..a8803f9 --- /dev/null +++ b/src/server/hateoas.js @@ -0,0 +1,8 @@ +/* global */ +'use strict'; + +import Hateoas from 'express-hateoas'; + +import express from './express'; + +export default new Hateoas(express); diff --git a/src/server/http.js b/src/server/http.js index 2a1c714..33b5de1 100644 --- a/src/server/http.js +++ b/src/server/http.js @@ -2,16 +2,18 @@ var http = require('http'); -var app = require('./express'); -var exit = require('./exit'); -var config = require('./config'); +import app from './express.js'; +import exit from './exit.js'; +import config from './config.js'; var Server = http.Server; // create and start the HTTP server with static file serving. -var server = module.exports = new Server(app); +let server = new Server(app); -exit.listen(function(resolve) { +export default server; + +exit(function(resolve) { if (!server) { console.log('Http server has not been created.'); diff --git a/src/server/main.jade b/src/server/main.jade deleted file mode 100644 index a10a6e0..0000000 --- a/src/server/main.jade +++ /dev/null @@ -1,33 +0,0 @@ -doctype xml -doctype html - -- - var attr_html = { - manifest: 'app.manifest' - }; - - var attr_script = { - type: 'application/javascript', - src: 'scripts.min.js' - }; - - if (dev) { - attr_script['src'] = 'lib/require.js'; - attr_script['data-main'] = 'require-config.js'; - delete attr_html['manifest']; - } - -html&attributes(attr_html) - - head - - meta(name="viewport", content="width=device-width, initial-scale=1, user-scalable=no") - - title Crucible LARP Manager - - script&attributes(attr_script) - - link(rel="stylesheet" href="styles.min.css") - - body(wrap-layout) - div(ui-view) diff --git a/src/server/model.js b/src/server/model.js index ee345b9..748c8fb 100644 --- a/src/server/model.js +++ b/src/server/model.js @@ -2,7 +2,7 @@ var Model = require('model'); -var socket = require('./socket'); +import socket from './socket'; module.exports = function(session) { diff --git a/src/server/neo4j.js b/src/server/neo4j.js index 55fef9d..f22bc8a 100644 --- a/src/server/neo4j.js +++ b/src/server/neo4j.js @@ -1,48 +1,44 @@ /* globals require, module */ -var neo4j = require('neo4j'); -var Promise = require('promise'); +import neo4j from 'neo4j-simple'; -var config = require('./config'); -var exit = require('./exit'); +import config from './config.js'; +import exit from './exit.js'; -var connection = null; +let connection = null; -function load() { +/** + * @returns {Promise} A neo4j database connection. + */ +export function connect() { + return new Promise((resolve, reject) => { + try { - if (!connection) { - connection = new neo4j.GraphDatabase(config.database); - } + if (!connection) { + connection = neo4j(config.database.url, { + idName: 'id' + }); + } - return connection; + return resolve(connection); + } catch (error) { + return reject(error); + } + }); } -module.exports = function(query, params) { - return new Promise(function(resolve, reject) { - load().cypher({ - query: query, - params: params - }, function(error, results) { - error - ? reject(error) - : resolve(results); - }); +export default function query(query, params) { + return connect().then((db) => { + return db.query(query, params); }); -}; +} -exit.listen(function(resolve) { +exit(function(resolve) { if (!connection) { console.log('Neo4j client has not been initialised.'); return resolve(config.constant.EXIT_OK); } - return connection.close().then(function() { - return Promise.resolve(config.constant.EXIT_OK); - }).catch(function(error) { - console.log(error); - return Promise.resolve(config.constant.EXIT_NEO4J); - }); - }); diff --git a/src/server/prototypes.js b/src/server/prototypes.js new file mode 100644 index 0000000..89d98eb --- /dev/null +++ b/src/server/prototypes.js @@ -0,0 +1,67 @@ +/* globals Symbol, Array, Map, Object */ + +export function iteratorDone() { + return { + done: true, + value: undefined + }; +} + +export function iteratorValue(value) { + return { + done: false, + value: value + }; +} + +export function iteratorNext(next) { + return { + next: next + }; +} + +export function softSet(prototype, property, value) { + + if (!prototype[property]) { + prototype[property] = value; + } + +} + +export function getIterator(iterable) { + + let generator = iterable[Symbol.iterator]; + + if (!generator || typeof(generator) !== 'function') { + throw new TypeError('Provided [ ' + protoChain(iterable) + ' ] is not iterable!'); + } + + let iterator = generator(); + + if (!iterator || typeof(iterator) != 'object') { + throw new TypeError('Generated iterator is invalid!') + } + + return iterator; +} + +export function protoChain(object = this) { + + if (!object) { + return ''; + } + + if (typeof(object) !== 'object') { + throw new TypeError(typeof(object) + ' is not an object'); + } + + let constructor = object.constructor; + let parent = protoChain(constructor.prototype.__proto__); + + return parent + ? parent + ' :: ' + constructor.name + : constructor.name; + +} + +softSet(Object.prototype, 'protoChain', protoChain); diff --git a/src/server/rest.js b/src/server/rest.js deleted file mode 100644 index 86c194d..0000000 --- a/src/server/rest.js +++ /dev/null @@ -1,134 +0,0 @@ -/* globals require, module */ - -var _ = require('underscore'); - -var app = require('./express'); -var auth = require('./service/auth-service'); -var account = require('./service/account-service'); -var adminCharacter = require('./service/admin-character-service'); - -function scan(config, path) { - - var endpoints = _.collect(config, function(value, key) { - - if (!_.isFunction(value)) { - return scan(value, ( path || '' ) + '/' + key); - } - - return app[key](path, function (request, response) { - - var data = _.extend({}, request.query, request.body, request.params); - - return value(data, request.session).then(function (result) { - return response.status(200).send(result); - - }, function (error) { - - // Basic error response. - if (_.isNumber(error)) { - return response.status(error); - } - - // Custom error response. - if (error.status && error.message) { - return response.status(error.status).send({ - error: error.message - }); - } - - // System error response. - if (error.message && error.stack) { - console.error(error.stack); - return response.status(500).send({ - error: error.message - }); - } - - // Unexpected error response. - console.error('Unexpected error response!'); - return response.status(500); - - }); - - }); - - }); - - return _.compact(endpoints); - -} - -module.exports = scan({ - - auth: { - - /** - * @api {get} /api/auth Checks that the authentication for the current user is valid. - * @apiName GetUser - * @apiGroup Authentication - * - * @apiSuccess {Object} user The user record currently in the session. - * - * @type {Function} - */ - get: auth.check, - - /** - * @api {post} /api/auth Logs the user in. - * @apiName ValidateUser - * @apiGroup Authentication - * - * @apiParam {String} email The email of the user. - * @apiParam {String} password The password of the user. - * - * @apiSuccess {Object} user The user record now stored in the session. - * - * @type {Function} - */ - post: auth.login, - - /** - * @api {delete} /api/auth Invalidates the current session. - * @apiName InvalidateUser - * @apiGroup Authentication - * - * @type {Function} - */ - delete: auth.logout - - }, - - account: { - - post: account.signup, - - put: account.update, - - get: account.recover - - }, - - admin: { - - accounts: { - post: null, // create - get: null, // list - ':id': { - get: null, // view - put: null, // update - delete: null // remove - } - }, - - characters: { - get: adminCharacter.list, - post: adminCharacter.create, - ':id': { - get: adminCharacter.read, - put: adminCharacter.update, - delete: adminCharacter.delete - } - } - - } -}, '/api'); diff --git a/src/server/server.js b/src/server/server.js index 2639372..28e8c2e 100644 --- a/src/server/server.js +++ b/src/server/server.js @@ -1,80 +1,90 @@ /* globals require, process, __dirname */ var _ = require('underscore'); -var Promise = require('promise'); -var config = require('./config'); -var http = require('./http'); -var rest = require('./rest'); +import config from './config'; +import http from './http'; +import express from './express.js'; +import rest from './hateoas'; +import './api/index.js'; var running = false; -module.exports = { +export function start(onSuccess, onError) { - start: function(onSuccess, onError) { + if (running) { + var error = new Error('Server already running.'); + onError && onError(error); + return Promise.reject(error); + } - if (running) { - var error = new Error('Server already running.'); - onError && onError(error); - return Promise.reject(error); - } + var promise_resolve, promise_reject; + var promise = new Promise(function(resolve, reject) { + promise_resolve = resolve; + promise_reject = reject; + }); - var promise_resolve, promise_reject; - var promise = new Promise(function(resolve, reject) { - promise_resolve = resolve; - promise_reject = reject; - }); + running = true; + http.listen(config.port, config.hostname, function() { + console.log('Started application on http://' + config.hostname + ':' + config.port + '/'); + onSuccess && onSuccess(); + return promise_resolve(); - running = true; - http.listen(config.port, config.hostname, function() { - console.log('Starting application on http://' + config.hostname + ':' + config.port + '/'); - onSuccess && onSuccess(); - return promise_resolve(); + }).on('error', function(error) { - }).on('error', function(error) { + console.error(error.stack); - console.error(error.stack); + running = false; + onError && onError(); + return promise_reject(error); - running = false; - onError && onError(); - return promise_reject(error); + }); - }); + return promise; - return promise; +} - }, +export function stop(onSuccess, onError) { - stop: function(onSuccess, onError) { + if (!running) { + return Promise.reject(new Error('Server already stopped.')); + } - if (!running) { - return Promise.reject(new Error('Server already stopped.')); - } + var promise_resolve; + var promise_reject; + var promise = new Promise(function(resolve, reject) { + promise_resolve = resolve; + promise_reject = reject; + }); - var promise_resolve; - var promise_reject; - var promise = new Promise(function(resolve, reject) { - promise_resolve = resolve; - promise_reject = reject; - }); + http.close(function(error) { + console.log('Application shutdown complete.'); - http.close(function(error) { - console.log('Application shutdown complete.'); + if (error) { + console.error(error.stack); + onError && onError(); + return promise_reject(error); + } + + running = false; + onSuccess && onSuccess(); + return promise_resolve(); - if (error) { - console.error(error.stack); - onError && onError(); - return promise_reject(error); - } + }); - running = false; - onSuccess && onSuccess(); - return promise_resolve(); + return promise; - }); +} - return promise; +express.use(function(error, request, response, next) { + if (response.headersSent) { + return next(error); } -}; + console.error(error.stack); + response + .status(500) + .send('Something broke!'); + +}); diff --git a/src/server/service/account-service.js b/src/server/service/account-service.js deleted file mode 100644 index 1082775..0000000 --- a/src/server/service/account-service.js +++ /dev/null @@ -1,31 +0,0 @@ -/* globals require, module */ - -var wrapper = require('./wrapper'); - -module.exports = { - - signup: wrapper(function(c) { - return { - }; - - }, function(params, session, resolve, reject) { - return reject(501); - }), - - recover: wrapper(function(c) { - return { - }; - - }, function(params, session, resolve, reject) { - return reject(501); - }), - - update: wrapper(function(c) { - return { - }; - - }, function(params, session, resolve, reject) { - return reject(501); - }) - -}; diff --git a/src/server/service/admin-character-service.js b/src/server/service/admin-character-service.js deleted file mode 100644 index e773c77..0000000 --- a/src/server/service/admin-character-service.js +++ /dev/null @@ -1,184 +0,0 @@ -/* globals require, module */ - -var _ = require('underscore'); -var Promise = require('promise'); - -var query = require('../neo4j'); -var wrapper = require('./wrapper'); - -var cipher_list = '' + - 'MATCH (node:Character),(user:User)' + - ' WHERE id(user) = {userId}' + - ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + - ' XOR NOT (node) - [:Requires] -> (:Permission)' + - ' RETURN id(node);'; - -var cipher_create = ''; - -var cipher_read = '' + - 'MATCH (node:Character),(user:User)' + - ' WHERE id(user) = {userId}' + - ' AND id(node) = {charId}' + - ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + - ' XOR NOT (node) - [:Requires] -> (:Permission)' + - ' RETURN node'; - -var cipher_update = '' + - 'MATCH (node:Character),(user:User)' + - ' WHERE id(user) = {userId}' + - ' AND id(node) = {charId}' + - ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + - ' XOR NOT (node) - [:Requires] -> (:Permission)' + - ' UPDATE node.name = {name}' + - ' RETURN node'; - -var cipher_delete = '' + - 'MATCH (node:Character),(user:User)' + - ' WHERE id(user) = {userId}' + - ' AND id(node) = {charId}' + - ' AND (node) - [:Requires] -> (:Permission) <- [:Possesses] - (user)' + - ' XOR NOT (node) - [:Requires] -> (:Permission)' + - ' REMOVE node' + - ' RETURN node'; - -/** - * A service for providing operations for character admin. - * @type {{list: Function, create: Function, read: Function, update: Function, delete: Function}} - */ -module.exports = { - - /** - * Lists all of the characters in the database. - * @return {Promise} Resolves to a list of Character ids. - */ - list: wrapper(function(c) { - return { - }; - - }, function(params, session, resolve, reject) { - return query(cipher_list, { - userId: session.user.id - - }).then(function(results) { - - var items = _.collect(results, function(result) { - return result['id(node)']; - }); - - return Promise.resolve(items); - - }).then(resolve, reject); - }), - - /** - * Create a new Character object with the needed properties and links. - * @param {Object} character The character object. - * @return {Promise} Resolves to the created entity. - */ - create: wrapper(function(c) { - return { - name: [ c.required, c.string ] - }; - - }, function(params, session, resolve, reject) { - return query(cipher_create, { - char: params - - }).then(function(results) { - - var result = _.first(results); - if (!result) { - throw new Error('Illegal state: CREATE query not returning inserted object.'); - } - - var character = _.extend({}, result.node.properties, { - id: result.node._id, - labels: result.node.labels - }); - - return Promise.resolve(character); - - }).then(resolve, reject); - }), - - read: wrapper(function(c) { - return { - id: [ c.required, c.integer ] - }; - - }, function(params, session, resolve, reject) { - return query(cipher_read, { - charId: params.id, - userId: session.user.id - - }).then(function(results) { - - var result = _.first(results); - if (!result) { - return Promise.reject(404); - } - - var character = _.extend({}, result.node.properties, { - id: result.node._id, - labels: result.node.labels - }); - - return Promise.resolve(character); - - }).then(resolve, reject); - }), - - update: wrapper(function(c) { - return { - id: [ c.required, c.integer ] - }; - - }, function(params, session, resolve, reject) { - return query(cipher_update, { - charId: params.id, - char: params - - }).then(function(results) { - - var result = _.first(results); - if (!result) { - throw new Error('Illegal state: UPDATE query not returning inserted object.'); - } - - var character = _.extend({}, result.node.properties, { - id: result.node._id, - labels: result.node.labels - }); - - return Promise.resolve(character); - - }).then(resolve, reject); - }), - - delete: wrapper(function(c) { - return { - id: [ c.required, c.integer ] - }; - - }, function(params, session, resolve, reject) { - return query(cipher_delete, { - charId: params.id - - }).then(function(results) { - - var result = _.first(results); - if (!result) { - throw new Error('Illegal state: DELETE query not returning inserted object.'); - } - - var character = _.extend({}, result.node.properties, { - id: result.node._id, - labels: result.node.labels - }); - - return Promise.resolve(character); - - }).then(resolve, reject); - }) - -}; diff --git a/src/server/service/auth-service.js b/src/server/service/auth-service.js deleted file mode 100644 index 46df2b5..0000000 --- a/src/server/service/auth-service.js +++ /dev/null @@ -1,83 +0,0 @@ -/* globals require, module, console */ - -var _ = require('underscore'); -var crypto = require('crypto'); -var Promise = require('promise'); - -var query = require('../neo4j'); -var wrapper = require('./wrapper'); - -var cipher_login = '' + - 'MATCH (user:User { email: {email} })' + - ' RETURN user;'; - -module.exports = { - - login: wrapper(function(c) { - return { - email: [ c.email, c.required ], - password: [ c.string, c.required ] - } - - }, function(params, session, resolve, reject) { - - return query(cipher_login, { - email: params.email - }).then(function(results) { - - var result = _.first(results); - - if (!result) { - return reject(404); - } - - var user = _.extend({}, result.user.properties, { - id: result.user._id - }); - - // run crypto hash on supplied password. - var hash = crypto.createHash('md5') - .update(params.password) - .digest('hex'); - - if (hash !== user.password) { - return reject(401); - } - - user.token = crypto.createHash('md5') - .update(user.email + hash) - .digest('hex'); - - session.user = user; - return resolve(user); - - }); - - }, false), - - logout: wrapper(function(c) { - return { - }; - - }, function(params, session, resolve, reject) { - - if (!session.user) { - return reject(404); - } - - session.destroy(); - return resolve(); - - }), - - check: wrapper(function(c) { - return { - }; - - }, function(params, session, resolve) { - - return resolve(session.user); - - }) - -}; diff --git a/src/server/service/wrapper.js b/src/server/service/wrapper.js deleted file mode 100644 index 6cae7e8..0000000 --- a/src/server/service/wrapper.js +++ /dev/null @@ -1,63 +0,0 @@ -/* globals require, module */ - -var _ = require('underscore'); -var suit = require('suit'); -var Promise = require('promise'); - -var constraint = suit.constraints(); - -var Validator = function(constructor) { - var schema = constructor(constraint); - return function(candidate) { - return new Promise(function(resolve, reject) { - try { - return resolve(suit.fit(candidate, schema)); - - } catch (error) { - - if (_.isString(error)) { - console.warn(error); - return reject(400, { - message: error - }); - } - - if (error.message && error.stack) { - return reject(error); - } - - return reject(400, error); - - } - }); - - } -}; - -module.exports = function(validation, operation, secure) { - - var validator = new Validator(validation); - - // Each service function is provided two arguments: params and session. - return function(params, session) { - - if (( secure || _.isUndefined(secure) ) && ( !session.user || !session.user.id )) { - console.log('Attempted access to secured endpoint.'); - return Promise.reject(401); - } - - // If the request payload successfully validates.. - return validator(params).then(function(result) { - - // Return a promise for the operation. - return new Promise(function(resolve, reject) { - - // All operations return the result of their resolution/rejection - return operation(result, session, resolve, reject); - - }); - - }); - - }; -}; diff --git a/src/server/sockit.js b/src/server/sockit.js index 8a8d412..4738b04 100644 --- a/src/server/sockit.js +++ b/src/server/sockit.js @@ -1,10 +1,11 @@ /* globals module, require */ -var app = require('./express'); -var http = require('./http'); -var sockit = require('sockit-express'); +let sockit = require('sockit-express'); -module.exports = sockit({ +import app from './express.js'; +import http from './http.js'; + +export default sockit({ express: app, server: http }); diff --git a/src/server/static/char.html b/src/server/static/index.html similarity index 100% rename from src/server/static/char.html rename to src/server/static/index.html diff --git a/src/test/api/auth/login.spec.js b/src/test/api/auth/login.spec.js new file mode 100644 index 0000000..f37e748 --- /dev/null +++ b/src/test/api/auth/login.spec.js @@ -0,0 +1,115 @@ +/* global describe, it */ +'use strict'; + +import chai from 'chai'; + +const expect = chai.expect; + +import * as setup from '../setup.js'; + +export const request = (email, password) => { + + const body = {}; + email && ( body.email = email ); + password && ( body.password = password ); + + return setup.request({ + uri: `${setup.baseurl}/auth`, + method: 'PUT', + body: body + }); + +}; + +describe('POST:/auth', () => { + + it('should reject a missing email', () => { + + return request(undefined, 'irrelevantpassword').then((result) => { + + expect(result).to.exist; + expect(result.statusCode).to.equal(400); + + }); + + }); + + it('should reject a missing password', () => { + + return request('irrelevantemail', undefined).then((result) => { + + expect(result).to.exist; + expect(result.statusCode).to.equal(400); + + }); + + }); + + it('should reject a missing email and password', () => { + + return request(undefined, undefined).then((result) => { + + expect(result).to.exist; + expect(result.statusCode).to.equal(400); + + }); + + }); + + it('should reject a bad email', () => { + + return request('notauser@dontexist.com', 'irrelevantpassword').then((result) => { + + expect(result).to.exist; + expect(result.statusCode).to.equal(404); + + }); + + }); + + it('should reject a bad password', () => { + + return request('email@somewhere.com', 'wrongpassword').then((result) => { + + expect(result).to.exist; + expect(result.statusCode).to.equal(401); + + }); + + }); + + it('should log-in a correct username + password', () => { + + return request('email@somewhere.com', 'password').then((result) => { + + expect(result).to.exist; + console.info(JSON.stringify(result.body)); + expect(result.statusCode).to.equal(200); + + }); + + }); + + describe('when successfully logged-in', () => { + + let result = null; + + before(() => { + return request('email@somewhere.com', 'password').then((response) => { + result = response; + }); + }); + + it('should not have a password listed.', () => { + expect(result.password).to.not.exist; + }); + + it('should have a list of user permissions', () => { + expect(result.permissions).to.exist; + expect(result.permissions).to.be.an('array'); + expect(result.permissions.length).to.be.greaterThan(0); + }); + + }); + +}); diff --git a/src/test/api/options.spec.js b/src/test/api/options.spec.js new file mode 100644 index 0000000..c13ffa8 --- /dev/null +++ b/src/test/api/options.spec.js @@ -0,0 +1,27 @@ +/* globals require, describe, beforeEach, it */ + +import chai from 'chai'; +import req from 'request-promise'; + +const expect = chai.expect; + +import * as setup from './setup.js'; + +export const request = () => { + return setup.request({ + uri: `${setup.baseurl}`, + method: 'OPTIONS' + }); +}; + +describe("OPTIONS:/", () => { + + it('should provide a', () => { + + return request().then((options) => { + expect(options).to.exist; + }); + + }); + +}); diff --git a/src/test/api/setup.js b/src/test/api/setup.js new file mode 100644 index 0000000..c26281f --- /dev/null +++ b/src/test/api/setup.js @@ -0,0 +1,24 @@ +/* globals before, after, describe, it, console */ + +import req from 'request-promise'; + +export const baseurl = 'http://localhost:8000/api'; + +export const request = req.defaults({ + resolveWithFullResponse: true, + simple: false, + json: true, + jar: true +}); + +before(() => { + + req.debug = true; + +}); + +beforeEach(() => { + + request.jar(); + +}); diff --git a/src/test/api/users/list.spec.js b/src/test/api/users/list.spec.js new file mode 100644 index 0000000..07ab9c7 --- /dev/null +++ b/src/test/api/users/list.spec.js @@ -0,0 +1,47 @@ +/* globals require, describe, it */ + +let chai = require('chai'); + +let expect = chai.expect; + +import * as setup from '../setup.js'; +import { request as login } from '../auth/login.spec.js'; + +export const request = () => { + return setup.request({ + resolveWithFullResponse: true, + uri: `${setup.baseurl}/users`, + method: 'GET', + simple: false, + json: true, + jar: true + }); +}; + +describe("GET:/users", () => { + + it('should be secured', () => { + + return request().then((response) => { + expect(response).to.exist; + expect(response.statusCode).to.equal(401); + + }); + + }); + + it('should provide a list of users', () => { + + return login('email@somewhere.com', 'password').then((response) => { + expect(response.statusCode).to.equal(200); + return request(); + + }).then((response) => { + expect(response).to.exist; + expect(response.statusCode).to.equal(200); + + }); + + }); + +}); diff --git a/src/test/e2e/account/account-options.e2e.es6 b/src/test/e2e/account/account-options.e2e.es6 new file mode 100644 index 0000000..1194978 --- /dev/null +++ b/src/test/e2e/account/account-options.e2e.es6 @@ -0,0 +1,14 @@ +/* globals module, require, describe, it, browser, element, by */ + +describe('animus account options', function() { + + var options = browser.options('http://localhost:8000/account'); + + it('should provide an html template', function(done) { + + expect(options).not.toBe(null); + + done(); + }); + +}); diff --git a/src/test/e2e/admin/admin-options.e2e.es6 b/src/test/e2e/admin/admin-options.e2e.es6 new file mode 100644 index 0000000..eeecc45 --- /dev/null +++ b/src/test/e2e/admin/admin-options.e2e.es6 @@ -0,0 +1,14 @@ +/* globals module, require, describe, it, browser, element, by */ + +describe('animus admin options', function() { + + var options = browser.options('http://localhost:8000/admin'); + + it('should provide an html template', function(done) { + + expect(options).not.toBe(null); + + done(); + }); + +}); diff --git a/src/test/e2e/auth/auth-options.es6 b/src/test/e2e/auth/auth-options.es6 new file mode 100644 index 0000000..645af43 --- /dev/null +++ b/src/test/e2e/auth/auth-options.es6 @@ -0,0 +1,14 @@ +/* globals module, require, describe, it, browser, element, by */ + +describe('animus auth options', function() { + + var options = browser.options('http://localhost:8000/auth'); + + it('should provide an html template', function(done) { + + expect(options).not.toBe(null); + + done(); + }); + +}); diff --git a/src/test/server/login.e2e.js b/src/test/e2e/auth/login.e2e.es6 similarity index 76% rename from src/test/server/login.e2e.js rename to src/test/e2e/auth/login.e2e.es6 index d80263a..8898e8b 100644 --- a/src/test/server/login.e2e.js +++ b/src/test/e2e/auth/login.e2e.es6 @@ -1,9 +1,9 @@ -/** globals module, require, describe, it, browser, element, by **/ +/* globals module, require, describe, it, browser, element, by */ describe('animus login page', function() { it('should login with test credentials', function(done) { - browser.get('http://localhost:8000/?dev=true'); + browser.get('http://localhost:8000/'); element(by.css('input[type=email]')).sendKeys('email@somewhere.com'); element(by.css('input[type=password]')).sendKeys('password'); diff --git a/src/test/e2e/options.e2e.es6 b/src/test/e2e/options.e2e.es6 new file mode 100644 index 0000000..577e741 --- /dev/null +++ b/src/test/e2e/options.e2e.es6 @@ -0,0 +1,11 @@ +/* globals module, require, describe, it, browser, element, by */ + +var chai = require('chai'); + +var expect = chai.expect; + +describe('animus root options', function() { + + var path = "http://localhost:8000/"; + +}); diff --git a/src/test/karma.conf.js b/src/test/karma.conf.js new file mode 100644 index 0000000..9e74c8f --- /dev/null +++ b/src/test/karma.conf.js @@ -0,0 +1,82 @@ +/* globals module, __dirname */ + +var path = require('path'); + +var config = require('../server/config'); + +module.exports = function(config) { + config.set({ + basePath: path.resolve(__dirname, '../../'), + + browsers: [ + 'PhantomJS' + ], + + frameworks: [ + 'mocha', + 'protractor', + 'traceur' + ], + + hostname: config.hostname, + + loggers: [ + + { + type: 'console' + }, + + { + type: 'file', + filename: 'karma.log', + maxLogSize: 20480, + backups: 0, + category: 'relative-logger' + } + ], + + plugins: [ + 'karma-mocha', + 'karma-chrome-launcher', + 'karma-phantomjs-launcher', + 'karma-coverage', + 'karma-junit-reporter' + ], + + port: config.port, + + preprocessors: { + + 'src/server/**/*.es6': [ + 'traceur', + 'coverage' + ], + + 'src/server/**/*.js': [ + 'coverage' + ] + + }, + + reporters: [ + 'progress', + 'coverage', + 'junit' + ], + + singleRun: true, + + coverageReporter: { + type: 'html', + dir: 'coverage/' + }, + + traceurPreprocessor: { + options: { + sourceMaps: true, + modules: 'amd' + } + } + + }) +}; diff --git a/src/test/mocha.opts b/src/test/mocha.opts new file mode 100644 index 0000000..3ebeef7 --- /dev/null +++ b/src/test/mocha.opts @@ -0,0 +1,5 @@ +--require expect +--ui bdd +--grep ^.+\.spec\..+$ +--recursive +--compilers es6:mocha-traceur diff --git a/src/test/protractor.js b/src/test/protractor.js index 3052785..cac42d6 100644 --- a/src/test/protractor.js +++ b/src/test/protractor.js @@ -1,39 +1,61 @@ /* globals exports, require, __dirname */ +var loader = require('es6-module-loader'); var phantomjs = require('phantomjs'); -var server = require('../server/server'); -var config = require('../scripts/config'); -var Promise = require('promise'); -exports.config = { +var System = loader.System; +System.transpiler = 'traceur'; +System.traceurOptions = { + // fuck knows. +}; - seleniumServerJar: config.PATH_LIBS_ABS + '/protractor/selenium/selenium-server-standalone-2.45.0.jar', +Promise.all([ + System.import('../server/server.es6'), + System.import('../scripts/config.es6') - capabilities: { - browserName: 'phantomjs', - 'phantomjs.binary.path': phantomjs.path - }, +]).then(function (imports) { + var server = imports[0]; + var config = imports[1]; - framework: 'mocha', + exports.config = { - mochaOpts: { - ui: 'bdd', - reporter: 'list' - }, + seleniumServerJar: config.PATH_LIBS_ABS + '/protractor/selenium/selenium-server-standalone-2.45.0.jar', - jasmineNodeOpts: { - isVerbose: true, - showColors: true, - includeStackTrace: true, - defaultTimeoutInterval: 30000 - }, + specs: [ + './protractor/**/*.e2e.*' + ], - beforeLaunch: function() { - return server.start(); - }, + capabilities: { + browserName: 'phantomjs', + 'phantomjs.binary.path': phantomjs.path + }, - afterLaunch: function() { - return server.stop(); - } + framework: 'mocha', -}; + mochaOpts: { + ui: 'bdd', + reporter: 'list', + compilers: 'es6:mocha-traceur' + }, + + jasmineNodeOpts: { + isVerbose: true, + showColors: true, + includeStackTrace: true, + defaultTimeoutInterval: 30000 + }, + + beforeLaunch: function () { + return server.start(); + }, + + afterLaunch: function () { + return server.stop(); + } + + }; + +}).catch(function (error) { + console.error(error.message); + throw error; +}); diff --git a/src/test/unit/prototypes.spec.es6 b/src/test/unit/prototypes.spec.es6 new file mode 100644 index 0000000..19fb3b6 --- /dev/null +++ b/src/test/unit/prototypes.spec.es6 @@ -0,0 +1,75 @@ +/* globals require, describe, it, Array, Map, Object */ + +import * as prototypes from '../../server/prototypes.js'; + +let chai = require('chai'); + +let expect = chai.expect; + +describe('A prototype extension', function() { + + describe('to collect iterable results', function() { + + it('should be defined on Array, Map, and Object prototypes', function() { + expect(Array.prototype.collect).to.be.a('function'); + expect(Map.prototype.collect).to.be.a('function'); + expect(Object.prototype.collect).to.be.a('function'); + }); + + it('should collect values transformed from an Array', function() { + + let array = [ 'a', 'b', 'c' ]; + let transform = function(item) { + return item.toUpperCase(); + }; + + let result = array.collect(transform); + + expect(result).to.eql([ 'A', 'B', 'C' ]); + + }) + + }); + + describe('to filter iterable results', function() { + + it('should be defined on Array, Map, and Object prototypes', function() { + expect(Array.prototype.filter).to.be.a('function'); + expect(Map.prototype.filter).to.be.a('function'); + expect(Object.prototype.filter).to.be.a('function'); + }); + + it('should filter an Array based on a provided predicate', function() { + + let array = [ 'a', 'b', 'c' ]; + let predicate = function(item) { + return item !== 'b'; + }; + + let result = prototypes.filter.call(array, predicate); + + expect(result).to.eql([ 'a', 'c' ]); + + }); + + }); + + describe('to print a prototype chain', function() { + + it('should be defined on Object', function() { + expect(Object.prototype.protoChain).to.be.a('function'); + }); + + it('should return a well-formatted prototype chain', function() { + + let array = []; + + let result = prototypes.protoChain.call(array); + + expect(result).to.equal('Object :: Array'); + + }); + + }); + +});