├── app ├── front │ ├── public │ │ ├── robots.txt │ │ ├── favicon.ico │ │ ├── images │ │ │ ├── nob.png │ │ │ ├── picker.png │ │ │ ├── palette.png │ │ │ ├── sliders.png │ │ │ ├── checkboard.png │ │ │ ├── editor-st.png │ │ │ ├── icon │ │ │ │ ├── favicon.ico │ │ │ │ ├── tmtheme-128.png │ │ │ │ ├── tmtheme-16.png │ │ │ │ ├── tmtheme-256.png │ │ │ │ ├── tmtheme-32.png │ │ │ │ ├── tmtheme-512.png │ │ │ │ └── tmtheme-1024.png │ │ │ ├── icons │ │ │ │ ├── TMTheme128.png │ │ │ │ ├── TMTheme16.png │ │ │ │ ├── TMTheme32.png │ │ │ │ └── TMTheme48.png │ │ │ └── screenshots │ │ │ │ ├── tmte-screenshot.png │ │ │ │ ├── tte-edit-popover.png │ │ │ │ └── tte-color-adjustments.png │ │ ├── fonts │ │ │ ├── tmthemeeditor.eot │ │ │ ├── tmthemeeditor.ttf │ │ │ ├── tmthemeeditor.woff │ │ │ └── tmthemeeditor.svg │ │ ├── humans.txt │ │ └── files │ │ │ ├── samples │ │ │ └── raw │ │ │ │ ├── latex.txt │ │ │ │ ├── perl.txt │ │ │ │ ├── css.txt │ │ │ │ ├── ruby.txt │ │ │ │ ├── js.txt │ │ │ │ ├── c-sharp.txt │ │ │ │ ├── coffee.txt │ │ │ │ ├── c.txt │ │ │ │ ├── java.txt │ │ │ │ ├── go.txt │ │ │ │ ├── html.txt │ │ │ │ ├── python.txt │ │ │ │ ├── haskell.txt │ │ │ │ ├── ocaml.txt │ │ │ │ ├── lua.txt │ │ │ │ ├── erlang.txt │ │ │ │ ├── c++.txt │ │ │ │ └── r.txt │ │ │ └── themes │ │ │ └── default.tmtheme │ ├── js │ │ ├── template │ │ │ ├── editor.html │ │ │ ├── modal │ │ │ │ ├── backdrop.html │ │ │ │ └── window.html │ │ │ ├── alert │ │ │ │ └── alert.html │ │ │ ├── preview │ │ │ │ ├── scope_hunter.html │ │ │ │ └── custom_code.html │ │ │ ├── modalOpenURL.html │ │ │ ├── main.html │ │ │ ├── sidebar.html │ │ │ ├── stats │ │ │ │ ├── general_tab.html │ │ │ │ ├── scopes_tab.html │ │ │ │ └── themes_tab.html │ │ │ ├── table_info.html │ │ │ ├── header_links.html │ │ │ ├── stats.html │ │ │ ├── preview.html │ │ │ ├── table_general.html │ │ │ ├── scope_hunter │ │ │ │ └── scope_hunter.html │ │ │ ├── header.html │ │ │ ├── action_bar.html │ │ │ ├── color_picker.html │ │ │ ├── dialog_general_colors.html │ │ │ ├── hud_colors.html │ │ │ ├── table_scopes.html │ │ │ ├── dialog_new.html │ │ │ ├── dialog_edit.html │ │ │ ├── gallery.html │ │ │ └── color_picker_sliders.html │ │ ├── services │ │ │ ├── tinycolor_service.coffee │ │ │ ├── filters.coffee │ │ │ ├── popover_new_service.coffee │ │ │ ├── color_picker_service.coffee │ │ │ ├── editor_service.coffee │ │ │ ├── popover_edit_service.coffee │ │ │ ├── popover_general_colors_service.coffee │ │ │ ├── theme_loader_service.coffee │ │ │ ├── scope_matcher_service.coffee │ │ │ ├── throbber_service.coffee │ │ │ ├── plist_to_json.coffee │ │ │ ├── json_to_plist.coffee │ │ │ ├── hud_adjustments_service.coffee │ │ │ ├── file_manager_service.coffee │ │ │ └── color_service.coffee │ │ ├── application.coffee │ │ ├── directives │ │ │ ├── range.coffee │ │ │ ├── draggable.coffee │ │ │ ├── focusme.coffee │ │ │ ├── shortcut.coffee │ │ │ ├── dropzone.coffee │ │ │ ├── inline_edit.coffee │ │ │ └── scopebar.coffee │ │ ├── controllers │ │ │ ├── modal_openURL_controller.coffee │ │ │ ├── page_controller.coffee │ │ │ ├── gallery_controller.coffee │ │ │ ├── color_picker_controller.coffee │ │ │ ├── stats_controller.coffee │ │ │ └── preview_controller.coffee │ │ ├── config │ │ │ ├── boot.coffee │ │ │ ├── resolves.coffee │ │ │ └── routes.coffee │ │ └── libs.js │ └── css │ │ ├── lib │ │ ├── variables.less │ │ ├── bootstrap.less │ │ ├── mixins.less │ │ └── buttons.less │ │ ├── app.less │ │ └── app │ │ ├── stats.less │ │ ├── scope_hunter.less │ │ ├── header.less │ │ ├── preview.less │ │ ├── global.less │ │ └── icons.less └── back │ ├── views │ ├── partials │ │ ├── meta.html │ │ └── analytics.html │ ├── errors │ │ ├── 404.html │ │ └── 500.html │ └── index.html │ ├── config.coffee │ ├── lib │ └── ngtemplate.coffee │ ├── controllers │ └── pages_controller.coffee │ └── app.coffee ├── Procfile ├── .gitignore ├── test └── services │ ├── filters_spec.coffee │ ├── theme_service_spec.coffee │ └── color_service_spec.coffee ├── bower.json ├── README.md ├── package.json ├── gulpfile.js └── coffeelint.json /app/front/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: coffee app/back/app.coffee 2 | -------------------------------------------------------------------------------- /app/front/js/template/editor.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | -------------------------------------------------------------------------------- /app/front/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/favicon.ico -------------------------------------------------------------------------------- /app/front/js/services/tinycolor_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory 'tinycolor', [ -> 2 | window.tinycolor 3 | ] 4 | -------------------------------------------------------------------------------- /app/front/public/images/nob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/nob.png -------------------------------------------------------------------------------- /app/front/public/images/picker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/picker.png -------------------------------------------------------------------------------- /app/front/public/images/palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/palette.png -------------------------------------------------------------------------------- /app/front/public/images/sliders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/sliders.png -------------------------------------------------------------------------------- /app/front/public/images/checkboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/checkboard.png -------------------------------------------------------------------------------- /app/front/public/images/editor-st.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/editor-st.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_components 3 | tmp 4 | log/*.log 5 | app/front/public/assets 6 | test/**/*.js 7 | dist 8 | *.log 9 | -------------------------------------------------------------------------------- /app/front/public/fonts/tmthemeeditor.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/fonts/tmthemeeditor.eot -------------------------------------------------------------------------------- /app/front/public/fonts/tmthemeeditor.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/fonts/tmthemeeditor.ttf -------------------------------------------------------------------------------- /app/front/public/fonts/tmthemeeditor.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/fonts/tmthemeeditor.woff -------------------------------------------------------------------------------- /app/front/public/images/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icon/favicon.ico -------------------------------------------------------------------------------- /app/front/public/images/icon/tmtheme-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icon/tmtheme-128.png -------------------------------------------------------------------------------- /app/front/public/images/icon/tmtheme-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icon/tmtheme-16.png -------------------------------------------------------------------------------- /app/front/public/images/icon/tmtheme-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icon/tmtheme-256.png -------------------------------------------------------------------------------- /app/front/public/images/icon/tmtheme-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icon/tmtheme-32.png -------------------------------------------------------------------------------- /app/front/public/images/icon/tmtheme-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icon/tmtheme-512.png -------------------------------------------------------------------------------- /app/front/public/images/icons/TMTheme128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icons/TMTheme128.png -------------------------------------------------------------------------------- /app/front/public/images/icons/TMTheme16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icons/TMTheme16.png -------------------------------------------------------------------------------- /app/front/public/images/icons/TMTheme32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icons/TMTheme32.png -------------------------------------------------------------------------------- /app/front/public/images/icons/TMTheme48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icons/TMTheme48.png -------------------------------------------------------------------------------- /app/front/public/images/icon/tmtheme-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/icon/tmtheme-1024.png -------------------------------------------------------------------------------- /app/front/public/images/screenshots/tmte-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/screenshots/tmte-screenshot.png -------------------------------------------------------------------------------- /app/front/public/images/screenshots/tte-edit-popover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/screenshots/tte-edit-popover.png -------------------------------------------------------------------------------- /app/front/js/services/filters.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "removeExtensionFilter", [ -> 2 | (filename) -> 3 | filename.replace(/\.(hidden-)?[tT]m[Tt]heme/,"") 4 | ] 5 | -------------------------------------------------------------------------------- /app/front/public/images/screenshots/tte-color-adjustments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aziz/tmTheme-Editor/HEAD/app/front/public/images/screenshots/tte-color-adjustments.png -------------------------------------------------------------------------------- /app/front/public/humans.txt: -------------------------------------------------------------------------------- 1 | /* TEAM */ 2 | Allen Bargi 3 | Twitter: http://twitter.com/aziz 4 | Github: http://github.com/aziz 5 | 6 | Github Repo: https://github.com/aziz/tmTheme-Editor -------------------------------------------------------------------------------- /app/front/js/template/modal/backdrop.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/front/js/application.coffee: -------------------------------------------------------------------------------- 1 | #= require config/boot 2 | #= require_tree template 3 | #= require config/resolves 4 | #= require config/routes 5 | #= require_tree directives 6 | #= require_tree services 7 | #= require_tree controllers 8 | -------------------------------------------------------------------------------- /app/front/js/directives/range.coffee: -------------------------------------------------------------------------------- 1 | Application.directive 'input', -> 2 | restrict: 'E' 3 | require: '?ngModel' 4 | link: (scope, element, attrs, ngModel) -> 5 | if 'type' of attrs and attrs.type.toLowerCase() == 'range' 6 | ngModel.$parsers.push parseFloat 7 | return 8 | -------------------------------------------------------------------------------- /app/front/css/lib/variables.less: -------------------------------------------------------------------------------- 1 | @systemFontFamily: 'lucida grande', 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif; 2 | @monoFontFamily: 'Source Code Pro', 'Consolas', 'Monaco', 'Menlo','Ubuntu Mono', 'Courier New', monospace; 3 | @sidebar_width: 400px; 4 | @header_height: 36px; 5 | -------------------------------------------------------------------------------- /app/front/js/directives/draggable.coffee: -------------------------------------------------------------------------------- 1 | Application.directive "draggable", ['$timeout', ($timeout) -> 2 | restrict: "A" 3 | link: (scope, element, attrs) -> 4 | draggable = -> 5 | options = scope.$eval(attrs.draggable) || {} 6 | element.draggable(options) 7 | $timeout draggable, 0, false 8 | ] 9 | -------------------------------------------------------------------------------- /test/services/filters_spec.coffee: -------------------------------------------------------------------------------- 1 | describe 'Filters', -> 2 | 3 | beforeEach(module('ThemeEditor')) 4 | 5 | describe 'filter: removeExtension', -> 6 | it 'removes extension from theme\'s file name', inject (removeExtensionFilter) -> 7 | expect(removeExtensionFilter("theme.tmTheme")).toEqual("theme") 8 | expect(removeExtensionFilter("theme2.tmtheme")).toEqual("theme2") 9 | 10 | -------------------------------------------------------------------------------- /app/front/js/template/alert/alert.html: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /app/front/js/controllers/modal_openURL_controller.coffee: -------------------------------------------------------------------------------- 1 | Application.controller 'ModalOpenURLController', 2 | ['$scope','$modalInstance', 'themeExternalURL', 3 | ($scope, $modalInstance, themeExternalURL) -> 4 | 5 | $scope.themeExternalURL = themeExternalURL 6 | $scope.ok = -> $modalInstance.close $scope.themeExternalURL 7 | $scope.cancel = -> $modalInstance.dismiss 'cancel' 8 | 9 | return 10 | ] 11 | -------------------------------------------------------------------------------- /app/front/css/app.less: -------------------------------------------------------------------------------- 1 | //= require lib/bootstrap 2 | //= require lib/buttons 3 | //= require lib/hud 4 | //= require lib/minicolors 5 | //= require app/global 6 | //= require app/header 7 | //= require app/sidebar 8 | //= require app/preview 9 | //= require app/gallery 10 | //= require app/popover 11 | //= require app/stats 12 | //= require app/icons 13 | //= require app/color_picker 14 | //= require app/scope_hunter 15 | -------------------------------------------------------------------------------- /app/back/views/partials/meta.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/front/js/services/popover_new_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "NewPopover", [ -> 2 | 3 | rule_pristine = {'name': '','scope': ' ','settings': {}} 4 | 5 | popover = {} 6 | popover.visible = false 7 | popover.rule = angular.copy(rule_pristine) 8 | popover.hide = -> @visible = false 9 | popover.show = -> 10 | @rule = angular.copy(rule_pristine) 11 | @visible = true 12 | 13 | return popover 14 | ] 15 | -------------------------------------------------------------------------------- /app/front/js/directives/focusme.coffee: -------------------------------------------------------------------------------- 1 | Application.directive "focusMe", ['$timeout', ($timeout) -> 2 | link: (scope, element, attrs) -> 3 | scope.$watch attrs.focusMe, (value) -> 4 | return unless value 5 | set_focus = -> 6 | el = element[0] 7 | el.focus() 8 | el.select() if attrs.autoSelect == "true" 9 | return 10 | $timeout(set_focus, 0) 11 | return 12 | return 13 | ] 14 | -------------------------------------------------------------------------------- /app/front/js/services/color_picker_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "ColorPicker", [ -> 2 | CP = {} 3 | 4 | CP.visible = false 5 | CP.current_tab = 'picker' 6 | CP.selector = null 7 | CP.rule = {} 8 | CP.active_sliders = { 9 | rgb: true 10 | hsl: false 11 | hsv: true 12 | } 13 | 14 | CP.pick = (rule, selector) -> 15 | CP.rule = rule 16 | CP.selector = selector 17 | CP.visible = true 18 | 19 | CP 20 | ] 21 | -------------------------------------------------------------------------------- /app/front/js/template/modal/window.html: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /app/front/js/controllers/page_controller.coffee: -------------------------------------------------------------------------------- 1 | Application.controller 'pageController', ['$scope', 'Theme', '$state', ($scope, Theme, $state) -> 2 | 3 | $scope.current_theme = Theme 4 | 5 | $scope.page_title = (theme) -> 6 | # TODO: use router custom data to set the title 7 | if $state.includes("editor.*") 8 | return 'TmTheme Editor' unless theme 9 | "#{theme.json.name} • TmTheme Editor" 10 | else 11 | "TmTheme Editor" 12 | 13 | return 14 | ] 15 | -------------------------------------------------------------------------------- /app/back/views/errors/404.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

404 Page not found!

4 |

5 | The page you were looking for isn't where you thought it was.
6 | You may have followed a bad external link, or mis-typed a URL. 7 |

8 |

9 | 10 | Take Me Home 11 | 12 |

13 |
14 |
15 | -------------------------------------------------------------------------------- /app/back/views/errors/500.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Oops! Looks like something went wrong!

4 |

5 | We track these errors automatically, but if the problem persists feel free to contact us. 6 | In the meantime, try refreshing. 7 |

8 |

9 | Take Me Home 10 |

11 |
12 |
13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/services/theme_service_spec.coffee: -------------------------------------------------------------------------------- 1 | describe 'Service: Theme', -> 2 | 3 | beforeEach(module('ThemeEditor')) 4 | 5 | xit 'processes a valid theme', inject (Theme) -> 6 | xit 'bg color', inject (Theme) -> 7 | xit 'fg color', inject (Theme) -> 8 | xit 'selection color', inject (Theme) -> 9 | xit 'gutter fg color', inject (Theme) -> 10 | xit 'color box border color', inject (Theme) -> 11 | xit 'valid css for scopes', inject (Theme) -> 12 | xit 'valid css for gutter', inject (Theme) -> 13 | xit 'valid css for selection', inject (Theme) -> 14 | xit 'font styles', inject (Theme) -> 15 | -------------------------------------------------------------------------------- /app/back/config.coffee: -------------------------------------------------------------------------------- 1 | config = module.exports = {} 2 | 3 | config.assets = ['app/front/js', 'app/front/css', 'bower_components'] 4 | config.cookie_secret = 'sandbox secret string' 5 | config.env = process.env.NODE_ENV || 'development' 6 | config.port = process.env.PORT || 9999 7 | config.env_development = true 8 | 9 | # Production Specific 10 | if config.env == 'production' 11 | config.port = process.env.PORT || 80 12 | config.env_development = false 13 | config.env_production = true 14 | config.log_file = 'production.log' 15 | config.assets_build_dir = process.env.ASSETS_BUILD_DIR || 'app/front/public/assets/' 16 | -------------------------------------------------------------------------------- /app/front/js/template/preview/scope_hunter.html: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /app/front/js/directives/shortcut.coffee: -------------------------------------------------------------------------------- 1 | Application.directive "shortcut", [ -> 2 | (scope, element, attr) -> 3 | element.bind "keyup", (event) -> 4 | shortcut_obj = scope.$eval(attr.shortcut) 5 | switch 6 | when event.keyCode == 27 7 | scope.$apply shortcut_obj["escape"] 8 | when event.keyCode == 13 9 | scope.$apply shortcut_obj["enter"] 10 | when 32 <= event.keyCode <= 126 11 | string = String.fromCharCode(event.keyCode).toLowerCase() 12 | string = "ctrl+#{string}" if event.ctrlKey 13 | scope.$apply shortcut_obj[string] 14 | # else 15 | # console.log "no match" 16 | ] 17 | -------------------------------------------------------------------------------- /app/front/js/template/modalOpenURL.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 6 | 12 | 16 |
17 | -------------------------------------------------------------------------------- /app/back/lib/ngtemplate.coffee: -------------------------------------------------------------------------------- 1 | Template = require('mincer/lib/mincer/template') 2 | prop = require('mincer/lib/mincer/common').prop 3 | templatecache = require('ng-templatecache') 4 | 5 | ngTemplatesEngine = module.exports = -> 6 | Template.apply this, arguments 7 | return 8 | 9 | require('util').inherits(ngTemplatesEngine, Template) 10 | 11 | ngTemplatesEngine::evaluate = (context) -> 12 | @data = templatecache( 13 | entries: [{ 14 | content: @data 15 | path: context.logicalPath + context.environment.attributesFor(context.pathname).extensions.join('') 16 | }] 17 | module: 'templates' 18 | standalone: false 19 | ) 20 | return 21 | 22 | prop ngTemplatesEngine, 'defaultMimeType', 'application/javascript' 23 | -------------------------------------------------------------------------------- /app/front/js/config/boot.coffee: -------------------------------------------------------------------------------- 1 | angular.module('templates', []) 2 | 3 | Application = angular.module('ThemeEditor', 4 | [ 5 | 'templates' 6 | 'ngSanitize' 7 | 'ui.router' 8 | 'ui.sortable' 9 | 'ui.bootstrap.dropdown' 10 | 'ui.bootstrap.alert' 11 | 'ui.bootstrap.modal' 12 | 'mgcrea.ngStrap.tooltip' 13 | 'minicolors' 14 | 'monospaced.elastic' 15 | ] 16 | ) 17 | 18 | Application.run ['$rootScope', 'Editor', ($rootScope, Editor) -> 19 | $rootScope.Editor = Editor 20 | return 21 | ] 22 | 23 | # Production mode 24 | # Application.config ['$logProvider','$compileProvider', ($logProvider, $compileProvider) -> 25 | # $logProvider.debugEnabled false 26 | # $compileProvider.debugInfoEnabled false 27 | # ] 28 | -------------------------------------------------------------------------------- /app/front/js/template/main.html: -------------------------------------------------------------------------------- 1 |
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | -------------------------------------------------------------------------------- /app/back/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TmThemeEditor 5 | 6 | <% include 'partials/meta' %> 7 | <%- css("app") %> 8 | 9 | 10 |
11 |
12 |
13 | {{alert.msg}} 14 |
15 | 16 | 17 | <%- js("libs") %> 18 | <%- js("application") %> 19 | <% include 'partials/analytics' %> 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/front/js/directives/dropzone.coffee: -------------------------------------------------------------------------------- 1 | Application.directive "dropZone", ["FileManager", "$location", "$q", (FileManager, $location, $q) -> 2 | restrict: "A" 3 | link: (scope, element, attrs) -> 4 | 5 | handleFileDrop = (e) -> 6 | e.stopPropagation() 7 | e.preventDefault() 8 | files = e.originalEvent.dataTransfer.files 9 | local_files = FileManager.add_local_theme(files) 10 | # update the location path to the last file 11 | $q.all(local_files).then (names) -> 12 | $location.path("/editor/local/#{names.last()}") 13 | 14 | handleDragOver = (e) -> 15 | e.stopPropagation() 16 | e.preventDefault() 17 | e.originalEvent.dataTransfer.dropEffect = 'copy' 18 | 19 | element.on 'dragover', handleDragOver 20 | element.on 'drop', handleFileDrop 21 | return 22 | ] 23 | -------------------------------------------------------------------------------- /app/front/js/template/sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | Scopes 5 | General 6 | Info 7 |
8 | 9 | 16 | -------------------------------------------------------------------------------- /app/front/js/template/stats/general_tab.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 22 | 23 | 24 |
#KeyValuesCount
{{::$index+1 }}{{::scope.name }} 14 |
15 | "{{ val }}"[{{ repeats.length }}] 16 |
17 |
{{ scope.count }} 20 | 21 |
25 | -------------------------------------------------------------------------------- /app/front/js/services/editor_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "Editor", [ -> 2 | 3 | Gallery = {} 4 | Gallery.visible = angular.fromJson($.cookie("gallery_visible") || false) 5 | Gallery.filter = {name: ''} 6 | Gallery.toggle = -> 7 | $('body').removeClass('transition-off') 8 | Gallery.visible = if Gallery.visible then false else true 9 | $.cookie('gallery_visible', Gallery.visible) 10 | transition_off = -> $('body').addClass('transition-off') 11 | setTimeout(transition_off, 600) 12 | 13 | Sidebar = {} 14 | Sidebar.current_tab = 'scopes' 15 | 16 | ScopeHunter = {} 17 | ScopeHunter.visible = angular.fromJson($.cookie("scopehunter_visible") || false) 18 | ScopeHunter.toggle = -> 19 | ScopeHunter.visible = if ScopeHunter.visible then false else true 20 | $.cookie('scopehunter_visible', ScopeHunter.visible) 21 | 22 | version = $("#version").attr("content") 23 | current_theme = {} 24 | 25 | { 26 | Gallery 27 | Sidebar 28 | ScopeHunter 29 | version 30 | current_theme 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tmTheme-Editor", 3 | "homepage": "https://github.com/aziz/tmTheme-Editor", 4 | "authors": [ 5 | "Allen Bargi " 6 | ], 7 | "license": "GNU AFFERO GENERAL PUBLIC LICENSE", 8 | "private": true, 9 | "ignore": [ 10 | "**/.*", 11 | "node_modules", 12 | "bower_components", 13 | "test", 14 | "tests" 15 | ], 16 | "dependencies": { 17 | "angular": "1.4.0", 18 | "angular-bootstrap": "angular-ui/bootstrap#0.13.0", 19 | "angular-elastic": "2.4.2", 20 | "angular-minicolors": "0.0.5", 21 | "angular-sanitize": "1.4.0", 22 | "angular-strap": "2.2.4", 23 | "angular-ui-router": "0.2.15", 24 | "angular-ui-sortable": "0.13.4", 25 | "bootstrap": "2.1.0", 26 | "FileSaver": "*", 27 | "jquery": "2.1.4", 28 | "jquery-ui": "1.11.4", 29 | "jquery.cookie": "1.4.1", 30 | "jquery.scrollintoview": "*", 31 | "spin.js": "2.3.1", 32 | "sugar": "1.4.1", 33 | "tinycolor": "1.1.2" 34 | }, 35 | "resolutions": { 36 | "angular": "1.4.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/front/js/template/table_info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
PropertyValue
UUID{{::Theme.json.uuid}}
Name
Author
Comment
34 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/latex.txt: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{article} 2 | % options include 12pt or 11pt or 10pt 3 | % classes include article, report, book, letter, thesis 4 | 5 | \title{This is the title} 6 | \author{Author One \\ Author Two} 7 | \date{29 February 2004} 8 | 9 | \usepackage{pstricks} 10 | \setlength{\textheight}{12.5cm} 11 | \setlength{\textwidth}{16.0cm} 12 | 13 | \newcommand{\cloud}[1]{ 14 | \psset{unit=#1cm} 15 | \pspicture(2,4) 16 | \psarc(2,0){1.25}{210}{35} 17 | \psarc(0,0){1.25}{105}{320} 18 | \psarc(0.2,.75){.75}{45}{145} 19 | \psarc(1.8,.5){1.15}{5}{150}% 20 | \endpspicture 21 | } 22 | 23 | \setlength{\parindent}{0mm} 24 | \setlength{\parskip}{5mm} 25 | 26 | 27 | \begin{document} 28 | \maketitle 29 | 30 | This is the content of this document. 31 | 32 | This is the 2nd paragraph. 33 | Here is an inline formula: 34 | $ V = \frac{4 \pi r^3}{3} $. 35 | And appearing immediately below 36 | is a displayed formula: 37 | $$ V = \frac{4 \pi r^3}{3} $$ 38 | 39 | This is a cloud size 0.3: ~ ~ ~ ~ ~ \cloud{0.3} 40 | 41 | This is a cloud size 0.9: ~ ~ ~ ~ ~ \cloud{0.9} 42 | 43 | \end{document} 44 | -------------------------------------------------------------------------------- /app/front/js/template/header_links.html: -------------------------------------------------------------------------------- 1 |
2 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /app/front/js/config/resolves.coffee: -------------------------------------------------------------------------------- 1 | Application.editorData = { 2 | current_theme: ['$stateParams', 'ThemeLoader', ($stateParams, ThemeLoader) -> 3 | theme = $stateParams.theme 4 | ThemeLoader.themes.then (data) -> 5 | theme_obj = data.find (t) -> t.name == theme 6 | return { 7 | data: ThemeLoader.load(theme_obj) 8 | name: theme 9 | url: theme_obj.url 10 | type: '' 11 | } 12 | ] 13 | } 14 | 15 | Application.urlData = { 16 | current_theme: ['$stateParams', 'ThemeLoader', ($stateParams, ThemeLoader) -> 17 | theme = $stateParams.theme 18 | return { 19 | data: ThemeLoader.load({ url: theme }) 20 | name: theme.split('/').last().replace(/%20/g, ' ') 21 | url: theme 22 | type: 'External URL' 23 | } 24 | ] 25 | } 26 | 27 | Application.localData = { 28 | current_theme: ['$stateParams', 'FileManager', '$q', ($stateParams, FileManager, $q) -> 29 | theme = $stateParams.theme 30 | deferred = $q.defer() 31 | data = FileManager.load(theme) 32 | deferred.resolve(data) 33 | return { 34 | data: deferred.promise 35 | name: theme 36 | type: 'Local File' 37 | } 38 | ] 39 | } 40 | 41 | -------------------------------------------------------------------------------- /app/front/js/template/stats.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 10 | 11 | 22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 |
30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /app/front/css/lib/bootstrap.less: -------------------------------------------------------------------------------- 1 | // CSS Reset 2 | @import "bootstrap/less/reset.less"; 3 | 4 | // Core variables and mixins 5 | @import "bootstrap/less/variables.less"; 6 | @import "lib/bootstrap_mixins.less"; 7 | 8 | // Grid system and page structure 9 | @import "bootstrap/less/scaffolding.less"; 10 | @import "bootstrap/less/grid.less"; 11 | @import "bootstrap/less/layouts.less"; 12 | 13 | // Base CSS 14 | @import "bootstrap/less/type.less"; 15 | @import "bootstrap/less/code.less"; 16 | @import "bootstrap/less/forms.less"; 17 | @import "bootstrap/less/tables.less"; 18 | 19 | // Components: common 20 | @import "bootstrap/less/dropdowns.less"; 21 | @import "bootstrap/less/close.less"; 22 | 23 | // Components: Buttons & Alerts 24 | @import "bootstrap/less/button-groups.less"; 25 | @import "bootstrap/less/alerts.less"; 26 | 27 | // Components: Nav 28 | @import "bootstrap/less/navs.less"; 29 | 30 | // Components: Popovers 31 | @import "bootstrap/less/modals.less"; 32 | @import "bootstrap/less/tooltip.less"; 33 | 34 | // Components: Misc 35 | @import "bootstrap/less/labels-badges.less"; 36 | @import "bootstrap/less/progress-bars.less"; 37 | 38 | // Utility classes 39 | @import "bootstrap/less/utilities.less"; // Has to be last to override when necessary 40 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/perl.txt: -------------------------------------------------------------------------------- 1 | use strict; 2 | 3 | # 4 | # This script also prints the contents of all the listed files, but 5 | # it first scans through the list to check that each file exists and 6 | # is readable. It will stop if there are any errors. 7 | # 8 | 9 | my $bad = 0; 10 | foreach my $fn (@ARGV) { 11 | if(! -r $fn) { 12 | # File cannot be read. See if it exists or not for a better 13 | # error message. 14 | if(-e $fn) { 15 | print STDERR "You do not have permission to read $fn.\n"; 16 | } else { 17 | print STDERR "File $fn does not exist.\n"; 18 | } 19 | 20 | # One way or the other, it's bad. 21 | $bad = 1; 22 | } 23 | } 24 | 25 | # If there was a problem, bail out. 26 | if($bad) { exit 2; } 27 | 28 | # Copy all the files. 29 | while(my $fn = shift @ARGV) { 30 | 31 | # Open the file. 32 | if(!open(INFILE, $fn)) { 33 | # We know the file is readable, but sometimes something else goes 34 | # wrong. It's safer to check. 35 | print STDERR "Cannot open $fn: $!\n"; 36 | next; 37 | } 38 | 39 | # Copy it. 40 | while(my $l = ) { 41 | print $l; 42 | } 43 | 44 | close INFILE; 45 | } 46 | -------------------------------------------------------------------------------- /app/front/js/libs.js: -------------------------------------------------------------------------------- 1 | //= require sugar/release/sugar-full.development.js 2 | //= require FileSaver/FileSaver.js 3 | //= require spin.js/spin.js 4 | //= require jquery/dist/jquery.js 5 | //= require jquery.cookie/jquery.cookie.js 6 | //= require jquery.scrollintoview/jquery.scrollintoview.js 7 | //= require angular/angular.js 8 | //= require angular-sanitize/angular-sanitize.js 9 | //= require angular-ui-router/release/angular-ui-router.js 10 | //= require tinycolor/tinycolor.js 11 | //= require angular-strap/dist/modules/dimensions.js 12 | //= require angular-strap/dist/modules/tooltip.js 13 | //= require angular-strap/dist/modules/tooltip.tpl.js 14 | //= require angular-bootstrap/src/position/position.js 15 | //= require angular-bootstrap/src/dropdown/dropdown.js 16 | //= require angular-bootstrap/src/alert/alert.js 17 | //= require angular-bootstrap/src/modal/modal.js 18 | //= require jquery-ui/ui/core.js 19 | //= require jquery-ui/ui/widget.js 20 | //= require jquery-ui/ui/mouse.js 21 | //= require jquery-ui/ui/sortable.js 22 | //= require jquery-ui/ui/draggable.js 23 | //= require angular-ui-sortable/sortable.js 24 | //= require jquery-minicolors/jquery.minicolors.js 25 | //= require angular-minicolors/angular-minicolors.js 26 | //= require angular-elastic/elastic.js 27 | -------------------------------------------------------------------------------- /app/back/controllers/pages_controller.coffee: -------------------------------------------------------------------------------- 1 | express = require 'express' 2 | request = require 'request' 3 | pjson = require '../../../package.json' 4 | 5 | router = module.exports = express.Router() 6 | parserURI = 'http://tmtheme-editor-parser.herokuapp.com/' 7 | #parserURI = 'http://localhost:4567/' 8 | 9 | router.get '/', (req, res, next) -> 10 | view = { 11 | app_version: pjson.version 12 | } 13 | # view.api_url = "http://localhost:#{process.env.PORT || 9999}" 14 | view.api_url = "" 15 | res.render 'index', view 16 | 17 | router.get '/get_uri', (req, res, next) -> 18 | res.set 'Content-Type', 'text/plain' 19 | request req.query.uri, (error, response, body) -> 20 | if !error && response.statusCode == 200 21 | res.send body 22 | else 23 | res.status 404 24 | res.send 'Not found' 25 | 26 | router.get '/stats', (req, res, next) -> 27 | res.redirect 301, '/#!/stats' 28 | 29 | router.post '/parse', (req, res, next) -> 30 | request.post parserURI, {form: {text: req.body.text, syntax: req.body.syntax} }, (error, response, body) -> 31 | if body == "

Internal Server Error

" 32 | res.status 404 33 | res.send 'Not found' 34 | else 35 | res.set 'Content-Type', 'text/plain' 36 | res.send body 37 | -------------------------------------------------------------------------------- /app/back/views/partials/analytics.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 18 | 21 | 22 | 23 | 32 | -------------------------------------------------------------------------------- /app/front/js/template/preview/custom_code.html: -------------------------------------------------------------------------------- 1 |
4 | 8 |
9 |

Paste your code below and press Save button.

10 |
11 |
12 | 20 | 21 | 28 | -------------------------------------------------------------------------------- /app/front/js/template/stats/scopes_tab.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 |
# 5 | Scope 6 | 7 | 8 | 11 | Count 12 | 13 | 14 |
{{::$index+1 }}{{::scope.name }}{{ scope.count }} 22 | 23 |
27 | -------------------------------------------------------------------------------- /app/front/js/template/preview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 |
11 |

15 |   
16 | 17 |
18 | 19 | 20 | {{ current_lang }} 21 | 22 | 27 |
28 | 29 | 30 | 31 |
32 | -------------------------------------------------------------------------------- /app/front/js/services/popover_edit_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "EditPopover", ['$timeout', ($timeout) -> 2 | 3 | popover = {} 4 | popover.visible = false 5 | popover.rule = {} 6 | popover.hide = -> @visible = false 7 | popover.show = (rule, rule_index) -> 8 | @rule = rule 9 | @visible = true 10 | $timeout => @set_position(rule_index) 11 | return 12 | 13 | popover.set_position = (rule_index) -> 14 | popover_el = $('#edit-popover') 15 | row = $("#scopes-list .rule-#{rule_index}") 16 | winH = $(window).height() 17 | popover_el_height = popover_el.outerHeight() 18 | row_height = row.outerHeight() 19 | top = row.offset().top 20 | 21 | if (winH - top) < popover_el_height/2 22 | popover_el.css({ 23 | 'top': 'auto' 24 | 'left': '' 25 | 'bottom': winH - top 26 | }).removeClass('on-bottom').addClass('on-top') 27 | else if top < popover_el_height/2 28 | popover_el.css({ 29 | 'left': '' 30 | 'top': top + row_height 31 | 'bottom': 'auto' 32 | }).removeClass('on-top').addClass('on-bottom') 33 | else 34 | popover_el.css({ 35 | 'top': top + (row_height/2) - (popover_el_height/2) 36 | 'left': '' 37 | 'bottom': 'auto' 38 | }).removeClass('on-top').removeClass('on-bottom') 39 | return true 40 | 41 | return popover 42 | 43 | ] 44 | -------------------------------------------------------------------------------- /app/front/js/services/popover_general_colors_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "GeneralColorsPopover", ['$timeout', ($timeout) -> 2 | 3 | popover = {} 4 | popover.visible = false 5 | popover.rule = {} 6 | popover.hide = -> @visible = false 7 | popover.show = (rule, rule_index) -> 8 | @rule = rule 9 | @visible = true 10 | $timeout => @set_position(rule_index) 11 | return 12 | 13 | popover.set_position = (rule_index) -> 14 | popover_el = $('#gc-popover') 15 | row = $("#general-list .rule-#{rule_index}") 16 | winH = $(window).height() 17 | popover_el_height = popover_el.outerHeight() 18 | row_height = row.outerHeight() 19 | top = row.offset().top 20 | 21 | if (winH - top) < popover_el_height/2 22 | popover_el.css({ 23 | 'top': 'auto' 24 | 'left': '' 25 | 'bottom': winH - top 26 | }).removeClass('on-bottom').addClass('on-top') 27 | else if top < popover_el_height/2 28 | popover_el.css({ 29 | 'left': '' 30 | 'top': top + row_height 31 | 'bottom': 'auto' 32 | }).removeClass('on-top').addClass('on-bottom') 33 | else 34 | popover_el.css({ 35 | 'top': top + (row_height/2) - (popover_el_height/2) 36 | 'left': '' 37 | 'bottom': 'auto' 38 | }).removeClass('on-top').removeClass('on-bottom') 39 | return true 40 | 41 | return popover 42 | 43 | ] 44 | -------------------------------------------------------------------------------- /app/front/js/services/theme_loader_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "ThemeLoader", 2 | ['$http', '$q', '$window', 'FileManager', '$state', 'Editor', 'throbber', 3 | ( $http, $q, $window, FileManager, $state, Editor, throbber) -> 4 | 5 | cache_prefix = "cache_http" 6 | 7 | themes_future = $q.defer() 8 | themes = $http.get("#{$window.API}/gallery.json") 9 | themes.success (data) -> 10 | for theme in data 11 | theme.color_type = if theme.light then 'light' else 'dark' 12 | themes_future.resolve(data) 13 | 14 | load = (theme) -> 15 | if $state.includes("editor.*") 16 | throbber.on(full_window: not Editor.Gallery.visible) 17 | else 18 | throbber.on(full_window: true) 19 | theme_promise = $q.defer() 20 | cached = FileManager.load(theme.url, cache_prefix) 21 | if cached 22 | theme_promise.resolve(cached) 23 | throbber.off() 24 | else 25 | http_get = $http.get("#{$window.API}/get_uri?uri=#{encodeURIComponent(theme.url)}") 26 | http_get.success (data) -> 27 | throbber.off() 28 | theme_promise.resolve(data) 29 | FileManager.save(theme.url, data, cache_prefix) 30 | http_get.error (data) -> 31 | throbber.off() 32 | theme_promise.reject("LOAD ERROR: Can not fetch color scheme") 33 | theme_promise.promise 34 | 35 | return { 36 | themes: themes_future.promise 37 | load: load 38 | } 39 | ] 40 | -------------------------------------------------------------------------------- /app/front/js/template/table_general.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 17 | 19 | 20 | 23 | 24 | 30 | 31 | 32 | 33 |
General ColorsColor
{{gcolor.name}} 21 | 22 | 25 |
29 |
34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # [tmTheme Editor](http://tmtheme-editor.herokuapp.com/) 3 | 4 | **tmTheme Editor** is a color scheme editor for [SublimeText](http://www.sublimetext.com/), 5 | [Textmate](http://macromates.com/) and bunch of other text editors. 6 | It allows you to edit `tmtheme` files easier and faster. it's written in [coffeescript](http://coffeescript.org/) 7 | using [angular.js](angularjs.org) 8 | 9 | ### [tmtheme-editor.herokuapp.com](http://tmtheme-editor.herokuapp.com/) 10 | 11 | ![TmTheme Editor Screenshot](app/front/public/images/screenshots/tmte-screenshot.png) 12 | 13 |

14 | 15 | 16 |

17 | 18 | ## Copyright 19 | **tmThemeEditor** 20 | © Copyright 2012-2015 Allen Bargi 21 | 22 | This program is free software: you can redistribute it and/or modify 23 | it under the terms of the GNU Affero General Public License as 24 | published by the Free Software Foundation, either version 3 of the 25 | License, or (at your option) any later version. 26 | 27 | This program is distributed in the hope that it will be useful, 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | GNU Affero General Public License for more details. 31 | 32 | You should have received a copy of the GNU Affero General Public License 33 | along with this program. If not, see . 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tmtheme-editor", 3 | "version": "0.12.2", 4 | "private": true, 5 | "author": { 6 | "name": "Allen Bargi" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git://github.com/aziz/tmTheme-Editor.git" 11 | }, 12 | "scripts": { 13 | "postinstall": "`npm bin`/bower install", 14 | "start": "`npm bin`/coffee app/back/app.coffee", 15 | "prod": "NODE_ENV=production PORT=9090 `npm bin`/coffee app/back/app.coffee", 16 | "build": "`npm bin`/gulp" 17 | }, 18 | "engines": { 19 | "node": "5.x.x", 20 | "npm": "3.x.x" 21 | }, 22 | "dependencies": { 23 | "body-parser": "1.13.1", 24 | "compression": "1.5.0", 25 | "cookie-parser": "1.3.5", 26 | "errorhandler": "1.4.0", 27 | "express-session": "1.11.3", 28 | "method-override": "2.3.3", 29 | "morgan": "1.6.0", 30 | "uglify-js": "2.4.23", 31 | "bower": "1.7.7", 32 | "request": "2.58.0", 33 | "coffee-script": "1.9.3", 34 | "connect-assets": "4.7.1", 35 | "csswring": "3.0.5", 36 | "ect": "0.5.9", 37 | "express": "4.13.0", 38 | "less": "2.5.1", 39 | "sugar": "1.4.1", 40 | "ng-templatecache": "0.1.4", 41 | "mincer": "1.2.5" 42 | }, 43 | "devDependencies": { 44 | "gulp": "3.9.0", 45 | "gulp-clean": "0.3.1", 46 | "gulp-concat": "2.5.2", 47 | "gulp-ext-replace": "0.2.0", 48 | "gulp-initial-cleaning": "0.0.1", 49 | "gulp-mincer": "0.0.2", 50 | "gulp-minify-css": "1.1.6", 51 | "gulp-minify-html": "1.0.3", 52 | "gulp-remote-src": "0.3.0", 53 | "gulp-uglify": "1.2.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/services/color_service_spec.coffee: -------------------------------------------------------------------------------- 1 | describe 'Service: Color', -> 2 | 3 | beforeEach(module('ThemeEditor')) 4 | 5 | it 'parses normal hex color', inject (Color) -> 6 | expect(Color.parse('#333333')).toBe('#333333') 7 | 8 | it 'parses hex color with alpha channel', inject (Color) -> 9 | expect(Color.parse('#333333cc')).toBe('rgba(51, 51, 51, 0.8)') 10 | expect(Color.parse('#33333300')).toBe('rgba(51, 51, 51, 0)') 11 | expect(Color.parse('#333333ff')).toBe('rgb(51, 51, 51)') 12 | 13 | it 'labels dark colors as dark and light colors as light', inject (Color) -> 14 | expect(Color.light_or_dark('#fff')).toBe('light') 15 | expect(Color.light_or_dark('#999')).toBe('light') 16 | expect(Color.light_or_dark('#000')).toBe('dark') 17 | expect(Color.light_or_dark('#666')).toBe('dark') 18 | 19 | it 'darkens/lightens colors properly', inject (Color) -> 20 | expect(Color.darken('#f00', 10)).toEqual('hsl(0, 100%, 40%)') 21 | expect(Color.darken('#f00', 30)).toEqual('hsl(0, 100%, 20%)') 22 | expect(Color.lighten('#f00', 10)).toEqual('hsl(0, 100%, 60%)') 23 | expect(Color.lighten('#f00', 30)).toEqual('hsl(0, 100%, 80%)') 24 | 25 | it 'detects colors correctly', inject (Color) -> 26 | expect(Color.is_color('not_color')).toBeFalsy() 27 | expect(Color.is_color('#22')).toBeFalsy() 28 | expect(Color.is_color('#a')).toBeFalsy() 29 | expect(Color.is_color('#aaa')).toBeTruthy() 30 | expect(Color.is_color('#aaaaaa')).toBeTruthy() 31 | expect(Color.is_color('#aaaaaaff')).toBeTruthy() 32 | 33 | xit 'brightness_contrast', -> 34 | xit 'invert, sepia, solarize', -> 35 | 36 | -------------------------------------------------------------------------------- /app/front/css/app/stats.less: -------------------------------------------------------------------------------- 1 | @import (reference) "lib/bootstrap_mixins.less"; 2 | @import (reference) "lib/mixins"; 3 | @import (reference) "lib/variables"; 4 | 5 | .progress { 6 | @pwidth: 400px; 7 | position: absolute; 8 | width: @pwidth; 9 | top: 12px; 10 | left: 50%; 11 | margin-left: -1 * @pwidth/2; 12 | border: 1px solid #969696; 13 | height: 12px; 14 | border-radius: 99px; 15 | @bs: 0 1px 0 rgba(255,255,255,.5) , inset 0 1px 3px rgba(0,0,0,.3); 16 | .box-shadow(@bs); 17 | 18 | .bar { 19 | @bs: 0 1px 0 rgba(255,255,255,.5) , inset 0 1px 3px rgba(0,0,0,.3); 20 | .box-shadow(@bs); 21 | .transition(none); 22 | -webkit-animation: progress-bar-stripes 800ms linear infinite !important; 23 | -moz-animation: progress-bar-stripes 800ms linear infinite !important; 24 | -ms-animation: progress-bar-stripes 800ms linear infinite !important; 25 | -o-animation: progress-bar-stripes 800ms linear infinite !important; 26 | animation: progress-bar-stripes 800ms linear infinite !important; 27 | } 28 | } 29 | 30 | #stats-tabs { 31 | position: fixed; 32 | left: 8px; 33 | right: 8px; 34 | top: 44px; 35 | } 36 | 37 | #stats-tables { 38 | position: fixed; 39 | left: 8px; 40 | right: 8px; 41 | top: 82px; 42 | bottom: 0; 43 | overflow: scroll; 44 | 45 | table { 46 | font-family: @monoFontFamily; 47 | 48 | th.active { 49 | background-color: #eee; 50 | } 51 | } 52 | } 53 | 54 | .stats-color-box { 55 | display: inline-block; 56 | width: 28px; 57 | height: 16px; 58 | border: 1px solid #000; 59 | position: relative; 60 | top: 2px; 61 | } 62 | -------------------------------------------------------------------------------- /app/front/js/config/routes.coffee: -------------------------------------------------------------------------------- 1 | Application.config ['$stateProvider', '$urlRouterProvider', '$locationProvider', ($stateProvider, $urlRouterProvider, $locationProvider) -> 2 | $locationProvider.hashPrefix '!' 3 | $urlRouterProvider.otherwise 'editor/theme/Monokai' 4 | 5 | $stateProvider 6 | .state 'editor', { 7 | url: '/editor' 8 | views: { 9 | '@': { 10 | templateUrl: 'template/editor.html' 11 | } 12 | 'gallery@editor': { 13 | controller: 'galleryController' 14 | templateUrl: 'template/gallery.html' 15 | } 16 | } 17 | } 18 | 19 | .state 'editor.gallery', { 20 | url: '^/editor/theme/:theme' 21 | views: { 22 | 'main': { 23 | templateUrl: 'template/main.html' 24 | controller: 'editorController' 25 | } 26 | } 27 | resolve: Application.editorData 28 | } 29 | 30 | .state 'editor.url', { 31 | url: '^/editor/url/*theme' 32 | views: { 33 | 'main': { 34 | templateUrl: 'template/main.html' 35 | controller: 'editorController' 36 | } 37 | } 38 | resolve: Application.urlData 39 | } 40 | 41 | .state 'editor.local', { 42 | url: '^/editor/local/:theme' 43 | views: { 44 | 'main': { 45 | templateUrl: 'template/main.html' 46 | controller: 'editorController' 47 | } 48 | } 49 | resolve: Application.localData 50 | } 51 | 52 | .state 'stats', { 53 | url: '/stats' 54 | templateUrl: 'template/stats.html' 55 | controller: 'statsController' 56 | } 57 | return 58 | ] 59 | -------------------------------------------------------------------------------- /app/front/js/services/scope_matcher_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "ScopeMatcher", ['Theme', (Theme) -> 2 | preview_root_scope = -> 3 | lang = $('#preview > pre').attr('class') 4 | root = '' 5 | root = lang.replace(/ng-\w+/g,'').trim().split(' ').join('.') if lang 6 | root 7 | 8 | element_scope = (scope, event, reverse=false) -> 9 | result = [scope] 10 | element = $(event.target) 11 | element.parents('s').each (index, item) -> 12 | result.push( $(item).data().entityScope ) 13 | return 14 | 15 | if reverse 16 | lang = element.closest('span.l').attr('class') 17 | output = '' 18 | output += lang.replace(/l l-\d+\s/,'').trim().split(' ').join('.') + ' ' if lang 19 | output += result.reverse().join(' ') 20 | return output 21 | else 22 | result.join(' ') 23 | 24 | bestMachingThemeRule = (active_scope) -> 25 | return unless Theme.json.settings 26 | bestMatch = 0 27 | candidates = Theme.json.settings.findAll (item) -> 28 | return false unless item.scope 29 | item_scopes = item.scope.split(',').map((s) -> s.trim()) 30 | match = item_scopes.filter (item_scope) -> 31 | item_scopes_arr = item_scope.split('.') 32 | active_scope_arr = active_scope.split('.') 33 | isMatching = (item_scopes_arr.subtract(active_scope_arr)).length == 0 34 | bestMatch = item_scopes_arr.length if isMatching && item_scopes_arr.length > bestMatch 35 | return isMatching && item_scopes_arr.length >= bestMatch 36 | return item if match.length 37 | candidates.last() 38 | 39 | { 40 | element_scope 41 | preview_root_scope 42 | bestMachingThemeRule 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /app/front/js/services/throbber_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "throbber", [ -> 2 | 3 | throbber = {} 4 | spinner_options = { 5 | lines: 13, # The number of lines to draw 6 | length: 10, # The length of each line 7 | width: 10, # The line thickness 8 | radius: 31, # The radius of the inner circle 9 | corners: 0.9, # Corner roundness (0..1) 10 | rotate: 0, # The rotation offset 11 | direction: 1, # 1: clockwise, -1: counterclockwise 12 | color: '#fff', # #rgb or #rrggbb 13 | speed: 1.4, # Rounds per second 14 | trail: 31, # Afterglow percentage 15 | shadow: false, # Whether to render a shadow 16 | hwaccel: true, # Whether to use hardware acceleration 17 | className: 'spinner', # The CSS class to assign to the spinner 18 | zIndex: 2e9, # The z-index (defaults to 2000000000) 19 | top: 'auto', # Top position relative to parent in px 20 | left: 'auto' # Left position relative to parent in px 21 | } 22 | element = $("#loading") 23 | spinner = new Spinner(spinner_options).spin(element[0]) 24 | loading_counter = 0 25 | 26 | throbber.on = (opt) -> 27 | loading_counter += 1 28 | # console.log "On #{loading_counter}" 29 | if opt && opt.full_window 30 | element.show().addClass("show full_window") 31 | else 32 | element.show().addClass("show") 33 | return 34 | 35 | throbber.off = -> 36 | loading_counter -= 1 if loading_counter > 0 37 | # console.log "Off #{loading_counter}" 38 | element.removeClass("show").hide().removeClass("full_window") if loading_counter == 0 39 | return 40 | 41 | throbber.visible = -> loading_counter > 0 42 | 43 | return throbber 44 | ] 45 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/css.txt: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: arial; 3 | } 4 | 5 | h1, p, table { 6 | background-color:#CCC; 7 | border: 1px solid; 8 | color:#39F; 9 | text-align: center; 10 | width: 100%; 11 | } 12 | 13 | /* Bootstrap snipit */ 14 | @media (min-width: 992px) and (max-width: 1199px) { 15 | .hidden-md, 16 | tr.hidden-md, 17 | th.hidden-md, 18 | td.hidden-md { 19 | display: none !important; 20 | } 21 | } 22 | 23 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ 24 | @-webkit-keyframes pulse { 25 | 50% { 26 | -webkit-transform: scale(1.1); 27 | transform: scale(1.1); 28 | } 29 | } 30 | @keyframes pulse { 31 | 50% { 32 | -webkit-transform: scale(1.1); 33 | -ms-transform: scale(1.1); 34 | transform: scale(1.1); 35 | } 36 | } 37 | .pulse { 38 | -webkit-animation-name: pulse; 39 | animation-name: pulse; 40 | } 41 | 42 | .addon-store .pagehead h1 { display: inline-block } 43 | .addon-store .addon-summary:after { clear: both } 44 | 45 | .addon-store .addon-icon { 46 | background: #fff; 47 | border: 1px solid #ddd; 48 | box-shadow: 0 1px 2px rgba(0,0,0,0.15); 49 | float: left; 50 | height: 80px; 51 | margin-right: 14px; 52 | width: 80px; 53 | } 54 | 55 | .addon-store .developer-callout { 56 | background-color: #f1f1f1; 57 | background-image: -moz-linear-gradient(#fafafa, #f1f1f1); 58 | background-image: -webkit-linear-gradient(#fafafa, #f1f1f1); 59 | background-image: linear-gradient(#fafafa, #f1f1f1); 60 | background-repeat: repeat-x; 61 | border: 1px solid #ddd; 62 | border-bottom: 1px solid #ccc; 63 | border-radius: 3px; 64 | box-shadow: inset 0 1px 0 #fff, 0 1px 5px #f1f1f1; 65 | margin-top: 40px; 66 | text-shadow: 0 1px 0 #fff; 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/front/css/app/scope_hunter.less: -------------------------------------------------------------------------------- 1 | @import (reference) "lib/bootstrap_mixins.less"; 2 | @import (reference) "lib/mixins"; 3 | @import (reference) "lib/variables"; 4 | 5 | .hunted { 6 | &, & * { 7 | background-color: #FFE792 !important; 8 | color: #00161B !important; 9 | } 10 | } 11 | 12 | .scope_hunter_box { 13 | position: absolute; 14 | bottom: 33px; 15 | background-color: #FFF; 16 | left: 0; 17 | right: 0; 18 | height: 175px; 19 | font-size: 11px; 20 | line-height: 16px; 21 | color: #303942; 22 | z-index: 9999; 23 | overflow: scroll; 24 | 25 | .header { 26 | background-color: #eee; 27 | border-bottom: 1px solid #BDBDBD; 28 | border-top: 1px solid #BDBDBD; 29 | padding: 0 10px; 30 | } 31 | 32 | .content { 33 | padding: 0 10px; 34 | 35 | .key { 36 | color: #B771BD; 37 | display: inline-block; 38 | vertical-align: text-top; 39 | } 40 | 41 | .sep { 42 | color: #82888d; 43 | font-weight: bold; 44 | display: inline-block; 45 | vertical-align: text-top; 46 | } 47 | .color { 48 | display: inline-block; 49 | vertical-align: text-top; 50 | width: 8px; 51 | height: 8px; 52 | border: 1px solid #b0b0b0; 53 | position: relative; 54 | top: 3px; 55 | } 56 | 57 | .icon { 58 | position: relative; 59 | top: 2px; 60 | color: #FF6666; 61 | } 62 | 63 | &.apprearance .value { 64 | font-family: @monoFontFamily; 65 | } 66 | } 67 | 68 | .element-scope, .value { 69 | color: #FF6666; 70 | max-width: 600px; 71 | display: inline-block; 72 | vertical-align: text-top; 73 | } 74 | } 75 | 76 | .scope_hunter_toggle_btn { 77 | position: absolute; 78 | bottom: 3px; 79 | left: 4px; 80 | z-index: 998; 81 | 82 | .icon { 83 | position: relative; 84 | top: 2px; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/ruby.txt: -------------------------------------------------------------------------------- 1 | class HTMLProcessor 2 | 3 | # called before parsing anything 4 | def start_parsing(scope_name) 5 | @line = "" 6 | @offset = 0 7 | @text= [] 8 | end 9 | 10 | # called after parsing everything 11 | def end_parsing(scope_name) 12 | @text.each_with_index do |line, index| 13 | @text[index] = "#{line}" 14 | end 15 | puts @text.join("") 16 | end 17 | 18 | # called before processing a line 19 | def new_line(line_content) 20 | @offset = 0 21 | @line = line_content.clone 22 | @text << @line 23 | end 24 | 25 | def open_tag(tag_name, position_in_current_line) 26 | tag = "" 27 | @line.insert(position_in_current_line + @offset, tag) 28 | @offset += tag.size 29 | end 30 | 31 | def close_tag(tag_name, position_in_current_line) 32 | tag = "" 33 | @line.insert(position_in_current_line + @offset, tag) 34 | @offset += tag.size 35 | end 36 | 37 | end 38 | 39 | syntax = Textpow.syntax('ruby') # or 'source.ruby' or 'lib/textpow/syntax/source.ruby.syntax' 40 | processor = HTMLProcessor.new 41 | syntax.parse(text, processor) 42 | 43 | require File.expand_path('../boot', __FILE__) 44 | 45 | require 'rails/all' 46 | 47 | if defined?(Bundler) 48 | # If you precompile assets before deploying to production, use this line 49 | Bundler.require(*Rails.groups(:assets => %w(development test))) 50 | # If you want your assets lazily compiled in production, use this line 51 | # Bundler.require(:default, :assets, Rails.env) 52 | end 53 | 54 | require 'rubygems' 55 | 56 | # Set up gems listed in the Gemfile. 57 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 58 | 59 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /app/front/js/directives/inline_edit.coffee: -------------------------------------------------------------------------------- 1 | Application.directive 'inlineEdit', ['ScopeMatcher', (ScopeMatcher) -> 2 | link: ($scope, element, attr) -> 3 | preview_el = $('#preview') 4 | 5 | $scope.$watch 'ScopeHunter.visible', (visible) -> 6 | if visible 7 | preview_el.unbind 'dblclick' 8 | else 9 | preview_el.bind 'dblclick', inline_edit_click_event 10 | 11 | inline_edit_click_event = (event) -> 12 | entityScope = event.target.dataset.entityScope 13 | if entityScope 14 | final_element_scope = ScopeMatcher.element_scope(entityScope, event) 15 | active_scope_rule = ScopeMatcher.bestMachingThemeRule(final_element_scope) 16 | showPopover(active_scope_rule, event) 17 | 18 | $scope.$on '$destroy', -> preview_el.unbind 'dblclick' 19 | 20 | showPopover = (rule, event) -> 21 | $scope.$apply -> 22 | $scope.$parent.NewPopover.visible = false 23 | $scope.$parent.EditPopover.rule = rule 24 | $scope.$parent.EditPopover.visible = true 25 | 26 | win_height = $(window).height() 27 | popover = $('#edit-popover') 28 | galley_offset = if popover.is('.slide') then $('#gallery').width() else 0 29 | offset_left = (popover.width() / 2) + 10 + galley_offset 30 | elm = $(event.target) 31 | elm_offset = elm.offset() 32 | 33 | if (win_height - elm_offset.top) < 360 34 | popover.css({ 35 | top: 'auto' 36 | left: elm_offset.left + (elm.outerWidth()/2) - offset_left 37 | bottom: win_height - elm_offset.top + 5 38 | }).removeClass('on-bottom').addClass('on-top') 39 | else 40 | popover.css({ 41 | left: elm_offset.left + (elm.outerWidth()/2) - offset_left 42 | top: elm_offset.top + 30 43 | bottom: 'auto' 44 | }).removeClass('on-top').addClass('on-bottom') 45 | 46 | return 47 | ] 48 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/js.txt: -------------------------------------------------------------------------------- 1 | // Cross-browser xml parsing 2 | var parseXML = function( data ) { 3 | var xml, tmp; 4 | if ( !data || typeof data !== "string" ) { 5 | return null; 6 | } 7 | try { 8 | if ( window.DOMParser ) { // Standard 9 | tmp = new DOMParser(); 10 | xml = tmp.parseFromString( data , "text/xml" ); 11 | } else { // IE 12 | xml = new ActiveXObject( "Microsoft.XMLDOM" ); 13 | xml.async = false; 14 | xml.loadXML( data ); 15 | } 16 | } catch( e ) { 17 | xml = undefined; 18 | } 19 | if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { 20 | jQuery.error( "Invalid XML: " + data ); 21 | } 22 | return xml; 23 | }; 24 | 25 | // Bind a function to a context, optionally partially applying any arguments. 26 | var proxy = function( fn, context ) { 27 | var tmp, args, proxy; 28 | 29 | if ( typeof context === "string" ) { 30 | tmp = fn[ context ]; 31 | context = fn; 32 | fn = tmp; 33 | } 34 | 35 | // Quick check to determine if target is callable, in the spec 36 | // this throws a TypeError, but we will just return undefined. 37 | if ( !jQuery.isFunction( fn ) ) { 38 | return undefined; 39 | } 40 | 41 | // Simulated bind 42 | args = core_slice.call( arguments, 2 ); 43 | proxy = function() { 44 | return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); 45 | }; 46 | 47 | // Set the guid of unique handler to the same of original handler, so it can be removed 48 | proxy.guid = fn.guid = fn.guid || jQuery.guid++; 49 | 50 | return proxy; 51 | }; 52 | 53 | Sound.play = function() {} 54 | Sound.prototype = { something; } 55 | Sound.prototype.play = function() {} 56 | Sound.prototype.play = myfunc 57 | var parser = document.createElement('a'); 58 | parser.href = "http://example.com:3000/pathname/?search=test#hash"; 59 | parser.hostname; // => "example.com" 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /app/front/js/template/scope_hunter/scope_hunter.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Current Scope 4 |
5 |
{{ hovered_element_scope }}
6 | 7 |
Matching Rule
8 |
9 |
10 | Name: 11 | 12 | {{ hovered_rule.name }} 13 | 14 | 15 | 16 |
17 |
18 | Scope: 19 | 20 | {{ hovered_rule.scope }} 21 | 22 | 23 |
24 |
25 | 26 |
Appearance
27 |
28 |
29 | Foreground: 30 | {{ hovered_rule.settings.foreground | uppercase }} 34 | 35 |
36 |
37 | Background: 38 | {{ hovered_rule.settings.background | uppercase }} 42 |
43 |
44 | Font Style: 45 | {{ hovered_rule.settings.fontStyle }} 46 |
47 |
48 |
49 | -------------------------------------------------------------------------------- /app/front/js/template/header.html: -------------------------------------------------------------------------------- 1 | 53 | -------------------------------------------------------------------------------- /app/front/css/app/header.less: -------------------------------------------------------------------------------- 1 | @import (reference) "lib/bootstrap_mixins.less"; 2 | @import (reference) "lib/mixins"; 3 | @import (reference) "lib/variables"; 4 | 5 | header { 6 | #gradient > .vertical(#E8E8E8,#C2C2C2); 7 | height: @header_height - 10; 8 | border-bottom: 1px solid #989898; 9 | position: relative; 10 | padding:5px 6px; 11 | 12 | .btn-toolbar {margin-top: 0;} 13 | .sep { 14 | height: @header_height; 15 | width: 1px; 16 | background: linear-gradient(to top, rgba(152,152,152,1) 0%,rgba(152,152,152,0) 60%); 17 | position: absolute; 18 | bottom: 0; 19 | left: 400px; 20 | 21 | &:after { 22 | content: ""; 23 | height: @header_height; 24 | width: 1px; 25 | display: block; 26 | position: relative; 27 | right: -1px; 28 | background: linear-gradient(to top, rgba(255,255,255,0.6) 0%,rgba(255,255,255,0) 60%); 29 | } 30 | } 31 | 32 | .dl-save { 33 | position: absolute; 34 | top: 5px; 35 | left: 252px; 36 | } 37 | 38 | .new-upload { 39 | position: absolute; 40 | top: 5px; 41 | left: 90px; 42 | } 43 | 44 | .theme-title { 45 | text-shadow: 0 1px 0 rgba(255,255,255,.4); 46 | color: #333; 47 | font-weight: bold; 48 | position: absolute; 49 | top: 10px; 50 | left: 410px; 51 | font-size: 16px; 52 | line-height: 16px; 53 | 54 | .icon-globe { 55 | color: #000; 56 | font-size: 13px; 57 | opacity: 0.5; 58 | &:hover { opacity: 1; } 59 | } 60 | } 61 | 62 | .links { 63 | position: absolute; 64 | top: 5px; 65 | right: 12px; 66 | } 67 | 68 | .icon-gear { 69 | width: 15px; 70 | height: 15px; 71 | } 72 | 73 | 74 | .icon-color-adjustments { 75 | width: 20px; 76 | height: 15px; 77 | background-position: 0 0; 78 | } 79 | 80 | .upload { 81 | position: absolute; 82 | top: 0; 83 | bottom: 0; 84 | left: 0; 85 | right: 0; 86 | width: 100%; 87 | opacity: 0; 88 | cursor: pointer; 89 | } 90 | 91 | .btn-small .caret { 92 | margin-top: 7px; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/front/js/services/plist_to_json.coffee: -------------------------------------------------------------------------------- 1 | Application.value "plist_to_json", (plist) -> 2 | 3 | # https://github.com/sandofsky/plist-to-json 4 | # jsonify function is taken from w3schools http://www.w3schools.com/Dom/dom_loadxmldoc.asp 5 | 6 | jsonify = (tag) -> 7 | switch tag.nodeName 8 | when "dict" 9 | d = {} 10 | i = 0 11 | nodes = tag.childNodes 12 | while i < nodes.length 13 | #console.log nodes[i], nodes[i].nodeName 14 | if nodes[i].nodeName is "key" 15 | key = nodes[i].textContent 16 | i++ 17 | i++ while nodes[i].nodeName is "#text" 18 | d[key] = jsonify(nodes[i]) 19 | i++ 20 | d 21 | when "array" 22 | a = [] 23 | i = 0 24 | nodes = tag.childNodes 25 | while i < nodes.length 26 | a.push jsonify(nodes[i]) unless nodes[i].nodeName is "#text" 27 | i++ 28 | a 29 | when "string" then tag.textContent.unescapeHTML() 30 | when "data" then tag.textContent.unescapeHTML() 31 | when "real" then tag.textContent 32 | when "integer" then tag.textContent 33 | when "true" then true 34 | when "false" then false 35 | else console.log "node name is not valid: ", tag.nodeName, tag 36 | 37 | loadXMLString = (txt) -> 38 | try 39 | xmlDoc = new ActiveXObject("Microsoft.XMLDOM") 40 | xmlDoc.async = "false" 41 | xmlDoc.loadXML txt 42 | return (xmlDoc) 43 | catch e 44 | try 45 | parser = new DOMParser() 46 | xmlDoc = parser.parseFromString(txt, "text/xml") 47 | return (xmlDoc) 48 | catch e 49 | console.log e.message 50 | null 51 | 52 | # removing all the comments 53 | plist_without_comments = plist.replace(//g, '').trim().replace(/\s&\s/, '&') 54 | # console.log(plist_without_comments) 55 | doc = loadXMLString(plist_without_comments) 56 | i = 0 57 | while i < doc.documentElement.childNodes.length 58 | return jsonify(doc.documentElement.childNodes[i]) unless doc.documentElement.childNodes[i].nodeName is "#text" 59 | i++ 60 | -------------------------------------------------------------------------------- /app/front/js/directives/scopebar.coffee: -------------------------------------------------------------------------------- 1 | Application.directive 'scopeBar', ['ScopeMatcher', '$timeout', (ScopeMatcher, $timeout) -> 2 | replace: true 3 | templateUrl: 'template/scope_hunter/scope_hunter.html' 4 | link: ($scope, element, attr) -> 5 | preview_el = $('#preview') 6 | 7 | $scope.scroll_rule_into_view = (rule) -> 8 | $scope.Editor.Sidebar.current_tab = 'scopes' 9 | $scope.Editor.ScopeHunter.hovered_rule = rule 10 | scroll_finished = -> 11 | $timeout(-> 12 | $scope.$apply -> $scope.Editor.ScopeHunter.hovered_rule = {} 13 | return 14 | , 2000) 15 | scroll_into_view = -> 16 | $('.hovered').scrollintoview(duration: 400, direction: 'vertical') 17 | scroll_finished() 18 | return 19 | $timeout scroll_into_view 20 | return 21 | 22 | mousemove = (event) -> 23 | entityScope = event.target.dataset.entityScope 24 | $scope.$apply -> 25 | if entityScope 26 | final_element_scope = ScopeMatcher.element_scope(entityScope, event) 27 | active_scope_rule = ScopeMatcher.bestMachingThemeRule(final_element_scope) 28 | hovered_element_scope = ScopeMatcher.element_scope(entityScope, event, true) 29 | else 30 | active_scope_rule = {} 31 | hovered_element_scope = ScopeMatcher.preview_root_scope() 32 | $scope.$parent.hovered_element_scope = hovered_element_scope 33 | $scope.$parent.hovered_rule = active_scope_rule 34 | 35 | preview_el.bind 'mousemove', mousemove 36 | 37 | preview_el.bind 'click', (event) -> 38 | entityScope = event.target.dataset.entityScope 39 | element = $(event.target) 40 | if entityScope 41 | if element.hasClass('hunted') 42 | preview_el.bind 'mousemove', mousemove 43 | element.removeClass 'hunted' 44 | else 45 | mousemove(event) 46 | preview_el.find('.hunted').removeClass('hunted') 47 | preview_el.unbind 'mousemove' 48 | element.addClass 'hunted' 49 | 50 | $scope.$on '$destroy', -> 51 | preview_el.find('.hunted').removeClass('hunted') 52 | preview_el.unbind 'mousemove' 53 | preview_el.unbind 'click' 54 | 55 | return 56 | ] 57 | -------------------------------------------------------------------------------- /app/front/js/services/json_to_plist.coffee: -------------------------------------------------------------------------------- 1 | Application.value "json_to_plist", (json) -> 2 | 3 | header = ''' 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ''' 13 | footer = '\n' 14 | content = "" 15 | indent_level = 1 16 | 17 | plist_object2string = (obj, oindent) -> 18 | obj_str = "" 19 | for own okey,ovalue of obj 20 | continue if okey == "$$hashKey" 21 | obj_str += "#{'\t'.repeat(oindent)}#{okey}\n" 22 | switch typeof ovalue 23 | when "string" 24 | obj_str += "#{'\t'.repeat(oindent)}#{ovalue.escapeHTML()}\n" 25 | when "object" 26 | if Array.isArray(ovalue) 27 | obj_str += "#{'\t'.repeat(oindent)}\n#{plist_array2string(ovalue, oindent + 1)}#{'\t'.repeat(oindent)}\n" 28 | else 29 | obj_str += "#{'\t'.repeat(oindent)}\n#{plist_object2string(ovalue, oindent + 1)}#{'\t'.repeat(oindent)}\n" 30 | obj_str 31 | 32 | plist_array2string = (array, aindent) -> 33 | arr_str = "" 34 | for item in array 35 | arr_str += "#{'\t'.repeat(aindent)}\n#{plist_object2string(item, aindent + 1)}#{'\t'.repeat(aindent)}\n" 36 | arr_str 37 | 38 | for own key,value of json 39 | content += "#{'\t'.repeat(indent_level)}#{key}\n" 40 | switch typeof value 41 | when "string" 42 | content += "#{'\t'.repeat(indent_level)}#{value.escapeHTML()}\n" 43 | when "object" 44 | if Array.isArray(value) 45 | content += "#{'\t'.repeat(indent_level)}\n#{plist_array2string(value, indent_level+1)}#{'\t'.repeat(indent_level)}\n" 46 | else 47 | content += "#{'\t'.repeat(indent_level)}\n#{plist_object2string(value, indent_level+1)}#{'\t'.repeat(indent_level)}\n" 48 | 49 | (header + content + footer).trim() 50 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/c-sharp.txt: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Abp.Domain.Entities; 4 | using Abp.Domain.Repositories; 5 | 6 | namespace Abp.MemoryDb.Repositories 7 | { 8 | //TODO: Implement thread-safety..? 9 | public class MemoryRepository : AbpRepositoryBase 10 | where TEntity : class, IEntity 11 | { 12 | private readonly IMemoryDatabaseProvider _databaseProvider; 13 | protected MemoryDatabase Database { get { return _databaseProvider.Database; } } 14 | 15 | protected List Table { get { return Database.Set(); } } 16 | 17 | private readonly MemoryPrimaryKeyGenerator _primaryKeyGenerator; 18 | 19 | public MemoryRepository(IMemoryDatabaseProvider databaseProvider) 20 | { 21 | _databaseProvider = databaseProvider; 22 | _primaryKeyGenerator = new MemoryPrimaryKeyGenerator(); 23 | } 24 | 25 | public override IQueryable GetAll() 26 | { 27 | return Table.AsQueryable(); 28 | } 29 | 30 | public override TEntity Insert(TEntity entity) 31 | { 32 | if (entity.IsTransient()) 33 | { 34 | entity.Id = _primaryKeyGenerator.GetNext(); 35 | } 36 | 37 | Table.Add(entity); 38 | return entity; 39 | } 40 | 41 | public override TEntity Update(TEntity entity) 42 | { 43 | var index = Table.FindIndex(e => EqualityComparer.Default.Equals(e.Id, entity.Id)); 44 | if (index >= 0) 45 | { 46 | Table[index] = entity; 47 | } 48 | 49 | return entity; 50 | } 51 | 52 | public override void Delete(TEntity entity) 53 | { 54 | Delete(entity.Id); 55 | } 56 | 57 | public override void Delete(TPrimaryKey id) 58 | { 59 | var index = Table.FindIndex(e => EqualityComparer.Default.Equals(e.Id, id)); 60 | if (index >= 0) 61 | { 62 | Table.RemoveAt(index); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/coffee.txt: -------------------------------------------------------------------------------- 1 | Application.directive "scopeBar", [], -> 2 | replace: true 3 | templateUrl: 'partials/scope_bar' 4 | 5 | link: (scope, element, attr) -> 6 | preview = element.prev() 7 | preview.bind "mouseover", (event) -> 8 | active = {} 9 | active.scope = event.target.dataset.entityScope 10 | 11 | if active.scope 12 | active_scope_rule = getScopeSettings(active.scope) 13 | active.name = active_scope_rule.name if active_scope_rule 14 | 15 | scope.$apply -> 16 | # Highlight in sidebar 17 | scope.$parent.hovered_rule = active_scope_rule 18 | 19 | preview.bind "mouseout", (event) -> 20 | # Unhighlight in sidebar 21 | scope.$parent.hovered_rule = null 22 | 23 | preview.bind "dblclick", (event) -> 24 | active = {} 25 | active.scope = event.target.dataset.entityScope 26 | 27 | if active.scope 28 | active_scope_rule = getScopeSettings(active.scope) 29 | showPopover active_scope_rule, event 30 | 31 | 32 | 33 | showPopover = (rule, event) -> 34 | scope.$apply -> 35 | scope.$parent.new_popover_visible = false 36 | scope.$parent.popover_rule = rule 37 | scope.$parent.edit_popover_visible = true 38 | 39 | popover = $("#edit-popover") 40 | 41 | if popover.is('.slide') 42 | left_offset = $("#gallery").width() 43 | else 44 | left_offset = 0 45 | 46 | offset = 47 | left: (popover.width() / 2) + 10 + left_offset 48 | top: 24 49 | 50 | popover.css({ 51 | "left": event.pageX - offset.left 52 | "top": event.pageY + offset.top 53 | }).addClass("on-bottom") 54 | 55 | 56 | getScopeSettings = (active_scope) -> 57 | return unless scope.$parent.jsonTheme.settings 58 | 59 | return scope.$parent.jsonTheme.settings.find (item) -> 60 | return unless item.scope 61 | 62 | item_scopes = item.scope.split(', ') 63 | 64 | match = item_scopes.filter (item_scope) -> 65 | item_scopes_arr = item_scope.split('.') 66 | active_scope_arr = active_scope.split('.') 67 | 68 | return (item_scopes_arr.subtract active_scope_arr).length < 1 69 | 70 | return item if match.length 71 | 72 | -------------------------------------------------------------------------------- /app/front/js/template/action_bar.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 9 |
10 |
13 | 14 |
15 |
18 | 19 |
20 |
21 |
22 | 23 |
24 |
25 |
26 | 31 | 32 | 33 | 38 |
39 | 40 |
43 | 44 |
45 |
46 |
47 | 48 |
49 |
50 |
51 | -------------------------------------------------------------------------------- /app/front/js/template/color_picker.html: -------------------------------------------------------------------------------- 1 |
5 | 6 |
7 |
    8 |
  • picker
  • 11 |
  • sliders
  • 14 |
  • palette
  • 17 |
18 | 19 |
20 | 21 |
22 |
23 | 24 |
25 |
26 |
27 | 31 |
32 |
33 | 34 | 35 | 36 |
37 |
38 | 41 | 42 | 43 | 44 |
45 |
46 | 47 |
48 |
49 |
50 |
51 |
52 |
53 | 54 |
55 | 56 |
57 | -------------------------------------------------------------------------------- /app/front/js/template/dialog_general_colors.html: -------------------------------------------------------------------------------- 1 |
4 | 5 |
6 | 7 |
8 |
12 | Reset 13 | 14 |
15 | 16 |
17 | 18 |
19 |
20 | 21 |
22 | 23 |
25 |
26 | 27 |
28 | 29 |
30 |
31 | 32 |
33 | 34 | 35 | 38 | 39 | {{GeneralColorsPopover.rule.editor_support.text}} 40 |
41 | 42 | 43 |
44 | 47 | 49 |
50 |
51 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/c.txt: -------------------------------------------------------------------------------- 1 | /* stringmerge.c -- Given two sorted files of strings, it creates 2 | * a sorted file consisting of all their elements. 3 | * The names of the files are passed as command 4 | * line parameters. 5 | */ 6 | 7 | #include 8 | #define MAXBUFFER 128 9 | 10 | int getline(FILE * fd, char buff[], int nmax){ 11 | /* It reads a line from fd and stores up to nmax of 12 | * its characters to buff. 13 | */ 14 | char c; 15 | int n=0; 16 | 17 | while ((c=getc(fd))!='\n'){ 18 | if(c==EOF)return EOF; 19 | if(n 4 | 5 | $scope.Color = Color 6 | $scope.Theme = Theme 7 | $scope.FileManager = FileManager 8 | $scope.local_themes = [] 9 | $scope.external_themes = [] 10 | $scope.themes = [] 11 | $scope.filtered_gallery = [] 12 | $scope.gallery_filter = Editor.Gallery.filter 13 | 14 | ThemeLoader.themes.then (data) -> 15 | $scope.themes_data = data 16 | render_theme_list(data) 17 | 18 | render_theme_list = (list) -> 19 | return unless list 20 | data = $filter('filter')(list, $scope.gallery_filter) 21 | $scope.filtered_gallery = data 22 | themes_html = "" 23 | selected = Editor.current_theme.name 24 | for theme in data 25 | themes_html += """ 26 |
  • 27 | 28 | 29 | #{theme.name} 30 | 31 |
  • 32 | """ 33 | $scope.themes = themes_html 34 | 35 | $scope.toggle_gallery_type_filter = (type) -> 36 | if $scope.gallery_filter.color_type == type 37 | delete $scope.gallery_filter.color_type 38 | else 39 | $scope.gallery_filter.color_type = type 40 | 41 | $scope.$watch 'gallery_filter', (n, o) -> 42 | return unless n 43 | render_theme_list($scope.themes_data) 44 | , true 45 | 46 | $scope.remove_local_theme = (theme) -> 47 | FileManager.remove(theme) 48 | $location.path('/') if $location.path() == "/editor/local/#{theme.name}" 49 | 50 | $scope.remove_external_theme = (theme) -> 51 | FileManager.remove_external_theme(theme) 52 | $location.path('/') if $location.path() == "/editor/url/#{theme.url}" 53 | 54 | #----------------------------------------------------------------------- 55 | $scope.$watchCollection 'Editor.current_theme', -> 56 | $scope.selected_theme = Editor.current_theme.name 57 | render_theme_list($scope.themes_data) 58 | 59 | $scope.$watch 'FileManager.local_themes', (n, o) -> 60 | $scope.local_themes = n 61 | , true 62 | 63 | $scope.$watch 'FileManager.external_themes', (n, o) -> 64 | $scope.external_themes = n 65 | , true 66 | 67 | return 68 | ] 69 | -------------------------------------------------------------------------------- /app/front/css/lib/mixins.less: -------------------------------------------------------------------------------- 1 | .seo-helper() { 2 | img:not([alt]), 3 | img[alt=""], 4 | img[alt^=" "], 5 | a[href=""], 6 | a[href^=" "], 7 | *[title=""], 8 | *[id=""] { 9 | outline: 2px solid red !important; 10 | outline-offset: 3px !important; 11 | } 12 | } 13 | 14 | // TEXT 15 | // -------------------------------------------------- 16 | .ellipsis { 17 | -ms-text-overflow: ellipsis; 18 | text-overflow: ellipsis; 19 | white-space: nowrap; 20 | overflow: hidden; 21 | } 22 | 23 | .prevent-text-breakouts() { 24 | -ms-word-break: break-all; 25 | word-break: break-all; 26 | word-break: break-word; 27 | -webkit-hyphens: auto; 28 | -moz-hyphens: auto; 29 | hyphens: auto; 30 | } 31 | 32 | .nowrap { 33 | white-space: nowrap; 34 | } 35 | 36 | .align-begin { 37 | text-align: left; 38 | } 39 | 40 | .align-end { 41 | text-align: right; 42 | } 43 | 44 | 45 | // Transitions and Transform 46 | // -------------------------------------------------- 47 | .transition-delay(@delay: 300ms) { 48 | -webkit-transition-delay: @delay; 49 | -moz-transition-delay: @delay; 50 | transition-delay: @delay; 51 | } 52 | 53 | .transition-property(@property: all) { 54 | -webkit-transition-property: @property; 55 | -moz-transition-property: @property; 56 | transition-property: @property; 57 | } 58 | 59 | .transition-duration(@duration: 1s) { 60 | -webkit-transition-duration: @duration; 61 | -moz-transition-duration: @duration; 62 | transition-duration: @duration; 63 | } 64 | 65 | .transition-timing-function(@timing-function: ease-in-out) { 66 | -webkit-transition-timing-function: @timing-function; 67 | -moz-transition-timing-function: @timing-function; 68 | transition-timing-function: @timing-function; 69 | } 70 | 71 | // Generic Transform 72 | .transform(@transform) { 73 | -webkit-transform: @transform; 74 | -moz-transform: @transform; 75 | transform: @transform; 76 | } 77 | 78 | .transform-origin(...) { 79 | -webkit-transform-origin: @arguments; 80 | -moz-transform-origin: @arguments; 81 | transform-origin: @arguments; 82 | } 83 | 84 | .perspective(...) { 85 | -webkit-perspective: @arguments; 86 | -moz-perspective: @arguments; 87 | perspective: @arguments; 88 | } 89 | 90 | .preserve-3d() { 91 | -webkit-transform-style: preserve-3d; 92 | -moz-transform-style: preserve-3d; 93 | transform-style: preserve-3d; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/java.txt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class Life { 4 | public static void show(boolean[][] grid){ 5 | String s = ""; 6 | for(boolean[] row : grid){ 7 | for(boolean val : row) 8 | if(val) 9 | s += "*"; 10 | else 11 | s += "."; 12 | s += "\n"; 13 | } 14 | System.out.println(s); 15 | } 16 | 17 | public static boolean[][] gen(){ 18 | boolean[][] grid = new boolean[10][10]; 19 | for(int r = 0; r < 10; r++) 20 | for(int c = 0; c < 10; c++) 21 | if( Math.random() > 0.7 ) 22 | grid[r][c] = true; 23 | return grid; 24 | } 25 | 26 | public static void main(String[] args){ 27 | boolean[][] world = gen(); 28 | show(world); 29 | System.out.println(); 30 | world = nextGen(world); 31 | show(world); 32 | Scanner s = new Scanner(System.in); 33 | while(s.nextLine().length() == 0){ 34 | System.out.println(); 35 | world = nextGen(world); 36 | show(world); 37 | 38 | } 39 | } 40 | 41 | public static boolean[][] nextGen(boolean[][] world){ 42 | boolean[][] newWorld 43 | = new boolean[world.length][world[0].length]; 44 | int num; 45 | for(int r = 0; r < world.length; r++){ 46 | for(int c = 0; c < world[0].length; c++){ 47 | num = numNeighbors(world, r, c); 48 | if( occupiedNext(num, world[r][c]) ) 49 | newWorld[r][c] = true; 50 | } 51 | } 52 | return newWorld; 53 | } 54 | 55 | public static boolean occupiedNext(int numNeighbors, boolean occupied){ 56 | if( occupied && (numNeighbors == 2 || numNeighbors == 3)) 57 | return true; 58 | else if (!occupied && numNeighbors == 3) 59 | return true; 60 | else 61 | return false; 62 | } 63 | 64 | private static int numNeighbors(boolean[][] world, int row, int col) { 65 | int num = world[row][col] ? -1 : 0; 66 | for(int r = row - 1; r <= row + 1; r++) 67 | for(int c = col - 1; c <= col + 1; c++) 68 | if( inbounds(world, r, c) && world[r][c] ) 69 | num++; 70 | 71 | return num; 72 | } 73 | 74 | private static boolean inbounds(boolean[][] world, int r, int c) { 75 | return r >= 0 && r < world.length && c >= 0 && 76 | c < world[0].length; 77 | } 78 | 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /app/back/app.coffee: -------------------------------------------------------------------------------- 1 | express = require 'express' 2 | bodyParser = require 'body-parser' 3 | methodOverride = require 'method-override' 4 | logger = require 'morgan' 5 | errorhandler = require 'errorhandler' 6 | cookieParser = require 'cookie-parser' 7 | session = require 'express-session' 8 | compress = require 'compression' 9 | fs = require 'fs' 10 | less = require 'less' 11 | assets_manager = require 'connect-assets' 12 | ECT = require 'ect' 13 | 14 | config = require './config' 15 | ngTemplatesEngine = require './lib/ngtemplate' 16 | pages_controller = require './controllers/pages_controller' 17 | 18 | 19 | app = module.exports = express() 20 | 21 | app.set 'view engine', 'html' 22 | app.set 'views', "#{__dirname}/views" 23 | app.set 'port', config.port 24 | app.set 'x-powered-by', false 25 | 26 | app.engine 'html', ECT(watch: true, root: "#{__dirname}/views", ext : '.html').render 27 | 28 | app.use compress() 29 | app.use express.static "#{__dirname}/../front/public" 30 | app.use bodyParser.json() 31 | app.use bodyParser.urlencoded({extended: true }) 32 | app.use cookieParser(config.cookie_secret) 33 | app.use methodOverride() 34 | 35 | register_mincer_engines = (instance) -> 36 | instance.environment.registerEngine('.html', ngTemplatesEngine) 37 | 38 | if config.env_development 39 | app.use logger("dev", skip: (req, res) -> res.statusCode is 304) 40 | app.use assets_manager({"paths": config.assets}, register_mincer_engines) 41 | 42 | if config.env_production 43 | log = fs.createWriteStream config.log_file, {flags: 'w'} 44 | app.use logger("combined", stream: log) 45 | app.use assets_manager({ 46 | buildDir: config.assets_build_dir, 47 | paths: config.assets, 48 | compress: true, 49 | fingerprinting: true 50 | }, register_mincer_engines) 51 | 52 | app.use (req, res, next) -> 53 | res.header 'Access-Control-Allow-Origin', '*' 54 | res.header 'Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept' 55 | next() 56 | 57 | app.use '/', pages_controller 58 | 59 | if config.env_development 60 | app.use errorhandler() 61 | 62 | app.use (req, res, next) -> 63 | res.status 404 64 | if req.accepts 'html' 65 | res.render 'errors/404' 66 | return 67 | if req.accepts 'json' 68 | res.send { error: 'Not found' } 69 | return 70 | 71 | app.use (err, req, res, next) -> 72 | res.status 500 73 | res.render 'errors/500' 74 | 75 | unless module.parent 76 | app.listen(config.port) 77 | console.log "Express server listening on port #{config.port} in '#{config.env}' environment" 78 | -------------------------------------------------------------------------------- /app/front/js/services/hud_adjustments_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "HUDEffects", ['Theme', 'Color', (Theme, Color) -> 2 | hud = {} 3 | 4 | original_colors = {} 5 | original_gcolors = [] 6 | reset_colors = {} 7 | reset_gcolors = [] 8 | 9 | hud.brightness = 0 10 | hud.contrast = 0 11 | hud.hue = 0 12 | hud.saturation = 0 13 | hud.lightness = 0 14 | hud.visible = false 15 | hud.colorize = false 16 | hud.apply_to_general = false 17 | 18 | hud.hide = -> @visible = false 19 | hud.toggle = -> 20 | if not @visible 21 | original_colors = angular.copy(Theme.json.settings) 22 | original_gcolors = angular.copy(Theme.gcolors) 23 | reset_colors = angular.copy(Theme.json.settings) 24 | reset_gcolors = angular.copy(Theme.gcolors) 25 | @visible = not @visible 26 | 27 | hud.reset_changes = -> 28 | Theme.json.settings = angular.copy(reset_colors) 29 | Theme.gcolors = angular.copy(reset_gcolors) 30 | original_colors = angular.copy(Theme.json.settings) 31 | original_gcolors = angular.copy(Theme.gcolors) 32 | @brightness = 0 33 | @contrast = 0 34 | @hue = 0 35 | @saturation = 0 36 | @lightness = 0 37 | 38 | hud.filter_colors = (filter) -> 39 | for rule in Theme.json.settings 40 | if rule.settings 41 | if rule.settings.foreground 42 | rule.settings.foreground = Color[filter](rule.settings.foreground) 43 | if rule.settings.background 44 | rule.settings.background = Color[filter](rule.settings.background) 45 | for rule in Theme.gcolors 46 | continue unless rule.isColor 47 | rule.color = Color[filter](rule.color) 48 | original_colors = angular.copy(Theme.json.settings) 49 | original_gcolors = angular.copy(Theme.gcolors) 50 | return 51 | 52 | hud.update_colors = (-> 53 | for rule,i in original_colors 54 | if rule.scope && rule.settings 55 | if fg = rule.settings.foreground 56 | Theme.json.settings[i].settings.foreground = apply_color_adjustments(fg) 57 | if bg = rule.settings.background 58 | Theme.json.settings[i].settings.background = apply_color_adjustments(bg) 59 | if @apply_to_general 60 | for rule,i in original_gcolors 61 | continue unless rule.isColor 62 | Theme.gcolors[i].color = apply_color_adjustments(rule.color) 63 | return 64 | ).throttle(40) 65 | 66 | apply_color_adjustments = (color) -> 67 | ca1 = Color.change_hsl(color, hud.hue, hud.saturation, hud.lightness, hud.colorize) 68 | ca2 = Color.brightness_contrast(ca1, hud.brightness, hud.contrast) 69 | return ca2 70 | 71 | return hud 72 | ] 73 | -------------------------------------------------------------------------------- /app/front/js/services/file_manager_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "FileManager", ['$q', ($q) -> 2 | 3 | PREFIX = "LOCAL" 4 | FM = {} 5 | 6 | _store = (key, value) -> 7 | try 8 | return localStorage.setItem(key, value) 9 | catch e 10 | if e.code == 22 11 | localStorage.clear() 12 | return localStorage.setItem(key, value) 13 | 14 | _read_from_file_system = (file) -> 15 | deferred = $q.defer() 16 | reader = new FileReader() 17 | reader.readAsText(file) 18 | reader.onload = do (file) -> 19 | (e) -> 20 | _store("#{PREFIX}/#{file.name}", e.target.result.trim()) 21 | deferred.resolve(file.name) 22 | return deferred.promise 23 | 24 | Object.defineProperty FM, "external_themes", { 25 | get: -> angular.fromJson(localStorage.getItem("external_themes") || []) 26 | set: (new_val) -> _store('external_themes', angular.toJson(new_val)) 27 | } 28 | 29 | Object.defineProperty FM, "local_themes", { 30 | get: -> angular.fromJson(localStorage.getItem("local_themes") || []) 31 | set: (new_val) -> _store('local_themes', angular.toJson(new_val)) 32 | } 33 | 34 | FM.add_external_theme = (theme_obj) -> 35 | return if @external_themes.find(theme_obj) 36 | @external_themes = @external_themes.add(theme_obj) 37 | 38 | # TODO: rename to add_local_theme 39 | # Add returns an array of promises 40 | FM.add_local_theme = (files) -> 41 | file_names = for file in files 42 | # TODO: if name exisits and size is the same rename 43 | continue unless file.name.endsWith(/\.(hidden-)?[tT]m[Tt]heme/) 44 | name = file.name 45 | @local_themes = @local_themes.add({name: name}) 46 | _read_from_file_system(file).then (file_name) -> file_name 47 | 48 | file_names 49 | 50 | FM.add_from_memory = (file_name, content) -> 51 | @local_themes = @local_themes.add({name: file_name}) 52 | @save(file_name, content) 53 | 54 | FM.load = (file_name, prefix = PREFIX) -> 55 | localStorage.getItem("#{prefix}/#{file_name}") 56 | 57 | FM.save = (file_name, content, prefix = PREFIX) -> 58 | _store("#{prefix}/#{file_name}", content) 59 | 60 | FM.remove = (file, prefix = PREFIX) -> 61 | @local_themes = @local_themes.remove((item) -> item.name == file.name) 62 | localStorage.removeItem("#{prefix}/#{file.name}") 63 | 64 | FM.remove_external_theme = (file) -> 65 | @external_themes = @external_themes.remove((item) -> item.url == file.url) 66 | localStorage.removeItem("cache_http/#{file.url}") 67 | 68 | FM.clear_cache = -> 69 | for key of localStorage 70 | localStorage.removeItem(key) if key.startsWith("cache") 71 | 72 | return FM 73 | ] 74 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/go.txt: -------------------------------------------------------------------------------- 1 | // Reading and writing files are basic tasks needed for 2 | // many Go programs. First we'll look at some examples of 3 | // reading files. 4 | 5 | package main 6 | 7 | import ( 8 | "bufio" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | "os" 13 | ) 14 | 15 | // Reading files requires checking most calls for errors. 16 | // This helper will streamline our error checks below. 17 | func check(e error) { 18 | if e != nil { 19 | panic(e) 20 | } 21 | } 22 | 23 | func main() { 24 | 25 | // Perhaps the most basic file reading task is 26 | // slurping a file's entire contents into memory. 27 | dat, err := ioutil.ReadFile("/tmp/dat") 28 | check(err) 29 | fmt.Print(string(dat)) 30 | 31 | // You'll often want more control over how and what 32 | // parts of a file are read. For these tasks, start 33 | // by `Open`ing a file to obtain an `os.File` value. 34 | f, err := os.Open("/tmp/dat") 35 | check(err) 36 | 37 | // Read some bytes from the beginning of the file. 38 | // Allow up to 5 to be read but also note how many 39 | // actually were read. 40 | b1 := make([]byte, 5) 41 | n1, err := f.Read(b1) 42 | check(err) 43 | fmt.Printf("%d bytes: %s\n", n1, string(b1)) 44 | 45 | // You can also `Seek` to a known location in the file 46 | // and `Read` from there. 47 | o2, err := f.Seek(6, 0) 48 | check(err) 49 | b2 := make([]byte, 2) 50 | n2, err := f.Read(b2) 51 | check(err) 52 | fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2)) 53 | 54 | // The `io` package provides some functions that may 55 | // be helpful for file reading. For example, reads 56 | // like the ones above can be more robustly 57 | // implemented with `ReadAtLeast`. 58 | o3, err := f.Seek(6, 0) 59 | check(err) 60 | b3 := make([]byte, 2) 61 | n3, err := io.ReadAtLeast(f, b3, 2) 62 | check(err) 63 | fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3)) 64 | 65 | // There is no built-in rewind, but `Seek(0, 0)` 66 | // accomplishes this. 67 | _, err = f.Seek(0, 0) 68 | check(err) 69 | 70 | // The `bufio` package implements a buffered 71 | // reader that may be useful both for its efficiency 72 | // with many small reads and because of the additional 73 | // reading methods it provides. 74 | r4 := bufio.NewReader(f) 75 | b4, err := r4.Peek(5) 76 | check(err) 77 | fmt.Printf("5 bytes: %s\n", string(b4)) 78 | 79 | // Close the file when you're done (usually this would 80 | // be scheduled immediately after `Open`ing with 81 | // `defer`). 82 | f.Close() 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/html.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Bootstrap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 53 | 54 | 55 |
    56 |
    57 |

    Bootstrap 3

    58 |

    Sleek, intuitive, and powerful mobile-first front-end framework for faster and easier web development.

    59 |

    60 | Download Bootstrap 61 |

    62 |
    63 |
    64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /app/front/js/controllers/color_picker_controller.coffee: -------------------------------------------------------------------------------- 1 | Application.controller 'colorpickerController', 2 | ['$scope', 'Color', 'Theme', ($scope, Color, Theme) -> 3 | 4 | $scope.picker_options = { inline: true, letterCase: 'uppercase' } 5 | $scope.Theme = Theme 6 | $scope.colorpalette = [] 7 | $scope.color = { 8 | hex: null 9 | alpha: 1 10 | rgba: {} 11 | hsla: {} 12 | hsva: {} 13 | } 14 | 15 | $scope.update_current_color = (new_color) -> 16 | $scope.CP.rule[$scope.CP.selector] = Color.tm_encode(Color.tm_decode(new_color)) 17 | 18 | $scope.update_alpha = -> 19 | current_color = Color.tm_decode($scope.CP.rule[$scope.CP.selector]) 20 | current_color.setAlpha($scope.color.alpha/100) 21 | $scope.CP.rule[$scope.CP.selector] = Color.tm_encode(current_color) 22 | 23 | update_colors = (color) -> 24 | return unless color 25 | decoded_color = Color.tm_decode($scope.CP.rule[$scope.CP.selector]) 26 | 27 | rgba = decoded_color.toRgb() 28 | hsla = decoded_color.toHsl() 29 | hsva = decoded_color.toHsv() 30 | 31 | hsla.h = hsla.h.round() 32 | hsla.s = (hsla.s*100).round() 33 | hsla.l = (hsla.l*100).round() 34 | 35 | hsva.h = hsva.h.round() 36 | hsva.s = (hsva.s*100).round() 37 | hsva.v = (hsva.v*100).round() 38 | 39 | $scope.color.hex = decoded_color.toHexString() 40 | $scope.color.alpha = (hsla.a*100).round() 41 | $scope.color.rgba = rgba 42 | $scope.color.hsla = hsla 43 | $scope.color.hsva = hsva 44 | 45 | $scope.$watch 'Theme.json', (-> $scope.colorpalette = $scope.Theme.color_palette()), true 46 | $scope.$watch 'Theme.gcolors', (-> $scope.colorpalette = $scope.Theme.color_palette()), true 47 | 48 | $scope.$watch "CP.rule[CP.selector]", update_colors 49 | $scope.$watch "color.hex", (color) -> 50 | return unless color 51 | current_color = Color.tm_decode($scope.color.hex) 52 | current_color.setAlpha($scope.color.alpha/100) 53 | $scope.CP.rule[$scope.CP.selector] = Color.tm_encode(current_color) 54 | 55 | $scope.select_color_from_palette = (color) -> 56 | $scope.CP.rule[$scope.CP.selector] = Color.tm_encode(color) 57 | 58 | $scope.slider_gradient = (source, base, min, max, step) -> 59 | checkboard_bg = 'url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAAAAACoWZBhAAAAFklEQVR4AWP4DwJnQIAkJpgE80lhAgBENVmnMdln/AAAAABJRU5ErkJggg==)' 60 | steps = [] 61 | for value in [min..max] by step 62 | step_color = angular.copy(source) 63 | step_color[base] = value 64 | steps.push "#{Color.tm_decode(step_color).toHslString()} #{(value/max)*100}%" 65 | "background-image: linear-gradient(to right, #{steps.join(',')}), #{checkboard_bg};" 66 | 67 | return 68 | ] 69 | -------------------------------------------------------------------------------- /app/front/js/template/hud_colors.html: -------------------------------------------------------------------------------- 1 |
    3 |
    4 | Color Adjustments 5 | 6 |
    7 |
    8 | 9 |
    10 | Reset 11 | 14 |
    15 | 16 |
    17 | 18 |
    19 | 20 | 21 | 22 |
    23 | 24 |
    25 | 26 | 27 | 28 |
    29 | 30 |
    31 | 32 |
    33 | 36 |
    37 | 38 |
    39 | 40 | 41 | 42 |
    43 | 44 |
    45 | 46 | 47 | 48 |
    49 | 50 |
    51 | 52 | 53 | 54 |
    55 | 56 |
    57 | 58 |
    59 | Invert    60 | Sepia    61 | Grayscale 62 |
    63 | 64 |
    65 |
    66 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var coffeescript = require('coffee-script/register'); 2 | var path = require('path'); 3 | var Mincer = require('mincer'); 4 | 5 | var gulp = require('gulp'); 6 | var clean = require('gulp-clean'); 7 | var concat = require('gulp-concat'); 8 | var ext_replace = require('gulp-ext-replace'); 9 | var cleaning = require('gulp-initial-cleaning'); 10 | var minCSS = require('gulp-minify-css'); 11 | var uglify = require('gulp-uglify'); 12 | var remoteSrc = require('gulp-remote-src'); 13 | var minifyHTML = require('gulp-minify-html'); 14 | var mince = require('gulp-mincer'); 15 | 16 | var environment = new Mincer.Environment(); 17 | var ngTemplatesEngine = require('./app/back/lib/ngtemplate.coffee'); 18 | 19 | var server; 20 | var DIST_DIR = "dist"; 21 | var ASSETS_DIR = DIST_DIR + "/assets"; 22 | var ASSETS_PATH = ["app/front/js", "app/front/css", "bower_components"]; 23 | var ASSETS = { 24 | external_scripts: "app/front/js/*.js", 25 | scripts: "app/front/js/*.coffee", 26 | styles: "app/front/css/*.less" 27 | }; 28 | 29 | environment.registerEngine('.html', ngTemplatesEngine); 30 | environment.appendPath(ASSETS_PATH); 31 | 32 | cleaning({tasks: ['default'], folders: ['dist']}); 33 | 34 | gulp.task('js-ext', function() { 35 | return gulp.src(ASSETS.external_scripts) 36 | .pipe(mince(environment)) 37 | .pipe(uglify()) 38 | .pipe(gulp.dest(ASSETS_DIR)); 39 | }); 40 | 41 | gulp.task('js', function() { 42 | return gulp.src(ASSETS.scripts) 43 | .pipe(mince(environment)) 44 | .pipe(uglify()) 45 | .pipe(ext_replace('.js')) 46 | .pipe(gulp.dest(ASSETS_DIR)); 47 | }); 48 | 49 | gulp.task('css', function() { 50 | return gulp.src(ASSETS.styles) 51 | .pipe(mince(environment)) 52 | .pipe(minCSS()) 53 | .pipe(ext_replace('.css')) 54 | .pipe(gulp.dest(ASSETS_DIR)); 55 | }); 56 | 57 | gulp.task('html', function() { 58 | process.env.NODE_ENV = 'production'; 59 | var app = require('./app/back/app.coffee'); 60 | server = app.listen(9898); 61 | var opts = { 62 | conditionals: true, 63 | spare: true, 64 | loose: true 65 | }; 66 | return remoteSrc(['/'], { base: 'http://localhost:9898' }) 67 | .pipe(concat('index.html')) 68 | .pipe(minifyHTML(opts)) 69 | .pipe(gulp.dest(DIST_DIR)); 70 | }); 71 | 72 | gulp.task('static-assets', function() { 73 | gulp.src([ 74 | 'app/front/public/**', 75 | '!app/front/public/assets{,/**}' 76 | ]).pipe(gulp.dest(DIST_DIR)); 77 | }); 78 | 79 | gulp.task('default', ['js-ext', 'js', 'css', 'html', 'static-assets'], function() { 80 | var cleanups = ['app/front/public/assets', 'production.log']; 81 | gulp.src(cleanups, {read: false}).pipe(clean()); 82 | server.close(); 83 | }); 84 | -------------------------------------------------------------------------------- /app/front/js/template/table_scopes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 21 | 22 | 32 | 33 | 39 | 40 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
    Scope NameFGBGBIU
    30 | {{ rule.name || rule.scope }} 31 | 34 |
    38 |
    41 |
    45 |
    54 | -------------------------------------------------------------------------------- /app/front/js/controllers/stats_controller.coffee: -------------------------------------------------------------------------------- 1 | Application.controller 'statsController', 2 | ['Color', 'ThemeLoader', 'plist_to_json', '$scope', '$location', 3 | ( Color, ThemeLoader , plist_to_json, $scope, $location) -> 4 | 5 | $scope.themes = [] 6 | $scope.scopes_data = [] 7 | $scope.general_data = [] 8 | $scope.progress = 0 9 | 10 | $scope.sort = {} 11 | $scope.sort.predicate = 'name' 12 | $scope.sort.reverse = false 13 | 14 | $scope.scopes_predicate = 'count' 15 | $scope.scopes_reverse = true 16 | 17 | $scope.current_tab = 'themes' 18 | progress_unit = 0 19 | 20 | load_theme = (theme) -> 21 | 22 | process_theme = (theme_data) -> 23 | theme.xmlTheme = theme_data 24 | theme.jsonTheme = plist_to_json(theme.xmlTheme) 25 | theme.bgcolor = theme.jsonTheme.settings.first().settings.background 26 | console.log theme unless theme.bgcolor 27 | theme.is_light = Color.light_or_dark(theme.bgcolor[0..6]) == 'light' 28 | theme.general_settings_count = Object.extended(theme.jsonTheme.settings.first().settings).size() 29 | process = -> process_scopes(theme.jsonTheme.settings) 30 | setTimeout(process, 0) 31 | 32 | handle_load_error = -> 33 | $scope.update_progress() 34 | 35 | theme_loader_promise = ThemeLoader.load(theme) 36 | theme_loader_promise.then(process_theme, handle_load_error) 37 | 38 | process_scopes = (settings) -> 39 | for key,value of settings[0].settings 40 | found_object = $scope.general_data.find((x) -> x.name == key) 41 | if found_object 42 | found_object.count = found_object.count + 1 43 | else 44 | $scope.general_data.push({ name: key, count: 1, values: [] }) 45 | if key.endsWith('Options') 46 | current_object = $scope.general_data.find((x) -> x.name == key) 47 | current_object.values.push(value) 48 | 49 | for d in $scope.general_data 50 | d.grouped_values = d.values.groupBy() 51 | 52 | for setting in settings 53 | if setting.scope 54 | scopes = setting.scope.split(',').map((s) -> s.trim()) 55 | for scope in scopes 56 | found_object = $scope.scopes_data.find((x) -> x.name == scope) 57 | if found_object 58 | found_object.count = found_object.count + 1 59 | else 60 | $scope.scopes_data.push({ name: scope, count: 1}) 61 | $scope.update_progress() 62 | 63 | ThemeLoader.themes.then (data) -> 64 | $scope.themes = data 65 | progress_unit = 100.0/data.length 66 | for theme in $scope.themes 67 | load_theme(theme) 68 | 69 | $scope.update_progress = -> 70 | $scope.$apply -> 71 | $scope.progress += progress_unit 72 | 73 | $scope.gallery = -> 74 | $scope.themes.map (theme) -> 75 | { 76 | name: theme.name 77 | url: theme.url 78 | light: theme.is_light 79 | } 80 | 81 | return 82 | ] 83 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/python.txt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import re 5 | import sublime 6 | import sublime_plugin 7 | from datetime import datetime 8 | 9 | 10 | class SublimeTasksBase(sublime_plugin.TextCommand): 11 | def run(self, edit): 12 | self.open_tasks_bullet = self.view.settings().get('open_tasks_bullet') 13 | self.done_tasks_bullet = self.view.settings().get('done_tasks_bullet') 14 | self.date_format = self.view.settings().get('date_format') 15 | if self.view.settings().get('done_tag'): 16 | self.done_tag = "@done" 17 | else: 18 | self.done_tag = "" 19 | self.runCommand(edit) 20 | 21 | 22 | class NewCommand(SublimeTasksBase): 23 | def runCommand(self, edit): 24 | for region in self.view.sel(): 25 | line = self.view.line(region) 26 | line_contents = self.view.substr(line).rstrip() 27 | has_bullet = re.match('^(\s*)[' + re.escape(self.open_tasks_bullet) + re.escape(self.done_tasks_bullet) + ']', self.view.substr(line)) 28 | current_scope = self.view.scope_name(self.view.sel()[0].b) 29 | if has_bullet: 30 | grps = has_bullet.groups() 31 | line_contents = self.view.substr(line) + '\n' + grps[0] + self.open_tasks_bullet + ' ' 32 | self.view.replace(edit, line, line_contents) 33 | elif 'header' in current_scope: 34 | header = re.match('^(\s*)\S+', self.view.substr(line)) 35 | if header: 36 | grps = header.groups() 37 | line_contents = self.view.substr(line) + '\n' + grps[0] + ' ' + self.open_tasks_bullet + ' ' 38 | else: 39 | line_contents = ' ' + self.open_tasks_bullet + ' ' 40 | self.view.replace(edit, line, line_contents) 41 | end = self.view.sel()[0].b 42 | pt = sublime.Region(end, end) 43 | self.view.sel().clear() 44 | self.view.sel().add(pt) 45 | else: 46 | has_space = re.match('^(\s+)(.*)', self.view.substr(line)) 47 | if has_space: 48 | grps = has_space.groups() 49 | spaces = grps[0] 50 | line_contents = spaces + self.open_tasks_bullet + ' ' + grps[1] 51 | self.view.replace(edit, line, line_contents) 52 | else: 53 | line_contents = ' ' + self.open_tasks_bullet + ' ' + self.view.substr(line) 54 | self.view.replace(edit, line, line_contents) 55 | end = self.view.sel()[0].b 56 | pt = sublime.Region(end, end) 57 | self.view.sel().clear() 58 | self.view.sel().add(pt) 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/haskell.txt: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Paths_postgrest (version) 4 | 5 | import PostgREST.App 6 | import PostgREST.Middleware 7 | import PostgREST.Error(errResponse) 8 | 9 | import Control.Monad (unless) 10 | import Control.Monad.IO.Class (liftIO) 11 | import Data.String.Conversions (cs) 12 | import Network.Wai (strictRequestBody) 13 | import Network.Wai.Middleware.Cors (cors) 14 | import Network.Wai.Handler.Warp hiding (Connection) 15 | import Network.Wai.Middleware.Gzip (gzip, def) 16 | import Network.Wai.Middleware.Static (staticPolicy, only) 17 | import Network.Wai.Middleware.RequestLogger (logStdout) 18 | import Data.List (intercalate) 19 | import Data.Version (versionBranch) 20 | import qualified Hasql as H 21 | import qualified Hasql.Postgres as P 22 | import Options.Applicative hiding (columns) 23 | 24 | import PostgREST.Config (AppConfig(..), argParser, corsPolicy) 25 | 26 | main :: IO () 27 | main = do 28 | let opts = info (helper <*> argParser) $ 29 | fullDesc 30 | <> progDesc ( 31 | "PostgREST " 32 | <> prettyVersion 33 | <> " / create a REST API to an existing Postgres database" 34 | ) 35 | parserPrefs = prefs showHelpOnError 36 | conf <- customExecParser parserPrefs opts 37 | let port = configPort conf 38 | 39 | unless (configSecure conf) $ 40 | putStrLn "WARNING, running in insecure mode, auth will be in plaintext" 41 | unless ("secret" /= configJwtSecret conf) $ 42 | putStrLn "WARNING, running in insecure mode, JWT secret is the default value" 43 | Prelude.putStrLn $ "Listening on port " ++ 44 | (show $ configPort conf :: String) 45 | 46 | let pgSettings = P.ParamSettings (cs $ configDbHost conf) 47 | (fromIntegral $ configDbPort conf) 48 | (cs $ configDbUser conf) 49 | (cs $ configDbPass conf) 50 | (cs $ configDbName conf) 51 | appSettings = setPort port 52 | . setServerName (cs $ "postgrest/" <> prettyVersion) 53 | $ defaultSettings 54 | middle = logStdout 55 | . (if configSecure conf then redirectInsecure else id) 56 | . gzip def . cors corsPolicy 57 | . staticPolicy (only [("favicon.ico", "static/favicon.ico")]) 58 | 59 | poolSettings <- maybe (fail "Improper session settings") return $ 60 | H.poolSettings (fromIntegral $ configPool conf) 30 61 | pool :: H.Pool P.Postgres 62 | <- H.acquirePool pgSettings poolSettings 63 | 64 | runSettings appSettings $ middle $ \req respond -> do 65 | body <- strictRequestBody req 66 | resOrError <- liftIO $ H.session pool $ H.tx Nothing $ 67 | authenticated conf (app conf body) req 68 | either (respond . errResponse) respond resOrError 69 | 70 | where 71 | prettyVersion = intercalate "." $ map show $ versionBranch version 72 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/ocaml.txt: -------------------------------------------------------------------------------- 1 | open Lexer_flow 2 | module Ast = Spider_monkey_ast 3 | open Ast 4 | module Error = Parse_error 5 | module SSet = Set.Make(String) 6 | module SMap = Map.Make(String) 7 | 8 | type lex_mode = 9 | | NORMAL_LEX 10 | | TYPE_LEX 11 | | JSX_TAG 12 | | JSX_CHILD 13 | 14 | let mode_to_string = function 15 | | NORMAL_LEX -> "NORMAL" 16 | | TYPE_LEX -> "TYPE" 17 | | JSX_TAG -> "JSX TAG" 18 | | JSX_CHILD -> "JSX CHILD" 19 | 20 | let lex lex_env = function 21 | | NORMAL_LEX -> token lex_env 22 | | TYPE_LEX -> type_token lex_env 23 | | JSX_TAG -> lex_jsx_tag lex_env 24 | | JSX_CHILD -> lex_jsx_child lex_env 25 | 26 | type env = { 27 | errors : (Loc.t * Error.t) list ref; 28 | comments : Comment.t list ref; 29 | labels : SSet.t; 30 | lb : Lexing.lexbuf; 31 | lookahead : lex_result ref; 32 | last : (lex_env * lex_result) option ref; 33 | priority : int; 34 | strict : bool; 35 | in_export : bool; 36 | in_loop : bool; 37 | in_switch : bool; 38 | in_function : bool; 39 | no_in : bool; 40 | no_call : bool; 41 | no_let : bool; 42 | allow_yield : bool; 43 | (* Use this to indicate that the "()" as in "() => 123" is not allowed in 44 | * this expression *) 45 | error_callback : (env -> Error.t -> unit) option; 46 | lex_mode_stack : lex_mode list ref; 47 | lex_env : lex_env ref; 48 | } 49 | 50 | (* constructor *) 51 | let init_env lb = 52 | let lex_env = new_lex_env lb in 53 | let lex_env, lookahead = lex lex_env NORMAL_LEX in 54 | { 55 | errors = ref []; 56 | comments = ref []; 57 | labels = SSet.empty; 58 | lb = lb; 59 | lookahead = ref lookahead; 60 | last = ref None; 61 | priority = 0; 62 | strict = false; 63 | in_export = false; 64 | in_loop = false; 65 | in_switch = false; 66 | in_function = false; 67 | no_in = false; 68 | no_call = false; 69 | no_let = false; 70 | allow_yield = true; 71 | error_callback = None; 72 | lex_mode_stack = ref [NORMAL_LEX]; 73 | lex_env = ref lex_env; 74 | } 75 | 76 | (* getters: *) 77 | let strict env = env.strict 78 | let lookahead env = !(env.lookahead) 79 | let lb env = env.lb 80 | let lex_mode env = List.hd !(env.lex_mode_stack) 81 | let lex_env env = !(env.lex_env) 82 | let last env = !(env.last) 83 | let in_export env = env.in_export 84 | let comments env = !(env.comments) 85 | let labels env = env.labels 86 | let in_loop env = env.in_loop 87 | let in_switch env = env.in_switch 88 | let in_function env = env.in_function 89 | let allow_yield env = env.allow_yield 90 | let no_in env = env.no_in 91 | let no_call env = env.no_call 92 | let no_let env = env.no_let 93 | let errors env = !(env.errors) 94 | -------------------------------------------------------------------------------- /app/front/js/controllers/preview_controller.coffee: -------------------------------------------------------------------------------- 1 | Application.controller 'previewController', 2 | ['$scope', '$http', 'throbber', 'FileManager', 'Editor', '$window', '$q', '$sce', 3 | ( $scope, $http, throbber, FileManager, Editor, $window, $q, $sce ) -> 4 | 5 | cache_prefix = "cache_sample" 6 | 7 | $scope.colorized = '' 8 | $scope.available_langs = [ 9 | 'C' 10 | 'C++' 11 | 'C#' 12 | 'CoffeeScript' 13 | 'CSS' 14 | 'Erlang' 15 | 'Haskell' 16 | 'HTML' 17 | 'Java' 18 | 'Javascript' 19 | 'Latex' 20 | 'Lua' 21 | 'Objective-C' 22 | 'OCaml' 23 | 'Perl' 24 | 'PHP' 25 | 'Python' 26 | 'R' 27 | 'Ruby' 28 | ] 29 | $scope.current_lang = $.cookie("preview_lang") || 'Javascript' 30 | 31 | $scope.current_lang_for_api = -> 32 | lang = $scope.current_lang 33 | switch lang 34 | when 'C#' then 'c-sharp' 35 | when 'Objective-C' then 'objc' 36 | when 'Javascript' then 'js' 37 | when 'CoffeeScript' then 'coffee' 38 | else lang.toLowerCase() 39 | 40 | $scope.set_lang = (lang) -> $scope.current_lang = lang 41 | 42 | # Custom Code 43 | $scope.custom_code = {} 44 | $scope.custom_code.text = localStorage.getItem('custom_code') || '' 45 | $scope.custom_code.editor_visible = false 46 | 47 | $scope.ScopeHunter = Editor.ScopeHunter 48 | 49 | $scope.update_preview = -> 50 | throbber.on(full_window: true) 51 | $.cookie("preview_lang", $scope.current_lang) 52 | defered_code = $q.defer() 53 | if $scope.custom_code.text.length > 0 54 | localStorage.setItem('custom_code', $scope.custom_code.text) 55 | parser = $http.post("#{$window.API}/parse", {text: $scope.custom_code.text, syntax: $scope.current_lang_for_api()}) 56 | parser.success (data) -> defered_code.resolve(data) 57 | parser.error -> defered_code.resolve("") 58 | else 59 | localStorage.removeItem('custom_code') 60 | lang = $scope.current_lang.toLowerCase() 61 | cached = FileManager.load(lang , cache_prefix) 62 | if cached 63 | defered_code.resolve(cached) 64 | else 65 | sample = $http.get("#{$window.API}/files/samples/compiled/#{$scope.current_lang_for_api()}.html") 66 | sample.success (data) -> 67 | defered_code.resolve(data) 68 | FileManager.save(lang, data, cache_prefix) 69 | sample.error -> 70 | defered_code.resolve("") 71 | 72 | 73 | defered_code.promise.then (data) -> 74 | root_scopes = $("
    #{data}
    ").find("span.l").map((x,item) -> $(item).attr("class").replace(/^l\s/, "").replace(/l-\d+ /, "")) 75 | root_scope = Array.prototype.unique.call(root_scopes) 76 | console.log "Warning: more than one root scope found for this source code" if root_scope.length > 1 77 | $scope.root_scope = root_scope[0] 78 | $scope.colorized = $sce.trustAsHtml(data) 79 | $scope.custom_code.editor_visible = false 80 | throbber.off() 81 | 82 | $scope.$watch 'current_lang', $scope.update_preview 83 | 84 | return 85 | ] 86 | -------------------------------------------------------------------------------- /app/front/js/template/dialog_new.html: -------------------------------------------------------------------------------- 1 |
    4 | 5 | 6 | 10 | 11 | 12 | 13 | 28 | 51 | 52 |
    14 | 15 | 19 | 23 | 27 | 29 | 30 |
    32 |
    36 | Reset 37 | 38 |
    39 | 40 | 41 |
    43 |
    47 | Reset 48 | 49 |
    50 |
    53 | 54 | 55 | 56 | 57 |
    58 | 61 | 64 |
    65 |
    66 | -------------------------------------------------------------------------------- /app/front/js/template/dialog_edit.html: -------------------------------------------------------------------------------- 1 |
    4 | 5 | 9 | 10 | 11 | 12 | 27 | 50 | 51 |
    13 | 14 | 18 | 22 | 26 | 28 | 29 |
    31 |
    35 | Reset 36 | 37 |
    38 | 39 | 40 |
    42 |
    46 | Reset 47 | 48 |
    49 |
    52 | 53 | 54 | 55 | 56 |
    57 | 59 | 61 |
    62 |
    63 | -------------------------------------------------------------------------------- /coffeelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "coffeescript_erroxxxr": { 3 | "level": "error" 4 | }, 5 | "arrow_spacing": { 6 | "name": "arrow_spacing", 7 | "level": "warn" 8 | }, 9 | "no_tabs": { 10 | "name": "no_tabs", 11 | "level": "error" 12 | }, 13 | "no_trailing_whitespace": { 14 | "name": "no_trailing_whitespace", 15 | "level": "error", 16 | "allowed_in_comments": false, 17 | "allowed_in_empty_lines": true 18 | }, 19 | "max_line_length": { 20 | "name": "max_line_length", 21 | "value": 120, 22 | "level": "warn", 23 | "limitComments": true 24 | }, 25 | "line_endings": { 26 | "name": "line_endings", 27 | "level": "ignore", 28 | "value": "unix" 29 | }, 30 | "no_trailing_semicolons": { 31 | "name": "no_trailing_semicolons", 32 | "level": "error" 33 | }, 34 | "indentation": { 35 | "name": "indentation", 36 | "value": 2, 37 | "level": "error" 38 | }, 39 | "camel_case_classes": { 40 | "name": "camel_case_classes", 41 | "level": "error" 42 | }, 43 | "colon_assignment_spacing": { 44 | "name": "colon_assignment_spacing", 45 | "level": "ignore", 46 | "spacing": { 47 | "left": 0, 48 | "right": 0 49 | } 50 | }, 51 | "no_implicit_braces": { 52 | "name": "no_implicit_braces", 53 | "level": "ignore", 54 | "strict": true 55 | }, 56 | "no_plusplus": { 57 | "name": "no_plusplus", 58 | "level": "ignore" 59 | }, 60 | "no_throwing_strings": { 61 | "name": "no_throwing_strings", 62 | "level": "error" 63 | }, 64 | "no_backticks": { 65 | "name": "no_backticks", 66 | "level": "error" 67 | }, 68 | "no_implicit_parens": { 69 | "name": "no_implicit_parens", 70 | "level": "ignore" 71 | }, 72 | "no_empty_param_list": { 73 | "name": "no_empty_param_list", 74 | "level": "ignore" 75 | }, 76 | "no_stand_alone_at": { 77 | "name": "no_stand_alone_at", 78 | "level": "ignore" 79 | }, 80 | "space_operators": { 81 | "name": "space_operators", 82 | "level": "ignore" 83 | }, 84 | "duplicate_key": { 85 | "name": "duplicate_key", 86 | "level": "error" 87 | }, 88 | "empty_constructor_needs_parens": { 89 | "name": "empty_constructor_needs_parens", 90 | "level": "ignore" 91 | }, 92 | "cyclomatic_complexity": { 93 | "name": "cyclomatic_complexity", 94 | "value": 10, 95 | "level": "ignore" 96 | }, 97 | "newlines_after_classes": { 98 | "name": "newlines_after_classes", 99 | "value": 3, 100 | "level": "ignore" 101 | }, 102 | "no_unnecessary_fat_arrows": { 103 | "name": "no_unnecessary_fat_arrows", 104 | "level": "warn" 105 | }, 106 | "missing_fat_arrows": { 107 | "name": "missing_fat_arrows", 108 | "level": "ignore" 109 | }, 110 | "non_empty_constructor_needs_parens": { 111 | "name": "non_empty_constructor_needs_parens", 112 | "level": "ignore" 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/front/js/template/stats/themes_tab.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 14 | 19 | 24 | 29 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 50 | 51 | 52 |
    # 5 | Name 6 | 7 | 8 | 10 | Author 11 | 12 | 13 | 15 | Scopes 16 | 17 | 18 | 20 | General 21 | 22 | 23 | 25 | BG 26 | 27 | 28 | 30 | light/dark 31 | 32 | 33 |
    {{::$index + 1 }}{{::theme.name }}{{::theme.jsonTheme.author.truncate(22) }}{{::theme.jsonTheme.settings.length }}{{::theme.general_settings_count }} 43 | 44 | {{::theme.bgcolor }} 45 | 47 |
    48 |
    49 |
    53 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/lua.txt: -------------------------------------------------------------------------------- 1 | local IO = require "kong.tools.io" 2 | local utils = require "kong.tools.utils" 3 | local cache = require "kong.tools.database_cache" 4 | local stringy = require "stringy" 5 | local constants = require "kong.constants" 6 | local responses = require "kong.tools.responses" 7 | local timestamp = require "kong.tools.timestamp" 8 | 9 | -- Define the plugins to load here, in the appropriate order 10 | local plugins = {} 11 | 12 | local _M = {} 13 | 14 | local function load_plugin_conf(api_id, consumer_id, plugin_name) 15 | local cache_key = cache.plugin_configuration_key(plugin_name, api_id, consumer_id) 16 | 17 | local plugin = cache.get_and_set(cache_key, function() 18 | local rows, err = dao.plugins_configurations:find_by_keys { 19 | api_id = api_id, 20 | consumer_id = consumer_id ~= nil and consumer_id or constants.DATABASE_NULL_ID, 21 | name = plugin_name 22 | } 23 | if err then 24 | return responses.send_HTTP_INTERNAL_SERVER_ERROR(err) 25 | end 26 | 27 | if #rows > 0 then 28 | return table.remove(rows, 1) 29 | else 30 | return { null = true } 31 | end 32 | end) 33 | 34 | if plugin and not plugin.null and plugin.enabled then 35 | return plugin 36 | else 37 | return nil 38 | end 39 | end 40 | 41 | local function init_plugins() 42 | configuration.plugins_available = configuration.plugins_available and configuration.plugins_available or {} 43 | 44 | print("Discovering used plugins. Please wait..") 45 | local db_plugins, err = dao.plugins_configurations:find_distinct() 46 | if err then 47 | error(err) 48 | end 49 | 50 | -- Checking that the plugins in the DB are also enabled 51 | for _, v in ipairs(db_plugins) do 52 | if not utils.table_contains(configuration.plugins_available, v) then 53 | error("You are using a plugin that has not been enabled in the configuration: "..v) 54 | end 55 | end 56 | 57 | local unsorted_plugins = {} -- It's a multivalue table: k1 = {v1, v2, v3}, k2 = {...} 58 | 59 | for _, v in ipairs(configuration.plugins_available) do 60 | local loaded, mod = utils.load_module_if_exists("kong.plugins."..v..".handler") 61 | if not loaded then 62 | error("The following plugin has been enabled in the configuration but is not installed on the system: "..v) 63 | else 64 | print("Loading plugin: "..v) 65 | local plugin_handler = mod() 66 | local priority = plugin_handler.PRIORITY and plugin_handler.PRIORITY or 0 67 | 68 | -- Add plugin to the right priority 69 | local list = unsorted_plugins[priority] 70 | if not list then list = {} end -- The list is required in case more plugins share the same priority level 71 | table.insert(list, { 72 | name = v, 73 | handler = plugin_handler 74 | }) 75 | unsorted_plugins[priority] = list 76 | end 77 | end 78 | 79 | local result = {} 80 | 81 | -- Now construct the final ordered plugin list 82 | -- resolver is always the first plugin as it is the one retrieving any needed information 83 | table.insert(result, { 84 | resolver = true, 85 | name = "resolver", 86 | handler = require("kong.resolver.handler")() 87 | }) 88 | 89 | -- Add the plugins in a sorted order 90 | for _, v in utils.sort_table_iter(unsorted_plugins, utils.sort.descending) do -- In descending order 91 | if v then 92 | for _, p in ipairs(v) do 93 | table.insert(result, p) 94 | end 95 | end 96 | end 97 | 98 | return result 99 | end 100 | -------------------------------------------------------------------------------- /app/front/js/template/gallery.html: -------------------------------------------------------------------------------- 1 | 76 | -------------------------------------------------------------------------------- /app/front/css/app/preview.less: -------------------------------------------------------------------------------- 1 | @import (reference) "lib/bootstrap_mixins.less"; 2 | @import (reference) "lib/mixins"; 3 | @import (reference) "lib/variables"; 4 | 5 | .is_bold { font-weight: bold !important; } 6 | .is_italic { font-style: italic; } 7 | .is_underline { text-decoration: underline; } 8 | 9 | // This should not be nested to prevent higher CSS specificity 10 | s { 11 | text-decoration: none; 12 | // padding: 2px; 13 | // margin: -2px; 14 | border-radius: 2px; 15 | cursor: default; 16 | 17 | &:hover { 18 | .user-select(none); 19 | } 20 | } 21 | 22 | pre { 23 | background-color: transparent; 24 | font-family: @monoFontFamily; 25 | } 26 | 27 | .preview { 28 | position: absolute; 29 | top: @header_height+ 1; 30 | bottom: 33px; 31 | left: 401px; 32 | right: 0; 33 | overflow: scroll; 34 | transform: translate3d(0px, 0px, 0px); 35 | 36 | pre { 37 | font-size: 15px; 38 | border:0; 39 | border-radius: 0; 40 | counter-reset: line_numbers; 41 | padding:0; 42 | margin:0; 43 | overflow-x: scroll; 44 | white-space: pre !important; 45 | word-wrap: normal !important; 46 | padding-bottom: 4px; 47 | line-height: 19px; 48 | 49 | .l { 50 | counter-increment: line_numbers; 51 | padding-left: 52px; 52 | // padding-right: 230px; 53 | } 54 | .l:before { 55 | content: counter(line_numbers); 56 | width: 36px; 57 | text-align: right; 58 | display: inline-block; 59 | padding: 0 8px 0 0; 60 | font-weight: normal; 61 | font-style: normal; 62 | text-decoration: none; 63 | .user-select(none); 64 | position: absolute; 65 | left: 0; 66 | } 67 | } 68 | } 69 | 70 | .custom_code_edtior { 71 | 72 | textarea { 73 | position: absolute; 74 | display: block; 75 | box-sizing: border-box; 76 | width: 100%; 77 | height: ~"calc(100% - 42px)"; 78 | border: 0; 79 | margin: 0; 80 | top: 42px; 81 | padding: 10px; 82 | border-radius: 0; 83 | resize: none; 84 | font-family: @monoFontFamily; 85 | font-size: 15px; 86 | line-height: 19px; 87 | } 88 | 89 | .cc_header { 90 | position: absolute; 91 | top: 0; 92 | left: 0; 93 | right: 0; 94 | border-bottom: 1px solid #bbb; 95 | color: #bbb; 96 | padding: 8px 10px; 97 | background-color: #FFF; 98 | 99 | p { 100 | margin-bottom: 0; 101 | line-height: 26px; 102 | } 103 | } 104 | } 105 | 106 | .custom_code_btn_bar { 107 | position: fixed; 108 | top: 45px; 109 | right: 12px; 110 | } 111 | 112 | .custom_code_toggle_btn { 113 | position: fixed; 114 | bottom: 3px; 115 | right: 175px; 116 | z-index: 998; 117 | } 118 | 119 | .languages-dd { 120 | position: fixed; 121 | bottom: 3px; 122 | right: 10px; 123 | text-shadow: none; 124 | z-index: 998; 125 | 126 | .btn-mac { 127 | width: 140px; 128 | text-align: left; 129 | } 130 | 131 | .ud-arrow { 132 | width: 5px; 133 | height: 13px; 134 | display: inline-block; 135 | float: right; 136 | top: 3px; 137 | position: relative; 138 | font-size: 10px; 139 | line-height: 16px; 140 | } 141 | } 142 | 143 | .preview-footer { 144 | position: fixed; 145 | bottom: 0; 146 | right: 0; 147 | height: 32px; 148 | left: @sidebar_width + 1; 149 | #gradient > .vertical(#e8e8e8, #c2c2c2); 150 | border-top: 1px solid #969696; 151 | .box-shadow(inset 0 1px 0 #f5f5f5); 152 | z-index: 99; 153 | color: #666; 154 | cursor: default; 155 | 156 | .message { 157 | position: absolute; 158 | left: 128px; 159 | top: 6px; 160 | font-size: 10px; 161 | color: #888; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /app/front/public/files/themes/default.tmtheme: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Untitiled 7 | settings 8 | 9 | 10 | settings 11 | 12 | background 13 | #FFFFFF 14 | caret 15 | #000000 16 | foreground 17 | #282828 18 | invisibles 19 | #cccccc 20 | lineHighlight 21 | #FFFFFF0D 22 | selection 23 | #C5DFE980 24 | 25 | 26 | 27 | name 28 | Comment 29 | scope 30 | comment 31 | settings 32 | 33 | foreground 34 | #1E9AE0 35 | 36 | 37 | 38 | name 39 | Constant 40 | scope 41 | constant 42 | settings 43 | 44 | foreground 45 | #FF3A83 46 | 47 | 48 | 49 | name 50 | Entity 51 | scope 52 | entity 53 | settings 54 | 55 | foreground 56 | #EFE900 57 | 58 | 59 | 60 | name 61 | Keyword 62 | scope 63 | keyword 64 | settings 65 | 66 | foreground 67 | #FFAA00 68 | 69 | 70 | 71 | name 72 | Storage 73 | scope 74 | storage 75 | settings 76 | 77 | foreground 78 | #F6F080 79 | 80 | 81 | 82 | name 83 | String 84 | scope 85 | string 86 | settings 87 | 88 | foreground 89 | #65BA3A 90 | 91 | 92 | 93 | name 94 | Support 95 | scope 96 | support 97 | settings 98 | 99 | foreground 100 | #9DF39F 101 | 102 | 103 | 104 | name 105 | Variable 106 | scope 107 | variable 108 | settings 109 | 110 | foreground 111 | #FB9A4B 112 | 113 | 114 | 115 | name 116 | Invalid 117 | scope 118 | invalid 119 | settings 120 | 121 | background 122 | #FF0000 123 | foreground 124 | #F8F8F8 125 | 126 | 127 | 128 | uuid 129 | e0983c83-67b2-46f4-ae17-3a325f5ac3af 130 | 131 | -------------------------------------------------------------------------------- /app/front/css/app/global.less: -------------------------------------------------------------------------------- 1 | @import (reference) "lib/bootstrap_mixins.less"; 2 | @import (reference) "lib/mixins"; 3 | @import (reference) "lib/variables"; 4 | 5 | [ng-cloak], .ng-cloak { display: none; } 6 | [ng-click] { cursor: pointer; } 7 | 8 | body { 9 | overflow: hidden; 10 | font-family: @systemFontFamily; 11 | } 12 | 13 | input, button, select, textarea { 14 | font-family: @systemFontFamily; 15 | } 16 | 17 | #loading { 18 | position: fixed; 19 | bottom: 0; 20 | right: 0; 21 | left: 200px; 22 | top: 37px; 23 | z-index: 999; 24 | background: rgba(0,0,0,.6); 25 | opacity: 0; 26 | display: none; 27 | .transition(all 1600ms ease); 28 | 29 | &.full_window { 30 | left: 0; 31 | } 32 | 33 | &.show { 34 | opacity:1; 35 | } 36 | 37 | .spinner { 38 | position: absolute !important; 39 | left: 50% !important; 40 | top: 50% !important; 41 | } 42 | } 43 | 44 | #alerts { 45 | position: fixed; 46 | z-index: 9999; 47 | top: 40px; 48 | right: 12px; 49 | 50 | .alert { 51 | position: relative; 52 | 53 | .close { 54 | font-size: 18px; 55 | position: absolute; 56 | top: 8px; 57 | right: 10px; 58 | } 59 | } 60 | 61 | .sr-only { 62 | display: none; 63 | } 64 | } 65 | 66 | .no-scroll { 67 | overflow-y: hidden !important; 68 | } 69 | 70 | .btn-mac { 71 | #gradient > .vertical(#eee, #c3c3c3); 72 | border: 1px solid #777; 73 | border-top: 1px solid #797979; 74 | border-bottom: 1px solid #747474; 75 | .transition(none); 76 | 77 | &:hover { 78 | background-position: 0 0; 79 | } 80 | &:active, &.active { 81 | #gradient > .vertical(#c0c0c0, #dadada); 82 | } 83 | } 84 | 85 | .btn-success, .btn-info, .btn-mac { 86 | text-shadow: none; 87 | } 88 | 89 | .btn-group.open .btn-mac.dropdown-toggle { 90 | #gradient > .vertical(#c0c0c0, #dadada); 91 | } 92 | 93 | .btn, header, .btn-toolbar, .tabbar, table.list th { 94 | .user-select(none); 95 | } 96 | 97 | .dropdown-menu { 98 | overflow-y: scroll; 99 | 100 | .divider { 101 | margin: 2px 0px; 102 | } 103 | 104 | a { 105 | padding: 2px 20px; 106 | } 107 | } 108 | 109 | // Modals 110 | .modal { 111 | background-color: #E5E5E5; 112 | border-radius: 0; 113 | border: 0; 114 | box-shadow: 0 24px 24px rgba(0, 0, 0, 0.55); 115 | top: -300px; 116 | 117 | form { 118 | margin: 0 119 | } 120 | 121 | &:before { 122 | content: ''; 123 | display: block; 124 | position: absolute; 125 | top: -14px; 126 | left: 0; 127 | right: 0; 128 | height: 16px; 129 | #gradient > .radial(#A6A6A6, #E5E5E5); 130 | } 131 | 132 | 133 | &:focus { 134 | outline: none; 135 | } 136 | 137 | &.fade.in, &.in { 138 | top: 35px; 139 | margin-top: 0; 140 | } 141 | 142 | .modal-header { 143 | border-bottom: 0; 144 | padding: 18px 20px 0 110px; 145 | 146 | h3.modal-title { 147 | line-height: 18px; 148 | font-size: 15px; 149 | font-weight: 600; 150 | letter-spacing: -0.02em; 151 | } 152 | } 153 | 154 | .modal-body { 155 | padding: 18px 20px 18px 110px; 156 | font-size: 13px; 157 | } 158 | 159 | .modal-footer { 160 | border-top: 0; 161 | box-shadow: none; 162 | border-radius: 0; 163 | background-color: transparent; 164 | padding: 0 20px 18px 110px; 165 | 166 | .btn { 167 | margin-left: 14px; 168 | min-width: 80px; 169 | } 170 | } 171 | 172 | .modal-icon { 173 | padding: 18px 20px; 174 | width: 64px; 175 | height: 64px; 176 | background: url('/images/icon/tmtheme-256.png') center center no-repeat; 177 | background-size: 64px; 178 | display: block; 179 | position: absolute; 180 | } 181 | 182 | .text-input { 183 | width: 100%; 184 | box-sizing: border-box; 185 | height: initial; 186 | margin-bottom: 0; 187 | } 188 | } 189 | 190 | .modal-backdrop.in {opacity: .4; } 191 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/erlang.txt: -------------------------------------------------------------------------------- 1 | -module(cowboy_protocol). 2 | 3 | %% API. 4 | -export([start_link/4]). 5 | 6 | %% Internal. 7 | -export([init/4]). 8 | -export([parse_request/3]). 9 | -export([resume/6]). 10 | 11 | -type opts() :: [{compress, boolean()} 12 | | {env, cowboy_middleware:env()} 13 | | {max_empty_lines, non_neg_integer()} 14 | | {max_header_name_length, non_neg_integer()} 15 | | {max_header_value_length, non_neg_integer()} 16 | | {max_headers, non_neg_integer()} 17 | | {max_keepalive, non_neg_integer()} 18 | | {max_request_line_length, non_neg_integer()} 19 | | {middlewares, [module()]} 20 | | {onresponse, cowboy:onresponse_fun()} 21 | | {timeout, timeout()}]. 22 | -export_type([opts/0]). 23 | 24 | -record(state, { 25 | socket :: inet:socket(), 26 | transport :: module(), 27 | middlewares :: [module()], 28 | compress :: boolean(), 29 | env :: cowboy_middleware:env(), 30 | onresponse = undefined :: undefined | cowboy:onresponse_fun(), 31 | max_empty_lines :: non_neg_integer(), 32 | req_keepalive = 1 :: non_neg_integer(), 33 | max_keepalive :: non_neg_integer(), 34 | max_request_line_length :: non_neg_integer(), 35 | max_header_name_length :: non_neg_integer(), 36 | max_header_value_length :: non_neg_integer(), 37 | max_headers :: non_neg_integer(), 38 | timeout :: timeout(), 39 | until :: non_neg_integer() | infinity 40 | }). 41 | 42 | -include_lib("cowlib/include/cow_inline.hrl"). 43 | -include_lib("cowlib/include/cow_parse.hrl"). 44 | 45 | %% API. 46 | 47 | -spec start_link(ranch:ref(), inet:socket(), module(), opts()) -> {ok, pid()}. 48 | start_link(Ref, Socket, Transport, Opts) -> 49 | Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]), 50 | {ok, Pid}. 51 | 52 | %% Internal. 53 | 54 | %% Faster alternative to proplists:get_value/3. 55 | get_value(Key, Opts, Default) -> 56 | case lists:keyfind(Key, 1, Opts) of 57 | {_, Value} -> Value; 58 | _ -> Default 59 | end. 60 | 61 | -spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok. 62 | init(Ref, Socket, Transport, Opts) -> 63 | ok = ranch:accept_ack(Ref), 64 | Timeout = get_value(timeout, Opts, 5000), 65 | Until = until(Timeout), 66 | case recv(Socket, Transport, Until) of 67 | {ok, Data} -> 68 | OnFirstRequest = get_value(onfirstrequest, Opts, undefined), 69 | case OnFirstRequest of 70 | undefined -> ok; 71 | _ -> OnFirstRequest(Ref, Socket, Transport, Opts) 72 | end, 73 | Compress = get_value(compress, Opts, false), 74 | MaxEmptyLines = get_value(max_empty_lines, Opts, 5), 75 | MaxHeaderNameLength = get_value(max_header_name_length, Opts, 64), 76 | MaxHeaderValueLength = get_value(max_header_value_length, Opts, 4096), 77 | MaxHeaders = get_value(max_headers, Opts, 100), 78 | MaxKeepalive = get_value(max_keepalive, Opts, 100), 79 | MaxRequestLineLength = get_value(max_request_line_length, Opts, 4096), 80 | Middlewares = get_value(middlewares, Opts, [cowboy_router, cowboy_handler]), 81 | Env = [{listener, Ref}|get_value(env, Opts, [])], 82 | OnResponse = get_value(onresponse, Opts, undefined), 83 | parse_request(Data, #state{socket=Socket, transport=Transport, 84 | middlewares=Middlewares, compress=Compress, env=Env, 85 | max_empty_lines=MaxEmptyLines, max_keepalive=MaxKeepalive, 86 | max_request_line_length=MaxRequestLineLength, 87 | max_header_name_length=MaxHeaderNameLength, 88 | max_header_value_length=MaxHeaderValueLength, max_headers=MaxHeaders, 89 | onresponse=OnResponse, timeout=Timeout, until=Until}, 0); 90 | {error, _} -> 91 | terminate(#state{socket=Socket, transport=Transport}) %% @todo ridiculous 92 | end. 93 | 94 | -spec until(timeout()) -> non_neg_integer() | infinity. 95 | until(infinity) -> 96 | infinity; 97 | until(Timeout) -> 98 | {Me, S, Mi} = os:timestamp(), 99 | Me * 1000000000 + S * 1000 + Mi div 1000 + Timeout. 100 | -------------------------------------------------------------------------------- /app/front/js/services/color_service.coffee: -------------------------------------------------------------------------------- 1 | Application.factory "Color", ['tinycolor', (tinycolor) -> 2 | 3 | clamp = (val, min= 0, max=1) -> Math.min(max, Math.max(min, val)) 4 | tm_hex8 = (standard_hex_8) -> "##{standard_hex_8[2..8]}#{standard_hex_8[0..1]}" 5 | 6 | parse = (color) -> 7 | return color unless color and color[0] == "#" and color.length >= 4 8 | if color.length > 7 9 | hex = color[0..6] 10 | rgba = tinycolor(hex).toRgb() 11 | opacity = parseInt(color[7..8], 16)/255 12 | rgba.a = opacity 13 | tinycolor(rgba).toRgbString() 14 | else 15 | color 16 | 17 | tm_encode = (color_str) -> 18 | color = tinycolor(color_str) 19 | if color.getAlpha() < 1 20 | tm_hex8(color.toHex8()).toUpperCase() 21 | else 22 | color.toHexString().toUpperCase() 23 | 24 | tm_decode = (color_str) -> tinycolor(@parse(color_str)) 25 | 26 | light_or_dark = (color) -> 27 | c = tinycolor(color) 28 | d = c.toRgb() 29 | yiq = ((d.r*299)+(d.g*587)+(d.b*114))/1000 30 | if yiq >= 128 then 'light' else 'dark' 31 | 32 | darken = (color, percent) -> 33 | c = tinycolor(color) 34 | hsl = c.toHsl() 35 | hsl.l -= percent/100 36 | hsl.l = clamp(hsl.l) 37 | tinycolor(hsl).toHslString() 38 | 39 | lighten = (color, percent) -> 40 | c = tinycolor(color) 41 | hsl = c.toHsl() 42 | hsl.l += percent/100 43 | hsl.l = clamp(hsl.l) 44 | tinycolor(hsl).toHslString() 45 | 46 | is_color = (color) -> if @parse(color) then true else false 47 | 48 | random = -> tinycolor.random().toHexString().toUpperCase() 49 | 50 | # Color Effects and Adjustments ----------------------- 51 | 52 | brightness_contrast = (color, brightness, contrast) -> 53 | rgb = tinycolor(@parse(color)).toRgb() 54 | brightMul = 1 + Math.min(150, Math.max(-150, brightness)) / 150 55 | contrast = contrast/100.0 56 | contrast = Math.max(0, contrast + 1) 57 | unless contrast is 1 58 | mul = brightMul * contrast 59 | add = -contrast * 128 + 128 60 | else 61 | mul = brightMul 62 | add = 0 63 | r = rgb.r * mul + add 64 | g = rgb.g * mul + add 65 | b = rgb.b * mul + add 66 | if r > 255 67 | new_r = 255 68 | else if r < 0 69 | new_r = 0 70 | else 71 | new_r = r 72 | if g > 255 73 | new_g = 255 74 | else if g < 0 75 | new_g = 0 76 | else 77 | new_g = g 78 | if b > 255 79 | new_b = 255 80 | else if b < 0 81 | new_b = 0 82 | else 83 | new_b = b 84 | tm_hex8(tinycolor(r: new_r, g: new_g, b: new_b, a: rgb.a).toHex8()) 85 | 86 | change_hsl = (color, h_change, s_change, l_change, colorize) -> 87 | hsl = tinycolor(@parse(color)).toHsl() 88 | if colorize 89 | hsl.h = parseInt(h_change) + 180 90 | else 91 | hsl.h = hsl.h + parseInt(h_change) 92 | hsl.h += 360 if hsl.h < 0 93 | hsl.h -= 360 if hsl.h > 360 94 | hsl.s = clamp(hsl.s + parseInt(s_change)/100.0) 95 | hsl.l = clamp(hsl.l + parseInt(l_change)/100.0) 96 | tm_hex8(tinycolor(hsl).toHex8()) 97 | 98 | invert = (color) -> 99 | rgb = tinycolor(@parse(color)).toRgb() 100 | rgb.r = 255 - rgb.r 101 | rgb.g = 255 - rgb.g 102 | rgb.b = 255 - rgb.b 103 | tm_hex8(tinycolor(rgb).toHex8()) 104 | 105 | grayscale = (color) -> 106 | hsl = tinycolor(@parse(color)).toHsl() 107 | hsl.s = 0 108 | tm_hex8(tinycolor(hsl).toHex8()) 109 | 110 | sepia = (color) -> 111 | rgb = tinycolor(@parse(color)).toRgb() 112 | r = (rgb.r * .393 + rgb.g * .769 + rgb.b * .189) 113 | g = (rgb.r * .349 + rgb.g * .686 + rgb.b * .168) 114 | b = (rgb.r * .272 + rgb.g * .534 + rgb.b * .131) 115 | r = 0 if r < 0 116 | r = 255 if r > 255 117 | g = 0 if g < 0 118 | g = 255 if g > 255 119 | b = 0 if b < 0 120 | b = 255 if b > 255 121 | tm_hex8(tinycolor(r: r, g: g, b: b, a: rgb.a).toHex8()) 122 | 123 | return { 124 | parse 125 | tm_encode 126 | tm_decode 127 | light_or_dark 128 | darken 129 | lighten 130 | random 131 | is_color 132 | brightness_contrast 133 | change_hsl 134 | invert 135 | grayscale 136 | sepia 137 | } 138 | ] 139 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/c++.txt: -------------------------------------------------------------------------------- 1 | #include "ContactsModel.h" 2 | #include "core/IdentityManager.h" 3 | #include "core/ContactsManager.h" 4 | #include 5 | 6 | inline bool contactSort(const ContactUser *c1, const ContactUser *c2) 7 | { 8 | if (c1->status() != c2->status()) 9 | return c1->status() < c2->status(); 10 | return c1->nickname().localeAwareCompare(c2->nickname()) < 0; 11 | } 12 | 13 | ContactsModel::ContactsModel(QObject *parent) 14 | : QAbstractListModel(parent), m_identity(0) 15 | { 16 | } 17 | 18 | void ContactsModel::setIdentity(UserIdentity *identity) 19 | { 20 | if (identity == m_identity) 21 | return; 22 | 23 | beginResetModel(); 24 | 25 | foreach (ContactUser *user, contacts) 26 | user->disconnect(this); 27 | contacts.clear(); 28 | 29 | if (m_identity) { 30 | disconnect(m_identity, 0, this, 0); 31 | disconnect(&m_identity->contacts, 0, this, 0); 32 | } 33 | 34 | m_identity = identity; 35 | 36 | if (m_identity) { 37 | connect(&identity->contacts, SIGNAL(contactAdded(ContactUser*)), SLOT(contactAdded(ContactUser*))); 38 | 39 | contacts = identity->contacts.contacts(); 40 | std::sort(contacts.begin(), contacts.end(), contactSort); 41 | 42 | foreach (ContactUser *user, contacts) 43 | connectSignals(user); 44 | } 45 | 46 | endResetModel(); 47 | emit identityChanged(); 48 | } 49 | 50 | QModelIndex ContactsModel::indexOfContact(ContactUser *user) const 51 | { 52 | int row = contacts.indexOf(user); 53 | if (row < 0) 54 | return QModelIndex(); 55 | return index(row, 0); 56 | } 57 | 58 | ContactUser *ContactsModel::contact(int row) const 59 | { 60 | return contacts.value(row); 61 | } 62 | 63 | void ContactsModel::updateUser(ContactUser *user) 64 | { 65 | if (!user) 66 | { 67 | user = qobject_cast(sender()); 68 | if (!user) 69 | return; 70 | } 71 | 72 | int row = contacts.indexOf(user); 73 | if (row < 0) 74 | { 75 | user->disconnect(this); 76 | return; 77 | } 78 | 79 | QList sorted = contacts; 80 | std::sort(sorted.begin(), sorted.end(), contactSort); 81 | int newRow = sorted.indexOf(user); 82 | 83 | if (row != newRow) 84 | { 85 | beginMoveRows(QModelIndex(), row, row, QModelIndex(), (newRow > row) ? (newRow+1) : newRow); 86 | contacts = sorted; 87 | endMoveRows(); 88 | } 89 | emit dataChanged(index(newRow, 0), index(newRow, 0)); 90 | } 91 | 92 | void ContactsModel::connectSignals(ContactUser *user) 93 | { 94 | connect(user, SIGNAL(statusChanged()), SLOT(updateUser())); 95 | connect(user, SIGNAL(nicknameChanged()), SLOT(updateUser())); 96 | connect(user, SIGNAL(contactDeleted(ContactUser*)), SLOT(contactRemoved(ContactUser*))); 97 | } 98 | 99 | void ContactsModel::contactAdded(ContactUser *user) 100 | { 101 | Q_ASSERT(!indexOfContact(user).isValid()); 102 | 103 | connectSignals(user); 104 | 105 | QList::Iterator lp = qLowerBound(contacts.begin(), contacts.end(), user, contactSort); 106 | int row = lp - contacts.begin(); 107 | 108 | beginInsertRows(QModelIndex(), row, row); 109 | contacts.insert(lp, user); 110 | endInsertRows(); 111 | } 112 | 113 | void ContactsModel::contactRemoved(ContactUser *user) 114 | { 115 | if (!user && !(user = qobject_cast(sender()))) 116 | return; 117 | 118 | int row = contacts.indexOf(user); 119 | beginRemoveRows(QModelIndex(), row, row); 120 | contacts.removeAt(row); 121 | endRemoveRows(); 122 | 123 | disconnect(user, 0, this, 0); 124 | } 125 | 126 | QHash ContactsModel::roleNames() const 127 | { 128 | QHash roles; 129 | roles[Qt::DisplayRole] = "name"; 130 | roles[PointerRole] = "contact"; 131 | roles[StatusRole] = "status"; 132 | return roles; 133 | } 134 | 135 | int ContactsModel::rowCount(const QModelIndex &parent) const 136 | { 137 | if (parent.isValid()) 138 | return 0; 139 | return contacts.size(); 140 | } 141 | 142 | QVariant ContactsModel::data(const QModelIndex &index, int role) const 143 | { 144 | if (!index.isValid() || index.row() >= contacts.size()) 145 | return QVariant(); 146 | 147 | ContactUser *user = contacts[index.row()]; 148 | 149 | switch (role) 150 | { 151 | case Qt::DisplayRole: 152 | case Qt::EditRole: 153 | return user->nickname(); 154 | case PointerRole: 155 | return QVariant::fromValue(user); 156 | case StatusRole: 157 | return user->status(); 158 | } 159 | 160 | return QVariant(); 161 | } 162 | -------------------------------------------------------------------------------- /app/front/css/lib/buttons.less: -------------------------------------------------------------------------------- 1 | @import (reference) "lib/bootstrap_mixins.less"; 2 | @import (reference) "lib/mixins"; 3 | @import (reference) "lib/variables"; 4 | @import (reference) "bootstrap/less/variables.less"; 5 | 6 | // Core 7 | .btn { 8 | display: inline-block; 9 | .ie7-inline-block(); 10 | padding: 4px 14px; 11 | margin-bottom: 0; // For input.btn 12 | font-size: @baseFontSize; 13 | line-height: @baseLineHeight; 14 | text-align: center; 15 | vertical-align: middle; 16 | cursor: pointer; 17 | .buttonBackground(@btnBackground, @btnBackgroundHighlight, @grayDark, 0 1px 1px rgba(255,255,255,.75)); 18 | border: 1px solid @btnBorder; 19 | border-bottom-color: darken(@btnBorder, 10%); 20 | .border-radius(4px); 21 | .ie7-restore-left-whitespace(); // Give IE7 some love 22 | .box-shadow(~"inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)"); 23 | 24 | // Hover state 25 | &:hover { 26 | color: @grayDark; 27 | text-decoration: none; 28 | background-color: darken(@white, 10%); 29 | background-position: 0 -15px; 30 | 31 | // transition is only when going to hover, otherwise the background 32 | // behind the gradient (there for IE<=9 fallback) gets mismatched 33 | .transition(background-position .1s linear); 34 | } 35 | 36 | // Focus state for keyboard and accessibility 37 | &:focus { 38 | .tab-focus(); 39 | } 40 | 41 | // Active state 42 | &.active, 43 | &:active { 44 | background-color: darken(@white, 10%); 45 | background-color: darken(@white, 15%) e("\9"); 46 | background-image: none; 47 | outline: 0; 48 | .box-shadow(~"inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)"); 49 | } 50 | 51 | // Disabled state 52 | &.disabled, 53 | &[disabled] { 54 | cursor: default; 55 | background-color: darken(@white, 10%); 56 | background-image: none; 57 | .opacity(65); 58 | .box-shadow(none); 59 | } 60 | 61 | } 62 | 63 | 64 | 65 | // Button Sizes 66 | // -------------------------------------------------- 67 | 68 | // Large 69 | .btn-large { 70 | padding: 9px 14px; 71 | font-size: @baseFontSize + 2px; 72 | line-height: normal; 73 | .border-radius(5px); 74 | } 75 | .btn-large [class^="icon-"] { 76 | margin-top: 2px; 77 | } 78 | 79 | // Small 80 | .btn-small { 81 | padding: 3px 9px; 82 | font-size: @baseFontSize - 2px; 83 | line-height: @baseLineHeight - 2px; 84 | } 85 | .btn-small [class^="icon-"] { 86 | margin-top: 0; 87 | } 88 | 89 | // Mini 90 | .btn-mini { 91 | padding: 2px 6px; 92 | font-size: @baseFontSize - 3px; 93 | line-height: @baseLineHeight - 4px; 94 | } 95 | 96 | // Block button 97 | .btn-block { 98 | display: block; 99 | width: 100%; 100 | padding-left: 0; 101 | padding-right: 0; 102 | .box-sizing(border-box); 103 | } 104 | .btn-block + .btn-block { 105 | margin-top: 5px; 106 | } 107 | 108 | 109 | // Alternate buttons 110 | // -------------------------------------------------- 111 | 112 | // Provide *some* extra contrast for those who can get it 113 | .btn-primary.active, 114 | .btn-warning.active, 115 | .btn-danger.active, 116 | .btn-success.active, 117 | .btn-info.active, 118 | .btn-inverse.active { 119 | color: rgba(255,255,255,.75); 120 | } 121 | 122 | // Set the backgrounds 123 | // ------------------------- 124 | .btn { 125 | // reset here as of 2.0.3 due to Recess property order 126 | border-color: #c5c5c5; 127 | border-color: rgba(0,0,0,.15) rgba(0,0,0,.15) rgba(0,0,0,.25); 128 | } 129 | .btn-primary { 130 | .buttonBackground(@btnPrimaryBackground, @btnPrimaryBackgroundHighlight); 131 | } 132 | // Warning appears are orange 133 | .btn-warning { 134 | .buttonBackground(@btnWarningBackground, @btnWarningBackgroundHighlight); 135 | } 136 | // Danger and error appear as red 137 | .btn-danger { 138 | .buttonBackground(@btnDangerBackground, @btnDangerBackgroundHighlight); 139 | } 140 | // Success appears as green 141 | .btn-success { 142 | .buttonBackground(@btnSuccessBackground, @btnSuccessBackgroundHighlight); 143 | } 144 | // Info appears as a neutral blue 145 | .btn-info { 146 | .buttonBackground(@btnInfoBackground, @btnInfoBackgroundHighlight); 147 | } 148 | // Inverse appears as dark gray 149 | .btn-inverse { 150 | .buttonBackground(@btnInverseBackground, @btnInverseBackgroundHighlight); 151 | } 152 | 153 | 154 | // Cross-browser Jank 155 | // -------------------------------------------------- 156 | 157 | button.btn, 158 | input[type="submit"].btn { 159 | 160 | // Firefox 3.6 only I believe 161 | &::-moz-focus-inner { 162 | padding: 0; 163 | border: 0; 164 | } 165 | 166 | } 167 | 168 | 169 | // Link buttons 170 | // -------------------------------------------------- 171 | 172 | // Make a button look and behave like a link 173 | .btn-link, 174 | .btn-link:active { 175 | background-color: transparent; 176 | background-image: none; 177 | .box-shadow(none); 178 | } 179 | .btn-link { 180 | border-color: transparent; 181 | cursor: pointer; 182 | color: @linkColor; 183 | .border-radius(0); 184 | } 185 | .btn-link:hover { 186 | color: @linkColorHover; 187 | text-decoration: underline; 188 | background-color: transparent; 189 | } 190 | -------------------------------------------------------------------------------- /app/front/public/files/samples/raw/r.txt: -------------------------------------------------------------------------------- 1 | geom_dotplot <- function (mapping = NULL, data = NULL, stat = "bindot", position = "identity", 2 | na.rm = FALSE, binwidth = NULL, binaxis = "x", method="dotdensity", binpositions = "bygroup", stackdir = "up", 3 | stackratio = 1, dotsize = 1, stackgroups = FALSE, ...) { 4 | GeomDotplot$new(mapping = mapping, data = data, stat = stat, position = position, 5 | na.rm = na.rm, binwidth = binwidth, binaxis = binaxis, method = method, binpositions = binpositions, 6 | stackdir = stackdir, stackratio = stackratio, dotsize = dotsize, stackgroups = stackgroups, ...) 7 | } 8 | 9 | GeomDotplot <- proto(Geom, { 10 | objname <- "dotplot" 11 | 12 | new <- function(., mapping = NULL, data = NULL, stat = NULL, position = NULL, ...){ 13 | # This code is adapted from Layer$new. It's needed to pull out the stat_params 14 | # and geom_params, then manually add binaxis to both sets of params. Otherwise 15 | # Layer$new will give binaxis only to the geom. 16 | 17 | stat <- Stat$find(stat) 18 | match.params <- function(possible, params) { 19 | if ("..." %in% names(possible)) { 20 | params 21 | } else { 22 | params[match(names(possible), names(params), nomatch = 0)] 23 | } 24 | } 25 | 26 | params <- list(...) 27 | # American names must be changed here so that they'll go to geom_params; 28 | # otherwise they'll end up in stat_params 29 | params <- rename_aes(params) 30 | 31 | geom_params <- match.params(.$parameters(), params) 32 | stat_params <- match.params(stat$parameters(), params) 33 | stat_params <- stat_params[setdiff(names(stat_params), names(geom_params))] 34 | # Add back binaxis 35 | stat_params <- c(stat_params, binaxis=params$binaxis) 36 | 37 | # If identical(position, "stack") or position is position_stack() (the test 38 | # is kind of complex), tell them to use stackgroups=TRUE instead. Need to 39 | # use identical() instead of ==, because == will fail if object is 40 | # position_stack() or position_dodge() 41 | if (!is.null(position) && (identical(position, "stack") || (is.proto(position) && position$objname == "stack"))) 42 | message("position=\"stack\" doesn't work properly with geom_dotplot. Use stackgroups=TRUE instead.") 43 | 44 | if (params$stackgroups && params$method == "dotdensity" && params$binpositions == "bygroup") 45 | message('geom_dotplot called with stackgroups=TRUE and method="dotdensity". You probably want to set binpositions="all"') 46 | 47 | do.call("layer", list(mapping = mapping, data = data, stat = stat, geom = ., position = position, 48 | geom_params = geom_params, stat_params = stat_params, ...)) 49 | } 50 | 51 | 52 | reparameterise <- function(., df, params) { 53 | df$width <- df$width %||% 54 | params$width %||% (resolution(df$x, FALSE) * 0.9) 55 | 56 | # Set up the stacking function and range 57 | if(is.null(params$stackdir) || params$stackdir == "up") { 58 | stackdots <- function(a) a - .5 59 | stackaxismin <- 0 60 | stackaxismax <- 1 61 | } else if (params$stackdir == "down") { 62 | stackdots <- function(a) -a + .5 63 | stackaxismin <- -1 64 | stackaxismax <- 0 65 | } else if (params$stackdir == "center") { 66 | stackdots <- function(a) a - 1 - max(a - 1) / 2 67 | stackaxismin <- -.5 68 | stackaxismax <- .5 69 | } else if (params$stackdir == "centerwhole") { 70 | stackdots <- function(a) a - 1 - floor(max(a - 1) / 2) 71 | stackaxismin <- -.5 72 | stackaxismax <- .5 73 | } 74 | 75 | 76 | # Fill the bins: at a given x (or y), if count=3, make 3 entries at that x 77 | df <- df[rep(1:nrow(df), df$count), ] 78 | 79 | # Next part will set the position of each dot within each stack 80 | # If stackgroups=TRUE, split only on x (or y) and panel; if not stacking, also split by group 81 | plyvars <- params$binaxis %||% "x" 82 | plyvars <- c(plyvars, "PANEL") 83 | if (is.null(params$stackgroups) || !params$stackgroups) 84 | plyvars <- c(plyvars, "group") 85 | 86 | # Within each x, or x+group, set countidx=1,2,3, and set stackpos according to stack function 87 | df <- ddply(df, plyvars, function(xx) { 88 | xx$countidx <- 1:nrow(xx) 89 | xx$stackpos <- stackdots(xx$countidx) 90 | xx 91 | }) 92 | 93 | 94 | # Set the bounding boxes for the dots 95 | if (is.null(params$binaxis) || params$binaxis == "x") { 96 | # ymin, ymax, xmin, and xmax define the bounding rectangle for each stack 97 | # Can't do bounding box per dot, because y position isn't real. 98 | # After position code is rewritten, each dot should have its own bounding box. 99 | df$xmin <- df$x - df$binwidth / 2 100 | df$xmax <- df$x + df$binwidth / 2 101 | df$ymin <- stackaxismin 102 | df$ymax <- stackaxismax 103 | df$y <- 0 104 | 105 | } else if (params$binaxis == "y") { 106 | # ymin, ymax, xmin, and xmax define the bounding rectangle for each stack 107 | # Can't do bounding box per dot, because x position isn't real. 108 | # xmin and xmax aren't really the x bounds, because of the odd way the grob 109 | # works. They're just set to the standard x +- width/2 so that dot clusters 110 | # can be dodged like other geoms. 111 | # After position code is rewritten, each dot should have its own bounding box. 112 | df <- ddply(df, .(group), transform, 113 | ymin = min(y) - binwidth[1] / 2, 114 | ymax = max(y) + binwidth[1] / 2) 115 | 116 | df$xmin <- df$x + df$width * stackaxismin 117 | df$xmax <- df$x + df$width * stackaxismax 118 | # Unlike with y above, don't change x because it will cause problems with dodging 119 | } 120 | df 121 | } 122 | -------------------------------------------------------------------------------- /app/front/css/app/icons.less: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | @import (reference) "lib/bootstrap_mixins.less"; 3 | @import (reference) "lib/mixins"; 4 | @import (reference) "lib/variables"; 5 | 6 | @font-face { 7 | font-family: "tmthemeeditor"; 8 | src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRk9UVE8AAAtoAAsAAAAAEGAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAABCAAACCcAAAs1bik64EZGVE0AAAkwAAAAGgAAABxypP+BR0RFRgAACUwAAAAdAAAAIAA6AARPUy8yAAAJbAAAAEcAAABgL7xMdWNtYXAAAAm0AAAARgAAAVrAPeMAaGVhZAAACfwAAAApAAAANgRkeYNoaGVhAAAKKAAAABgAAAAkBC8CA2htdHgAAApAAAAAHgAAAB4EqAEObWF4cAAACmAAAAAGAAAABgANUABuYW1lAAAKaAAAAO4AAAHOfHX2UHBvc3QAAAtYAAAAEAAAACAAAwABeJx9Vl2M3cQV9oXre4dlWdp0jUBNkz40UJQKpfSXpxQKJSotaWizfSQtuwFClvx0k5D9u9f2eGY8xz/jsX3v/qWbZLO7BCLSJFJ4JJHIE1KkSmlTUdE3WqFUbXnyqq7UHu+VEFERGmnOzJnzN/Odc+yaUa8btVptYGx07KWR0ZGR4ZfHDhw2ancYNePxtYfuWPv6nWv314P+GvTfCf31TX3GAz/f8F+ATxb9TYC1bC0zNxr/uHejYXxhY635xY1G/8a7+zYYA5UZYtxr3Gd8xfiasdV41HjM+IHxtPGssdv4tXHgyKsvP7Vt27Ye+WaPPNoj3+qRb/fId3rkuz3yvR55skee6pEf9siPbrvI7bcyjBqviZpfkzWoBbWwFtXimqolNW3cU0V6R+1kvVbn9TP18w3ZONt8l2whH94V3vXhQPFBkVlwjI5PTU5OjdNjcAzG9eTs1BxdgEVY1Auzc3OzC3oRyCIs0Lmp2Uk9DsdI8eAbFkQQ+qEM/UAA+WVqipxnLIuV0jpLUqWjOAyhGpVc4OUT84dPE39dXIAvfZ+8MGq6sRM5EXGvmFCZwoFnQJ5pMOC+9HxHHBeHHOEIl5EX3jDxOPCBg0OnpqamHZtRX0gfNfwAj2Ym8+m0TZjDUZ4MuSZ6keioEhDkJ83Kb1hJygjIO64ZObGtHM4YpY7nMir4uqjfk9P2/MTSERKui+MdgjAkl86aKc9EJkg6ZK47xYFnQN5rKIjDIAmz6ES0nEVZlCpyab+JxzKEGDI9OzM7m+VKh2ipsicjP5xasGdoRmIdZ3FO3knNKAgDdLT+bGSgyNZes77aV/60fM2Ch/782D8Fj6WSqUwh81M/E6nIeO4H7eBgOOx5bxF+Us/PzyzMLsSnZCZjqZlmCc+gK0/zGU2iJqhIs5BFNuPKzt7QKu50XwVKORfMx8G571UgIRgiwghjX/kZ9aWjeeCC7SmesFTqlk84CCl84UtUkdSTXsDBlqgQqbkwilXuayBB6oFUIs38OEgCFcZxFCVJguaDyrzEmwYkjaII00WFiUh44grh+QwoF0I4IEIvDFNQBFKFqTU7M0fnhZa4TpSKAVKYZafTmdf00fgIkAmY9Cc5kU3JgYcicVcyfty3p1qORz3qO5LKoyLoBt2TiA8JTo2N2crXKYRREIvYD2zmMpcmMsEbgcfxOYgQnAnOvbBNucullgnEQSAwjbgU8uho60UYJgUrn7T+sHT19/ABJJAgRLLKcEARzCXU5Yx7NGcxcRJXtZknPHRAwQk8EdDY1aAAoiiMMRAlCfDAkwgGPi7zvcDzEBYHoReIhwhZ7MdcEaadiCVCgkQ3duxomtCUdvxMZnEK4HlT3CPcZQ71POry2EbUBULMMSSfokXKycDaUHGX9fAtc/5Mugpn4e3xC6+8ue/cyPzz8Dzsndi/f3T/xF5cPj8/cu4V8ua+CxNvwyqs6DNz5O8Pmx27C92cLC2ZaS5zu0vKfxXPWHC2s3zq5MlTy52zaHGldXrs9Fj3EIzC/vahI0ePHjnUHgUyCge7yD/dWoGzGEVW3LDKwfIXOAYLnAuccSCnOVDcqJeDKDHYHFgbL163ftNAaBAZhhkLjExl3sKmpcZClsxuBiUUi1nshRRIOV70W8Owb/rggQMHp/fBMLwws2/14MqBc9MX4SKcm1ldXVmZPQeXCFycOof81X0zw0CiklmvwuHs6OKxRXsJXofVfGlx8eTimfx1tPnjLdZtTg5/RjBnesEUTxdPWwrrLcZkDRPQ5EwTtJ9wxRWLUBowr1DT94CSw02goYdWGVpHP/+uf87x5xglxc+Kv1oz3aDjZHbelq0WOX7cbLVkG7dOJ+x2SPlRed6y2x7z/Wnkd+yIK0xqHahIKfLbE2aMi0AHCVqNecxCTFXJBGMkL/5iMXRDAw+YRA6XDLyARtgVQj9heRujwOIkWABhHOW57LS6pDhffmSdOG52Wx2ZZxkyp7tk/ITZ6rYD23HsoN1trXe6zCr7ymeLNphI37eKvmJn2Yair9xpDqwNFoMWVMmLjQrrsno9bFAcS6F6Duwr2FhUiE+HXRiLJOIhRzxu3He7DnJRR67rBHGlFP+fzu/esyAVCVNe4oUuYnE/DI+Y7fY0m4RJmFbtDhm5UD4ApovIY2ky4YFLtjXBjahiCZZkCmTt+40Ukgh7FPZbSMkjhbaE9mK090Qx2ACFJbzuESF7fP1bh32G+5X/cvCJJprmggo3oAkjWAaDJor7FfIxXhU5xaCZIEgi/eQb8VH5RyvPYb6dk+euvXvNrNZ2bucTYNvkuV27rpm9tW3DRG6Ta7t27TJ7a8W1QPwhCRH/a9fe3WViFxa4B11xBtYOVG+vJIbAexH/58H1kKuHlVXIe5vAArxPL0iy9mCjF2iMbRVbd/FMHdVV9fS3qSMssqqaFyt19pnq6hP1+DPVP+W98v9p9SiO171XXeOUpROPVo1w80iDbt2+fSslI81qT71Eb7rQ3Kq336S3CB7iXieJ3nyhoW/dvHlLkwvNal/pbxpp3qI3t+utpPxV+Yi13BxK9lz2rpBDDb3j6u7rlBRZfbm5g+7eTXeQ5UZy5fLlKwlZXrYONa94l/ckQ8ik13df3aFJ+Vb9ur56VV9HZW9oz54hD4F86U9WGJhdyJTuEGwfl0yVhfiz4WcsdZWjnMDxHd9lzCXlN0q+833TQ74d2KEjqOd63JWOj5vEJX8r7zG1k7MOVN11EKz5/j78d/1S9Uf85WLDx1vKDeWGLb3542IDcnDefPf/AALJVvQAeJxjYGBgZACC83HHfoHoi4tlnGE0AE/JBpUAAHicY2BkYGDgA2IJBhBgYmAEQh4gZgHzGAAEzgA/AAAAeJxjYGZiYJzAwMrAwejDmMbAwOAOpb8ySDK0MDAwMbByMsCBAILJEJDmmsLg8IDhAT/jg/8PGPSYIMKMcAUKQMgIAPPKCqUAeJxjYGBgZoBgGQZGBhAIAfIYwXwWBgsgzQGETCCJB+wP+P//B7MYHvCAWAogdRBdLEDMzcDJwMXAAxRigwmPXAAAQSkI3AAAeJxjYGRgYADixcdWGcfz23xl4GZiAIGLi2WckWkmBrA4B4QCAAUlB6kAAAB4nGNgZGBgYgACPTAJYjMyoAImAAXQADkCAAAAAgAAJQAcADYAAAAAAAAAigASABwAJQANAFUAAAAAUAAADQAAeJyVjjFOw0AQRd86TlAUkpIionALki3bCilcUvgALtJHysqxFNuS41yF83AQTsAp+BsWJAok2NVo38z/szPALS8Y3DEsufcccEPhecLDtyeU583zlIUJPM9Ymkc5TThXZX3tchyw4qs+oeLZcyjPq+cpd7x7nrE2K0ZaxRGr1+oeaJT3DDC249G21h6asVdaSa25cGLv1MrWl9NeUMrdqae8dtVyReQkpHoLxe8TPvWMDTFbRa6ejCd92Xdj2Q+1jfIkjYroxybKs028jfM0k/Xv+++kDpylu33dXLcjOzucm76LsiT9x28fRZFM9gAAeJxjYGZABowMaAAAAI4ABQ==) format('woff'), 9 | url("/fonts/tmthemeeditor.ttf") format("truetype"), 10 | url("/fonts/tmthemeeditor.svg#tmthemeeditor") format("svg"); 11 | font-weight: normal; 12 | font-style: normal; 13 | 14 | } 15 | 16 | [data-icon]:before { 17 | font-family: "tmthemeeditor" !important; 18 | content: attr(data-icon); 19 | font-style: normal !important; 20 | font-weight: normal !important; 21 | font-variant: normal !important; 22 | text-transform: none !important; 23 | speak: none; 24 | line-height: 1; 25 | -webkit-font-smoothing: antialiased; 26 | -moz-osx-font-smoothing: grayscale; 27 | } 28 | 29 | .btn [class^="icon-"], .btn [class*=" icon-"] { 30 | position: relative; 31 | top: 2px; 32 | margin-right: 2px; 33 | } 34 | 35 | [class^="icon-"]:before, 36 | [class*=" icon-"]:before { 37 | font-family: "tmthemeeditor" !important; 38 | font-style: normal !important; 39 | font-weight: normal !important; 40 | font-variant: normal !important; 41 | text-transform: none !important; 42 | speak: none; 43 | line-height: 1; 44 | min-width: 12px; 45 | -webkit-font-smoothing: antialiased; 46 | -moz-osx-font-smoothing: grayscale; 47 | .scale(1.25); 48 | display: inline-block; 49 | } 50 | 51 | .icon-gear:before { 52 | content: "\e000"; 53 | } 54 | .icon-globe:before { 55 | content: "\e001"; 56 | } 57 | .icon-search:before { 58 | content: "\e002"; 59 | } 60 | .icon-plus:before { 61 | content: "\e003"; 62 | } 63 | .icon-minus:before { 64 | content: "\e004"; 65 | } 66 | .icon-adjust:before { 67 | content: "\e005"; 68 | } 69 | .icon-arrow-combo:before { 70 | content: "\e006"; 71 | } 72 | .icon-download:before { 73 | content: "\e007"; 74 | } 75 | .icon-cancel-circle:before { 76 | content: "\e00d"; 77 | } 78 | .icon-menu:before { 79 | content: "\e00e"; 80 | } 81 | .icon-scope-hunter:before { 82 | content: "\e00c"; 83 | } 84 | .icon-check:before { 85 | content: "\e00f"; 86 | } 87 | -------------------------------------------------------------------------------- /app/front/js/template/color_picker_sliders.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 | 5 | 6 | 7 | 8 | 13 |
    14 | 15 |
    16 |
    17 |
    Red
    18 | 22 | 25 |
    26 |
    27 |
    Green
    28 | 32 | 35 |
    36 |
    37 |
    Blue
    38 | 42 | 45 |
    46 |
    47 | 48 |
    49 |
    50 |
    Hue
    51 | 55 | ° 58 |
    59 |
    60 |
    Saturation
    61 | 65 | % 68 |
    69 |
    70 |
    Brightness
    71 | 75 | % 78 |
    79 |
    80 | 81 |
    82 |
    83 |
    Hue
    84 | 88 | ° 91 |
    92 |
    93 |
    Saturation
    94 | 98 | % 101 |
    102 |
    103 |
    Lightness
    104 | 108 | % 111 |
    112 |
    113 | 114 |
    115 |
    116 |
    Alpha
    117 | 121 | % 124 |
    125 |
    126 |
    127 | -------------------------------------------------------------------------------- /app/front/public/fonts/tmthemeeditor.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by Fontastic.me 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------