├── app ├── .electron │ ├── Cookies-journal │ ├── Cookies │ ├── Cache │ │ ├── data_0 │ │ ├── data_1 │ │ ├── data_2 │ │ ├── data_3 │ │ ├── index │ │ └── f_00000c │ └── GPUCache │ │ ├── data_0 │ │ ├── data_1 │ │ ├── data_2 │ │ ├── data_3 │ │ └── index ├── assets │ ├── images │ │ └── pedal.png │ ├── fonts │ │ ├── Hasklig-Light.otf │ │ ├── roboto │ │ │ ├── Roboto-Bold.eot │ │ │ ├── Roboto-Bold.ttf │ │ │ ├── Roboto-Thin.eot │ │ │ ├── Roboto-Thin.ttf │ │ │ ├── Roboto-Bold.woff │ │ │ ├── Roboto-Bold.woff2 │ │ │ ├── Roboto-Light.eot │ │ │ ├── Roboto-Light.ttf │ │ │ ├── Roboto-Light.woff │ │ │ ├── Roboto-Light.woff2 │ │ │ ├── Roboto-Medium.eot │ │ │ ├── Roboto-Medium.ttf │ │ │ ├── Roboto-Medium.woff │ │ │ ├── Roboto-Regular.eot │ │ │ ├── Roboto-Regular.ttf │ │ │ ├── Roboto-Thin.woff │ │ │ ├── Roboto-Thin.woff2 │ │ │ ├── Roboto-Medium.woff2 │ │ │ ├── Roboto-Regular.woff │ │ │ └── Roboto-Regular.woff2 │ │ ├── Raleway │ │ │ ├── Raleway-Black.ttf │ │ │ ├── Raleway-Bold.ttf │ │ │ ├── Raleway-Light.ttf │ │ │ ├── Raleway-Thin.ttf │ │ │ ├── Raleway-Italic.ttf │ │ │ ├── Raleway-Medium.ttf │ │ │ ├── Raleway-Regular.ttf │ │ │ ├── Raleway-BoldItalic.ttf │ │ │ ├── Raleway-ExtraBold.ttf │ │ │ ├── Raleway-ExtraLight.ttf │ │ │ ├── Raleway-SemiBold.ttf │ │ │ ├── Raleway-ThinItalic.ttf │ │ │ ├── Raleway-BlackItalic.ttf │ │ │ ├── Raleway-LightItalic.ttf │ │ │ ├── Raleway-MediumItalic.ttf │ │ │ ├── Raleway-ExtraBoldItalic.ttf │ │ │ ├── Raleway-SemiBoldItalic.ttf │ │ │ ├── Raleway-ExtraLightItalic.ttf │ │ │ └── OFL.txt │ │ └── Julius_Sans_One │ │ │ ├── JuliusSansOne-Regular.ttf │ │ │ └── OFL.txt │ ├── js │ │ ├── LICENSE │ │ └── dispersion.js │ └── css │ │ └── style.css ├── components │ ├── partials │ │ ├── topbar.html │ │ ├── project-add-bar.html │ │ ├── publishCard.html │ │ ├── daemon-load.html │ │ ├── settings.html │ │ └── FileHistoryPartial.html │ ├── directives │ │ ├── daemon-load-directive.js │ │ ├── FadeInDirective.js │ │ ├── topbarDirective.js │ │ ├── project-directive.js │ │ ├── publishDirective.js │ │ ├── settings-directive.js │ │ └── FileHistoryDirective.js │ ├── controllers │ │ ├── settingsController.js │ │ ├── mainController.js │ │ ├── filesController.js │ │ ├── publishController.js │ │ ├── ProjectController.js │ │ ├── mockdata.js │ │ └── FileHistoryController.js │ └── factories │ │ ├── FileHistoryFactory.js │ │ ├── ProjectService.js │ │ ├── fileFactory.js │ │ ├── diskFactory.js │ │ ├── publishService.js │ │ └── ipfsService.js ├── test │ ├── ipfsService.spec.js │ ├── ipfsservicetest.js │ ├── spectrontest.js │ └── errorlog.txt ├── bower.json ├── app.js ├── main.js ├── package.json ├── karma.conf.js └── index.html ├── todolist ├── .vscode └── settings.json ├── test.html ├── .gitignore ├── LICENSE ├── README.md └── test.css /app/.electron/Cookies-journal: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /todolist: -------------------------------------------------------------------------------- 1 | persisitpublished state on project 2 | mark on files page published with icon 3 | -------------------------------------------------------------------------------- /app/.electron/Cookies: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/Cookies -------------------------------------------------------------------------------- /app/.electron/Cache/data_0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/Cache/data_0 -------------------------------------------------------------------------------- /app/.electron/Cache/data_1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/Cache/data_1 -------------------------------------------------------------------------------- /app/.electron/Cache/data_2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/Cache/data_2 -------------------------------------------------------------------------------- /app/.electron/Cache/data_3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/Cache/data_3 -------------------------------------------------------------------------------- /app/.electron/Cache/index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/Cache/index -------------------------------------------------------------------------------- /app/assets/images/pedal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/images/pedal.png -------------------------------------------------------------------------------- /app/.electron/GPUCache/data_0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/GPUCache/data_0 -------------------------------------------------------------------------------- /app/.electron/GPUCache/data_1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/GPUCache/data_1 -------------------------------------------------------------------------------- /app/.electron/GPUCache/data_2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/GPUCache/data_2 -------------------------------------------------------------------------------- /app/.electron/GPUCache/data_3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/GPUCache/data_3 -------------------------------------------------------------------------------- /app/.electron/GPUCache/index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/.electron/GPUCache/index -------------------------------------------------------------------------------- /app/assets/fonts/Hasklig-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Hasklig-Light.otf -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "editor.fontSize": 15, 4 | } -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Bold.eot -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Bold.ttf -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Thin.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Thin.eot -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Thin.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-Black.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-Bold.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-Light.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-Thin.ttf -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Bold.woff -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Bold.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Light.eot -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Light.ttf -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Light.woff -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Light.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Medium.eot -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Medium.ttf -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Medium.woff -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Regular.eot -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Regular.ttf -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Thin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Thin.woff -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Thin.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-Italic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-Medium.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-Regular.ttf -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Medium.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Regular.woff -------------------------------------------------------------------------------- /app/assets/fonts/roboto/Roboto-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/roboto/Roboto-Regular.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-BoldItalic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-ExtraBold.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-ExtraLight.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-SemiBold.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-ThinItalic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-BlackItalic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-LightItalic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-MediumItalic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/Raleway-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Raleway/Raleway-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Julius_Sans_One/JuliusSansOne-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dispersionjs/Dispersion/HEAD/app/assets/fonts/Julius_Sans_One/JuliusSansOne-Regular.ttf -------------------------------------------------------------------------------- /app/components/partials/topbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/components/directives/daemon-load-directive.js: -------------------------------------------------------------------------------- 1 | angular.module('daemonDirective', []) 2 | 3 | .directive('daemonLoad', function() { 4 | return { 5 | restrict: 'E', 6 | transclude: true, 7 | scope: false, 8 | templateUrl: 'components/partials/daemon-load.html', 9 | replace: true 10 | }; 11 | }) -------------------------------------------------------------------------------- /app/components/directives/FadeInDirective.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('FadeInEffect', []) 3 | .directive('fadeInEffect', function () { 4 | return { 5 | restrict: 'A', 6 | link: function ($scope, element) { 7 | var duration = 800; 8 | $(element).fadeIn(duration); 9 | } 10 | }; 11 | }) 12 | 13 | -------------------------------------------------------------------------------- /app/components/directives/topbarDirective.js: -------------------------------------------------------------------------------- 1 | angular.module('topbarDirective', []) 2 | 3 | .directive('topBar', function() { 4 | return { 5 | restrict: 'E', 6 | transclude: true, 7 | controller: 'FilesController', 8 | scope: false, 9 | templateUrl: 'components/partials/topbar.html', 10 | replace: true 11 | }; 12 | }) 13 | -------------------------------------------------------------------------------- /app/test/ipfsService.spec.js: -------------------------------------------------------------------------------- 1 | 2 | describe('IpfsService', function () { 3 | var ipfsService; 4 | beforeEach(angular.mock.module('ipfsService')); 5 | 6 | beforeEach(inject(function (_ipfsService_) { 7 | ipfsService = _ipfsService_; 8 | })); 9 | 10 | it('should be', function () { 11 | expect(ipfsService).to.be.a('Object'); 12 | }); 13 | 14 | }) -------------------------------------------------------------------------------- /app/components/directives/project-directive.js: -------------------------------------------------------------------------------- 1 | angular.module('projectDirective', []) 2 | 3 | .directive('projectAddBar', function () { 4 | return { 5 | restrict: 'E', 6 | transclude: true, 7 | controller: 'PublishController', 8 | controllerAs: 'pubCtrl', 9 | 10 | templateUrl: 'components/partials/project-add-bar.html', 11 | replace: true 12 | } 13 | }) -------------------------------------------------------------------------------- /app/components/directives/publishDirective.js: -------------------------------------------------------------------------------- 1 | angular.module('publishDirective', ['PublishController']) 2 | 3 | 4 | .directive('publishCard', function () { 5 | return { 6 | restrict: 'E', 7 | transclude: true, 8 | controller: 'PublishController', 9 | controllerAs: 'pubCtrl', 10 | scope: false, 11 | templateUrl: 'components/partials/publishCard.html', 12 | replace: true 13 | }; 14 | }) -------------------------------------------------------------------------------- /app/test/ipfsservicetest.js: -------------------------------------------------------------------------------- 1 | var benv = require('benv'); 2 | 3 | 4 | 5 | describe('calc module', function () { 6 | beforeEach(function setupEnvironment(done) { 7 | benv.setup(function () { 8 | benv.expose({ 9 | angular: benv.require('../node_modules/angular/angular.js', 'angular') 10 | }); 11 | done(); 12 | }); 13 | }); 14 | // more stuff will go here 15 | afterEach(function destroySyntheticBrowser() { 16 | console.log("distroy") 17 | benv.teardown(true); 18 | }); 19 | }); 20 | 21 | console.log("In IPFS test!") -------------------------------------------------------------------------------- /app/components/directives/settings-directive.js: -------------------------------------------------------------------------------- 1 | angular.module('settingsDirective', []) 2 | 3 | .directive('settings', function () { 4 | return { 5 | restrict: 'E', 6 | transclude: true, 7 | controller: 'SettingsController', 8 | controllerAs: 'settingsCtrl', 9 | link: function (scope, element, attribute) { 10 | $('.collapsible').collapsible({ accordion: false }); 11 | // A setting that changes the collapsible behavior to expandable instead of the default accordion style 12 | }, 13 | scope: false, 14 | templateUrl: 'components/partials/settings.html', 15 | replace: true 16 | }; 17 | }) -------------------------------------------------------------------------------- /app/components/partials/project-add-bar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/components/directives/FileHistoryDirective.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('FileHistoryDirective', ['FileHistoryController']) 3 | 4 | .directive('fileHistory', function () { 5 | return { 6 | restrict: 'E', 7 | transclude: true, 8 | scope: { 9 | index: '@', 10 | filename: '@', 11 | projectname: '@', 12 | projectobject: '@', 13 | mode: '@' 14 | }, 15 | // link: function (scope) { 16 | // scope.updateEditorContent(); 17 | // scope.recordIndex(); 18 | // scope.toggleShowInfo(); 19 | // }, 20 | controller: 'FileHistoryController', 21 | templateUrl: 'components/partials/FileHistoryPartial.html', 22 | replace: true 23 | }; 24 | }) -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dispersion", 3 | "description": "Electron based interface for ipfs", 4 | "main": "main.js", 5 | "authors": [ 6 | "Dispersion" 7 | ], 8 | "license": "MIT", 9 | "keywords": [ 10 | "electron", 11 | "ipfs" 12 | ], 13 | "homepage": "https://github.com/waggertron/Dispersion", 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "angular": "^1.5.8", 23 | "jquery": "^3.1.1", 24 | "angular-ui-ace": "^0.2.3", 25 | "materialize": "^0.97.7", 26 | "hammerjs": "^2.0.8", 27 | "angular-materialize": "^0.2.1", 28 | "angular-animate": "^1.5.8", 29 | "angular-aria": "^1.5.8", 30 | "angular-messages": "^1.5.8", 31 | "material-design-icons": "^3.0.1" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/components/controllers/settingsController.js: -------------------------------------------------------------------------------- 1 | angular 2 | .module('SettingsController', []) 3 | //passing $scope and UserFactory as dependencies to controller 4 | 5 | .controller('SettingsController', ['IpfsService', SettingsController]); 6 | function SettingsController(IpfsService) { 7 | const self = this; 8 | self.activated = true; 9 | self.loadConfig = function () { 10 | IpfsService.getSettingsInfo().then(function (data) { 11 | self.peerID = data[0] 12 | self.bootStrapList = data[1] 13 | self.multiAddr = data[2] 14 | self.ipfsVersion = data[3] 15 | }) 16 | 17 | } 18 | self.hashPeers = false; 19 | self.checkHealth = function (hash) { 20 | IpfsService.findProviders(hash).then(function (data) { 21 | console.log('theData', data) 22 | self.health = data.length; 23 | self.hashPeers = true; 24 | }) 25 | } 26 | 27 | self.addPeer = function (address) { 28 | IpfsService.addPeer(address).then(function (data) { 29 | }); 30 | } 31 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | bower_components 33 | 34 | 35 | # Optional npm cache directory 36 | .npm 37 | 38 | # Optional REPL history 39 | .node_repl_history 40 | 41 | #files saved locally from electron apllication by user. 42 | savedfiles 43 | projectFolder 44 | 45 | #Apple files 46 | .DS_Store 47 | 48 | #local hash storage 49 | *data.json 50 | 51 | #from build 52 | app/appe-darwin-x64/ 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/test/spectrontest.js: -------------------------------------------------------------------------------- 1 | var Application = require('spectron').Application; 2 | var assert = require('assert'); 3 | var path = require("path"); 4 | var appPath = path.resolve(__dirname, '../'); //require the whole thing 5 | var electronPath = path.resolve(__dirname, '../node_modules/.bin/electron'); 6 | var expect = require('chai').expect; 7 | var chai = require('chai'); 8 | var chaiAsPromised = require('chai-as-promised'); 9 | //require('fluentnode') 10 | //var helpers = require('./global-setup') 11 | 12 | 13 | describe('application launch', function () { 14 | this.timeout(10000) 15 | 16 | beforeEach(function () { 17 | this.app = new Application({ 18 | path: electronPath, 19 | args: [appPath] 20 | }) 21 | return this.app.start() 22 | }) 23 | 24 | afterEach(function () { 25 | if (this.app && this.app.isRunning()) { 26 | return this.app.stop() 27 | } 28 | }) 29 | 30 | it('shows an initial window', function () { 31 | return this.app.client.getWindowCount().then(function (count) { 32 | assert.equal(count, 1) 33 | }) 34 | }) 35 | }) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Dispersionjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/assets/js/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2016 Materialize 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | const childProcess = require('child_process'); 2 | const exec = childProcess.exec; 3 | const spawn = childProcess.spawn; 4 | const storage = require('electron-json-storage'); 5 | const fs = require('fs'); 6 | const readChunk = require('read-chunk'); // npm install read-chunk 7 | const fileType = require('file-type'); 8 | const https = require('https'); 9 | const request = require('request'); 10 | const username = require('username'); 11 | const fse = require('fs-extra'); 12 | const path = require('path'); 13 | const {dialog} = require('electron').remote; 14 | 15 | angular.module('myApp', [ 16 | 'topbarDirective', 17 | 'publishDirective', 18 | 'daemonDirective', 19 | 'settingsDirective', 20 | 'FileFactory', 21 | 'PublishService', 22 | 'MainController', 23 | 'DiskFactory', 24 | 'IpfsService', 25 | 'FilesController', 26 | 'PublishController', 27 | 'SettingsController', 28 | 'ui.ace', 29 | 'ProjectService', 30 | 'ProjectController', 31 | 'FileHistoryDirective', 32 | 'FadeInEffect', 33 | 'FileHistoryController', 34 | 'FileHistoryFactory', 35 | 'ui.materialize' 36 | ]) 37 | .config(['$sceProvider', function ($sceProvider) { 38 | $sceProvider.enabled(false); 39 | }]) 40 | .controller('ViewController', [viewController]) 41 | function viewController() { 42 | const self = this; 43 | self.view = 'loading'; 44 | self.changeView = function (view) { 45 | self.view = view; 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /app/components/partials/publishCard.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |
6 |
7 | {{projectName}} 8 |

Date added: {{value[0].date}}

9 |
10 |
11 | mode_edit 12 | 13 | 14 |
done_allcurrently published
15 | add 16 |
17 |
18 |
19 |
20 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## Dispersion 5 | 6 | A desktop application that allows users to save files on their IPFS local node. 7 | 8 | ##Getting Started 9 | 10 | Please install IPFS before using Dispersion. You can download IPFS from the following link: https://ipfs.io/docs/install/ 11 | 12 | 13 | Installation 14 | ------------ 15 | 16 | ``` 17 | git clone https://github.com/Dispersionjs/Dispersion.git 18 | cd Dispersion/app 19 | npm run install:dispersion 20 | npm start 21 | ``` 22 | 23 | 24 | ## Dashboard Page 25 | 26 | This page is used to view and add files or entire applications to IPFS. 27 | These files can then be staged for publish, downloaded or deleted from Dispersion. 28 | 29 | ## Publish 30 | 31 | Once a file is staged it appears on the publish page, where it can then be publish to your ipfs node's fixed IPNS. 32 | Selecting the + icon will publish to your IPNS. This can be mapped to a specific domain name. 33 | 34 | When selecting the pencil icon, the user can edit and save individual project files as well as manage a complete version history. 35 | 36 | 37 | ## Settings 38 | 39 | The settings can be accessed by clicking the gear icon in the top right corner of the application. 40 | 41 | The settings displays the users peerID, and MultAddr address(used to allow peers to add you to their trusted bootstrap list). It also allows you to add peers to your list as well as check the health of any content on ipfs, by displaying the number of nodes that have pinned the content. 42 | -------------------------------------------------------------------------------- /app/test/errorlog.txt: -------------------------------------------------------------------------------- 1 | lookup error: failed to bind to any unicat udp port 2 | on adding large folder (1 gb) worked on second retry, should attempt to readd after wait period, alert user 3 | ll data from LOCAL STORAGE [Object, Object] 4 | >>>>>>ipfsService.js:22 12:12:31.116 ERROR commands/h: err: multipart: unexpected line in Next(): "(\x82h\xa0Q\xefh,\xaev\x1c\xe6\x87Ē~n\u007f8=9\xc7\r\xc1\xbc\xf1k\xec\xfa?V,\x14\xacs\t\xe3.\x10*\xb9\x94\x02O?\x12w\x85\xdco\u05fb\xc9{J\xebʽg\xf5=5u\xe64>z/\xf9m\xc3A\x16\xaaٛ\xd9\xcbqQ76ɴ\x9a7\xad<\xdb\x16\xa0u\xc1N%Źw4@L\x9fu\xb1.z\x8e\xc0\xa9`\"\xd5%d\xb1*\xd2\xfec\xed\xe0W\xea,\xabQ\x98\x8c\x9f\x1fP\x0eΞս\xb5\x9c \xf7\xf1)ڗ\xf8\x81,Rro\xb1l\xc4L\x9cE\x06\f\xe3bմ\x85\x06̸u\xbf\x86\xa3'\xd4C\xe6\xf3?8\xee-\xa9\xcf#\x10\xe4\x10?Q\x90\xac\xec\xe0e\x155\xc0\xa8\xdc\xf4.Y1\x9d\xaf\xfd\xb0E\x96\xcb\xc9<\xac\b\x93\"\xe4\xdd\x1e\x17\x05=\x80\aH[\xe3\xcdb\x84Q\x8c\x9b\x8b\x1dzrOW\xc4\x00m|\x98\x80\xa0\x88\x8d-\xc63\xea\xe6\xe95\xb0\x18\x11\x99\xe9\x1eXr\xbc\xad\xe2\x84\xdbf\x99u\xb0\x90\xb2Aw\x89\xe1+Lv\x97`\xfe\xff\xadk\xb2\x1f\x87G\vg(\x11]8\xecp\xebn\x0f\xd8\u007f\x9c\xe3eCx\xbb\xf4]\x88\xf6)\xce;\xe1\u007f\xdc\xdcG\x97\x19\xb9Է\xad'\x9e\xc0V\xee~4\xbe=0GӒM\uf680\xe9\xb8\\\xab\xa9\xd9 b\x8f$\xa9\x14\xac[!\xc8\fX\xd5\xf7\f\x1a\x1f\x13\xf4\v=\xc5O\x89m\xf4ƌ\xd36\xe3h\x8f\x81\xec\x9cl\x90\xd4\x03 \"K\xa8-L\xbb\x89\xa7\x9f\xfb\x1b۹e\x16\x99\xf0\x19\xb3\xa8\x04\x11\xfa7Sa\x92\xa3u\xa2n\xe1\x0em\xbb\x8ck2\xb1\v\xf9\xdd\xd3\xe3\xc6x2\xbc\xf8I\x1d\xdc\b\x9b\x10\n" handler.go:288 5 | ipfsService.js:22 12:12:34.765 ERROR  mdns: mdns lookup error: failed to bind to any unicast udp port mdns.go:131 -------------------------------------------------------------------------------- /app/components/controllers/mainController.js: -------------------------------------------------------------------------------- 1 | 2 | angular 3 | .module('MainController', []) 4 | //passing $scope and UserFactory as dependencies to controller 5 | .controller('MainController', ['$scope', 'PublishService', 'FileFactory', 'DiskFactory', 'IpfsService', '$timeout', 'FileHistoryFactory', mainController]); 6 | 7 | function mainController($scope, PublishService, FileFactory, DiskFactory, IpfsService, $timeout, FileHistoryFactory) { 8 | //load publish object when switching to publish page 9 | const self = this; 10 | let secondAttempt = false; 11 | self.startApp = () => { 12 | IpfsService.init() 13 | .then((daemonStatus) => { 14 | self.daemonStatus = daemonStatus; 15 | return FileFactory.init() 16 | }) 17 | .then(DiskFactory.init) 18 | .then(PublishService.init) 19 | .then(FileHistoryFactory.init) 20 | .then(() => { 21 | $timeout(() => { 22 | self.view = 'files'; 23 | }, 500); 24 | }) 25 | .catch((error) => { 26 | // $timeout(() => { 27 | // if (error && self.view !== 'files' && !secondAttempt) { 28 | // secondAttempt = true; 29 | // console.log('error in mainController.startApp, will attempt retry'); 30 | // } else { 31 | // console.log('unable to load') 32 | // //add error view 33 | // } 34 | // }, 5000); 35 | console.error(error); 36 | 37 | }); 38 | } 39 | // PublishService.init().then( 40 | 41 | // ) 42 | // IpfsService.init().then((data) => { 43 | 44 | // console.log('daemondata', data) 45 | // self.daemonStatus = data; 46 | // }); 47 | // DiskFactory.init(); 48 | // FileFactory.init(); 49 | // self.view = 'files'; 50 | self.startApp(); 51 | } 52 | 53 | -------------------------------------------------------------------------------- /test.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | ul li { 4 | cursor: pointer; 5 | -webkit-transition: padding .05s linear; 6 | transition: padding .05s linear; 7 | } 8 | ul li.drop { 9 | position: relative; 10 | } 11 | ul > li { 12 | display: inline-block; 13 | } 14 | ul li a { 15 | line-height: 80px; 16 | padding: 0 20px; 17 | height: 80px; 18 | color: #777; 19 | -webkit-transition: all .3s ease-out; 20 | transition: all .3s ease-out; 21 | } 22 | ul li a:hover { 23 | color: #eee; 24 | } 25 | 26 | .dropOut .triangle { 27 | width: 0; 28 | height: 0; 29 | position: absolute; 30 | border-left: 8px solid transparent; 31 | border-right: 8px solid transparent; 32 | border-bottom: 8px solid #000; 33 | top: -8px; 34 | left: 50%; 35 | margin-left: -8px; 36 | } 37 | .dropdownContain { 38 | width: 160px; 39 | position: absolute; 40 | z-index: 2; 41 | left: 50%; 42 | margin-left: -80px; /* half of width */ 43 | top: -400px; 44 | } 45 | .dropOut { 46 | width: 160px; 47 | background: white; 48 | float: left; 49 | position: relative; 50 | margin-top: 0px; 51 | opacity: 0; 52 | border-radius: 4px; 53 | box-shadow: 0 1px 6px rgba(37, 126, 176, 0.15); 54 | -webkit-transition: all .3s ease-out; 55 | transition: all .3s ease-out; 56 | } 57 | 58 | .dropOut ul { 59 | float: left; 60 | padding: 10px 0; 61 | } 62 | .dropOut ul li { 63 | text-align: left; 64 | float: left; 65 | width: 125px; 66 | padding: 12px 0 10px 15px; 67 | margin: 0px 10px; 68 | color: #777; 69 | -webkit-border-radius: 4px; 70 | border-radius: 4px; 71 | -webkit-transition: background .3s ease-out; 72 | transition: background .3s ease-out; 73 | } 74 | 75 | .dropOut ul .mat:hover { 76 | background: #f6f6f6; 77 | } 78 | 79 | /*ul li:hover a { color: rgb(74, 122, 194); } 80 | ul li:hover .dropdownContain { top: 65px; } 81 | ul li:hover .underline { border-bottom-color: #777; }*/ 82 | ul li:hover .dropOut { opacity: 1; margin-top: 8px; } 83 | -------------------------------------------------------------------------------- /app/components/controllers/filesController.js: -------------------------------------------------------------------------------- 1 | angular 2 | .module('FilesController', []) 3 | //passing $scope and UserFactory as dependencies to controller 4 | .controller('FilesController', ['FileFactory', 'PublishService', 'DiskFactory', 'IpfsService', 'FileHistoryFactory', FilesController]); 5 | 6 | function FilesController(FileFactory, PublishService, DiskFactory, IpfsService, FileHistoryFactory) { 7 | 8 | const self = this; 9 | self.sortBy = 'time'; 10 | //get Username of local user. Used for file saving 11 | username().then(username => { 12 | self.username = username; 13 | }); 14 | self.files = FileFactory.data; 15 | self.getFileData = FileFactory.getFileData 16 | //shows additional info about pinned file 17 | self.showInfo = function (index) { 18 | $(`#sel-option${index}`).show(); 19 | } 20 | 21 | self.addHash = FileFactory.addHash; 22 | self.formatDate = function (date) { 23 | let dateOut = new Date(date); 24 | return dateOut; 25 | }; 26 | 27 | self.deleteHash = function (hash, index) { 28 | Materialize.toast("File Deleted!", 2000); 29 | IpfsService.unPin(hash); 30 | FileFactory.removeFile(index); 31 | } 32 | 33 | self.addToPublish = function (value) { 34 | Materialize.toast("Staged for Publish!", 2000); 35 | console.log('in add to publish, value: ', value); 36 | DiskFactory.addProject(value.pathToFile); 37 | PublishService.add({ 38 | [value.file]: [{ 39 | 'date': value.date, 40 | 'hash': value.hash, 41 | 'publish': true, 42 | 'changed': null, 43 | 'url': value.url, 44 | 'files': value.files 45 | }] 46 | }); 47 | //initial add of all files to FileVersionHistory 48 | FileHistoryFactory.initialAdd(value.date, value.url, value.hash, value.files, value.file); 49 | 50 | // date, url, hash, filesArray, projectName 51 | 52 | } 53 | 54 | self.getIframeUrl = function (fileObj, fileName) { 55 | return fileObj + fileName; 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /app/main.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron') 2 | 3 | // Module to control application life. 4 | const app = electron.app 5 | // Module to create native browser window. 6 | const BrowserWindow = electron.BrowserWindow 7 | 8 | 9 | 10 | // Keep a global reference of the window object, if you don't, the window will 11 | // be closed automatically when the JavaScript object is garbage collected. 12 | let mainWindow 13 | 14 | function createWindow() { 15 | // Create the browser window. 16 | mainWindow = new BrowserWindow({ 17 | width: 1200, 18 | height: 800 19 | }) 20 | 21 | // and load the index.html of the app. 22 | mainWindow.loadURL(`file://${__dirname}/index.html`) 23 | 24 | // Open the DevTools. 25 | // mainWindow.webContents.openDevTools() 26 | // Emitted when the window is closed. 27 | mainWindow.on('closed', function () { 28 | // Dereference the window object, usually you would store windows 29 | // in an array if your app supports multi windows, this is the time 30 | // when you should delete the corresponding element. 31 | mainWindow = null 32 | }) 33 | } 34 | // app.clearCache(callback) 35 | 36 | 37 | // This method will be called when Electron has finished 38 | // initialization and is ready to create browser windows. 39 | // Some APIs can only be used after this event occurs. 40 | app.on('ready', createWindow) 41 | console.log(app.getPath('userData')) 42 | // app.getPath(('userData') + '/Cache') 43 | // Quit when all windows are closed. 44 | app.on('window-all-closed', function () { 45 | // On OS X it is common for applications and their menu bar 46 | // to stay active until the user quits explicitly with Cmd + Q 47 | if (process.platform !== 'darwin') { 48 | app.quit() 49 | } 50 | }) 51 | 52 | app.on('activate', function () { 53 | // On OS X it's common to re-create a window in the app when the 54 | // dock icon is clicked and there are no other windows open. 55 | if (mainWindow === null) { 56 | createWindow() 57 | } 58 | }) 59 | -------------------------------------------------------------------------------- /app/components/controllers/publishController.js: -------------------------------------------------------------------------------- 1 | angular 2 | .module('PublishController', []) 3 | //passing $scope and UserFactory as dependencies to controller 4 | 5 | .controller('PublishController', ['PublishService', 'IpfsService', 'DiskFactory', 'ProjectService', PublishController]); 6 | 7 | function PublishController(PublishService, IpfsService, DiskFactory, ProjectService) { 8 | // PublishService.init().then(console.log('init called in publish controller')) 9 | const self = this; 10 | self.data = PublishService.data; 11 | self.currentlyPublished = PublishService.currentlyPublished; 12 | self.setAsPublished = PublishService.setPublished; 13 | self.isPublished = function (projectName) { 14 | return self.currentlyPublished() === projectName; 15 | } 16 | self.setProjectView = function (projectName) { 17 | console.log('setting project view for: ', projectName) 18 | ProjectService.changeSelectedProject(projectName) 19 | } 20 | 21 | // self.addPubDataOnEdit = function (pubObj, projectName) { 22 | // console.log('when clicked edit, adding this to published:', pubObj) 23 | // pubObj[0].publish = true; 24 | // PublishService.unshiftForEditFix(pubObj[0], projectName) 25 | // ProjectService.changeSelectedProject(projectName) 26 | // } 27 | 28 | 29 | 30 | self.publishToIpfs = function (value, name) { 31 | console.log('value, name in publish to ipfs called from publish controller', value, name) 32 | // self.publishedProjectCard = name; 33 | self.setAsPublished(name); 34 | ProjectService.changeSelectedProject(name); 35 | IpfsService.publish(value, name) 36 | // PublishService.add(value, true, name); 37 | } 38 | 39 | // self.activeButton = function (value) { 40 | // console.log('value passed to active button', value); 41 | // console.log('self.data: ', self.data); 42 | // self.currentlyPublished = value; 43 | // for (let key in self.data) { 44 | // if (self.data[key].toggled && self.data[key] !== value) { 45 | // self.data[key].toggled = false 46 | // } 47 | // } 48 | // value.toggled = !value.toggled; 49 | // } 50 | // self.addProject = DiskFactory.addProject; 51 | // self.overwrite = DiskFactory.overwrite; 52 | // self.delete = DiskFactory.delete; 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /app/components/factories/FileHistoryFactory.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | angular.module('FileHistoryFactory', []) 8 | .factory('FileHistoryFactory', ['ProjectService', '$q', 'IpfsService', '$timeout', fileHistoryFactory]) 9 | 10 | function fileHistoryFactory(ProjectService, $q, IpfsService, $timeout) { 11 | var historyData = {} 12 | function init() { 13 | return $q((resolve, reject) => { 14 | storage.get('fileVersions', (error, data) => { 15 | if (error) reject(error) 16 | console.log('file version data from local storage in init', data); 17 | for (let key in data) { 18 | historyData[key] = data[key] 19 | } 20 | resolve(data) 21 | // if (error) reject(error) 22 | //update history array 23 | 24 | }) 25 | 26 | }); 27 | } 28 | function getFileHistory() { 29 | return historyData 30 | } 31 | 32 | function updateLocalStorage() { 33 | storage.set('fileVersions', historyData) 34 | } 35 | 36 | 37 | function addFileVersion(fileVersionObj, projectName) { 38 | console.log('addFileVersion called in fileHistoryFactory, fileVersionObj, projectname: \n', fileVersionObj, projectName); 39 | historyData[projectName].push(fileVersionObj); 40 | $timeout((updateLocalStorage), 5000); 41 | } 42 | function addInitialFileVersionOnPublish(date, url, hash, filesArray, projectName) { 43 | console.log('addintila file version on publish, passed in args: ', ...arguments) 44 | if (!historyData[projectName]) { 45 | historyData[projectName] = []; 46 | filesArray.forEach((filename, index) => { 47 | historyData[projectName].push({ 48 | date: date, 49 | url: url + filename, 50 | hash: hash, 51 | file: filename 52 | }) 53 | console.log(`item #${index} added: `, { 54 | date: date, 55 | url: url + filename, 56 | hash: hash, 57 | file: filename 58 | }); 59 | }) 60 | updateLocalStorage() 61 | } 62 | // historyData[projectName].push(fileVersionObj); 63 | // $timeout((updateLocalStorage), 2000); 64 | } 65 | 66 | return { 67 | fileHistory: historyData, 68 | getFileHistory: getFileHistory, 69 | add: addFileVersion, 70 | init: init, 71 | initialAdd: addInitialFileVersionOnPublish 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /app/components/factories/ProjectService.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('ProjectService', []) 3 | .service('ProjectService', ['$http', '$q', 'PublishService', projectService]); 4 | 5 | 6 | function projectService($http, $q, PublishService) { 7 | /**returns length -1 of currently selected project data array */ 8 | const self = this; 9 | self.init = () => { 10 | $q((resolve, reject) => { 11 | storage.get('currentlyPublished', (error, data) => { 12 | if (error) reject(error); 13 | resolve(data); 14 | }) 15 | }) 16 | } 17 | // self.publishedArrayLength = () => self.publishedProjectVersions().length - 1; 18 | /** returns all published event objects from the projectArray history */ 19 | self.publishedProjectVersions = () => { 20 | if (!PublishService.data || !PublishService.data[self.selected]) return []; 21 | return PublishService.data[self.selected].filter((pubObj) => { 22 | return pubObj.publish === true; 23 | }) 24 | } 25 | 26 | /** returns the url of the currently selected project version */ 27 | self.currentUrl = (file) => { 28 | if (!file) { 29 | return self.selectedVersion().url; 30 | } else { 31 | return self.selectedVersion().url 32 | } 33 | } 34 | 35 | 36 | //should refactor self one \/ 37 | /** returns a string that was the last changed file of the publish event */ 38 | // self.currentFile = () => self.selectedVersion.changed; 39 | // self.currentFileType = () => self.currentFile(); 40 | 41 | self.changeSelectedVersion = (index) => { 42 | //will need to change to account for unpublished projects 43 | // 44 | self.currentIndex = index; 45 | // self.selectedVersion = self.publishedProjectVersions.length === 1 ? self.publishedProjectVersions()[self.publishedArrayLength() - index] : null; 46 | 47 | } 48 | 49 | self.getContentUrl = () => { 50 | return self.currentUrl() + self.currentFile(); 51 | } 52 | self.changeSelectedProject = (projectName) => { self.selected = projectName } 53 | self.currentIndex = 0; 54 | self.selectedVersionFilesList = () => self.selectedVersion().files; 55 | self.selected = ''; 56 | self.currentProject = () => self.selected; 57 | self.selectedVersion = () => { 58 | if (!self.publishedProjectVersions()) return []; 59 | return self.publishedProjectVersions()[self.currentIndex]; 60 | } 61 | } -------------------------------------------------------------------------------- /app/components/partials/daemon-load.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 13 | 14 | 19 | 23 | 24 |
25 |

Spinning Up Local Daemon

26 |
27 |
-------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dispersion", 3 | "version": "1.0.0", 4 | "description": "Electron based interface for ipfs", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "mocha test", 8 | "start": "electron .", 9 | "clean": "rm -rf ./dist", 10 | "install:dispersion": "npm install && ./node_modules/bower/bin/bower install", 11 | "clean:osx": "rm -rf ./dist/osx", 12 | "pack": "npm run clean:osx && electron-packager . \"EA Todo\" --out=dist/osx --platform=darwin --arch=x64 --version=0.36.2 --icon=assets/osx/logo.icns --ignore=dist --ignore=assets --ignore=builder.json --ignore=bower.json --ignore=README.md --ignore=.gitignore --ignore=preview.png", 13 | "build": "npm run pack:osx && electron-builder \"dist/osx/EA Todo-darwin-x64/EA Todo.app\" --platform=osx --out=\"dist/osx\" --config=builder.json" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/dispersionjs/Dispersion.git" 18 | }, 19 | "keywords": [ 20 | "electron", 21 | "ipfs", 22 | "ipns", 23 | "dispersion", 24 | "webhosting", 25 | "p2p", 26 | "peer-to-peer", 27 | "distributed-web", 28 | "dag", 29 | "dht" 30 | ], 31 | "author": "Dispersion", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/dispersionjs/Dispersion/issues" 35 | }, 36 | "homepage": "http://dispersion.io", 37 | "dependencies": { 38 | "angular": "^1.5.8", 39 | "dialog": "^0.2.0", 40 | "electron": "^1.4.2", 41 | "electron-builder": "^7.11.4", 42 | "electron-json-storage": "^2.0.0", 43 | "electron-packager": "^8.1.0", 44 | "file-type": "^3.8.0", 45 | "fs": "0.0.1-security", 46 | "fs-extra": "^0.30.0", 47 | "hammerjs": "^2.0.8", 48 | "https": "^1.0.0", 49 | "jquery": "^3.1.1", 50 | "mime": "^1.3.4", 51 | "read-chunk": "^2.0.0", 52 | "remote": "^0.2.6", 53 | "request": "^2.75.0", 54 | "username": "^2.2.2" 55 | }, 56 | "devDependencies": { 57 | "angular-mocks": "^1.5.8", 58 | "benv": "^3.1.0", 59 | "chai": "^3.5.0", 60 | "chai-as-promised": "^6.0.0", 61 | "describe-it": "^1.7.0", 62 | "electron-mocha": "^3.1.1", 63 | "eslint": "^3.9.0", 64 | "eslint-config-airbnb": "^12.0.0", 65 | "eslint-plugin-react": "^6.4.1", 66 | "expect.js": "^0.3.1", 67 | "jasmine-core": "^2.5.2", 68 | "karma": "^1.3.0", 69 | "karma-chrome-launcher": "^2.0.0", 70 | "karma-electron": "^5.1.1", 71 | "karma-jasmine": "^1.0.2", 72 | "karma-mocha": "^1.2.0", 73 | "karma-phantomjs-launcher": "^1.0.2", 74 | "spectron": "^3.4.0" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Fri Oct 21 2016 11:40:19 GMT-0700 (PDT) 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: ['jasmine'], 14 | 15 | 16 | // list of files / patterns to load in the browser 17 | files: [ 18 | './node_modules/angular/angular.js', 19 | './node_modules/angular-mocks/angular-mocks.js', 20 | './components/factories/ipfsService.js', 21 | './app.js', 22 | 'test/ipfsService.spec.js' 23 | ], 24 | 25 | 26 | // list of files to exclude 27 | exclude: [ 28 | ], 29 | 30 | 31 | // preprocess matching files before serving them to the browser 32 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 33 | preprocessors: { 34 | }, 35 | 36 | 37 | // test results reporter to use 38 | // possible values: 'dots', 'progress' 39 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 40 | reporters: ['progress'], 41 | 42 | 43 | // web server port 44 | port: 9876, 45 | 46 | 47 | // enable / disable colors in the output (reporters and logs) 48 | colors: true, 49 | 50 | 51 | // level of logging 52 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 53 | logLevel: config.LOG_INFO, 54 | 55 | 56 | // enable / disable watching file and executing tests whenever any file changes 57 | autoWatch: true, 58 | 59 | // start these browsers 60 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 61 | // Inside `karma.conf.js` 62 | browsers: ['Electron'], 63 | 64 | // If you would like Node.js integration support (e.g. `require`) 65 | // then, you must include this in `preprocessors` and `client` 66 | // DEV: preprocessors is for backfilling `__filename` and local `require` paths 67 | preprocessors: { 68 | '**/*.js': ['electron'] 69 | }, 70 | // DEV: `useIframe: false` is for launching a new window instead of using an iframe 71 | // In Electron, iframes don't get `nodeIntegration` priveleges yet windows do 72 | client: { 73 | useIframe: false 74 | }, 75 | 76 | // Continuous Integration mode 77 | // if true, Karma captures browsers, runs the tests and exits 78 | singleRun: false, 79 | 80 | // Concurrency level 81 | // how many browser should be started simultaneous 82 | concurrency: Infinity 83 | }) 84 | } 85 | -------------------------------------------------------------------------------- /app/components/factories/fileFactory.js: -------------------------------------------------------------------------------- 1 | var module = angular 2 | .module('FileFactory', []) 3 | 4 | module.service('FileFactory', ['$q', 'IpfsService', fileFactory]); 5 | 6 | function fileFactory($q, IpfsService) { 7 | let fileData = []; 8 | 9 | function addToFileData(hashObj) { 10 | hashObj.fileType = testFileType(hashObj); 11 | fileData.push(hashObj); 12 | storage.set('files', fileData, (error) => { 13 | if (error) { 14 | console.log('error in addFile to data in file Factory, the error is: \n'); 15 | console.error(error); 16 | } 17 | }) 18 | } 19 | 20 | function removeFile(index) { 21 | fileData.splice(index,1); 22 | storage.set('files', fileData, (error) => { 23 | if (error) { 24 | console.log('error in addFile to data in file Factory, the error is: \n'); 25 | console.error(error); 26 | } 27 | }) 28 | } 29 | 30 | 31 | function addHash() { 32 | dialog.showOpenDialog({ properties: ['openFile', 'openDirectory', 'multiSelections'] }, function (selected) { 33 | if (selected) { 34 | IpfsService.addFile(selected[0]).then((addedHashObject) => { 35 | addedHashObject.pathToFile = selected[0]; 36 | console.log('path on obj', addedHashObject.pathToFile); 37 | addToFileData(addedHashObject); 38 | }); 39 | } 40 | }); 41 | } 42 | 43 | function init() { 44 | return $q((resolve, reject) => { 45 | storage.get('files', (error, data) => { 46 | console.log('files key in local storage', data) 47 | if (error) { 48 | console.error(error) 49 | reject() 50 | } else { 51 | Object.assign(fileData, data); 52 | console.log('files loaded from storage: \n', data) 53 | resolve(fileData); 54 | } 55 | }) 56 | }) 57 | } 58 | function testFileType(item) { 59 | let fileName = item.file 60 | if (fileName.includes('.jpg') || fileName.includes('.png') || fileName.includes('.JPG') || fileName.includes('.PNG') || fileName.includes('.jpeg')) { 61 | return 'image'; 62 | } else if (!fileName.includes('.')) { 63 | return 'folder'; 64 | } else if (fileName.includes('.xl')) { 65 | return 'excel'; 66 | } else if (fileName.includes('.pdf') || fileName.includes('.txt') || fileName.includes('.doc')) { 67 | return 'doc'; 68 | } else { 69 | return 'other'; 70 | } 71 | } 72 | 73 | function getFileData() { 74 | return fileData; 75 | } 76 | return { 77 | removeFile: removeFile, 78 | addHash: addHash, 79 | data: fileData, 80 | add: addToFileData, 81 | getFileData: getFileData, 82 | init: init 83 | } 84 | } -------------------------------------------------------------------------------- /app/components/partials/settings.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/components/factories/diskFactory.js: -------------------------------------------------------------------------------- 1 | var module = angular 2 | .module('DiskFactory', []) 3 | 4 | module.factory('DiskFactory', ['$q', 'PublishService', 'IpfsService', diskFactory]); 5 | 6 | function diskFactory($q, PublishServic, IpfsService) { 7 | //Add "projectFolder" to local app folder 8 | //Return promise 9 | function initProjectFolder() { 10 | $q((resolve, reject) => { 11 | fse.ensureDir(path.resolve(__dirname + `/../projectFolder`), (err) => { 12 | if (err) { 13 | reject(err); 14 | } else { 15 | console.log('projectFolder made in Dispersion directory: ', path.resolve(__dirname + `/../projectFolder`)); 16 | resolve() 17 | } 18 | }); 19 | }) 20 | } 21 | 22 | function copyProjectToAppStorage(copyFromPath) { 23 | 24 | let copyFrom = '/' + copyFromPath; 25 | let pathBrokenIntoArray = copyFrom.split('/'); 26 | let project = '/' + pathBrokenIntoArray[pathBrokenIntoArray.length - 1] 27 | let copyTo = path.resolve(__dirname + `/../projectFolder` + project) 28 | 29 | console.log('copy from ', copyFrom) 30 | console.log('copyTo ', copyTo) 31 | 32 | fse.copy(copyFrom, copyTo, (err) => { 33 | if (err) return console.error(err); 34 | console.log('copied folder to local directory') 35 | }) 36 | } 37 | ///Users/ygoldobin/Desktop/test 38 | ///Users/ygoldobin/Desktop/codesmithHackathon1 39 | // (//index.html, dispersion, data) 40 | function overwriteFileInProject(fileName, projectName, data, fileVersionObj) { 41 | if (fileName[0] !== '/') fileName = '/' + fileName; 42 | let pathToProjectFolder = path.resolve(__dirname + `/../projectFolder/` + projectName); 43 | fs.writeFile(pathToProjectFolder + fileName, data, (err) => { 44 | if (err) return console.error(err); 45 | IpfsService.rehashProject(pathToProjectFolder, fileVersionObj, fileName, projectName, true) 46 | // console.log('overwrote file at this path: \n', path.resolve(__dirname + `/../projectFolder` + projectFolderName + fileName)) 47 | }) 48 | 49 | } 50 | 51 | function deleteAProjectFolder(deletePath) { 52 | 53 | let pathBrokenIntoArray = deletePath.split('/'); 54 | let deleteProject = '/' + pathBrokenIntoArray[pathBrokenIntoArray.length - 1] 55 | let deleteIt = path.resolve(__dirname + `/../projectFolder` + deleteProject) 56 | 57 | fse.emptyDir(deleteIt, (err) => { 58 | if (err) throw err; 59 | console.log('deleted directory contents') 60 | }) 61 | } 62 | 63 | //function to clear specific project file given the string; 64 | //function returns a promise that resolves when a folder is cleared 65 | //function that requests a hash and resolves a promise with the hash data 66 | 67 | return { 68 | init: initProjectFolder, 69 | addProject: copyProjectToAppStorage, 70 | overwrite: overwriteFileInProject, 71 | delete: deleteAProjectFolder 72 | } 73 | } -------------------------------------------------------------------------------- /app/components/factories/publishService.js: -------------------------------------------------------------------------------- 1 | var module = angular 2 | .module('PublishService', []) 3 | 4 | 5 | module.factory('PublishService', ['$q', pubService]); 6 | 7 | function pubService($q) { 8 | let publishData = {}; 9 | // function init() { 10 | // return loadPublished() 11 | // } 12 | function init() { 13 | return $q((resolve, reject) => { 14 | storage.get('publish', (error, data) => { 15 | if (error) reject(error); 16 | publishData = Object.assign(publishData, data); 17 | // console.log('publishData in publish service:', publishData) 18 | storage.get('currentlyPublished', (err, name) => { 19 | currentlyPublished = name; 20 | console.log(currentlyPublished); 21 | resolve(data) 22 | }) 23 | }); 24 | }) 25 | } 26 | let currentlyPublished; 27 | function getCurrentlyPublished() { 28 | return currentlyPublished; 29 | } 30 | function setCurrentlyPublished(name) { 31 | currentlyPublished = name; 32 | storage.set('currentlyPublished', name); 33 | } 34 | function updateStore() { 35 | // uncomment later, just for a check 36 | storage.set('publish', publishData) 37 | storage.get('currentlyPublished', (error, data) => { 38 | currentlyPublished = data; 39 | }) 40 | } 41 | // //unshift for edit fix is here, add an unhashed object for edit purposes// 42 | // function unshiftForEditFix(pubObj, name) { 43 | // console.log('unshifting pubObj ', pubObj, "onto ",name ) 44 | // publishData[name].unshift(pubObj) 45 | // updateStore() 46 | // } 47 | 48 | function addToPublish(pubObj, snapshot = false, name = '') { 49 | console.log('publishData ', publishData) 50 | console.log('pubObj ', pubObj) 51 | if (snapshot) { 52 | // for (let key in pubObj) { 53 | // console.log('key in publishData', publishData[key]) 54 | console.log('unshifting after rehash of project', pubObj) 55 | console.log(publishData) 56 | //THIS LINE RIGHT HERE 57 | publishData[name].unshift(pubObj) 58 | // } 59 | } else { 60 | console.log('add to publish called in publish service'); 61 | console.log('pubObj in add to publish: \n', pubObj); 62 | for (let key in pubObj) { 63 | if (!publishData[key]) { 64 | console.log('key, publishData'); 65 | console.log(key, publishData) 66 | publishData[key] = pubObj[key]; 67 | } else { 68 | console.log('this project has already been published') 69 | //add more logic to maybe just append to array 70 | } 71 | } 72 | } 73 | updateStore() 74 | } 75 | 76 | return { 77 | data: publishData, 78 | add: addToPublish, 79 | init: init, 80 | currentlyPublished: getCurrentlyPublished, 81 | setPublished: setCurrentlyPublished, 82 | // unshiftForEditFix: unshiftForEditFix, 83 | updatePublishData: updateStore 84 | } 85 | } 86 | 87 | 88 | -------------------------------------------------------------------------------- /app/components/partials/FileHistoryPartial.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 25 | 26 | 27 | 28 | 38 | 39 |
52 |
53 |
54 | 55 | 56 | 57 | 58 |
59 | 60 | 61 |
62 |
63 | 64 |
65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
-------------------------------------------------------------------------------- /app/components/controllers/ProjectController.js: -------------------------------------------------------------------------------- 1 | angular.module('ProjectController', []) 2 | .controller('ProjectController', ['$http', 'ProjectService', '$scope', '$timeout', projectController]); 3 | 4 | function projectController($http, ProjectService, $scope, $timeout) { 5 | const self = this; 6 | self.projectArray = ProjectService.projectArray; 7 | self.publishedVersions = ProjectService.publishedProjectVersions; 8 | self.selectedVersion = ProjectService.selectedVersion; 9 | self.currentFile = ProjectService.currentFile;//function 10 | self.currentUrl = ProjectService.currentUrl; //function 11 | 12 | self.filesList = ProjectService.selectedVersionFilesList;//function 13 | self.fileVersions = ProjectService.fileChangedVersions; //function 14 | self.mediaContentUrl = ''; 15 | self.showEditor = false; 16 | self.showMedia = false; 17 | self.showFiles = false; 18 | self.lastProjectIndex = null; 19 | self.fileContentViewIndex = null; 20 | self.currentlySelectedFile = null; 21 | 22 | self.setFileContentViewIndex = (index) => { 23 | self.fileContentViewIndex = index; 24 | } 25 | self.changeCurrentlySelectedFile = (fileName, index = 0) => { 26 | self.showEditor = false; 27 | $timeout(() => { 28 | if (!self.isImage(fileName) && (self.fileContentViewIndex === null || self.currentlySelectedFile !== fileName)) { 29 | self.showEditor = true; 30 | self.setFileContentViewIndex(index); 31 | self.currentlySelectedFile = fileName; 32 | 33 | } else { 34 | self.showEditor = false; 35 | self.fileContentViewIndex = null; 36 | self.currentlySelectedFile = null; 37 | } 38 | }, 0); 39 | } 40 | 41 | self.toggleShowFiles = (index) => { 42 | self.showFiles = self.lastVersionIndex === undefined || index !== self.lastVersionIndex ? true : !self.showFiles; 43 | self.lastVersionIndex = index; 44 | } 45 | self.getMediaContentUrl = () => self.mediaContentUrl; 46 | self.currentProject = ProjectService.currentProject;//function 47 | //clean this function up 48 | self.selectVersion = function (index) { 49 | ProjectService.changeSelectedVersion(index); 50 | // if (self.showIframe && self.lastProjectIndex !== null && index === self.lastProjectIndex) { 51 | // // if (self.showIframe && self.lastProjectIndex !== null && index === self.lastProjectIndex) { 52 | // self.showIframe = false; 53 | // } else { 54 | // self.showIframe = true; 55 | // } 56 | if (self.lastProjectIndex === index) { 57 | self.lastProjectIndex = index; 58 | 59 | } else { 60 | self.lastProjectIndex = index; 61 | } 62 | 63 | } 64 | self.getMode = function (filename) { 65 | let textTester = /(\.html$)|(\.js$)|(\.css$)|(\.txt$)|(\.json$)|(\.md$)|(\.log$)/gmi; 66 | let text = textTester.test(filename); 67 | return text ? self.getAceMode(filename.split('.').pop()) : false; 68 | } 69 | self.getAceMode = function (ext) { 70 | switch (ext) { 71 | case 'js': 72 | return 'javascript'; 73 | case 'html': 74 | return 'html'; 75 | case 'css': 76 | return 'css'; 77 | case 'json': 78 | return 'json'; 79 | default: 80 | return ''; 81 | } 82 | } 83 | self.isImage = (file) => { 84 | let imageTester = /(\.jpeg$)|(\.jpg$)|(\.png$)|(\.gif$)|(\.json$)|(\.md$)|(\.log$)/i; 85 | return imageTester.test(file); 86 | } 87 | self.modalTrigger = function () { 88 | console.log('in modalTrigger') 89 | $('#projectModal').openModal() 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/assets/fonts/Julius_Sans_One/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, LatinoType (luciano@latinotype.com), with Reserved Font Names 'Julius' 2 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 3 | This license is copied below, and is also available with a FAQ at: 4 | http://scripts.sil.org/OFL 5 | 6 | 7 | ----------------------------------------------------------- 8 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 9 | ----------------------------------------------------------- 10 | 11 | PREAMBLE 12 | The goals of the Open Font License (OFL) are to stimulate worldwide 13 | development of collaborative font projects, to support the font creation 14 | efforts of academic and linguistic communities, and to provide a free and 15 | open framework in which fonts may be shared and improved in partnership 16 | with others. 17 | 18 | The OFL allows the licensed fonts to be used, studied, modified and 19 | redistributed freely as long as they are not sold by themselves. The 20 | fonts, including any derivative works, can be bundled, embedded, 21 | redistributed and/or sold with any software provided that any reserved 22 | names are not used by derivative works. The fonts and derivatives, 23 | however, cannot be released under any other type of license. The 24 | requirement for fonts to remain under this license does not apply 25 | to any document created using the fonts or their derivatives. 26 | 27 | DEFINITIONS 28 | "Font Software" refers to the set of files released by the Copyright 29 | Holder(s) under this license and clearly marked as such. This may 30 | include source files, build scripts and documentation. 31 | 32 | "Reserved Font Name" refers to any names specified as such after the 33 | copyright statement(s). 34 | 35 | "Original Version" refers to the collection of Font Software components as 36 | distributed by the Copyright Holder(s). 37 | 38 | "Modified Version" refers to any derivative made by adding to, deleting, 39 | or substituting -- in part or in whole -- any of the components of the 40 | Original Version, by changing formats or by porting the Font Software to a 41 | new environment. 42 | 43 | "Author" refers to any designer, engineer, programmer, technical 44 | writer or other person who contributed to the Font Software. 45 | 46 | PERMISSION & CONDITIONS 47 | Permission is hereby granted, free of charge, to any person obtaining 48 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 49 | redistribute, and sell modified and unmodified copies of the Font 50 | Software, subject to the following conditions: 51 | 52 | 1) Neither the Font Software nor any of its individual components, 53 | in Original or Modified Versions, may be sold by itself. 54 | 55 | 2) Original or Modified Versions of the Font Software may be bundled, 56 | redistributed and/or sold with any software, provided that each copy 57 | contains the above copyright notice and this license. These can be 58 | included either as stand-alone text files, human-readable headers or 59 | in the appropriate machine-readable metadata fields within text or 60 | binary files as long as those fields can be easily viewed by the user. 61 | 62 | 3) No Modified Version of the Font Software may use the Reserved Font 63 | Name(s) unless explicit written permission is granted by the corresponding 64 | Copyright Holder. This restriction only applies to the primary font name as 65 | presented to the users. 66 | 67 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 68 | Software shall not be used to promote, endorse or advertise any 69 | Modified Version, except to acknowledge the contribution(s) of the 70 | Copyright Holder(s) and the Author(s) or with their explicit written 71 | permission. 72 | 73 | 5) The Font Software, modified or unmodified, in part or in whole, 74 | must be distributed entirely under this license, and must not be 75 | distributed under any other license. The requirement for fonts to 76 | remain under this license does not apply to any document created 77 | using the Font Software. 78 | 79 | TERMINATION 80 | This license becomes null and void if any of the above conditions are 81 | not met. 82 | 83 | DISCLAIMER 84 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 85 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 86 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 87 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 88 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 89 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 90 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 91 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 92 | OTHER DEALINGS IN THE FONT SOFTWARE. 93 | -------------------------------------------------------------------------------- /app/components/controllers/mockdata.js: -------------------------------------------------------------------------------- 1 | const testProjectData = { 2 | "Dispersion": [ 3 | { 4 | "date": "2016-10-14T18:22:23.133Z", 5 | "hash": "QmehudYxpxDW3egZraNvq7MKEXzky8GLRcxJ6VbmpUcbxV", 6 | "publish": true, 7 | "changed": "/smoke_trail.jpeg", 8 | "url": "https://ipfs.io/ipfs/QmehudYxpxDW3egZraNvq7MKEXzky8GLRcxJ6VbmpUcbxV", 9 | "files": [ 10 | "/index.html", 11 | "/main.js", 12 | "/styles.css" 13 | ] 14 | }, 15 | { 16 | "date": "2016-10-15T18:22:23.133Z", 17 | "hash": "QmPdqizZHVSKbCGkv6rXaotXwdwRC5jHQLUNy2niEfNg1o", 18 | "publish": true, 19 | "changed": "/styles.css", 20 | "url": "https://ipfs.io/ipfs/QmPdqizZHVSKbCGkv6rXaotXwdwRC5jHQLUNy2niEfNg1o", 21 | "files": [ 22 | "/index.html", 23 | "/main.js", 24 | "/styles.css", 25 | "/smoke_trail.jpeg" 26 | ] 27 | }, 28 | { 29 | "date": "2016-10-16T18:22:23.133Z", 30 | "hash": "QmXEib3wKC3ZnNQGyLJdZJ5iPpmgoqoJyqPfLNdTRbwtUg", 31 | "publish": true, 32 | "changed": "/main.js", 33 | "url": "https://ipfs.io/ipfs/QmXEib3wKC3ZnNQGyLJdZJ5iPpmgoqoJyqPfLNdTRbwtUg", 34 | "files": [ 35 | "/index.html", 36 | "/main.js", 37 | "/styles.css", 38 | "/smoke_trail.jpeg" 39 | ] 40 | }, 41 | { 42 | "date": "2016-10-17T18:22:23.133Z", 43 | "hash": "QmTG9nQUhYJdH5uraNyVdDftoTWDhBgPtTbdCp9x7Xawrx", 44 | "publish": true, 45 | "changed": "/index.html", 46 | "url": "https://ipfs.io/ipfs/QmTG9nQUhYJdH5uraNyVdDftoTWDhBgPtTbdCp9x7Xawrx", 47 | "files": [ 48 | "/index.html", 49 | "/main.js", 50 | "/styles.css", 51 | "/smoke_trail.jpeg" 52 | ] 53 | }, 54 | { 55 | "date": "2016-10-18T18:22:23.133Z", 56 | "hash": "QmT45exg6ZEiCBxC4LfoVZPvPkzdtQvNqWxbF9CJN3Xnec", 57 | "publish": false, 58 | "changed": "/index.html", 59 | "url": "https://ipfs.io/ipfs/QmT45exg6ZEiCBxC4LfoVZPvPkzdtQvNqWxbF9CJN3Xnec", 60 | "files": [ 61 | "/index.html", 62 | "/main.js", 63 | "/styles.css", 64 | "/smoke_trail.jpeg" 65 | ] 66 | }, 67 | { 68 | "date": "2016-10-19T18:22:23.133Z", 69 | "hash": "QmXtuj4RRhSNDxNpa2MKaea4sZ5GRprjvtrdaTH84pY9NC", 70 | "publish": false, 71 | "changed": "/index.html", 72 | "url": "https://ipfs.io/ipfs/QmXtuj4RRhSNDxNpa2MKaea4sZ5GRprjvtrdaTH84pY9NC", 73 | "files": [ 74 | "/index.html", 75 | "/main.js", 76 | "/styles.css", 77 | "/smoke_trail.jpeg" 78 | ] 79 | }, 80 | { 81 | "date": "2016-10-20T18:22:23.133Z", 82 | "hash": "QmWxnq9onYoNcsYjTpk1mcHTCU6bgmXBCALwkP7roP68HY", 83 | "publish": false, 84 | "changed": "/index.html", 85 | "url": "https://ipfs.io/ipfs/QmWxnq9onYoNcsYjTpk1mcHTCU6bgmXBCALwkP7roP68HY", 86 | "files": [ 87 | "/index.html", 88 | "/main.js", 89 | "/styles.css", 90 | "/smoke_trail.jpeg" 91 | ] 92 | } 93 | ] 94 | } 95 | const testFileData = { 96 | "Dispersion": [ 97 | { 98 | "date": "2016-10-18T18:22:23.133Z", 99 | "hash": "QmT45exg6ZEiCBxC4LfoVZPvPkzdtQvNqWxbF9CJN3Xnec", 100 | "file": "/index.html", 101 | "hash": 102 | "url": "https://ipfs.io/ipfs/QmT45exg6ZEiCBxC4LfoVZPvPkzdtQvNqWxbF9CJN3Xnec", 103 | }, 104 | { 105 | "date": "2016-10-19T18:22:23.133Z", 106 | "hash": "QmXtuj4RRhSNDxNpa2MKaea4sZ5GRprjvtrdaTH84pY9NC", 107 | "file": "/index.html", 108 | "url": "https://ipfs.io/ipfs/QmXtuj4RRhSNDxNpa2MKaea4sZ5GRprjvtrdaTH84pY9NC/index.html", 109 | }, 110 | { 111 | "date": "2016-10-20T18:22:23.133Z", 112 | "hash": "QmWxnq9onYoNcsYjTpk1mcHTCU6bgmXBCALwkP7roP68HY", 113 | "file": "/index.html", 114 | "url": "https://ipfs.io/ipfs/QmWxnq9onYoNcsYjTpk1mcHTCU6bgmXBCALwkP7roP68HY/index.html", 115 | } 116 | ], 117 | "yang": [ 118 | { 119 | "date": "2016-10-18T18:22:23.133Z", 120 | "hash": "QmT45exg6ZEiCBxC4LfoVZPvPkzdtQvNqWxbF9CJN3Xnec", 121 | "file": "/index.html", 122 | "url": "https://ipfs.io/ipfs/QmT45exg6ZEiCBxC4LfoVZPvPkzdtQvNqWxbF9CJN3Xnec/index.html", 123 | }, 124 | { 125 | "date": "2016-10-19T18:22:23.133Z", 126 | "hash": "QmXtuj4RRhSNDxNpa2MKaea4sZ5GRprjvtrdaTH84pY9NC", 127 | "file": "/index.html", 128 | "url": "https://ipfs.io/ipfs/QmXtuj4RRhSNDxNpa2MKaea4sZ5GRprjvtrdaTH84pY9NC/index.html", 129 | }, 130 | { 131 | "date": "2016-10-20T18:22:23.133Z", 132 | "hash": "QmWxnq9onYoNcsYjTpk1mcHTCU6bgmXBCALwkP7roP68HY", 133 | "file": "/index.html", 134 | "url": "https://ipfs.io/ipfs/QmWxnq9onYoNcsYjTpk1mcHTCU6bgmXBCALwkP7roP68HY/index.html", 135 | } 136 | ] 137 | } 138 | -------------------------------------------------------------------------------- /app/assets/fonts/Raleway/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Matt McInerney (matt@pixelspread.com), 2 | Copyright (c) 2011, Pablo Impallari (www.impallari.com|impallari@gmail.com), 3 | Copyright (c) 2011, Rodrigo Fuenzalida (www.rfuenzalida.com|hello@rfuenzalida.com), with Reserved Font Name Raleway 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /app/assets/css/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Julius Sans One"; 3 | src: url("./../fonts/Julius_Sans_One/JuliusSansOne-Regular.ttf"); 4 | } 5 | 6 | html { 7 | font-weight: 300; 8 | } 9 | 10 | body { 11 | background: #eeeeee; 12 | } 13 | 14 | a { 15 | text-decoration:none; 16 | } 17 | 18 | h1 { 19 | font-size: 32px; 20 | text-align: center; 21 | color: #eeeeee; 22 | margin:0; 23 | padding-top: 8px; 24 | padding-bottom: 8px 25 | } 26 | 27 | .brand-logo { 28 | font-family: "Julius Sans One"; 29 | font-weight: 200; 30 | letter-spacing: .15em; 31 | } 32 | 33 | .tabs .indicator { 34 | /*color: #4db6ac;*/ 35 | background-color: #607d8b ; 36 | } 37 | 38 | i { 39 | color: white; 40 | } 41 | 42 | .file-icon-images i { 43 | color: #ffc107; 44 | } 45 | 46 | .sel-box{ 47 | position:relative; 48 | } 49 | 50 | .add-icon { 51 | font-size: 55px; 52 | cursor: pointer; 53 | } 54 | 55 | [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { 56 | display: none !important; 57 | } 58 | 59 | .title { 60 | font-weight: bold; 61 | color:#4db6ac; 62 | } 63 | 64 | blockquote { 65 | margin: 20px 0; 66 | padding-left: 1.5rem; 67 | border-left: 5px solid #ffb300; /* Just change the color value and that's it*/ 68 | } 69 | 70 | .btn-ad { 71 | margin-left: 10px; 72 | } 73 | 74 | #hash-input, #project-input { 75 | font-size: 32px; 76 | padding-left: 65px; 77 | } 78 | 79 | #hash-input:hover { 80 | cursor: pointer; 81 | font-size: 32px; 82 | padding-left: 65px; 83 | } 84 | 85 | .card .card-action { 86 | position: relative; 87 | display: flex; 88 | align-items: center; 89 | justify-content: space-between; 90 | } 91 | 92 | .project-nav-bar{ 93 | font-size: 2.1rem; 94 | margin-left: 30px; 95 | font-family: "Julius Sans One"; 96 | font-weight: 200; 97 | letter-spacing: .15em; 98 | } 99 | 100 | /*CSS for Daemon Load*/ 101 | .preload { 102 | margin: 0; 103 | position: absolute; 104 | overflow: hidden; 105 | z-index: 999; 106 | width: 100%; 107 | height: 100vh; 108 | top: 0; 109 | background: #ff8300; 110 | background: linear-gradient(to top left, #ffff66 -40%, #ff8300); 111 | } 112 | 113 | .container { 114 | position: absolute; 115 | top:0; 116 | bottom: 0; 117 | left: 0; 118 | right: 0; 119 | width: 350px; 120 | height: 350px; 121 | margin: auto; 122 | } 123 | 124 | .part { 125 | width: 350px; 126 | position: absolute; 127 | } 128 | 129 | .svgpath { 130 | fill: rgba(145,220,90,0); 131 | stroke: #ff8300; 132 | stroke-width: 1.8px; 133 | stroke-dasharray: 1000; 134 | stroke-linecap: round; 135 | z-index: 2; 136 | } 137 | 138 | .svgbg { 139 | fill: rgba(255,255,255,0.2); 140 | z-index: 1; 141 | } 142 | 143 | #playload { 144 | animation: dash 2.5s reverse ease-in-out infinite; 145 | } 146 | 147 | @keyframes dash { 148 | to { 149 | stroke-dashoffset: 2000; 150 | } 151 | } 152 | 153 | .settings-item span { 154 | font-size: 21px; 155 | font-weight: thin; 156 | } 157 | 158 | .projectView .ace_editor { 159 | min-height: 200px; 160 | } 161 | 162 | .projectView ul li { 163 | display: inline; 164 | } 165 | 166 | .projectView #outer{ 167 | width: 320px; 168 | height: 180px; 169 | 170 | } 171 | 172 | .projectView img{ 173 | max-width:100%; 174 | max-height:100%; 175 | } 176 | 177 | .projectView button.selected { 178 | background-color: lightblue; 179 | } 180 | 181 | .projectView .changedFile::after { 182 | content: '*changed'; 183 | } 184 | 185 | .projectView .mediaContentWrapper { 186 | max-height: 900px; 187 | max-width: 600px; 188 | } 189 | .projectView .fileVersion { 190 | margin: 0; 191 | font-size: 15px; 192 | text-decoration: none; 193 | } 194 | 195 | .save-delete { 196 | padding-top: 8px; 197 | } 198 | 199 | .fileVersionListItem { 200 | margin: 0; 201 | padding-top: 10px; 202 | padding: 0; 203 | height: 20px; 204 | } 205 | .fileVersionList { 206 | padding: 0; 207 | padding-top: 8px; 208 | padding-bottom: 8px; 209 | display: flex; 210 | } 211 | 212 | .transparent { 213 | background-color: transparent; 214 | background-repeat:no-repeat; 215 | border: none; 216 | cursor:pointer; 217 | overflow: hidden; 218 | outline:none; 219 | } 220 | 221 | .projectView .editor { 222 | width: 100%; 223 | min-height: 400px; 224 | max-height: 800px; 225 | } 226 | 227 | .content-link { 228 | cursor: pointer; 229 | } 230 | 231 | .close-modal { 232 | position: absolute; 233 | right: 5px; 234 | top: 5px; 235 | cursor:pointer; 236 | color: #fff; 237 | border: 1px solid #AEAEAE; 238 | border-radius: 30px; 239 | background: #605F61; 240 | font-size: 31px; 241 | font-weight: bold; 242 | display: inline-block; 243 | line-height: 0px; 244 | padding: 11px 3px; 245 | } 246 | 247 | .close-modal:before { 248 | content: "×"; 249 | } 250 | 251 | .iframe-wrap { 252 | z-index: 9999; 253 | position: absolute; 254 | top:22px; 255 | left:50%; 256 | transform: translate(-50%, 0); 257 | width: 95vw; 258 | height: 100vw; 259 | background-color: #fafafa; 260 | border-radius: 2px; 261 | } 262 | 263 | .file-iframe { 264 | width: 100%; 265 | height: 100%; 266 | } 267 | 268 | .modal { 269 | width: 90%; 270 | max-height: 85%; 271 | } 272 | 273 | .modal.modal-fixed-footer { 274 | height: 85%; 275 | } 276 | 277 | @media only screen and (max-width: 992px) { 278 | .modal { 279 | width: 90%; 280 | } 281 | } 282 | 283 | .modal h4 { 284 | text-align: center; 285 | padding-top: 15px; 286 | } 287 | 288 | .project { 289 | margin-left: 25px; 290 | } 291 | 292 | .individual-file-partial{ 293 | padding: 5px; 294 | } 295 | 296 | .save-delete-buttons{ 297 | width: 157px; 298 | } 299 | 300 | .proj-modal-button { 301 | margin-left:5px; 302 | } 303 | 304 | .pub-version-list { 305 | padding-right: 5px; 306 | } 307 | 308 | .ace-chaos .ace_print-margin { 309 | border-left: none; 310 | background: none; 311 | } 312 | 313 | div.ace_print-margin { 314 | width: 0 !important; 315 | } 316 | 317 | .backdrop { 318 | background-color: #455a64; 319 | } 320 | 321 | .collection-item > .collapsible-header { 322 | transition: 400ms ease; 323 | } 324 | .collection-item > .collapsible-header:hover { 325 | background-color: rgba(255,255,255,0.7) !important; 326 | } 327 | 328 | .body-wrapper { 329 | padding: 5px; 330 | } 331 | 332 | .ipfs-version { 333 | position: absolute; 334 | right: 20px; 335 | top: 10px; 336 | } 337 | 338 | .side-nav a, .material-icons { 339 | cursor: pointer; 340 | } 341 | 342 | .file-headers { 343 | border-top: none; 344 | border-right: none; 345 | border-left: none; 346 | margin: none; 347 | box-shadow: none; 348 | } -------------------------------------------------------------------------------- /app/assets/js/dispersion.js: -------------------------------------------------------------------------------- 1 | // required by the index.html file 2 | // executed in the renderer process for that window. 3 | 4 | 5 | (function (window) { 6 | //Dispersion Library Definition 7 | function define_Dispersion_Library() { 8 | var Dispersion = {}; 9 | 10 | 11 | // On click submits inputed file to be hashed. 12 | Dispersion.submitFile = function (filepath) { 13 | 14 | //file or directory to be hashed. 15 | let hashFile = filepath 16 | if (hashFile.includes('/')) hashFile = `"${hashFile}"`; 17 | // recursively hashes directory or file and adds to ipfs 18 | let command = `ipfs add -r ${hashFile}`; 19 | 20 | exec(command, function (error, stdout, stderr) { 21 | //grabs just the filename from the absolute path of the added file 22 | let fileLocationArray = hashFile.split('/'); 23 | let name = fileLocationArray[fileLocationArray.length - 1]; 24 | //separate hashes from folder into an array 25 | let hashArray = stdout.trim().split('\n'); 26 | let topHash = hashArray[hashArray.length - 1].split(' '); 27 | let file = topHash.slice(2).join(' '); 28 | let hashObj = { 29 | "file": file, 30 | "time": new Date().toUTCString(), 31 | "url": "https://ipfs.io/ipfs/" + topHash[1], 32 | 'files': [] 33 | } 34 | //iterates over the individual hashes, makes requests to them, and stores top level hash in local storage 35 | hashArray.forEach(function (hString, index) { 36 | let tempArray = hString.split(' '); 37 | var requestObj = { 38 | [tempArray[1]]: { 39 | "url": "https://ipfs.io/ipfs/" + tempArray[1] 40 | } 41 | } 42 | //grabs the inner file paths and pushes into file array 43 | if (index < hashArray.length - 1) { 44 | hashObj.files.push(`/${tempArray[2].split('/').slice(1).join('/')}`) 45 | } 46 | //store top hash in local storage 47 | storage.set(topHash[1], hashObj, function (error) { 48 | if (error) throw error; 49 | }); 50 | //requests each hash url 5 times 51 | 52 | //good functionality to abstract into its own function 53 | for (let key in requestObj) { 54 | let url = requestObj[key]["url"] 55 | for (let i = 0; i < 5; i++) { 56 | request(url, (err, response, body) => { 57 | if (err) { 58 | console.log('error making distribute request to IPFS'); 59 | console.error(err); 60 | } else { 61 | console.log(url) 62 | console.log(response.statusCode) 63 | } 64 | }) 65 | } 66 | } 67 | }) 68 | }) 69 | } 70 | 71 | //Removes the pinned object from local storage. 72 | Dispersion.unPin = function (pinHash) { 73 | let pinRmCommand = 'ipfs pin rm ' + pinHash; 74 | exec(pinRmCommand, function (error, stdout, stderr) { 75 | storage.remove(pinHash, function (error) { 76 | if (error) throw error; 77 | }); 78 | if (error !== null) { 79 | console.log('exec error: ' + error); 80 | } 81 | }) 82 | } 83 | 84 | //publishes the hash to the Peer ID ipns 85 | Dispersion.publishHash = function (hash) { 86 | let publishIt = 'ipfs name publish ' + hash; 87 | console.log(publishIt); 88 | exec(publishIt, function (error, stdout, stderr) { 89 | console.log(stdout, hash); 90 | let hashed = `http://gateway.ipfs.io/ipns/${stdout.split(' ')[2].slice(0, -1)}` 91 | //$('#hashlink').text(hashed); 92 | if (error !== null) { 93 | console.log('exec error: ' + error); 94 | } 95 | }) 96 | } 97 | 98 | //function to add pin to local storage 99 | Dispersion.addPin = function (pinHash, pinDescription) { 100 | let pinCommand = 'ipfs pin add ' + pinHash; 101 | let hashObject = { 102 | "file": pinDescription, 103 | "pinnedBy": 'someone else', 104 | "pinDate": new Date(), 105 | "url": "https://ipfs.io/ipfs/" + pinHash 106 | }; 107 | exec(pinCommand, function (error, stdout, stderr) { 108 | //saves pinned hash to Electron App storage 109 | storage.set(pinHash, hashObject, function (error) { 110 | if (error) throw error; 111 | }); 112 | if (error !== null) { 113 | console.log('exec error: ' + error); 114 | } 115 | }) 116 | } 117 | 118 | //save selected hash to local computer's desktop 119 | Dispersion.saveToDisk = function (pinHash, username) { 120 | //set save-to directory to a file on user's desktop 121 | let directory = `/Users/${username}/Desktop/ipfs` 122 | let pinSaveCommand = `ipfs get --output="${directory}" ${pinHash}`; 123 | exec(pinSaveCommand, function (error, stdout, stderr) { 124 | if (error !== null) console.log('exec error: ' + error); 125 | //get data from hash for file save 126 | storage.get(pinHash, function (error, data) { 127 | if (error) throw error; 128 | //check if the hash has already been pinned. 129 | if (Object.keys(data).length === 0) { 130 | alert("Please pin before download!"); 131 | return; 132 | } 133 | //initial location and name of saved hash. Default to Desktop 134 | let fileLocation = `${directory}/${pinHash}` 135 | //filename of hash 136 | let filename = data.file 137 | let fileExtension; 138 | //determine and set file extension for saving 139 | if (!filename.includes('.')) { 140 | let buffer = readChunk.sync(fileLocation, 0, 262); 141 | fileExtension = `.${fileType(buffer).ext}`; 142 | } else { 143 | fileExtension = '' 144 | } 145 | //rename file based on filename and extension 146 | fs.rename(fileLocation, `"${directory}/${filename}${fileExtension}"`, function (err) { 147 | if (err) console.log('ERROR: ' + err); 148 | }); 149 | }); 150 | }) 151 | } 152 | 153 | //function to start daemon 154 | Dispersion.startDaemon = function () { 155 | let daemonCommand = spawn('ipfs', ['daemon']); 156 | daemonCommand.stdout.on('data', function (data) { 157 | let dataString = data.toString(); 158 | let result = /Daemon is ready/.test(dataString); 159 | if (result) { 160 | console.log('the daemon is running') 161 | } 162 | }); 163 | daemonCommand.stderr.on('data', function (data) { 164 | let dataString = data.toString(); 165 | let result = /daemon is running/.test(dataString); 166 | if (result) { 167 | console.log('Warning: Daemon already is running in a seperate process! Closing this application will not kill your IPFS Daemon.') 168 | } 169 | }) 170 | } 171 | return Dispersion; 172 | } 173 | 174 | document.ondragover = document.ondrop = (ev) => { 175 | ev.preventDefault() 176 | } 177 | 178 | document.body.ondrop = (ev) => { 179 | console.log('hi ', ev.dataTransfer.files[0].path) 180 | $('#hash-input').val(ev.dataTransfer.files[0].path); 181 | ev.preventDefault() 182 | $('#hash-input').trigger('input'); 183 | // $('#project-input').trigger('input'); 184 | } 185 | 186 | 187 | 188 | 189 | 190 | 191 | //define globally if it doesn't already exist 192 | if (typeof (Dispersion) === 'undefined') { 193 | window.Dispersion = define_Dispersion_Library(); 194 | } else { 195 | console.log("Dispersion already defined."); 196 | } 197 | 198 | })(window); 199 | -------------------------------------------------------------------------------- /app/components/controllers/FileHistoryController.js: -------------------------------------------------------------------------------- 1 | angular.module('FileHistoryController', []) 2 | .controller('FileHistoryController', ['ProjectService', '$scope', '$http', 'DiskFactory', 'FileHistoryFactory', fileHistoryController]); 3 | function fileHistoryController(ProjectService, $scope, $http, DiskFactory, FileHistoryFactory) { 4 | //TODO: 5 | 6 | FileHistoryFactory.init() 7 | 8 | $scope.showInfo = false; 9 | $scope.showEditor = false; 10 | $scope.showMedia = false; 11 | $scope.ext = $scope.filename.split('.').pop(); 12 | $scope.previousEditorContent = ''; 13 | $scope.theme = 'monokai'; 14 | $scope.modes = [ 15 | 'abap', 16 | 'actionscript', 17 | 'ada', 18 | 'apache_conf', 19 | 'asciidoc', 20 | 'assembly_x86', 21 | 'autohotkey', 22 | 'batchfile', 23 | 'c9search', 24 | 'c_cpp', 25 | 'cirru', 26 | 'clojure', 27 | 'cobol', 28 | 'coffee', 29 | 'coldfusion', 30 | 'csharp', 31 | 'css', 32 | 'curly', 33 | 'd', 34 | 'dart', 35 | 'diff', 36 | 'dockerfile', 37 | 'dot', 38 | 'dummy', 39 | 'dummysyntax', 40 | 'eiffel', 41 | 'ejs', 42 | 'elixir', 43 | 'elm', 44 | 'erlang', 45 | 'forth', 46 | 'ftl', 47 | 'gcode', 48 | 'gherkin', 49 | 'gitignore', 50 | 'glsl', 51 | 'golang', 52 | 'groovy', 53 | 'haml', 54 | 'handlebars', 55 | 'haskell', 56 | 'haxe', 57 | 'html', 58 | 'html_ruby', 59 | 'ini', 60 | 'io', 61 | 'jack', 62 | 'jade', 63 | 'java', 64 | 'javascript', 65 | 'json', 66 | 'jsoniq', 67 | 'jsp', 68 | 'jsx', 69 | 'julia', 70 | 'latex', 71 | 'less', 72 | 'liquid', 73 | 'lisp', 74 | 'livescript', 75 | 'logiql', 76 | 'lsl', 77 | 'lua', 78 | 'luapage', 79 | 'lucene', 80 | 'makefile', 81 | 'markdown', 82 | 'matlab', 83 | 'mel', 84 | 'mushcode', 85 | 'mysql', 86 | 'nix', 87 | 'objectivec', 88 | 'ocaml', 89 | 'pascal', 90 | 'perl', 91 | 'pgsql', 92 | 'php', 93 | 'powershell', 94 | 'praat', 95 | 'prolog', 96 | 'properties', 97 | 'protobuf', 98 | 'python', 99 | 'r', 100 | 'rdoc', 101 | 'rhtml', 102 | 'ruby', 103 | 'rust', 104 | 'sass', 105 | 'scad', 106 | 'scala', 107 | 'scheme', 108 | 'scss', 109 | 'sh', 110 | 'sjs', 111 | 'smarty', 112 | 'snippets', 113 | 'soy_template', 114 | 'space', 115 | 'sql', 116 | 'stylus', 117 | 'svg', 118 | 'tcl', 119 | 'tex', 120 | 'text', 121 | 'textile', 122 | 'toml', 123 | 'twig', 124 | 'typescript', 125 | 'vala', 126 | 'vbscript', 127 | 'velocity', 128 | 'verilog', 129 | 'vhdl', 130 | 'xml', 131 | 'xquery', 132 | 'yaml', 133 | ]; 134 | $scope.projectobj = JSON.parse($scope.projectobject); 135 | 136 | $scope.versions = function () { 137 | if (!FileHistoryFactory.getFileHistory()[$scope.projectname]) return [] 138 | return FileHistoryFactory.getFileHistory()[$scope.projectname].filter((version) => { 139 | let file = $scope.filename 140 | if (file) { 141 | if (file[0] !== '/') file = '/' + file; 142 | return version.file === file; 143 | } 144 | }); 145 | } 146 | $scope.toggleEditor = () => { 147 | $scope.showEditor = !$scope.showEditor; 148 | } 149 | $scope.toggleShowInfo = () => { 150 | console.log('clicked toggle show info') 151 | $scope.showInfo = !$scope.showInfo; 152 | } 153 | 154 | //instead now make new file history obj 155 | $scope.makeNewHistoryObj = () => { 156 | return [$scope.filename, $scope.projectname, $scope.editorContent, { date: new Date().toUTCString(), file: $scope.filename }] 157 | } 158 | 159 | //make new history, need to add to file history factroy data store 160 | $scope.saveFile = function () { 161 | Materialize.toast("New Version Saved", 2000); 162 | console.log('$scope.editorcontent in saveFile', $scope.editorContent); 163 | let fileDataSaveArray = $scope.makeNewHistoryObj(); 164 | console.log('save clicked, historyoobj generated: \n', fileDataSaveArray); 165 | console.log('pushing to FilehHistoryfactory') 166 | FileHistoryFactory.add(fileDataSaveArray[3], fileDataSaveArray[1]) 167 | DiskFactory.overwrite(...fileDataSaveArray); 168 | } 169 | $scope.recordIndex = function (index) { 170 | console.log(index) 171 | $scope.openVersionIndex = index; 172 | } 173 | 174 | // delete item from file factroy array 175 | $scope.delete = function () { 176 | //update to change in extended full app data store model 177 | Materialize.toast("Version deleted", 2000); 178 | console.log('filehistoryversions:', $scope.fileHistoryVersions) 179 | console.log($scope.openVersionIndex); 180 | console.log('deleteitem:', $scope.fileHistoryVersions[$scope.openVersionIndex]) 181 | let deleteItem = $scope.fileHistoryVersions[$scope.openVersionIndex] 182 | if (confirm('Are you sure you wish to delete: ', $scope.filename.slice(1), deleteItem.date)) { 183 | $scope.fileHistoryVersions.splice($scope.openVersionIndex, 1); 184 | } 185 | $scope.aceEditor.setValue(''); 186 | $scope.openVersionIndex = 0; 187 | $scope.updateEditorContent(0, $scope.fileHistoryVersions[0]); 188 | } 189 | $scope.aceEditor; 190 | $scope.aceLoaded = function (_editor) { 191 | _editor.$blockScrolling = Infinity; 192 | $scope.aceEditor = _editor; 193 | 194 | 195 | $scope.renderer = _editor.renderer; 196 | $scope.session = _editor.getSession(); 197 | $scope.session.setUndoManager(new ace.UndoManager()); 198 | _editor.on("changeSession", function (e) { 199 | }) 200 | $scope.session.on("change", function (e) { 201 | $scope.editorContent = $scope.session.getValue() 202 | }) 203 | } 204 | $scope.aceChanged = function (e) { 205 | 206 | }; 207 | 208 | //change to use just url on file obj 209 | $scope.updateEditorContent = function (index = 0, file) { 210 | if (!$scope.image) { 211 | let version = file ? file : $scope.versions()[index]; 212 | if (version && version.data) { 213 | $scope.aceEditor.setValue(version.data) 214 | $scope.showEditor = true; 215 | } else { 216 | if (version && version.url) { 217 | $http.get(version.url).then((res) => { 218 | $scope.versions()[index].data = res.data; 219 | $scope.previousEditorContent = $scope.editorContent; 220 | $scope.editorContent = res.data; 221 | $scope.showEditor = true; 222 | }); 223 | } 224 | } 225 | } 226 | } 227 | // $scope.updateEditorContent = function (index = 0, file) { 228 | // // console.log($scope.aceEditor); 229 | // if (!$scope.image) { 230 | // let version = file ? file : $scope.fileHistoryVersions[index]; 231 | 232 | // // console.log(version); 233 | 234 | // if (version && version.data) { 235 | // // $scope.editorContent = version.data; 236 | // $scope.aceEditor.setValue(version.data) 237 | // $scope.showEditor = true; 238 | // } else { 239 | // if (version && version.url) { 240 | // $http.get(version.url + $scope.filename).then((res) => { 241 | // // console.log('http called for ', version.url + $scope.filename) 242 | // $scope.fileHistoryVersions[index].data = res.data; 243 | // $scope.previousEditorContent = $scope.editorContent; 244 | // $scope.editorContent = res.data; 245 | // // $scope.aceEditor.setValue(res.data); 246 | // $scope.showEditor = true; 247 | // }); 248 | // } 249 | // // $scope.showEditor = false; 250 | // } 251 | // } 252 | // } 253 | $scope.clearEditor = function () { 254 | console.log('clear clicked', $scope.editorContent) 255 | $scope.previousEditorContent = $scope.editorContent; 256 | $scope.aceEditor.setValue(''); 257 | } 258 | $scope.undo = function () { 259 | console.log('undo clicked'); 260 | console.log($scope.previousEditorContent); 261 | $scope.editorContent = $scope.previousEditorContent; 262 | } 263 | 264 | $scope.getMediaContent = (url) => { 265 | 266 | $scope.showEditor = false; 267 | $scope.mediaContentUrl = url; 268 | $scope.showMedia = true; 269 | } 270 | 271 | // 272 | $scope.getContentUrl = ProjectService.getContentUrl; //function 273 | // $http.get(self.getContentUrl(file)).then((res) => { 274 | // $scope.editorContent = res.data; 275 | // }) 276 | 277 | $scope.themes = [ 278 | "chrome", 279 | "clouds", 280 | "crimson_editor", 281 | "dawn", 282 | "dreamweaver", 283 | "eclipse", 284 | "github", 285 | "solarized_light", 286 | "textmate", 287 | "tomorrow", 288 | "xcode", 289 | "kuroir", 290 | "katzenmilch", 291 | "ambiance", 292 | "chaos", 293 | "clouds_midnight", 294 | "cobalt", 295 | "idle_fingers", 296 | "kr_theme", 297 | "merbivore", 298 | "merbivore_soft", 299 | "mono_industrial", 300 | "monokai", 301 | "pastel_on_dark", 302 | "solarized_dark", 303 | "terminal", 304 | "tomorrow_night", 305 | "tomorrow_night_blue", 306 | "tomorrow_night_bright", 307 | "tomorrow_night_eighties", 308 | "twilight", 309 | "vibrant_ink" 310 | ]; 311 | $scope.updateEditorContent(); 312 | $scope.recordIndex(); 313 | $scope.toggleShowInfo(); 314 | } 315 | 316 | 317 | 318 | 319 | 320 | //taken from project ctrl 321 | // needs lots of refactoring 322 | // self.aceOptions = { 323 | // useWrapMode: true, 324 | // showGutter: true, 325 | // onLoad: self.aceLoaded, 326 | // onChange: self.aceChanged, 327 | // enableBasicAutocompletion: true, 328 | // // enableLiveAutocompletion: true 329 | // enableSnippets: true 330 | // // advanced: { 331 | // // enableSnippets: true, 332 | // // enableBasicAutocompletion: true, 333 | // // enableLiveAutocompletion: true 334 | // // } 335 | // }; 336 | // self.aceLoaded = function (_editor) { 337 | // // Options 338 | // _editor.setReadOnly(true); 339 | // }; 340 | 341 | // self.aceChanged = function (e) { 342 | // // 343 | // }; 344 | // self.isImage = (file) => { 345 | // let imageTester = /(\.jpeg$)|(\.jpg$)|(\.png$)|(\.gif$)|(\.json$)|(\.md$)|(\.log$)/i; 346 | // return imageTester.test(file); 347 | // } 348 | // self.isText = (file) => { 349 | // let textTester = /(\.html$)|(\.js$)|(\.css$)|(\.txt$)|(\.json$)|(\.md$)|(\.log$)/i; 350 | // return textTester.test(file); 351 | // } 352 | // self.updateEditorContent = (index, url) => { 353 | // console.log(self.fileVersions(self.filesList()[index])) 354 | // if (!url) { 355 | // url = self.currentUrl() + self.filesList()[index]; 356 | // } 357 | // let splitArr = url.split('/') 358 | // let file = splitArr[splitArr.length - 1]; 359 | // let textTester = /(\.html$)|(\.js$)|(\.css$)|(\.txt$)|(\.json$)|(\.md$)|(\.log$)/; 360 | // let text = textTester.test(file); 361 | // let type; 362 | // if (text) { 363 | // type = textTester.exec(file)[0].slice(1); 364 | // } 365 | // if (!text) { 366 | // self.getMediaContent(url); 367 | // } else { 368 | 369 | // console.log(type); 370 | // self.getContent(url); 371 | // } 372 | // } 373 | // self.getMediaContent = (url) => { 374 | 375 | // self.showEditor = false; 376 | // self.mediaContentUrl = url; 377 | // self.showMedia = true; 378 | // } -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dispersion 7 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 |
17 | 18 |
19 |
20 | 34 |
35 | 36 | 37 |
38 |
39 |
40 |
41 |
42 | 46 |
47 | 53 |
54 |
55 |
56 |
    57 | 58 |
  • 59 |
    60 | 61 | folder 62 | web 63 | visibility 64 | description 65 | insert_chart 66 | play_arrow 67 | 68 | 69 | 70 | 71 |
    72 |
    73 |
    74 |
    75 |
    {{fileObj.url}}
    76 |
    77 | 78 | 79 |
    80 |
      81 | 87 |
    88 | Stage 90 | Download 92 | Delete 94 |
    95 |
    96 |
    97 |
  • 98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | 107 |
108 |
109 |
110 |
111 |
112 | 125 | 126 |
127 | 128 |
129 |
130 |
    131 |
  • 132 | 134 |
  • 135 |
136 |
137 |
138 | 139 |
140 |
141 |
142 | 143 | 150 |
151 |
152 |
153 |
154 |
155 | 158 |
159 |
160 |
161 |
162 | 170 |
171 |
172 |
173 |
174 |
175 | 176 | 177 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 233 | 234 | -------------------------------------------------------------------------------- /app/components/factories/ipfsService.js: -------------------------------------------------------------------------------- 1 | angular 2 | .module('IpfsService', []) 3 | .factory('IpfsService', ['$q', '$interval', 'PublishService', ipfsService]); 4 | 5 | function ipfsService($q, $interval, PublishService) { 6 | 7 | ///may have made some breaking changes, please try and clean up and test thoroughly 8 | let daemonLoadedStatus = () => daemonLoaded; 9 | let daemonLoaded = false; 10 | 11 | function startDaemon() { 12 | return $q(function (resolve, reject) { 13 | let daemonCommand = spawn('ipfs', ['daemon']); 14 | daemonCommand.stdout.on('data', function (data) { 15 | let dataString = data.toString(); 16 | let result = /Daemon is ready/.test(dataString); 17 | if (result) { 18 | console.log('the daemon is running') 19 | resolve(result); 20 | } 21 | }); 22 | daemonCommand.stderr.on('data', function (data) { 23 | let dataString = data.toString(); 24 | let result = /daemon is running/.test(dataString); 25 | if (result) { 26 | console.log('Warning: Daemon already is running in a seperate process! Closing this application will not kill your IPFS Daemon.') 27 | resolve(result); 28 | } else { 29 | reject(dataString); 30 | } 31 | }) 32 | }) 33 | } 34 | 35 | //Hashes file, puts it in storage, and requests it to distribute 36 | function submitFile(filepath) { 37 | return $q((resolve, reject) => { 38 | //file or directory to be hashed. 39 | let hashFile = filepath 40 | if (hashFile.includes('/')) hashFile = `"${hashFile}"`; 41 | // recursively hashes directory or file and adds to ipfs 42 | let command = `ipfs add -r ${hashFile}`; 43 | 44 | exec(command, function (error, stdout, stderr) { 45 | //grabs just the filename from the absolute path of the added file 46 | let fileLocationArray = hashFile.split('/'); 47 | let name = fileLocationArray[fileLocationArray.length - 1]; 48 | //separate hashes from folder into an array 49 | let hashArray = stdout.trim().split('\n'); 50 | console.log('hash array, tophash'); 51 | console.log(hashArray) 52 | let topHash = hashArray[hashArray.length - 1].split(' '); 53 | console.log(topHash) 54 | let file = topHash.slice(2).join(' '); 55 | let hashObj = { 56 | "file": file, 57 | "hash": topHash[1], 58 | "date": new Date().toUTCString(), 59 | "url": "https://ipfs.io/ipfs/" + topHash[1], 60 | // "url": "http://ipfs.io/ipfs/" + topHash[1], 61 | 'files': [] 62 | } 63 | hashArray.forEach(function (hString, index) { 64 | let tempArray = hString.split(' '); 65 | var requestObj = { 66 | [tempArray[1]]: { 67 | "url": "https://ipfs.io/ipfs/" + tempArray[1] 68 | // "url": "http://ipfs.io/ipfs/" + tempArray[1] 69 | } 70 | } 71 | if ((/\./.test(tempArray[tempArray.length - 1])) && index < hashArray.length - 1) { 72 | console.log('tempArray', tempArray) 73 | // hashObj.files.push(`/${tempArray[2].split('/').slice(1).join('/')}`) 74 | hashObj.files.push(`/${tempArray.slice(2).join('\ ').split('/').slice(1).join('/')}`) 75 | } 76 | 77 | requestHashes(requestObj) 78 | resolve(hashObj) 79 | }) 80 | }) 81 | }) 82 | } 83 | function rehashProject(filepath, fileVersionObject, fileName, projectName, addToPublishHistory = false) { 84 | //file or directory to be hashed. 85 | // recursively hashes directory or file and adds to ipfs 86 | // let command = `ipfs add -r "${filepath}"`; 87 | 88 | // exec(command, function (error, stdout, stderr) { 89 | // //grabs just the filename from the absolute path of the added file 90 | 91 | // let hashArray = stdout.trim().split('\n'); 92 | 93 | // let topHash = hashArray[hashArray.length - 1].split(' ')[1]; 94 | // console.log(topHash) 95 | // fileVersionObject.hash = topHash; 96 | // fileVersionObject.url = `https://ipfs.io/ipfs/${topHash}${fileName}`; 97 | 98 | // let hashObj = { 99 | // "file": fileName, 100 | // "hash": topHash[1], 101 | // "url": "https://ipfs.io/ipfs/" + topHash[1] + fileName, 102 | // } 103 | // hashArray.forEach(function (hString, index) { 104 | // let tempArray = hString.split(' '); 105 | // var requestObj = { 106 | // [tempArray[1]]: { 107 | // "url": "https://ipfs.io/ipfs/" + tempArray[1] 108 | // } 109 | // } 110 | // requestHashes(requestObj) 111 | // }) 112 | // }) 113 | let command = `ipfs add -r "${filepath}"`; 114 | 115 | exec(command, function (error, stdout, stderr) { 116 | //grabs just the filename from the absolute path of the added file 117 | 118 | let hashArray = stdout.trim().split('\n'); 119 | 120 | let topHash = hashArray[hashArray.length - 1].split(' ')[1]; 121 | console.log(topHash) 122 | fileVersionObject.hash = topHash; 123 | fileVersionObject.url = `https://ipfs.io/ipfs/${topHash}${fileName}`; 124 | // fileVersionObject.url = `http://ipfs.io/ipfs/${topHash}${fileName}`; 125 | 126 | let hashObj = { 127 | "hash": topHash, 128 | "date": new Date().toUTCString(), 129 | "url": "https://ipfs.io/ipfs/" + topHash, 130 | // "url": "http://ipfs.io/ipfs/" + topHash, 131 | 'files': [], 132 | 'publish': false 133 | } 134 | 135 | 136 | hashArray.forEach(function (hString, index) { 137 | let tempArray = hString.split(' '); 138 | var requestObj = { 139 | [tempArray[1]]: { 140 | "url": "https://ipfs.io/ipfs/" + tempArray[1] 141 | // "url": "http://ipfs.io/ipfs/" + tempArray[1] 142 | } 143 | } 144 | if ((/\./.test(tempArray[tempArray.length - 1])) && index < hashArray.length - 1) { 145 | console.log('tempArray', tempArray) 146 | // hashObj.files.push(`/${tempArray[2].split('/').slice(1).join('/')}`) 147 | hashObj.files.push(`/${tempArray.slice(2).join('\ ').split('/').slice(1).join('/')}`) 148 | } 149 | requestHashes(requestObj) 150 | }) 151 | PublishService.add(hashObj, true, projectName) 152 | }) 153 | } 154 | 155 | function requestHashes(requestObj) { 156 | for (let key in requestObj) { 157 | let url = requestObj[key]["url"]; 158 | for (let i = 0; i < 5; i++) { 159 | request(url, (err, response, body) => { 160 | if (err) { 161 | console.log('error making distribute request to IPFS'); 162 | console.error(err); 163 | } else { 164 | console.log(response.statusCode) 165 | } 166 | }) 167 | } 168 | } 169 | } 170 | 171 | 172 | function unPin(pinHash) { 173 | return $q(function (resolve, reject) { 174 | let pinRmCommand = 'ipfs pin rm ' + pinHash; 175 | exec(pinRmCommand, function (error, stdout, stderr) { 176 | console.log(stdout) 177 | resolve() 178 | if (error !== null) { 179 | reject(error); 180 | } 181 | }) 182 | }) 183 | } 184 | 185 | function publishHash(publishObj, projectName) { 186 | // console.log(projectName) 187 | // console.log(publishObj) 188 | if (PublishService && PublishService.data && PublishService.data[projectName] && PublishService.data[projectName][0]) { 189 | PublishService.data[projectName][0]['publish'] = true; 190 | console.log("reach into publish service data", PublishService.data[projectName][0]); 191 | } 192 | console.log('publish obj 0', publishObj[0]) 193 | hash = publishObj[0]['hash'] 194 | console.log('hash in publishHash hash'); 195 | let publishIt = 'ipfs name publish ' + hash; 196 | exec(publishIt, function (error, stdout, stderr) { 197 | console.log(stdout, hash); 198 | let hashed = `http://gateway.ipfs.io/ipns/${stdout.split(' ')[2].slice(0, -1)}` 199 | //$('#hashlink').text(hashed); 200 | if (error !== null) { 201 | console.log('exec error: ' + error); 202 | } else { 203 | PublishService.updatePublishData() 204 | } 205 | }) 206 | } 207 | 208 | function addPin(pinHash, pinDescription) { 209 | let pinCommand = 'ipfs pin add ' + pinHash; 210 | let hashObject = { 211 | "file": pinDescription, 212 | "pinnedBy": 'someone else', 213 | "pinDate": new Date(), 214 | "url": "https://ipfs.io/ipfs/" + pinHash 215 | // "url": "http://ipfs.io/ipfs/" + pinHash 216 | }; 217 | exec(pinCommand, function (error, stdout, stderr) { 218 | //saves pinned hash to Electron App storage 219 | storage.set(pinHash, hashObject, function (error) { 220 | if (error) throw error; 221 | }); 222 | if (error !== null) { 223 | console.log('exec error: ' + error); 224 | } 225 | }) 226 | } 227 | 228 | function getFileData(hash, file) { 229 | return $q(function (resolve, reject) { 230 | let fileCommand = `ipfs cat ${hash}/${file}`; 231 | exec(fileCommand, function (error, stdout, stderr) { 232 | resolve(stdout) 233 | if (error !== null) { 234 | console.log('exec error: ' + error); 235 | } 236 | }) 237 | }) 238 | } 239 | 240 | function saveToDisk(pinHash, username) { 241 | //set save-to directory to a file on user's desktop 242 | let directory = `/Users/${username}/Desktop/ipfs` 243 | let pinSaveCommand = `ipfs get --output="${directory}" ${pinHash}`; 244 | exec(pinSaveCommand, function (error, stdout, stderr) { 245 | if (error !== null) console.log('exec error: ' + error); 246 | //get data from hash for file save 247 | storage.get(pinHash, function (error, data) { 248 | if (error) throw error; 249 | //check if the hash has already been pinned. 250 | if (Object.keys(data).length === 0) { 251 | alert("Please pin before download!"); 252 | return; 253 | } 254 | //initial location and name of saved hash. Default to Desktop 255 | let fileLocation = `${directory}/${pinHash}` 256 | //filename of hash 257 | let filename = data.file 258 | let fileExtension; 259 | //determine and set file extension for saving 260 | if (!filename.includes('.')) { 261 | let buffer = readChunk.sync(fileLocation, 0, 262); 262 | fileExtension = `.${fileType(buffer).ext}`; 263 | } else { 264 | fileExtension = '' 265 | } 266 | //rename file based on filename and extension 267 | fs.rename(fileLocation, `"${directory}/${filename}${fileExtension}"`, function (err) { 268 | if (err) console.log('ERROR: ' + err); 269 | }); 270 | }); 271 | }) 272 | } 273 | 274 | function getPeerID() { 275 | return $q(function (resolve, reject) { 276 | let idCommand = 'ipfs config show'; 277 | exec(idCommand, function (error, stdout, stderr) { 278 | if (error !== null) console.log('exec error: ' + error); 279 | let peerID = JSON.parse(stdout)['Identity']['PeerID']; 280 | let bootstrap = JSON.parse(stdout)['Bootstrap']; 281 | let ipnsLink = `https://gateway.ipfs.io/ipns/${peerID}`; 282 | let peerArray = [ipnsLink, bootstrap] 283 | resolve(peerArray) 284 | }) 285 | }) 286 | } 287 | 288 | function findProviders(hash) { 289 | return $q(function (resolve, reject) { 290 | let provs = `ipfs dht findprovs ${hash}`; 291 | exec(provs, function (error, stdout, stderr) { 292 | if (error !== null) console.log('exec error: ' + error); 293 | resolve(stdout.split('\n')) 294 | }) 295 | }) 296 | } 297 | 298 | function getSettingsInfo() { 299 | return $q(function (resolve, reject) { 300 | getPeerID().then(function (data) { 301 | let idCommand = 'ipfs id'; 302 | exec(idCommand, function (error, stdout, stderr) { 303 | if (error !== null) console.log('exec error: ' + error); 304 | let multiAddr = JSON.parse(stdout)['Addresses'][3]; 305 | let version = JSON.parse(stdout)["ProtocolVersion"].split('/')[1] 306 | data.push(multiAddr, version) 307 | resolve(data) 308 | }) 309 | }) 310 | }) 311 | } 312 | 313 | function addBootstrapPeer(peerAddress) { 314 | return $q(function (resolve, reject) { 315 | let idCommand = `ipfs bootstrap add ${peerAddress}`; 316 | exec(idCommand, function (error, stdout, stderr) { 317 | if (error !== null) console.log('exec error: ' + error); 318 | let success = `peer added` 319 | resolve(success) 320 | }) 321 | }) 322 | } 323 | 324 | return { 325 | findProviders: findProviders, 326 | addPeer: addBootstrapPeer, 327 | getSettingsInfo: getSettingsInfo, 328 | getFileData: getFileData, 329 | rehashProject: rehashProject, 330 | init: startDaemon, 331 | addFile: submitFile, 332 | saveToDisk: saveToDisk, 333 | pin: addPin, 334 | unPin: unPin, 335 | publish: publishHash 336 | } 337 | } -------------------------------------------------------------------------------- /app/.electron/Cache/f_00000c: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o' 43 | } else if (obj.outerHTML) { 44 | return obj.outerHTML 45 | } else if (isNode(obj)) { 46 | return serialize(obj) 47 | } else { 48 | var constructor = 'Object' 49 | if (obj.constructor && typeof obj.constructor === 'function') { 50 | constructor = obj.constructor.name 51 | } 52 | 53 | strs.push(constructor) 54 | strs.push('{') 55 | var first = true 56 | for (var key in obj) { 57 | if (Object.prototype.hasOwnProperty.call(obj, key)) { 58 | if (first) { 59 | first = false 60 | } else { 61 | strs.push(', ') 62 | } 63 | 64 | strs.push(key + ': ' + stringify(obj[key], depth - 1)) 65 | } 66 | } 67 | strs.push('}') 68 | } 69 | return strs.join('') 70 | default: 71 | return obj 72 | } 73 | } 74 | 75 | module.exports = stringify 76 | 77 | },{"./util":2,"dom-serialize":6}],2:[function(require,module,exports){ 78 | exports.instanceOf = function (value, constructorName) { 79 | return Object.prototype.toString.apply(value) === '[object ' + constructorName + ']' 80 | } 81 | 82 | exports.elm = function (id) { 83 | return document.getElementById(id) 84 | } 85 | 86 | exports.generateId = function (prefix) { 87 | return prefix + Math.floor(Math.random() * 10000) 88 | } 89 | 90 | exports.isUndefined = function (value) { 91 | return typeof value === 'undefined' 92 | } 93 | 94 | exports.isDefined = function (value) { 95 | return !exports.isUndefined(value) 96 | } 97 | 98 | exports.parseQueryParams = function (locationSearch) { 99 | var params = {} 100 | var pairs = locationSearch.substr(1).split('&') 101 | var keyValue 102 | 103 | for (var i = 0; i < pairs.length; i++) { 104 | keyValue = pairs[i].split('=') 105 | params[decodeURIComponent(keyValue[0])] = decodeURIComponent(keyValue[1]) 106 | } 107 | 108 | return params 109 | } 110 | 111 | },{}],3:[function(require,module,exports){ 112 | // Load our dependencies 113 | var stringify = require('../common/stringify') 114 | 115 | // Define our context Karma constructor 116 | var ContextKarma = function (callParentKarmaMethod) { 117 | // Define local variables 118 | var hasError = false 119 | var self = this 120 | 121 | // Define our loggers 122 | // DEV: These are intentionally repeated in client and context 123 | this.log = function (type, args) { 124 | var values = [] 125 | 126 | for (var i = 0; i < args.length; i++) { 127 | values.push(this.stringify(args[i], 3)) 128 | } 129 | 130 | this.info({log: values.join(', '), type: type}) 131 | } 132 | 133 | this.stringify = stringify 134 | 135 | // Define our proxy error handler 136 | // DEV: We require one in our context to track `hasError` 137 | this.error = function () { 138 | hasError = true 139 | callParentKarmaMethod('error', [].slice.call(arguments)) 140 | return false 141 | } 142 | 143 | // Define our start handler 144 | var UNIMPLEMENTED_START = function () { 145 | this.error('You need to include some adapter that implements __karma__.start method!') 146 | } 147 | // all files loaded, let's start the execution 148 | this.loaded = function () { 149 | // has error -> cancel 150 | if (!hasError) { 151 | this.start(this.config) 152 | } 153 | 154 | // remove reference to child iframe 155 | this.start = UNIMPLEMENTED_START 156 | } 157 | // supposed to be overriden by the context 158 | // TODO(vojta): support multiple callbacks (queue) 159 | this.start = UNIMPLEMENTED_START 160 | 161 | // Define proxy methods 162 | // DEV: This is a closured `for` loop (same as a `forEach`) for IE support 163 | var proxyMethods = ['complete', 'info', 'result'] 164 | for (var i = 0; i < proxyMethods.length; i++) { 165 | (function bindProxyMethod (methodName) { 166 | self[methodName] = function boundProxyMethod () { 167 | callParentKarmaMethod(methodName, [].slice.call(arguments)) 168 | } 169 | }(proxyMethods[i])) 170 | } 171 | 172 | // Define bindings for context window 173 | this.setupContext = function (contextWindow) { 174 | // If we clear the context after every run and we already had an error 175 | // then stop now. Otherwise, carry on. 176 | if (self.config.clearContext && hasError) { 177 | return 178 | } 179 | 180 | // Perform window level bindings 181 | // DEV: We return `self.error` since we want to `return false` to ignore errors 182 | contextWindow.onerror = function () { 183 | return self.error.apply(self, arguments) 184 | } 185 | // DEV: We must defined a function since we don't want to pass the event object 186 | contextWindow.onbeforeunload = function (e, b) { 187 | callParentKarmaMethod('onbeforeunload', []) 188 | } 189 | 190 | contextWindow.dump = function () { 191 | self.log('dump', arguments) 192 | } 193 | 194 | contextWindow.alert = function (msg) { 195 | self.log('alert', [msg]) 196 | } 197 | 198 | // If we want to overload our console, then do it 199 | var getConsole = function (currentWindow) { 200 | return currentWindow.console || { 201 | log: function () {}, 202 | info: function () {}, 203 | warn: function () {}, 204 | error: function () {}, 205 | debug: function () {} 206 | } 207 | } 208 | if (self.config.captureConsole) { 209 | // patch the console 210 | var localConsole = contextWindow.console = getConsole(contextWindow) 211 | var logMethods = ['log', 'info', 'warn', 'error', 'debug'] 212 | var patchConsoleMethod = function (method) { 213 | var orig = localConsole[method] 214 | if (!orig) { 215 | return 216 | } 217 | localConsole[method] = function () { 218 | self.log(method, arguments) 219 | return Function.prototype.apply.call(orig, localConsole, arguments) 220 | } 221 | } 222 | for (var i = 0; i < logMethods.length; i++) { 223 | patchConsoleMethod(logMethods[i]) 224 | } 225 | } 226 | } 227 | } 228 | 229 | // Define call/proxy methods 230 | ContextKarma.getDirectCallParentKarmaMethod = function (parentWindow) { 231 | return function directCallParentKarmaMethod (method, args) { 232 | // If the method doesn't exist, then error out 233 | if (!parentWindow.karma[method]) { 234 | parentWindow.karma.error('Expected Karma method "' + method + '" to exist but it doesn\'t') 235 | return 236 | } 237 | 238 | // Otherwise, run our method 239 | parentWindow.karma[method].apply(parentWindow.karma, args) 240 | } 241 | } 242 | ContextKarma.getPostMessageCallParentKarmaMethod = function (parentWindow) { 243 | return function postMessageCallParentKarmaMethod (method, args) { 244 | parentWindow.postMessage({__karmaMethod: method, __karmaArguments: args}, window.location.origin) 245 | } 246 | } 247 | 248 | // Export our module 249 | module.exports = ContextKarma 250 | 251 | },{"../common/stringify":1}],4:[function(require,module,exports){ 252 | // Load in our dependencies 253 | var ContextKarma = require('./karma') 254 | 255 | // Resolve our parent window 256 | var parentWindow = window.opener || window.parent 257 | 258 | // Define a remote call method for Karma 259 | var callParentKarmaMethod = ContextKarma.getDirectCallParentKarmaMethod(parentWindow) 260 | 261 | // If we don't have access to the window, then use `postMessage` 262 | // DEV: In Electron, we don't have access to the parent window due to it being in a separate process 263 | // DEV: We avoid using this in Internet Explorer as they only support strings 264 | // http://caniuse.com/#search=postmessage 265 | var haveParentAccess = false 266 | try { haveParentAccess = !!parentWindow.window } catch (err) { /* Ignore errors (likely permisison errors) */ } 267 | if (!haveParentAccess) { 268 | callParentKarmaMethod = ContextKarma.getPostMessageCallParentKarmaMethod(parentWindow) 269 | } 270 | 271 | // Define a window-scoped Karma 272 | window.__karma__ = new ContextKarma(callParentKarmaMethod) 273 | 274 | },{"./karma":3}],5:[function(require,module,exports){ 275 | (function (global){ 276 | 277 | var NativeCustomEvent = global.CustomEvent; 278 | 279 | function useNative () { 280 | try { 281 | var p = new NativeCustomEvent('cat', { detail: { foo: 'bar' } }); 282 | return 'cat' === p.type && 'bar' === p.detail.foo; 283 | } catch (e) { 284 | } 285 | return false; 286 | } 287 | 288 | /** 289 | * Cross-browser `CustomEvent` constructor. 290 | * 291 | * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent.CustomEvent 292 | * 293 | * @public 294 | */ 295 | 296 | module.exports = useNative() ? NativeCustomEvent : 297 | 298 | // IE >= 9 299 | 'function' === typeof document.createEvent ? function CustomEvent (type, params) { 300 | var e = document.createEvent('CustomEvent'); 301 | if (params) { 302 | e.initCustomEvent(type, params.bubbles, params.cancelable, params.detail); 303 | } else { 304 | e.initCustomEvent(type, false, false, void 0); 305 | } 306 | return e; 307 | } : 308 | 309 | // IE <= 8 310 | function CustomEvent (type, params) { 311 | var e = document.createEventObject(); 312 | e.type = type; 313 | if (params) { 314 | e.bubbles = Boolean(params.bubbles); 315 | e.cancelable = Boolean(params.cancelable); 316 | e.detail = params.detail; 317 | } else { 318 | e.bubbles = false; 319 | e.cancelable = false; 320 | e.detail = void 0; 321 | } 322 | return e; 323 | } 324 | 325 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 326 | },{}],6:[function(require,module,exports){ 327 | 328 | /** 329 | * Module dependencies. 330 | */ 331 | 332 | var extend = require('extend'); 333 | var encode = require('ent/encode'); 334 | var CustomEvent = require('custom-event'); 335 | var voidElements = require('void-elements'); 336 | 337 | /** 338 | * Module exports. 339 | */ 340 | 341 | exports = module.exports = serialize; 342 | exports.serializeElement = serializeElement; 343 | exports.serializeAttribute = serializeAttribute; 344 | exports.serializeText = serializeText; 345 | exports.serializeComment = serializeComment; 346 | exports.serializeDocument = serializeDocument; 347 | exports.serializeDoctype = serializeDoctype; 348 | exports.serializeDocumentFragment = serializeDocumentFragment; 349 | exports.serializeNodeList = serializeNodeList; 350 | 351 | /** 352 | * Serializes any DOM node. Returns a string. 353 | * 354 | * @param {Node} node - DOM Node to serialize 355 | * @param {String} [context] - optional arbitrary "context" string to use (useful for event listeners) 356 | * @param {Function} [fn] - optional callback function to use in the "serialize" event for this call 357 | * @param {EventTarget} [eventTarget] - optional EventTarget instance to emit the "serialize" event on (defaults to `node`) 358 | * return {String} 359 | * @public 360 | */ 361 | 362 | function serialize (node, context, fn, eventTarget) { 363 | if (!node) return ''; 364 | if ('function' === typeof context) { 365 | fn = context; 366 | context = null; 367 | } 368 | if (!context) context = null; 369 | 370 | var rtn; 371 | var nodeType = node.nodeType; 372 | 373 | if (!nodeType && 'number' === typeof node.length) { 374 | // assume it's a NodeList or Array of Nodes 375 | rtn = exports.serializeNodeList(node, context, fn); 376 | } else { 377 | 378 | if ('function' === typeof fn) { 379 | // one-time "serialize" event listener 380 | node.addEventListener('serialize', fn, false); 381 | } 382 | 383 | // emit a custom "serialize" event on `node`, in case there 384 | // are event listeners for custom serialization of this node 385 | var e = new CustomEvent('serialize', { 386 | bubbles: true, 387 | cancelable: true, 388 | detail: { 389 | serialize: null, 390 | context: context 391 | } 392 | }); 393 | 394 | e.serializeTarget = node; 395 | 396 | var target = eventTarget || node; 397 | var cancelled = !target.dispatchEvent(e); 398 | 399 | // `e.detail.serialize` can be set to a: 400 | // String - returned directly 401 | // Node - goes through serializer logic instead of `node` 402 | // Anything else - get Stringified first, and then returned directly 403 | var s = e.detail.serialize; 404 | if (s != null) { 405 | if ('string' === typeof s) { 406 | rtn = s; 407 | } else if ('number' === typeof s.nodeType) { 408 | // make it go through the serialization logic 409 | rtn = serialize(s, context, null, target); 410 | } else { 411 | rtn = String(s); 412 | } 413 | } else if (!cancelled) { 414 | // default serialization logic 415 | switch (nodeType) { 416 | case 1 /* element */: 417 | rtn = exports.serializeElement(node, context, eventTarget); 418 | break; 419 | case 2 /* attribute */: 420 | rtn = exports.serializeAttribute(node); 421 | break; 422 | case 3 /* text */: 423 | rtn = exports.serializeText(node); 424 | break; 425 | case 8 /* comment */: 426 | rtn = exports.serializeComment(node); 427 | break; 428 | case 9 /* document */: 429 | rtn = exports.serializeDocument(node, context, eventTarget); 430 | break; 431 | case 10 /* doctype */: 432 | rtn = exports.serializeDoctype(node); 433 | break; 434 | case 11 /* document fragment */: 435 | rtn = exports.serializeDocumentFragment(node, context, eventTarget); 436 | break; 437 | } 438 | } 439 | 440 | if ('function' === typeof fn) { 441 | node.removeEventListener('serialize', fn, false); 442 | } 443 | } 444 | 445 | return rtn || ''; 446 | } 447 | 448 | /** 449 | * Serialize an Attribute node. 450 | */ 451 | 452 | function serializeAttribute (node, opts) { 453 | return node.name + '="' + encode(node.value, extend({ 454 | named: true 455 | }, opts)) + '"'; 456 | } 457 | 458 | /** 459 | * Serialize a DOM element. 460 | */ 461 | 462 | function serializeElement (node, context, eventTarget) { 463 | var c, i, l; 464 | var name = node.nodeName.toLowerCase(); 465 | 466 | // opening tag 467 | var r = '<' + name; 468 | 469 | // attributes 470 | for (i = 0, c = node.attributes, l = c.length; i < l; i++) { 471 | r += ' ' + exports.serializeAttribute(c[i]); 472 | } 473 | 474 | r += '>'; 475 | 476 | // child nodes 477 | r += exports.serializeNodeList(node.childNodes, context, null, eventTarget); 478 | 479 | // closing tag, only for non-void elements 480 | if (!voidElements[name]) { 481 | r += ''; 482 | } 483 | 484 | return r; 485 | } 486 | 487 | /** 488 | * Serialize a text node. 489 | */ 490 | 491 | function serializeText (node, opts) { 492 | return encode(node.nodeValue, extend({ 493 | named: true, 494 | special: { '<': true, '>': true, '&': true } 495 | }, opts)); 496 | } 497 | 498 | /** 499 | * Serialize a comment node. 500 | */ 501 | 502 | function serializeComment (node) { 503 | return ''; 504 | } 505 | 506 | /** 507 | * Serialize a Document node. 508 | */ 509 | 510 | function serializeDocument (node, context, eventTarget) { 511 | return exports.serializeNodeList(node.childNodes, context, null, eventTarget); 512 | } 513 | 514 | /** 515 | * Serialize a DOCTYPE node. 516 | * See: http://stackoverflow.com/a/10162353 517 | */ 518 | 519 | function serializeDoctype (node) { 520 | var r = ''; 535 | return r; 536 | } 537 | 538 | /** 539 | * Serialize a DocumentFragment instance. 540 | */ 541 | 542 | function serializeDocumentFragment (node, context, eventTarget) { 543 | return exports.serializeNodeList(node.childNodes, context, null, eventTarget); 544 | } 545 | 546 | /** 547 | * Serialize a NodeList/Array of nodes. 548 | */ 549 | 550 | function serializeNodeList (list, context, fn, eventTarget) { 551 | var r = ''; 552 | for (var i = 0, l = list.length; i < l; i++) { 553 | r += serialize(list[i], context, fn, eventTarget); 554 | } 555 | return r; 556 | } 557 | 558 | },{"custom-event":5,"ent/encode":7,"extend":9,"void-elements":11}],7:[function(require,module,exports){ 559 | var punycode = require('punycode'); 560 | var revEntities = require('./reversed.json'); 561 | 562 | module.exports = encode; 563 | 564 | function encode (str, opts) { 565 | if (typeof str !== 'string') { 566 | throw new TypeError('Expected a String'); 567 | } 568 | if (!opts) opts = {}; 569 | 570 | var numeric = true; 571 | if (opts.named) numeric = false; 572 | if (opts.numeric !== undefined) numeric = opts.numeric; 573 | 574 | var special = opts.special || { 575 | '"': true, "'": true, 576 | '<': true, '>': true, 577 | '&': true 578 | }; 579 | 580 | var codePoints = punycode.ucs2.decode(str); 581 | var chars = []; 582 | for (var i = 0; i < codePoints.length; i++) { 583 | var cc = codePoints[i]; 584 | var c = punycode.ucs2.encode([ cc ]); 585 | var e = revEntities[cc]; 586 | if (e && (cc >= 127 || special[c]) && !numeric) { 587 | chars.push('&' + (/;$/.test(e) ? e : e + ';')); 588 | } 589 | else if (cc < 32 || cc >= 127 || special[c]) { 590 | chars.push('&#' + cc + ';'); 591 | } 592 | else { 593 | chars.push(c); 594 | } 595 | } 596 | return chars.join(''); 597 | } 598 | 599 | },{"./reversed.json":8,"punycode":10}],8:[function(require,module,exports){ 600 | module.exports={ 601 | "9": "Tab;", 602 | "10": "NewLine;", 603 | "33": "excl;", 604 | "34": "quot;", 605 | "35": "num;", 606 | "36": "dollar;", 607 | "37": "percnt;", 608 | "38": "amp;", 609 | "39": "apos;", 610 | "40": "lpar;", 611 | "41": "rpar;", 612 | "42": "midast;", 613 | "43": "plus;", 614 | "44": "comma;", 615 | "46": "period;", 616 | "47": "sol;", 617 | "58": "colon;", 618 | "59": "semi;", 619 | "60": "lt;", 620 | "61": "equals;", 621 | "62": "gt;", 622 | "63": "quest;", 623 | "64": "commat;", 624 | "91": "lsqb;", 625 | "92": "bsol;", 626 | "93": "rsqb;", 627 | "94": "Hat;", 628 | "95": "UnderBar;", 629 | "96": "grave;", 630 | "123": "lcub;", 631 | "124": "VerticalLine;", 632 | "125": "rcub;", 633 | "160": "NonBreakingSpace;", 634 | "161": "iexcl;", 635 | "162": "cent;", 636 | "163": "pound;", 637 | "164": "curren;", 638 | "165": "yen;", 639 | "166": "brvbar;", 640 | "167": "sect;", 641 | "168": "uml;", 642 | "169": "copy;", 643 | "170": "ordf;", 644 | "171": "laquo;", 645 | "172": "not;", 646 | "173": "shy;", 647 | "174": "reg;", 648 | "175": "strns;", 649 | "176": "deg;", 650 | "177": "pm;", 651 | "178": "sup2;", 652 | "179": "sup3;", 653 | "180": "DiacriticalAcute;", 654 | "181": "micro;", 655 | "182": "para;", 656 | "183": "middot;", 657 | "184": "Cedilla;", 658 | "185": "sup1;", 659 | "186": "ordm;", 660 | "187": "raquo;", 661 | "188": "frac14;", 662 | "189": "half;", 663 | "190": "frac34;", 664 | "191": "iquest;", 665 | "192": "Agrave;", 666 | "193": "Aacute;", 667 | "194": "Acirc;", 668 | "195": "Atilde;", 669 | "196": "Auml;", 670 | "197": "Aring;", 671 | "198": "AElig;", 672 | "199": "Ccedil;", 673 | "200": "Egrave;", 674 | "201": "Eacute;", 675 | "202": "Ecirc;", 676 | "203": "Euml;", 677 | "204": "Igrave;", 678 | "205": "Iacute;", 679 | "206": "Icirc;", 680 | "207": "Iuml;", 681 | "208": "ETH;", 682 | "209": "Ntilde;", 683 | "210": "Ograve;", 684 | "211": "Oacute;", 685 | "212": "Ocirc;", 686 | "213": "Otilde;", 687 | "214": "Ouml;", 688 | "215": "times;", 689 | "216": "Oslash;", 690 | "217": "Ugrave;", 691 | "218": "Uacute;", 692 | "219": "Ucirc;", 693 | "220": "Uuml;", 694 | "221": "Yacute;", 695 | "222": "THORN;", 696 | "223": "szlig;", 697 | "224": "agrave;", 698 | "225": "aacute;", 699 | "226": "acirc;", 700 | "227": "atilde;", 701 | "228": "auml;", 702 | "229": "aring;", 703 | "230": "aelig;", 704 | "231": "ccedil;", 705 | "232": "egrave;", 706 | "233": "eacute;", 707 | "234": "ecirc;", 708 | "235": "euml;", 709 | "236": "igrave;", 710 | "237": "iacute;", 711 | "238": "icirc;", 712 | "239": "iuml;", 713 | "240": "eth;", 714 | "241": "ntilde;", 715 | "242": "ograve;", 716 | "243": "oacute;", 717 | "244": "ocirc;", 718 | "245": "otilde;", 719 | "246": "ouml;", 720 | "247": "divide;", 721 | "248": "oslash;", 722 | "249": "ugrave;", 723 | "250": "uacute;", 724 | "251": "ucirc;", 725 | "252": "uuml;", 726 | "253": "yacute;", 727 | "254": "thorn;", 728 | "255": "yuml;", 729 | "256": "Amacr;", 730 | "257": "amacr;", 731 | "258": "Abreve;", 732 | "259": "abreve;", 733 | "260": "Aogon;", 734 | "261": "aogon;", 735 | "262": "Cacute;", 736 | "263": "cacute;", 737 | "264": "Ccirc;", 738 | "265": "ccirc;", 739 | "266": "Cdot;", 740 | "267": "cdot;", 741 | "268": "Ccaron;", 742 | "269": "ccaron;", 743 | "270": "Dcaron;", 744 | "271": "dcaron;", 745 | "272": "Dstrok;", 746 | "273": "dstrok;", 747 | "274": "Emacr;", 748 | "275": "emacr;", 749 | "278": "Edot;", 750 | "279": "edot;", 751 | "280": "Eogon;", 752 | "281": "eogon;", 753 | "282": "Ecaron;", 754 | "283": "ecaron;", 755 | "284": "Gcirc;", 756 | "285": "gcirc;", 757 | "286": "Gbreve;", 758 | "287": "gbreve;", 759 | "288": "Gdot;", 760 | "289": "gdot;", 761 | "290": "Gcedil;", 762 | "292": "Hcirc;", 763 | "293": "hcirc;", 764 | "294": "Hstrok;", 765 | "295": "hstrok;", 766 | "296": "Itilde;", 767 | "297": "itilde;", 768 | "298": "Imacr;", 769 | "299": "imacr;", 770 | "302": "Iogon;", 771 | "303": "iogon;", 772 | "304": "Idot;", 773 | "305": "inodot;", 774 | "306": "IJlig;", 775 | "307": "ijlig;", 776 | "308": "Jcirc;", 777 | "309": "jcirc;", 778 | "310": "Kcedil;", 779 | "311": "kcedil;", 780 | "312": "kgreen;", 781 | "313": "Lacute;", 782 | "314": "lacute;", 783 | "315": "Lcedil;", 784 | "316": "lcedil;", 785 | "317": "Lcaron;", 786 | "318": "lcaron;", 787 | "319": "Lmidot;", 788 | "320": "lmidot;", 789 | "321": "Lstrok;", 790 | "322": "lstrok;", 791 | "323": "Nacute;", 792 | "324": "nacute;", 793 | "325": "Ncedil;", 794 | "326": "ncedil;", 795 | "327": "Ncaron;", 796 | "328": "ncaron;", 797 | "329": "napos;", 798 | "330": "ENG;", 799 | "331": "eng;", 800 | "332": "Omacr;", 801 | "333": "omacr;", 802 | "336": "Odblac;", 803 | "337": "odblac;", 804 | "338": "OElig;", 805 | "339": "oelig;", 806 | "340": "Racute;", 807 | "341": "racute;", 808 | "342": "Rcedil;", 809 | "343": "rcedil;", 810 | "344": "Rcaron;", 811 | "345": "rcaron;", 812 | "346": "Sacute;", 813 | "347": "sacute;", 814 | "348": "Scirc;", 815 | "349": "scirc;", 816 | "350": "Scedil;", 817 | "351": "scedil;", 818 | "352": "Scaron;", 819 | "353": "scaron;", 820 | "354": "Tcedil;", 821 | "355": "tcedil;", 822 | "356": "Tcaron;", 823 | "357": "tcaron;", 824 | "358": "Tstrok;", 825 | "359": "tstrok;", 826 | "360": "Utilde;", 827 | "361": "utilde;", 828 | "362": "Umacr;", 829 | "363": "umacr;", 830 | "364": "Ubreve;", 831 | "365": "ubreve;", 832 | "366": "Uring;", 833 | "367": "uring;", 834 | "368": "Udblac;", 835 | "369": "udblac;", 836 | "370": "Uogon;", 837 | "371": "uogon;", 838 | "372": "Wcirc;", 839 | "373": "wcirc;", 840 | "374": "Ycirc;", 841 | "375": "ycirc;", 842 | "376": "Yuml;", 843 | "377": "Zacute;", 844 | "378": "zacute;", 845 | "379": "Zdot;", 846 | "380": "zdot;", 847 | "381": "Zcaron;", 848 | "382": "zcaron;", 849 | "402": "fnof;", 850 | "437": "imped;", 851 | "501": "gacute;", 852 | "567": "jmath;", 853 | "710": "circ;", 854 | "711": "Hacek;", 855 | "728": "breve;", 856 | "729": "dot;", 857 | "730": "ring;", 858 | "731": "ogon;", 859 | "732": "tilde;", 860 | "733": "DiacriticalDoubleAcute;", 861 | "785": "DownBreve;", 862 | "913": "Alpha;", 863 | "914": "Beta;", 864 | "915": "Gamma;", 865 | "916": "Delta;", 866 | "917": "Epsilon;", 867 | "918": "Zeta;", 868 | "919": "Eta;", 869 | "920": "Theta;", 870 | "921": "Iota;", 871 | "922": "Kappa;", 872 | "923": "Lambda;", 873 | "924": "Mu;", 874 | "925": "Nu;", 875 | "926": "Xi;", 876 | "927": "Omicron;", 877 | "928": "Pi;", 878 | "929": "Rho;", 879 | "931": "Sigma;", 880 | "932": "Tau;", 881 | "933": "Upsilon;", 882 | "934": "Phi;", 883 | "935": "Chi;", 884 | "936": "Psi;", 885 | "937": "Omega;", 886 | "945": "alpha;", 887 | "946": "beta;", 888 | "947": "gamma;", 889 | "948": "delta;", 890 | "949": "epsilon;", 891 | "950": "zeta;", 892 | "951": "eta;", 893 | "952": "theta;", 894 | "953": "iota;", 895 | "954": "kappa;", 896 | "955": "lambda;", 897 | "956": "mu;", 898 | "957": "nu;", 899 | "958": "xi;", 900 | "959": "omicron;", 901 | "960": "pi;", 902 | "961": "rho;", 903 | "962": "varsigma;", 904 | "963": "sigma;", 905 | "964": "tau;", 906 | "965": "upsilon;", 907 | "966": "phi;", 908 | "967": "chi;", 909 | "968": "psi;", 910 | "969": "omega;", 911 | "977": "vartheta;", 912 | "978": "upsih;", 913 | "981": "varphi;", 914 | "982": "varpi;", 915 | "988": "Gammad;", 916 | "989": "gammad;", 917 | "1008": "varkappa;", 918 | "1009": "varrho;", 919 | "1013": "varepsilon;", 920 | "1014": "bepsi;", 921 | "1025": "IOcy;", 922 | "1026": "DJcy;", 923 | "1027": "GJcy;", 924 | "1028": "Jukcy;", 925 | "1029": "DScy;", 926 | "1030": "Iukcy;", 927 | "1031": "YIcy;", 928 | "1032": "Jsercy;", 929 | "1033": "LJcy;", 930 | "1034": "NJcy;", 931 | "1035": "TSHcy;", 932 | "1036": "KJcy;", 933 | "1038": "Ubrcy;", 934 | "1039": "DZcy;", 935 | "1040": "Acy;", 936 | "1041": "Bcy;", 937 | "1042": "Vcy;", 938 | "1043": "Gcy;", 939 | "1044": "Dcy;", 940 | "1045": "IEcy;", 941 | "1046": "ZHcy;", 942 | "1047": "Zcy;", 943 | "1048": "Icy;", 944 | "1049": "Jcy;", 945 | "1050": "Kcy;", 946 | "1051": "Lcy;", 947 | "1052": "Mcy;", 948 | "1053": "Ncy;", 949 | "1054": "Ocy;", 950 | "1055": "Pcy;", 951 | "1056": "Rcy;", 952 | "1057": "Scy;", 953 | "1058": "Tcy;", 954 | "1059": "Ucy;", 955 | "1060": "Fcy;", 956 | "1061": "KHcy;", 957 | "1062": "TScy;", 958 | "1063": "CHcy;", 959 | "1064": "SHcy;", 960 | "1065": "SHCHcy;", 961 | "1066": "HARDcy;", 962 | "1067": "Ycy;", 963 | "1068": "SOFTcy;", 964 | "1069": "Ecy;", 965 | "1070": "YUcy;", 966 | "1071": "YAcy;", 967 | "1072": "acy;", 968 | "1073": "bcy;", 969 | "1074": "vcy;", 970 | "1075": "gcy;", 971 | "1076": "dcy;", 972 | "1077": "iecy;", 973 | "1078": "zhcy;", 974 | "1079": "zcy;", 975 | "1080": "icy;", 976 | "1081": "jcy;", 977 | "1082": "kcy;", 978 | "1083": "lcy;", 979 | "1084": "mcy;", 980 | "1085": "ncy;", 981 | "1086": "ocy;", 982 | "1087": "pcy;", 983 | "1088": "rcy;", 984 | "1089": "scy;", 985 | "1090": "tcy;", 986 | "1091": "ucy;", 987 | "1092": "fcy;", 988 | "1093": "khcy;", 989 | "1094": "tscy;", 990 | "1095": "chcy;", 991 | "1096": "shcy;", 992 | "1097": "shchcy;", 993 | "1098": "hardcy;", 994 | "1099": "ycy;", 995 | "1100": "softcy;", 996 | "1101": "ecy;", 997 | "1102": "yucy;", 998 | "1103": "yacy;", 999 | "1105": "iocy;", 1000 | "1106": "djcy;", 1001 | "1107": "gjcy;", 1002 | "1108": "jukcy;", 1003 | "1109": "dscy;", 1004 | "1110": "iukcy;", 1005 | "1111": "yicy;", 1006 | "1112": "jsercy;", 1007 | "1113": "ljcy;", 1008 | "1114": "njcy;", 1009 | "1115": "tshcy;", 1010 | "1116": "kjcy;", 1011 | "1118": "ubrcy;", 1012 | "1119": "dzcy;", 1013 | "8194": "ensp;", 1014 | "8195": "emsp;", 1015 | "8196": "emsp13;", 1016 | "8197": "emsp14;", 1017 | "8199": "numsp;", 1018 | "8200": "puncsp;", 1019 | "8201": "ThinSpace;", 1020 | "8202": "VeryThinSpace;", 1021 | "8203": "ZeroWidthSpace;", 1022 | "8204": "zwnj;", 1023 | "8205": "zwj;", 1024 | "8206": "lrm;", 1025 | "8207": "rlm;", 1026 | "8208": "hyphen;", 1027 | "8211": "ndash;", 1028 | "8212": "mdash;", 1029 | "8213": "horbar;", 1030 | "8214": "Vert;", 1031 | "8216": "OpenCurlyQuote;", 1032 | "8217": "rsquor;", 1033 | "8218": "sbquo;", 1034 | "8220": "OpenCurlyDoubleQuote;", 1035 | "8221": "rdquor;", 1036 | "8222": "ldquor;", 1037 | "8224": "dagger;", 1038 | "8225": "ddagger;", 1039 | "8226": "bullet;", 1040 | "8229": "nldr;", 1041 | "8230": "mldr;", 1042 | "8240": "permil;", 1043 | "8241": "pertenk;", 1044 | "8242": "prime;", 1045 | "8243": "Prime;", 1046 | "8244": "tprime;", 1047 | "8245": "bprime;", 1048 | "8249": "lsaquo;", 1049 | "8250": "rsaquo;", 1050 | "8254": "OverBar;", 1051 | "8257": "caret;", 1052 | "8259": "hybull;", 1053 | "8260": "frasl;", 1054 | "8271": "bsemi;", 1055 | "8279": "qprime;", 1056 | "8287": "MediumSpace;", 1057 | "8288": "NoBreak;", 1058 | "8289": "ApplyFunction;", 1059 | "8290": "it;", 1060 | "8291": "InvisibleComma;", 1061 | "8364": "euro;", 1062 | "8411": "TripleDot;", 1063 | "8412": "DotDot;", 1064 | "8450": "Copf;", 1065 | "8453": "incare;", 1066 | "8458": "gscr;", 1067 | "8459": "Hscr;", 1068 | "8460": "Poincareplane;", 1069 | "8461": "quaternions;", 1070 | "8462": "planckh;", 1071 | "8463": "plankv;", 1072 | "8464": "Iscr;", 1073 | "8465": "imagpart;", 1074 | "8466": "Lscr;", 1075 | "8467": "ell;", 1076 | "8469": "Nopf;", 1077 | "8470": "numero;", 1078 | "8471": "copysr;", 1079 | "8472": "wp;", 1080 | "8473": "primes;", 1081 | "8474": "rationals;", 1082 | "8475": "Rscr;", 1083 | "8476": "Rfr;", 1084 | "8477": "Ropf;", 1085 | "8478": "rx;", 1086 | "8482": "trade;", 1087 | "8484": "Zopf;", 1088 | "8487": "mho;", 1089 | "8488": "Zfr;", 1090 | "8489": "iiota;", 1091 | "8492": "Bscr;", 1092 | "8493": "Cfr;", 1093 | "8495": "escr;", 1094 | "8496": "expectation;", 1095 | "8497": "Fscr;", 1096 | "8499": "phmmat;", 1097 | "8500": "oscr;", 1098 | "8501": "aleph;", 1099 | "8502": "beth;", 1100 | "8503": "gimel;", 1101 | "8504": "daleth;", 1102 | "8517": "DD;", 1103 | "8518": "DifferentialD;", 1104 | "8519": "exponentiale;", 1105 | "8520": "ImaginaryI;", 1106 | "8531": "frac13;", 1107 | "8532": "frac23;", 1108 | "8533": "frac15;", 1109 | "8534": "frac25;", 1110 | "8535": "frac35;", 1111 | "8536": "frac45;", 1112 | "8537": "frac16;", 1113 | "8538": "frac56;", 1114 | "8539": "frac18;", 1115 | "8540": "frac38;", 1116 | "8541": "frac58;", 1117 | "8542": "frac78;", 1118 | "8592": "slarr;", 1119 | "8593": "uparrow;", 1120 | "8594": "srarr;", 1121 | "8595": "ShortDownArrow;", 1122 | "8596": "leftrightarrow;", 1123 | "8597": "varr;", 1124 | "8598": "UpperLeftArrow;", 1125 | "8599": "UpperRightArrow;", 1126 | "8600": "searrow;", 1127 | "8601": "swarrow;", 1128 | "8602": "nleftarrow;", 1129 | "8603": "nrightarrow;", 1130 | "8605": "rightsquigarrow;", 1131 | "8606": "twoheadleftarrow;", 1132 | "8607": "Uarr;", 1133 | "8608": "twoheadrightarrow;", 1134 | "8609": "Darr;", 1135 | "8610": "leftarrowtail;", 1136 | "8611": "rightarrowtail;", 1137 | "8612": "mapstoleft;", 1138 | "8613": "UpTeeArrow;", 1139 | "8614": "RightTeeArrow;", 1140 | "8615": "mapstodown;", 1141 | "8617": "larrhk;", 1142 | "8618": "rarrhk;", 1143 | "8619": "looparrowleft;", 1144 | "8620": "rarrlp;", 1145 | "8621": "leftrightsquigarrow;", 1146 | "8622": "nleftrightarrow;", 1147 | "8624": "lsh;", 1148 | "8625": "rsh;", 1149 | "8626": "ldsh;", 1150 | "8627": "rdsh;", 1151 | "8629": "crarr;", 1152 | "8630": "curvearrowleft;", 1153 | "8631": "curvearrowright;", 1154 | "8634": "olarr;", 1155 | "8635": "orarr;", 1156 | "8636": "lharu;", 1157 | "8637": "lhard;", 1158 | "8638": "upharpoonright;", 1159 | "8639": "upharpoonleft;", 1160 | "8640": "RightVector;", 1161 | "8641": "rightharpoondown;", 1162 | "8642": "RightDownVector;", 1163 | "8643": "LeftDownVector;", 1164 | "8644": "rlarr;", 1165 | "8645": "UpArrowDownArrow;", 1166 | "8646": "lrarr;", 1167 | "8647": "llarr;", 1168 | "8648": "uuarr;", 1169 | "8649": "rrarr;", 1170 | "8650": "downdownarrows;", 1171 | "8651": "ReverseEquilibrium;", 1172 | "8652": "rlhar;", 1173 | "8653": "nLeftarrow;", 1174 | "8654": "nLeftrightarrow;", 1175 | "8655": "nRightarrow;", 1176 | "8656": "Leftarrow;", 1177 | "8657": "Uparrow;", 1178 | "8658": "Rightarrow;", 1179 | "8659": "Downarrow;", 1180 | "8660": "Leftrightarrow;", 1181 | "8661": "vArr;", 1182 | "8662": "nwArr;", 1183 | "8663": "neArr;", 1184 | "8664": "seArr;", 1185 | "8665": "swArr;", 1186 | "8666": "Lleftarrow;", 1187 | "8667": "Rrightarrow;", 1188 | "8669": "zigrarr;", 1189 | "8676": "LeftArrowBar;", 1190 | "8677": "RightArrowBar;", 1191 | "8693": "duarr;", 1192 | "8701": "loarr;", 1193 | "8702": "roarr;", 1194 | "8703": "hoarr;", 1195 | "8704": "forall;", 1196 | "8705": "complement;", 1197 | "8706": "PartialD;", 1198 | "8707": "Exists;", 1199 | "8708": "NotExists;", 1200 | "8709": "varnothing;", 1201 | "8711": "nabla;", 1202 | "8712": "isinv;", 1203 | "8713": "notinva;", 1204 | "8715": "SuchThat;", 1205 | "8716": "NotReverseElement;", 1206 | "8719": "Product;", 1207 | "8720": "Coproduct;", 1208 | "8721": "sum;", 1209 | "8722": "minus;", 1210 | "8723": "mp;", 1211 | "8724": "plusdo;", 1212 | "8726": "ssetmn;", 1213 | "8727": "lowast;", 1214 | "8728": "SmallCircle;", 1215 | "8730": "Sqrt;", 1216 | "8733": "vprop;", 1217 | "8734": "infin;", 1218 | "8735": "angrt;", 1219 | "8736": "angle;", 1220 | "8737": "measuredangle;", 1221 | "8738": "angsph;", 1222 | "8739": "VerticalBar;", 1223 | "8740": "nsmid;", 1224 | "8741": "spar;", 1225 | "8742": "nspar;", 1226 | "8743": "wedge;", 1227 | "8744": "vee;", 1228 | "8745": "cap;", 1229 | "8746": "cup;", 1230 | "8747": "Integral;", 1231 | "8748": "Int;", 1232 | "8749": "tint;", 1233 | "8750": "oint;", 1234 | "8751": "DoubleContourIntegral;", 1235 | "8752": "Cconint;", 1236 | "8753": "cwint;", 1237 | "8754": "cwconint;", 1238 | "8755": "CounterClockwiseContourIntegral;", 1239 | "8756": "therefore;", 1240 | "8757": "because;", 1241 | "8758": "ratio;", 1242 | "8759": "Proportion;", 1243 | "8760": "minusd;", 1244 | "8762": "mDDot;", 1245 | "8763": "homtht;", 1246 | "8764": "Tilde;", 1247 | "8765": "bsim;", 1248 | "8766": "mstpos;", 1249 | "8767": "acd;", 1250 | "8768": "wreath;", 1251 | "8769": "nsim;", 1252 | "8770": "esim;", 1253 | "8771": "TildeEqual;", 1254 | "8772": "nsimeq;", 1255 | "8773": "TildeFullEqual;", 1256 | "8774": "simne;", 1257 | "8775": "NotTildeFullEqual;", 1258 | "8776": "TildeTilde;", 1259 | "8777": "NotTildeTilde;", 1260 | "8778": "approxeq;", 1261 | "8779": "apid;", 1262 | "8780": "bcong;", 1263 | "8781": "CupCap;", 1264 | "8782": "HumpDownHump;", 1265 | "8783": "HumpEqual;", 1266 | "8784": "esdot;", 1267 | "8785": "eDot;", 1268 | "8786": "fallingdotseq;", 1269 | "8787": "risingdotseq;", 1270 | "8788": "coloneq;", 1271 | "8789": "eqcolon;", 1272 | "8790": "eqcirc;", 1273 | "8791": "cire;", 1274 | "8793": "wedgeq;", 1275 | "8794": "veeeq;", 1276 | "8796": "trie;", 1277 | "8799": "questeq;", 1278 | "8800": "NotEqual;", 1279 | "8801": "equiv;", 1280 | "8802": "NotCongruent;", 1281 | "8804": "leq;", 1282 | "8805": "GreaterEqual;", 1283 | "8806": "LessFullEqual;", 1284 | "8807": "GreaterFullEqual;", 1285 | "8808": "lneqq;", 1286 | "8809": "gneqq;", 1287 | "8810": "NestedLessLess;", 1288 | "8811": "NestedGreaterGreater;", 1289 | "8812": "twixt;", 1290 | "8813": "NotCupCap;", 1291 | "8814": "NotLess;", 1292 | "8815": "NotGreater;", 1293 | "8816": "NotLessEqual;", 1294 | "8817": "NotGreaterEqual;", 1295 | "8818": "lsim;", 1296 | "8819": "gtrsim;", 1297 | "8820": "NotLessTilde;", 1298 | "8821": "NotGreaterTilde;", 1299 | "8822": "lg;", 1300 | "8823": "gtrless;", 1301 | "8824": "ntlg;", 1302 | "8825": "ntgl;", 1303 | "8826": "Precedes;", 1304 | "8827": "Succeeds;", 1305 | "8828": "PrecedesSlantEqual;", 1306 | "8829": "SucceedsSlantEqual;", 1307 | "8830": "prsim;", 1308 | "8831": "succsim;", 1309 | "8832": "nprec;", 1310 | "8833": "nsucc;", 1311 | "8834": "subset;", 1312 | "8835": "supset;", 1313 | "8836": "nsub;", 1314 | "8837": "nsup;", 1315 | "8838": "SubsetEqual;", 1316 | "8839": "supseteq;", 1317 | "8840": "nsubseteq;", 1318 | "8841": "nsupseteq;", 1319 | "8842": "subsetneq;", 1320 | "8843": "supsetneq;", 1321 | "8845": "cupdot;", 1322 | "8846": "uplus;", 1323 | "8847": "SquareSubset;", 1324 | "8848": "SquareSuperset;", 1325 | "8849": "SquareSubsetEqual;", 1326 | "8850": "SquareSupersetEqual;", 1327 | "8851": "SquareIntersection;", 1328 | "8852": "SquareUnion;", 1329 | "8853": "oplus;", 1330 | "8854": "ominus;", 1331 | "8855": "otimes;", 1332 | "8856": "osol;", 1333 | "8857": "odot;", 1334 | "8858": "ocir;", 1335 | "8859": "oast;", 1336 | "8861": "odash;", 1337 | "8862": "plusb;", 1338 | "8863": "minusb;", 1339 | "8864": "timesb;", 1340 | "8865": "sdotb;", 1341 | "8866": "vdash;", 1342 | "8867": "LeftTee;", 1343 | "8868": "top;", 1344 | "8869": "UpTee;", 1345 | "8871": "models;", 1346 | "8872": "vDash;", 1347 | "8873": "Vdash;", 1348 | "8874": "Vvdash;", 1349 | "8875": "VDash;", 1350 | "8876": "nvdash;", 1351 | "8877": "nvDash;", 1352 | "8878": "nVdash;", 1353 | "8879": "nVDash;", 1354 | "8880": "prurel;", 1355 | "8882": "vltri;", 1356 | "8883": "vrtri;", 1357 | "8884": "trianglelefteq;", 1358 | "8885": "trianglerighteq;", 1359 | "8886": "origof;", 1360 | "8887": "imof;", 1361 | "8888": "mumap;", 1362 | "8889": "hercon;", 1363 | "8890": "intercal;", 1364 | "8891": "veebar;", 1365 | "8893": "barvee;", 1366 | "8894": "angrtvb;", 1367 | "8895": "lrtri;", 1368 | "8896": "xwedge;", 1369 | "8897": "xvee;", 1370 | "8898": "xcap;", 1371 | "8899": "xcup;", 1372 | "8900": "diamond;", 1373 | "8901": "sdot;", 1374 | "8902": "Star;", 1375 | "8903": "divonx;", 1376 | "8904": "bowtie;", 1377 | "8905": "ltimes;", 1378 | "8906": "rtimes;", 1379 | "8907": "lthree;", 1380 | "8908": "rthree;", 1381 | "8909": "bsime;", 1382 | "8910": "cuvee;", 1383 | "8911": "cuwed;", 1384 | "8912": "Subset;", 1385 | "8913": "Supset;", 1386 | "8914": "Cap;", 1387 | "8915": "Cup;", 1388 | "8916": "pitchfork;", 1389 | "8917": "epar;", 1390 | "8918": "ltdot;", 1391 | "8919": "gtrdot;", 1392 | "8920": "Ll;", 1393 | "8921": "ggg;", 1394 | "8922": "LessEqualGreater;", 1395 | "8923": "gtreqless;", 1396 | "8926": "curlyeqprec;", 1397 | "8927": "curlyeqsucc;", 1398 | "8928": "nprcue;", 1399 | "8929": "nsccue;", 1400 | "8930": "nsqsube;", 1401 | "8931": "nsqsupe;", 1402 | "8934": "lnsim;", 1403 | "8935": "gnsim;", 1404 | "8936": "prnsim;", 1405 | "8937": "succnsim;", 1406 | "8938": "ntriangleleft;", 1407 | "8939": "ntriangleright;", 1408 | "8940": "ntrianglelefteq;", 1409 | "8941": "ntrianglerighteq;", 1410 | "8942": "vellip;", 1411 | "8943": "ctdot;", 1412 | "8944": "utdot;", 1413 | "8945": "dtdot;", 1414 | "8946": "disin;", 1415 | "8947": "isinsv;", 1416 | "8948": "isins;", 1417 | "8949": "isindot;", 1418 | "8950": "notinvc;", 1419 | "8951": "notinvb;", 1420 | "8953": "isinE;", 1421 | "8954": "nisd;", 1422 | "8955": "xnis;", 1423 | "8956": "nis;", 1424 | "8957": "notnivc;", 1425 | "8958": "notnivb;", 1426 | "8965": "barwedge;", 1427 | "8966": "doublebarwedge;", 1428 | "8968": "LeftCeiling;", 1429 | "8969": "RightCeiling;", 1430 | "8970": "lfloor;", 1431 | "8971": "RightFloor;", 1432 | "8972": "drcrop;", 1433 | "8973": "dlcrop;", 1434 | "8974": "urcrop;", 1435 | "8975": "ulcrop;", 1436 | "8976": "bnot;", 1437 | "8978": "profline;", 1438 | "8979": "profsurf;", 1439 | "8981": "telrec;", 1440 | "8982": "target;", 1441 | "8988": "ulcorner;", 1442 | "8989": "urcorner;", 1443 | "8990": "llcorner;", 1444 | "8991": "lrcorner;", 1445 | "8994": "sfrown;", 1446 | "8995": "ssmile;", 1447 | "9005": "cylcty;", 1448 | "9006": "profalar;", 1449 | "9014": "topbot;", 1450 | "9021": "ovbar;", 1451 | "9023": "solbar;", 1452 | "9084": "angzarr;", 1453 | "9136": "lmoustache;", 1454 | "9137": "rmoustache;", 1455 | "9140": "tbrk;", 1456 | "9141": "UnderBracket;", 1457 | "9142": "bbrktbrk;", 1458 | "9180": "OverParenthesis;", 1459 | "9181": "UnderParenthesis;", 1460 | "9182": "OverBrace;", 1461 | "9183": "UnderBrace;", 1462 | "9186": "trpezium;", 1463 | "9191": "elinters;", 1464 | "9251": "blank;", 1465 | "9416": "oS;", 1466 | "9472": "HorizontalLine;", 1467 | "9474": "boxv;", 1468 | "9484": "boxdr;", 1469 | "9488": "boxdl;", 1470 | "9492": "boxur;", 1471 | "9496": "boxul;", 1472 | "9500": "boxvr;", 1473 | "9508": "boxvl;", 1474 | "9516": "boxhd;", 1475 | "9524": "boxhu;", 1476 | "9532": "boxvh;", 1477 | "9552": "boxH;", 1478 | "9553": "boxV;", 1479 | "9554": "boxdR;", 1480 | "9555": "boxDr;", 1481 | "9556": "boxDR;", 1482 | "9557": "boxdL;", 1483 | "9558": "boxDl;", 1484 | "9559": "boxDL;", 1485 | "9560": "boxuR;", 1486 | "9561": "boxUr;", 1487 | "9562": "boxUR;", 1488 | "9563": "boxuL;", 1489 | "9564": "boxUl;", 1490 | "9565": "boxUL;", 1491 | "9566": "boxvR;", 1492 | "9567": "boxVr;", 1493 | "9568": "boxVR;", 1494 | "9569": "boxvL;", 1495 | "9570": "boxVl;", 1496 | "9571": "boxVL;", 1497 | "9572": "boxHd;", 1498 | "9573": "boxhD;", 1499 | "9574": "boxHD;", 1500 | "9575": "boxHu;", 1501 | "9576": "boxhU;", 1502 | "9577": "boxHU;", 1503 | "9578": "boxvH;", 1504 | "9579": "boxVh;", 1505 | "9580": "boxVH;", 1506 | "9600": "uhblk;", 1507 | "9604": "lhblk;", 1508 | "9608": "block;", 1509 | "9617": "blk14;", 1510 | "9618": "blk12;", 1511 | "9619": "blk34;", 1512 | "9633": "square;", 1513 | "9642": "squf;", 1514 | "9643": "EmptyVerySmallSquare;", 1515 | "9645": "rect;", 1516 | "9646": "marker;", 1517 | "9649": "fltns;", 1518 | "9651": "xutri;", 1519 | "9652": "utrif;", 1520 | "9653": "utri;", 1521 | "9656": "rtrif;", 1522 | "9657": "triangleright;", 1523 | "9661": "xdtri;", 1524 | "9662": "dtrif;", 1525 | "9663": "triangledown;", 1526 | "9666": "ltrif;", 1527 | "9667": "triangleleft;", 1528 | "9674": "lozenge;", 1529 | "9675": "cir;", 1530 | "9708": "tridot;", 1531 | "9711": "xcirc;", 1532 | "9720": "ultri;", 1533 | "9721": "urtri;", 1534 | "9722": "lltri;", 1535 | "9723": "EmptySmallSquare;", 1536 | "9724": "FilledSmallSquare;", 1537 | "9733": "starf;", 1538 | "9734": "star;", 1539 | "9742": "phone;", 1540 | "9792": "female;", 1541 | "9794": "male;", 1542 | "9824": "spadesuit;", 1543 | "9827": "clubsuit;", 1544 | "9829": "heartsuit;", 1545 | "9830": "diams;", 1546 | "9834": "sung;", 1547 | "9837": "flat;", 1548 | "9838": "natural;", 1549 | "9839": "sharp;", 1550 | "10003": "checkmark;", 1551 | "10007": "cross;", 1552 | "10016": "maltese;", 1553 | "10038": "sext;", 1554 | "10072": "VerticalSeparator;", 1555 | "10098": "lbbrk;", 1556 | "10099": "rbbrk;", 1557 | "10184": "bsolhsub;", 1558 | "10185": "suphsol;", 1559 | "10214": "lobrk;", 1560 | "10215": "robrk;", 1561 | "10216": "LeftAngleBracket;", 1562 | "10217": "RightAngleBracket;", 1563 | "10218": "Lang;", 1564 | "10219": "Rang;", 1565 | "10220": "loang;", 1566 | "10221": "roang;", 1567 | "10229": "xlarr;", 1568 | "10230": "xrarr;", 1569 | "10231": "xharr;", 1570 | "10232": "xlArr;", 1571 | "10233": "xrArr;", 1572 | "10234": "xhArr;", 1573 | "10236": "xmap;", 1574 | "10239": "dzigrarr;", 1575 | "10498": "nvlArr;", 1576 | "10499": "nvrArr;", 1577 | "10500": "nvHarr;", 1578 | "10501": "Map;", 1579 | "10508": "lbarr;", 1580 | "10509": "rbarr;", 1581 | "10510": "lBarr;", 1582 | "10511": "rBarr;", 1583 | "10512": "RBarr;", 1584 | "10513": "DDotrahd;", 1585 | "10514": "UpArrowBar;", 1586 | "10515": "DownArrowBar;", 1587 | "10518": "Rarrtl;", 1588 | "10521": "latail;", 1589 | "10522": "ratail;", 1590 | "10523": "lAtail;", 1591 | "10524": "rAtail;", 1592 | "10525": "larrfs;", 1593 | "10526": "rarrfs;", 1594 | "10527": "larrbfs;", 1595 | "10528": "rarrbfs;", 1596 | "10531": "nwarhk;", 1597 | "10532": "nearhk;", 1598 | "10533": "searhk;", 1599 | "10534": "swarhk;", 1600 | "10535": "nwnear;", 1601 | "10536": "toea;", 1602 | "10537": "tosa;", 1603 | "10538": "swnwar;", 1604 | "10547": "rarrc;", 1605 | "10549": "cudarrr;", 1606 | "10550": "ldca;", 1607 | "10551": "rdca;", 1608 | "10552": "cudarrl;", 1609 | "10553": "larrpl;", 1610 | "10556": "curarrm;", 1611 | "10557": "cularrp;", 1612 | "10565": "rarrpl;", 1613 | "10568": "harrcir;", 1614 | "10569": "Uarrocir;", 1615 | "10570": "lurdshar;", 1616 | "10571": "ldrushar;", 1617 | "10574": "LeftRightVector;", 1618 | "10575": "RightUpDownVector;", 1619 | "10576": "DownLeftRightVector;", 1620 | "10577": "LeftUpDownVector;", 1621 | "10578": "LeftVectorBar;", 1622 | "10579": "RightVectorBar;", 1623 | "10580": "RightUpVectorBar;", 1624 | "10581": "RightDownVectorBar;", 1625 | "10582": "DownLeftVectorBar;", 1626 | "10583": "DownRightVectorBar;", 1627 | "10584": "LeftUpVectorBar;", 1628 | "10585": "LeftDownVectorBar;", 1629 | "10586": "LeftTeeVector;", 1630 | "10587": "RightTeeVector;", 1631 | "10588": "RightUpTeeVector;", 1632 | "10589": "RightDownTeeVector;", 1633 | "10590": "DownLeftTeeVector;", 1634 | "10591": "DownRightTeeVector;", 1635 | "10592": "LeftUpTeeVector;", 1636 | "10593": "LeftDownTeeVector;", 1637 | "10594": "lHar;", 1638 | "10595": "uHar;", 1639 | "10596": "rHar;", 1640 | "10597": "dHar;", 1641 | "10598": "luruhar;", 1642 | "10599": "ldrdhar;", 1643 | "10600": "ruluhar;", 1644 | "10601": "rdldhar;", 1645 | "10602": "lharul;", 1646 | "10603": "llhard;", 1647 | "10604": "rharul;", 1648 | "10605": "lrhard;", 1649 | "10606": "UpEquilibrium;", 1650 | "10607": "ReverseUpEquilibrium;", 1651 | "10608": "RoundImplies;", 1652 | "10609": "erarr;", 1653 | "10610": "simrarr;", 1654 | "10611": "larrsim;", 1655 | "10612": "rarrsim;", 1656 | "10613": "rarrap;", 1657 | "10614": "ltlarr;", 1658 | "10616": "gtrarr;", 1659 | "10617": "subrarr;", 1660 | "10619": "suplarr;", 1661 | "10620": "lfisht;", 1662 | "10621": "rfisht;", 1663 | "10622": "ufisht;", 1664 | "10623": "dfisht;", 1665 | "10629": "lopar;", 1666 | "10630": "ropar;", 1667 | "10635": "lbrke;", 1668 | "10636": "rbrke;", 1669 | "10637": "lbrkslu;", 1670 | "10638": "rbrksld;", 1671 | "10639": "lbrksld;", 1672 | "10640": "rbrkslu;", 1673 | "10641": "langd;", 1674 | "10642": "rangd;", 1675 | "10643": "lparlt;", 1676 | "10644": "rpargt;", 1677 | "10645": "gtlPar;", 1678 | "10646": "ltrPar;", 1679 | "10650": "vzigzag;", 1680 | "10652": "vangrt;", 1681 | "10653": "angrtvbd;", 1682 | "10660": "ange;", 1683 | "10661": "range;", 1684 | "10662": "dwangle;", 1685 | "10663": "uwangle;", 1686 | "10664": "angmsdaa;", 1687 | "10665": "angmsdab;", 1688 | "10666": "angmsdac;", 1689 | "10667": "angmsdad;", 1690 | "10668": "angmsdae;", 1691 | "10669": "angmsdaf;", 1692 | "10670": "angmsdag;", 1693 | "10671": "angmsdah;", 1694 | "10672": "bemptyv;", 1695 | "10673": "demptyv;", 1696 | "10674": "cemptyv;", 1697 | "10675": "raemptyv;", 1698 | "10676": "laemptyv;", 1699 | "10677": "ohbar;", 1700 | "10678": "omid;", 1701 | "10679": "opar;", 1702 | "10681": "operp;", 1703 | "10683": "olcross;", 1704 | "10684": "odsold;", 1705 | "10686": "olcir;", 1706 | "10687": "ofcir;", 1707 | "10688": "olt;", 1708 | "10689": "ogt;", 1709 | "10690": "cirscir;", 1710 | "10691": "cirE;", 1711 | "10692": "solb;", 1712 | "10693": "bsolb;", 1713 | "10697": "boxbox;", 1714 | "10701": "trisb;", 1715 | "10702": "rtriltri;", 1716 | "10703": "LeftTriangleBar;", 1717 | "10704": "RightTriangleBar;", 1718 | "10716": "iinfin;", 1719 | "10717": "infintie;", 1720 | "10718": "nvinfin;", 1721 | "10723": "eparsl;", 1722 | "10724": "smeparsl;", 1723 | "10725": "eqvparsl;", 1724 | "10731": "lozf;", 1725 | "10740": "RuleDelayed;", 1726 | "10742": "dsol;", 1727 | "10752": "xodot;", 1728 | "10753": "xoplus;", 1729 | "10754": "xotime;", 1730 | "10756": "xuplus;", 1731 | "10758": "xsqcup;", 1732 | "10764": "qint;", 1733 | "10765": "fpartint;", 1734 | "10768": "cirfnint;", 1735 | "10769": "awint;", 1736 | "10770": "rppolint;", 1737 | "10771": "scpolint;", 1738 | "10772": "npolint;", 1739 | "10773": "pointint;", 1740 | "10774": "quatint;", 1741 | "10775": "intlarhk;", 1742 | "10786": "pluscir;", 1743 | "10787": "plusacir;", 1744 | "10788": "simplus;", 1745 | "10789": "plusdu;", 1746 | "10790": "plussim;", 1747 | "10791": "plustwo;", 1748 | "10793": "mcomma;", 1749 | "10794": "minusdu;", 1750 | "10797": "loplus;", 1751 | "10798": "roplus;", 1752 | "10799": "Cross;", 1753 | "10800": "timesd;", 1754 | "10801": "timesbar;", 1755 | "10803": "smashp;", 1756 | "10804": "lotimes;", 1757 | "10805": "rotimes;", 1758 | "10806": "otimesas;", 1759 | "10807": "Otimes;", 1760 | "10808": "odiv;", 1761 | "10809": "triplus;", 1762 | "10810": "triminus;", 1763 | "10811": "tritime;", 1764 | "10812": "iprod;", 1765 | "10815": "amalg;", 1766 | "10816": "capdot;", 1767 | "10818": "ncup;", 1768 | "10819": "ncap;", 1769 | "10820": "capand;", 1770 | "10821": "cupor;", 1771 | "10822": "cupcap;", 1772 | "10823": "capcup;", 1773 | "10824": "cupbrcap;", 1774 | "10825": "capbrcup;", 1775 | "10826": "cupcup;", 1776 | "10827": "capcap;", 1777 | "10828": "ccups;", 1778 | "10829": "ccaps;", 1779 | "10832": "ccupssm;", 1780 | "10835": "And;", 1781 | "10836": "Or;", 1782 | "10837": "andand;", 1783 | "10838": "oror;", 1784 | "10839": "orslope;", 1785 | "10840": "andslope;", 1786 | "10842": "andv;", 1787 | "10843": "orv;", 1788 | "10844": "andd;", 1789 | "10845": "ord;", 1790 | "10847": "wedbar;", 1791 | "10854": "sdote;", 1792 | "10858": "simdot;", 1793 | "10861": "congdot;", 1794 | "10862": "easter;", 1795 | "10863": "apacir;", 1796 | "10864": "apE;", 1797 | "10865": "eplus;", 1798 | "10866": "pluse;", 1799 | "10867": "Esim;", 1800 | "10868": "Colone;", 1801 | "10869": "Equal;", 1802 | "10871": "eDDot;", 1803 | "10872": "equivDD;", 1804 | "10873": "ltcir;", 1805 | "10874": "gtcir;", 1806 | "10875": "ltquest;", 1807 | "10876": "gtquest;", 1808 | "10877": "LessSlantEqual;", 1809 | "10878": "GreaterSlantEqual;", 1810 | "10879": "lesdot;", 1811 | "10880": "gesdot;", 1812 | "10881": "lesdoto;", 1813 | "10882": "gesdoto;", 1814 | "10883": "lesdotor;", 1815 | "10884": "gesdotol;", 1816 | "10885": "lessapprox;", 1817 | "10886": "gtrapprox;", 1818 | "10887": "lneq;", 1819 | "10888": "gneq;", 1820 | "10889": "lnapprox;", 1821 | "10890": "gnapprox;", 1822 | "10891": "lesseqqgtr;", 1823 | "10892": "gtreqqless;", 1824 | "10893": "lsime;", 1825 | "10894": "gsime;", 1826 | "10895": "lsimg;", 1827 | "10896": "gsiml;", 1828 | "10897": "lgE;", 1829 | "10898": "glE;", 1830 | "10899": "lesges;", 1831 | "10900": "gesles;", 1832 | "10901": "eqslantless;", 1833 | "10902": "eqslantgtr;", 1834 | "10903": "elsdot;", 1835 | "10904": "egsdot;", 1836 | "10905": "el;", 1837 | "10906": "eg;", 1838 | "10909": "siml;", 1839 | "10910": "simg;", 1840 | "10911": "simlE;", 1841 | "10912": "simgE;", 1842 | "10913": "LessLess;", 1843 | "10914": "GreaterGreater;", 1844 | "10916": "glj;", 1845 | "10917": "gla;", 1846 | "10918": "ltcc;", 1847 | "10919": "gtcc;", 1848 | "10920": "lescc;", 1849 | "10921": "gescc;", 1850 | "10922": "smt;", 1851 | "10923": "lat;", 1852 | "10924": "smte;", 1853 | "10925": "late;", 1854 | "10926": "bumpE;", 1855 | "10927": "preceq;", 1856 | "10928": "succeq;", 1857 | "10931": "prE;", 1858 | "10932": "scE;", 1859 | "10933": "prnE;", 1860 | "10934": "succneqq;", 1861 | "10935": "precapprox;", 1862 | "10936": "succapprox;", 1863 | "10937": "prnap;", 1864 | "10938": "succnapprox;", 1865 | "10939": "Pr;", 1866 | "10940": "Sc;", 1867 | "10941": "subdot;", 1868 | "10942": "supdot;", 1869 | "10943": "subplus;", 1870 | "10944": "supplus;", 1871 | "10945": "submult;", 1872 | "10946": "supmult;", 1873 | "10947": "subedot;", 1874 | "10948": "supedot;", 1875 | "10949": "subseteqq;", 1876 | "10950": "supseteqq;", 1877 | "10951": "subsim;", 1878 | "10952": "supsim;", 1879 | "10955": "subsetneqq;", 1880 | "10956": "supsetneqq;", 1881 | "10959": "csub;", 1882 | "10960": "csup;", 1883 | "10961": "csube;", 1884 | "10962": "csupe;", 1885 | "10963": "subsup;", 1886 | "10964": "supsub;", 1887 | "10965": "subsub;", 1888 | "10966": "supsup;", 1889 | "10967": "suphsub;", 1890 | "10968": "supdsub;", 1891 | "10969": "forkv;", 1892 | "10970": "topfork;", 1893 | "10971": "mlcp;", 1894 | "10980": "DoubleLeftTee;", 1895 | "10982": "Vdashl;", 1896 | "10983": "Barv;", 1897 | "10984": "vBar;", 1898 | "10985": "vBarv;", 1899 | "10987": "Vbar;", 1900 | "10988": "Not;", 1901 | "10989": "bNot;", 1902 | "10990": "rnmid;", 1903 | "10991": "cirmid;", 1904 | "10992": "midcir;", 1905 | "10993": "topcir;", 1906 | "10994": "nhpar;", 1907 | "10995": "parsim;", 1908 | "11005": "parsl;", 1909 | "64256": "fflig;", 1910 | "64257": "filig;", 1911 | "64258": "fllig;", 1912 | "64259": "ffilig;", 1913 | "64260": "ffllig;" 1914 | } 1915 | },{}],9:[function(require,module,exports){ 1916 | 'use strict'; 1917 | 1918 | var hasOwn = Object.prototype.hasOwnProperty; 1919 | var toStr = Object.prototype.toString; 1920 | 1921 | var isArray = function isArray(arr) { 1922 | if (typeof Array.isArray === 'function') { 1923 | return Array.isArray(arr); 1924 | } 1925 | 1926 | return toStr.call(arr) === '[object Array]'; 1927 | }; 1928 | 1929 | var isPlainObject = function isPlainObject(obj) { 1930 | if (!obj || toStr.call(obj) !== '[object Object]') { 1931 | return false; 1932 | } 1933 | 1934 | var hasOwnConstructor = hasOwn.call(obj, 'constructor'); 1935 | var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf'); 1936 | // Not own constructor property must be Object 1937 | if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { 1938 | return false; 1939 | } 1940 | 1941 | // Own properties are enumerated firstly, so to speed up, 1942 | // if last one is own, then all properties are own. 1943 | var key; 1944 | for (key in obj) {/**/} 1945 | 1946 | return typeof key === 'undefined' || hasOwn.call(obj, key); 1947 | }; 1948 | 1949 | module.exports = function extend() { 1950 | var options, name, src, copy, copyIsArray, clone, 1951 | target = arguments[0], 1952 | i = 1, 1953 | length = arguments.length, 1954 | deep = false; 1955 | 1956 | // Handle a deep copy situation 1957 | if (typeof target === 'boolean') { 1958 | deep = target; 1959 | target = arguments[1] || {}; 1960 | // skip the boolean and the target 1961 | i = 2; 1962 | } else if ((typeof target !== 'object' && typeof target !== 'function') || target == null) { 1963 | target = {}; 1964 | } 1965 | 1966 | for (; i < length; ++i) { 1967 | options = arguments[i]; 1968 | // Only deal with non-null/undefined values 1969 | if (options != null) { 1970 | // Extend the base object 1971 | for (name in options) { 1972 | src = target[name]; 1973 | copy = options[name]; 1974 | 1975 | // Prevent never-ending loop 1976 | if (target !== copy) { 1977 | // Recurse if we're merging plain objects or arrays 1978 | if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { 1979 | if (copyIsArray) { 1980 | copyIsArray = false; 1981 | clone = src && isArray(src) ? src : []; 1982 | } else { 1983 | clone = src && isPlainObject(src) ? src : {}; 1984 | } 1985 | 1986 | // Never move original objects, clone them 1987 | target[name] = extend(deep, clone, copy); 1988 | 1989 | // Don't bring in undefined values 1990 | } else if (typeof copy !== 'undefined') { 1991 | target[name] = copy; 1992 | } 1993 | } 1994 | } 1995 | } 1996 | } 1997 | 1998 | // Return the modified object 1999 | return target; 2000 | }; 2001 | 2002 | 2003 | },{}],10:[function(require,module,exports){ 2004 | (function (global){ 2005 | /*! https://mths.be/punycode v1.4.1 by @mathias */ 2006 | ;(function(root) { 2007 | 2008 | /** Detect free variables */ 2009 | var freeExports = typeof exports == 'object' && exports && 2010 | !exports.nodeType && exports; 2011 | var freeModule = typeof module == 'object' && module && 2012 | !module.nodeType && module; 2013 | var freeGlobal = typeof global == 'object' && global; 2014 | if ( 2015 | freeGlobal.global === freeGlobal || 2016 | freeGlobal.window === freeGlobal || 2017 | freeGlobal.self === freeGlobal 2018 | ) { 2019 | root = freeGlobal; 2020 | } 2021 | 2022 | /** 2023 | * The `punycode` object. 2024 | * @name punycode 2025 | * @type Object 2026 | */ 2027 | var punycode, 2028 | 2029 | /** Highest positive signed 32-bit float value */ 2030 | maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 2031 | 2032 | /** Bootstring parameters */ 2033 | base = 36, 2034 | tMin = 1, 2035 | tMax = 26, 2036 | skew = 38, 2037 | damp = 700, 2038 | initialBias = 72, 2039 | initialN = 128, // 0x80 2040 | delimiter = '-', // '\x2D' 2041 | 2042 | /** Regular expressions */ 2043 | regexPunycode = /^xn--/, 2044 | regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars 2045 | regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators 2046 | 2047 | /** Error messages */ 2048 | errors = { 2049 | 'overflow': 'Overflow: input needs wider integers to process', 2050 | 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', 2051 | 'invalid-input': 'Invalid input' 2052 | }, 2053 | 2054 | /** Convenience shortcuts */ 2055 | baseMinusTMin = base - tMin, 2056 | floor = Math.floor, 2057 | stringFromCharCode = String.fromCharCode, 2058 | 2059 | /** Temporary variable */ 2060 | key; 2061 | 2062 | /*--------------------------------------------------------------------------*/ 2063 | 2064 | /** 2065 | * A generic error utility function. 2066 | * @private 2067 | * @param {String} type The error type. 2068 | * @returns {Error} Throws a `RangeError` with the applicable error message. 2069 | */ 2070 | function error(type) { 2071 | throw new RangeError(errors[type]); 2072 | } 2073 | 2074 | /** 2075 | * A generic `Array#map` utility function. 2076 | * @private 2077 | * @param {Array} array The array to iterate over. 2078 | * @param {Function} callback The function that gets called for every array 2079 | * item. 2080 | * @returns {Array} A new array of values returned by the callback function. 2081 | */ 2082 | function map(array, fn) { 2083 | var length = array.length; 2084 | var result = []; 2085 | while (length--) { 2086 | result[length] = fn(array[length]); 2087 | } 2088 | return result; 2089 | } 2090 | 2091 | /** 2092 | * A simple `Array#map`-like wrapper to work with domain name strings or email 2093 | * addresses. 2094 | * @private 2095 | * @param {String} domain The domain name or email address. 2096 | * @param {Function} callback The function that gets called for every 2097 | * character. 2098 | * @returns {Array} A new string of characters returned by the callback 2099 | * function. 2100 | */ 2101 | function mapDomain(string, fn) { 2102 | var parts = string.split('@'); 2103 | var result = ''; 2104 | if (parts.length > 1) { 2105 | // In email addresses, only the domain name should be punycoded. Leave 2106 | // the local part (i.e. everything up to `@`) intact. 2107 | result = parts[0] + '@'; 2108 | string = parts[1]; 2109 | } 2110 | // Avoid `split(regex)` for IE8 compatibility. See #17. 2111 | string = string.replace(regexSeparators, '\x2E'); 2112 | var labels = string.split('.'); 2113 | var encoded = map(labels, fn).join('.'); 2114 | return result + encoded; 2115 | } 2116 | 2117 | /** 2118 | * Creates an array containing the numeric code points of each Unicode 2119 | * character in the string. While JavaScript uses UCS-2 internally, 2120 | * this function will convert a pair of surrogate halves (each of which 2121 | * UCS-2 exposes as separate characters) into a single code point, 2122 | * matching UTF-16. 2123 | * @see `punycode.ucs2.encode` 2124 | * @see 2125 | * @memberOf punycode.ucs2 2126 | * @name decode 2127 | * @param {String} string The Unicode input string (UCS-2). 2128 | * @returns {Array} The new array of code points. 2129 | */ 2130 | function ucs2decode(string) { 2131 | var output = [], 2132 | counter = 0, 2133 | length = string.length, 2134 | value, 2135 | extra; 2136 | while (counter < length) { 2137 | value = string.charCodeAt(counter++); 2138 | if (value >= 0xD800 && value <= 0xDBFF && counter < length) { 2139 | // high surrogate, and there is a next character 2140 | extra = string.charCodeAt(counter++); 2141 | if ((extra & 0xFC00) == 0xDC00) { // low surrogate 2142 | output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); 2143 | } else { 2144 | // unmatched surrogate; only append this code unit, in case the next 2145 | // code unit is the high surrogate of a surrogate pair 2146 | output.push(value); 2147 | counter--; 2148 | } 2149 | } else { 2150 | output.push(value); 2151 | } 2152 | } 2153 | return output; 2154 | } 2155 | 2156 | /** 2157 | * Creates a string based on an array of numeric code points. 2158 | * @see `punycode.ucs2.decode` 2159 | * @memberOf punycode.ucs2 2160 | * @name encode 2161 | * @param {Array} codePoints The array of numeric code points. 2162 | * @returns {String} The new Unicode string (UCS-2). 2163 | */ 2164 | function ucs2encode(array) { 2165 | return map(array, function(value) { 2166 | var output = ''; 2167 | if (value > 0xFFFF) { 2168 | value -= 0x10000; 2169 | output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); 2170 | value = 0xDC00 | value & 0x3FF; 2171 | } 2172 | output += stringFromCharCode(value); 2173 | return output; 2174 | }).join(''); 2175 | } 2176 | 2177 | /** 2178 | * Converts a basic code point into a digit/integer. 2179 | * @see `digitToBasic()` 2180 | * @private 2181 | * @param {Number} codePoint The basic numeric code point value. 2182 | * @returns {Number} The numeric value of a basic code point (for use in 2183 | * representing integers) in the range `0` to `base - 1`, or `base` if 2184 | * the code point does not represent a value. 2185 | */ 2186 | function basicToDigit(codePoint) { 2187 | if (codePoint - 48 < 10) { 2188 | return codePoint - 22; 2189 | } 2190 | if (codePoint - 65 < 26) { 2191 | return codePoint - 65; 2192 | } 2193 | if (codePoint - 97 < 26) { 2194 | return codePoint - 97; 2195 | } 2196 | return base; 2197 | } 2198 | 2199 | /** 2200 | * Converts a digit/integer into a basic code point. 2201 | * @see `basicToDigit()` 2202 | * @private 2203 | * @param {Number} digit The numeric value of a basic code point. 2204 | * @returns {Number} The basic code point whose value (when used for 2205 | * representing integers) is `digit`, which needs to be in the range 2206 | * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is 2207 | * used; else, the lowercase form is used. The behavior is undefined 2208 | * if `flag` is non-zero and `digit` has no uppercase form. 2209 | */ 2210 | function digitToBasic(digit, flag) { 2211 | // 0..25 map to ASCII a..z or A..Z 2212 | // 26..35 map to ASCII 0..9 2213 | return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); 2214 | } 2215 | 2216 | /** 2217 | * Bias adaptation function as per section 3.4 of RFC 3492. 2218 | * https://tools.ietf.org/html/rfc3492#section-3.4 2219 | * @private 2220 | */ 2221 | function adapt(delta, numPoints, firstTime) { 2222 | var k = 0; 2223 | delta = firstTime ? floor(delta / damp) : delta >> 1; 2224 | delta += floor(delta / numPoints); 2225 | for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { 2226 | delta = floor(delta / baseMinusTMin); 2227 | } 2228 | return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); 2229 | } 2230 | 2231 | /** 2232 | * Converts a Punycode string of ASCII-only symbols to a string of Unicode 2233 | * symbols. 2234 | * @memberOf punycode 2235 | * @param {String} input The Punycode string of ASCII-only symbols. 2236 | * @returns {String} The resulting string of Unicode symbols. 2237 | */ 2238 | function decode(input) { 2239 | // Don't use UCS-2 2240 | var output = [], 2241 | inputLength = input.length, 2242 | out, 2243 | i = 0, 2244 | n = initialN, 2245 | bias = initialBias, 2246 | basic, 2247 | j, 2248 | index, 2249 | oldi, 2250 | w, 2251 | k, 2252 | digit, 2253 | t, 2254 | /** Cached calculation results */ 2255 | baseMinusT; 2256 | 2257 | // Handle the basic code points: let `basic` be the number of input code 2258 | // points before the last delimiter, or `0` if there is none, then copy 2259 | // the first basic code points to the output. 2260 | 2261 | basic = input.lastIndexOf(delimiter); 2262 | if (basic < 0) { 2263 | basic = 0; 2264 | } 2265 | 2266 | for (j = 0; j < basic; ++j) { 2267 | // if it's not a basic code point 2268 | if (input.charCodeAt(j) >= 0x80) { 2269 | error('not-basic'); 2270 | } 2271 | output.push(input.charCodeAt(j)); 2272 | } 2273 | 2274 | // Main decoding loop: start just after the last delimiter if any basic code 2275 | // points were copied; start at the beginning otherwise. 2276 | 2277 | for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { 2278 | 2279 | // `index` is the index of the next character to be consumed. 2280 | // Decode a generalized variable-length integer into `delta`, 2281 | // which gets added to `i`. The overflow checking is easier 2282 | // if we increase `i` as we go, then subtract off its starting 2283 | // value at the end to obtain `delta`. 2284 | for (oldi = i, w = 1, k = base; /* no condition */; k += base) { 2285 | 2286 | if (index >= inputLength) { 2287 | error('invalid-input'); 2288 | } 2289 | 2290 | digit = basicToDigit(input.charCodeAt(index++)); 2291 | 2292 | if (digit >= base || digit > floor((maxInt - i) / w)) { 2293 | error('overflow'); 2294 | } 2295 | 2296 | i += digit * w; 2297 | t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); 2298 | 2299 | if (digit < t) { 2300 | break; 2301 | } 2302 | 2303 | baseMinusT = base - t; 2304 | if (w > floor(maxInt / baseMinusT)) { 2305 | error('overflow'); 2306 | } 2307 | 2308 | w *= baseMinusT; 2309 | 2310 | } 2311 | 2312 | out = output.length + 1; 2313 | bias = adapt(i - oldi, out, oldi == 0); 2314 | 2315 | // `i` was supposed to wrap around from `out` to `0`, 2316 | // incrementing `n` each time, so we'll fix that now: 2317 | if (floor(i / out) > maxInt - n) { 2318 | error('overflow'); 2319 | } 2320 | 2321 | n += floor(i / out); 2322 | i %= out; 2323 | 2324 | // Insert `n` at position `i` of the output 2325 | output.splice(i++, 0, n); 2326 | 2327 | } 2328 | 2329 | return ucs2encode(output); 2330 | } 2331 | 2332 | /** 2333 | * Converts a string of Unicode symbols (e.g. a domain name label) to a 2334 | * Punycode string of ASCII-only symbols. 2335 | * @memberOf punycode 2336 | * @param {String} input The string of Unicode symbols. 2337 | * @returns {String} The resulting Punycode string of ASCII-only symbols. 2338 | */ 2339 | function encode(input) { 2340 | var n, 2341 | delta, 2342 | handledCPCount, 2343 | basicLength, 2344 | bias, 2345 | j, 2346 | m, 2347 | q, 2348 | k, 2349 | t, 2350 | currentValue, 2351 | output = [], 2352 | /** `inputLength` will hold the number of code points in `input`. */ 2353 | inputLength, 2354 | /** Cached calculation results */ 2355 | handledCPCountPlusOne, 2356 | baseMinusT, 2357 | qMinusT; 2358 | 2359 | // Convert the input in UCS-2 to Unicode 2360 | input = ucs2decode(input); 2361 | 2362 | // Cache the length 2363 | inputLength = input.length; 2364 | 2365 | // Initialize the state 2366 | n = initialN; 2367 | delta = 0; 2368 | bias = initialBias; 2369 | 2370 | // Handle the basic code points 2371 | for (j = 0; j < inputLength; ++j) { 2372 | currentValue = input[j]; 2373 | if (currentValue < 0x80) { 2374 | output.push(stringFromCharCode(currentValue)); 2375 | } 2376 | } 2377 | 2378 | handledCPCount = basicLength = output.length; 2379 | 2380 | // `handledCPCount` is the number of code points that have been handled; 2381 | // `basicLength` is the number of basic code points. 2382 | 2383 | // Finish the basic string - if it is not empty - with a delimiter 2384 | if (basicLength) { 2385 | output.push(delimiter); 2386 | } 2387 | 2388 | // Main encoding loop: 2389 | while (handledCPCount < inputLength) { 2390 | 2391 | // All non-basic code points < n have been handled already. Find the next 2392 | // larger one: 2393 | for (m = maxInt, j = 0; j < inputLength; ++j) { 2394 | currentValue = input[j]; 2395 | if (currentValue >= n && currentValue < m) { 2396 | m = currentValue; 2397 | } 2398 | } 2399 | 2400 | // Increase `delta` enough to advance the decoder's state to , 2401 | // but guard against overflow 2402 | handledCPCountPlusOne = handledCPCount + 1; 2403 | if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { 2404 | error('overflow'); 2405 | } 2406 | 2407 | delta += (m - n) * handledCPCountPlusOne; 2408 | n = m; 2409 | 2410 | for (j = 0; j < inputLength; ++j) { 2411 | currentValue = input[j]; 2412 | 2413 | if (currentValue < n && ++delta > maxInt) { 2414 | error('overflow'); 2415 | } 2416 | 2417 | if (currentValue == n) { 2418 | // Represent delta as a generalized variable-length integer 2419 | for (q = delta, k = base; /* no condition */; k += base) { 2420 | t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); 2421 | if (q < t) { 2422 | break; 2423 | } 2424 | qMinusT = q - t; 2425 | baseMinusT = base - t; 2426 | output.push( 2427 | stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) 2428 | ); 2429 | q = floor(qMinusT / baseMinusT); 2430 | } 2431 | 2432 | output.push(stringFromCharCode(digitToBasic(q, 0))); 2433 | bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); 2434 | delta = 0; 2435 | ++handledCPCount; 2436 | } 2437 | } 2438 | 2439 | ++delta; 2440 | ++n; 2441 | 2442 | } 2443 | return output.join(''); 2444 | } 2445 | 2446 | /** 2447 | * Converts a Punycode string representing a domain name or an email address 2448 | * to Unicode. Only the Punycoded parts of the input will be converted, i.e. 2449 | * it doesn't matter if you call it on a string that has already been 2450 | * converted to Unicode. 2451 | * @memberOf punycode 2452 | * @param {String} input The Punycoded domain name or email address to 2453 | * convert to Unicode. 2454 | * @returns {String} The Unicode representation of the given Punycode 2455 | * string. 2456 | */ 2457 | function toUnicode(input) { 2458 | return mapDomain(input, function(string) { 2459 | return regexPunycode.test(string) 2460 | ? decode(string.slice(4).toLowerCase()) 2461 | : string; 2462 | }); 2463 | } 2464 | 2465 | /** 2466 | * Converts a Unicode string representing a domain name or an email address to 2467 | * Punycode. Only the non-ASCII parts of the domain name will be converted, 2468 | * i.e. it doesn't matter if you call it with a domain that's already in 2469 | * ASCII. 2470 | * @memberOf punycode 2471 | * @param {String} input The domain name or email address to convert, as a 2472 | * Unicode string. 2473 | * @returns {String} The Punycode representation of the given domain name or 2474 | * email address. 2475 | */ 2476 | function toASCII(input) { 2477 | return mapDomain(input, function(string) { 2478 | return regexNonASCII.test(string) 2479 | ? 'xn--' + encode(string) 2480 | : string; 2481 | }); 2482 | } 2483 | 2484 | /*--------------------------------------------------------------------------*/ 2485 | 2486 | /** Define the public API */ 2487 | punycode = { 2488 | /** 2489 | * A string representing the current Punycode.js version number. 2490 | * @memberOf punycode 2491 | * @type String 2492 | */ 2493 | 'version': '1.4.1', 2494 | /** 2495 | * An object of methods to convert from JavaScript's internal character 2496 | * representation (UCS-2) to Unicode code points, and back. 2497 | * @see 2498 | * @memberOf punycode 2499 | * @type Object 2500 | */ 2501 | 'ucs2': { 2502 | 'decode': ucs2decode, 2503 | 'encode': ucs2encode 2504 | }, 2505 | 'decode': decode, 2506 | 'encode': encode, 2507 | 'toASCII': toASCII, 2508 | 'toUnicode': toUnicode 2509 | }; 2510 | 2511 | /** Expose `punycode` */ 2512 | // Some AMD build optimizers, like r.js, check for specific condition patterns 2513 | // like the following: 2514 | if ( 2515 | typeof define == 'function' && 2516 | typeof define.amd == 'object' && 2517 | define.amd 2518 | ) { 2519 | define('punycode', function() { 2520 | return punycode; 2521 | }); 2522 | } else if (freeExports && freeModule) { 2523 | if (module.exports == freeExports) { 2524 | // in Node.js, io.js, or RingoJS v0.8.0+ 2525 | freeModule.exports = punycode; 2526 | } else { 2527 | // in Narwhal or RingoJS v0.7.0- 2528 | for (key in punycode) { 2529 | punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); 2530 | } 2531 | } 2532 | } else { 2533 | // in Rhino or a web browser 2534 | root.punycode = punycode; 2535 | } 2536 | 2537 | }(this)); 2538 | 2539 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 2540 | },{}],11:[function(require,module,exports){ 2541 | /** 2542 | * This file automatically generated from `pre-publish.js`. 2543 | * Do not manually edit. 2544 | */ 2545 | 2546 | module.exports = { 2547 | "area": true, 2548 | "base": true, 2549 | "br": true, 2550 | "col": true, 2551 | "embed": true, 2552 | "hr": true, 2553 | "img": true, 2554 | "input": true, 2555 | "keygen": true, 2556 | "link": true, 2557 | "menuitem": true, 2558 | "meta": true, 2559 | "param": true, 2560 | "source": true, 2561 | "track": true, 2562 | "wbr": true 2563 | }; 2564 | 2565 | },{}]},{},[4]); 2566 | --------------------------------------------------------------------------------