diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ff3e768 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +deploy: + provider: pages + skip-cleanup: true + local_dir: ./dist + github-token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable + keep-history: true + on: + branch: master diff --git a/README.md b/README.md index 47c8f52..75d817e 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,11 @@ -# Runway Web Interface +# TaraScope [(taraframework.github.io/tarascope/)](https://taraframework.github.io/tarascope/) -This provides a web interface to Runway, so you can run models of distributed -systems, visualize them, and interact with them. It embeds -[runway-compiler](https://github.com/salesforce/runway-compiler) to parse -and execute model files. +![TaraScope](images/RaftScope.png) -Runway is a newly released project (May 2016), and we're actively working on -introductory materials and documentation. Existing resources include: - - [intro blog post](https://medium.com/salesforce-open-source/runway-intro-dc0d9578e248), - includes recording of talk and demos of Too Many Bananas, Elevators, Raft models - - [USENIX ;login: article](https://www.usenix.org/publications/login/fall2016/ongaro) - - [wiki](https://github.com/salesforce/runway-browser/wiki) - - [specification language guide](https://github.com/salesforce/runway-compiler/blob/master/doc/LANGUAGE-GUIDE.md) - - [runway-dev mailing list](https://groups.google.com/forum/#!forum/runway-dev) +Tarascope is an extended version of [Raftscope](https://github.com/ongardie/raftscope) & [Runway Browser](https://github.com/salesforce/runway-browser) by Diego Ongaro (@ongardie). -Here's an [example](https://runway.systems): +TaraScope aides your understanding of TARA with a bunch of visualized edge cases. -[![Too Many Bananas simulation screencast](screencast.gif)](https://runway.systems) +[Try this model in Runway](https://runway.systems/?model=github.com/taraframework/runway-model-tara) -## Setup - -You can try this out on , but if you're developing a -model, you'll probably find it more comfortable to run runway-browser locally. - -First make sure you have `node` and `npm` (node package manager) installed. -Then run `npm install` to install dependencies. - -Run `npm run webpack`. This packages up the interpreter along with its -dependencies into a single JavaScript file using -[webpack](https://webpack.github.io/). (This is a big gotcha if you're changing -the internal code, where you forget this step. Use -`./node_modules/.bin/webpack --watch` for that or -[webpack-dev-server](https://webpack.github.io/docs/webpack-dev-server.html).) - -Set up a web server to serve the `dist/` directory. For example: - - npm install -g nws - nws -d dist -o - -The `-o` will open `dist/index.html` in a web browser as served through that web server. -The first thing that'll do is pull down a model and view file for the default -model. By design, the model and view files aren't compiled into `bundle.js` -with webpack and aren't processed by the web server at all. - -You should see a very basic counter model come up. - -To see other models, symlink them underneath the `dist/models/` directory, then -pass `?model=path/to/directory`. For example, navigating to - will load -`dist/models/elevators/package.json`. The `package.json` file describes where -to find the spec and view. Otherwise, Runway will look default to files named -after the directory (`dist/models/elevators/elevators.model` and -`dist/models/elevators/elevators.js` here). -Be sure to load only trustworthy view files, since those may run arbitrary -JavaScript code within your browser. - -## Writing a View - -To get the most out of Runway, you need to provide a view, describing how to -visualize and manipulate your model. Defining the view can be tedious but isn't -particularly difficult once you get the hang of it. The nice thing is you've -got all of the global state dumped out right below the SVG by default, so you -can build up the view incrementally. - -Views used to be written with React and JSX, but that is now deprecated in -favor of d3. - -Start with an existing example such as -[runway-model-raft](https://github.com/ongardie/runway-model-raft) for the -basic structure. The key things you need -to understand are: - -- [D3](https://d3js.org/). - See [API Reference](https://github.com/mbostock/d3/wiki/API-Reference) and - [Thinking With Joins](https://bost.ocks.org/mike/join/). -- [SVG](https://developer.mozilla.org/en-US/docs/Web/SVG). - In particular, you should familiarize yourself with these common elements: - [g](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g), - [rect](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect), - [circle](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle), - [text](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text), - [line](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line), and - [path](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path). -- Coordinate space: (0, 0) is the top left of the canvas, with Y growing - downwards. The current canvas is about 100x100, but one of the dimensions can - be slightly larger depending on how it's resized. We might change this soon, - as other SVG tools seem to default to canvases that are an order of magnitude - or so larger. -- Manually positioning everything is annoying. Hopefully we can find a nicer - solution in the future. `BBox` in [lib/util.js](lib/util.js) might help. -- Don't be afraid to embrace some "globals" in your view. It's a lot easier - than passing around the model everywhere, for example. -- Access variables from the model using runway-compiler's - [JavaScript API](https://github.com/salesforce/runway-compiler/blob/master/doc/JAVASCRIPT-API.md). +TaraScope may not cover all edge cases either due to lack of code. This specification of TARA is for visual purposes of understanding only & not a final specification; if there is such a thing, it's [TARA.tla](https://github.com/TARAFramework/tara.tla). diff --git a/dist/448c34a56d699c29117adc64c43affeb.woff2 b/dist/448c34a56d699c29117adc64c43affeb.woff2 new file mode 100644 index 0000000..64539b5 Binary files /dev/null and b/dist/448c34a56d699c29117adc64c43affeb.woff2 differ diff --git a/dist/89889688147bd7575d6327160d64e760.svg b/dist/89889688147bd7575d6327160d64e760.svg new file mode 100644 index 0000000..94fb549 --- /dev/null +++ b/dist/89889688147bd7575d6327160d64e760.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dist/bundle.js b/dist/bundle.js new file mode 100644 index 0000000..7b27192 --- /dev/null +++ b/dist/bundle.js @@ -0,0 +1,1743 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + eval("/*\n * Copyright (c) 2015-2016, Salesforce.com, Inc.\n * All rights reserved.\n * Licensed under the MIT license.\n * For full license text, see LICENSE.md file in the repo root or\n * https://opensource.org/licenses/MIT\n */\n\n'use strict';\n\nlet jQuery = __webpack_require__(74);\nwindow.jQuery = jQuery;\n__webpack_require__(75);\nlet _ = __webpack_require__(98);\n//delete window._;\nlet queryString = __webpack_require__(100);\nlet getParams = queryString.parse(window.location.search.slice(1));\n\nlet compiler = __webpack_require__(103);\nwindow.compiler = compiler;\nlet GlobalEnvironment = __webpack_require__(108).GlobalEnvironment;\nlet preludeText = __webpack_require__(157);\nlet PubSub = __webpack_require__(158);\n\nlet Featured = __webpack_require__(159);\nlet Controller = __webpack_require__(160).Controller;\nlet Highlight = __webpack_require__(165);\nlet makeBrowserRequire = __webpack_require__(169);\nlet WorkerClient = __webpack_require__(335);\n\nlet showAbout = __webpack_require__(336);\nlet ExecutionView = __webpack_require__(338);\nlet REPLView = __webpack_require__(340);\nlet RuleControls = __webpack_require__(342);\nlet StateDump = __webpack_require__(331);\nlet TimelineView = __webpack_require__(343).TimelineView;\n\nlet workerClient = new WorkerClient();\n\nlet pageLoaded = new Promise((resolve, reject) => {\n jQuery(window).on('load', resolve);\n});\n\nclass Package {\n constructor(original, repo) {\n this.original = original;\n this.repo = repo; // may be undefined\n this.p = _.cloneDeep(original);\n\n let basename;\n if (repo !== undefined) {\n basename = _.last(repo.split('/'));\n if (repo.startsWith('github.com/')) {\n basename = repo.split('/')[2];\n }\n let m = basename.match('^runway-model-(.*)$');\n if (m !== null) {\n basename = m[1];\n }\n }\n\n if (this.p === undefined) {\n this.p = {};\n }\n\n if (this.p.name === undefined) {\n this.p.name = basename;\n }\n\n if (this.p['runway-label'] === undefined) {\n let m = this.p.name.match('^runway-model-(.*)$');\n if (m === null) {\n this.p['runway-label'] = this.p.name;\n } else {\n this.p['runway-label'] = m[1];\n }\n }\n\n if (this.p.models === undefined ||\n this.p.models === []) {\n console.log(`No models specified in package.json, ` +\n `guessing ${basename}.model and ${basename}.js`);\n this.p.models = [\n {\n id: basename,\n name: basename,\n spec: `${basename}.model`,\n view: `${basename}.js`,\n }\n ];\n }\n if (!_.isArray(this.p.models)) {\n // This format is deprecated. Models used to be a plain object, but\n // that doesn't provide ordering for menu items.\n this.p.models = _.toPairs(this.p.models).map(kv => {\n if (_.isString(kv[1])) {\n return {id: kv[0], alias: kv[1]};\n } else {\n kv[1].id = kv[0];\n return kv[1];\n }\n });\n }\n this.p.models.forEach(m => {\n if (m.id === undefined) {\n m.id = basename;\n }\n if (m.label === undefined) {\n m.label = m.name;\n if (m.label === undefined) {\n m.label = m.id;\n }\n }\n });\n }\n\n getModel(id) {\n let model;\n if (id === undefined) {\n model = _.first(this.p.models);\n } else {\n model = _.find(this.p.models, m => m.id === id);\n }\n if (model !== undefined &&\n model.alias !== undefined) { // permit one level of aliasing\n return _.find(this.p.models, m => m.id === model.alias);\n }\n return model;\n }\n\n getRepo() {\n if (this.repo !== undefined) {\n return this.repo;\n }\n if (this.p.repository === undefined ||\n this.p.repository.type !== 'git') {\n return undefined;\n }\n let m = this.p.repository.url.match('https://github.com/(.*)/(.*).git');\n if (m === null) {\n return undefined;\n }\n return `github.com/${m[1]}/${m[2]}`;\n }\n}\n\nclass ModelsNav {\n constructor(active) {\n this.active = active;\n this.found = false;\n this.ul = jQuery('